一, 我们所熟知的广播大家也比较有印象的可能是学校的喇叭通报这个,通知那个的,他是通过无线电波或导线传送声音的新闻传播工具。通过无线电波传送节目的称无线广播,通过导线传送节目的称有线广播。当年我们听到放假通知那是各种收拾准备走人,这时候我们学生就是对应的广播接收器,相对于听到的消息,进行对应的行为操作。
在Android中广播,我们能做到的是在特定的时刻发送一条广播,所有对应的广播接收器都可以做出相应的操作,从实现原理上可以看,android中的广播使用了观察者模式,基于消息的发布/订阅事件模型,因此,android中的广播将广播的发送者与接收者极大程度的解耦,使得系统能够方便集成,更易扩展。
二、学习广播,首先要了解的肯定是广播的应用场景:
1.同一app内部的同一组件的消息通信(单个或多个线程之间)
2.同一app内部的不同组件的消息通信(单个进程)
3.同一app内部具有多个进程的不同组件的消息通信
4.不同app之间的组件之间消息通信
5.android系统在特定情况下与app之间的消息通信
三,广播分为有序广播和无序广播:
无序广播:接着刚才的例子,就是喇叭通知放假(即发广播)之后,学生们作为广播接收器,他们是同时下课的,因为他们接受到的广播是在同一时间发生的,因此,这一类的广播称为无序广播,
有序广播:就类似与击鼓传花游戏,喝酒敲7的游戏,当第一个人开始后,就相当于发了广播,下一个人作为广播接收器,依次向下传递。但规则只能是前一位做完游戏后,后一位才可以做游戏,因此这样的一类广播我们称之为有序广播。但值得注意的地方是广播接收器是可以截断有序广播的,一旦截断之后,后面的广播接收器就无法再被执行,就相当于上面玩游戏,第一个人向第二个人传递的时候,还没传给第三个人的时候,这个时候第三个人接了第一个人传递的,这就导致了这个游戏失败了,就得开始,因此第三个人以后的人再刚才的这场游戏中,无法继续玩游戏了。
四、了解到用法以及广播的分类,接下来我们谈谈他的使用。广播作为四大组件之一,还需要对BroadcastRecevier进行注册。注册又分为静态注册和动态注册:
1.静态注册:
类似于Activity,自定义一个广播接收器之后,在清单文件(AndroidManifest.xml)中注册即为静态注册。
action就类似于显示生活中的广播的频段,当广播发送的时候需要制定后面的字符串,接收器接受的时候,也会根据该处的制定的字符串进行过滤,通常命名规范为项目的包命加上自定义的名字。
2.动态注册:
动态注册就是在java代码中进行注册BroadcastReceiver,也就是说只有在程序启动后,执行到注册代码才会注册成功,并且动态注册的广播需要解除注册才可以,
public class MainActivity extends AppCompatActivity {
private static final String My_ACTION = "com.example.administrator.broadcastdemo.MYBROADCAST";
private MyBroad myBroad;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化广播接收器对象
myBroad = new MyBroad();
//初始化过滤器,对应清单文件中receiver中的字段
IntentFilter intentFilter = new IntentFilter();
//在过滤器中添加action
intentFilter.addAction(My_ACTION);
//注册广播
registerReceiver(myBroad,intentFilter);
}
class MyBroad extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MyBroad", "接收到广播");
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消动态注册的广播
unregisterReceiver(myBroad);
}
}
静态注册与动态注册的区别:
①静态注册:在android的清单文件中注册,在程序未执行的时候就已经注册成功了。例如手机在开机之后会发送一个系统的广播,我们可以根据此广播做到开机启动应用程序。
②动态注册:在java代码中进行注册,也就是程序执行到注册代码之后,才能注册成功,并且动态注册的广播接收器需要在特定的时刻取消注册,一般在生命周期的onDestroy()方法中。
五、现在我们来学习一下自定义广播。
1.发送无序的广播:
通过Context的sendBroadCast(Intent intent)方法发送无序广播,它是完全异步的。所有receivers(广播接受器)的执行顺序是不确定的。
public class MainActivity extends AppCompatActivity {
private Button btn;
private String MyAction = "com.example.administrator.myapplication.MYBROADCAST";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.btn);
final Intent intent = new Intent(MyAction);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//发送无序广播
sendBroadcast(intent);
}
});
}
其中的action是我们自定义的,那我们发送个自定义的广播,我们可以看到,广播是通过Intent进行发送的,intent是连接Android组件的枢纽。
2.发送有序广播:
通过Context.sendOrderedBroadcast()来发送,所有的recevier(广播接收器)依次执行,Receiver可以使用setResult()方法来把结果传给下一个Receiver,通过getResult()方法来取得上个Receiver的返回结果,并可以以abort()方法来让系统丢弃该广播,使得改广播不再传送到下一个Receiver。Receiver可以设置优先级属性,来决定Receiver的执行顺序。
public class MainActivity extends AppCompatActivity {
private Button btn;
private String MyAction = "com.example.administrator.myapplication.MYBROADCAST";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.btn);
final Intent intent = new Intent(MyAction);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//发送有序的广播
sendOrderedBroadcast(intent,null);
}
});
}
六,广播接收器(BroadcastReceiver)
广播接受器就是我们平时所说的Android四大组件之一的广播,BroadcastReceiver是一个抽象类,因此我们可以自定义一个类来继承BroadRecevier,并实现它的抽象方法。
// 自定义的类继承BroadcastReceiver,并实现抽象方法
public class MyBroadCast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("todo", "接受到了广播");
}
}
BroadcastRecevier的方法:
abortBroadcast() : 中止有序广播
getResultData() : 获取广播接收者之间传递的数据对象
getResultCode() :获取广播结束者之间传递的code
getResultExtras() :获取广播接收者之间传递的Bundle
setResultData(String data) :向下传递数据
setResultCode() :向下传递code
setResult(int code, String data, Bundle) :向下传递三个数据
setResultExtras(Bundle extras) :向下传递Bundle
isOrderedBroadcast() :判断是否是有序广播
广播得接收器:
public class MyBroad extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MyBroad", "接收到广播");
//获取上一个Receiver中传递来的数据
int code = getResultCode();//获取一种结果代码的初始值。通常为 Activity.RESULT_OK 。这个值是 -1 ;为其他 int 型 也可以,如 0,1,2 ;
String data = getResultData();//获取广播数据
Bundle args = getResultExtras(false);//获取广播的附加信息
//向下一个Receiver传递数据,Bundle中可以携带需要的数据
setResultCode(100);
setResultData("Afanbaby");
setResultExtras(args);
//截断广播,不再向下进行传递
abo }
}
七,接收系统的广播:
系统的广播通常是指Android系统执行的特定时刻,系统会发送特定的广播,以方便开发者获取一些数据或状态,只要涉及到手机的基本操作,基本上都会发出相应的系统广播,例如接收到短信,网络切换,系统开机的时候等等,每一个特定的广播都对应一个知己的特定action(也就是类似与频段)
下面是一些常用的系统广播:
android.intent.action.AIRPLANE_MODE 切换飞行模式时
android.intent.action.BATTERY_LOW 电池电量低时
android.intent.action.BATTERY_OKAY 电池由低到正常时
android.intent.action.BOOT_COMPLETED 系统开机成功之后
android.intent.action.PACKAGE_ADDED 成功的安装APK之后
android.intent.action.ACTION_POWER_CONNECTED 插上外部电源时发出的广播
android.net.conn.CONNECTIVITY_CHANGE 网络状态改变时
android.provider.Telephony.SMS_RECEIVED 接收短信
还有需要注意:某些广播的使用需要配合相应的系统权限,例如检查系统开机需要android.permission.RECEIVE_BOOT_COMPLETED权限;检查网络变化需要android.permission.ACCESS_NETWORK_STATE权限