BroadcastReciver 位於 android.content 包下,主要用於對廣播消息(Intent)的過濾並響應的控件。可以理解爲全局的監聽器。BroadcastReceiver 自身並不實現圖形用戶界面,但是當它收到某個廣播消息後,BroadcastReceiver 可以啓動 Activity 作爲響應,或者啓動 Service 服務等等。
目錄
-廣播分類
-靜態廣播
-動態廣播
-廣播發送
-本地廣播
廣播分類
Broadcast(廣播)是Android的四大組件之一,用於進程/線程間通信。按照不同的方式分類有不同的歸類
######發送方式
1.標準廣播
完全異步執行的廣播,沒有先後順序,不可被攔截,效率高
2.有序廣播
同步執行的廣播,有先後順序,發送出去的廣播被廣播接收者按照先後順序接收,並且前面的廣播接收器還可以截斷正在傳遞的廣播,這樣後面的廣播接收器就無法接收廣播消息了。
######註冊方式
1.靜態廣播
不管應用程序是否處於活動狀態,都會進行監聽。每次觸發都會建立新的 Receiver 對象。
2.動態廣播
代碼中進行註冊,動態註冊的廣播一定要取消註冊才行,通常是在 onDestroy()方法中調用 unregisterReceiver()方法來實現。從開始創建直到其被解除註冊會使用同一個 Receiver,無論這個廣播被觸發幾次。
######定義方式
1.系統廣播
Android 系統中內置了多個系統廣播,每個系統廣播都具有特定的 IntentFilter,其中主要包括具體的 Action,系統廣播發出後,將被相應的 BroadcastReceiver 接收。系統廣播在系統內部當特定事件發生時,由系統自動發出。
2.自定義廣播
開發者自己定義的廣播
######範圍方式
1.全局廣播
發出的廣播可以被其他任意的應用程序接收,或者可以接收來自其他任意應用程序的廣播。
2.本地廣播
只能在本應用程序的內部進行傳遞的廣播,廣播接收器也只能接收內部的廣播,不能接受其他應用程序的廣播。
介紹完廣播按照不同方式的不同歸類,接下來來講解一下廣播的使用
靜態廣播
靜態廣播的註冊是在 AndroidMainfest.xml 中定義的
<receiver android:name=".ui.broadcast.MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<!-- 接收系統開機廣播 -->
<action android:name="android.intent.action.ACTION_BATTERY_LOW" />
<!-- 接收自定義的廣播 -->
<action android:name="com.madreain.broadcast.MyReceiverFilter" />
</intent-filter>
</receiver>
enabled="true"代表能夠接受到廣播信息。exported="true"代表能夠接收到外部 APK 發送的廣播信息
動態廣播
動態廣播只需要在使用的代碼中註冊
MyReceiver myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
// 系統廣播 action 接受網絡變化
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
// 自定義的 action
intentFilter.addAction(MyReceiver.ACTION);
registerReceiver(myReceiver, intentFilter);
在onDestory方法中註銷廣播
unregisterReceiver(myReceiver);
廣播發送
無論靜態廣播還是動態廣播,發送廣播的方式都是一樣的
Intent intent = new Intent();
// 自定義的 action
intent.setAction(MyReceiver.ACTION);
sendBroadcast(intent);
廣播接收器
廣播的接受,創建廣播接收器來實現廣播的接受
public class MyReceiver extends BroadcastReceiver {
private static final String ACTION = "com.madreain.broadcast.MyReceiverFilter";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION) ){
//接收固定廣播進行處理
}
}
}
8.0 靜態廣播
Android8.0 引入了新的廣播接收器限制,因此您應該移除所有爲隱式廣播 Intent 註冊的廣播接收器。將它們留在原位並不會在構建時或運行時令應用失效,但當應用運行在 Android8.0 上時它們不起任何作用。顯式廣播 Intent(只有您的應用可以響應的 Intent)在 Android8.0 上仍以相同方式工作。這個新增限制有一些例外情況。如需查看在以 Android 8.0 爲目標平臺的應用中仍然有效的隱式廣播的列表,請參閱隱式廣播例外。
8.0 發送廣播需修改,需設置 ComponetName,ComponetName(“自定義廣播的包名”, “自定義廣播的路徑”)
Intent intent = new Intent(STATICACTION);
intent.setComponent(new ComponentName("com.madreain.broadcast", "com.madreain.broadcast.MyReceiver"));
sendBroadcast(intent);
帶權限的廣播
在廣播的實際應用中,我們爲了避免別的應用監聽我們的廣播,或者別人的應用冒充我們的應用進行發送廣播。我們在使用中可以給廣播增加權限來避免這些安全問題
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.madreain">
<!-- 自定義一個自己的權限 -->
<permission android:name="com.madreain.permissions.MY_BROADCAST"/>
<!-- 使用自定義的權限 -->
<uses-permission android:name="com.madreain.permissions.MY_BROADCAST"/>
<application ...>
<!-- 添加權限 -->
<receiver android:name=".ui.broadcast.MyReceiver"
android:permission="com.madreain.broadcast.MY_BROADCAST"
android:enabled="true"
android:exported="true">
<intent-filter>
<!-- 例如:接收自定義的廣播 -->
<action android:name="com.madreain.broadcast.MyReceiverFilter" />
</intent-filter>
</receiver>
</application>
</manifest>
在發送廣播時,我們也得指定權限,讓具有權限的應用才能接受到此廣播
Intent intent = new Intent();
intent.setAction(MyReceiver.ACTION);
// 發送廣播,添加權限
sendBroadcast(intent, "com.madreain.permissions.MY_BROADCAST");
其實爲了解決 Android 的廣播安全問題,Android 還引入了另一個 LocalBroadcastManger 類,接下來的本地廣播來介紹
本地廣播
本地廣播用於應用內部傳遞消息,比 BroadcastReceiver 更加高效,它只在應用內部有效,不需要考慮安全問題。本地廣播的創建仍然是繼承 BroadcastReceiver 創建子類,並實現父類的 onReceive() 方法。在註冊、發送、註銷廣播時使用 LocalBroadcastManager 來進行相關操作。
發送廣播
Intent intent = new Intent(MyReceiver.ACTION));
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
接受廣播
MyReceiver myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(MyReceiver.ACTION);
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, intentFilter);
註銷廣播
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
在此推薦一個第三方消息傳遞的庫EventBus,後期文章將把BroadcastReciver和EventBus做對比進行分析