Android BroadcastReceiver 的静态动态注册及区别

前言

为了方便Android系统各个应用程序及程序内部进行通信,Android系统引入了一套广播机制。各个应用程序可以对感兴趣的广播进行注册,当系统或者其他程序发出这条广播的时候,对发出的广播进行注册的程序便能够收到这条广播。为此,Android系统中有一套完整的API,允许程序只有的发送和接受广播。
本文会分别介绍静态注册广播和动态注册广播的方法并比较这两种的区别。

在此会先说明发送广播的两种方法

广播两种基本类型

在一个程序中,可以发送广播供当前程序的广播接收器收到。首先我们来看下两种方式的发送广播。
在Android系统中,主要有两种基本的广播类型:

  • 标准广播(Normal Broadcasts)
  • 有序广播(Ordered Broadcasts)

    标准广播

是一种完全异步执行的广播,在广播发出之后,所有的广播接收器会在同一时间接收到这条广播,广播无法被截断。

发送广播的方式十分简单,只需要实例化一个Intent对象,然后调用context sendBroadcast() 方法。

1
2
3
//intent中的参数为action
Intent intent=new Intent("com.example.dimple.BROADCAST_TEST");
sendBroadcast(intent);

这样就完成了广播的发送,至于接收呢,需要用到广播接收器,这个下面会写到。

有序广播

是一种同步执行的广播,在广播发出之后,优先级高的广播接收器可以优先接收到这条广播,并可以在优先级较低的广播接收器之前截断停止发送这条广播。

至于有序广播:

1
2
3
//intent中的参数为action
Intent intent=new Intent("com.example.dimple.BROADCAST_TEST");
sendOrderBroadcast(intent,null);//第二个参数是与权限相关的字符串。

到此时,如果你的程序中只有一个广播接收器的话,是体现不出有序广播的特点的,
右击包名——New——Other——BroadcastReceiver多创建几个广播接收器。

此时你还是会发现,所有的广播接收器是同时接收到广播消息的。注意上面介绍的时候说到优先级,这个时候我们需要设置优先级,在AndroidManifest文件中的Receiver标签中设置广播接收器的优先级。

1
2
3
4
5
6
7
8
9
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<!--注意此时有一个Priority属性-->
<intent-filter android:priority="100">
<action android:name="android.intent.action.BROADCAST_TEST"></action>
</intent-filter>
</receiver>

优先级越高的广播接收器可以先收到广播,也可以在收到广播的时候调用abortBroadcast()方法截断广播。优先级低的广播接收器就无法接收到广播了。

注册广播

自定义BroadcastReceiver

在Android的广播接收机制中,如果需要接收广播,就需要创建广播接收器。而创建广播接收器的方法就是新建一个类(可以是单独新建类,也可以是内部类(public)) 继承自BroadcastReceiver

1
2
3
4
5
6
7
8
class myBroadcastReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
//接收到广播的处理,注意不能有耗时操作,当此方法长时间未结束,会报错。
//同时,广播接收器中不能开线程。
}
}

两种注册方法

动态注册

所谓动态注册是指在代码中注册。步骤如下 :

  • 实例化自定义的广播接收器。
  • 创建IntentFilter实例。
  • 调用IntentFilter实例的addAction()方法添加监听的广播类型。
  • 最后调用ContextregisterReceiver(BroadcastReceiver,IntentFilter)动态的注册广播。

此时,已经为我们自定义的广播接收器绑定了广播,当收到和绑定的广播一直的广播的时候,就会调用广播接收器中的onReceiver方法。

1
2
3
4
MyBroadcastReceiver myBroadcastReceiver=new MyBroadcastReceiver();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("com.example.dimple.MY_BROADCAST");
registerReceiver(myBroadcastReceiver,intentFilter);

PS:这里提醒一点,如果需要接收系统的广播(比如电量变化,网络变化等等),别忘记在AndroidManifest配置文件中加上权限。

另外,动态注册的广播在活动结束的时候需要取消注册:

1
2
3
4
5
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myBroadcastReceiver);
}

静态注册

这里我们使用静态注册来接收开机广播。
使用Android Studio 中的快捷方法来创建广播接收器。

右击包名——New——Other——BroadcastReceiver。

{mdFileName}-20183414490

PS:静态注册的广播接收器需要在AndroidManifest文件中注册,由于使用的AS的快捷方式,所以已经创建好了。
如图所示:

{mdFileName}-201834145034

在创建好的广播接收器中添加一个Toast提示。代码如下:

class MyReceiver extends BroadcastReceiver {
1
2
3
4
5
    @Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"开机启动!",Toast.LENGTH_LONG).show();
}
}

然后在AndroidManifest文件中添加:

  • 权限
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>

  • Intent-filter

1
2
3
4
5
6
7
8
9
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<!--添加以下3行-->
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>

此时重启Android系统就可以收到开机提示了。

总结

动态注册和静态注册的区别:

  • 动态注册的广播接收器可以自由的控制注册和取消,有很大的灵活性。但是只能在程序启动之后才能收到广播,此外,不知道你注意到了没,广播接收器的注销是在onDestroy()方法中的。所以广播接收器的生命周期是和当前活动的生命周期一样。

  • 静态注册的广播不受程序是否启动的约束,当应用程序关闭之后,还是可以接收到广播。

标准广播和有序广播的接收和发送都是全局性的,这样会使得其他程序有可能接收到广播,会造成一定的安全隐患。为了解决这个问题,Android系统中有一套本地广播的机制。这个机制是让所有的广播事件(接收与发送)都在程序内部完成。主要是采用的一个localBroadcastReceiver对广播进行管理。

-------------本文结束感谢您的阅读-------------
na,给我一个棒棒糖!