美文网首页
Package Installer源码学习分析

Package Installer源码学习分析

作者: 图乐 | 来源:发表于2016-12-11 15:04 被阅读224次

    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源码学习分析

          本文链接:https://www.haomeiwen.com/subject/icfguttx.html