咱们使用的上一届的版本中,使用的底层的 安卓的 API 是 Android7.0 。在这一版本中,咱们将 API进行了升级,为了更好的兼容新功能。(发送通知),咱们在升级 API中遇到的主要问题就是,在 Android7.0 到 Android8.0 这两个版本之间的时候,安卓会禁用隐式的静态广播,至于什么是安卓的广播与广播的机制,咱们推荐这篇博客,传送门 。html
广播主要用于 Android 中的不一样进程之间的通讯。通常执行的操做主要是 唤醒,或者发送通知,启动等等。java
广播的主要工做流程是:android
1.广播接收者BroadcastReceiver经过Binder机制向AMS(Activity Manager Service)进行注册;api
2.广播发送者经过binder机制向AMS发送广播;app
3.AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(通常状况下是Activity)相应的消息循环队列中;ui
4.消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。code
安卓系统不断地升级的过程当中,对广播机制作了不少的改变,这是由于广播的机制对资源的占用与消耗。所以在 Android 不断地升级的过程当中对这个广播机制作出了更多的限制。component
不一样Android API版本中广播机制相关API重要变迁htm
1).Android5.0/API level 21开始粘滞广播和有序粘滞广播过时,之后再也不建议使用;blog
2).”静态注册的广播接收器即便app已经退出,主要有相应的广播发出,依然能够接收到,但此种描述自Android 3.1开始有可能再也不成立“
Android 3.1开始系统在Intent与广播相关的flag增长了参数,分别是FLAG_INCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES。
FLAG_INCLUDE_STOPPED_PACKAGES:包含已经中止的包(中止:即包所在的进程已经退出)
FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已经中止的包
而在安卓的官方文档中能够看到 Android8.0 对广播机制作出的更加严格限制:
可是有时候,咱们仍是想使用静态广播来发送提醒或者是在 APP 关闭的状况下接收广播。
突破隐式限制的方法就是发送广播的时候携带intent.addFlags(0x01000000);
咱们看一下 Android8.0 的开源代码,在1278行有一个 skip = true;
1267 } else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0) 1268 || (r.intent.getComponent() == null 1269 && r.intent.getPackage() == null 1270 && ((r.intent.getFlags() 1271 & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0) 1272 && !isSignaturePerm(r.requiredPermissions))) { 1273 mService.addBackgroundCheckViolationLocked(r.intent.getAction(), 1274 component.getPackageName()); 1275 Slog.w(TAG, "Background execution not allowed: receiving " 1276 + r.intent + " to " 1277 + component.flattenToShortString()); 1278 skip = true; 1279 }
咱们想要进去的话,就不带 FLAG_RECEIVER_INCLUDE_BACKGROUND 标志位就能够了,因而咱们设置
public static final int FLAG_RECEIVER_INCLUDE_BACKGROUND = 0x01000000;