Package Installer源码学习分析


title: Package Installer源码学习分析
tags: android,Package Installer,AOSP
grammar_cjkRuby: true


背景

主要功能:

  1. 安装前验证
  2. 安装程序
  3. 卸载程序

主要安装方式:

  • Intent 隐式调用
  • adb install or pm shell命令
  • root权限or 静默安装

这里主要看第一种方式,Package Installer 入口 一般通过Java代码安装应用会创建Intent,并且指定一个activity action,隐式调用。
可以先看看PackageInstaller的AndroidManifest.xml文件
与普通应用的区别没有Android.intent.action.MAIN的activity action 所以不会在Android 系统的程序列表中有任何图标

PackageInstallerActivity InstallAppProgress
UninstallerActivity UninstallAppProgress

Intent隐式调用安装apk ,其中Uri from file: |package: PackageInstallerActivity是负责安装的入口界面,在这个activity中完成安装应用的初始化操作。在onCreat()方法中完成下面主要的核心任务:

  • 从Intent对象中获取Package Uri,Scheme等信息。
  • 对从Intent中获取的信息进行校验,主要是Scheme信息。
  • 根据Scheme信息(file|package)进行处理相应的,获取ApplicationInfo对象,该对象包含应用相关信息。如应用名称,图标。并且显示应用的信息。
  • 校验系统是否允许安装“未知来源”的应用
  • 进行安装前的准备,并根据具体情况显示校验窗口
    initiateInstall()初始化工作并且调用 startInstallConfirm()权限列表,尽管安装之前的校验工作很复杂,但是这并不是Package Installer 的主要任务,安装才是主要的工作,这是在InstallAppProgress中完成的。
    在InstallAppProgress中的onCreate方法中获取ApplicationInfo对象的值mAppInfo和mPackageURI接下来会验证scheme是否是file或者package最后调用initView方法开始安装应用。安装应用的核心代码也在initView这个方法中。一开始initView方法根据package name 或者apk 文件的路径获取一些信息,然后判断该程序是否已经安装,如果已经安装就进入更新模式(通过installFlags变量控制)。尽管在initView方法的代码看上去很多,但是真正核心的就下面几行代码
        if ("package".equals(mPackageURI.getScheme())) {
            try {
                //根据packageName更新应用
                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的路径安装或者更新应用
            pm.installPackageWithVerificationAndEncryption(mPackageURI, observer, installFlags,
                    installerPackageName, verificationParams, null);//Android 4.2以后有这个方法
        }

其中installExistingPackage和installPackageWithVerificationAndEncryption都是PackageManger类的方法,这两个方法都是静默安装应用。但是这两个方法都被设为hide,在普通的Activity中无法使用。由于这两个方法都是异步执行的,PackageInstallObserver是安装事件的监听器,不管安装成功还是失败都会给用户一个反馈。

卸载应用

卸载Android 应用与安装应用类似,也是调用系统几的API,这些API无法在普通应用中调用,使用这些API可以实现静默卸载。Package Installer 在卸载之前都会弹出确认。这个询问对话框就是卸载的入口,对应 UninstallerActivity 类。该Activity也允许普通程序通过Action调用,UninstallerActivity的关键部分是确认按钮对应的事件如下

 @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 应用对于所有用户的程序和数据
        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);
        //允许卸载窗口返回是否卸载成功的标志,可以用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);
    }

点击确认按钮后会调用startUninstallProgress方法,和安装过程类似,卸载过程是在UninstallAppProgress中完成的。

你可能感兴趣的:(Package Installer源码学习分析)