天天看点

Android 组件BroadcastReceiver详解

1.什么是BroadcastReceiver?

是一个全局的监听器,属于Android四大组件之一,主要监听 或者 接收 应用 App 发出的广播消息,并 做出响应。

Android不同组件间的通信,多线程通信,与 Android 系统在特定情况下的通信等等都能用到广播。

Android中的广播采用了观察者模式的设计模式去实现:基于消息的发布 / 订阅事件模型。

2.广播不同角度各种分类

  • 按照注册方式划分
可分为静态广播注册和动态广播注册
  • 按照广播发送顺序
有序广播、普通广播
  • 按照广播范围
本地广播、系统广播

3.静态广播注册和静态广播注册

  • 静态广播注册

    1)创建class集成Broadcastreceiver并重写相关方法

public class BroardCastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e("TAG","============"+intent.getStringExtra("name"));
    }
}
           

2)AndroidManifest.xml清单文件中注册广播

<receiver android:name=".BroardCastReceiver">
            <intent-filter>
                <action android:name="com.org.mybroadcastreceiver"></action>
            </intent-filter>
        </receiver>
           

3)发送广播

Intent intent=new Intent();
        intent.setAction("com.org.mybroadcastreceiver");
        intent.putExtra("name","我是通过静态注册的普通广播");
        sendBroadcast(intent);
           
  • 动态广播注册

    1).定义自定义广播重写相应的方法

    2)代码动态注册代码

    3)解注册

    4)调用

public class MainActivity extends AppCompatActivity {
    MyDynamicBroadCastReceiver myDynamicBroadCastReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        registerBroadCastReceiver();

    }

    /**
     * 2)注册广播
     */
    private void registerBroadCastReceiver() {
         myDynamicBroadCastReceiver = new MyDynamicBroadCastReceiver();
        IntentFilter intent=new IntentFilter();
        intent.addAction("com.org.mydynamicbroadcastreceiver");
        registerReceiver(new MyDynamicBroadCastReceiver(),intent);
    }

    public void sendBroadCastReceiverStatic(View view){
        Intent intent=new Intent();
        intent.setAction("com.org.mybroadcastreceiver");
        intent.putExtra("name","我是通过静态注册的普通广播");
        sendBroadcast(intent);
    }

    /**
     * 4)发送广播
     * @param view
     */
    public void sendBroadCastReceiverDynamic(View view){
        Intent intent=new Intent();
        intent.setAction("com.org.mydynamicbroadcastreceiver");
        intent.putExtra("name","我是通过动态注册的普通广播");
        sendBroadcast(intent);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        //3)解注册广播释放资源
        unregisterReceiver(myDynamicBroadCastReceiver);
    }

    /**
     * 1)自定义广播类
     */
    class MyDynamicBroadCastReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e("TAG", "==============="+intent.getStringExtra("name"));
        }
    }


}
           

注意

动态注册的广播接收器可以自由地控制注册与注销,在灵活性方面有很大的优势,但是它也存在着一个缺点,即必须要在程序启动之后才能接收到广播,因为注册的逻辑是写在onCreate()方法中的。那么有没有什么办法可以让程序在未启动的情况下就能接收到广播呢?这就需要使用静态注册的方式了

不能静态注册的广播:

android.intent.action.SCREEN_ON  //屏幕被打开之后的广播

  android.intent.action.SCREEN_OFF  屏幕被关闭之后的广播

  android.intent.action.BATTERY_CHANGED   充电状态,或者电池的电量发生变化

  android.intent.action.CONFIGURATION_CHANGED  

  android.intent.action.TIME_TICK
           

3.有序广播

BroadcastReceiver可以使用setResult系列函数来结果传给下一个BroadcastReceiver,通过getResult系列函数来取得上个BroadcastReceiver返回的结果,并可以abortBroadcast()函数来让系统丢弃该广播,使用该广播不再传送到别的BroadcastReceiver。

可以通过在intent-filter中设置android:priority属性来设置receiver的优先级,优先级相同的receiver其执行顺序不确定。

如果BroadcastReceiver是代码中注册的话,且其intent-filter拥有相同android:priority属性的话,先注册的将先收到广播

有序广播,即从优先级别最高的广播接收器开始接收,接收完了如果没有丢弃,就下传给下一个次高优先级别的广播接收器进行处理。

1) 定义3个广播分别去接收同一发送者发送的广播。

public class PriorityBroadcastReceiver  {
    public static class HighPriority extends BroadcastReceiver {
        //高级广播接收者
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e("TAG", "优先级高的");
            //传递结果到下一个广播接收器
            int code = ;
            String data = "我是有序广播";
            Bundle bundle = null;
            setResult(code, data, bundle);

        }
    }

    public static class MidPriority extends BroadcastReceiver {
        //中级广播接收者
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e("TAG", "优先级中等");
            //获取上一个广播接收器结果s
            int code = getResultCode();
            String data = getResultData();
            Log.e("TAG", "获取到上一个广播接收器结果:" + "code=" + code + "data=" + data);
            //终止广播传递
            abortBroadcast();
        }
    }

    public static class LowPriority extends BroadcastReceiver {
        //低级广播接收者
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e("TAG", "优先级低的");
            int code = getResultCode();
            String data = getResultData();
            Log.e("TAG", "获取到上一个广播接收器结果:" + "code=" + code + "data=" + data);
        }
    }

}
           

