基础概念与作用
- 基础概念
- 用于接收系统或应用发出的广播消息(
Intent
),并在onReceive()
方法中处理对应逻辑。 - 是 Android 四大组件中唯一不依赖用户界面的组件,可异步响应事件。
- 用于接收系统或应用发出的广播消息(
- 作用
- 监听系统全局事件(如网络状态变化、电池电量低)或应用自定义事件(如数据更新通知)。
广播类型
1.标准广播
标准广播是一种无序广播,广播发出后,所有的接收者几乎同时接收到广播,接收者之间没有先后顺序。发送标准广播使用的是sendBroadcast()
方法。例如,当设备的电池电量发生变化时,系统会发送一个标准广播,多个应用程序可以同时监听并处理这个广播,用于更新界面上的电量显示相关信息。
java
public class MainActivity extends AppCompatActivity {
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建广播接收器实例
networkChangeReceiver = new NetworkChangeReceiver();
// 创建IntentFilter并添加要监听的广播动作
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); // 网络状态变化广播
// 动态注册广播接收器
registerReceiver(networkChangeReceiver, intentFilter);
// 发送自定义广播(示例)
findViewById(R.id.send_broadcast_button).setOnClickListener(v -> {
Intent customIntent = new Intent("com.example.CUSTOM_ACTION");
customIntent.putExtra("message", "这是一条自定义广播");
sendBroadcast(customIntent);
});
}
// @Override
// protected void onResume() {
// super.onResume();
// IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
// registerReceiver(receiver, filter);
// }
// @Override
// protected void onPause() {
// super.onPause();
// unregisterReceiver(receiver);
// }
@Override
protected void onDestroy() {
super.onDestroy();
// 注销广播接收器,防止内存泄漏
unregisterReceiver(networkChangeReceiver);
}
// 自定义广播接收器类
private class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
// 处理网络变化事件
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
String status = isConnected ? "网络已连接" : "网络已断开";
Toast.makeText(context, status, Toast.LENGTH_SHORT).show();
}
else if ("com.example.CUSTOM_ACTION".equals(action)) {
// 处理自定义广播
String message = intent.getStringExtra("message");
Toast.makeText(context, "收到自定义广播: " + message, Toast.LENGTH_SHORT).show();
}
}
}
}
2.有序广播
广播发出后,系统会根据接收者的优先级依次接收广播。优先级可以在注册广播接收者时通过android:priority
属性来设定。接收者可以消费广播(调用abortBroadcast()
方法),这样后面的接收者就无法接收到该广播了。 例如,当设备收到一个短信的广播,安全软件可以优先接收这个广播,判断短信是否为垃圾短信,如果是,就消费该广播,避免后续的应用程序接收到垃圾短信的广播。
java
private void sendOrderedBroadcast() {
// 创建广播意图
Intent intent = new Intent(ACTION_ORDERED_BROADCAST);
// 设置初始数据
Bundle bundle = new Bundle();
bundle.putString("data", "初始数据");
// 发送有序广播
// 参数说明:
// 1. 广播意图
// 2. 接收权限(null表示不需要权限)
// 3. 最终接收器(所有优先级接收器处理完后最后执行,可为null)
// 4. 处理线程(null表示主线程)
// 5. 初始结果码
// 6. 初始结果数据
// 7. 初始结果 extras
sendOrderedBroadcast(intent, null, null, null,
RESULT_OK, "初始结果数据", bundle);
}
java
public class HighPriorityReceiver extends BroadcastReceiver {
private static final String TAG = "HighPriorityReceiver";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("com.example.ORDERED_BROADCAST".equals(action)) {
Log.d(TAG, "接收到有序广播");
// 获取广播携带的数据
Bundle bundle = getResultExtras(true);
String originalData = bundle.getString("data", "默认数据");
Log.d(TAG, "原始数据: " + originalData);
// 修改广播数据
bundle.putString("data", originalData + " -> 高优先级接收器修改后");
setResultExtras(bundle);
// 不拦截广播,继续传递给下一个接收器
// 如果调用abortBroadcast(),则低优先级接收器无法收到广播
// abortBroadcast();
}
}
}
java
public class LowPriorityReceiver extends BroadcastReceiver {
private static final String TAG = "LowPriorityReceiver";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("com.example.ORDERED_BROADCAST".equals(action)) {
Log.d(TAG, "接收到有序广播");
// 获取高优先级接收器修改后的数据
Bundle bundle = getResultExtras(true);
String modifiedData = bundle.getString("data", "无数据");
Log.d(TAG, "接收到的数据: " + modifiedData);
// 低优先级接收器可以继续修改数据
bundle.putString("data", modifiedData + " -> 低优先级接收器修改后");
setResultExtras(bundle);
}
}
}
注册方式
1.静态注册
-
在
AndroidManifest.xml
中声明<receiver>
标签,需指定intent-filter
。 -
特点:
- 即使应用未启动,也能接收广播(如开机完成广播
ACTION_BOOT_COMPLETED
)。 - 系统资源消耗较高,需谨慎使用(部分系统广播仅允许系统应用静态注册)
- 即使应用未启动,也能接收广播(如开机完成广播
xml
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.NETWORK_STATE_CHANGED" />
</intent-filter>
</receiver>
2.动态注册
-
通过
Context.registerReceiver(receiver, filter)
在代码中注册,需创建BroadcastReceiver
实例和IntentFilter
。 -
特点:
- 生命周期与注册组件(如 Activity)绑定,组件销毁时需调用
unregisterReceiver()
解注册,否则可能导致内存泄漏。 - 适合监听仅在组件活跃时需要响应的广播(如 Activity 可见时监听屏幕旋转)。
- 生命周期与注册组件(如 Activity)绑定,组件销毁时需调用
java
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); // 网络状态变化广播
registerReceiver(receiver, filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
生命周期
1. 广播接收器的生命周期
1.创建阶段
-
静态注册:
-
应用安装时由系统解析 AndroidManifest.xml 中的
<receiver>
标签创建,无需应用启动即可接收广播。 -
示例:
xml<receiver android:name=".MyReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
-
-
动态注册:
-
在代码中通过
context.registerReceiver(receiver, filter)
手动创建,需在组件(如 Activity)的生命周期内完成。 -
示例:
javaMyReceiver receiver = new MyReceiver(); IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); registerReceiver(receiver, filter); // 在Activity的onCreate()或onResume()中调用
-
2.接收广播阶段
-
当系统或应用发送匹配的广播时,
onReceive(Context context, Intent intent)
方法被调用。 -
关键限制:
onReceive()
必须在 10 秒内完成(前台广播)或几秒钟(后台广播),否则触发 ANR。- 禁止在
onReceive()
中执行耗时操作(如网络请求、数据库操作)。
3.销毁阶段
-
静态注册:
- 随应用卸载自动销毁。
-
动态注册:
-
需手动调用
context.unregisterReceiver(receiver)
注销,通常在组件销毁时(如 Activity 的onDestroy()
)执行。 -
若未注销,可能导致内存泄漏或空指针异常(如 Activity 已销毁但接收器仍尝试操作 UI)。
-
2. 生命周期与组件的绑定关系
1.与Activity/Fragment绑定关系
广播接收器的生命周期依赖于绑定组件。
java
public class MainActivity extends AppCompatActivity {
private MyReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
receiver = new MyReceiver();
registerReceiver(receiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver); // 必须注销
}
}
2.与Service关系
若在 Service 中注册广播接收器,需在 Service 的onDestroy()
中注销。
java
public class MyService extends Service {
private MyReceiver receiver;
@Override
public void onCreate() {
super.onCreate();
receiver = new MyReceiver();
registerReceiver(receiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
}
3. 最佳实践
- 动态注册的位置选择 :
- 若仅在 Activity 可见时接收广播,在
onResume()
中注册,onPause()
中注销。 - 若需在 Activity 整个生命周期接收,在
onCreate()
中注册,onDestroy()
中注销。
- 若仅在 Activity 可见时接收广播,在
- 避免静态内部类持有外部类引用 :
- 若使用内部类接收器,声明为
static
并通过弱引用访问外部类
- 若使用内部类接收器,声明为
java
public class MainActivity extends AppCompatActivity {
private static class MyReceiver extends BroadcastReceiver {
private WeakReference<MainActivity> activityRef;
public MyReceiver(MainActivity activity) {
this.activityRef = new WeakReference<>(activity);
}
@Override
public void onReceive(Context context, Intent intent) {
MainActivity activity = activityRef.get();
if (activity != null && !activity.isFinishing()) {
// 安全操作Activity
}
}
}
}
- 使用 LocalBroadcastManager :
- 若广播仅在应用内使用,推荐使用
LocalBroadcastManager
,避免跨应用安全风险,且无需担心权限问题。
- 若广播仅在应用内使用,推荐使用
java
// 注册
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);
// 发送
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
// 注销
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
核心方法和应用场景
1.核心方法
-
onReceive()
- 功能:这是广播接收器的核心方法,当广播被接收到时,系统会调用这个方法。它会在主线程中执行,所以在该方法中不能进行耗时操作,否则可能会阻塞主线程,影响应用的响应速度。
- 参数
- Context context :提供了广播接收者运行的上下文环境。可以使用这个上下文来启动新的Activity、获取系统服务等操作。例如,你可以通过
context.startActivity()
来启动一个新的Activity,用于显示接收到广播后的界面。 - Intent intent :包含了广播的消息内容。你可以通过
intent.getAction()
获取广播的类型(action),使用intent.getExtras()
获取广播携带的其他数据。例如,对于系统发出的电量变化广播,你可能通过intent.getIntExtra()
来获取当前电量。
- Context context :提供了广播接收者运行的上下文环境。可以使用这个上下文来启动新的Activity、获取系统服务等操作。例如,你可以通过
-
abortBroadcast()
- 功能:用于中断广播的传递。在有序广播中,如果一个广播接收者调用了这个方法,那么后续优先级较低的广播接收者将无法接收到该广播。这个方法在标准广播中无效,因为标准广播是无序的,所有的广播接收者几乎会同时接收到广播。
- 注意 :使用
abortBroadcast()
需要谨慎,只有在特定情况下(如安全软件阻止垃圾短信的通知广播)才应该使用它,因为这可能会影响其他应用的正常功能。
-
setResult()
- 功能:在有序广播中,可以使用这个方法来设置广播的结果。结果可以包括一个整数值、一个字符串和一个Intent对象。后续的广播接收者可以获取并修改这个结果。
- 示例:比如在一个需要多个应用处理的广播场景中,第一个接收者处理完后,可以设置结果来指示处理的状态,后续接收者可以基于这个结果继续处理或者放弃处理。
-
getResultData() 和 getResultExtras()
- 功能 :用于获取前面广播接收者通过
setResult()
设置的结果数据。getResultData()
返回的是字符串形式的结果,getResultExtras()
返回的是Intent对象中的额外数据。 - 应用场景 :在有序广播的多个接收者之间进行数据传递和协作。例如,广播接收者A处理完数据后,通过
setResult()
设置结果,广播接收者B可以使用getResultData()
和getResultExtras()
来获取这个结果,继续进行后续处理。
- 功能 :用于获取前面广播接收者通过
2.应用场景
-
开机启动应用
-
原理 :系统在开机完成后会发送一个
BOOT_COMPLETED
广播。应用可以注册一个广播接收者来监听这个广播,当接收到广播后,启动应用的主Activity或者后台服务。 -
代码示例(在AndroidManifest.xml中静态注册) :
xml<receiver android:name=".BootReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
对应的广播接收者类:
javapublic class BootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) { // 启动应用主Activity Intent i = new Intent(context, MainActivity.class); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); } } }
-
注意 :为了能够接收开机广播,需要在应用的
AndroidManifest.xml
中添加RECEIVE_BOOT_COMPLETED
权限。
-
-
监听系统广播(如电量变化、网络状态变化)
-
电量变化监听
-
原理 :系统会定期发送电量变化的广播(
BATTERY_CHANGED
)。通过注册广播接收者来监听这个广播,可以获取当前电量信息,用于显示电量状态或者在电量低时提醒用户。 -
代码示例(动态注册) :
javaIntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); registerReceiver(batteryReceiver, filter);
广播接收者类:
javaprivate BroadcastReceiver batteryReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); float batteryPct = level / (float)scale; // 更新电量显示 Log.d("BatteryLevel", "Battery level: " + batteryPct); } };
-
-
网络状态变化监听
-
原理 :系统会发送网络连接状态变化的广播,如
CONNECTIVITY_ACTION
。广播接收者可以监听这个广播来判断网络连接是否可用、网络类型(Wi - Fi、移动网络等)。 -
代码示例(动态注册) :
javaIntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(networkReceiver, filter);
广播接收者类:
javaprivate BroadcastReceiver networkReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo(); if (activeNetwork != null && activeNetwork.isConnected()) { String type = activeNetwork.getTypeName(); // 更新网络状态显示 Log.d("NetworkStatus", "Network connected, type: " + type); } else { Log.d("NetworkStatus", "Network disconnected"); } } };
-
-
-
应用内通信
-
原理:应用内的不同组件之间可以通过广播来进行通信。例如,一个Activity可以发送一个广播,另一个Activity或者Service作为广播接收者来接收这个广播,从而实现组件之间的解耦。
-
代码示例(发送广播) :
java// 发送自定义广播 Intent intent = new Intent("com.example.CUSTOM_ACTION"); intent.putExtra("message", "Hello from Activity"); sendBroadcast(intent);
广播接收者类:
javapublic class CustomReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String message = intent.getStringExtra("message"); // 处理接收到的消息 Log.d("CustomReceiver", "Received message: " + message); } }
-
应用场景:在一个电商应用中,购物车页面的Activity可以发送一个广播,通知商品详情页面的Activity更新商品购买数量等信息。
-
-
定时任务提醒
-
原理 :可以结合
AlarmManager
来发送定期广播。设置一个定时的广播,当到达指定时间时,广播接收者接收广播并执行相应操作,如提醒用户有预约的会议、发送定期推送消息等。 -
代码示例(设置定时广播) :
javaIntent intent = new Intent(context, AlarmReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); long triggerTime = System.currentTimeMillis() + 10 * 60 * 1000; // 10分钟后 alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
广播接收者类:
javapublic class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 执行定时任务,如显示通知提醒 NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = new NotificationCompat.Builder(context, "reminder_channel") .setContentTitle("Reminder") .setContentText("Your scheduled reminder") .setSmallIcon(R.drawable.ic_notification) .build(); notificationManager.notify(1, notification); } }
-
注意:从Android 8.0(API级别26)开始,通知需要设置通知渠道,所以需要在代码中添加通知渠道的创建逻辑。
-