前言
广播机制是Android中一种非常重要的通信机制,用于在应用程序之间或应用程序的不同组件之间传递信息。广播可以是系统广播,也可以是自定义广播。广播机制主要包括标准广播和有序广播两种类型。
简介
在Android中,广播(Broadcast)是一种消息,任何应用程序都可以发送广播消息,任何应用程序也都可以接收广播消息。广播通常用于通知应用程序某些事件的发生,比如系统启动、电量低、网络状态改变等。
广播的主要组件包括:
- Broadcast Receiver(广播接收器):用于接收广播消息并响应这些消息的组件。
- Intent(意图):用于传递广播消息的数据结构。
-
标准广播:
标准广播(Normal Broadcast)是完全异步的,所有接收器几乎同时接收广播,并且接收顺序是不确定的。标准广播的特点是速度快,因为它们不需要等待其他接收器处理完广播才能继续传递。
-
有序广播:
有序广播(Ordered Broadcast)是同步的,一个接收器接收到广播并处理完后,广播才会继续传递给下一个接收器。接收器可以修改广播的数据或截断广播,使其不再传递给其他接收器。有序广播允许通过设置优先级来控制接收器的接收顺序,优先级高的接收器会先接收广播。
接收系统广播
监听网络变化
先新建BroadcastTest项目,修改MainActivity
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter; // 意图过滤器,用于监听特定广播事件
private NetworkChangeReceiver networkChangeReceiver; // 广播接收器实例
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 设置布局文件
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); // 添加网络连接变化的广播事件
networkChangeReceiver = new NetworkChangeReceiver(); // 初始化广播接收器
registerReceiver(networkChangeReceiver, intentFilter); // 注册广播接收器
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver); // 注销广播接收器
}
class NetworkChangeReceiver extends BroadcastReceiver {
// 内部类,继承自BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show(); // 网络变化时显示提示信息
}
}
}
动态注册的广播一定都要取消注册
取消注册原因:
防止内存泄漏:
- 如果广播接收器在不需要时未被注销,它会持有对
Context
的引用,可能会导致内存泄漏。特别是在Activity
和Service
中,如果它们被销毁后广播接收器仍然存在,会导致这些组件无法被垃圾回收器回收,进而占用系统资源。避免不必要的资源消耗:
- 如果不注销广播接收器,它仍然会继续接收广播,即使相关的
Activity
或Service
已经不再需要这些广播。这会导致不必要的系统资源消耗,因为每次接收到广播时都会触发onReceive
方法的执行。防止潜在的崩溃:
- 在一些情况下,如果广播接收器在
Activity
或Service
销毁后继续接收广播,可能会导致应用程序崩溃。例如,如果onReceive
方法中试图访问已销毁的Activity
的 UI 元素,会引发NullPointerException
等异常。良好的编程实践:
- 注销广播接收器是一种良好的编程习惯,有助于保持代码的整洁和可靠性。它确保每个资源都被合理管理和释放,避免因资源管理不当而导致的各种问题。
上面的代码只能提示网络是否变化,可以对上面的代码进行优化
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter; // 意图过滤器,用于监听特定广播事件
private NetworkChangeReceiver networkChangeReceiver; // 广播接收器实例
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 设置布局文件
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); // 添加网络连接变化的广播事件
networkChangeReceiver = new NetworkChangeReceiver(); // 初始化广播接收器
registerReceiver(networkChangeReceiver, intentFilter); // 注册广播接收器
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver); // 注销广播接收器
}
class NetworkChangeReceiver extends BroadcastReceiver {
// 内部类,继承自BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); // 获取连接管理器
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); // 获取当前活动的网络信息
if (networkInfo != null && networkInfo.isAvailable()) {
// 检查网络是否可用
Toast.makeText(context, "network is available", Toast.LENGTH_SHORT).show(); // 网络可用时显示提示信息
} else {
Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show(); // 网络不可用时显示提示信息
}
}
}
}
就可以显式网络是否连接了
静态注册实现开机启动
先在com/example/boardcasttest包下点击New→Other→Broadcast Receiver,修改名字为BootCompleteReceiver并且勾选Exported(是否允许这个广播接收器接收本程序以外的广播),Enabled(表示是否启用这个广播接收器)创建完成
修改BootCompleteReceiver中的代码:
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show();
}
}
此外还需要在AndroidManifest文件中注册,但是由于我们使用的是快捷方式创建,所以这一步已经被自动完成了:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.BoardcastTest"
tools:targetApi="31">
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
</receiver>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
新建了一个标签<receiver>
但是目前还是接收不到开机广播,需要对AndroidManifest进行修改:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=