分享一些 Broadcast 使用技巧

简介

Broadcast(广播) 是 Android 的四大组件之一,用于进程/线程间通讯。java

广播最大的特色就是发送方并不关心接收方是否接到数据,也不关心接收方是如何处理数据的,它只负责「说」而无论你「听不听」。android

广播能够来之系统,例如,Android 系统在发生各类系统事件时发送广播(系统启动或者设备开始充电时)。git

也能够来自于其余应用程序,例如,应用程序也能够发送自定义广播,来通知其余应用程序接受他们可能感兴趣的内容(更新数据)。github

广播的分类

按发送方式分类

  • 标准广播

是一种「彻底异步执行」的广播,没有任何前后顺序,全部的广播接收器几乎同一时刻接收到这条广播消息,效率高,没法被截断。安全

  • 有序广播

是一种「同步执行」的广播,有前后顺序,同一时刻只有一个接收器能够接收这个广播消息,优先级高的广播接收器能够先收到广播消息,而且前面的广播接收器还能够截断正在传递的广播,这样后面的广播接收器就没法接收广播消息了。网络

按注册方式分类

  • 静态广播

无论应用程序是否处于活动状态,都会进行监听。每次触发都会创建新的 Receiver 对象。app

  • 动态广播

在代码中进行注册,注意动态注册的广播必定要取消注册才行,一般是在 onDestroy() 方法中调用 unregisterReceiver() 方法来实现。异步

从开始建立直到其被解除注册会使用同一个 Receiver,不管这个广播被触发几回。ide

按定义方式分类

  • 系统广播

Android 系统中内置了多个系统广播,每一个系统广播都具备特定的 IntentFilter,其中主要包括具体的 Action,系统广播发出后,将被相应的 BroadcastReceiver 接收。系统广播在系统内部当特定事件发生时,由系统自动发出。学习

  • 自定义广播

由应用程序开发者本身定义的广播。

按范围方式分类

  • 全局广播

发出的广播能够被其余任意的应用程序接收,或者能够接收来自其余任意应用程序的广播。

  • 本地广播

只能在应用程序的内部进行传递的广播,广播接收器也只能接收内部的广播,不能接受其余应用程序的广播。

广播的使用

建立广播接收器

使用广播咱们须要先建立 BroadcastReceiver(广播接收器) ,直接继承 BroadcastReceiver 建立子类并实现父类的 onReceive() 方法便可,以下示例代码。

public class MyReceiver extends BroadcastReceiver {
  // 自定义 action
  private static final String ACTION = "com.jeanboy.broadcast.MyReceiverFilter";
  
  @Override
  public void onReceive(Context context, Intent intent) {
    //TODO: 接收到广播进行处理
  }
}
复制代码

静态广播

在使用广播时还须要在 AndroidMainfest 文件中定义,也就是注册静态广播。

<receiver android:name=".ui.broadcast.MyReceiver" android:enabled="true" android:exported="true">
    <intent-filter>
        <!-- 例如:接收系统开机广播 -->
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <!-- 例如:接收自定义的广播 -->
        <action android:name="com.jeanboy.broadcast.MyReceiverFilter" />
    </intent-filter>
</receiver>
复制代码

上面的 enabled 设置为 true 意味着可以接受到广播信息。exported 为 true 意味着可以接收到外部 APK 发送的广播信息。

动态广播

使用动态广播不须要在 AndroidMainfest 文件中定义,只需在代码中注册便可。

// 建立广播
MyReceiver myReceiver = new MyReceiver();
// 建立 IntentFilter
IntentFilter intentFilter = new IntentFilter();
// 例如:添加系统广播 action 接受网络变化
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
// 例如:添加自定义的 action
intentFilter.addAction(MyReceiver.ACTION);
// 注册广播
registerReceiver(myReceiver, intentFilter);
// 注销广播
unregisterReceiver(myReceiver);
复制代码

发送广播

发送广播比较简单,不管静态广播仍是动态广播,都是以下方式(系统广播 Android 系统会自动发送,不在本文讨论范围)。

// 建立 Intent
Intent intent = new Intent();
// 例如:添加自定义的 action
intent.setAction(MyReceiver.ACTION);
// 发送广播
sendBroadcast(intent);
复制代码

Android 8.0 中的静态广播

因为 Android 8.0 废除大部分静态广播,对于代码须要修改某些部分。

发送广播部分须要设置 ComponetName

Intent intent = new Intent(MyReceiver.ACTION);
// ComponetName("自定义广播的包名", "自定义广播的路径")
ComponentName component = new ComponentName("com.jeanboy.app.broadcast", "com.jeanboy.app.broadcast.MyReceiver");
intent.setComponent(component);
sendBroadcast(intent);
复制代码

带权限的广播

使用广播可能引起的安全问题:

  • 若是别的应用程序监听咱们的广播,那么会形成咱们应用程序的数据泄露;
  • 若是别的应用程序冒充咱们的应用发送广播,那么就会频繁的启动咱们的广播接收程序,形成咱们应用的混乱,甚至崩溃。

为了不以上安全问题,Android 为咱们提供了权限机制。

首先在注册静态广播时能够在 AndroidMainfest 文件中添加权限。

<manifest ...>
  <!-- 自定义一个本身的权限 -->
  <permission android:name="com.jeanboy.permissions.MY_BROADCAST"/>
  <!-- 使用自定义的权限 -->
  <uses-permission android:name="com.jeanboy.permissions.MY_BROADCAST"/>

  <application ...>
    <!-- 添加权限 -->
    <receiver android:name=".ui.broadcast.MyReceiver" android:permission="com.jeanboy.broadcast.MY_BROADCAST" android:enabled="true" android:exported="true">
      <intent-filter>
        <!-- 例如:接收自定义的广播 -->
        <action android:name="com.jeanboy.broadcast.MyReceiverFilter" />
      </intent-filter>
    </receiver>
  </application>
</manifest>
复制代码

而后在咱们发送广播时,能够为它指定一个权限,只有具备该权限的应用才能接收到广播,以下所示:

// 建立 Intent
Intent intent = new Intent();
// 例如:添加自定义的 action
intent.setAction(MyReceiver.ACTION);
// 发送广播,添加权限
sendBroadcast(intent, "com.jeanboy.permissions.MY_BROADCAST");
复制代码

本地广播

上面介绍的 BroadcastReceiver 用于应用之间的传递消息,本质上它是跨进程的,还有可能被其余应用拦截。

而 LocalBroadcast(本地广播)用于应用内部传递消息,比 BroadcastReceiver 更加高效,它只在应用内部有效,不须要考虑安全问题。

本地广播的建立仍然是继承 BroadcastReceiver 建立子类,并实现父类的 onReceive() 方法。在注册、发送、注销广播时使用 LocalBroadcastManager 来进行相关操做。

// 建立广播
MyReceiver myReceiver = new MyReceiver();
// 建立 IntentFilter
IntentFilter intentFilter = new IntentFilter();
// 例如:添加自定义的 action
intentFilter.addAction(MyReceiver.ACTION);
// 注册本地广播
LocalBroadcastManager.getInstance(this)
                .registerReceiver(myReceiver, intentFilter);

// 发送广播
Intent intent = new Intent(MyReceiver.ACTION));
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

// 注销本地广播
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
复制代码

参考资料

个人 Github

github.com/jeanboydev/…

个人公众号

欢迎关注个人公众号,分享各类技术干货,各类学习资料,职业发展和行业动态。

Android 波斯湾

技术交流群

欢迎加入技术交流群,来一块儿交流学习。

QQ 技术交流群

QQ 技术交流群
相关文章
相关标签/搜索