Skip to the content.

通过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>
  1. <uses-permission/>配置会在应用安装时告知用户,算是Android的一种应用隐私保护策略;
  2. 广播的发送方和接收方可以是同一应用,也可以是不同应用,当双方是同一应用的场景,等于限制广播只能在单个应用内传播;

2.2 接收广播

注册BroadcastReceiver的时候指明permission,就可以限制广播来源。来源范围限制粒度,取决于permissionprotectionLevel

  1. 静态注册

    <receiver android:name="MyReceiver" android:permission="com.example.app1.broadcast">
        <intent-filter>
            <action android:name="com.example.app1.SOME_CUSTOM_ACTION" />
        </intent-filter>
    </receiver>
    
  2. 动态注册

    弃用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在几个场景下的效果

  1. 系统广播不受permission影响,加了permissionBroadcastReceiver实例仍然可以接收系统广播;
  2. 从应用添加到系统通知栏的RemoteView发送的自定义广播,可以视为应用内的“本地广播”,也可以通过添加permission限制Intent传播范围;
  3. 快捷方式、桌面Widget、等,应当视为应用外部,添加permission可能导致Intent无法接收,具体场景请严格测试;
  4. LocalBroadcastManager可以达到跟permission类似的效果(此组件及其类已弃用,请改用 LiveData 或响应式流),但相比permission如下劣势:
    1. 需要依赖support库或androidx库,可能增加应用包体积;
    2. 仅能用于进程内广播,跨进程(含系统通知栏)的广播不能用LocalBroadcastManager