Android-BroadcastReceiver详解

来源:互联网 发布:heading标签优化 编辑:程序博客网 时间:2024/06/13 12:04

什么是Broadcast

Broadcast即广播,在Android广播是非常重要的功能。例如我们想在系统开机之后做某些事情、监控手机的电量、监控手机的网络状态等等,这些功能都需要用到广播。当然我们也可以自定义广播。

自定义广播

通常实现一个简单的自定义广播可以通过如下几个步骤:

  • 创建一个类继承android.content.BroadcastReceiver,并实现onReceive方法
  • 在AndroidManifest.xml中注册广播
  • 通过Context的registerReceiver等方法注册广播
  • 调用Context的sendBroadcast等方法发送广播,在onReceive方法中处理广播
  • 调用Context的unregisterReceiver等方法注销广播

我们通过代码来解释一下上面的步骤:

1.创建一个类继承android.content.BroadcastReceiver,并实现onReceive方法

package com.mark.broadcastreciver;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.util.Log;/** * 创建一个自定义广播接收者需要继承android.content.BroadcastReceiver, * 并实现onReceive方法即可。 */public class MyReceiver extends BroadcastReceiver {    private final static String TAG = MyReceiver.class.getSimpleName();    public MyReceiver() {    }    /**     * 当接收到广播之后会调用此方法     * @param context 上下文对象     * @param intent 调用sendBroadcast(intent)传入的Intent实例,其中包含了action、和其他附带信息     */    @Override    public void onReceive(Context context, Intent intent) {        // 获取msg对应的数据        String msg = intent.getStringExtra("msg");        // 打印msg数据        Log.i(TAG, "msg = " + msg);        // 打印action字符串        Log.i(TAG, "action = " + intent.getAction());    }}

2.在AndroidManifest.xml中注册广播

<application>    <receiver android:name=".MyReceiver">    </receiver></application>

3.通过Context的registerReceiver等方法注册广播
4.调用Context的sendBroadcast等方法发送广播,在onReceive方法中处理广播
5.调用Context的unregisterReceiver等方法注销广播

package com.mark.broadcastreciver;import android.content.BroadcastReceiver;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;public class MainActivity extends AppCompatActivity {    BroadcastReceiver registerReceiver;    IntentFilter intentFilter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // 创建BroadcastReceiver实例        registerReceiver = new MyReceiver();        // 创建IntentFilter,指定其action为com.mark.broadcast.receiver,这个可以自己定义        intentFilter = new IntentFilter("com.mark.broadcast.receiver");        // 注册广播将registerReceiver与intentFilter关联,        // registerReceiver可以接收到action为com.mark.broadcast.receiver的广播        registerReceiver(registerReceiver, intentFilter);        findViewById(R.id.btnRegister).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                // 发送广播                // 创建Intent,指定其action为com.mark.broadcast.receiver,与registerReceiver关联的action一致                Intent intent = new Intent("com.mark.broadcast.receiver");                // 指定要发送的信息                intent.putExtra("msg", "Hello, a new message.");                sendBroadcast(intent);            }        });    }    @Override    protected void onDestroy() {        super.onDestroy();        unregisterReceiver(registerReceiver);    }}

通过上述的步骤我们就实现了一个自定义广播,当我们点击Button在控制台中可以看到如下信息:

04-13 17:12:28.591 16882-16882/com.mark.broadcastreciver I/MyReceiver: msg = Hello, a new message.04-13 17:12:28.591 16882-16882/com.mark.broadcastreciver I/MyReceiver: action = com.mark.broadcast.receiver

注册广播

注册广播的方式有两种:静态注册和动态注册。

静态注册

这种方法是在配置AndroidManifest.xml配置文件中注册,通过这种方式注册的广播为常驻型广播,也就是说如果应用程序关闭了,有相应事件触发,程序还是会被系统自动调用运行。例如:

<!-- 在配置文件中注册BroadcastReceiver能够匹配的Intent --><receiver android:name=“.MyReceiver">    <intent-filter>        </action>        <action android:name=“com.mark.broadcast.reveiver”/>        <category android:name="android.intent.category.DEFAULT"></category>    </intent-filter></receiver>

动态注册

这种方法是通过代码在.Java文件中进行注册。通过这种方式注册的广播为非常驻型广播,即它会跟随Activity的生命周期,所以在Activity结束前我们需要调用unregisterReceiver(receiver)方法移除它。例如:

// 创建BroadcastReceiver实例registerReceiver = new MyReceiver(); // 创建IntentFilter,指定其action为com.mark.broadcast.receiver,这个可以自己定义 intentFilter = new IntentFilter("com.mark.broadcast.receiver"); // 注册广播将registerReceiver与intentFilter关联, // registerReceiver可以接收到action为com.mark.broadcast.receiver的广播registerReceiver(registerReceiver, intentFilter);

注意:如果我们在Activity中注册了BroadcastReceiver,当这个Activity销毁的时候要主动撤销注册否则会出现异常。方法如下:

@Override    protected void onDestroy() {        super.onDestroy();        unregisterReceiver(registerReceiver);    }

广播的类型

Broadcast的类型有两种:普通广播和有序广播。

Normal broadcasts (普通广播)

Normal broadcasts是完全异步的可以同一时间被所有的接收者接收到。消息的传递效率比较高。但缺点是接收者不能讲接收的消息的处理信息传递给下一个接收者也不能停止消息的传播。多个普通广播设置相同的IntentFilter,则先注册的先收到广播。

Ordered broadcasts (有序广播)

Ordered broadcasts的接收者按照一定的优先级进行消息的接收。如:A,B,C的优先级依次降低,那么消息先传递给A,在传递给B,最后传递给C。优先级别声明在中,取值为[-1000,1000]数值越大优先级别越高。优先级也可通过filter.setPriority(10)方式设置。

另外Ordered broadcasts的接收者可以通过abortBroadcast()的方式取消广播的传播,也可以通过setResultData和setResultExtras方法将处理的结果存入到Broadcast中,传递给下一个接收者。然后,下一个接收者通过getResultData()和getResultExtras(true)接收高优先级的接收者存入的数据。

例如:

<receiver    android:name=".FirstReceiver">    <intent-filter        android:priority="999">        <action android:name="com.mark.broadcast.receiver" />        <category android:name="android.intent.category.DEFAULT" />    </intent-filter></receiver><receiver android:name=".MyReceiver" >    <intent-filter        android:priority="1000">        <action android:name="com.mark.broadcast.receiver" />        <category android:name="android.intent.category.DEFAULT" />    </intent-filter></receiver>

如上两个receiver我们分别设置为priority为999,和1000,及时MyReceiver是后注册的,但是其优先级比FirstReceiver高,则MyReceiver会先处理广播。

sendOrderedBroadcast 发送有序广播

sendOrderedBroadcast(intent, receiverPermission)方法接收两个参数,比普通广播的发送方式多了一个receiverPermission参数,这是一个String类型的参数,代表具有这个权限的Receiver才能处理收到此广播。如果为null则表明不要求接受者声明指定权限。我们来看一下具体的操作。

首先我们要自定义一个权限,例如:

<permission    android:name="com.permissions.MY_BROADCAST_RECEIVER"    android:protectionLevel="normal" />

然后我们要是当前的程序具有此权限:例如:

<uses-permission android:name="com.permissions.MY_BROADCAST_RECEIVER" />

这样当前程序就拥有此权限了。

我们在发送有序广播是指定其权限为com.permissions.MY_BROADCAST_RECEIVER,注意拼写不要有错误,最好是复制过来。发送广播如下:

// 创建Intent,指定其action为com.mark.broadcast.receiver,与registerReceiver关联的action一致Intent intent = new Intent("com.mark.broadcast.receiver");// 指定要发送的信息intent.putExtra("msg", "Hello, a new message.");sendOrderedBroadcast(intent, "com.permissions.MY_BROADCAST_RECEIVER");

这样我们发送广播,并指定其权限为com.permissions.MY_BROADCAST_RECEIVER,因为当前的程序已经使用了此权限了,所以当前程序中的receiver是可以接收并处理此条广播的。否则不能接收此条广播。此处的权限体现了android对安全性的重视。

sendStickyBroadcast 粘性广播

粘性广播与其他的广播方式最大的不同在于“异步”,也就是说当一个粘性广播发出去后,可以没有Receiver进行处理,但是这个广播还会一直存在,假如过了一段时间之后有Receiver注册了此广播,则此Receiver还是可以处理这条广播的。但是细心的朋友们可以看到sendStickyBroadcast的一系列重载方法的参数中并没有上面提到的receiverPermission参数,这也将导致粘性广播在安全性上存在问题。所以在API Level 21 上sendStickyBroadcast方法被标记为deprecated,也就是不建议我们使用粘性广播了。因为在安全性和其他方面粘性广播存在很多缺陷。这里我们也就不在重点讨论了。

总结

这里我们对广播及广播接收者进行一个简单的总结以及在使用时的一些注意事项。

1.发送广播的方法都是ContextWrapper中的方法,而Activity、Service都是ContextWrapper的子类,所以在它们中都可以发送和注册广播
2.onReceive方法中不能做耗时操作,否则也会导致ANR
3.根据实际开发需要,尽可能为广播增加权限
4.尽可能避免使用粘性广播
5.有序广播的优先级为【-1000 ~ 1000】,数值越大,优先级越高

上述描述和某些观点可能不是正解,仅供参考,欢迎大家指正、批评。

0 0