標籤:
//此系列博文是《第一行Android代碼》的學習筆記,如有錯漏,歡迎指正!
Android 中的每個應用程式都可以對自己感興趣的廣播進行註冊,這樣該程式就只會接收到自己所關心的廣播內容,這些廣播可能是來自於系統的,也可能是來自於其他應用程式的。Android 提供了一套完整的 API,允許應用程式自由地發送和接收廣播。
一、廣播的類型:
Android 中的廣播主要可以分為兩種類型,標準廣播和有序廣播。
1)標準廣播(Normal broadcasts)是一種完全非同步執行的廣播,在廣播發出之後,所有的廣播接收器幾乎都會在同一時刻接收到這條廣播訊息,因此它們之間沒有任何先後順序可言。這種廣播的效率會比較高,但同時也意味著它是無法被截斷的。
2)有序廣播(Ordered broadcasts)則是一種同步執行的廣播,在廣播發出之後,同一時刻只會有一個廣播接收器能夠收到這條廣播訊息,當這個廣播接收器中的邏輯執行完畢後,廣播才會繼續傳遞。所以此時的廣播接收器是有先後順序的,優先順序高的廣播接收器就可以先收到廣播訊息,並且前面的廣播接收器還可以截斷正在傳遞的廣播,這樣後面的廣播接收器就無法收到廣播訊息了。
二、接收系統廣播:
Android 內建了很多系統層級的廣播,我們可以在應用程式中通過監聽這些廣播來得到各種系統的狀態資訊。比如手機開機完成後會發出一條廣播,電池的電量發生變化會發出一
條廣播,時間或時區發生改變也會發出一條廣播等等。如果想要接收到這些廣播,就需要使用廣播接收器。廣播接收器可以自由地對自己感興趣的廣播進行註冊,這樣當有相應的廣播發出時,廣播接收器就能夠收到該廣播,並在內部處理相應的邏輯。註冊廣播的方式一般有兩種,在代碼中註冊和在 AndroidManifest.xml 中註冊, 其中前者也被稱為動態註冊, 後者也被稱為靜態註冊。
1)動態註冊:
我們使用動態註冊來實現這樣的一個功能:提醒使用者網路是否處於開啟狀態,代碼如下:
1 public class MainActivity extends AppCompatActivity { 2 3 private IntentFilter intentFilter; 4 private NetworkChangeReceiver networkChangeReceiver; 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 intentFilter = new IntentFilter();10 intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");11 networkChangeReceiver = new NetworkChangeReceiver();12 registerReceiver(networkChangeReceiver, intentFilter);13 }14 @Override15 protected void onDestroy() {16 super.onDestroy();17 unregisterReceiver(networkChangeReceiver);18 }19 class NetworkChangeReceiver extends BroadcastReceiver {20 @Override21 public void onReceive(Context context, Intent intent) {22 ConnectivityManager connectionManager = (ConnectivityManager)23 getSystemService(Context.CONNECTIVITY_SERVICE);24 NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();25 if (networkInfo != null && networkInfo.isAvailable()) {26 Toast.makeText(context, "network is available",27 Toast.LENGTH_SHORT).show();28 } else {29 Toast.makeText(context, "network is unavailable",30 Toast.LENGTH_SHORT).show();31 }32 }33 }34 }View Code
我們在 MainActivity 中定義了一個內部類 NetworkChangeReceiver,這個類是繼承自 BroadcastReceiver 的, 並重寫了父類的 onReceive()方法。 這樣每當網路狀態發生變化時,onReceive()方法就會得到執行。在 onReceive()方法中,首先通過 getSystemService()方法得到了 ConnectivityManager 的執行個體, 這是一個系統服務類, 專門用於管理網路連接的。 然後調用它的 getActiveNetworkInfo()方法可以得到 NetworkInfo的執行個體,接著調用 NetworkInfo 的 isAvailable()方法,就可以判斷出當前是否有網路了,最後我們還是通過 Toast的方式對使用者進行提示。
然後觀察 onCreate()方法,首先我們建立了一個 IntentFilter 的執行個體,並給它添加了一個值為 android.net.conn.CONNECTIVITY_CHANGE 的 action,當網路狀態發生變化時,系統發出的便是一條值為 android.net.conn.CONNECTIVITY_CHANGE 的廣播,也就是說我們的廣播接收器想要監聽什麼廣播,就在這裡添加相應的action 就行了。 接下來建立了一個NetworkChangeReceiver 的執行個體, 然後調用 registerReceiver()方法進行註冊,將 NetworkChangeReceiver 的執行個體和 IntentFilter 的執行個體都傳了進去,這樣NetworkChangeReceiver就會收到所有值為android.net.conn.CONNECTIVITY_CHANGE的廣播,也就實現了監聽網路變化的功能。
最後要記得, 動態註冊的廣播接收器一定都要取消註冊才行,這裡我們是在 onDestroy()方法中通過調用 unregisterReceiver()方法來實現的。
另外,這裡有非常重要的一點需要說明,這裡查詢系統的網路狀態就是需要聲明許可權的,否則程式將會直接崩潰,聲明的話只需在manifest檔案假如下列語句即可:
1 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
效果如下:
2)靜態註冊:
動態註冊的廣播接收器可以自由地控制註冊與登出,在靈活性方面有很大的優勢,但是它必須要在程式啟動之後才能接收到廣播,假如我們想讓程式開機時就相應呢?這時候我們就可以使用靜態註冊了:
(1)首先建立一個 BootCompleteReceiver 繼承自BroadcastReceiver,代碼如下:
1 public class BootCompleteReceiver extends BroadcastReceiver {2 @Override3 public void onReceive(Context context, Intent intent) {4 Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();5 }6 }
在OnRecieve()方法中我們只是簡單地彈出一條文本。
(2)在manifest檔案中取得許可權和聲明廣播,代碼如下:
1 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
監聽系統開機廣播也是需要聲明許可權的,我們使用<uses-permission>標籤又加入了一條 android.permission.RECEIVE_BOOT_COMPLETED 許可權。接著我們在application標籤下插入下面代碼:
1 <receiver android:name=".BootCompleteReceiver" >2 <intent-filter>3 <action android:name="android.intent.action.BOOT_COMPLETED" />4 </intent-filter>5 </receiver>
所有靜態註冊的廣播接收器都是在標籤<receiver>進行註冊的。通過 android:name來指定具體註冊哪一個廣播接收器, 然後在<intent-filter>標籤裡加入想要接收的廣播就行了,由於Android系統啟動完成後會發出一條值為android.intent.action.BOOT_COMPLETED的廣播,因此我們在這裡添加了相應的 action。
重新啟動手機後,程式就會在螢幕中彈出文本:Boot Complete。
//End.
Android學習筆記(十三)——廣播機制