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

相关推荐
松仔log7 小时前
Java中级——组合和继承
android·java·开发语言
我命由我1234510 小时前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
lilian23311 小时前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos
2601_9557596211 小时前
ClaudeAPI成本中心与业务标签设计指南
android·java·数据库
余衫马11 小时前
2026最新版!Android Studio 极速安装与配置指南
android·ide·android studio
AFinalStone11 小时前
Android 7系统异常问题排查(五)Framework层(下)—System Server崩溃
android·tombstone·系统异常
AFinalStone11 小时前
Android 7系统异常问题排查(八)系统追踪—Trace机制与性能诊断
android·系统异常
极客猴子15 小时前
Android录音转写频繁卡顿?多款APP长时间会议场景稳定性实测
android·人工智能·智能手机·飞书
Kapaseker15 小时前
Boolean 变量到底该怎么命名?
android·kotlin
AFinalStone15 小时前
Android 7系统异常问题排查(六)应用异常(上)—ANR机制全解
android·系统异常