APK安装流程详解(一)

APK安装流程详解(一)

一.基础知识

1.1 AndroidManifest理解

我们大家都知道AndroidManifest是清单文件,列举了APK的核心信息,包括权限、元数据、四大组件、启动模式等信息。但他只是一个xml文件,在安装时会起什么作用呢?为了便于理解,我们看下图:



下面我们依据上图把涉及到的类分析一下:

1.1.1 PackageInfo

该类实现了Parceable接口,可以在进程间传递。
重要成员变量简介:

  • public String packageName: 包名
  • public String versionName:版本名
  • public String versionCode:版本号
  • public String sharedUserId:共享用户ID,签名相同的情况下程序之间数据共享
  • public long firstInstallTime:第一次安装时间,忽略之前安装后卸载的情况单位ms
  • public long lastUpdateTime:最后更新时间,相同版本号的APK覆盖安装,该值也会发生变化,单位ms
  • public String[] requestedPermissions:请求的权限
  • public ApplicationInfo applicationInfo:Applicationinfo对象,下面会讲解
  • public ActivityInfo[] activities:注册的Activity
  • public ActivityInfo[] receivers:注册的Receiver,PS:注意这里是ActivityInfo[]
  • public ServiceInfo[] services:注册的服务
  • public ProviderInfo[] providers:注册的Providers

我们看可以看出,该类包含了从AndroidManifest.xml中收集的所有信息。

1.1.2 PackageItemInfo

它是AndroidManifest.xml文件中所有节点的基类,提供最基本的属性集合,如:label、icon、meta等。

1.1.3 ApplicationInfo

该类继承自PackageItemInfo并实现了Parcelable接口,对应Manifest.xml中的<application>节点里的信息

1.1.4 ActivityInfo、ServiceInfo、Provider

ActivityInfo继承自ComponentInfo并实现了Parcelable接口,对应AndroidManifest.xml里面的<activity>或者<receiver>节点里的信息,可以用来设置我们的任何属性,包括theme、launchMode等。

ServiceInfo继承自ComponentInfo并实现了Parcelable接口,它对应manifest里面<service>节点的信息。

ProviderInfo类继承自ComponentInfo并实现了Parcelable接口,对应manifest里面的<provider>节点的信息

1.1.5 ResolveInfo

ResolveInfo就是解件intent过程返回的信息,对应位于AndroidManifest.xml的<intent>标签收集到的信息。
重要成员变量简介:

  • public ActivityInfo activityInfo:和Intent相匹配的ActivityInfo(可能是Activity或者Receiver)
  • public ServiceInfo serviceInfo:和Intent相匹配的serviceInfo
  • public ProviderInfo providerInfo:和Intent相匹配的providerInfo
  • public IntentFilter filter:匹配的IntentFilter
1.1.6PermissionInfo

顾名思义,这个类代表应用的权限描述信息,既是权限信息的记录,也是权限的级别保护,在Android系统中,做任何操作都要申请权限。使用PermissionInfo指定一个权限的基本信息时,需要指定protectedLevel和所属的group信息。
重要的成员变量:

  • public int protectionLevel:保护权限的级别,可以是如下级别
    public static final int PROTECTION_NORMAL:表示只要是申请了就可以使用的级别。
    public static final int PROTECTION_DANGEROUS:表示在安装时需要用户确认才可以使用
    public static final int PROTECTION_SIGNATURE:表示使用者的APP和系统使用同一个证书,即系统权限级别
  • public String group:权限组
1.1.7类结构

上述类的类结构如下图所示:


二.PackageManager

2.1PackageManager简介

我们先来看一下注释

/**
 * Class for retrieving various kinds of information related to the application
 * packages that are currently installed on the device.
 *
 * You can find this class through {@link Context#getPackageManager}.
 */
public abstract class PackageManager {
   ...
}

由以上可知这是一个抽象类,可以获取已安装APK的各种信息,你可以通过Context.getPackageManager方法来获取这个类。

2.2PackageManager与APK安装

2.2.1 什么是PackageManager

