楼主: FIZb6z0063w4
36 0

[作业] Android Broadcast全面解析 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
20 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2018-6-27
最后登录
2018-6-27

楼主
FIZb6z0063w4 发表于 2025-12-11 12:55:10 |AI写论文
setResultData()

修改数据并传递给下一个接收者。

sendBroadcast(Intent)
sendOrderedBroadcast(Intent, String)

2. 按作用范围划分:全局广播与本地广播

全局广播(Global Broadcast):

  • 可在整个系统范围内被任意应用的接收者监听,也可由任何应用发送。
  • 存在安全风险,如敏感信息可能通过广播泄露;同时若多个应用注册监听,可能导致广播延迟或性能下降。
  • 常用于跨应用通信或监听系统事件,如开机广播、网络变化等。

本地广播(Local Broadcast):

  • 仅限于当前应用内部传播,不支持跨进程传输,由
LocalBroadcastManager

统一管理。

  • 优势明显:安全性更高(避免外部窃听)、效率更优(无需Binder通信)、无ANR隐患(基于Handler机制实现)。
  • 推荐用于应用内组件通信,如Fragment向Activity传值、Activity控制Service启动等场景。

3. 按来源划分:系统广播与自定义广播

系统广播(System Broadcast):由Android系统在特定事件发生时自动发出,具有固定的Action标识。常见示例包括:

  • 网络状态变更:
android.net.conn.CONNECTIVITY_CHANGE
  • 设备启动完成:
android.intent.action.BOOT_COMPLETED
  • 电池电量过低:
android.intent.action.BATTERY_LOW

自定义广播(Custom Broadcast):开发者自行定义Action名称的广播,用于传递应用特有的事件消息。例如,在应用内部定义“支付成功”事件,其Action可设置为:

com.example.app.PAY_SUCCESS

三、广播接收者的实现与注册方式

BroadcastReceiver是处理广播消息的核心组件,其实现流程主要包括三个步骤:定义接收者、注册广播、处理逻辑。其中,“注册”环节尤为关键,直接影响广播能否正常接收。

1. 定义广播接收者

无论采用哪种注册方式,接收者的定义方式一致:需继承

BroadcastReceiver

类,并重写

onReceive()

方法以实现消息处理逻辑。

// 自定义广播接收者
public class MyBroadcastReceiver extends BroadcastReceiver {
    // 广播接收后回调此方法
    @Override
    public void onReceive(Context context, Intent intent) {
        // 1. 获取广播携带的数据
        String action = intent.getAction();
        String data = intent.getStringExtra("key");
        
        // 2. 根据Action区分不同广播,执行对应逻辑
        if ("com.example.app.PAY_SUCCESS".equals(action)) {
            // 处理支付成功逻辑:更新订单状态、提示用户等
            Toast.makeText(context, "支付成功:" + data, Toast.LENGTH_SHORT).show();
        } else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
            // 处理网络变化逻辑
            checkNetworkState(context);
        }
    }
    
    // 示例:检查网络状态
    private void checkNetworkState(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info != null && info.isConnected()) {
            Toast.makeText(context, "网络已连接", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(context, "网络已断开", Toast.LENGTH_SHORT).show();
        }
    }
}

注意事项:

  • onReceive() 方法运行在主线程中,因此严禁在此方法中执行耗时操作(超过10秒将导致ANR)。
  • 若需执行长时间任务(如文件读写、网络请求),应通过启动Service或使用WorkManager来异步处理。
  • 虽然可以在onReceive()中创建新线程,但不建议这样做,因为系统可能在广播处理完成后立即回收进程,导致线程未完成就被终止。

2. 广播的注册方式

只有完成注册,BroadcastReceiver才能接收到广播消息。Android提供了两种注册机制:“静态注册”和“动态注册”,它们在生命周期管理和使用场景上存在显著差异。

方式一:静态注册(通过AndroidManifest.xml声明)

广播接收者的注册方式

在 Android 开发中,广播接收者可通过两种方式进行注册:静态注册与动态注册。它们在使用场景、生命周期管理及系统兼容性方面存在显著差异。

方式一:静态注册(清单文件注册)

通过在 AndroidManifest.xml 文件中声明接收者实现注册,属于“全局注册”机制,即使应用未启动也能接收到特定的系统广播。

AndroidManifest.xml

关键属性说明:

  • enabled:控制该接收者是否处于启用状态。若设置为 false,则即便已注册也无法接收任何广播。
  • exported:决定是否允许接收来自其他应用程序的广播。若设为 false,仅能接收本应用自身发出的广播,从而增强安全性。

适用场景主要包括需要在应用未运行时响应的系统级事件,例如设备开机完成、应用安装或卸载等广播通知。

