我爱编程

安卓四大组件之—BroadcastReceiver详解

2018-07-26  本文已影响0人  menteelin

一 概述

BroadcastReceiver是安卓四大组件之一,它是一个全局的监听器,它能够接收安卓系统、App内以及其它App发出的广播。安卓的广播采用观察者模式,基于消息的 订阅 / 发布 事件模型,因此广播的发送者和接收者完全解耦,易于使用和扩展。

二 BroadcastReceiver使用流程

  1. 自定义BroadcastReceiver
    我们要想使用BroadcastReceiver需要先定义个类继承BroadcastReceiver然后实现其public void onReceive(Context context, Intent intent)方法。

广播接收器接收到相应的广播后会自动回调onReceive方法,该方法运行在主线程中,因此不宜做耗时操作。
一般情况下在onReceive方法中会涉及到与其它组件的交互,比如打开Service、启动Activity等。

代码示例

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //获得意图(intent)中传递过来的action
        String action = intent.getAction();
        Log.e(getClass().getSimpleName(),"action:"+action);
        //可以在意图(intent)中使用bundle传递参数
        Bundle extras = intent.getExtras();
        String id = extras.getString("id");
        String name = extras.getString("name");
        Log.e(getClass().getSimpleName(),"id:"+id+",name:"+name);
    }
}
  1. BroadcastReceiver注册
    我们自定义了BroadcastReceiver之后,还需要注册一下才能收到对应的广播消息。广播的注册有两种方式分别为:静态注册和动态注册。
<receiver
    //广播接收者的类名路径
    android:name=".MyReceiver"
    //发送广播的app应该具有的权限
    android:permission="String"
    //广播是否可用,为true时系统才会初始化该广播
    android:enabled="true"
    //是否能接受其他app发出的广播,当有intent-filter时默认为true
    android:exported="true">
    <intent-filter>
        //接受到的广播类型,可以使用系统已有的广播类型也可以自定义
        <action android:name="com.jrmf360.sendrp"/>
    </intent-filter>
</receiver>

当app启动时系统会自动实例化该广播类,并注册到系统中

@Override
protected void onResume() {
    super.onResume();
    broadcastReceiver = new MyBroadcastReceiver();
    //创建意图过滤器并添加Action
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.jrmf360.sendrp");
    //注册BroadcastReceiver
    registerReceiver(broadcastReceiver,intentFilter);
}


@Override
protected void onPause() {
    super.onPause();
    unregisterReceiver(broadcastReceiver);
}


class MyBroadcastReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.e(getClass().getSimpleName(),"action:"+action);
        Bundle extras = intent.getExtras();
        String id = extras.getString("id");
        String name = extras.getString("name");
        Log.e(getClass().getSimpleName(),"id:"+id+",name:"+name);
    }
}

在onResume方法中注册BroadcastReceiver在onPause方法中取消注册BroadcastReceiver。注册和反注册必须成对出现以免造成内存泄漏。

  1. 广播种类
    广播分为普通广播、有序广播、系统广播和App内广播,具体说明如下:
//创建意图并设置Action
Intent intent = new Intent();
//只有当广播的接收Action于此匹配才能接收到该广播
intent.setAction("com.jrmf360.sendrp");
//使用bundle传递参数
Bundle bundle = new Bundle();
bundle.putString("id","123456");
bundle.putString("name","zhangsan");
intent.putExtras(bundle);
//发送广播
sendBroadcast(intent);
系统操作 action
网络变化 android.net.conn.CONNECTIVITY_CHANGE
充电时或电量发生变化 Intent.ACTION_BATTERY_CHANGED
屏幕被关闭 Intent.ACTION_SCREEN_OFF
屏幕被打开 Intent.ACTION_SCREEN_ON
系统启动完成后(仅广播一次) Intent.ACTION_BOOT_COMPLETED
<receiver
    //广播接收者的类名路径
    android:name=".MyReceiver"
    //发送广播的app应该具有的权限
    android:permission="com.jrmf360.permission.send"
    //广播是否可用,为true时系统才会初始化该广播
    android:enabled="true"
    //是否能接受其他app发出的广播,当有intent-filter时默认为true
    android:exported="false">
    <intent-filter>
        //接受到的广播类型,可以使用系统已有的广播类型也可以自定义
        <action android:name="com.jrmf360.sendrp"/>
    </intent-filter>
</receiver>

单单接收不到其它App发出的广播还不能满足我们的要求,还需要我们自己发出的广播其它App接收不到,这就需要在发送广播的时候设置包名:

Intent intent = new Intent();
intent.setAction("com.jrmf360.sendrp");
Bundle bundle = new Bundle();
bundle.putString("id","123456");
bundle.putString("name","zhangsan");
intent.putExtras(bundle);
//设置包名
intent.setPackage("应用包名");
sendBroadcast(intent);

方式二:
使用LocalBroadcastManager也可以实现应用内广播,需要注意的是只有动态注册的广播才能使用LocalBroadcastManager并且广播的注册,发送和反注册都要使用LocalBroadcastManager.getInstance(this)的单例对象去完成。示例如下:

@Override
protected void onResume() {
    super.onResume();
    broadcastReceiver = new MyBroadcastReceiver();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.jrmf360.sendrp");
    LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver,intentFilter);
}


@Override
protected void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
}


@Override
public void onClick(View v) {
    int id = v.getId();
    if (id == R.id.btn_sendBroadcast){
        Intent intent = new Intent();
        intent.setAction("com.jrmf360.sendrp");
        Bundle bundle = new Bundle();
        bundle.putString("id","123456");
        bundle.putString("name","zhangsan");
        intent.putExtras(bundle);
        sendBroadcast(intent);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }
}
  1. 广播的权限
    广播的权限分为广播发送者要求广播接收者具有的权限和广播接收者要求广播发送者具有的权限。
<receiver
    android:name=".MyReceiver2"
    //添加自定义权限
    android:permission="com.jrmf360.permission.send2"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="com.jrmf360.sendrp"/>
    </intent-filter>
</receiver>

然后我们需要在xml文件中声明该权限

<!--权限声明-->
<permission android:name="com.jrmf360.permission.send2"/>

最后广播发送者所在的App需要在xml中注册该权限

<uses-permission android:name="com.jrmf360.permission.send2"/>
sendBroadcast(intent,"com.jrmf360.rp");

接着在xml文件中声明该权限

<permission android:name="com.jrmf360.rp"/>

最后广播接收者所在的App需要在xml中注册该权限

<!--权限注册-->
<uses-permission android:name="com.jrmf360.rp"/>

广播的权限是对广播接收者随意接收广播的限制和保护。

总结:广播可以跨线程、进程和App通信,我们在开发过程中可以很方便的利用它来传递消息。但我们也不能滥用广播可能会导致接收消息的地方过多不好维护而且广播接收者相对是个比较重的组件,比如线程间通信我们可以通过Handler解决,没有必要使用广播。

上一篇下一篇

猜你喜欢

热点阅读