Android随笔-BroadcastReceiver

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 注册)

xml 复制代码
<!-- 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>
java 复制代码
// 接收器实现
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. 动态广播(代码注册)

java 复制代码
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);
    }
}
java 复制代码
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. 有序广播

java 复制代码
// 发送有序广播
public void sendOrderedBroadcast() {
    Intent intent = new Intent("com.example.ACTION_ORDERED");
    sendOrderedBroadcast(intent, null); // 第二个参数是权限
}
xml 复制代码
<!-- 接收器设置优先级 -->
<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>
java 复制代码
// 高优先级接收器可以拦截或修改广播
public class HighPriorityReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 修改结果数据
        setResultData("modified_data");

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

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

java 复制代码
// 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 风险(最重要)

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

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

2. 内存泄漏

java 复制代码
// ❌ 错误:匿名内部类持有 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"));
    }
}
java 复制代码
// ✅ 正确:使用成员变量 + 成对注册/注销
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+ 后台限制

java 复制代码
// ⚠️ 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. 安全性

java 复制代码
// ❌ 错误:exported=true 且无权限控制,任意应用可发送/接收
<receiver android:name=".MyReceiver" android:exported="true">
    <intent-filter>
        <action android:name="com.example.ACTION" />
    </intent-filter>
</receiver>
xml 复制代码
<!-- ✅ 正确:自定义权限控制 -->
<!-- 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>
java 复制代码
// 4. 发送时指定权限
sendBroadcast(intent, "com.example.permission.RECEIVE_BROADCAST");
xml 复制代码
<!-- ✅ 更推荐:使用 exported=false 限制应用内部 -->
<receiver android:name=".InternalReceiver" android:exported="false">
    <intent-filter>
        <action android:name="com.example.ACTION_INTERNAL" />
    </intent-filter>
</receiver>

5. 跨进程通信

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

6. 粘性广播(已废弃)

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

7. 本地广播替代方案

java 复制代码
// 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,避免广播带来的性能和安全问题。

相关推荐
pengyu2 小时前
【Kotlin 协程修仙录 · 金丹境 · 后阶】 | 异常防火墙:supervisorScope 与异常隔离的终极奥义
android·kotlin
cheng2191013 小时前
Cocos Creator打包安卓并支持 Android 16KB 页面大小
android
夏沫琅琊3 小时前
Jetpack Compose + 原生 PDF API 从零搭一个 Android 工具应用 (一)
android·pdf·kotlin
聚美智数4 小时前
常见疾病查询-疾病症状—疾病介绍-疾病大全-疾病治疗查询API接口介绍
android·java·数据库
私人珍藏库13 小时前
[Android] 会计快题库 -财会职称考试刷题学习
android·人工智能·学习·app·软件·多功能
安卓修改大师19 小时前
安卓修改大师 vs MT管理器:反编译工具终极对决与全景解析
android·人工智能·机器翻译
程序员小八77720 小时前
从 0 学习 MySQL 索引——7 大核心精讲
android·学习·mysql
雅客李20 小时前
2026云手机低价机型实测 安卓云手机踩坑测评报告
android·智能手机
蓝速科技21 小时前
蓝速科技鸿蒙广告机替代安卓实测:信创系统下的性能与边界评估
android·科技·harmonyos