概念:Android四大组件之一,没有可视化界面,用于不同组件和多线程之间的通信。
目录
- 静态注册和动态注册的区别
- Android 8.0静态广播失效解决办法
- 有序广播
-
静态注册和动态注册的区别
- 静态注册:在AndroidManifest.xml 中,通过标签来声明
<receiver android:name="com.yirong.library.NetStateReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
</intent-filter>
</receiver>
优点:不受其他组件生命周期影响,即使应用程序被关闭,也能接收广播。
缺点:耗电,占内存。
适用场景:需要时刻监听的广播
事实上在,google因为电池优化的原因从7.0开始已经对静态注册做出了一些限制(权限),并在8.0使大部分静态注册失效了,极少数例如ACTION_BOOT_COMPLETED
, ACTION_HEADSET_PLUG
, ACTION_CONNECTION_STATE_CHANGED
等广播依旧有效。可以说,未来使用动态注册已经是一种趋势,不过在兼容低版本时,静态注册依旧好用。
- 动态注册:在代码中注册
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
receiver = new NetStateReceiver();
registerReceiver(receiver, intentFilter);
unregisterReceiver(receiver);
优点:灵活,不耗电,易控,省内存
缺点:需要手动注销
适用场景:需要特定时候监听的广播
-
Android 8.0静态广播失效解决办法
- Android 8.0行为变更文档地址:https://developer.android.google.cn/about/versions/oreo/android-8.0-changes
- 能不用静态注册就不用,尽量使用动态注册
- 显式广播注册
Intent intent = new Intent("com.yirong.library.receiver");
intent.putExtra("receive","helloworld!");
intent.setPackage(getPackageName());
//intent.setComponent(...)
sendBroadcast(intent);
- 看源码,使用@hide API
if (!skip) {
final int allowed = mService.getAppStartModeLocked(
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
// We won't allow this receiver to be launched if the app has been
// completely disabled from launches, or it was not explicitly sent
// to it and the app is in a state that should not receive it
// (depending on how getAppStartModeLocked has determined that).
if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
Slog.w(TAG, "Background execution disabled: receiving "
+ r.intent + " to "
+ component.flattenToShortString());
skip = true;
} else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
|| (r.intent.getComponent() == null
&& r.intent.getPackage() == null
&& ((r.intent.getFlags()
& Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
&& !isSignaturePerm(r.requiredPermissions))) {
mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
component.getPackageName());
Slog.w(TAG, "Background execution not allowed: receiving "
+ r.intent + " to "
+ component.flattenToShortString());
skip = true;
}
}
}
携带 FLAG_RECEIVER_INCLUDE_BACKGROUND 这个标志位的intent,可以调用静态广播。
发送广播的时候携带intent.addFlags(0x01000000); 即能让广播突破隐式广播限制。
解决方法:https://blog.csdn.net/jingwen3699/article/details/83107017
-
有序广播
一般广播都是所有接收者同时执行的,有序广播有所不同。
他根据广播的优先级,按顺序执行。只有当优先级高的广播接收者onReceive()方法执行完毕,才会执行优先级低的广播接受者的onReceive()方法。同时,当前正在执行的广播接收者能够终止广播的传播。
Tips:粘性广播已经被弃用