四大组件Android开发经验谈Android技术知识

17 个必须掌握的 BroadcastReceiver 知识点「

2019-11-08  本文已影响0人  圆号本昊
Android

文章目录


文章目录

方便大家学习,我在 GitHub 上建立个 仓库


一、BroadcastReceiver

1.1 什么是 BroadcastReceiver

什么是 BroadcastReceiver

1.2 广播分为两种

广播分为两种

1.2.1 无序广播

无序广播

1.2.2 有序广播

有序广播 总结
  1. 按被接收者的优先级循序传播 A > B > C ,
  2. 每个都有权终止广播, 下一个就得不到
  3. 每一个都可进行修改操作, 下一个就得到上一个修改后的结果.

1.2.3 最终广播者

最终广播者

1.2.4 常见的广播接收者运用场景

广播接收者运用场景

1.3 BroadcastReceiver 的种类

1.3.1 广播作为 Android 组件间的通信方式,如下使用场景:

对前一部分 “ 请描述一下 BroadcastReceiver ” 进行展开补充

BroadcastReceiver 使用场景

1.3.2 系统广播

系统广播 常见系统广播 Intent 中的 Action 值
  1. 短信提醒:android.provider.Telephony.SMS_RECEIVED
  2. 电量过低:ACTION_BATIERY_LOW
  3. 电量发生改变:ACTION_BATTERY_CHANGED
  4. 连接电源:ACTION_POWER_CO

1.3.3 局部广播

局部广播
  1. 其他的 APP 不会受到局部广播,不用担心数据泄露的问题。
  2. 其他 APP 不可能向当前的 APP 发送局部广播,不用担心有安全漏洞被其他 APP 利用。
  3. 局部广播比通过系统传递的全局广播的传递效率更高。

1.4 BroadcastReceiver 注册方式

BroadcastReceiver 注册方式

1.4.1 静态注册

AndroidManifest.xml 文件中配置。

<receiver android:name=".MyReceiver" android:exported="true">
    <intent-filter>
        <!-- 指定该 BroadcastReceiver 所响应的 Intent 的 Action -->
        <action android:name="android.intent.action.INPUT_METHOD_CHANGED"
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>
两个重要属性
  1. android: exported
    其作用是设置此 BroadcastReceiver 能否接受其他 APP 发出的广播 ,当设为 false 时,只能接受同一应用的的组件或具有相同 user ID 的应用发送的消息。这个属性的默认值是由 BroadcastReceiver 中有无 Intent-filter 决定的,如果有 Intent-filter ,默认值为 true ,否则为 false
  2. android: permission
    如果设置此属性,具有相应权限的广播发送方发送的广播才能被此 BroadcastReceiver 所接受;如果没有设置,这个值赋予整个应用所申请的权限。

1.4.2 动态注册

1.5 在 Mainfest 和代码如何注册和使用 BroadcastReceiver ? ( 一个 action 是重点 )

Mainfest 和代码如何注册和使用 BroadcastReceiver

1.5.1 使用文件注册 ( 静态广播 )

使用文件注册 ( 静态广播 )
  1. 一个 app 里: 自定义一个类继承 BroadcastReceiver 然后要求重写 onReveiver 方法
public class MyBroadCastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("MyBroadCastReceiver", "收到信息,内容是 : " + intent.getStringExtra("info") + "");
    }
}
  1. 清单文件注册,并设置 Action , 就那么简单完成接收准备工作
<receiver android:name=".MyBroadCastReceiver">
    <intent-filter>
        <action android:name="myBroadcast.action.call"/>
    </intent-filter>
</receiver>

1.5.2 代码注册 ( 动态广播 )

代码注册 ( 动态广播 )
  1. 在和广播接受者相同的 app 里的 MainActivity 添加一个注册按钮 , 用来注册广播接收者
  2. 设置意图过滤,添加 Action
//onCreate创建广播接收者对象
mReceiver = new MyBroadCastReceiver();              

//注册按钮
public void click(View view) {
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("myBroadcast.action.call");
    registerReceiver(mReceiver, intentFilter);
}
  1. 销毁的时候取消注册
@Override
protected void onDestroy() {
    unregisterReceiver(mReceiver);
    super.onDestroy();
}

1.5.3 在另一个 app , 定义一个按钮, 设置意图, 意图添加消息内容, 意图设置 action( ... ) 要匹配 , 然后发送广播即可.

代码注册 ( 动态广播 )
public void click(View view) {
    Intent intent = new Intent();
    intent.putExtra("info", "消息内容");
    intent.setAction("myBroadcast.action.call");
    sendBroadcast(intent);
}
  1. 静态注册的方法: 另一 app 直接发广播就收到了
  2. 动态注册的方法: 自己的 app 先代码注册,然后另一个 app 直接发广播即可.-

1.6 BroadcastReceiver 的实现原理是什么?

