BroadCast详解

一、什么是BroadcastReceiver?

       BroadcastReceiver(广播接收器)属于Android四大组件之一,是一个全局监听器,用于监听/接收App发出的广播消息,并作出响应,也用于不同组件之间的相互通信。

二、实现原理

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

       模型中有3个角色。

1、消息订阅者(广播接收者)

2、消息发布者(广播发送者)

3、消息中心(AMS,即 Activity Manager Service)

示意图如下:


三、使用流程

3.1、自定义广播接收者,继承自BroadcastReceiver基类,必须复写其中onReceive()方法。

广播接收器接收到广播之后,会调用onReceive()方法,一般情况下,onReceive()方法会涉及与其他组件的交互。

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        Toast.makeText(context,"......onReceive.........",Toast.LENGTH_LONG).show();
        Log.i("TAG","......FirstReceive.......");

    }
}

3.2、注册广播

1、静态注册(Android8.0后不推荐使用):

在manifest.xml中注册,示例代码:

<receiver android:name=".SecondReceiver">
    <intent-filter>
        <action android:name="com.example.pc.staticregisterbroadcastreceiver.SecondReceiver"/>

    </intent-filter>

注意:Android 8.0之后系统不提倡静态注册的广播,会发生广播接收不到的情况,所以最稳妥的方法还是用动态注册。但如果你无法修改代码,也可以通过添加一行代码,来继续使用静态注册。

 intent=new Intent();

intent.setComponent(new ComponentName("com.example.pc.staticregisterbroadcastreceiver","com.example.pc.staticregisterbroadcastreceiver.SecondReceiver"));

其中的ComponentName()的两个参数,第一个为广播接收者的包名,第二个为广播接收者的路径。

2、动态注册:

1)在Activity中创建一个自定义的BroadcastReceiver对象。

2)创建一个IntentFilter,并设置这个广播接收者的Action。

3)通过registerReceiver()方法注册广播,其中的两个参数,一个为新建的BroadcastReceiver对象,一个是IntentFilter。

receiver=new MyReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction("com.heep.cn");
registerReceiver(receiver,filter);

3、两种注册方法的区别:


3.3、发送广播:

调用Context的sendBroadcast()发送广播。如果是有序广播,则需要调用sendOrderedBroadcast();

特别注意:

动态广播,最好在Activity的onResume()中注册,在onPause()中注销,以防止内存泄漏。在onResume()注册、onPause()注销是因为onPause()在App死亡前一定会被执行,从而保证广播在App死亡前一定会被注销,从而防止内存泄露。

四、广播的类型:

一般分为5中广播类型:

普通广播(Nomal Broadcast)

系统广播(System Broadcast)

有序广播(Orderd Broadcast)

粘性广播(Sticky Broadcast)

App应用内广播(Local Broadcast)

1、普通广播

即开发者自定义Intent的广播。

intent=new Intent();
intent.putExtra("message","这是一条广播");
intent.setAction("com.example.pc.staticregisterbroadcastreceiver.SecondReceiver");
sendBroadcast(intent);

2、系统广播

Android中内置了多个系统广播:只要涉及到手机的基本操作(如开机、网络状态变化、拍照等等),都会发出相应的广播

每个广播都有特定的Intent - Filter(包括具体的action),Android系统广播action如下:

注:当使用系统广播时,只需要在注册广播接收者时定义相关的action即可,并不需要手动发送广播,当系统有相关操作时会自动进行系统广播

3、有序广播

发送出去的广播被广播接收者按照权限的大小顺序接收

1、按照Priority属性值从大-小排序;

2、Priority属性相同者,动态注册的广播优先;

3、接收广播按顺序接收

4、先接收的广播接收者可以对广播进行截断,即后接收的广播接收者不再接收到此广播;

5、先接收的广播接收者可以对广播进行修改,那么后接收的广播接收者将接收到被修改后的广播

receiver=new MyReceiver();
IntentFilter filter=new IntentFilter();
filter.setPriority(150);
filter.addAction("com.heep.cn");
registerReceiver(receiver,filter);
Intent intent=new Intent();
intent.setAction("com.heep.cn");
sendOrderedBroadcast(intent,null);

4、App应用内广播

Android中的广播可以跨App直接通信(exported对于有intent-filter情况下默认值为true)


可能出现的问题:

其他App针对性发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收广播并处理;

其他App注册与当前App一致的intent-filter用于接收广播,获取广播具体信息;

即会出现安全性 & 效率性的问题。

解决方法:

将全局广播设置成局部广播

  1. 注册广播时将exported属性设置为false,使得非本App内部发出的此广播不被接收;
  2. 在广播发送和接收时,增设相应权限permission,用于权限验证;
  3. 发送广播时指定该广播接收器所在的包名,此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。
通过 intent.setPackage(packageName) 指定报名

5. 粘性广播(Sticky Broadcast)
由于在Android5.0 & API 21中已经失效,所以不建议使用,在这里也不作过多的总结。


参考:https://www.jianshu.com/p/ca3d87a4cdf3



猜你喜欢

转载自blog.csdn.net/mahuicool/article/details/80313002
今日推荐