为什么应该使用本地广播(LocalBroadcastManager)

Posted on 2017-09-10 by Shawn Wang

Posted in android

从 Android 诞生已来,就一直有所谓的四大组件,BroadcastReceiver 是其中之一。 几乎在各种样的应用中都有 BroadcastReceiver 的使用,它被应用于接收系统发送的消息以及与其他应用之间的交互,但也被大量的误用于应用内部通信。 然而在同应用中使用则违背 BroadcastReceiver 的设计用途及理念。

全局 Broadcast 在应用内使用的缺陷

在 Google 的开发指南中清楚的描述了 Broadcast 用于接受来自系统的消息,例如:系统启动、开始充电、应用安装等,那么,它的本质就是一个类似于发布定阅模式用于跨进程的通信机制。这代表了,在进程内部去使用这样一种全局的通信机制,是不合适的,以下选取了几个侧面来进行说明。

  • 全局的 Broadcast 是不隐私的,其他应用可能获取到应用内部通过 Broadcast 发送的隐私信息,无论我的 Intent Filters 是在 Manifest 文件里声明还是动态的注册,作为字符串常量,他们都不会被混淆。 通过逆向工程,能够非常容易的找到他们,创建可以收到你的应用广播的 BroadcastReceiver,这非常容易导致敏感信息的泄漏。其他应用的这种缺陷,还可以被用来做应用保活,这个思路也早被一些流氓应用实践。
  • 全局 Broadcast 是不安全的,与上一条不隐私对应,你的应也用可以接受其他应用发来的特定 IntentFilter 的 Broadcast,这意味着,攻击者可以通过分析构造特定的广播数据,危害根据业务不同和代码的防护性差异而程度不一。很多开发者可能觉得问题不大,举个栗子,如果你的一个 Activity 在启动时要获取 intent 数据,进行相应的操作,如果攻击者使用一个空数据的 intent 启动你的 Activity,会怎样呢?是否会崩溃呢?再比如,如果攻击用任意数据,不断发送广播到你应用的 Receiver 又会怎么样呢?这也是很多国内安全厂商在扫描应用安全时,提出的所谓拒绝攻击
  • 如果保需要在应用内通信,全局广播将造成资源上的浪费,Android 为了使得广播更效率,专门设置了优先级,甚至还有阻断拦截。

LocalBroadcastManager

然而我们可以在应用内发送广播时使用 LocalBroadcastManager,就不再需要担心以上的总是,LocalBroadManager 作为 support v4 包的一部分,用于在进程内注册和接收广播,其使用也和全局的 Broadcast 一脉相承,不需要任何学习成本。

在项目中引入 v4 包以后,发送广播的方法如下:

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);

Intent localIntent = new Intent(CUSTOM_ACTION);
localBroadcastManager.sendBroadcast(localIntent);

而接收广播的方法如下:

// 先创建一个 BroadcastReceiver 实例
private BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive( Context context, Intent intent ) {
        String data = intent.getStringExtra(DATA);
        Log.d( Received data : , data);
    }
};

// 动态注册这个 receiver 实例,记得在不需要时注销
localBroadcastManager.registerReceiver(receiver);

仔细观察以上代码,你会发现它的用法差别,就是将注册和发送广播的 Context 实例换成了 LocalBroadcastManager 实例而已。

使全局 Broadcast 更加安全

有人会说,我虽然已经明白了 LocalBroadcastManager 的好处,但仍然在特定的业务场景下需要使用全局的 Broadcast,但也担心前文提到的种种安全问题,该怎么办呢? 你可以尝试以下方法,但需要声明的是,它们并不能解决你所有问题。

  • 通过权限声明来限制能够收到广播的应用
    这使得合作应用必须要在 Manifest 中声明特定权限才能够收到相应权限要求的广播,如下:
<receiver
    android:name=”.MyBroadcastReceiver”
    android:permission=”YOUR_CUSTOM_PERMISSION”>
    <intent-filter>
        <action android:name=”android.intent.action.AIRPLANE_MODE”/>
    </intent-filter>
</receiver>

相应的,在发送广播时,要需要指定协商好的权限,如下:

sendBroadcast(new Intent(com.example.NOTIFY), YOUR_CUSTOM_PERMISSION);
  • 发送广播时指定可以收到广播的应用包名
sendBroadcast(new Intent(com.example.NOTIFY).setPackageName("YOUR_PACKAGE_NAME"), YOUR_CUSTOM_PERMISSION);

很显然以上两种方法除了能够提高广播效率以外,并不会使稳私和安全得到太大的改善。

最后

我们应该在可能的情况下尽量使用 LocalBroadcastManager,这使用 Broadcast 也应对其有更多的理解,使得其更加安全有效。Android 近年在资源控制方面的工作很多,在 Android O 上为了提升性能,对 Broadcast 相对 Android N 做出了更严格的限制,对它有更好的了解,能帮助我们更好的去适应不同的 Android 版本。


android 本地广播 LocalBroadcastManager Broadcast Receiver

Donation

Latest Posts

在 VPS 上搭建 Cisco IPsec|L2TP over IPsec 的极简攻略

三年前我写过一篇在VPS上搭建PPTP VPN的极简攻略, 不过一年前我就不再使用 PPTP VPN 了,最主要的原因是因为 macOS 完全不支持 PPTP;另一个原因是基于 ipsec 协议的 VPN 更加安全,IPsec 协议会加密你的网络数据, 避免泄漏或者中间人攻击。所以现在对于需要全局代

为什么应该使用本地广播(LocalBroadcastManager)

从 Android 诞生已来,就一直有所谓的四大组件,BroadcastReceiver 是其中之一。 几乎在各种样的应用中都有 BroadcastReceiver 的使用,它被应用于接收系统发送的消息以及与其他应用之间的交互,但也被大量的误用于应用内部通信。 然而在同应用中使用则违背 Broadc

推荐 Vocabulary.com

阅读之前如果你还在思考背单词的意义,我建议你先想清楚,或者参考别人的意见,例如知乎的讨论 背单词是必须吗 等问题。 从英语方面来说,我肯定不是大神,小神都算不上。 我背单词的路径基本是 中学大学英语书附录 -> 高频词汇书 -> 扇贝单词 -> Vocabulary.com。 那为什么要来推荐 Vo

Comments