Broadcast原理和使用

536 阅读9分钟

Android广播Broadcast的功能、使用流程、原理及代码示例

一、功能

Android广播(Broadcast)是Android系统中用于组件间和应用间通信的一种机制。 它允许发送者发送消息(广播事件),而接收者可以监听并响应这些消息。具体功能包括:

  • 组件间通信:在同一应用内,Activity、Service等组件可以通过广播相互通信。

  • 应用间通信:当满足条件时(如exported属性为true,且有相应权限),不同应用间的组件也可以通过广播进行通信。

  • 系统事件通知:系统通过广播通知应用关于设备状态的变化,如网络变化、电量低等。

  • 静态注册和动态注册的区别

    静态注册在AndroidManifest,应用安装时就注册到系统,是常驻广播,即使没有运行也能接收广播;(监听系统启动等)

    动态注册,生命周期跟注册它的组件关联,注销后无法再接收。(动态监听某个事件)

二、使用流程

1. 广播的发送

广播的发送通常是通过创建一个Intent对象,并使用Context的sendBroadcast()sendOrderedBroadcast()方法来实现。

// 创建一个Intent对象,指定要发送的广播
Intent intent = new Intent("com.example.CUSTOM_ACTION");
// 可以通过putExtra()方法添加额外的数据
intent.putExtra("key", "value");

// 发送标准广播
sendBroadcast(intent);

// 或者发送有序广播
// sendOrderedBroadcast(intent, null); // null表示不指定接收者的权限
2. 广播的接收

广播的接收通过BroadcastReceiver实现,BroadcastReceiver需要实现onReceive(Context context, Intent intent)方法。 注册方式有两种:

  • 静态注册

    AndroidManifest.xml中声明BroadcastReceiver,并通过<intent-filter>指定其能接收的广播类型。

    <receiver android:name=".MyBroadcastReceiver">
        <intent-filter>
            <action android:name="com.example.CUSTOM_ACTION" />
        </intent-filter>
    </receiver>
    

    MyBroadcastReceiver.java

    public class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 处理广播逻辑
        }
    }
    
  • 动态注册

    在代码中注册BroadcastReceiver,并在不再需要时注销它。

    BroadcastReceiver myReceiver = new MyBroadcastReceiver();
    IntentFilter filter = new IntentFilter("com.example.CUSTOM_ACTION");
    registerReceiver(myReceiver, filter);
    
    // 注销BroadcastReceiver
    unregisterReceiver(myReceiver);
    

三、原理

Android广播机制基于观察者模式。 当广播发送者通过Intent发送广播时,系统会检查所有已注册的BroadcastReceiver, 将广播传递给所有与Intent的action、category和data匹配的BroadcastReceiver。 每个匹配的BroadcastReceiver的onReceive()方法将被调用,执行相应的逻辑。

  • 广播发送者:负责发送广播,不需要知道有哪些接收者。
  • 广播接收者:负责监听并响应感兴趣的广播。
  • 系统:作为中介,负责广播的分发和管理。

四、总结

Android广播提供了一种灵活且松耦合的组件间和应用间通信方式。 通过广播,应用可以响应系统事件或与其他应用/组件进行交互,从而增强应用的灵活性和可扩展性。


【本地广播】 Android本地广播是一种在应用内部进行通信的机制,它允许应用程序内部的不同组件(如Activity、Service等) 通过广播的形式发送和接收消息,但这些广播消息不会被其他应用程序获取。

Android本地广播的使用

  1. 注册广播接收器

    • 创建广播接收器类:首先,你需要创建一个继承自BroadcastReceiver的类,并在其中实现onReceive(Context context, Intent intent)方法来处理接收到的广播消息。
    • 动态注册广播接收器: 由于本地广播无法静态注册,因此你需要在应用程序的某个组件(如Activity或Service)中通过 调用LocalBroadcastManager.getInstance(context).registerReceiver(receiver, intentFilter)来动态注册你的广播接收器。 其中,receiver是你的广播接收器实例,intentFilter用于指定你感兴趣的广播类型。
  2. 发送广播消息

    • 当你需要发送广播消息时,可以通过创建一个Intent对象,并设置相应的Action来标识该广播消息。 然后,通过调用LocalBroadcastManager.getInstance(context).sendBroadcast(intent)来发送广播消息。 所有已注册的、并且符合IntentFilter条件的广播接收器都会收到该消息,并调用其onReceive方法进行处理。
  3. 处理广播消息

    • 在你的广播接收器的onReceive方法中,你可以根据接收到的广播消息进行相应的处理。 你可以从Intent对象中提取出额外的数据,以便进行进一步的操作。 但需要注意的是,onReceive方法是在主线程中执行的,因此不要在其中执行耗时的操作,否则可能会导致应用程序界面卡顿或响应缓慢。
  4. 取消注册广播接收器

    • 当你不再需要接收广播消息时,应该调用LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver)来取消注册你的广播接收器,以避免内存泄漏。

Android本地广播的原理

Android本地广播的实现原理主要基于观察者模式,并结合了LocalBroadcastManager类来实现广播的发送和接收。具体原理如下:

  • 注册阶段:在应用程序中,当你通过LocalBroadcastManager注册一个广播接收器时,LocalBroadcastManager会将该接收器及其对应的IntentFilter保存到内部的一个集合中。这样,当发送广播时,LocalBroadcastManager就可以根据这些信息来找到匹配的接收器。
  • 发送阶段:当你通过LocalBroadcastManager发送一个广播时,LocalBroadcastManager会遍历其内部保存的接收器集合,找到所有符合IntentFilter条件的接收器,并将广播消息传递给它们。由于这个过程是在应用程序内部进行的,因此广播消息不会被其他应用程序获取。
  • 接收阶段:对于每个接收到广播消息的接收器,LocalBroadcastManager会调用其onReceive方法来处理广播消息。由于onReceive方法是在主线程中执行的,因此需要注意不要在其中执行耗时的操作。

