Android学习笔记之Broadcast
1. Broadcast概述
Broadcast(广播)是一种消息传递机制,用于实现“一处发生事情,多处得到通知”的效果。它常用于跨进程通信,由AMS(Activity Manager Service)集中管理。
广播分为两种类型:
- 动态广播:在运行时通过
registerReceiver()注册。 - 静态广播:在
AndroidManifest.xml中声明。
此外,广播还支持有序广播(Ordered Broadcast),可以按照一定顺序递送消息。
2. 广播RECEIVER
广播接收器(Broadcast Receiver)用于接收广播消息。它可以是动态注册的(运行时注册)或静态注册的(在AndroidManifest.xml中声明)。
2.1 动态广播
动态广播需要在运行时注册,通常用于监听特定事件。
- 1 注册动态广播
// 动态注册广播
BroadcastReceiver dynamicReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_BATTERY_LOW.equals(action)) {
Log.d("DynamicReceiver", "电量过低");
}
}
};
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_LOW);
registerReceiver(dynamicReceiver, filter);
- 2 取消注册
// 取消注册广播
unregisterReceiver(dynamicReceiver);
2.2 静态广播
静态广播在AndroidManifest.xml中声明,适用于应用启动前的广播接收。
- 1 声明静态广播
<receiver android:name=".StaticReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
- 2 实现静态广播接收器
public class StaticReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Log.d("StaticReceiver", "设备启动完成");
}
}
}
2.3 有序广播
有序广播允许接收者按照优先级顺序接收消息。
- 1 发送有序广播
Intent intent = new Intent("com.example.ORDERED_BROADCAST");
sendOrderedBroadcast(intent, null);
- 2 接收有序广播
public class OrderedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("OrderedReceiver", "接收到有序广播");
// 修改广播数据
Bundle resultExtras = getResultExtras(true);
resultExtras.putString("key", "value");
setResultExtras(resultExtras);
}
}
2.4 系统广播
系统广播是由Android系统在特定事件发生时发出的广播,例如开机完成、电量变化、网络状态变化等。这些广播是全局的,可以被任何应用接收。
-
1 常见系统广播
-
BOOT_COMPLETED:设备启动完成。
-
BATTERY_CHANGED:电池电量变化。
-
CONNECTIVITY_CHANGE:网络连接状态变化。
-
SCREEN_ON/SCREEN_OFF:屏幕开启/关闭。
-
2 注册系统广播
系统广播通常使用动态或静态注册。以下是动态注册示例:
BroadcastReceiver systemReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Log.d("SystemReceiver", "设备启动完成");
}
}
};
IntentFilter systemFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
registerReceiver(systemReceiver, systemFilter);
静态注册需要在 AndroidManifest.xml 中声明,并添加相应权限(如 RECEIVE_BOOT_COMPLETED)。
<receiver android:name=".SystemReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
- 3 注意事项
- 某些系统广播需要特定权限。
- 从Android 8.0开始,静态注册的隐式广播受限,推荐使用动态注册或JobScheduler。
- 避免在广播接收器中执行耗时操作。
5. 广播权限设置
广播权限用于保护广播,防止未经授权的应用发送或接收敏感广播。通过权限,可以控制谁能发送或接收特定广播。
5.1 声明自定义权限
在 AndroidManifest.xml 中声明自定义权限。
<permission
android:name="com.example.permission.MY_BROADCAST"
android:protectionLevel="normal" />
5.2 发送广播时指定权限
发送广播时,可以要求接收者具有特定权限。
Intent intent = new Intent("com.example.MY_ACTION");
sendBroadcast(intent, "com.example.permission.MY_BROADCAST");
5.3 接收广播时要求权限
在接收器声明中指定所需权限。
<receiver android:name=".MyReceiver"
android:permission="com.example.permission.MY_BROADCAST">
<intent-filter>
<action android:name="com.example.MY_ACTION" />
</intent-filter>
</receiver>
5.4 注意事项
- 使用
protectionLevel设置权限级别(如 normal、dangerous)。 - 确保发送者和接收者都声明了相同的权限。
- 对于系统广播,可能需要系统权限。
6. 总结
广播机制是Android中重要的消息传递方式,适用于跨进程通信和事件通知。通过动态和静态广播的结合,可以实现灵活的消息处理。
实操demo:
- 要求: 展示如何监听网络连接广播并在 MainActivity 中显示网络变化的时间和参数,同时弹出提示框提示用户网络连接信息的变更
- 实现步骤:
- 在 AndroidManifest.xml 中声明网络状态变化广播接收器
- 创建 NetworkChangeReceiver 类,继承 BroadcastReceiver,实现 onReceive 方法
- 在 onReceive 方法中获取网络连接状态参数,更新 MainActivity 中的 TextView
- 代码实现:
- 修改 AndroidManifest.xml 在 AndroidManifest.xml 中声明所需的权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- 创建广播接收器 新建一个类 NetworkChangeReceiver.java,实现广播接收器逻辑:
public class NetworkChangeReceiver extends BroadcastReceiver {
private NetworkChangeListener listener;
public NetworkChangeReceiver(NetworkChangeListener listener) {
this.listener = listener;
}
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
String networkType;
if (isConnected) {
networkType = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI ? "WiFi" :
activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE ? "Mobile Data" : "Unknown";
} else {
networkType = "No Network";
}
String message = isConnected ? "Connected to " + networkType : "No network connection";
// Show a Toast message
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
// Notify the listener (MainActivity will implement this interface)
if (listener != null) {
listener.onNetworkChange(message);
}
}
public interface NetworkChangeListener {
void onNetworkChange(String message);
}
}
-
在 MainActivity 中动态注册广播接收器 在 MainActivity.java 中实现动态注册和相关逻辑:
import android.content.BroadcastReceiver; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.os.Bundle; import android.widget.TextView; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; ppublic class MainActivity extends AppCompatActivity implements NetworkChangeReceiver.NetworkChangeListener { private BroadcastReceiver networkChangeReceiver; private TextView mainTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mainTextView = findViewById(R.id.mainTextView); // Initialize and register the network change receiver networkChangeReceiver = new NetworkChangeReceiver(this); IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(networkChangeReceiver, filter); } @Override protected void onDestroy() { super.onDestroy(); // Unregister the receiver to avoid memory leaks unregisterReceiver(networkChangeReceiver); } @Override public void onNetworkChange(String message) { // Update the TextView and show a dialog runOnUiThread(() -> { // Append the message with timestamp to the TextView String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date()); mainTextView.append("\n" + timestamp + " - " + message); // Show a dialog with the network change message new AlertDialog.Builder(MainActivity.this) .setTitle("Network Change") .setMessage(message) .setPositiveButton("OK", (dialog, which) -> dialog.dismiss()) .show(); }); } -
创建布局文件 activity_main.xml 确保在 activity_main.xml 中有一个 TextView 用于显示网络变化的时间和状态:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <TextView android:id="@+id/mainTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Network status changes will appear here" android:textSize="16sp" android:padding="8dp" /> </LinearLayout> -
运行效果 当网络连接状态发生变化时: NetworkChangeReceiver 捕获广播并回调 onReceive() 方法。 MainActivity 的 onNetworkChange 方法会更新 UI。 TextView 会显示网络变化的时间和状态,例如: 2025-08-8 14:30:00 - Connected to WiFi 2025-08-8 14:31:00 - No network connection 弹窗会提示用户网络状态的变化: Title: Network Change Message: Connected to WiFi
补充说明
- 动态注册广播接收器: 动态注册确保广播只在 MainActivity 存在时监听,避免了不必要的资源消耗。
- 静态注册广播接收器: 静态注册确保广播在应用启动时就已经注册,即使 MainActivity 不存在也能收到广播。
- 权限申请: 确保在 AndroidManifest.xml 中申请了 android.permission.ACCESS_NETWORK_STATE 权限,以便获取网络连接状态。
- 广播接收器生命周期: 广播接收器的生命周期与应用的生命周期相关,确保在不需要时及时注销,避免内存泄漏。
- 弹窗提示: 弹窗提示用户网络状态的变化,使用 Toast 实现。