2)广播清单文件中注册

里面的android:priority=”100”就是设定广播接收器的级别,这个值从1000~-1000,数值越大,优先级别就越高

<receiver android:name=".PriorityBroadcastReceiver$HighPriority">
            <intent-filter
                android:priority="999"
                >
                <action android:name="com.org.mysortbroadcastreceiver"></action>
            </intent-filter>
        </receiver>

        <receiver android:name=".PriorityBroadcastReceiver$MidPriority">
            <intent-filter
                android:priority="888"
                >
                <action android:name="com.org.mysortbroadcastreceiver"></action>
            </intent-filter>
        </receiver>

        <receiver android:name=".PriorityBroadcastReceiver$LowPriority">
            <intent-filter
                android:priority="777"
                >
                <action android:name="com.org.mysortbroadcastreceiver"></action>
            </intent-filter>
        </receiver>
           

3)发送有序广播

Intent intent=new Intent();
        intent.setAction("com.org.mysortbroadcastreceiver");
        intent.putExtra("name","我是有序广播");
        sendOrderedBroadcast(intent,null);
           

输出log

- :: -/com.phone.test_broadcastreceiver E/TAG: 优先级高的
- :: -/com.phone.test_broadcastreceiver E/TAG: 优先级中等
- :: -/com.phone.test_broadcastreceiver E/TAG: 获取到上一个广播接收器结果:code=data=我是有序广播
           

如果在MidPriority拦截的广播,但是还想在Low中接收到广播还可以这样做

Intent intent=new Intent();
        intent.setAction("com.org.mysortbroadcastreceiver");
        intent.putExtra("name","我是有序广播");
        sendOrderedBroadcast(intent,null,new PriorityBroadcastReceiver.LowPriority(),new Handler(),,null,null);
           

log如下:

- :: -/com.phone.test_broadcastreceiver E/TAG: 优先级高的
- :: -/com.phone.test_broadcastreceiver E/TAG: 优先级中等
- :: -/com.phone.test_broadcastreceiver E/TAG: 获取到上一个广播接收器结果:code=data=我是有序广播
- :: -/com.phone.test_broadcastreceiver E/TAG: 优先级低的
- :: -/com.phone.test_broadcastreceiver E/TAG: 获取到上一个广播接收器结果:code=data=我是有序广播
           

4.本地广播

发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播。

  • 可以明确地知道正在发送的广播不会离开本程序,因此不需要担心机密数据泄漏的问题。
  • 其他程序无法将广播发送到本程序的内部,因此不需要担心会有安全漏洞的隐患。
  • 发送本地广播比起发送系统全局广播将会更加高效

注册本地广播

/**
     * 注册广播
     */
    private void registerReceiverLocal() {
        localBroadcastManager = LocalBroadcastManager.getInstance(this);

        IntentFilter filter=new IntentFilter();
        filter.addAction("com.org.localreceiver");
        localBroadcastManager.registerReceiver(myDynamicBroadCastReceiver,filter);
    }
           

发送广播

/**
     * 发送本地广播
     */
    public void sendLocalReceiver(){

        Intent intent=new Intent();
        intent.setAction("com.org.localreceiver");
        localBroadcastManager.sendBroadcast(intent);
    }
           

解注册

//在生命周期最后释放资源
 localBroadcastManager.unregisterReceiver(myDynamicBroadCastReceiver);
           

**

注意本地广播不能是用静态注册的方式去注册

**

5.在使用广播的特殊注意

  • 广播中启动activity
//需要开启新的任务栈去存放要启动的activity,否则会报错
Intent intent1=newIntent(context,main.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
           
  • 广播中打开对话框

6.常见的系统广播

action 含义
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 插入耳机时
Intent.ACTION_MEDIA_BAD_REMOVAL 未正确移除SD卡但已取出来时(正确移除方法:设置–SD卡和设备内存–卸载SD卡)
Intent.ACTION_MEDIA_CHECKING 插入外部储存装置(如SD卡)
Intent.ACTION_HEADSET_PLUG 插入耳机时
Intent.ACTION_PACKAGE_ADDED 成功安装APK
Intent.ACTION_PACKAGE_REMOVED 成功删除APK
Intent.ACTION_REBOOT 重启设备
Intent.ACTION_SCREEN_OFF 屏幕被关闭
Intent.ACTION_SCREEN_ON 屏幕被打开
Intent.ACTION_SHUTDOWN 关闭系统时
Intent.ACTION_REBOOT 重启设备

参考文档

BroadcastReceiver1

BroadcastReceiver2

BroadcastReceiver3

BroadcastReceiver4

BroadcastReceiver5

BroadcastReceiver6

BroadcastReceiver7