Android中APK安装过程

前言:

你能从这篇文章中得到什么?
本文介绍android如何处理应用程序安装过程。具体包括:

安装应用程序的方法有哪些?
android如何处理安装过程?
如何默认应用程序PackageInstaller表演它的魔力?
流程如何从一个活动流向另一个活动?
这个过程涉及到哪些不同的组件?
安装APK的不同方法。
安装Android应用程序有几种方法。

安装APK的不同方法

安装Android应用程序有几种方法:

应用市场,这是大多数用户安装应用程序的方式。

将APK文件下载到设备,然后打开它。只有在设置中启用“未知源”选项时,才能安装此选项。

使用adb installandroidsdk的命令,它在最后调用pm安装指向的命令cmd package install .

直接将APK文件复制到系统应用程序目录之一。当APK文件直接复制到某个应用程序目录时,它会自动被检测并安装。

安卓操作系统

最近,Android已经成为全球最受欢迎的移动平台。最初它是为智能手机设计的,但现在为平板电脑、电视和可穿戴设备提供动力,很快甚至会出现在汽车上。

安卓是建立在Linux内核。在android系统架构中,应用在最高层。在Android中,每个应用程序都有自己的目录来保存数据。Android在安装时为每个应用程序分配一个UID(userID)。它是一个常量值,在重新安装应用程序之前不会更改。它不同于PID(processID),后者一直在变化。

Android使用UID设置内核级应用程序沙盒。内核通过标准的Linux工具(例如分配给应用程序的用户和组id)在进程级强制应用程序和系统之间的安全性。默认情况下,应用程序不能相互交互,对操作系统的访问也受到限制。

Android应用主要有两类。

1.系统应用
它包含在操作系统映像中,是一个只读应用程序,普通用户无法卸载或更改。系统应用程序可以在/system/app/目录,而某些特权应用程序存在于 /系统/专用应用程序/目录。这个/system/vendor/app/目录承载特定于供应商的应用程序。

2.用户应用
用户安装的应用程序安装在一个专用的读写分区(通常称为/data)上,该分区承载用户数据,可以卸载或更改。用户安装的应用程序可以在中找到/data/app/ 。

安装工艺流程

PackageInstaller和PackageManager
PackageInstaller是在android设备上安装任何应用程序的默认应用程序。它提供了一个交互界面来安装一个普通的软件包。

PackageManager是一个类,用于检索与设备上当前安装的应用程序包相关的各种信息。它是抽象类,具体实现由 应用程序包管理器创建于ContextImpl#getPackageManager() .

初始活动

任何使用其APK文件安装的应用程序都被视为“未知源”。未知源的实际定义要宽泛一些;启动时,PackageInstaller检索UID和请求安装APK的应用程序包。它检查请求的应用程序是否具有特权(存在于/system/priv-app/,即 谷歌软件包安装程序),如果没有,则视为未知源。

要安装的包可以是内容URI的形式,也可以是文件URI。发生的第一个活动是InstallStart确定哪个活动是安装的第一个可见活动并将意图转发给它的活动。

如果一个包是从内容URI安装的,然后InstallStaging已启动活动,它加载包并将其从文件转换为安装,它创造了阶段同步任务并获取一个包文件。

如果在此过程中发生错误,则设置错误结果,并且showError()被称为。如果文件已暂存,则它将启动 删除StagedFileOnResult,它在最后召唤PackageInstallerActivity并删除分阶段安装文件。

包装安装

安装APK文件也称为安装程序包侧装应用程序 .PackageInstallerActivity通过侧载安装应用程序时启动。

在PackageInstallerActivity,首先解析包,然后通过对话框通知用户解析错误。如果成功解析包,则会通知用户打开“未知来源”设置中的选项。如果设备上已经存在该软件包,则会向用户显示一个确认对话框(以替换现有的软件包)。所有状态转换都在此活动中处理。

活动分析包并检查是否有任何错误。如果包被正确解析,那么它将为此包设置安装程序。

PackageInstaller调用startInstall()会引发亚活动 正在安装…正在安装以实际安装应用程序

安装活动

InstallInstalling活动将包发送到包管理器并处理来自包管理器的结果。这有两个阶段:首先,将数据发送到包管理器,然后等待包管理器处理结果。

