Android8.0无法接收隐式广播消息


App里有一个自己在Manifest文件里面注册的广播接收器(Receiver),到Android8.0的机器上调试的时候却接收不到消息,一番搜索和研究之后,才发现Android8.0已经对隐式广播做了限制。


版本区别

对于targetSdkVersion26或者以上的App,在Manifest里面注册的Receiver已经受到限制,而用Java代码动态注册的Receiver则不受影响。

targetSdkVersion 在 25或以下的App,其Receiver不受影响,即使在Android8.0以上的机器上运行。

如果targetSdkVersion 在26或者以上,在Manifest注册的Receiver可能无法接收到广播消息,并且会在Logcat里面打印出如下消息:

BroadcastQueue: Background execution not allowed: receiving Intent { act=com.xiaoqiang.try.something.receiver flg=0x2010 (has extras) } to xiaoqiang.com.trysomething/.broadcast.TheReceiver


有哪些影响

首先要了解一个概念。官方文档里提到implicit broadcast,可译为隐式广播,指那些没有指定接收App(即包名)的广播。
- 系统发送的广播毫无疑问都是隐式广播,因此基本上都会受到影响,除了部分受豁免广播之外
- App发送的自定义隐式广播,都会受到影响


为何限制隐式广播

总所周知,在Manifest里面注册的系统广播接收器会被缓存在系统中,即使当App关闭之后,如果有相应的广播发出,应用程序仍然会被唤醒。比如如果有20个App在Manifest里面注册了ACTION_BOOT_COMPLETED的广播接收器监听设备启动,那么当设备启动时,就会有20个应用程序被唤醒并作出相应的动作。而动态注册的广播则跟随组件的生命周期而消存。因此在Manifest里面注册广播接收器的App越多,设备的性能就越容易受到影响,限制隐式广播主要是为了优化系统性能。


如何应对这一限制

分析了受限制的原因之后,就知道该如何应对这一影响了。
- 优先使用动态注册Receiver的方式,能动态注册绝不使用Manifest注册

    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.xiaoqiang.try.something.receiver");
    TheReceiver receiver = new TheReceiver();
    registerReceiver(receiver, intentFilter);
  • 如果一定要Manifest注册,那么当发送广播的时候,指定广播接收者的包名,即发送显式广播
    Intent intent = new Intent("com.xiaoqiang.try.something.receiver");
    intent.putExtra("receive","test broadcast");
    intent.setPackage(getPackageName());
    //intent.setComponent(...)
    sendBroadcast(intent);
  • 如果要接收系统广播,而对应的广播在Android8.0中无法被接收,那么只能暂时把App的targetSdkVersion改为25或以下。


参考文章:
1. Android O and the Implicit Broadcast Ban
2. 官方文档

猜你喜欢

转载自blog.csdn.net/chenrenxiang/article/details/80886745