美文网首页Android精选Android
Broadcast 知识梳理(1) - BroadcastRec

Broadcast 知识梳理(1) - BroadcastRec

作者: 泽毛 | 来源:发表于2019-01-02 11:09 被阅读133次

    一、基本概念

    1.1 实现广播接收者

    首先,我们需要创建一个广播接收者,继承于BroadcastReceiver并重写它的onReceive方法。

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

    在创建完接收者之后,还需要进行注册,告诉系统有这个监听者。广播注册的方式分为:静态注册和动态注册。

    静态注册

    静态注册在AndroidManifest.xml中进行指定。

    <receiver android:enabled=["true" | "false"]
        android:exported=["true" | "false"]
        android:icon="drawable resource"
        android:label="string resource"
        android:name="string"
        android:permission="string"
        android:process="string" >
    . . .
    </receiver>
    
    • exportedexported决定了 广播接收者所能收到广播的范围,假如为false,那么只有同一个App,或者userId相同的App发出的广播它才能够收到,并不是指同一个进程。exported一般情况下默认为false,唯一例外的是假如设置了intent-filter,那么默认值为true。对于静态注册的广播,在Android 3.1之后,应用如果没有启动并且Intent中包含了FLAG_INCLUDE_STOPPED_PACKAGES属性,那么会先调起应用,否则在应用没有启动的情况下将无法收到广播。

    • permission:如果设置了permission,那么只有 具有相应权限的广播发送方 发送的广播才能被此BroadcastReceiver接收。Android广播的权限机制是双向的,即我们既可以 要求发送者具有权限,也可以 要求接收者具有权限,才能完成端到端的通信过程,这里就是 要求发送者具有权限

    • process:运行所处的进程,默认为App的进程。

    动态注册

    动态注册的广播无需在AndroidManifest.xml进行声明,在代码中进行注册和注销即可。

    //注册广播。
    registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
    //注销广播。
    unregisterReceiver(BroadcastReceiver receiver);
    

    1.2 发送广播

    广播的发送者通过Intent将其意图发送出去,系统找到匹配的接收者,发送广播的一般方式如下:

    Intent intent = new Intent();
    intent.setAction(INTENT_ACTION);
    sendBroadcast(intent);
    

    1.3 广播类型

    广播可以分为以下几类:无序广播、有序广播和粘性广播。

    1.3.1 无序广播

    无序广播指的是所有广播接收者收到广播的顺序是没有规律的。

    1.3.2 有序广播

    有序广播指的是发送出的广播被BroadcastReceiver按照priority从大到小的顺序接收,当priority相同时,动态广播优先静态广播,发送有序广播的方式为:

    sendOrderedBroadcast(intent, receiverPermission, ...)
    

    对于有序广播有一个特点,先接收的BroadcastReceiver具有拦截广播的权利,拦截的方法为onReceive方法中调用abortBroadcast()方法。

    1.3.3 粘性广播

    已经废弃,它是用来处理先收到广播然后才注册的情况。

    1.4 应用内广播

    假如exported属性为true,那么是允许两个不同应用通过广播进行通信的。就可能出现 安全隐患

    • 其他App可能会针对性地发出与当前Appintent-filter相匹配的广播,导致当前App不断接收到广播并处理。
    • 其他App可以注册与当前App相匹配的intent-filter,从而获取广播具体信息。

    为了避免出现以上的安全问题,有以下的解决方法:

    • 设置exported属性为false
    • 设置权限。
    • 发送广播时,指定具体的包名。

    假如我们的广播只需要在应用内部通信,那么可以采用封装好的LocalBroadcastManager类,用于解决安全问题。

    传统的广播是通过Binder来实现的,而LocalBroadcastManager则是采用Handler的方式。当注册广播的时候,其实将Receiver添加到单例对象LocalBroadcastManager维护的列表当中,发送消息的时候,通过Receiver所关联的action找到它,最后回调它的onReceive方法。

    因此,只有通过LocalBroadcastManager注册的BroadcastReceiver才能收到通过LocalBroadcastManager发出的广播。

    具体的代码实现可以参考这篇文章 LocalBroadcastManager 的实现原理,还是 Binder?

    二、一些需要注意的点

    2.1 权限问题

    通过权限可以也可以解决我们之前谈到的安全问题,Broadcast的权限是双向的。

    2.1.1 要求接收者具有权限

    这种方式 用于防止广播信息泄露

    发送者AndroidManifest.xml中定义权限。

    <permission android:name = "com.android.permission.RECV_XXX"/>
    

    发送者在发送广播的时候,采用带有权限的接口进行发送。

    sendBroadcast("com.android.XXX_ACTION", "com.android.permission.RECV_XXX");
    

    接收者 如果希望能收到广播,那么需要在它的AndroidManifest.xml进行声明使用该权限。

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

    2.1.2 要求发送者具有权限

    这种方式 用于防止外部应用恶意地发送广播,导致接收者一直在处理

    接收者AndroidManifest.xml中定义权限。

    <permission android:name="com.android.SEND_XXX"/>
    

    在接收者的AndroidManifest.xml声明BroadcastReceiver的时候,通过permission字段指定权限。

    <receiver android:name=".XXXReceiver" 
              android:permission="com.android.permission.SEND_XXX"> 
        <intent-filter>
             <action android:name="com.android.XXX_ACTION" /> 
        </intent-filter>
    </receiver>
    

    发送者 如果希望广播能被该接收者收到,那么需要在AndroidManifest.xml中声明使用该权限。

    <uses-permission android:name="com.android.permission.SEND_XXX“></users-permission>
    

    2.2 ANR

    BroadcastReceiver方法中,不要进行耗时的操作,超过10s会发生BroadcastQueue TimeoutANR异常。

    2.3 onReceive 传入的 Context

    • 静态注册的BroadcastReceiver,其Contextandroid.app.ReceiverRestrictedContext

    • 动态注册的普通BroadcastReceiver,与调用registerReceiver方法的Context有关,如果是通过Application Context注册的,那么ContextApplication Context,如果是Activity Context,那么其ContextActivity Context

    • LocalBroadcastManager动态注册的BroadcastReceiver,其ContextApplication Context

    三、参考文章

    Android Broadcast 和 BroadcastReceiver 的权限限制
    Android 总结篇系列:Android 广播机制
    LocalBroadcastManager 的实现原理,还是 Binder?

    相关文章

      网友评论

        本文标题:Broadcast 知识梳理(1) - BroadcastRec

        本文链接:https://www.haomeiwen.com/subject/khsblqtx.html