BroadcastReceiver作為Android四大組件之一,即廣播。廣播分為發(fā)送者和接收者。要想使用廣播,首先必須先注冊廣播接收者,然后接著發(fā)送廣播。最后在接收者中處理廣播。
其中廣播接收者需繼承BroadcastReceiver并重寫onReceive來實現(xiàn),onReceive就是最終處理廣播的方法。
注意:Android中規(guī)定了BroadCastReceiver不能處理復(fù)雜長時間的邏輯操作,如果在onReceive方法在10s內(nèi)沒法執(zhí)行完畢,則系統(tǒng)會視之為未響應(yīng)狀態(tài),可能會報ANR錯誤??梢詫⑦@些耗時操作放在Service中開辟子線程去執(zhí)行。
BroadcastReceiver分以下幾個來寫:
- 靜態(tài)注冊
- 動態(tài)注冊
- 有序廣播
- 本地廣播
- 圖解BroadcastReceiver源碼處理過程
靜態(tài)注冊廣播
靜態(tài)廣播注冊:在AndroidManifest.xml中注冊BroadcastReceiver。
首先定一個廣播接收者StaticReceiver.java
/**
* <pre>
* author: chmj
* time : 2017/8/23
* desc : 廣播接收者,需要繼承BroadcastReceiver,并且重寫onReceive方法。其中intent參數(shù)就是發(fā)送的時候的Intent。
* </pre>
*/
public class StaticReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//獲取廣播的數(shù)據(jù).
String msg = intent.getStringExtra("test");
LogHelper.i("靜態(tài)廣播接收消息....." + msg);
}
}
接著在在AndroidManifest中注冊:
<receiver android:name=".activity.broadcastreceiver.staticregist.StaticReceiver">
<intent-filter>
<action android:name="com.broadcast.static"/>
</intent-filter>
</receiver>
注意這里的action,這個屬性是這個廣播的標志。在我們發(fā)送廣播的時候會加入廣播標志,在接收的時候只有改廣播標志對上的才能接收。
在Activity中發(fā)送廣播。
findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/**
* 1、通過sendBroadcast將廣播的Intent發(fā)送出去,Intent可以攜帶數(shù)據(jù).
* 2、setAction表示為intent設(shè)置上一個action,即給這個廣播添加一個標志,
* 后續(xù)只有和這個標志匹配的廣播接收者才可以收到。
*/
Intent intent = new Intent();
//廣播標志. 在靜態(tài)注冊中即在在AndroidManifest中需攔截這個action。
intent.setAction("com.broadcast.static");
//數(shù)據(jù).
intent.putExtra("test","test data 123");
//發(fā)送廣播
sendBroadcast(intent);
}
});
動態(tài)注冊廣播
動態(tài)注冊,即在代碼中注冊,用到IntentFileter這個類包裝Receiver然后通過registerReceiver去注冊。動態(tài)注冊可以反注冊,靜態(tài)注冊的廣播不能取消,一直存在到app退出。一般動態(tài)注冊在onCreate中注冊。在onDestroy中進行反注冊.
同樣定一個廣播接收者DynamicReceiver.java
/**
* <pre>
* author: chmj
* time : 2017/8/23
* desc : 廣播接收者,需要繼承BroadcastReceiver,并且重寫onReceive方法。其中intent參數(shù)就是發(fā)送的時候的Intent。
* </pre>
*/
public class DynamicReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//獲取廣播的數(shù)據(jù).
String msg = intent.getStringExtra("test");
LogHelper.i("動態(tài)廣播接收消息....." + msg);
}
}
動態(tài)注冊即在代碼中注冊,我們一般在onCreate里面注冊。通過IntentFileter這個類包裝Receiver然后通過registerReceiver去注冊。
private DynamicReceiver mDynamicReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_common_broad_cast_context);
//包裝Receiver
IntentFilter intentFilter = new IntentFilter();
//添加標志
intentFilter.addAction("com.broadcast.dynamic");
mDynamicReceiver = new DynamicReceiver();
//動態(tài)注冊廣播
registerReceiver(mDynamicReceiver,intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mDynamicReceiver);
}
注冊完,然后發(fā)送廣播。
findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
//廣播標志. 在靜態(tài)注冊中即在在AndroidManifest中需攔截這個action。
intent.setAction("com.broadcast.dynamic");
//數(shù)據(jù).
intent.putExtra("test","test data 123");
//發(fā)送廣播
sendBroadcast(intent);
}
});
有序廣播
上面那兩種廣播發(fā)送方式都是無序的,有序廣播通過sendOrderedBroadcast發(fā)送,而接受者Receiver的Action是同一個,只不過他們通過priority屬性進行優(yōu)先級的判定。priority越大優(yōu)先級越高,優(yōu)先級最高的會第一個攔截廣播并處理,然后才會往下傳遞.
首先我們定義3個廣播接收者:
FirstReceiver
public class FirstReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String msg = intent.getStringExtra("msg");
LogHelper.i("This is the First msg from Activity " + msg);
/**
* 接著發(fā)送消息,action是一樣的,下面的Receiver根據(jù)priority優(yōu)先級來判斷由誰來接收.
*
*/
setResultData("FirstReceiver send msg ");
setResultCode(100);
}
}
接收到廣播處理之后,要想在傳數(shù)據(jù)給下一個廣播接收者使用,就用setResultData,setResultExtras等方法。而下一個廣播接收者要想獲取上一個廣播接收者傳過來的信息,就用getResultData,getResultExtras等。
SecondReceiver
public class SecondReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//獲取上一個廣播傳過來的信息
String msg = getResultData();
//獲取code
int code = getResultCode();
/**
* getResultExtras:參數(shù)為true的時候如果Bundle是空的,則會創(chuàng)建一個Bundle返回,如果是false,則直接返回Bundle對象.
*/
Bundle bundle1 = getResultExtras(false);
Bundle bundle2 = getResultExtras(true);
LogHelper.i("----idOrderBroadcast----" + isOrderedBroadcast());
LogHelper.i("---bundle1--" + bundle1 + " bundle2 " + bundle2);
LogHelper.i("---msg--" + msg + " code " + code);
Bundle bundle = new Bundle();
bundle.putString("test","444444");
setResultExtras(bundle);
}
}
這里getResultExtras:參數(shù)為true的時候如果Bundle是空的,則會創(chuàng)建一個Bundle返回,如果是false,則直接返回Bundle對象.
ThirdReveiver
public class ThirdReveiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = getResultExtras(false);
String msg = bundle.getString("test");
LogHelper.i("ThirdReveiver msg " + msg);
}
}
注冊三個廣播接收者
<receiver
android:name=".activity.broadcastreceiver.orderregist.FirstReceiver">
<intent-filter android:priority="300">
<action android:name="com.broadcast.order"/>
</intent-filter>
</receiver>
<receiver
android:name=".activity.broadcastreceiver.orderregist.SecondReceiver">
<intent-filter android:priority="200">
<action android:name="com.broadcast.order"/>
</intent-filter>
</receiver>
<receiver
android:name=".activity.broadcastreceiver.orderregist.ThirdReveiver">
<intent-filter android:priority="100">
<action android:name="com.broadcast.order"/>
</intent-filter>
</receiver>
這里注意priority這個參數(shù),priority值越高越優(yōu)先,在這邊FirstReceiver優(yōu)先級最高,則從activity發(fā)出來的廣播,最先被它攔截處理。
發(fā)送廣播通過sendOrderedBroadcast;
findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
//廣播標志. 在靜態(tài)注冊中即在在AndroidManifest中需攔截這個action。
intent.setAction("com.broadcast.order");
//數(shù)據(jù).
intent.putExtra("test","test data 123");
//發(fā)送廣播
sendOrderedBroadcast(intent,null);
}
});
本地廣播
本地廣播,通過LocalBroadcastManager來注冊,不需要考慮安全問題,因為它只在應(yīng)用內(nèi)部有效。是安全的廣播。
同樣定一個廣播接收者DynamicReceiver
public class DynamicReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//獲取廣播的數(shù)據(jù).
String msg = intent.getStringExtra("test");
LogHelper.i("動態(tài)廣播接收消息....." + msg);
}
}
注冊的時候需通過LocalBroadcastManager來注冊。
private LocalBroadcastManager mLocalBroadcastManager;
private LocalReceiver mLocalReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_common_broad_cast_context);
mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext);
mLocalReceiver = new LocalReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.broadcast.local");
//本地廣播注冊.
mLocalBroadcastManager.registerReceiver(mLocalReceiver,intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocalBroadcastManager.unregisterReceiver(mLocalReceiver);
}
發(fā)送廣播也是通過LocalBroadcastManager來發(fā)送。
findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.broadcast.local");
//數(shù)據(jù).
intent.putExtra("msg","test data 123");
//發(fā)送本地廣播需要通過LocalBroadcastManager來發(fā)送.
mLocalBroadcastManager.sendBroadcast(intent);
}
});
用三張圖來看看源碼處理廣播的過程。
注冊過程

發(fā)送過程

處理過程
