本篇是对Android四大组件:BroadcastReceiver史上最全面解析的学习笔记。
一、作用
广播接收器的作用是接收应用/Andorid系统内的广播,并且做出相应反应。
二、相关概念
1. 观察者模式
...待续
三、 具体使用
1. 自定义广播接收器
创建一个类,继承自BroadcastReceiver
,重写onReceive()
,当接收当广播后回调该方法。
public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// do something
}
}
2. 注册广播接收器
(1)静态注册
在AndroidManifest.xml
中,使用<receiver>
标签实现静态注册。
<receiver android:name=".MyReceiver"
android:enabled="true"
android:exported="true"
android:icon="@android:color/background_dark"
android:label="@string/app_name"
android:permission="@string/app_name"
android:process="@string/app_name">
<intent-filter android:priority="100">
<action android:name="android.net.conn.CONNECTIVITY_CHANGED"/>
</intent-filter>
</receiver>
-
android:enable
是否启用这个广播接收器 -
android:exported
Android 四大组件都有这个属性。是否允许这个广播接收器接收本程序以外的广播。 -
icon
、lable
、name
基本属性配置 -
intent-filter
每个 receiver 都要配置过滤条件,action
表示该广播接收器感兴趣的广播,否则什么广播都接收不到。
(2)动态注册
在代码中调用Context.registerReceiver()
动态注册要有对应的注销。注册一般放在生命周期的
onResume()
中,注销放在onPause()
中。因为当系统内存不足或其他情况下,需要回收 Activity 时,onPause()
一定会被回调,但onStop()
、onDestroy()
不一定会有机会被回调。这样保证了广播接收器一定会被注销,防止内存泄露。
public class MainActivity extends AppCompatActivity {
MyReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
receiver = new MyReceiver();
// 广播接收器要设置相应的 action,否则接收不到任何广播
IntentFilter filter = new IntentFilter();
// 设置可接收的广播类型
filter.addAction(android.net.conn.CONNECTIVTY_CHANGED);
// 注册广播接收器
registerReceiver(receiver, filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
}
3. 发布广播
(1)普通广播
开发者自定义的广播。把意图发送出去,即是发送广播。
Intent intent = new Intent();
intent.setAction("BROADCAST");
sendBroadcast(intent);
若广播接收器的 action
中指定接收名为BROADCAST"
的广播,则可以接收到。
(2)系统广播
-
Android 内置了多个系统广播:只要涉及到手机的基本操作(如开机、网络状态变化、拍照等),都会发出相应广播。
-
每个广播都有特定的Intent - Filter(包括具体的action)
例如:接收开机广播
android.intent.action.BOOT_COMPLETED
,需要权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
(3)粘性广播
用的比较少。
(4)有序广播
sendOrderedBroadcast(intent);
-
发出去的广播被广播接收者按先后顺序接收
-
广播接收者接收的顺序根据
<receiver>
标签中的android:priority
属性的顺序确定
priority
的值越大越靠前;
若priority
的值相同,则动态注册的广播优先。
-
先接收广播的 Receiver 可以截断广播,则后面的 Receiver 接收不到
-
先接收广播的 Receiver 可以修改广播,则后面的 Receiver 接收到修改后的广播
(5)应用内广播
Android 中的广播可以跨 App 直接通信,那么可能出现的问题有:
-
其他 App 有针对性地发送与本 App 的
Intent-filter
相匹配的广播,使得本 Application 不断接收广播并做出处理,消耗资源 -
其他 App 注册与本 App 相同的
Intent-filter
的 Receiver,用于接收本 App 的广播,存在安全问题
所以将全局广播修改为局部广播,有2种方法。
a)将全局广播设置为局部广播
-
注册广播时将
exported
属性设置为false,使得非本App内部发出的此广播不被接收; -
在广播发送和接收时,增设相应权限
permission
,用于权限验证; -
发送广播时指定该广播接收器所在的包名,此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中
b)使用封装好的LocalBroadcastManager类
LocalBroadcastManager 发送的应用内广播的 Receiver 只能通过动态方式注册。
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
receiver = new MyReceiver();
// 广播接收器要设置相应的 action,否则接收不到任何广播
IntentFilter filter = new IntentFilter();
// 设置可接收的广播类型
filter.addAction(android.net.conn.CONNECTIVTY_CHANGED);
// 注册广播接收器
localBroadcastManager.registerReceiver(receiver, filter);
localBroadcastManager.unregisterReceiver(receiver);
4. 接收广播
广播接收器接收到广播后会回调onReceive()
方法。
四、注意事项
对于不同注册方式的广播接收器回调OnReceive(Context context,Intent intent)中的context返回值是不一样的:
-
对于静态注册(全局+应用内广播)
回调onReceive(context, intent)中的context返回值是:ReceiverRestrictedContext; -
对于全局广播的动态注册
回调onReceive(context, intent)中的context返回值是:Activity Context; -
对于应用内广播的动态注册(LocalBroadcastManager方式)
回调onReceive(context, intent)中的context返回值是:Application Context。 -
对于应用内广播的动态注册(非LocalBroadcastManager方式)
回调onReceive(context, intent)中的context返回值是:Activity Context;
网友评论