Benjy's Blog

BroadcastReceiver 接收顺序

2014-09-28

今天项目里有这样一个需求,访问一个请求并把手机号作为参数传过去,同时拦截收到的短信验证码,自动填进 EditText,一个看似很简单的功能。然而在真机上测试竟然没有拦截到,把优先级调到最大也无济于事。

四处寻访,原来 BroadcastReceiver 除了有优先级顺序之外,还有注册的顺序。

大家都知道广播分有序广播和无序广播,有序广播和无序广播的区别就是,有序广播可以被任何一个接受者消耗掉,而无序广播则不可以,注册的话既可以在代码里面动态注册,也可以在 Manifest 里面直接声明,屌丝青年大多会直接在 Manifest 里面定义注册,文艺青年一般使用代码动态注册。这两种方式接受的广播的顺序是不一样的。

一般来说有序广播在同等优先级的情况下有这样的顺序

  • 动态注册的 BroadcastReceiver,先注册的先接收
  • Manifest 里注册的 BroadcastReceiver,接收广播的顺序与 String[] java.io.File.list() 顺序一致

在不同优先级的情况下

  • 有序广播按优先级顺序接收
  • 无序广播因为是异步的所以接收 Broadcast 的顺序不确定。
假设有如下优先级的 5 个接收器 并且 B 先于 C 注册
1.动态A(优先级=1)
2.动态B(优先级=2)
3.动态C(优先级=2)
4.静态D(优先级=1)
5.静态E(优先级=2)
那么实际接收顺序应为: B C E A D

关于 String[] java.io.File.list()

我们以开机时候发出的广播 android.intent.action.BOOT_COMPLETED 为例,这是个无序广播。如果应用想要开启自启动,那么就要监听这个广播,程序启动之前,动态广播接收器肯定是无法使用的,只能在 XML 中静态注册。大家都知道,第三方应用是存放在 /data/app 目录下,当安装完毕之后,你会找到一个文件,他的名字是以与安装的应用包名开始的,然后可能会跟着”-数字.apk”,比如:com.android.test-1.apk。接收的顺序与这个名字是有关的!那么关系是怎样的呢?

  • 系统在开机的时候,会按着一个顺序解析apk,首先,会解析手机中的 /system/framework 这个目录,原生系统中,这下面就一个 apk - framework-res.apk,当然各个厂商也会加入自己的内容
  • 然后受到重视的文件夹按顺序分别为:
    /system/app,
    /vendor/app,
    /data/app,
    /drm/app-private
    那么每个文件夹下解析的顺序是怎样的呢?我们先只看 /data/app,也就是用户安装的第三方应用的存放位置,这与下面代码返回结果的顺序是一致的
    File file = new File(“/data/app/“);
    String[] files = file.list();
    也就是说,我们按顺序打印这个数组,就能知道哪个接收器会先接收到这个广播,哪个会后接收到。
Tags: Android