API 26 后的限制:自 Android 8.0(API 级别 26)起,为提升系统性能和减少后台行为,除少数预定义的系统广播外,大多数隐式广播不再支持通过静态注册方式接收。

<application ...>
    
    <receiver
        android:name=".MyBroadcastReceiver"  
        android:enabled="true"  
        android:exported="true">  
        <intent-filter>
            
            <action android:name="com.example.app.PAY_SUCCESS" />
            
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        </intent-filter>
    </receiver>
</application>


<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

方式二:动态注册(代码注册)

在 Activity、Service 等组件的运行时代码中调用相关方法完成注册,其生命周期与注册组件紧密绑定。

registerReceiver()

只有当注册组件(如 Activity)处于活跃状态时,广播接收者才能正常接收消息。同时,在组件销毁前必须显式调用注销方法,否则可能引发内存泄漏问题。

public class MainActivity extends AppCompatActivity {
    private MyBroadcastReceiver myReceiver;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 1. 初始化接收者
        myReceiver = new MyBroadcastReceiver();
        
        // 2. 配置接收的广播Action
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.app.PAY_SUCCESS"); // 自定义广播
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_CHANGE); // 系统广播
        // 若为有序广播,可设置优先级(-1000~1000,数值越大优先级越高)
        intentFilter.setPriority(100);
        
        // 3. 注册广播
        registerReceiver(myReceiver, intentFilter);
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 4. 必须注销广播,避免内存泄漏
        unregisterReceiver(myReceiver);
    }
}

注销操作需在适当时机执行:

unregisterReceiver()

若未正确注销,系统将抛出异常提示:

IllegalArgumentException

当前开发实践中,推荐使用 LiveDataSharedFlow(Kotlin)或 EventBus 等更高效、类型安全的方案替代传统的本地广播通信机制。

两种注册方式对比总结

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

在Android开发中,广播(Broadcast)是一种关键的组件间通信机制,它类似于一个“全局通知系统”,支持应用内部乃至不同应用之间通过“发布-订阅”模式进行消息传递。无论是响应网络状态变更、监听设备启动完成,还是实现模块间的解耦通信,广播都发挥着不可替代的作用。然而,尽管其使用看似简单,背后却涉及许多细节与最佳实践。

一、广播的基本概念与核心作用

1. 什么是广播

广播是Android平台提供的一种跨组件、跨进程的消息传递机制,基于“事件驱动”模型设计。当特定事件被触发时——例如电量不足、网络断开或新应用安装——事件源会发送一条广播消息。所有注册了对应事件的接收者(即BroadcastReceiver)都将接收到该消息,并执行预设逻辑。

2. 广播中的三大角色

广播发送者(Sender):负责发起广播的一方,可以是系统服务、第三方应用,也可以是本应用中的Activity或Service等组件。发送过程通常借助Intent封装数据,并调用相应的系统API完成广播的投递。

Intent

广播接收者(Receiver):用于监听和处理广播消息的组件,必须继承自

BroadcastReceiver

类,并重写

onReceive(Context, Intent)

方法,这是广播到达后执行业务逻辑的核心入口。

系统服务(AMS):即Activity Manager Service,作为广播系统的中枢管理者,负责广播的分发与匹配。发送者将广播提交给AMS后,AMS根据Action、权限等条件筛选出所有符合条件的接收者,并依次派发消息。

3. 广播的核心价值

  • 组件解耦:广播实现了发送方与接收方之间的完全解耦。发送者无需知晓谁在监听,接收者也不必依赖具体发送者。例如,“支付成功”这一事件可通过广播通知订单模块、推送模块等,各模块只需注册即可响应,无需直接调用。
  • 系统事件监听:开发者可利用广播感知系统级变化,如屏幕开关、网络切换、电池状态更新等,从而及时调整应用行为。
  • 跨进程通信能力:广播天然支持跨应用通信。比如系统发出的“应用安装完成”广播,所有监听该事件的应用均可收到,实现多应用协同操作。

二、广播的分类方式

1. 按发送方式划分:有序广播 vs 无序广播

特性 无序广播(Normal Broadcast) 有序广播(Ordered Broadcast)
传递顺序 所有接收者同时接收,无固定次序 按优先级从高到低依次传递
截断能力 无法中断传播,所有接收者均能收到 高优先级接收者可调用
abortBroadcast()

来终止后续传递,使低优先级接收者无法接收。

数据修改 接收者不能更改广播内容 高优先级接收者可通过
发送API
典型场景 适用于通知类信息,如天气更新、新消息提醒 适合需要顺序处理的流程,如短信拦截、权限校验链
对比维度 静态注册 动态注册
注册时机 应用安装时由系统自动完成注册 组件运行期间手动注册(如 onCreate 中)
应用未启动时能否接收 可以接收(仅限 API 26 之前) 无法接收
生命周期管理 与应用整体生命周期绑定,除非卸载或被禁用 与注册组件绑定,组件销毁前需主动注销
API 26 兼容性 大部分普通广播失效 完全兼容
灵活性 较低,无法在运行时动态修改 较高,可按需添加或移除 Action 过滤条件

