Broadcast
本篇内容整理自郭霖的 《第一行代码》
文章目录
广播机制介绍
- Android 系统广播更加灵活
- 应用对喜欢的广播注册,只接收想要的内容
- 广播来自系统或其他应用
发送广播需要借助Intent
接收广播需要广播接收器(Broadcast Receiver)
-
广播是一种跨进程的通信方式,因此这个应用发出广播,其他应用也可以收到
-
广播类型:标准广播、有序广播
标准广播(Normal broadcasts)
- 完全异步执行的广播(广播发出后,所有广播接收器会同时收到广播消息),效率较高
- 无序
- 无法截断
有序广播(Ordered broadcasts)
- 同步执行的广播(同一时刻只会有一个广播接收器 能接收到这条广播消息)
- 广播接收器逻辑执行完毕才会继续传递广播
- 有序
- 可以截断
接收系统的广播
-
Android 内置了很多系统级别的广播:
-
手机开机会发出一条广播
-
电池电量发生变化会发出一条广播
-
时间或者时区发生改变会发出一条广播
-
…
-
广播接收器注册广播,就可以接收该广播,并在内部处理相应的逻辑
-
在代码中注册:动态注册
-
在 AndroidManifest.xml 中注册:静态注册
动态注册 —— 监听网络变化
- 新建个类继承 BroadcastReceiver
- 重写父类的 onReceive() 方法:接收广播后的逻辑处理在此方法中
监听网络变化例子:
public class MainActivity extends Activity{
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
//网络状态发生变化,系统发出的就是这一条值为 android.net.conn.CONNECTIVITY_CHANGE 的广播
//(3)实例化广播接收器
networkChangeReceiver = new NetworkChangeReceiver();
//(4)对广播进行注册。两个参数,第一:广播接收器 第二:要注册的广播
registerReceiver(networkChangeReceiver, intentFilter);
}
protected void onDestroy(){
super.onDestroy();
//(5)动态注册的广播接收器一定要取消注册
unregisterReceiver(networkChangeReceiver);
}
// (1)新建一个内部类(广播接收器)继承 BroadcastReceiver
class NetworkChangeReceiver extends BroadcastReceiver{
// (2)重写父类的 onReceive() 方法
public void onReceive(Context context, Intent intent){
// 接收到广播后具体的业务处理
ConnectiviyManager connectionManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isAvailable()){
Toast.makeText(context, "network is available", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show();
// 查询系统的网络状态需要在配置文件中声明权限 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE />"
}
}
}
}
静态注册 —— 开机启动
- 可以使应用程序在未启动的状态下接收广播
开机启动例子:
// (1)新建一个 BootCompleteReceiver(不是内部类) 继承自 BroadcastReceiver
public class BootCompleteReceiver extends BroadcastReceiver{
public void onReceiver(Context context, Intent intent){
// 接收到广播后具体的业务处理
}
}
(2)在 AndroidManifest 中注册广播
....
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <-- 监听系统开机是需要权限 -->
<application
.....
>
<receiver android:name=".BootCompleteReceiver"> <-- 指定具体的广播接收器 -->
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" /> <-- 指定想要接收的广播 -->
</intent-filter>
</receiver>
</application>
onReceive()
方法不能开启线程,无法进行耗时操作。长时间运行程序会报错(广播接收器更多用处是打开程序其他组件。创建一条状态栏通知,启动服务之类)
发送自定义广播
发送标准广播
超级简单
public void onClick(){
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);
//点击事件发送了一条值为 com.example.broadcasttest.MY_BROADCAST 的广播
}
发送有序广播
同样超级简单
- 发送有序广播
public void onClick(){
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendOrderedBroadcast(intent, null);// 将 sendBroadcast 改为 sendOrderedBroadcast 即可发送有序广播
// sendOrderedBroadcast() 接收两个参数,第一:Intent 第二:与权限相关的字符
}
- 设置有序广播接收器优先级
只需在 AndroidManifest 中设置优先级
<receiver ....>
<intent-filter android:priority="99"> <--设置广播接收器优先级为99-->
<action ... />
</intent-filter>
</receiver>
- 广播接收器阻断有序广播
public void onReceive(Context context, Intent intent){
// 接收到广播后具体的业务处理
abortBroadcast(); // 阻断广播
}
使用本地广播
- 本地广播:广播只在本应用中传播,其他应用接收不到。无法使用静态注册
使用 LocalBroadcastManager 来对广播进行管理,并提供了发送广播和注册广播接收器的方法
private LocalReceiver localReceiver;
private LocalBroadcastManager localBroadcastManager;
protected void onCreate(...){
....
localBroadcastManager = LocalBroadcastManager.getInstance(this); // 获取 LocalBroadcastManager 实例
intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
localBroadcastManager.registerReceiver(localReceiver, intentFilter);// 注册广播
}
public void onClick(){
Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent); //发送本地广播
}
public void onDestroy(){
localBroadcastManager.unregisterReceiver(localReceiver);
}
class LocalReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent){
// 接收到广播后具体的业务处理
}
}
本地广播的优点:
- 广播不会发送到其他程序,不用担心数据泄漏问题
- 其他广播不会发送到程序内部,不会有安全漏洞
- 更加高效