Android基礎總結(4)——廣播接收器
在Android中的每個應用程式可以對自己感興趣的廣播進行註冊,這樣該程式就只會接收自己所關心的廣播內容,這些廣播可能來自於系統的,也可能來自於其他應用程式的。Android提供了一整套完整的API,允許應用程式自由地傳送和接收廣播。傳送廣播就是藉助之前瞭解過的Intent,接收廣播則需要用到廣播接收器(Broadcast Receiver)。.
1、廣播的型別
- 標準廣播:Normal broadcast,是一種完全非同步執行的廣播,在廣播發出之後,所有的廣播接收器幾乎都會在同一時刻接收到這條廣播訊息,因此他們之間沒有任何先後順序可言。這種廣播效率比較高,同時也意味著無法被截斷。
-
有序廣播
2、廣播接收器的使用方法
Android系統內建了很多系統級別的廣播,我們可以在應用程式中通過監聽這些廣播來得到各種系統的狀態資訊。例如,手機開機完成後會發出一條廣播訊息,電池的電量發生變化時會發出一條廣播,時間或時區發生改變時也會發出一條廣播等等;我們如果想要接收到這些廣播,則需要用到廣播接收器。
建立廣播接收器的方法很簡單,我們只需要新建一個類,讓它繼承自BroadcastReceiver,並重寫父類的onReceive()方法就行了。這樣當有廣播到來時,onReceive()方法就會得到執行,具體的邏輯可以在這個方法中進行處理。
3、廣播接收器的註冊
廣播接收器可以自由地對自己感興趣的廣播進行註冊,這樣才能在有相應的廣播發出時,廣播接收器就能夠收到該廣播,並在內部進行相應的邏輯處理。註冊廣播的方式有兩種:
-
在程式碼內註冊:也稱動態註冊。這種註冊方法一般過程是
- 在Activity中建立一個IntentFilter的物件,然後用IntentFilter物件的addAction()方法新增相應的廣播型別
- 我們還需要有一個我們自定義的廣播接收器的物件,
- 然後通過Activity的registerReceiver(BroadcastReceiver , IntentFilter)將過濾器和廣播接收器連線在一起,這樣就完成了註冊
- 最後要記得,動態註冊的廣播接收器一定要記得取消註冊才行,取消時是通過unregisterReceiver(networkChangeReceiver);方法就可以取消註冊
1 public class ThirdActivity extends Activity {
2
3 private IntentFilter intentFilter ;
4 private NetworkChangeReceiver networkChangeReceiver ;
5
6 @Override
7 protected void onCreate(Bundle savedInstanceState) {
8 super.onCreate(savedInstanceState);
9 setContentView(R.layout.activity_third);
10
11 intentFilter = new IntentFilter() ;
12 intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
13 networkChangeReceiver = new NetworkChangeReceiver() ;
14 registerReceiver(networkChangeReceiver, intentFilter) ;
15
16 unregisterReceiver(networkChangeReceiver);
17 }
18
19 class NetworkChangeReceiver extends BroadcastReceiver{
20 @Override
21 public void onReceive(Context context, Intent intent) {
22 Toast.makeText(context, "network changed", Toast.LENGTH_SHORT).show();
23 }
24 }
25 }
優缺點:動態註冊的廣播接收器可以自由地控制註冊和登出,非常靈活,但是也存在著一個缺點,即必須要在程式啟動之後才能接收到廣播,因為註冊的邏輯是寫在Activity的onCreate()方法中的。
- 在AndroidManifest.xml中註冊:也稱靜態註冊。這種情況下,我們一般不用內部類的方法來定義廣播接收器,因為需要在AndroidManifest.xml中進行註冊時需要用到我們自定義的廣播接收器的類名。其具體的註冊方法同Activity的註冊方法類似。在intent-filter中加入我們想要接收的廣播就行了。
<receiver android:name=".BootCompleteReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED />
</intent-filter>
</receiver>
靜態註冊的優點在於可以一開機就可以開始接收相應的廣播,不會像動態註冊那樣必須要等到啟動程式後才可以。
- 此外,還有一點非常重要的是,android系統為了保證應用程式的安全性做了規定,如果程式中需要訪問系統的關鍵性資訊,必須在配置檔案中宣告許可權才行,否則程式將會直接崩潰,比如像上面的查詢網路狀態就需要宣告許可權。
- 不要在廣播接收器的onReceive()方法中新增過多的邏輯或者進行任何耗時操作,因為在廣播接收器中是不允許開啟執行緒的,當onReceive()方法執行太長時間而沒有結束時,系統會報錯。
4、傳送自定義廣播
廣播是一種可以跨程序的通訊方式,我們可以在我們的應用程式中傳送廣播,其他應用程序也可以收到我們的廣播資訊。傳送廣播是通過Intent來實現的。
- 傳送標準廣播:通過建立一個Intent物件,然後通過Activity的sendBroadcast(Intent intent)方法來進行傳送。廣播的型別可以在我們建立Intent物件的時候通過構造方法Intent(String action)來自定義,eg:
1 button.setOnClickListener(new OnClickListener() {
2 @Override
3 public void onClick(View v) {
4 Intent intent = new Intent("com.keli.MY_BROADCAST") ;
5 sendBroadcast(intent);
6 }
7 });
當然,我們也可以在傳送廣播的Intent中攜帶一些資料。然後在廣播接收器的onReceive()方法中通過getIntent()方法來獲取Intent,並取出相應的資料。
- 傳送有序廣播:傳送有序廣播的方法和傳送標準廣播的方法基本相同,只是需要將最後的sendBroadcast(intent)傳送方法換成sendOrderedBroadcast(intent,null)即可。這裡的第二個引數是一個與許可權相關的字串。那麼設定廣播的先後順序是根據廣播的優先順序來判斷的,我們可以在AndroidManifest.xml中註冊廣播接收器時通過android:priority屬性來設定優先順序。
1 <receiver android:name=".MyBroascastReceiver">
2 <intent-filter android:priority="100">
3 <action android:name="com.keli.MY_BROADCAST"/>
4 </intent-filter>
5 </receiver>
此外,對於有序廣播,我們可以在我們的廣播接收器中的onReceive()方法的邏輯中對該廣播進行截斷,截斷廣播的方法也很簡單,直接呼叫abortBroadcast();方法就可以了。
- 使用本地廣播:Android引入了一套本地廣播機制,使用這個機制發出的廣播只能夠在應用程式內部進行傳遞,並且廣播接收器也只能接收來自本應用程式發出的廣播。主要是使用了一個LocalBroadcastManager物件來對廣播進行管理,並提供了傳送和註冊廣播接收器的方法。本地廣播是無法通過靜態註冊的方法進行註冊的。
5、在廣播接收器中啟動活動
在廣播接收器中也可以啟動一個活動,但是我們啟動活動之前必須給intent加入FLAG_ACTIVITY_NEW_TASK標誌,否則將無法啟動。下面的程式碼是建立一個廣播接收器,在接收到廣播後彈出一個警告對話方塊,並且設定該對話方塊不可取消,只能通過點選確定按鈕來啟動另一個活動頁面。
1 public class NetworkChangeReceiver extends BroadcastReceiver{
2 @Override
3 public void onReceive(final Context context, Intent intent) {
4 //構建對話方塊,並設定對話方塊的標題、內容
5 AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context) ;
6 dialogBuilder.setTitle("Warning") ;
7 dialogBuilder.setMessage("You are forced to ofline. Please try to login again") ;
8 //設定對話方塊不可取消
9 dialogBuilder.setCancelable(false) ;
10 //設定對話方塊的確定按鈕,第一個引數是按鈕上顯示的text,
11 //第二個引數是新增點選確定按鈕的響應事件,這裡我們設定為啟動一個登陸介面
11 dialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
12 @Override
13 public void onClick(DialogInterface dialog, int which) {
14 Intent intent = new Intent(context, LoginActivity.class) ;
15 //必須新增FLAG_ACTIVITY_NEW_TASK標誌
16 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) ;
17 context.startActivity(intent);
18 }
19 });
20 AlertDialog alertDialog = dialogBuilder.create() ;
21 //設定AlertDialog的型別,保證在廣播接收器中可以正常彈出
22 alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
23 }
24 }