Package Installer源碼學(xué)習(xí)分析


title: Package Installer源碼學(xué)習(xí)分析
tags: android,Package Installer,AOSP
grammar_cjkRuby: true


背景

主要功能:

  1. 安裝前驗(yàn)證
  2. 安裝程序
  3. 卸載程序

主要安裝方式:

  • Intent 隱式調(diào)用
  • adb install or pm shell命令
  • root權(quán)限or 靜默安裝

這里主要看第一種方式,Package Installer 入口 一般通過Java代碼安裝應(yīng)用會(huì)創(chuàng)建Intent,并且指定一個(gè)activity action,隱式調(diào)用。
可以先看看PackageInstaller的AndroidManifest.xml文件
與普通應(yīng)用的區(qū)別沒有Android.intent.action.MAIN的activity action 所以不會(huì)在Android 系統(tǒng)的程序列表中有任何圖標(biāo)

PackageInstallerActivity InstallAppProgress
UninstallerActivity UninstallAppProgress

Intent隱式調(diào)用安裝apk ,其中Uri from file: |package: PackageInstallerActivity是負(fù)責(zé)安裝的入口界面,在這個(gè)activity中完成安裝應(yīng)用的初始化操作。在onCreat()方法中完成下面主要的核心任務(wù):

  • 從Intent對(duì)象中獲取Package Uri,Scheme等信息。
  • 對(duì)從Intent中獲取的信息進(jìn)行校驗(yàn),主要是Scheme信息。
  • 根據(jù)Scheme信息(file|package)進(jìn)行處理相應(yīng)的,獲取ApplicationInfo對(duì)象,該對(duì)象包含應(yīng)用相關(guān)信息。如應(yīng)用名稱,圖標(biāo)。并且顯示應(yīng)用的信息。
  • 校驗(yàn)系統(tǒng)是否允許安裝“未知來源”的應(yīng)用
  • 進(jìn)行安裝前的準(zhǔn)備,并根據(jù)具體情況顯示校驗(yàn)窗口
    initiateInstall()初始化工作并且調(diào)用 startInstallConfirm()權(quán)限列表,盡管安裝之前的校驗(yàn)工作很復(fù)雜,但是這并不是Package Installer 的主要任務(wù),安裝才是主要的工作,這是在InstallAppProgress中完成的。
    在InstallAppProgress中的onCreate方法中獲取ApplicationInfo對(duì)象的值mAppInfo和mPackageURI接下來會(huì)驗(yàn)證scheme是否是file或者package最后調(diào)用initView方法開始安裝應(yīng)用。安裝應(yīng)用的核心代碼也在initView這個(gè)方法中。一開始initView方法根據(jù)package name 或者apk 文件的路徑獲取一些信息,然后判斷該程序是否已經(jīng)安裝,如果已經(jīng)安裝就進(jìn)入更新模式(通過installFlags變量控制)。盡管在initView方法的代碼看上去很多,但是真正核心的就下面幾行代碼
        if ("package".equals(mPackageURI.getScheme())) {
            try {
                //根據(jù)packageName更新應(yīng)用
                pm.installExistingPackage(mAppInfo.packageName);
                observer.packageInstalled(mAppInfo.packageName,
                        PackageManager.INSTALL_SUCCEEDED);
            } catch (PackageManager.NameNotFoundException e) {
                observer.packageInstalled(mAppInfo.packageName,
                        PackageManager.INSTALL_FAILED_INVALID_APK);
            }
        } else {
            //使用APK的路徑安裝或者更新應(yīng)用
            pm.installPackageWithVerificationAndEncryption(mPackageURI, observer, installFlags,
                    installerPackageName, verificationParams, null);//Android 4.2以后有這個(gè)方法
        }

其中installExistingPackage和installPackageWithVerificationAndEncryption都是PackageManger類的方法,這兩個(gè)方法都是靜默安裝應(yīng)用。但是這兩個(gè)方法都被設(shè)為hide,在普通的Activity中無法使用。由于這兩個(gè)方法都是異步執(zhí)行的,PackageInstallObserver是安裝事件的監(jiān)聽器,不管安裝成功還是失敗都會(huì)給用戶一個(gè)反饋。

卸載應(yīng)用

卸載Android 應(yīng)用與安裝應(yīng)用類似,也是調(diào)用系統(tǒng)幾的API,這些API無法在普通應(yīng)用中調(diào)用,使用這些API可以實(shí)現(xiàn)靜默卸載。Package Installer 在卸載之前都會(huì)彈出確認(rèn)。這個(gè)詢問對(duì)話框就是卸載的入口,對(duì)應(yīng) UninstallerActivity 類。該Activity也允許普通程序通過Action調(diào)用,UninstallerActivity的關(guān)鍵部分是確認(rèn)按鈕對(duì)應(yīng)的事件如下

 @Override
        public void onClick(DialogInterface dialog, int which) {
            if (which == Dialog.BUTTON_POSITIVE) {
                ((UninstallerActivity) getActivity()).startUninstallProgress();
            } else {
                ((UninstallerActivity) getActivity()).dispatchAborted();
            }
        }
      void startUninstallProgress() {
        Intent newIntent = new Intent(Intent.ACTION_VIEW);
        newIntent.putExtra(Intent.EXTRA_USER, mDialogInfo.user);
        //卸載改Android 應(yīng)用對(duì)于所有用戶的程序和數(shù)據(jù)
        newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mDialogInfo.allUsers);
        newIntent.putExtra(PackageInstaller.EXTRA_CALLBACK, mDialogInfo.callback);
        newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mDialogInfo.appInfo);
        //允許卸載窗口返回是否卸載成功的標(biāo)志,可以用startActivityForResult接收
        if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
            newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
            newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
        }
        newIntent.setClass(this, UninstallAppProgress.class);
        startActivity(newIntent);
    }

點(diǎn)擊確認(rèn)按鈕后會(huì)調(diào)用startUninstallProgress方法,和安裝過程類似,卸載過程是在UninstallAppProgress中完成的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容