Android Broadcast 详解

一、BroadcastReceiver是什么

BroadcastReceiver是 Android 四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),本质上是一种发布-订阅模式的通信机制:

  • 发送方:通过 sendBroadcast() 发送 Intent
  • 接收方:通过 BroadcastReceiveronReceive() 接收并处理

广播可以实现:

  • 应用内部组件通信
  • 跨应用通信(系统广播、自定义广播)
  • 系统事件监听(开机、网络变化、电量变化等)

二、广播的类型与区别

1. 按注册方式分类

类型 注册方式 生命周期 特点
静态广播 AndroidManifest.xml<receiver> 标签 应用未运行也能接收 系统级事件、开机启动
动态广播 代码中 registerReceiver() 随注册组件生命周期 灵活控制、性能更好

2. 按发送方式分类

类型 发送方法 特点 安全性
普通广播 sendBroadcast() 异步、无序、同时发送给所有接收者 低,可被任意应用接收
有序广播 sendOrderedBroadcast() 同步、按优先级顺序传递,可拦截/修改 中等
本地广播 LocalBroadcastManager.sendBroadcast() 仅应用内部通信,效率更高 高(已废弃)

3. 按发送范围分类

类型 说明 使用场景
系统广播 Android 系统发送(如开机、网络变化) 监听系统状态变化
自定义广播 应用自己发送 应用内部/跨应用通信

三、核心原理

发送与接收流程

发送方
    ↓
Context.sendBroadcast(Intent)
    ↓
AMS (ActivityManagerService)
    ↓
遍历所有已注册的 BroadcastReceiver
    ↓
┌─────────────────┐
│ 静态广播         │ → 通过 PackageManager 解析 Manifest
│ 动态广播         │ → 通过 AMS 维护的 Receiver 列表
└─────────────────┘
    ↓
匹配 IntentFilter(action、category、data 等)
    ↓
创建 BroadcastReceiver 实例
    ↓
调用 onReceive(Context, Intent) [主线程]
    ↓
onReceive 执行完毕 → 销毁 Receiver 实例

关键原理点

  1. Receiver 是临时实例:每次广播到达时,系统会创建新的 BroadcastReceiver 实例,执行完 onReceive() 后立即销毁
  2. onReceive 在主线程执行:耗时操作会导致 ANR(10 秒超时)
  3. AMS 统一管理:所有广播路由都经过 ActivityManagerService

四、使用示例

1. 静态广播(Manifest 注册)

<!-- AndroidManifest.xml -->
<receiver android:name=".BootReceiver"
    android:exported="true">  <!--  exported=true 允许跨应用接收  -->
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

<!-- 自定义广播 -->
<receiver android:name=".MyReceiver"
    android:exported="false">  <!-- 仅应用内部 -->
    <intent-filter>
        <action android:name="com.example.ACTION_CUSTOM" />
    </intent-filter>
</receiver>
// 接收器实现
public class BootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            // 开机启动逻辑
            Intent serviceIntent = new Intent(context, MyService.class);
            context.startService(serviceIntent);
        }
    }
}

2. 动态广播(代码注册)

public class MainActivity extends AppCompatActivity {

    private MyReceiver receiver;
    private IntentFilter filter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        receiver = new MyReceiver();
        filter = new IntentFilter();
        filter.addAction("com.example.ACTION_CUSTOM");
        filter.addAction(Intent.ACTION_SCREEN_ON);

        // 注册
        registerReceiver(receiver, filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 必须注销,否则内存泄漏
        unregisterReceiver(receiver);
    }

    // 发送广播
    public void sendCustomBroadcast() {
        Intent intent = new Intent("com.example.ACTION_CUSTOM");
        intent.putExtra("data", "hello");
        sendBroadcast(intent);
    }
}
public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if ("com.example.ACTION_CUSTOM".equals(action)) {
            String data = intent.getStringExtra("data");
            Log.d("MyReceiver", "收到: " + data);
        }
    }
}

3. 有序广播

// 发送有序广播
public void sendOrderedBroadcast() {
    Intent intent = new Intent("com.example.ACTION_ORDERED");
    sendOrderedBroadcast(intent, null); // 第二个参数是权限
}
<!-- 接收器设置优先级 -->
<receiver android:name=".HighPriorityReceiver">
    <intent-filter android:priority="100">  <!-- 优先级越高越先收到 -->
        <action android:name="com.example.ACTION_ORDERED" />
    </intent-filter>
</receiver>

<receiver android:name=".LowPriorityReceiver">
    <intent-filter android:priority="1">
        <action android:name="com.example.ACTION_ORDERED" />
    </intent-filter>
</receiver>
// 高优先级接收器可以拦截或修改广播
public class HighPriorityReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 修改结果数据
        setResultData("modified_data");

        // 拦截广播,不再传递给低优先级接收器
        abortBroadcast();
    }
}

4. 本地广播(已废弃,了解即可)

// LocalBroadcastManager 已废弃,建议使用 LiveData / Flow 替代
// 或直接使用 exported=false 的广播

五、系统常用广播

广播 Action 说明 权限要求
ACTION_BOOT_COMPLETED 开机完成 RECEIVE_BOOT_COMPLETED
ACTION_SCREEN_ON/OFF 屏幕亮/灭
ACTION_BATTERY_CHANGED 电量变化 无(粘性广播)
ACTION_CONNECTIVITY_CHANGE 网络变化 ACCESS_NETWORK_STATE
ACTION_PACKAGE_ADDED/REMOVED 应用安装/卸载
ACTION_TIME_TICK 每分钟触发

