最近遇到一个问题,在做培训时,屡试不爽的广播消息竟然存在接收不到广播的情况。经了解后发现,Android O 已对隐式广播添加限制。so,下面总结下 Android 中广播相关。
1. 广播注册
广播注册分为静态注册和动态注册,静态注册的广播,可以在程序没被启动时,接收到全局广播消息。而动态注册广播,只有在程序启动后接收广播消息。
1.1 静态注册
定义好广播消息后,在 AndroidManife.xml 中注册即可,示例中,添加多个 Action。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <receiver android:name="com.flueky.demo.DemoReceiver" android:permission="com.flueky.demo.permission.Demo_Receiver"> <intent-filter android:priority="999"> <action android:name="com.flueky.app.Demo_Receiver" /> </intent-filter> <intent-filter> <action android:name="com.flueky.demo.TEST_RECEIVER1" /> </intent-filter> <intent-filter> <action android:name="com.flueky.demo.TEST_RECEIVER2" /> </intent-filter> </receiver>
|
1.2 动态注册
动态注册指在 Activity 或 Service 中注册,并在 Activity 或 Service 销毁时,需要注销。
1 2 3 4
| registerReceiver(testReceiver, new IntentFilter("com.flueky.demo.TEST_RECEIVER1"));
unregisterReceiver(testReceiver);
|
由于动态注册的广播可以通过定义内部类的方式实现,因此,动态 注册的广播可以同宿主 Activity 或 Service 进行交互。
2. 广播分类
2.1 无序广播
应用发出广播后,所有注册了广播 Action 接收到广播的先后顺序是未知的,则叫发送了无序广播。
1 2
| Intent intent = new Intent("com.flueky.app.Demo_Receiver"); sendBroadcast(intent, "com.flueky.demo.permission.Demo_Receiver");
|
2.2 有序广播
应用发出广播后,所有注册了广播 Action 接收到广播的先后顺序是固定的,则叫发送了无序广播。
1 2
| Intent intent = new Intent("com.flueky.app.Demo_Receiver"); sendOrderedBroadcast(intent, "com.flueky.demo.permission.Demo_Receiver");
|
- 发送有序广播需要指定一个权限。
- 优先级高的接收器,优先接收到消息,并可以像优先级低的广播传递数据,还可以终止广播继续传递。
1 2 3 4
| <intent-filter android:priority="999"> <action android:name="com.flueky.app.Demo_Receiver" /> </intent-filter>
|
有序广播接收器中传递消息和终止广播如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| if (!isOrderedBroadcast()) return;
Bundle bundle = getResultExtras(true); String received = bundle.getString("received");
Log.d(TAG, "onReceive: 广播发送 "+(received==null?"null":received));
bundle.putString("received","已被 send 接收"); setResultExtras(bundle);
abortBroadcast();
|
2.3 本地广播
发送有序广播和无序广播后,设备中的其他应用只需要注册了接收广播的 Action ,都可以接收到广播消息。为了只在自己应用中接收到广播消息,Google 先后给出了两种方案。其中一种是本地广播,通过 v4 包提供了 LocalBroadcastManager 类,注册、注销和发送广播。
1 2 3 4 5 6 7
| LocalBroadcastManager.getInstance(this).registerReceiver(testReceiver, new IntentFilter("com.flueky.demo.TEST_RECEIVER2"));
LocalBroadcastManager.getInstance(this).sendBr oadcast(new Intent("com.flueky.demo.TEST_RECEIVER2"));
LocalBroadcastManager.getInstance(this).unregisterReceiver(testReceiver);
|
本地广播只能通过动态注册的方式,而且由 LocalBroadcastManager 注册的广播只能接收 LocalBroadcastManager 发送的广播。
3. 自定义权限
在 Android 8.0 以上,使用全局广播必须给广播接收器添加上权限。发送广播时需要使用广播接收器申明的权限,而且,发送广播的应用需要在 AndroidManifest.xml 中申明权限。
具体做法是:发送广播的应用清单文件类容如下:
1 2 3 4 5 6 7
| <permission android:name="com.flueky.demo.permission.Demo_Receiver" android:protectionLevel="signature" />
<uses-permission android:name="com.flueky.demo.permission.Demo_Receiver" />
|
代码如下:
1 2 3
| Intent intent = new Intent("com.flueky.app.Demo_Receiver"); sendBroadcast(intent, "com.flueky.demo.permission.Demo_Receiver");
|
接收广播应用的清单文件如下:
1 2 3 4 5 6 7 8 9 10
| <uses-permission android:name="com.flueky.demo.permission.Demo_Receiver" />
<receiver android:name="com.flueky.demo.DemoReceiver" android:permission="com.flueky.demo.permission.Demo_Receiver"> <intent-filter android:priority="1000"> <action android:name="com.flueky.app.Demo_Receiver" /> </intent-filter> </receiver>
|
最后,发送广播和接收广播的应用必须使用同一个签名文件。因为自定义权限的安全级别是 signature。
源码地址。
觉得有用?那打赏一个呗。[去打赏](/donate/)