廣播2種注冊方式:靜態(tài)注冊和動態(tài)注冊
- 靜態(tài)注冊:在AndroidManifest.xml文件中進(jìn)行注冊,當(dāng)App退出后,Receiver仍然可以接收到廣播并且進(jìn)行相應(yīng)的處理宏侍。
API 級別 26 或更高級別的平臺版本為目標(biāo),則不能使用清單為隱式廣播(沒有明確針對您的應(yīng)用的廣播)聲明接收器,但一些不受此限制的隱式廣播除外洼怔。在大多數(shù)情況下,您可以使用調(diào)度作業(yè)來代替左驾。
<receiver android:name=".MyBroadcastReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
</intent-filter>
</receiver>
private const val TAG = "MyBroadcastReceiver"
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
StringBuilder().apply {
append("Action: ${intent.action}\n")
append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n")
toString().also { log ->
Log.d(TAG, log)
Toast.makeText(context, log, Toast.LENGTH_LONG).show()
}
}
}
}
- 動態(tài)注冊:在代碼中動態(tài)注冊镣隶,當(dāng)App退出后,也就沒辦法再接受廣播了
val br: BroadcastReceiver = MyBroadcastReceiver()
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
}
registerReceiver(br, filter)
//要注冊本地廣播诡右,請調(diào)用 `LocalBroadcastManager.registerReceiver(BroadcastReceiver, IntentFilter)`
停止接收廣播安岂,請調(diào)用 unregisterReceiver(android.content.BroadcastReceiver)
。當(dāng)您不再需要接收器或上下文不再有效時帆吻,請務(wù)必注銷接收器域那。
發(fā)送廣播三種方式
- sendOrderedBroadcast(Intent, String) 方法一次向一個接收器發(fā)送廣播。當(dāng)接收器逐個順序執(zhí)行時猜煮,接收器可以向下傳遞結(jié)果次员,也可以完全中止廣播,使其不再傳遞給其他接收器王带。接收器的運(yùn)行順序可以通過匹配的 intent-filter 的 android:priority 屬性來控制淑蔚;具有相同優(yōu)先級的接收器將按隨機(jī)順序運(yùn)行。
- sendBroadcast(Intent) 方法會按隨機(jī)的順序向所有接收器發(fā)送廣播愕撰。這稱為常規(guī)廣播刹衫。這種方法效率更高醋寝,但也意味著接收器無法從其他接收器讀取結(jié)果,無法傳遞從廣播中收到的數(shù)據(jù)带迟,也無法中止廣播音羞。
- LocalBroadcastManager.sendBroadcast 方法會將廣播發(fā)送給與發(fā)送器位于同一應(yīng)用中的接收器。如果您不需要跨應(yīng)用發(fā)送廣播仓犬,請使用本地廣播嗅绰。這種實(shí)現(xiàn)方法的效率更高(無需進(jìn)行進(jìn)程間通信),而且您無需擔(dān)心其他應(yīng)用在收發(fā)您的廣播時帶來的任何安全問題婶肩。
發(fā)送廣播限制及API更改
隨著 Android 平臺的發(fā)展办陷,它會不定期地更改系統(tǒng)廣播的行為方式。如果您的應(yīng)用以 Android 7.0(API 級別 24)或更高版本為目標(biāo)平臺律歼,或者安裝在搭載 Android 7.0 或更高版本的設(shè)備上民镜,請注意以下更改。
#### Android 9
從 Android 9(API 級別 28)開始险毁,[`NETWORK_STATE_CHANGED_ACTION`](https://developer.android.com/reference/android/net/wifi/WifiManager?hl=zh-cn#NETWORK_STATE_CHANGED_ACTION) 廣播不再接收有關(guān)用戶位置或個人身份數(shù)據(jù)的信息制圈。
此外,如果您的應(yīng)用安裝在搭載 Android 9 或更高版本的設(shè)備上畔况,則通過 WLAN 接收的系統(tǒng)廣播不包含 SSID鲸鹦、BSSID、連接信息或掃描結(jié)果跷跪。要獲取這些信息馋嗜,請調(diào)用 [`getConnectionInfo()`](https://developer.android.com/reference/android/net/wifi/WifiManager?hl=zh-cn#getConnectionInfo())。
#### Android 8
從 Android 8.0(API 級別 26)開始吵瞻,系統(tǒng)對清單聲明的接收器施加了額外的限制葛菇。
如果您的應(yīng)用以 Android 8.0 或更高版本為目標(biāo)平臺,那么對于大多數(shù)隱式廣播(沒有明確針對您的應(yīng)用的廣播)橡羞,您不能使用清單來聲明接收器眯停。當(dāng)用戶正在活躍地使用您的應(yīng)用時,您仍可使用[上下文注冊的接收器](https://developer.android.com/guide/components/broadcasts?hl=zh-cn#context-registered-recievers)卿泽。
#### Android 7
Android 7.0(API 級別 24)及更高版本不發(fā)送以下系統(tǒng)廣播:
* `[ACTION_NEW_PICTURE](https://developer.android.com/reference/android/hardware/Camera?hl=zh-cn#ACTION_NEW_PICTURE)`
* `[ACTION_NEW_VIDEO](https://developer.android.com/reference/android/hardware/Camera?hl=zh-cn#ACTION_NEW_VIDEO)`
此外莺债,以 Android 7.0 及更高版本為目標(biāo)平臺的應(yīng)用必須使用 `[registerReceiver(BroadcastReceiver, IntentFilter)](https://developer.android.com/reference/android/content/Context?hl=zh-cn#registerReceiver(android.content.BroadcastReceiver,%20android.content.IntentFilter))` 注冊 `[CONNECTIVITY_ACTION](https://developer.android.com/reference/android/net/ConnectivityManager?hl=zh-cn#CONNECTIVITY_ACTION)` 廣播。無法在清單中聲明接收器签夭。
-
通過權(quán)限限制廣播
帶權(quán)限的發(fā)送齐邦,當(dāng)您調(diào)用 sendBroadcast(Intent, String) 或 sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) 時,可以指定權(quán)限參數(shù)第租。接收器若要接收此廣播侄旬,則必須通過其清單中的 <uses-permission style="box-sizing: inherit;">標(biāo)記請求該權(quán)限(如果存在危險(xiǎn),則會被授予該權(quán)限)煌妈。
發(fā)送:
sendBroadcast(Intent("com.example.NOTIFY"), Manifest.permission.SEND_SMS)
接收權(quán)限:
<uses-permission android:name="android.permission.SEND_SMS"/>
帶權(quán)限接收,如果您在注冊廣播接收器時指定了權(quán)限參數(shù)(通過 registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) 或清單中的 <receiver>
,則廣播方必須通過其清單中的 <uses-permission>
標(biāo)記請求該權(quán)限(如果存在危險(xiǎn)璧诵,則會被授予該權(quán)限)汰蜘,才能向該接收器發(fā)送 Intent。
接收:
var filter = IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)
registerReceiver(receiver, filter, Manifest.permission.SEND_SMS, null )
發(fā)送:
<uses-permission android:name="android.permission.SEND_SMS"/>
廣播最佳做法建議
- 優(yōu)先只用應(yīng)用內(nèi)廣播
- 優(yōu)先使用動態(tài)注冊廣播
- 廣播命名帶包名防止同名廣播
- onReceive()主線程執(zhí)行之宿,不要在主線程執(zhí)行耗時任務(wù)
- 廣播可作為跨應(yīng)用和普通用戶流之外的消息傳遞系統(tǒng)族操。但是,您必須小心比被,不要濫用在后臺響應(yīng)廣播和運(yùn)行作業(yè)的機(jī)會色难,因?yàn)檫@會導(dǎo)致系統(tǒng)變慢。