浅谈Android BroadcastReceiver
文章目录
简介
BroadcastReceiver,翻译为广播接收者,它是用来接收来自系统和应用中的广播。而在Android里面有各种各样的广播,比如电池的使用状态,电话的接收和短信的接收都会产生一个广播,应用程序开发者可以监听这些广播并做出程序逻辑的处理。
广播的类型
广播分为两种不同的类型:普通广播和有序广播
普通广播:
- 完全异步执行
- 所有广播接收器几乎都会在同一时刻接收到这条广播消息, 没有任何先后顺序可言
- 效率较高, 无法被截断
有序广播:
- 同步执行
- 同一时刻只会有一个广播接收器能够收到这条广播消息
- 当这个广播接收器中的逻辑执行完毕后, 广播才会继续传递。所以此时的广播接收器是有先后顺序的, 优先级高的广播接收器就可以先收到广播消息。优先级声明在intent-filter元素的Android:priority属性中,数值越大优先级越高,取值范围为-1000到1000
- 前面的广播接收器还可以截断正在传递的广播, 这样后面的广播接收器就无法收到广播消息了
广播的发送
- 普通广播通过调用Context.sendBroadcast()来进行发送广播
清单文件代码如下:
<receiver android:name=".MyBroadcastReceiver" android:exported="true">
<intent-filter>
<action android:name="com.example.broadcast.MyBroadcast"/>
</intent-filter>
</receiver>
发送广播
//获取程序中的button按钮
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//创建Intent对象
Intent intent = new Intent();
intent.setAction("com.example.broadcast.MyBroadcast");
intent.putExtra("msg", "简单的消息");
//发送普通广播
sendBroadcast(intent);
}
});
接收者
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,
"接收到的Intent的Action为"+intent.getAction()
+"\n消息内容是:"+intent.getStringExtra("msg"),
Toast.LENGTH_SHORT).show();
}
}
效果图如下:
- 有序广播通过调用Context.sendOrderedBroadcast()来进行发送广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者。
清单文件的代码如下:
<receiver android:name=".MyBroadcastReceiver" android:exported="true">
<intent-filter android:priority="100">
<action android:name="com.example.broadcast.MyBroadcast"/>
</intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiver2" android:exported="true">
<intent-filter android:priority="0">
<action android:name="com.example.broadcast.MyBroadcast"/>
</intent-filter>
</receiver>
发送广播
//获取程序中的button按钮
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//创建Intent对象
Intent intent = new Intent();
intent.setAction("com.example.broadcast.MyBroadcast");
intent.putExtra("msg", "简单的消息");
//发送有序广播
sendOrderedBroadcast(intent,null);
}
});
第一个接收者
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("MyReceiver called");
Toast.makeText(context,
"接收到的Intent的Action为"+intent.getAction()
+"\n消息内容是:"+intent.getStringExtra("msg"),
Toast.LENGTH_SHORT).show();
//创建Bundle对象并存入数据
Bundle bundle = new Bundle();
bundle.putString("first","第一个BroadcastReceiver存入的消息");
//将Bundle放入结果中
setResultExtras(bundle);
}
}
第二个接收者
public class MyBroadcastReceiver2 extends MyBroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent){
System.out.println("MyReceiver called");
Bundle bundle = getResultExtras(true);
//解析前一个BroadcastReceiver所存入得到key为first的消息
String first = bundle.getString("first");
Toast.makeText(context,"第一个BroadcastReceiver存入的消息:"
+first,Toast.LENGTH_LONG).show();
}
}
效果如下:
Android系统当中自带的Broadcast Action
如果应用需要在系统特定时刻执行某些操作,就可以通过监听系统广播来实现。Android的大量系统事件都会对外发送标准广播。下面是Android常见的广播Action常量
- ACTION_TIME_CHANGED:系统事件被改变
- ACTION_DATE_CHANGED:系统日期被改变
- ACTION_TIMEZONE_CHANGED:系统时区被改变
- ACTION_BOOT_COMPLETED:系统启动完成
- ACTION_PACKAGE_ADDED:系统添加包
- ACTION_PACKAGE_CHANGED:系统的包改变
- ACTION_PACKAGE_REMOVED:系统的包被删除
- ACTION_PACKAGE_RESTARTED:系统的包被重启
- ACTION_PACKAGE_DATA_CLEARED:系统的包数据被清空
- ACTION_BATTERY_CHANGED:电池电量改变
- ACTION_BATTERY_LOW:电池电量低
- ACTION_POWER_CONNECTED:系统连接电源
- ACTION_POWER_DISCONNECTED:系统与电源断开
- ACTION_SHUTDOWN:系统被关闭
通过使用BroadcastReceiver来监听特殊的广播,即可让应用随系统执行特定的操作。
使用广播接收器的一般步骤
1.实现一个广播接收器,继承自BroadcastReceiver类,重写onReceive()方法
注意不要在onReceive() 方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的, 如果BroadcastReceiver的onReceiver()方法不能在10秒内执行完成,Android会认为该程序无响应,会弹出ANR(Application No Response)对话框。
如果确实需要根据Broadcast来完成一项比较耗时的操作,则可以考虑通过Intent启动一个Service来完成该操作。
2.注册广播接收器
广播接收器的注册方法有两种:静态注册和动态注册
静态注册
在清单配置文件中声明,即使进程被杀死,该广播仍然运行。
<receiver android:name=".MyBroadcastReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
可惜的是在清单文件进行静态注册这种方式在Android8.0,API26以后已经不能使用了。
动态注册
在代码中注册,受activity生命周期的影响。
在这里稍微说一下,在Context这个类当中提供了如下两个函数:
- registerReceiver(receiver,filter);
这个函数的作用就是将一个BroadcastReceiver注册到应用程序当中,这个函数接收两个参数,第一个参数是需要注册的BroadcastReceiver对象,第二个是一个IntentFilter。第一个参数是非常容易理解的,第二个参数的作用是定义了哪些Intent才能触发这个注册的BroadcastReceiver对象。 - unregisterReceiver(receiver);
这个方法就非常简单了,用于解除BroadcastReceiver的绑定状态。一旦解除完成,响应的BroadcastReceiver就不会再接收系统所广播的Intent了。
public class MainActivity extends AppCompatActivity {
private MyBroadcastReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//动态注册
IntentFilter filter = new IntentFilter();
//广播接收器想要监听什么广播, 就在这里add相应的action
filter.addAction("android.intent.action.BOOT_COMPLETED");
receiver = new MyBroadcastReceiver();
//注册
registerReceiver(receiver,filter);
}
@Override
//当Activity不可见或者销毁时,解除注册
protected void onStop(){
super.onStop();
unregisterReceiver(receiver);
}
}
实例介绍(动态注册——监听网络变化)
MainActivity.java
public class MainActivity extends AppCompatActivity {
private NetWorkChangeReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
receiver = new NetWorkChangeReceiver();
registerReceiver(receiver,filter);
}
@Override
protected void onStop(){
super.onStop();
unregisterReceiver(receiver);
}
}
NetWorkChangeReceiver.java
public class NetWorkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent){
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if (networkInfo!=null&&networkInfo.isAvailable()){
Toast.makeText(context,"网络可用", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context,"网络不可用",Toast.LENGTH_SHORT).show();
}
}
}
最后在AndroidManifest.xml清单文件中添加权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
效果如下:
广播接收者静态注册方式与静态注册方式差异
- 静态注册方法可以保证在应用程序安装之后,BroadcastReceiver始终处于活动状态,通常用于监听系统状态的改变,比如说手机的电量,WiFi网卡的状态(当然,监视这些东西也是取决于软件的需求)。对于这样的BroadcastReceiver,通常是在产生某个特定的系统事件之后,进行相应的操作,比如说WiFi网卡打开时,给用户一个提示。
- 动态注册方法相对于静态注册要灵活的多,这样注册的BroadcastReceiver通常用于更新UI的状态。一般来说,都是在一个Activity启动的时候使用这样的方法注册BroadcastReceiver,一旦接收到广播的事件,就可以在onReceiver方法当中更新当前的这个Activity当中的控件。但是需要注意的是如果这个Activity不可见了,就应该调用unregisterReceiver方法来解除注册。
作者:沈东源
原文地址:https://blog.csdn.net/qq_41491927/article/details/106616020