目录
前言——手机的“小动作”
什么是广播?
有了服务为什么还需要广播?
常见的系统action
广播有哪些成员?
广播发送者
广播的发送过程
广播发送过程时序图
广播的两种发送方式
广播接受者
广播接受者的注册过程
广播注册过程时序图
广播的两种注册方式
如电量低到一定程度会有低电量提醒,插入电源线时炫酷的动画,充满电时又会显示电量已充满,以及当手机开机时显示“欢迎使用中国移动/联通/电信”提醒,关闭wifi、数据时会弹出“网络不可用”等,这些手机的“小动作”都需要系统或应用做出一些反应来让用户感知手机状态的变化,而广播就充当了这个大喇叭的角色,来告知系统和应用是时候做出反应了。
作为Android系统的四大组件之一,广播(Broadcast)是一种在组件之间进行消息传递的方式。这些组件可以是在同一个进程或不同进程中,所以广播机制可以让应用与应用间传递消息,也可以让应用接收系统消息。它利用了观察者模式,基于消息发布/订阅事件模型,它没有用户界面,但可以启动Service或Activity,所以它可以对感兴趣的外部事件(电话呼入、网络连接等)来接收并做出响应。
广播机制类似服务的Binder机制都是进程间通信,同样也是基于Binder机制的基础上实现的,但对于Binder来说,在Client组件在和Service组件通信之前,必须要先获得它的一个代理对象,即Client组件事先要知道Service组件的存在。然而在广播机制中,广播发送者实先不需要知道广播接收者的存在,这样就可以降低广播发送者和广播接收者之间的耦合度,从而提高系统的可扩展性和可维护性。
ACTION_TIME_CHANGED | 系统时间被改变 |
ACTION_DATE_CHANGED | 系统日期被改变 |
ACTION_TIMEZONE_CHANGED | 系统时区被改变 |
ACTION_BOOT_COMPLETED | 系统启动完成 |
ACTION_BATTERY_CHANGED | 电池电量改变 |
ACTION_SHUTDOWN | 系统被关闭 |
ACTION_BATTRY_LOW | 电池电量低 |
一个事件的完整周期必须有一个传达者,即广播发送者,它将手机状态以广播的形式发送出去,这时候就需要一个做出反应的接收者,即广播接收器,它对于接收到的广播做出一些应有的反应,如插入电源线时它接收到电源插入的广播就让系统弹出充电效果和此时电量值。
广播发送者负责发送消息,而广播接收者需要先订阅消息,然后才能收到消息,而广播发送者是Android的两个组件,即Activity和Service组件,它们被赋予了广播发送的能力。
代码使用如下:
定义一个事件,发送无序广播
Intent intent=new Intene();
//设置任意String的动作,可自定义为了接收者方便接收
intent.setAction("com.example.broadcast");
sendBroadcast(intent)
定义一个广播接收者来接收这个广播事件
public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context,Intent intent){
//do something
Toast.makeText(context,"收到广播",Toast.LENGTH_SHORT).show();
}
}
在Manifest.xml中配置该接收者
运行结果:Toast打印出“收到广播”
代码使用如下:
定义一个事件,发送一个有序广播
Intent intent = new Intent();
//设置intent的动作为com.example.broadcast,可以任意定义
intent.setAction("com.example.broadcast");
//发送无序广播
//第一个参数:intent
//第二个参数:String类型的接收者权限
//第三个参数:BroadcastReceiver 指定的接收者
//第四个参数:Handler scheduler
//第五个参数:int 此次广播的标记
//第六个参数:String 初始数据
//第七个参数:Bundle 往Intent中添加的额外数据
sendOrderedBroadcast(intent, null, null, null, "这是初始数据", );
定义多个广播接收者,来接收这个广播事件。通过Toast的打印判断是否收到广播
public class MyReceiver1 extends BroadcastReceiver {
public MyReceiver1() {
}
@Override
public void onReceive(Context context, Intent intent) {
//获取广播中的数据(即得到 "这是初始数据" 字符串)
String message = getResultData();
Toast.makeText(context ,message ,Toast.LENGTH_SHORT).show();
//修改数据
setResultData("这是修改后的数据");
}
}
public class MyReceiver2 extends BroadcastReceiver {
public MyReceiver2() {
}
@Override
public void onReceive(Context context, Intent intent) {
String message = getResultData();
Toast.makeText(context ,message ,Toast.LENGTH_SHORT).show();
//终止广播
abortBroadcast();
}
}
public class MyReceiver3 extends BroadcastReceiver {
public MyReceiver3() {
}
@Override
public void onReceive(Context context, Intent intent) {
String message = getResultData();
Toast.makeText(context ,message ,Toast.LENGTH_SHORT).show();
}
}
在Manifest.xml中配置该接收者。并设置优先级:MyReceiver1>MyReceiver2>MyReceiver3。
运行结果:MyReceiver1得到广播数据后打印“这是初始数据”,MyReceiver2接收到广播数据打印“这是修改后的数据”,MyReceiver3没有打印。
接收到广播后的业务逻辑,直接另写一个新的类继承BroadcastReceiver随后重写onReceive(context,intent)方法,在其中执行接收到广播后所要执行的逻辑,要想接受到广播,就要注册这个广播接收者
public class MyBroadCastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent)
{ //doSometing
Toast.makeText(context,"手机开机了",Toast.LENGTH_LONG).show();
//还可以从Intent中获取数据、还可以调用BroadcastReceiver的getResultData()获取数据
}
}
前面提到,在Android系统的广播机制中,AMS扮演着注册中心的角色,用来注册广播接收者以及转发广播。因此,Android应用程序注册广播接收者的过程实际上就是把一个广播接收者注册到AMS中。
代码中的动态注册
//new出上边定义好的BroadcastReceiver
MyBroadCastReceiver mBroadCastReceiver = new MyBroadCastReceiver();
//实例化过滤器并设置要过滤的广播
IntentFilter intentFilter = new IntentFilter("android.intent.action.MAIN");
//注册广播
myContext.registerReceiver(mBroadCastReceiver,intentFilter,
"android.permission.RECEIVE_BOOT_COMPLETED", null);
在AndroidManifest.xml的静态注册
直接在AndroidManifest.xml文件中
还要在
以上就是广播的使用介绍了,以上代码在广播接收器的onReceive()方法中都只是简单使用了Toast提示了一段文本信息,当真正在项目中使用它时可编写其他逻辑,但是不能在其中添加过多的逻辑或进行任何耗时操作,因为广播接收器时不允许开启线程的,当onReceive()方法运行了较长时间而没有结束时,程序就会报错,因此广播接收器更多的是扮演一种打开程序其他组件的角色,比如创建一条状态栏通知或启动一个服务等。
此内容均来自本小编公众号,此文章可回复“广播”搜索,主要介绍Java、Android方面知识,欢迎关注一起探讨技术问题
IT女小白的成长史