————————————廣播機制簡介————————————
我們先看一下什麼是廣播機制:
Android中的廣播機制非常靈活,Android中的每個應用程序都可以對自己感興趣的廣播進行註冊,這個程序也只會收到自己所關心的廣播內容,這些廣播可能是來自於系統的,也可能是來自於其他應用程序的。
Android提供了一套完整的API,允許應用程序自由地發送和接受廣播。
Android中的廣播主要可以分爲兩種類型,標準廣播 和有序廣播。
標準廣播(Normal broadcasts):標準廣播是一種 完全異步 執行的廣播,在廣播發出之後,所有的廣播接收器幾乎會在同一時刻接收到這條廣播消息。這種廣播效率比較高,但同時也意味着它是無法被截斷的。
有序廣播(Ordered broadcasts):有序廣播則是一種 同步 執行的廣播,在廣播發出之後,同一時刻只會有一個廣播接收器能夠收到這條廣播消息,當這個廣播接收器中的邏輯執行完畢之後,廣播纔會繼續傳遞。
————————————接受系統廣播————————————
Android內置了很多系統級別的廣播,可以在應用程序中通過監聽這些廣播來得到各種系統的狀態信息。
手機開機完成後會發出一條廣播,電池的電量發生變化會發出一條廣播,時間改變也會發出一條廣播……如果想要接受到這些廣播,就需要使用廣播接收器。
廣播接收器可以自由地對自己感興趣的廣播進行註冊,當有相應的廣播發出時,廣播接收器就能夠收到該廣播,並在內部處理相對應的邏輯。
我們來看一下兩種註冊方式:
- 在代碼中註冊(動態註冊)
- 在 AndroidManifest.xml 中註冊(靜態註冊)
創建廣播接收器只需要新建一個類,讓它繼承自BroadcastReceiver,並重寫父類的onReceiver()方法。當有消息通過廣播傳遞過來時,onReceive()方法就會得到執行。
讓我們先看第一種註冊,動態註冊監聽網絡變化:
看代碼:
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
//爲過濾器添加處理規則
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
//註冊廣播接收器
registerReceiver(networkChangeReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//動態的廣播接收器最後一定要取消註冊
unregisterReceiver(networkChangeReceiver);
}
//自定義內部類,繼承自BroadcastReceiver
public class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//實現onReceive()方法的邏輯
Toast.makeText(context, "網絡狀態改變", Toast.LENGTH_SHORT).show();
}
}
}
接下來讓我們分析一下這段代碼:
NetworkChangeReceiver extends BroadcastReceiver 這段代碼就是在MainActivity中定義了一個內部類,並且繼承了BroadcastReceiver,然後重寫了父類的onReceive
IntentFilter 的 addAction() 方法中添加了一個值爲 android.net.conn.CONNECTIVITY_CHANGE 的 action,用於接收系統對網絡狀態改變而發出的一條廣播。(廣播接收器想要監聽什麼廣播,就在這裏添加相應的action)
調用 registerReceiver() 方法對廣播接收器進行註冊,將 networkChangeReceiver(繼承了BroadcastReceiver) 和 IntentFilter 的實例傳遞進去即可。
最後要記得,動態註冊的廣播接收器一定都要取消註冊才行。通過調用 unregisterReceiver() 方法取消註冊。
這樣我們看起來這一段代碼還是十分簡單的。
我們現在只是提醒網絡發生變換,但是這是不夠人性化的,我們應該能直接準確的告訴用戶有網絡還是沒有網絡,這樣我們對上面的代碼進行優化:
修改 NetworkChangeReceiver 的 onReceiver() 方法,使之能夠準確告訴用戶當前網絡狀態:
Android系統規定,如果程序需要訪問系統關鍵信息,必須在配置文件中聲明權限纔可以,否則程序直接崩潰。
這裏查詢網絡狀態需要聲明權限,打開AndroidManifest.xml文件,爲添加權限(之前),代碼如下:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
修改 NetworkChangeReceiver 中的代碼:
public class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//connectivityManger是一個系統服務類,專門用於管理網絡連接
ConnectivityManager connectivityManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
//調用NetworkInfo的isAvailable()方法判斷是否聯網
if(networkInfo != null && networkInfo.isAvailable()){
Toast.makeText(context,"網絡已連接",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context,"網絡不可用",Toast.LENGTH_SHORT).show();
}
}
}