Broadcast广播机制

1、注册方式

1.1 静态注册

使用清单文件进行注册

在AndroidManifest.xml清单文件里直接声明的方式叫做静态注册。

<receiver 
    //此广播接收者类是mXRReceiver
    android:name=".mXRReceiver" >
    //用于系统启动完成时,接收系统发送的广播
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>
<receiver
  android:enabled=["true" | "false"]
  //此broadcastReceiver能否接收其他App的发出的广播
  //默认值是由receiver中有无intent-filter决定的:如果有intent-filter,默认值为true,否则为false
  android:exported=["true" | "false"]
  android:icon="drawable resource"
  android:label="string resource"
  //继承BroadcastReceiver子类的类名
  android:name=".mXRReceiver"
  //具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收;
  android:permission="string"
  //BroadcastReceiver运行所处的进程
  //默认为app的进程,可以指定独立的进程
  //注:Android四大基本组件都可以通过此属性指定自己的独立进程
  android:process="string" >

  //用于指定此广播接收器将接收的广播类型
  //本示例中给出的是用于系统启动完成时,接收系统发送的广播
  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
  </intent-filter>
</receiver>

1.2 动态注册

在代码中进行注册

private void initBroadcastReceiver() {
    if (mXRBroadcastReceiver == null) {
        mXRBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                ...
            }
        };

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.BOOT_COMPLETE);
        registerReceiver(mXRBroadcastReceiver, intentFilter);
    }
}

注意:动态广播最好在Activity的onResume()注册、onPause()注销。一旦忘记注销,那么就会造成内存泄露哦。

2 Broadcast的分类

1、普通广播

2、系统广播

3、有序广播

4、粘性广播

5、本地广播

2.1 普通广播

也就是标准广播,是一种完全异步执行的广播,和学校大喇叭完全一样,发出广播后,所有广播接收者都能收到广播,且没有优先之分,上面程序都是普通广播。

2.2 系统广播

监听网络变化 android.net.conn.CONNECTIVITY_CHANGE
关闭或打开飞行模式 Intent.ACTION_AIRPLANE_MODE_CHANGED
充电时或电量发生变化 Intent.ACTION_BATTERY_CHANGED
电池电量低 Intent.ACTION_BATTERY_LOW
电池电量充足(即从电量低变化到饱满时会发出广播 Intent.ACTION_BATTERY_OKAY
系统启动完成后(仅广播一次) Intent.ACTION_BOOT_COMPLETED
按下照相时的拍照按键(硬件按键)时 Intent.ACTION_CAMERA_BUTTON
屏幕锁屏 Intent.ACTION_CLOSE_SYSTEM_DIALOGS
设备当前设置被改变时(界面语言、设备方向等) Intent.ACTION_CONFIGURATION_CHANGED
插入耳机时 Intent.ACTION_HEADSET_PLUG
未正确移除SD卡但已取出来时(正确移除方法:
设置–SD卡和设备内存–卸载SD卡) Intent.ACTION_MEDIA_BAD_REMOVAL
插入外部储存装置(如SD卡) Intent.ACTION_MEDIA_CHECKING
成功安装APK Intent.ACTION_PACKAGE_ADDED
成功删除APK Intent.ACTION_PACKAGE_REMOVED
重启设备 Intent.ACTION_REBOOT
屏幕被关闭 Intent.ACTION_SCREEN_OFF
屏幕被打开 Intent.ACTION_SCREEN_ON
关闭系统时 Intent.ACTION_SHUTDOWN
重启设备 Intent.ACTION_REBOOT

2.3 有序广播

有序广播是一种同步执行的广播,按广播接收者的优先级由高到低排序,轮流接收到广播,且前面的广播接收者可以拦截该广播,这样后面的广播接收者就无法接收到该广播了。同时,前面的广播接受者也可以修改该广播并不做拦截,这样下一个接收到的广播就是被修改过的。 设置广播接收者的优先级可以用priority属性,数字越高代表优先级越高,最高是1000.
<receiver 
    //此广播接收者类是mXRReceiver
    android:name=".mXRReceiver" >
    //用于系统启动完成时,接收系统发送的广播
    <intent-filter android:priority="1000">
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

2.4 本地广播

BroadcastReceiver可用于不同应用之间传递消息,但难免会出现这两种情况:

  • 我们的App注册了广播接收者A,同时其他App可能要完成某个操作,碰巧发送了符合接收者A过滤条件的广播,导致我们的App就一直错误的接收到了这个广播;
  • 我们的App注册了广播接收者A,同时其他App也碰巧注册了和我们同样过滤条件的广播接收者,这样就导致本来是我们App接收的广播,其他App也接收到了;

基于这两大问题,LocalBroadcastManager就可以很好的解决该问题。LocalBroadcastManager用于应用内部传递消息,比broadcastReceiver更加高效和安全

2.4.1 为何更加安全

BroadcastReceiver是以 Binder 通讯方式为底层实现的机制不同,众所周知Binder是跨进程的。而LocalBroadcastManager 是利用应用内部的Handler来实现,只是利用到了 IntentFilter 的 match 功能,因为是 Handler 实现的应用内的通信,自然安全性更好,效率更高。

2.4.2 如何实现本地广播

方法一:把全局广播改为本地广播

  • 注册广播时将exported属性设置为false,表示该广播接收者不对外;
  • 在广播发送和接收时,增设相应权限permission,用于权限验证;
  • 发送广播时通过intent.setPackage(packageName)指定该广播接收器所在的包名,因此保证该发送出去的广播只会发送到指定包名的App内的广播接收者。

3、APP1 能否接收到APP2 的广播

当然能,只要使用全局的BroadCastRecevier能进行跨进程通信,不过只能被动接收广播。