此活动检查程序包,如果系统上已为其他用户安装了具有给定包名称的应用程序,则它将调用PackageManager#installExistingPackage()并为呼叫用户安装它。

实际安装

InstallInstalling活动创建PackageInstaller.SessionParams并设置一些重要属性:

完全安装模式
程序包源
程序包名称
包装尺寸
安装位置
所有其他重要属性都可以在文档 .
此信息会话由创建createSession(params) .

InstallInstallInstalling活动创建InstallingAsyncTask,将包发送到安装程序的AsyncTask。它打开了 程序包安装程序会话,由检索openSession()并使用打开OutputStreamopenWrite(String name, long offsetBytes, long lengthBytes)它打开一个流以将APK文件写入会话。使用设置安装进度setStagingProgress(float)和addProgress(float)在会议结束时,把所有的东西都交出来。

结果活动

在InstallInstalling活动广播接收器 安装事件接收器在观察者处注册launchFinishBasedOnResult方法。安装过程完成后, InstallEventReceiver通知观察者

launchFinishBasedOnResult根据结果启动相应的完成活动。

  • InstallSuccess通过打电话launchSuccess()如果流程成功完成
  • InstallFailed通过打电话launchFailure()用适当的 状态和 状态消息对于失败的结果

更新系统数据库中的信息

Android操作系统有两个用于在Android系统中保存应用程序信息的配置文件。packages.list和包.xml。这两个文件都可以位于/data/system/目录

包.列表

com.google.android.carriersetup 10073 0 /data/user/0/com.google.android.carriersetup default:privapp:targetSdkVersion=28 3003
com.android.wallpaperbackup 1000 0 /data/user/0/com.android.wallpaperbackup platform:privapp:targetSdkVersion=28 1065,3002,1023,3003,3001
com.innersloth.spacemafia 10090 0 /data/user/0/com.innersloth.spacemafia default:targetSdkVersion=30 3003
...
com.kruna1pate1.pictionaryapp 10089 1 /data/user/0/com.kruna1pate1.pictionaryapp default:targetSdkVersion=32 3003

在这里,空间分为6列,其中包含6个应用程序相关信息:

应用程序包的名称
应用程序的UID。(通过观察它们,我们可以很容易地将其绘制出来u0_a89=> ten thousand and eighty-nine )
应用程序是否处于调试模式。
应用程序的数据存储路径。
SEinfo公司应用程序的信息。
应用程序所属的用户组。

包.xml

以下是其内容的抽象视图:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<packages>
    <version ... />

    <permission-trees>
        <item name="xyz" package="xyz" />
        ...
    </permission-trees>

    <permissions>
        ...
    </permissions>

    <package ...>
        <sigs count="1" schemeVersion="3">
            <cert ... />
        </sigs>

        <perms>
            <item name="xyz" granted="true" flags="0" />
            ...
        </perms>

        <proper-signing-keyset identifier="6" />
    </package>

    <updated-package ... >
        <perms>
            ...
        </perms>
    </updated-package>

    <shared-user ... >
        <sigs count="1" schemeVersion="3">
            <cert index="4" />
        </sigs>

        <perms>
            ...
        </perms>
    </shared-user>

    <keyset-settings version="1">
        <keys>
            <public-key ... />
            ...
        </keys>

        <keysets>
            <keyset identifier="1">
                <key-id identifier="1" />
            </keyset>
        </keysets>

        <lastIssuedKeyId value="17" />
        <lastIssuedKeySetId value="17" />

    </keyset-settings>
</packages>

此文件的关键元素:

权限块:系统中定义的权限列表。
包块:已安装应用程序的详细信息。
更新包块:与更新包相关的信息
共享用户块:系统定义的共享用户信息。
键集设置块:包含已安装的应用程序签名的公钥信息。

通知其他组件

最后,对包数据库的更改(新的包条目和任何新的权限)将持久化在磁盘上。PackageManagerService发送ACTION_PACKAGE_ADDED或ACTION_PACKAGE_REPLACED以防更新时通知其他组件有关新添加的应用程序。

猜你喜欢

转载自blog.csdn.net/m0_56255097/article/details/127559656