通过permission限定Android广播范围
[TOC]
在默认情况下,Android自定义广播可以在任意应用之间传播。不管是发送的广播被预期之外的应用接收、还是收到预期之外的应用发送的广播,都可能导致应用数据泄露或自身稳定性。针对上述风险,可以通过下面的步骤为广播添加
permission
,限制广播数据传播的范围(如应用内部、或司内应用之间)。本文原写于2018年,如文中内容如今已有变化,劳烦告知。
1. 广播发出方
1.1 声明permission
<!-- inside AndroidManifest.xml -->
<manifest package="com.example.app1">
<permission android:name="com.example.app1.broadcast" android:protectionLevel="signature"/>
</manifest>
关于permission
的其他字段、以及protectionLevel
的详细说明,可参考Developers关于permission的指引。其中signature
限定只有签名相同的应用才能获取该项权限,应用包名可以不同。
1.2 发出广播
弃用Context.sendBroadcast(Intent intent)
,改用Context.sendBroadcast(Intent intent, String receiverPermission)
。
context.sendBroadcast(intent, Manifest.permission.broadcast);
有且仅有通过<uses-permission>
申请了permission
的接收者应用才有机会收到此广播。其中Manifest.permission.broadcast
是Android编译插件根据AndroidManifest.xml
自动生成的。
// inside Manifest.java which is auto-generated by aapt tool
package com.example.app1;
public final class Manifest {
public static final class permission {
public static final String broadcast="com.example.app1.broadcast";
}
}
2. 广播接收方
2.1 申请permission
<!-- inside AndroidManifest.xml -->
<manifest package="com.example.app2">
<uses-permission android:name="com.example.app1.broadcast"/>
</manifest>
<uses-permission/>
配置会在应用安装时告知用户,算是Android的一种应用隐私保护策略;- 广播的发送方和接收方可以是同一应用,也可以是不同应用,当双方是同一应用的场景,等于限制广播只能在单个应用内传播;
2.2 接收广播
注册BroadcastReceiver
的时候指明permission
,就可以限制广播来源。来源范围限制粒度,取决于permission
的protectionLevel
。
-
静态注册
<receiver android:name="MyReceiver" android:permission="com.example.app1.broadcast"> <intent-filter> <action android:name="com.example.app1.SOME_CUSTOM_ACTION" /> </intent-filter> </receiver>
-
动态注册
弃用
Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
,改用Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler
。context.registerReceiver(myReceiver, filter, "com.example.app1.broadcast", null);
3. permission在几个场景下的效果
- 系统广播不受
permission
影响,加了permission
的BroadcastReceiver
实例仍然可以接收系统广播; - 从应用添加到系统通知栏的
RemoteView
发送的自定义广播,可以视为应用内的“本地广播”,也可以通过添加permission
限制Intent
传播范围; - 快捷方式、桌面Widget、等,应当视为应用外部,添加
permission
可能导致Intent
无法接收,具体场景请严格测试; LocalBroadcastManager
可以达到跟permission
类似的效果(此组件及其类已弃用,请改用LiveData
或响应式流),但相比permission
如下劣势:- 需要依赖support库或androidx库,可能增加应用包体积;
- 仅能用于进程内广播,跨进程(含系统通知栏)的广播不能用
LocalBroadcastManager
;