《第一行代码》读书笔记 -- 应用组件之 BroadcastReceiver
《第一行代码》读书笔记(一)-- 平台架构 (第1章)
《第一行代码》读书笔记(二)-- 应用组件之 Activity (第2、4章)
《第一行代码》读书笔记(三)-- 应用组件之 Service (第10章)
《第一行代码》读书笔记(四)-- 应用组件之 BroadcastReceiver (第5章)
《第一行代码》读书笔记(五)-- 应用组件之 ContentProvider (第7章)
《第一行代码》读书笔记(六)-- 数据存储方案 (第6章)
《第一行代码》读书笔记(七)-- 多媒体资源 (第8章)
《第一行代码》读书笔记(八)-- 网络编程 (第9章)
第5章 全局大喇叭
BroadcastReceiver,广播接收者,它是一个系统全局的监听器,用于监听系统全局的 Broadcast 消息,所以它可以很方便的进行系统组件之间的通信。
BroadcastReceiver 属于系统级的监听器,它拥有自己的进程,只要存在与之匹配的 Broadcast 被以 Intent 的形式发送出来,BroadcastReceiver 就会被激活。
广播的使用场景:
(1)同一 APP 具有多进程的不同组件之间的信息通信。
(2)不同 APP 之间的组件之间信息通信。
Android中的广播分为两种类型,标准广播和有序广播
(1)标准广播
标准广播是一种完全异步执行的广播,在广播发出后所有的广播接收器会在同一时间接收到这条广播,之间没有先后顺序,效率比较高,且无法被截断。
(2)有序广播
有序广播是一种同步执行的广播,在广播发出后同一时刻只有一个广播接收器能够接收到, 优先级高的广播接收器会优先接收,当优先级高的广播接收器的 onReceiver() 方法运行结束后,广播才会继续传递,且前面的广播接收器可以选择截断广播,这样后面的广播接收器就无法接收到这条广播了。
接收系统广播
动态注册
动态注册 BroadcastReceiver 是在代码中定义并设置好一个 IntentFilter 对象,然后在需要注册的地方调用 Context.registerReceiver() 方法,调用 Context.unregisterReceiver() 方法取消注册,此时就不需要在清单文件中注册。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private IntentFilter intentFilter;
private NetWorkBroadcastReceiver netWorkBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
netWorkBroadcastReceiver = new NetWorkBroadcastReceiver();
registerReceiver(netWorkBroadcastReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(netWorkBroadcastReceiver);
}
class NetWorkBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive: "+"network changes");
}
}
}
动态注册广播接收器可以自由地控制注册与注销,但是必须程序启动之后才能收到广播,因为注册的逻辑是写在 onCreate() 方法中。
静态注册
静态注册即在清单文件中为 BroadcastReceiver 进行注册,使用 < receiver > 标签声明,并在标签内用 < intent-filter > 标签设置过滤器。
这种形式的 BroadcastReceiver 的生命周期伴随着整个应用,如果这种方式处理的是系统广播,那么不管应用是否在运行,该广播接收器都能接收到该广播。
public class BootCompleteReceiver extends BroadcastReceiver {
private static final String TAG = "BootCompleteReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive: "+"Boot Complete");
}
}
manifest 文件中声明:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
发送自定义广播
前面是同通过广播接收器接收系统广播,接下来是发送自定义广播。
首先注册广播接收器,这里选择静态注册方法:
public class CustomReceiver extends BroadcastReceiver {
private static final String TAG = "CustomReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive: "+"接收到自定义广播");
}
}
然后在 manifest 中声明 广播接收器:
<receiver
android:name=".CustomReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.wshunli.broadcastreceiverdemo.CUSTOM_BROADCAST" />
</intent-filter>
</receiver>
发送标准广播
发送标准广播调用的是 sendBroadcast(Intent) 方法
sendBroadcast(new Intent("com.wshunli.broadcastreceiverdemo.CUSTOM_BROADCAST"));
发送有序广播
发送有序广播调用的是 sendOrderedBroadcast(Intent , String) 方法,String 参数值在自定义权限时使用。
sendOrderedBroadcast(new Intent("com.wshunli.broadcastreceiverdemo.CUSTOM_BROADCAST"),null);
Receiver 接收广播时不仅因为 “priority” 属性存在先后顺序,且 Receiver 之间也能够传递数据。
此外,BroadcastReceiver 也能调用 abortBroadcast() 方法截断广播,这样低优先级的广播接收器就无法接收到广播了。
使用本地广播
之前发送和接收到的广播全都是属于系统全局广播,即发出的广播可以被其他应用接收到,而且也可以接收到其他应用发送出的广播,这样可能会有不安全因素。
因此,在某些情况下可以采用本地广播机制,使用这个机制发出的广播只能在应用内部进行传递,而且广播接收器也只能接收本应用内自身发出的广播。
本地广播是使用 LocalBroadcastManager 来对广播进行管理。
首先,创建一个 BroadcastReceiver 用于接收本地广播:
class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive: " + "LocalReceiver");
}
}
然后使用 LocalBroadcastManager 注册或者注销 广播接收器:
private IntentFilter intentFilter;
private LocalReceiver localReceiver;
private LocalBroadcastManager localBroadcastManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("com.wshunli.broadcastreceiverdemo.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);
}
最后通过 LocalBroadcastManager 发送本地广播:
localBroadcastManager.sendBroadcast(new Intent("com.wshunli.broadcastreceiverdemo.LOCAL_BROADCAST"));
需要注意的是,本地广播是无法通过静态注册的方式来接收的,因为静态注册广播主要是为了在程序未启动的情况下也能接收广播,而本地广播是应用自己发送的,此时应用肯定是启动的了。
本地广播的优势:
(1)发送的广播不会离开我们的应用程序,所以不必担心机密数据泄露;
(2)其他程序的广播也无法发送到我们程序内部,不用担心会有安全漏洞;
(3)本地广播比发送系统全局广播将更加有效。
参考资料
1、Broadcasts | Android Developers
https://developer.android.com/guide/components/broadcasts.html
2、Android之BroadcastReceiver | 吴小龙同學
http://wuxiaolong.me/2015/11/03/BroadcastReceiver/
3、Android BroadcastReceiver使用详解 - 简书
https://www.jianshu.com/p/f348f6d7fe59
4、Android深入四大组件(四)广播的注册、发送和接收过程 | 刘望舒的博客
http://liuwangshu.cn/framework/component/4-broadcastreceiver.html
评论 (0)