1.BroadcastReceiver是什么蔬蕊?
BroadcastReceiver是Android的四大組件之一,Android系統(tǒng)發(fā)送的廣播哥谷,在BroadcastReceiver中接收岸夯,因此BroadcastReceiver即廣播接收者。廣播是一種跨進程通信的方式们妥,我們在應(yīng)用程序中發(fā)出的廣播猜扮,不僅在自己的應(yīng)用程序中能收到,而且其他的應(yīng)用程序也可以收到监婶。廣播是系統(tǒng)全局的旅赢,夸進程的,因此可進行組件通信惑惶,多線程通信煮盼,跨進程通訊,跨應(yīng)用通信等带污。例如僵控,當(dāng)手機電量不足時,系統(tǒng)會發(fā)送一個電量不足的廣播鱼冀,此時报破,系統(tǒng)內(nèi)的所有的應(yīng)用都能接收到這個廣播悠就。當(dāng)然,除了系統(tǒng)廣播以外泛烙,我們在實際開發(fā)中也能發(fā)送自定義廣播理卑。
1.發(fā)送自定義廣播
// 發(fā)送一個ACTION為MY_CUSTOM_BROADCAST的自定義廣播
Intent broadcastInt = new Intent();
broadcastInt.setAction("MY_CUSTOM_BROADCAST");
sendBroadcast(broadcastInt);
在AndroidManifest.xml文件里注冊廣播接收者,設(shè)置ACTION為MY_CUSTOM_BROADCAST
<receiver android:name=".com.text.broadcast.MyBroadcastReceiver">
<intent-filter>
<action android:name="MY_CUSTOM_BROADCAST"/>
</intent-filter>
</receiver>
然后實現(xiàn)自定義廣播接收者
必須繼承BroadcastReceiver并實現(xiàn)抽象方法onReceive
由于廣播接收者默認在主線程運行蔽氨,因此在onReceive中不能做耗時操作藐唠,否則會導(dǎo)致ANR
在onReceive既可以接收系統(tǒng)廣播,也可以接收自定義廣播鹉究。
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("MyBroadcastReceiver","接收到靜態(tài)注冊的廣播了");
}
}
最后當(dāng)點擊Activity的按鈕發(fā)送自定義廣播的時候Log打印如下
06-04 03:59:12.926 3685-3685/com.text.demo I/MyBroadcastReceiver: 接收到靜態(tài)注冊的廣播了
2.BroadcastReceiver有幾種創(chuàng)建方式宇立?
BroadcastReceiver有2種注冊方式
1.靜態(tài)注冊即在AndroidManifest.xml注冊廣播接收者,靜態(tài)廣播是通過PackageManagerService在app初始化的時候由系統(tǒng)注冊的自赔。
如上文提到的自定義廣播妈嘹,這個廣播只有一個ACTION,而想實際開發(fā)中我們可以給廣播接收者設(shè)置多個ACTION绍妨,并且可以在接收者的onReceive中判斷ACTION润脸。
<receiver android:name=".com.text.broadcast.MyBroadcastReceiver">
<intent-filter>
<action android:name="MY_CUSTOM_BROADCAST"/>
<action android:name="MY_CUSTOM_BROADCAST1"/>
</intent-filter>
</receiver>
發(fā)送自定義廣播
// 發(fā)送名為MY_CUSTOM_BROADCAST的自定義廣播
if(v.getId() == bt.getId()){
Intent broadcastInt = new Intent();
broadcastInt.setAction("MY_CUSTOM_BROADCAST");
sendBroadcast(broadcastInt);
}else if(v.getId() == sendBt.getId()){
Intent broadcastInt = new Intent();
broadcastInt.setAction("MY_CUSTOM_BROADCAST1");
sendBroadcast(broadcastInt);
}
接收廣播
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction() == "MY_CUSTOM_BROADCAST"){
Log.i("MyBroadcastReceiver","接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST");
}else if(intent.getAction() == "MY_CUSTOM_BROADCAST1"){
Log.i("MyBroadcastReceiver","接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST1");
}
}
}
最后的輸出結(jié)果
06-04 04:13:35.472 3959-3959/com.text.demo I/MyBroadcastReceiver: 接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST
06-04 04:13:38.884 3959-3959/com.text.demo I/MyBroadcastReceiver: 接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST1
2.動態(tài)注冊即調(diào)用registerReceiver方法注冊。注:在Activity中最好是在onResume方法中調(diào)用registerReceiver注冊他去,在onDestroy方法中調(diào)用unregisterReceiver注銷廣播毙驯,否則會造成內(nèi)存泄露。
注冊,設(shè)置IntentFilter的ACTION為REGISTER_BROADCAST
@Override
protected void onResume() {
super.onResume();
// 動態(tài)注冊廣播
receiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter("REGISTER_BROADCAST");
registerReceiver(receiver,filter);
}
銷毀灾测,Activity銷毀時注銷廣播接收者
@Override
protected void onDestroy() {
super.onDestroy();
// 銷毀廣播
unregisterReceiver(receiver);
}
接收廣播則和靜態(tài)注冊一樣爆价。
3.BroadcastReceiver2種創(chuàng)建方式的異同?
動態(tài)注冊的優(yōu)點和缺點(確認下8.0是否不允許靜態(tài)注冊)
動態(tài)注冊廣播接收者相對靜態(tài)注冊來說要更靈活媳搪,用的時候隨時注冊铭段,但需要及時銷毀,否則容易造成內(nèi)存泄露秦爆。
靜態(tài)注冊的優(yōu)點和缺點
靜態(tài)注冊則是在APP初始化的時候就注冊了序愚,不需要注冊和銷毀動作,也就不存在不銷毀就內(nèi)存泄露的風(fēng)險等限。
4.如何給BroadcastReceiver設(shè)置優(yōu)先級展运?
廣播分為普通廣播和有序廣播。普通廣播為完全異步的精刷,是可以同時被所有的廣播接收者接收到,并且廣播接收者收到廣播后無法終止廣播蔗候。而有序廣播則有先后之分怒允,且廣播可以被廣播接收者攔截和終止,調(diào)用abortBroadcast()方法即可終止锈遥。給有序廣播設(shè)置priority屬性纫事,priority的取值范圍是-1000~10000勘畔,值越大廣播的優(yōu)先級越高。廣播接收者處理了有序廣播后還可以將處理結(jié)果存入數(shù)據(jù)(可通過setResultExtras(Bundle)方法將數(shù)據(jù)存入Broadcast)丽惶,當(dāng)做Broadcast再傳遞給下一級接收者(可通過代碼Bundle bundle = getResultExtras(true)獲取上一級傳遞過來的數(shù)據(jù))
日志結(jié)果MY_CUSTOM_BROADCAST優(yōu)先級大于MY_CUSTOM_BROADCAST1炫七,當(dāng)接收到MY_CUSTOM_BROADCAST時終止廣播,因此MyReceive里面就接收不到了钾唬。
代碼示例
<receiver
android:name=".com.text.broadcast.MyBroadcastReceiver">
<intent-filter android:priority="13">
<action android:name="MY_CUSTOM_BROADCAST"/>
</intent-filter>
<intent-filter android:priority="10">
<action android:name="MY_CUSTOM_BROADCAST1"/>
</intent-filter>
</receiver>
<receiver android:name=".com.text.broadcast.MyReceive">
<intent-filter android:priority="13">
<action android:name="MY_CUSTOM_BROADCAST"/>
</intent-filter>
<intent-filter android:priority="10">
<action android:name="MY_CUSTOM_BROADCAST1"/>
</intent-filter>
</receiver>
// 發(fā)送有序廣播
if(v.getId() == bt.getId()){
Intent broadcastInt = new Intent();
broadcastInt.setAction("MY_CUSTOM_BROADCAST");
sendOrderedBroadcast(broadcastInt,null);
}else if(v.getId() == sendBt.getId()){
Intent broadcastInt = new Intent();
broadcastInt.setAction("MY_CUSTOM_BROADCAST1");
sendOrderedBroadcast(broadcastInt,null);
}
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction() == "MY_CUSTOM_BROADCAST"){
Log.i("MyBroadcastReceiver","接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST");
abortBroadcast();
}else if(intent.getAction() == "MY_CUSTOM_BROADCAST1"){
Log.i("MyBroadcastReceiver","接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST1");
}
}
}
public class MyReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction() == "MY_CUSTOM_BROADCAST"){
Log.i("MyReceive","接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST");
abortBroadcast();
}else if(intent.getAction() == "MY_CUSTOM_BROADCAST1"){
Log.i("MyReceive","接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST1");
}
}
}
這是輸出結(jié)果
06-04 05:16:29.570 5388-5388/com.text.demo I/MyBroadcastReceiver: 接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST
06-04 05:16:34.379 5388-5388/com.text.demo I/MyBroadcastReceiver: 接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST1
06-04 05:16:34.382 5388-5388/com.text.demo I/MyReceive: 接收到靜態(tài)注冊的廣播了-MY_CUSTOM_BROADCAST1
5.有哪些常用的系統(tǒng)廣播万哪?
Intent.ACTION_BATTERY_LOW
//低電量廣播
Intent.ACTION_BATTERY_OKAY
//充電完成廣播
Intent.ACTION_BOOT_COMPLETED
//系統(tǒng)啟動完成廣播
Intent.ACTION_CAMERA_BUTTON
//拍照按鈕廣播
Intent.ACTION_DATE_CHANGED
//系統(tǒng)生日改變廣播
Intent.ACTION_DEVICE_STORAGE_LOW
//系統(tǒng)內(nèi)存不足廣播
另附開發(fā)文檔鏈接:https://developer.android.google.cn/guide/components/broadcast-exceptions
5.廣播的通訊原理是什么?
1..廣播的發(fā)送和接收模式抡秆,實際上是消息的發(fā)布和訂閱模式奕巍,屬于廣義的觀察者模式。
2.廣播的發(fā)送為完全異步儒士,只管發(fā)送而不管是否有接收的止,什么時候被接收,接收后也不需要callback着撩。
3.廣播發(fā)送者通過Binder機制發(fā)送廣播到消息隊列诅福,廣播接收者通過Binder機制在ActivityManagerService進行注冊,當(dāng)消息循環(huán)機制找到符合條件(IntentFilter/Action/Permission)的廣播接收者時調(diào)用對應(yīng)的廣播接收者的onReceive().