PackageManager是管理应用程序安装、卸载和升级的API。当我们安装APK文件时,PackageManager会解析APK包文件和显示确认信息。当我们点击OK按钮后,PackageManager会调用InstallPackage方法,PackageManager会启动一个Service服务PackageManagerService(下文简称PMS),所有相关的操作都在这个service中发生。APK安装流程如下图:

2.2.2 PackageManager的作用是什么
  • 安装、卸载应用
  • 查询permission信息(application、activity、receiver、service、provider及相应属性等)
  • 查询Application相关信息
  • 查询已安装应用
  • 增加、删除permission
  • 清除用户数据、缓存、代码等

2.3PackageManager的具体实现类

我们知道PackageManager是一个抽象类,现在我们来看一下它的具体实现类。2.1小节中我们看PackageManager的注释中,官方推荐通过Context的实现类ContextImpl#getPackageManager方法来获取,查看Android源码,发现返回的是ApplicationPackageManager类。

@Override
    public PackageManager getPackageManager() {
        // 第一步
        if (mPackageManager != null) {
            return mPackageManager;
        }
        // 第二步
        IPackageManager pm = ActivityThread.getPackageManager();
         // 第三步
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }
        return null;
    }
2.3.1 ApplicationPackageManager

ApplicationPackageManager中关于PackageManager的具体实现,其实是调用IPackageManager来实现的。

2.3.2 IPackageManager

IPackageManager的获取是在Context的getPackageManager方法中,调用ActivityThread#getPackageManager方法,关于ActivityThread会在后续Android系统启动流程中详细讲解。

/**ActivityThread.java**/
public static IPackageManager getPackageManager() {
         //第一步
        if (sPackageManager != null) {
            return sPackageManager;
        }
        // 第二步
        IBinder b = ServiceManager.getService("package");
        
        // 第三步 
        //返回IpackageManager.Stub.Proxy
        sPackageManager = IPackageManager.Stub.asInterface(b);
       
        return sPackageManager;
    }

这个方法内部流程大体上分三步:

  • 判断sPackageManager是否为空,如果为空说明是第一次调用,走第二步,如果不为空,直接返回sPackageManager
  • 走到第二步,说明是第一次调用。调用ServiceManager#getService方法获取一个IBinder对象
  • 通过调用IPackageManager.Stub.asInterface方法获取一个sPackageManager对象

上面的代码看着是不是有点熟悉?是不是让你写到了AIDL?这里涉及到了Binder知识,会在另外一个系列文章中讲述。

所以我们得知在ApplicationPackageManager里面的mPM其实就是IPackageManager.Stub内部类的Proxy对象。对应的IPackageManager.Stub就是PackageManagerService.java,因为:

public class PackageManagerService extends IPackageManager.Stub {
   ...
}
  • PackageManager负责通信。

IPackageManager中定义了很多业务方法,但是出于安全等方面的考虑,Android SDK对外提供的是它的一个子集,该子集被封装在抽象类PackageManager中。客户端一般通过Context#getPackageManager方法获取PackageManager,实际返回的是ApplicationPackageManager,ApplicationPackageManager并没有直接参与Binder通信,而是其中一个mPM成员指向了一个IPackageManager.stub.Proxy对象

  • AIDL中的Binder服务端是PackageManagerService。PMS作为服务端参与Binder通信。

  • AIDL中的Binder客户端是ApplicationPackageManager中成员变量mPM,mPM指向的是IPackageManager.stub.Proxy

整体Binder流程如下:

2.4形象理解

假设你在和客房商谈事务,要给老板打电话请示。这里,你就是应用进程里的ApplicationPackageManager,IpackageMaanger就是你们的通信工具-电话,你的老板就是SystemServer进程里面的PackageManagerService,你的电话是IPackageManager.Stub.Proxy,老板的电话是IPackageManager.Stub。IpackageManager其实就是一个具体业务场景下的数据交换的工具而已。

三.总结

本文主要讲了PackageManager和PackageManagerService的关系,PackageManagerService事实上是一个binder(继承自IpackageManager.Stub,而Stub继承自Binder),Client端通过获取获取PMS的服务代理对象IpackageManager.Stub.Proxy,通过Binder调用服务端Binder中的方法,即Stub中的接口实现。如下图:


参考文章:http://www.jianshu.com/p/a301291ca845

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容