BroadcastReceiver 的实现原理
  1. 消息订阅者( 广播接收者 )
  2. 消息发布者( 广播发布者 )
  3. 消息中心( AMS,即 Activity Manager Service

1.6.1 原理:

原理

1.7 本地广播

在这里插入图片描述
  1. 调用 LocalBroadcastManager.getInstance() 获得实例
  2. 调用 registerReceiver() 方法注册广播
  3. 调用 sendBroadcast() 方法发送广播
  4. 调用 unregisterReceiver() 方法取消注册

1.7.1 注意事项:

注意事项
  1. 本地广播无法通过静态注册方式来接受,相比起系统全局广播更加高效。
  2. 在广播中启动 Activity 时,需要为 Intent 加入 FLAG_ACTIVITY_NEW_TASK 标记,否则会报错,因为需要一个栈来存放新打开的 Activity
  3. 广播中弹出 Alertdialog 时,需要设置对话框的类型为 TYPE_SYSTEM_ALERT ,否则无法弹出。
  4. 不要在 onReceiver() 方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的,当 onReceiver() 方法运行了较长时间而没有结束时,程序就会报错。

1.8 Sticky Broadcast 粘性广播

Sticky Broadcast 粘性广播
  1. 粘性广播通过 ContextsendStickyBroadcast ( Intent ) 接口发送,需要添加权限
  2. uses-permission android:name=”android.permission.BROADCAST_STICKY”
  3. 也可以通过 ContextremoveStickyBroadcast ( Intent intent ) 接口移除缓存的粘性广播

1.9 LocalBroadcastManager 详解

1.9.1 特点:

LocalBroadcastManager 特点
  1. 使用它发送的广播将只在自身APP内传播,因此你不必担心泄漏隐私数据;

  2. 其他 APP 无法对你的 APP 发送该广播,因为你的APP根本就不可能接收到非自身应用发送的该广播,因此你不必担心有安全漏洞可以利用;

  3. 比系统的全局广播更加高效。

1.9.2 源码分析 :

LocalBroadcastManager 源码分析
  1. LocalBroadcastManager 内部协作主要是靠这两个 Map 集合:MReceiversMActions ,当然还有一个 List 集合 MPendingBroadcasts ,这个主要就是存储待接收的广播对象。

  2. LocalBroadcastManager 高效的原因主要是因为它内部是通过 Handler 实现的,它的 sendBroadcast() 方法含义并非和我们平时所用的一样,它的 sendBroadcast() 方法其实是通过 handler 发送一个 Message 实现的;

  3. 既然它内部是通过 Handler 来实现广播的发送的,那么相比于系统广播通过 Binder 实现那肯定是更高效了,同时使用 Handler 来实现,别的应用无法向我们的应用发送该广播,而我们应用内发送的广播也不会离开我们的应用;

1.9.3 BroadcastReceiver 安全问题

BroadcastReceiver 安全问题

1.9.4 广播的安全性

  1. 其他 APP 可以接收到当前 APP 发送的广播,导致数据外泄。
  2. 其他 APP 可以向当前 APP 放广播消息,导致 APP 被非法控制。
广播的安全性
  1. 发送广播时,增加相应的 permission ,用于权限验证。
  2. Android 4.0 及以上系统中发送广播时,可以使用 setPackage() 方法设置接受广播的包名。
  3. 使用局部广播。
  1. 注册广播接收器时,增加相应的 permission ,用于权限验证。
  2. 注册广播接收器时,设置 android:exported 的值为false。
  1. 发送广播时,如果增加了 permission
  2. 那接受广播的 APP 必须申请相应权限,这样才能收到对应的广播,反之亦然。

1.9.5 使用 BroadcastReceiver 的好处

使用 BroadcastReceiver 的好处
  1. 因广播数据在本应用范围内传播,你不用担心隐私数据泄露的问题。

  2. 不用担心别的应用伪造广播,造成安全隐患。

  3. 相比在系统内发送全局广播,它更高效。

1.10 如何让自己的广播只让指定的 app 接收?

让自己的广播只让指定的 app 接收
  1. 权限, 保护层级是普通正常.
  2. 用户权限
<permission android:name="broad.ok.receiver" android:protectionLevel="normal"/>
<uses-permission android:name="broad.ok.receiver" />
  1. 发送广播的时候加上权限字符串
public void click(View view) {
    Intent intent = new Intent();
    intent.putExtra("info", "消息内容");
    intent.setAction("myBroadcast.action.call");
    sendBroadcast(intent, "broad.ok.receiver");
    //sendOrderedBroadcast(intent,"broad.ok.receiver");
}
  1. 其他app接收者想好获取广播,必须声明在清单文件权限
<uses-permission android:name="broad.ok.receiver"/>

1.11 广播的优先级对无序广播生效吗?

广播的优先级对无序广播生效

1.12 动态注册的广播优先级谁高?

动态注册的广播优先级谁高

1.13 如何判断当前的 BrodcastReceiver 接收到的是有序还是无序的广播?

判断当前的 BrodcastReceiver 接收到的是有序还是无序
public void onReceive(Context context, Intent intent) {
    Log.d("MyBroadCastReceiver", "收到信息,内容是 : " + intent.getStringExtra("info") + "");
    boolean isOrderBroadcast = isOrderedBroadcast();
}

1.14 BroadcastReceiver 不能执行耗时操作

BroadcastReceiver 不能执行耗时操作
  1. BroadcastReceiver 一般处于主线程。
  2. 耗时操作会导致 ANR
  1. BroadcastReceiver 启动时间较短。
  2. 如果一个进程里面只存在一个 BroadcastReceiver 组件。并且在其中开启子线程执行耗时任务。
  3. 系统会认为该进程是优先级最低的空进程。很容易将其杀死。

总结


  1. 本文应该是全网最全面的 BroadcastReceiver 知识总结了,如果有什么遗漏的地方,欢迎大家在评论区指出。
  2. 前前后后投入了大量时间来完成。希望大家通过本次阅读都能有所收获。
  3. 重点:关于 Android 的四大组件,到现在为止我才总结完 ActivityServiceBroadcastRecevier 等,有关事件分发、滑动冲突、新能优化等重要模块,后续我将进行全面总结,欢迎大家关注 _yuanhao 的简书 ,方便及时接收更新

码字不易,你的点赞是我总结的最大动力!


Android
上一篇下一篇

猜你喜欢

热点阅读