通过这种机制,Android本地广播提供了一种在应用内部进行高效、安全通信的方式。 与全局广播相比,本地广播具有更高的安全性和效率, 因为它不会泄露数据给其他应用程序,也不会受到系统对全局广播的限制和干扰。


代码用例一:在Android应用中使用本地广播(LocalBroadcastManager):

1. 创建广播接收器类

首先,我们创建一个继承自BroadcastReceiver的类,用于处理接收到的本地广播。

public class MyLocalBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 检查是否是我们感兴趣的广播
        String action = intent.getAction();
        if (action.equals("com.example.myapp.LOCAL_BROADCAST")) {
            // 提取数据
            String data = intent.getStringExtra("data");
            Log.d("BroadcastReceiver", "Received broadcast: " + data);
            // 这里可以进行更多的数据处理
        }
    }
}

2. 动态注册广播接收器

在你的Activity或Service中,动态注册这个广播接收器。这里以Activity为例:

public class MainActivity extends AppCompatActivity {

    private MyLocalBroadcastReceiver myReceiver;
    private IntentFilter intentFilter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化广播接收器
        myReceiver = new MyLocalBroadcastReceiver();
        // 初始化IntentFilter,并添加我们感兴趣的action
        intentFilter = new IntentFilter("com.example.myapp.LOCAL_BROADCAST");

        // 注册广播接收器
        LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, intentFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 取消注册广播接收器
        LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
    }
}

3. 发送广播消息

在需要发送广播的地方,通过LocalBroadcastManager发送广播:

Intent intent = new Intent("com.example.myapp.LOCAL_BROADCAST");
intent.putExtra("data", "Hello, Local Broadcast!");
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);

确保替换context为你当前的上下文环境,比如this(如果你在Activity中)或getApplicationContext()

4. 完整性和清理

确保在不再需要接收广播时(如Activity的onDestroy方法中),调用unregisterReceiver来取消注册你的广播接收器,以避免内存泄漏。

注意事项

  • 本地广播仅在同一应用内部传递,不会跨应用发送。
  • onReceive方法在主线程中执行,不要在其中进行耗时操作。
  • 本地广播的注册和取消注册应在相应的生命周期方法中进行,以避免内存泄漏。

这个用例展示了如何在Android应用中实现和使用本地广播,以便在不同组件之间传递消息而不影响系统全局广播。


代码用例二:在Android应用中使用有序广播(sendOrderedBroadcast())。 有序广播允许接收者按照声明的优先级顺序接收广播,并且前一个接收者可以修改广播中的数据或完全中止广播的传递。

发送有序广播

要发送一个有序广播,你需要使用sendOrderedBroadcast()方法而不是sendBroadcast()。这个方法允许你指定一个BroadcastReceiver的列表,这些BroadcastReceiver将按照指定的顺序接收广播。但是,在实际应用中,我们更常见的是通过AndroidManifest.xml中的<intent-filter>标签来声明接收者,并设置优先级。

发送有序广播的示例代码:

Intent intent = new Intent("com.example.MY_ORDERED_BROADCAST");
intent.putExtra("key", "value");
sendOrderedBroadcast(intent, null); // 第二个参数是权限字符串,如果为null,则不检查权限

接收有序广播

在AndroidManifest.xml中声明接收者时,可以通过<intent-filter>android:priority属性来设置接收者的优先级。优先级范围从-1000到1000,数值越大,优先级越高。

<receiver android:name=".MyBroadcastReceiver">
    <intent-filter android:priority="100">
        <action android:name="com.example.MY_ORDERED_BROADCAST" />
    </intent-filter>
</receiver>

BroadcastReceiveronReceive()方法中,你可以通过调用abortBroadcast()方法来中止广播的进一步传递。

修改广播数据

在有序广播中,接收者可以修改广播的额外数据(extras),这些数据将传递给下一个接收者。但是,需要注意的是,广播的Intent对象是只读的,你不能直接修改它。不过,你可以通过setResultExtras(Bundle)方法设置一个新的Bundle作为结果,这个Bundle将作为下一个接收者接收到的Intent的一部分。

@Override
public void onReceive(Context context, Intent intent) {
    // 假设我们想要修改或添加一些数据
    Bundle extras = getResultExtras(true); // 获取当前的结果Bundle,如果为null则创建一个新的
    extras.putString("newKey", "newValue");
    setResultExtras(extras); // 设置新的结果Bundle

    // 如果需要,可以中止广播
    // abortBroadcast();
}

注意事项

  • 广播接收者(BroadcastReceiver)的执行时间非常有限,因此不应该在onReceive()方法中执行耗时操作。
  • 从Android 8.0(API 级别 26)开始,对后台服务、广播接收器和隐式Intent的启动进行了限制。确保你的应用符合这些限制,特别是如果你打算在后台接收广播。
  • 考虑到性能和用户体验,尽量避免发送过多的广播,特别是有序广播,因为它们可能会阻塞主线程。

有序广播提供了一种强大的机制来在多个组件之间按顺序传递和处理数据,但使用时需要谨慎以避免潜在的性能问题。