导读:本文说明系统是如何注册动态广播以及静态广播,这里主要注意其注册的顺序

这篇文章主要是针对我前两篇文章

android安全问题(四) 抢先开机启动 - 结果篇

android安全问题(五) 抢先拦截短信 - 结果篇

之前只给出了结果,并没有给出代码分析,现在给出第一步分的分析

大家都知道,广播接收器分为动态注册和静态注册两种

静态接收,就是配置到manifest.xml文件中,PackageManagerService扫描后记录其信息……

动态接收,就是从代码中注册,通过调用下面的方法实现

Intent android.content.Context.registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

(下面的流程图估计画的比较水,将就看一下吧,得补习一下UML了)

首先分析静态注册Receiver的流程

静态receiver的注册是由PackageManagerService开机的时候负责初始化

(PackageManagerService之后简称为PMS)

PMS在开机的时候会对系统一些目录逐个扫描,解析apk文件。静态广播接收器就是在PMS做这件事情的时候顺便处理的。

PMS会解析apk的manifest文件,查找这里注册的receiver,然后加载到内存中

下面看一下PMS是如何工作的

这部分内容没有什么难度,只要有耐心就行,我画了一个很简单流程图,从调用PMS的构造函数开始

注意,这里有几个同名函数,大家需要分清。并不是同一个函数调用了两次

这里只看几处

1.PMS初始化的时候干了些什么

当然,PMS会做很多很多事情,这里我们只看我们关注的,和这篇文章相关的部分

Java代码 复制代码 收藏代码
  1. // Collect all system packages.
  2. mSystemAppDir = new File(Environment.getRootDirectory(), "app");
  3. mSystemInstallObserver = new AppDirObserver(
  4. mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
  5. mSystemInstallObserver.startWatching();
  6. scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
// Collect all system packages.mSystemAppDir = new File(Environment.getRootDirectory(), "app");mSystemInstallObserver = new AppDirObserver(    mSystemAppDir.getPath(), OBSERVER_EVENTS, true);mSystemInstallObserver.startWatching();scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

扫描目录的顺序

system/framework

system/app

vendor/app

data/app

drm/app-private

这里以system/app目录为例

2.下一个要关注的地方是

void com.android.server.pm.PackageManagerService.scanDirLI(File dir, int flags, int scanMode, long currentTime)

Java代码 复制代码 收藏代码
  1. private void scanDirLI(File dir, int flags, int scanMode, long currentTime {
  2. String[] files = dir.list();
  3. ……
  4. int i;
  5. for (i=0; i<files.length; i++) {
  6. File file = new File(dir, files[i]);
  7. ……
  8. PackageParser.Package pkg = scanPackageLI(file, flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
  9. ……
  10. }
  11. }
private void scanDirLI(File dir, int flags, int scanMode, long currentTime {    String[] files = dir.list();    ……    int i;    for (i=0; i<files.length; i++) {        File file = new File(dir, files[i]);……        PackageParser.Package pkg = scanPackageLI(file, flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);……    }}

注意

Java代码 复制代码 收藏代码
  1. String[] files = dir.list();
String[] files = dir.list();

以及之后的for循环

3.之后的部分比较无聊,我们直接跳到parseApplication函数部分

Java代码 复制代码 收藏代码
  1. else if (tagName.equals("receiver")) {
  2. Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
  3. if (a == null) {
  4. mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
  5. return false;
  6. }
  7. owner.receivers.add(a);
  8. }
else if (tagName.equals("receiver")) {    Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);    if (a == null) {        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;        return false;    }    owner.receivers.add(a);}

这部分就是解析manifest中的receiver部分,大家会很奇怪,receiver为什么会变成一个Activity

此Activity非彼Activity,这个Activity是PackageParser的一个内部类,结构也非常简单

更多相关文章

  1. 关于代码家(干货集中营)共享知识点汇总系列——Android
  2. 《Android第一行代码》笔记
  3. Android开心消消乐代码实例详解
  4. Android的static静态变量
  5. Android同一套代码打多个APP包并能够在同一个手机上安装运行
  6. android实现短按电源键关机的实现代码
  7. strcpy函数在android中的实现
  8. android sqlite 批量插入数据优化代码

随机推荐

  1. Android获取屏幕高度宽度的方法
  2. 阅读材料。。 暂存,放着读一下。。
  3. 2.4.1 自动完成文本框
  4. Android和.NET通用的AES算法
  5. Android(二):Notification基本操作
  6. Android(安卓)SMS(一) —— 读取短信 .
  7. 判断android应用程序是否已安装
  8. android中ContentResolver的使用
  9. Android(安卓)实现两次点击返回键 提示退
  10. Android全局变量的设置