问题解决记录
最近发现了一个问题,我们的APK只能够接收待机下去的广播,而接收不到待机起来的广播。这就很奇怪了,于是便找到了系统发送待机和待机起来广播的相关类。
frameworks\base\services\java\com\android\server\power\Notifier.java
从里面找到下面这段代码,可以看到对于开机和待机广播发送的代码其实是一样的。
mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
既然如此,按理说我们的应用是可以接到到两个广播才对啊,不然就应该两个都收不到。于是便进一步分析自己的应用。分析后来发现,接受待机广播是静态注册的,而接收待机起来的广播是动态注册的。这时候可以注意到,两个 TAG 里面有一个Intent.FLAG_RECEIVER_REGISTERED_ONLY
。
我们查了一下,发现如果发送广播时设置了这个标志,那只会调用静态注册了的接收器——BroadcastReceiver组件不会被启动。所以这里就很明白了,因为我们需要比较快的接收到待机广播,从而做出处理,所以这里我们采用了优先级较高的动态注册,这样会一定程度上的防止接收不到广播的问题。那么要解决这个问题,只要在发送待机起来广播的时候把相应的TAG去掉就好,所以修改后代码如下:
mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
关于广播接收器的一些参考资料
广播接收器注册的两种形式
- 静态注册
非常驻型广播,也就是说广播跟随activity的生命周期。注意: 在activity结束前,移除广播接收器。 - 动态注册
常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行
广播的类型:
-
有序广播
- 优先级高的先接收
- 同优先级的广播接收器,动态优先于静态
- 同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。
-
普通广播
- 无视优先级,动态广播接收器优先于静态广播接收器
- 同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。
网友评论