1、應用程序安裝基礎
- 單個APK程序安裝的過程
- 把原始的APk文件複製到程序相應的目錄文件下,對於第三方app複製到/data/app/目錄下
- 爲程序創建相應的數據目錄、提取dex文件、修改系統包管理信息
- 程序安裝過程
- 在程序目錄下創建以包名稱命名的程序apk文件File
- 在data/data/目錄下創建應用程序的數據文件
- 將程序所有的信息寫入到配置文件package.xml文件中
- HandlerParams主要實現子類
- InstallParams:完成要安裝程序的Copy工作
- MoveParams:實現對已安裝程序移動到外部保存目錄中
abstract class HandlerParams { // 抽象類
4676 final static int MAX_RETRIES = 4; // 最多重試4次
4677 int retry = 0;
4678 final boolean startCopy() { // 提供文件Copy方法
4679 try {
4681 retry++;
4682 if (retry > MAX_RETRIES) { // 嘗試超過4次報錯
4684 mHandler.sendEmptyMessage(MCS_GIVE_UP); // 超過4次後發送報錯信息,回調錯誤方法
4685 handleServiceError();
4686 return false;
4687 } else {
4688 handleStartCopy(); // 子類需重寫,執行文件複製操作
res = true;
4691 }
4692 } catch (RemoteException e) {
4694 mHandler.sendEmptyMessage(MCS_RECONNECT);
4695 }
4696 handleReturnCode();
return res;
4697 }
4699 final void serviceError() {
4701 handleServiceError();
4702 handleReturnCode();
4703 }
4704 abstract void handleStartCopy() throws RemoteException; // 抽象方法
4705 abstract void handleServiceError();
4706 abstract void handleReturnCode();
}
由上面源碼知道,HandlerParams是抽象類,內部提供程序文件的複製功能,執行將安裝的apk文件複製到程序的制定安裝位置,程序調用startCopy()後開始執行文件賦值,具體賦值調用抽象方法handleStartCopy(),所以具體的功能子類需要重寫此方法,在copy發生異常時會發送Handler消息實現重試,最多重試4次後拋出異常;
2、PMS中APK安裝過程
程序的安裝執行到PMS中後,從Packagemanager的installpackage()方法開始,間接調用到PMS中installStage()函數,installStage()中首先創建InstallParams對象,保存要安裝的文件URI和其他信息,然後發送INIT_COPY異步消息啓動文件複製
public void installStage(….) {
4590 Message msg = mHandler.obtainMessage(INIT_COPY); // 創建INIT_COPY消息
4591 msg.obj = new InstallParams(packageURI, observer, flags,
4592 installerPackageName); // 創建InstallParams對象封裝安裝包屬性信息
4593 mHandler.sendMessage(msg);
4594 }
Handler在處理INIT_COPY消息時,根據mBound變量確定是否綁定了MSC服務,未綁定的先調用connectToService()執行綁定過程,然後將HandlerParams加入mPendingInstalls集合中等待執行,在服務綁定後發送MCS_BOUND消息,對於已經綁定的直接發送MSC_BOUND事件執行任務
if (!mBound) { // 1、判斷服務是否綁定
457 if (!connectToService()) { // 2、執行Service綁定
459 params.serviceError();
460 return;
461 } else {
464 mPendingInstalls.add(idx, params); // 3、添加要執行的任務
465 }
466 } else {
467 mPendingInstalls.add(idx, params); // 3、添加任務
470 if (idx == 0) {
471 mHandler.sendEmptyMessage(MCS_BOUND); // 4、就一個事件時,直接發送事件立即執行
472 }
473 }
在處理MCS_BOUND消息時,使用獲取的Binder服務從mPendingInstalls列表中取出安裝信息HandlerParams類中,
if (msg.obj != null) {
mContainerService = (IMediaContainerService) msg.obj; // 1、獲取對應的服務
}
HandlerParams params = mPendingInstalls.get(0); // 2、取出要安裝的參數
if (params != null) {
If(params.startCopy()){ // 3、執行Copy文件,最終執行到FileInstallArgs.copyApk()
if (mPendingInstalls.size() > 0) {
mPendingInstalls.remove(0); // 刪除集合中的數據
}
};
}
在Handler處理事件時,從消息msg中獲取IMediaContainerService服務對象,並從mPendingInstalls集合中獲取要執行的任務,此處獲取的是前面創建的InstallParams對象,然後調用params.startCopy()方法執行文件複製,按照HandlerParams的源碼程序會調用InstallParams.handleStartCopy()方法;
// InstallParams:實現全新安裝時的複製過程
class InstallParams extends HandlerParams {
public void handleStartCopy() throws RemoteException {
mArgs = createInstallArgs(this); // 1、
4834 if (ret == PackageManager.INSTALL_SUCCEEDED) {
4837 ret = mArgs.copyApk(mContainerService, true); // 2、
4838 }
}
}
在InstallParams中主要執行兩個過程:
- 根據Params類型創建InstallerArgs對象保存請求數據
- 調用InstallArgs.copyApk()方法實現複製
private InstallArgs createInstallArgs(InstallParams params) {
4931 if (installOnSd(params.flags)) {
4932 return new SdInstallArgs(params);//複製到外部存儲時使用
4933 } else {
4934 return new FileInstallArgs(params); // 複製到內部存儲時使用,在FileInstallArgs內部調用IMediaContainerService服務執行Copy過程
}
}
InstallArgs本身是一個抽象類,內部包含了很多屬性信息,它的實現類主要有兩個FileInstallArgs和SdInstallArgs,FileInstallArgs主要實現將文件複製到內部存儲,而SdInstallArgs執行復制到外部文件存儲,這裏會創建FileInstallArgs對象,在FileInstallArgs.copy()中直接調用doCopyApk();
- FileInstallArgs.copyApk()
int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
// 1、創建臨時文件路徑:data/app/vmd.sessionId.tmp 文件目錄
final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
codeFile = tempDir;
resourceFile = tempDir;
final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
@Override
public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
try {
final File file = new File(codeFile, name); // 創建apk文件
final FileDescriptor fd = Os.open(file.getAbsolutePath(),
O_RDWR | O_CREAT, 0644);
Os.chmod(file.getAbsolutePath(), 0644);
return new ParcelFileDescriptor(fd); //2、以臨時File創建ParcelFileDescriptor對象,用於進程通信
}
}
};
// 3、調用IMS方法實現文件Copy,將apk文件複製到temp文件中,然後將tmp文件複製到data/app/下,刪除臨時tmp文件
ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
}
在doCopyApk()中,首先在data/app/目錄下創建臨時目錄data/app/vmd.sessionId.tmp 文件,然後實例化IParcelFileDescriptorFactory.Stub()對象,並以臨時文件File創建ParcelFileDescriptor類用於Binder通信,最後調用imcs.copyPackage()執行文件複製,這裏imcs實際是DefaultContainerService的對象;
- DefaultContainerService.copyPackage()
final File packageFile = new File(packagePath); // 1、獲取要複製的apk文件
pkg = PackageParser.parsePackageLite(packageFile, 0); // 2、parser程序包
return copyPackageInner(pkg, target); // 3、執行文件複製
private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target)
throws IOException, RemoteException {
copyFile(pkg.baseCodePath, target, "base.apk”); // 1、複製apk文件
if (!ArrayUtils.isEmpty(pkg.splitNames)) {
for (int i = 0; i < pkg.splitNames.length; i++) {
copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk”); // 2、複製拆分的apk
}
}
return PackageManager.INSTALL_SUCCEEDED;
}
在copyPackage()方法中,首先根據文件路徑獲取apk文件,調用PackageParser解析apk文件,這裏的解析主要是看apk是否包含split apk,然後調用copyPackageInner執行文件複製工作,在copyPackageInner中調用copyFile()
private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName)
throws IOException, RemoteException {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(sourcePath);
out = new ParcelFileDescriptor.AutoCloseOutputStream(
target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE)); // 回調target
FileUtils.copy(in, out); // 執行文件複製,在tmp/base.apk/
} finally {
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(in);
}
}
在copyFile()中,首先回調target的open()方法完成ParcelFileDescriptor的創建,然後調用FileUtils.copy()方法,將apk文件複製到tmp/base.apk/中,由前面的HandlerParam知道apk複製成功之後,回調InstallParams.handleReturnCode(),handleReturnCode()中直接調用processPendingInstall()方法
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
mHandler.post(new Runnable() { //1、mHandler發送延時任務
public void run() {
mHandler.removeCallbacks(this); //移除其它任務
PackageInstalledInfo res = new PackageInstalledInfo();
res.setReturnCode(currentStatus);
res.uid = -1;
res.pkg = null;
res.removedInfo = null;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
args.doPreInstall(res.returnCode); //2、執行安裝前處理
synchronized (mInstallLock) {
installPackageTracedLI(args, res); //3、執行安裝和解析
}
args.doPostInstall(res.returnCode, res.uid);//4、執行安裝後的掃尾工作
}
});
}
在processPendingInstall()中直接發送handler事件執行APK的安裝工作,在Handler事件中首先創建PackageInstalledInfo對象,保存安裝的狀態,在複製成功後執行以下操作:
- 調用args.doPreInstall()執行安裝apk前準備;
- 調用installPackageTracedLI(args, res)執行apk的解析和安裝工作
- 調用args.doPostInstall()執行apk文件安裝完成後的工作
- args.doPreInstall(res.returnCode):如果複製狀態不爲Success,則清除複製的文件
int doPreInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {//未複製成功清除文件
cleanUp();
}
return status;
}
- installPackageTracedLI()中直接調用installPackageLI()
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
final int installFlags = args.installFlags;
final String installerPackageName = args.installerPackageName;
final File tmpPackageFile = new File(args.getCodePath());
PackageParser pp = new PackageParser();
pkg = pp.parsePackage(tmpPackageFile, parseFlags); // 1、解析apk文件
//檢查apk
//校驗簽名
// 2、/data/app/vmdl18300388.tmp/base.apk,重命名爲/data/app/包名-1/base.apk。
if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
return;
}
if (replace) {
replacePackageLIF(pkg, parseFlags, scanFlags, args.user,
installerPackageName, res, args.installReason); // 3、替換apk
} else {
installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, volumeUuid, res, args.installReason); // 3、安裝新的apk
}
}
在installPackageLI()中主要執行以下操作:
- 創建PackageParser對象解析複製的臨時apk文件;
- 檢查複製的apk文件並校驗簽名信息等;
- 將複製的apk文件目錄,重命名爲以包名爲目錄的文件
- 確認是已安裝的apk更新還是新安裝的app,對於新安裝的app執行installNewPackageLIF()方法
- installNewPackageLIF():安裝新的apk
PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags, scanFlags, // 重新掃描apk文件
System.currentTimeMillis(), user);
updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason); // 更新Setting
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
prepareAppDataAfterInstallLIF(newPackage); // 爲安裝好的App準備數據
}
在installNewPackageLIF()中首先調用scanPackageTracedLI()重新掃描apk文件,scanPackageTracedLI內部會調用scanPackageNewLI()提交解析結果,將解析的結果Package對象添加到PMS的屬性中,詳細流程參見深入PMS源碼(一)—— PMS的啓動過程和執行流程,在安裝完成後調用updateSettingsLI()更新mSetting屬性,最後調用prepareAppDataAfterInstallLIF()爲新安裝的程序準備數據;
scannedPkg = scanPackageNewLI(pkg, parseFlags, scanFlags, currentTime, user);
到此程序的安裝就完成了,上面主要介紹了Android系統是如何實現安裝和文件複製的,在複製完成後,就會向PMS啓動過程一樣解析和處理apk文件;
3、應用程序的卸載過程
- 應用程序的卸載
packageManager.packageInstaller.uninstall() //卸載程序
由深入PMS源碼(一)—— PMS的啓動過程和執行流程分析知道此處packageManager獲取的是ApplicationPackageManager,而packageInstaller是在ApplicationPackageManager內部實例化的PackageInstaller的對象
@Override
public PackageInstaller getPackageInstaller() {
synchronized (mLock) {
if (mInstaller == null) {
try {
mInstaller = new PackageInstaller(mPM.getPackageInstaller(),
mContext.getPackageName(), mContext.getUserId());
}
}
return mInstaller;
}
}
在創建PackageInstaller對象中,調用mPM.getPackageInstaller()調用PMS中方法獲取PackageInstallerService對象,並將其封裝在PackageInstaller對象中,程序繼續調用PackageInstaller.uninstall()中
public void uninstall(@NonNull String packageName, @DeleteFlags int flags,
@NonNull IntentSender statusReceiver) {
uninstall(new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
flags, statusReceiver);
}
uninstall()中首先根據傳入的包名創建VersionedPackage對象,然後繼續調用uninstall的重載方法
@RequiresPermission(anyOf = {
Manifest.permission.DELETE_PACKAGES,
Manifest.permission.REQUEST_DELETE_PACKAGES})
public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags,
@NonNull IntentSender statusReceiver) {
try {
mInstaller.uninstall(versionedPackage, mInstallerPackageName,
flags, statusReceiver, mUserId); //2、
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在uninstall()中直接調用mInstaller.uninstall(),這裏的mInstaller對象就是在創建PackageInstaller時傳入的第一個參數,即PMS中實例話的PackageInstallerService對象,PackageInstallerService實現了IPackageInstaller.Stub類,可用於進程間通信
public class PackageInstallerService extends IPackageInstaller.Stub {
@Override
public void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags,IntentSender statusReceiver, int userId) throws RemoteException {
mPermissionManager.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall"); // 1、檢查權限
final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
statusReceiver, versionedPackage.getPackageName(),
isDeviceOwnerOrAffiliatedProfileOwner, userId); //2、
}
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)== PackageManager.PERMISSION_GRANTED) {
mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
}
}
在PackageInstallerService.install()權限中,主要執行3個流程:
- 創建PackageDeleteObserverAdapter對象,用於接收響應刪除的結果
- 檢查當前程序是否具有刪除權限
- 調用PMS的deletePackageVersioned()方法執行程序的卸載
從上面分析應用程序真正開始卸載,是從PackageManager的deletePackageAsUser()函數開始,間接調用PMS的deletePackageVersioned()方法
@Override
public void deletePackageVersioned(VersionedPackage versionedPackage,
final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
mHandler.post(new Runnable() { //發送Handler事件
public void run() {
mHandler.removeCallbacks(this); // 移除事件
int returnCode;
final PackageSetting ps = mSettings.mPackages.get(internalPackageName);//獲取PackageSettings對象
boolean doDeletePackage = true;
if (ps != null) {
final boolean targetIsInstantApp =
ps.getInstantApp(UserHandle.getUserId(callingUid));
doDeletePackage = !targetIsInstantApp
|| canViewInstantApps;
}
if (doDeletePackage) {
if (!deleteAllUsers) {
returnCode = deletePackageX(internalPackageName, versionCode,
userId, deleteFlags);
}
}
try {
observer.onPackageDeleted(packageName, returnCode, null);// 刪除後回調
}
}
});
}
在deletePackageVersioned()中發送Post事件執行異步刪除操作,在Handler事件中調用deletePackageX()方法
int deletePackageX(String packageName, long versionCode, int userId, int deleteFlags) {
final PackageRemovedInfo info = new PackageRemovedInfo(this);
if (isPackageDeviceAdmin(packageName, removeUser)) {
Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
}
info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true);
res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
deleteFlags | PackageManager.DELETE_CHATTY, info, true, null);
}
在deletePackageX()中首先判斷要卸載的程序是否是admin管理的,如果是則直接return,如果不是則執行deletePackageLIF()方法繼續卸載程序
- deletePackageLIF()
p = mPackages.get(packageName); //1、獲取保存應用程序的Package對象
if (isSystemApp(p)) {
ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings); //2、如果是系統app
6376 } else {
// 3、處理第三方app卸載
ret = deleteInstalledPackageLIF(p, deleteCodeAndResources, flags, outInfo,
6381 writeSettings);
6382 }
deletePackageLIF()中根據app類型區分系統app和第三方app,執行不同的卸載程序,對於第三方app執行deleteInstalledPackageLIF()方法,在deleteInstalledPackageLIF()中也是直接調用removePackageDataLI()
- removePackageDataLIF()
private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,int flags, boolean writeSettings) {
6183 String packageName = p.packageName;
6187 removePackageLI(p, (flags&REMOVE_CHATTY) != 0); // 1、移除mPackages集合中保存的package對象
if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
final PackageParser.Package resolvedPkg;
resolvedPkg = new PackageParser.Package(ps.name);
resolvedPkg.setVolumeUuid(ps.volumeUuid);
}
destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); // 2、調用Installer執行清除/data/app/目錄下的文件信息
destroyAppProfilesLIF(resolvedPkg, UserHandle.USER_ALL);
//3、發送包清理事件
schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
}
6210 synchronized (mPackages) {
6211 if (deletedPs != null) {
6212 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
6213 if (outInfo != null) {
6214 outInfo.removedUid = mSettings.removePackageLPw(packageName); // 4、移除mSetting中保存的數據
6215 }
6216 if (deletedPs != null) {
mHandler.post(new Runnable() {
@Override
public void run() {//5、發送事件殺死進程信息
killApplication(deletedPs.name, deletedPs.appId,
KILL_APP_REASON_GIDS_CHANGED);
}
});
6221 }
6222 }
6223 }
if (writeSettings) {
mSettings.writeLPr(); // 6、寫入mSettings信息,更新Package.xml文件
}
}
在removePackageDataLIF()方法中執行了卸載刪除的重要操作,具體如下:
- 調用removePackageLI()刪除mPackages集合中保存的次apk的解析對象Package,在removePackageLI中會調用cleanPackageDataStructuresLILPw(),刪除此PMS中保存的此應用程序中的四大組件信息
void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
int N = pkg.providers.size();
for (i=0; i<N; i++) {
PackageParser.Provider p = pkg.providers.get(i);
mProviders.removeProvider(p);
}
N = pkg.services.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Service s = pkg.services.get(i);
mServices.removeService(s);
}
}
......
}
- 調用destroyAppDataLIF()方法,使用Installer刪除此應用程序/data/app/目錄下的安裝包信息
- 調用schedulePackageCleaning()發送START_CLEANING_PACKAGE事件執行外部使用數據刪除
- 刪除mSetting中保存此程序的PackageSetting對象
- 發送Handler事件調用killApplication()殺死應用進程
- 調用mSettings.writeLPr()將mSettings信息寫入配置文件package.xml中
- destroyAppDataLIF()
在destroyAppDataLIF()中直接調用destroyAppDataLeafLIF()方法,destroyAppDataLeafLIF中主要調用mInstaller中方法執行刪除,刪除應用數據之後調用mDexManager通知刪除結束;
private void destroyAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
final PackageSetting ps;
synchronized (mPackages) {
ps = mSettings.mPackages.get(pkg.packageName);//獲取PackageSetting對象
}
for (int realUserId : resolveUserIds(userId)) {
final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0;
try { // 調用mInstaller執行文件數據刪除
mInstaller.destroyAppData(pkg.volumeUuid, pkg.packageName, realUserId, flags,
ceDataInode);
}
mDexManager.notifyPackageDataDestroyed(pkg.packageName, userId);
}
}
- schedulePackageCleaning():執行mSetting中信息和程序數據文件的刪除
void schedulePackageCleaning(String packageName, int userId, boolean andCode) {
final Message msg = mHandler.obtainMessage(START_CLEANING_PACKAGE,
userId, andCode ? 1 : 0, packageName); // 創建Message對象
msg.sendToTarget(); // 發送事件
}
case START_CLEANING_PACKAGE: {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
final String packageName = (String)msg.obj;
final int userId = msg.arg1;
final boolean andCode = msg.arg2 != 0;
synchronized (mPackages) {
mSettings.addPackageToCleanLPw(
new PackageCleanItem(userId, packageName, andCode));
} Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
startCleaningPackages();
} break;
在schedulePackageCleaning()創建Message對象併發送事件,在Handler處理事件時首先調用mSetting將要刪除的信息保存在Settings的mPackagesToBeCleaned集合中,然後調用startCleaningPackages()啓動本地服務DefaultContainerService服務,
@Override
protected void onHandleIntent(Intent intent) {
if (PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE.equals(intent.getAction())) {
final IPackageManager pm = IPackageManager.Stub.asInterface(
ServiceManager.getService("package")); // 獲取PMS對象
PackageCleanItem item = null;
try {
while ((item = pm.nextPackageToClean(item)) != null) {
final UserEnvironment userEnv = new UserEnvironment(item.userId);
//刪除/Android/data/xxxx/下文件信息
eraseFiles(userEnv.buildExternalStorageAppDataDirs(item.packageName));
//刪除/Android/media/xxxx/下文件信息
eraseFiles(userEnv.buildExternalStorageAppMediaDirs(item.packageName));
}
}
}
}
在本地服務的onHandleIntent()中調用PMS的nextPackageToClean()獲取剛纔加入的mSetting中的mPackagesToBeCleaned集合,並遍歷集合一次從中取出要卸載刪除的數據包,並獲取文件路徑執行eraseFiles()刪除文件;
void eraseFiles(File path) {
if (path.isDirectory()) {
String[] files = path.list();
if (files != null) {
for (String file : files) {
eraseFiles(new File(path, file)); // 遞歸刪除目錄下文件
}
}
}
path.delete(); // 刪除數據
}
到此應用程序的app安裝文件和使用中產生的數據文件都已被刪除,且配置文件已更新完成,此時會回調deletePackageVersioned()中的 observer.onPackageDeleted(packageName, returnCode, null)方法通知刪除結果,這裏回調的是PackageDeleteObserverAdapter類中
@Override
public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
if (PackageManager.DELETE_SUCCEEDED == returnCode && mNotification != null) {
NotificationManager notificationManager = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(basePackageName,
SystemMessage.NOTE_PACKAGE_STATE,
mNotification);
}
final Intent fillIn = new Intent();
fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName);
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
PackageManager.deleteStatusToPublicStatus(returnCode));
fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
PackageManager.deleteStatusToString(returnCode, msg));
fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
try {
mTarget.sendIntent(mContext, 0, fillIn, null, null);
} catch (SendIntentException ignored) {
}
}
在onPackageDeleted()中,首先調用NotificationManager中方法發送notify()通知安裝成功,然後創建Intent對象並回調mTarget.sendIntent(),這裏的mTarget對象其實就是卸載最開始時調用uninstall()方法傳入的第二個參數,即IntentSender對象,用於接收刪除的結果;