Broadcast 专讲

最近遇到一个问题,在做培训时,屡试不爽的广播消息竟然存在接收不到广播的情况。经了解后发现,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. 优先级高的接收器,优先接收到消息,并可以像优先级低的广播传递数据,还可以终止广播继续传递。
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
<!--使用自定义的权限,包括下面注册广播时,使用的 permission 属性。-->
<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/)

Author: flueky
Link: http://example.com/023/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.