广播的发送机制

发送广播的核心在于构建一个包含指定 Action 和可选数据的 Intent 对象,并调用相应的发送方法。

Intent

根据广播的传递特性可分为两类:

发送无序广播

// 1. 构建Intent,指定广播Action
Intent intent = new Intent("com.example.app.PAY_SUCCESS");
// 2. 携带数据(键值对形式)
intent.putExtra("orderId", "123456");
intent.putExtra("amount", 99.0);
// 3. 发送无序广播
sendBroadcast(intent);
// 发送时可以带上权限字符串,只有拥有该权限的接收者才能收到。
sendBroadcast(intent, "com.example.PERMISSION");

// 发送本地无序广播(仅应用内可见)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

发送有序广播

Intent intent = new Intent("com.example.app.SMS_RECEIVED");
intent.putExtra("smsContent", "【验证码】123456");
// 发送有序广播,第二个参数是权限(若为null,所有应用均可接收)
// 优先级高的接收者可截断广播
sendOrderedBroadcast(intent, null);
// 有序广播的截断与数据修改示例(在接收者的onReceive中)
@Override
public void onReceive(Context context, Intent intent) {
    if ("com.example.app.SMS_RECEIVED".equals(intent.getAction())) {
        // 1. 修改广播数据
        setResultData("【拦截后】验证码已屏蔽");
        // 2. 截断广播,后续接收者无法收到
        abortBroadcast();
    }
}

实践示例:监听系统网络状态变化

以下是一个典型的广播使用流程,用于实时监听设备网络连接状态的变化。

1. 声明必要权限

<!-- 访问网络状态权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

2. 定义广播接收者类

public class NetworkChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 适配API 23+的网络状态获取方式
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Network network = cm.getActiveNetwork();
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
            if (capabilities != null) {
                if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    sendNetworkEvent(context, "WiFi网络");
                } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    sendNetworkEvent(context, "移动数据网络");
                } else {
                    sendNetworkEvent(context, "无网络连接");
                }
            } else {
                sendNetworkEvent(context, "无网络连接");
            }
        } else {
            // 兼容低版本
            NetworkInfo info = cm.getActiveNetworkInfo();
            if (info != null && info.isConnected()) {
                if (info.getType() == ConnectivityManager.TYPE_WIFI) {
                    sendNetworkEvent(context, "WiFi网络");
                } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
                    sendNetworkEvent(context, "移动数据网络");
                }
            } else {
                sendNetworkEvent(context, "无网络连接");
            }
        }
    }
    
    // 发送事件到Activity(可通过接口或LiveData优化)
    private void sendNetworkEvent(Context context, String state) {
        if (context instanceof MainActivity) {
            ((MainActivity) context).onNetworkStateChanged(state);
        }
    }
}

3. 在组件中进行动态注册与注销

public class MainActivity extends AppCompatActivity {
    private NetworkChangeReceiver networkReceiver;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 注册网络变化广播
        networkReceiver = new NetworkChangeReceiver();
        IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(networkReceiver, intentFilter);
    }
    
    // 接收网络状态变化事件,更新UI
    public void onNetworkStateChanged(String state) {
        TextView tvNetwork = findViewById(R.id.tv_network);
        tvNetwork.setText("当前网络:" + state);
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 注销广播
        unregisterReceiver(networkReceiver);
    }
}

结语

广播(Broadcast)作为 Android 四大组件之一,尽管概念历史悠久,但其设计思想仍具有现实意义。从早期开放式的广播机制,到 Android 8.0 对隐式广播的严格限制,再到 Android 14 强制要求导出组件明确声明 exported 标志,每一次演进都体现了系统对安全性和资源效率的持续优化。

对开发者而言,掌握广播不仅意味着会编写 registerReceiver() 或声明 Receiver,更重要的是理解其背后的通信模型、权限边界以及版本适配策略。

在实际项目中,建议遵循“最小权限原则”,优先采用动态注册方式处理事件,并积极使用 LiveDataSharedFlow 等现代架构组件替代传统本地广播,以提升应用性能与可维护性。同时,应密切关注不同 Android 版本间的兼容性差异,确保功能稳定可靠。

希望本文能帮助你建立起完整的广播知识体系。面对多样化的组件通信方案,愿你能依据具体场景,选择最合适的实现路径。Happy Coding!

onReceive
SharedFlow
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Android broad DROID Road ADC

返回列表 发帖 回复
您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群

京ICP备16021002号-2 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2025-12-21 11:18