六、注意事项

1. ANR 风险(最重要)

// ❌ 错误:onReceive 中做耗时操作
@Override
public void onReceive(Context context, Intent intent) {
    // 超过 10 秒就会 ANR!
    downloadLargeFile();
}
// ✅ 正确:使用 goAsync() 或启动 Service
@Override
public void onReceive(Context context, Intent intent) {
    final PendingResult pendingResult = goAsync();

    new Thread(() -> {
        try {
            downloadLargeFile();
        } finally {
            pendingResult.finish(); // 必须调用!
        }
    }).start();
}
// ✅ 更推荐:启动 Service 或 WorkManager
@Override
public void onReceive(Context context, Intent intent) {
    Intent serviceIntent = new Intent(context, MyService.class);
    context.startService(serviceIntent);
}

2. 内存泄漏

// ❌ 错误:匿名内部类持有 Activity 引用
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 匿名内部类隐式持有 MainActivity 引用
        registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // 如果 Activity 已销毁但 Receiver 未注销,泄漏
            }
        }, new IntentFilter("ACTION"));
    }
}
// ✅ 正确:使用成员变量 + 成对注册/注销
public class MainActivity extends AppCompatActivity {

    private BroadcastReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        receiver = new MyReceiver();
        registerReceiver(receiver, new IntentFilter("ACTION"));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver); // 必须注销!
    }
}

3. Android 8.0+ 后台限制

// ⚠️ Android 8.0 (API 26) 开始,大部分隐式广播无法通过静态注册接收
// 以下广播仍支持静态注册:
// - 开机完成 (BOOT_COMPLETED)
// - 应用安装/卸载 (PACKAGE_ADDED/REMOVED)
// - 时区变化 (TIMEZONE_CHANGED)
// - 语言变化 (LOCALE_CHANGED)

// ❌ 以下广播不再支持静态注册:
// - 网络变化 (CONNECTIVITY_CHANGE)
// - 屏幕亮灭 (SCREEN_ON/OFF)
// - 电量变化 (BATTERY_CHANGED)

// ✅ 解决方案:改用动态注册
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    registerReceiver(networkReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}

4. 安全性

// ❌ 错误:exported=true 且无权限控制,任意应用可发送/接收
<receiver android:name=".MyReceiver" android:exported="true">
    <intent-filter>
        <action android:name="com.example.ACTION" />
    </intent-filter>
</receiver>
<!-- ✅ 正确:自定义权限控制 -->
<!-- 1. 定义权限(发送方和接收方都要声明) -->
<permission android:name="com.example.permission.RECEIVE_BROADCAST"
    android:protectionLevel="signature" />

<!-- 2. 发送方声明权限 -->
<uses-permission android:name="com.example.permission.RECEIVE_BROADCAST" />

<!-- 3. 接收方要求权限 -->
<receiver android:name=".MyReceiver"
    android:permission="com.example.permission.RECEIVE_BROADCAST"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.ACTION" />
    </intent-filter>
</receiver>
// 4. 发送时指定权限
sendBroadcast(intent, "com.example.permission.RECEIVE_BROADCAST");
<!-- ✅ 更推荐:使用 exported=false 限制应用内部 -->
<receiver android:name=".InternalReceiver" android:exported="false">
    <intent-filter>
        <action android:name="com.example.ACTION_INTERNAL" />
    </intent-filter>
</receiver>

5. 跨进程通信

// 跨应用广播需要 exported=true
// 或使用显式 Intent 指定目标包名
Intent intent = new Intent();
intent.setAction("com.example.ACTION");
intent.setPackage("com.target.app");  // 指定接收方包名
sendBroadcast(intent);

6. 粘性广播(已废弃)

// ⚠️ sendStickyBroadcast() 已废弃,不要使用
// 替代方案:使用 LiveData、SharedPreferences 或 ContentProvider

7. 本地广播替代方案

// LocalBroadcastManager 已废弃,推荐使用:
// 1. LiveData / MutableLiveData(应用内通信)
// 2. Kotlin Flow / SharedFlow
// 3. EventBus(第三方库)
// 4. RxBus(RxJava)

// ✅ 示例:使用 LiveData
class EventBus {
    private val _events = MutableLiveData<Event>()
    val events: LiveData<Event> = _events

    fun post(event: Event) {
        _events.value = event
    }
}

七、总结

问题 答案
BroadcastReceiver是什么? Android 发布-订阅模式的组件间通信机制
核心原理? 通过 AMS 路由,匹配 IntentFilter,在主线程回调 onReceive
静态 vs 动态? 静态:应用未运行也能接收;动态:灵活、性能更好、需手动注销
普通 vs 有序? 普通:异步无序;有序:同步按优先级,可拦截
主要风险? ANR(10秒限制)、内存泄漏、Android 8.0+ 后台限制
现代替代方案? 应用内通信用 LiveData/Flow,跨组件用 WorkManager/Service

一句话总结:BroadcastReceiver是 Android 的"全局事件总线",适合系统事件监听和跨应用通信;应用内部通信优先使用 LiveData/Flow,避免广播带来的性能和安全问题。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