Broadcast知识点总结
1.定义
广播是Android为了让app内部或者app之间或者app和系统之间的交互所使用的一个机制,其主要的特点就是,broadcast只负责发送广播,不负责对应事件的处理和处理结果,也就是说它只负责发送广播,而听到广播后所采取的动作和事件与他无关。
2.广播的组成
广播主要是由三个部分组成。
- 广播(Broadcast):用于发送广播,当发送完广播之后,相应的广播接收器会有响应。
- 广播接收器(BroadcastReceiver):用于接收广播,当接收到广播之后,处理对应事件。
- 意图(Intent):用于保存广播相关的数据。
2.广播分类
- 标准广播(Normal broadcasts):广播的最标准的形式,为异步执行。当发出这种广播的时候,所有的广播接收器都会无差别的在同一时刻内接收到这条广播,效率高,但是也无法截断,一般情况下都会采用这种广播。
- 有序广播(Ordered broadcasts):广播的同步执行的形式。当发出这种广播之后,所有的广播接收器会按照设定好的优先级顺序依次接收到广播。
- 只有在前面一个广播接收器的逻辑执行完之后,后面的广播接收器才能收到广播。
- 有序广播中,后面的广播接收器所接收到的数据,是前面的广播接收器已经修改过的。
- 有序广播是可以从中间截断的,截断之后,后面的广播接收器就收不到广播了。
- 本地广播:仅在当前app内部所传播的广播,发出的广播不会被其他app监听到。
- 系统广播:由Android系统所发出的广播,发出的广播所有的app都能监听到。
3.广播的注册方式
首先,无论是哪种广播的注册,都需要一个广播接收器,新建一个类继承BroadcastReceiver,并重写其中的onReceive()方法,这样一个广播接收器就完成了。
public class ToastBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "It's a broadcastReceiver", Toast.LENGTH_SHORT).show();
}
}
3.1动态注册
动态注册:在代码中注册,在注册之后,每当发出广播的时候,广播接收器就会响应,并且完成相应的事件。
- 在MainActivity中注册一个监听网络变化的广播。在我们实机上改变网络环境时(模拟器不太好使),比如开关数据连接和开关wifi的时候,就会弹出这个toast。顺带一提,广播的执行是无关app的,也就是说,当你切换网络环境的时候,即使在桌面或者其他app,也会弹出这个toast。
public class MainActivity extends AppCompatActivity {
public IntentFilter intentFilter = new IntentFilter();
//实例化一个广播
ToastBroadcastReceiver toastBroadcastReceiver = new ToastBroadcastReceiver();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//android.net.conn.CONNECTIVITY_CHANGE是Android系统在每当网络环境变化的时候发出的系统广播
//在intentfilter添加这个动作之后,就会对这个行为进行监听
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
//动态注册广播必须要有context,而activity本身就是一个context
registerReceiver(toastBroadcastReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//动态注册广播的优势就是,在不需要使用的时候,就注销,注销之后就不会再有监听了。
unregisterReceiver(toastBroadcastReceiver);
}
}
3.2静态注册
静态注册:在AndroidManifest.xml中注册,用静态方式注册的广播不能取消注册,不过好处是,静态广播一经注册,即使没有打开app,也会在接收到广播的时候使用。
- 删除动态注册的代码,在AndroidManifet.xml中添加监听手机开机的广播,这样在手机开机的时候就会有对应Toast,当然,手机刚开机的时候我们的app自然是没有打开。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcastdemo">
<!-- 添加app可以监听开机的权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 这个receiver就是我们的广播接收器了 -->
<receiver
android:name=".ToastBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<!-- 为广播接收器添加监听开机的广播 -->
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>
-
其中android:enabled="true"表示广播接收器可以被实例化;android:exported="true"表示广播接收器可以被其他app所看见。
-
为什么不监听网络的原因1:android的SDKVersion上24的时候,不能再用静态监听了,不过动态监听不受影响。
-
注意2:从Android8.0开始,绝大部份的静态广播都不再被允许注册了,不过刚刚测试用到的开机广播还是可以使用的。
4.自定义广播
广播不仅是指接收来自系统发出的广播,我们自己也可以写一个广播来使用。
- 删除Android静态广播的receiver部分。
- 布局中随意添加一个button作为发出广播的条件。
- 由于这个广播只是内部使用,所以就正好用本地广播。在MainActivity添加本地广播的代码。
- 要注意的是,本地广播和普通广播是分开计算,不能互相监听,本地广播发出的广播只能被本地注册的接收器接收到,普通注册的接收不到。
public class MainActivity extends AppCompatActivity {
//意图过滤器,用这个添加我们所需要的广播,也就是过滤掉不需要的广播
private IntentFilter intentFilter = new IntentFilter();
ToastBroadcastReceiver toastBroadcastReceiver = new ToastBroadcastReceiver();
//本地广播所需要的本地广播管理类。
private LocalBroadcastManager localBroadcastManager;
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
//获取实例
localBroadcastManager = LocalBroadcastManager.getInstance(this);
//既然是自定义广播,那广播名字自然也是自定义
intentFilter.addAction("test_Aciton");
//注册本地广播
localBroadcastManager.registerReceiver(toastBroadcastReceiver, intentFilter);
//注册广播
//registerReceiver(toastBroadcastReceiver, intentFilter);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//实例化意图和添加广播
Intent intent = new Intent("test_Aciton");
//通过本地广播管理类发出本地广播
localBroadcastManager.sendBroadcast(intent);
//如果是发送普通广播就用下面这个,当然注册广播的时候也要注册普通广播
//sendBroadcast(intent);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
//注销本地广播
localBroadcastManager.unregisterReceiver(toastBroadcastReceiver);
//注销广播
//unregisterReceiver(toastBroadcastReceiver);
}
}
5.其他
5.1 同时注册的静态动态广播
有一个广播同时用静态和动态的方式注册了,那么在发出广播的时候,会先执行动态注册的那个广播。
5.2 多个广播接收器中指定其中一个
如果一个广播可以同时被多个广播接收器给接受,那么要如何做才能只让其中的一个广播接收器收到广播呢?
在AndroidManifest文件中,为广播加上自定义权限。广播接收器所在的app必须声明了这个权限才能收到该广播。
在发出广播的app中声明:
<permission android:name="broad.ok.receiver" android:protectionLevel="normal"/>
<uses-permission android:name="broad.ok.receiver" />
发出广播的时候加上权限字符串。
Intent intent = new Intent();
intent.putExtra("info", "消息内容");
intent.setAction("myBroadcast.action.call");
sendBroadcast(intent, "broad.ok.receiver");
//sendOrderedBroadcast(intent,"broad.ok.receiver");
只有声明了该权限的app才能收到该广播。
<uses-permission android:name="broad.ok.receiver"/>
参考材料
Android总结篇系列:Android广播机制
http://www.cnblogs.com/lwbqqyumidi/p/4168017.html%20
第一行代码——Android(第2版)
p170 - p185
17 个必须掌握的 BroadcastReceiver 知识点「建议收藏」 - 圆号本昊 - 博客园
https://www.cnblogs.com/yuanhao-1999/p/11817955.html
静态注册不监听网络的原因参考这篇:
https://blog.csdn.net/c6e5uli1n/article/details/81351511 ↩︎新版本不能静态注册广播的原因参考这篇:
https://www.cnblogs.com/fuyaozhishang/p/8580610.html ↩︎