title: Package Installer源碼學(xué)習(xí)分析
tags: android,Package Installer,AOSP
grammar_cjkRuby: true
背景
主要功能:
- 安裝前驗(yàn)證
- 安裝程序
- 卸載程序
主要安裝方式:
- 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中完成的。