統(tǒng)計(jì)網(wǎng)站建設(shè)青島設(shè)計(jì)優(yōu)化公司
Android13 不能靜態(tài)注冊(cè)的幾個(gè)廣播
文章目錄
- Android13 不能靜態(tài)注冊(cè)的幾個(gè)廣播
- 一、不能靜態(tài)注冊(cè)的廣播:
- 二、靜態(tài)注冊(cè)無法生效的分析
- 1、Intent.java
- 2、其他地方聲明了不能靜態(tài)注冊(cè)的廣播
- 3、為啥靜態(tài)注冊(cè)的廣播無效?
- 4、其他靜態(tài)注冊(cè)無法生效的廣播
- 5、其他
- Android framework 所有廣播的定義
- 靜態(tài)廣播注冊(cè)無效解決
- 詳解Android廣播Broadcast的啟動(dòng)流程
- AMS 四大組件之 Broadcast流程分析
本文介紹一些廣播相關(guān)的知識(shí),主要是靜態(tài)廣播注冊(cè)無效的介紹。
其實(shí)從Android 8.0 就開始有這個(gè)問題的,只是本文的源碼是基于Android13 分析的。
一、不能靜態(tài)注冊(cè)的廣播:
其實(shí)并不是不能靜態(tài)注冊(cè),只是靜態(tài)注冊(cè)會(huì)無效而已。
android.intent.action.SCREEN_ON //屏幕亮起android.intent.action.SCREEN_OFF//屏幕亮起android.intent.action.BATTERY_CHANGED //電池電量改變android.intent.action.CONFIGURATION_CHANGED //配置改變,界面語言,設(shè)備方向等配置信息android.intent.action.TIME_TICK //每分鐘回調(diào)一次
主要是系統(tǒng)安全問題,這些廣播都是比較頻繁的,或者是重要時(shí)機(jī)的,避免普通應(yīng)用亂用。
你以為就完了嗎,其實(shí)沒有!
上面五個(gè)廣播都是 Intent.java 里面定義的廣播,網(wǎng)上很多就說了上面五個(gè),
其實(shí)還有其他廣播靜態(tài)注冊(cè)是無法生效的。
二、靜態(tài)注冊(cè)無法生效的分析
1、Intent.java
framework\base\core\java\android\content\Intent.java
看其中一個(gè)無法靜態(tài)注冊(cè)的廣播 Intent.ACTION_TIME_TICK 說明
/*** Broadcast Action: The current time has changed. Sent every* minute. You <em>cannot</em> receive this through components declared* in manifests, only by explicitly registering for it with* {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)* Context.registerReceiver()}.** <p class="note">This is a protected intent that can only be sent* by the system.*/@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)public static final String ACTION_TIME_TICK = "android.intent.action.TIME_TICK";
從注釋代碼其實(shí)可以看到:
You <em>cannot</em> receive this through components declaredin manifests,
//你不能通過 manifests 聲明進(jìn)行注冊(cè)
only by explicitly registering for it
//只能動(dòng)態(tài)注冊(cè)它
在Intent.java 全局搜索 “only by explicitly registering for it”,確實(shí)只有上面五個(gè)。
全局搜索一下源碼,發(fā)現(xiàn)其他地方也有這個(gè)聲明的注釋代碼,那么那些聲明了的廣播,也是會(huì)靜態(tài)注冊(cè)無效的。
2、其他地方聲明了不能靜態(tài)注冊(cè)的廣播
framework\base\media\java\android\media\AudioManager.java
/*** Broadcast Action: Wired Headset plugged in or unplugged.** You <em>cannot</em> receive this through components declared* in manifests, only by explicitly registering for it with* {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)* Context.registerReceiver()}.** <p>The intent will have the following extra values:* <ul>* <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>* <li><em>name</em> - Headset type, human readable string </li>* <li><em>microphone</em> - 1 if headset has a microphone, 0 otherwise </li>* </ul>* </ul>*/@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)public static final String ACTION_HEADSET_PLUG ="android.intent.action.HEADSET_PLUG";public static final String ACTION_MICROPHONE_MUTE_CHANGED ="android.media.action.MICROPHONE_MUTE_CHANGED";public static final String ACTION_SPEAKERPHONE_STATE_CHANGED ="android.media.action.SPEAKERPHONE_STATE_CHANGED";
framework\base\telephony\java\android\telephony\TelephonyManager.java
public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
packages\modules\Wifi\framework\java\android\net\wifi\p2p\WifiP2pManager.java
public static final String ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED";
上面的廣播基本沒怎么用過,這里不進(jìn)行描述介紹了。
看一眼知道這些廣播也是靜態(tài)注冊(cè)無效的就行了。
3、為啥靜態(tài)注冊(cè)的廣播無效?
其實(shí)我是猜測應(yīng)該是AMS加載apk的流程中會(huì)加載靜態(tài)注冊(cè)的廣播,在這個(gè)過程可能會(huì)把某些靜態(tài)注冊(cè)的廣播跳過處理,所以靜態(tài)注冊(cè)這些廣播是無效的。
下面是 Android AMS 加載 AndroidManifest.xml 廣播過程如下:
1、AMS 通過 ActivityThread 獲取 ContextImpl 對(duì)象,然后通過 ContextImpl 對(duì)象獲取 PackageManager 對(duì)象。2、AMS 調(diào)用 PackageManager 的 getReceiverInfo 方法獲取廣播接收者的信息,包括接收者的名稱、所在的進(jìn)程、導(dǎo)出狀態(tài)等信息。3、AMS 調(diào)用 ActivityThread 的 getPackageInfo 方法獲取應(yīng)用程序的信息,包括應(yīng)用程序的名稱、包名、版本號(hào)等信息。4、AMS 調(diào)用 PackageParser 的 parsePackage 方法解析 AndroidManifest.xml 文件,獲取應(yīng)用程序的組件信息,包括 Activity、Service、Receiver 等信息。5、AMS 遍歷解析出來的組件信息,找到與廣播接收者匹配的組件。6、如果找到匹配的組件,則將廣播發(fā)送給該組件;否則,將廣播發(fā)送給默認(rèn)的廣播接收者。
我大概看了一下源碼,看不出啊,加載的過程沒有對(duì)某個(gè)靜態(tài)廣播判斷的過程。
如果需要分析研究,要在上面的第四五步過程,進(jìn)行詳細(xì)的打印分析,應(yīng)該會(huì)有一下線索的。
目前沒時(shí)間進(jìn)一步進(jìn)行分析了,有搞懂的可以跟我說說哈!
4、其他靜態(tài)注冊(cè)無法生效的廣播
其實(shí)除了上面說明了 “only by explicitly registering for it” 的廣播,還有其他廣播也是有些會(huì)有靜態(tài)注冊(cè)無法生效的問題。
比如最近接觸的 只能動(dòng)態(tài)注冊(cè)的藍(lán)牙部分廣播:
BluetoothAdapter.ACTION_STATE_CHANGED: //藍(lán)牙開關(guān)
BluetoothAdapter.ACTION_SCAN_MODE_CHANGED: //藍(lán)牙掃描狀態(tài)修改
BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED: //藍(lán)牙連接詳細(xì)情況
BluetoothDevice.ACTION_BOND_STATE_CHANGED: //藍(lán)牙綁定狀態(tài)改變,綁定前后藍(lán)牙變化廣播
其他一些藍(lán)牙廣播是可以靜態(tài)注冊(cè)正常收到的。
所以說整個(gè)系統(tǒng)除了上面說的的廣播,可能還有些廣播是靜態(tài)注冊(cè)無效的。
如果要分析個(gè)所以然來還是要在上面的AMS加載流程中分析。
5、其他
Android framework 所有廣播的定義
//我們常用的廣播都定義在里面,如果要新增可以在里面新增
framework\base\core\res\AndroidManifest.xml<protected-broadcast android:name="android.intent.action.SCREEN_OFF" /><protected-broadcast android:name="android.intent.action.SCREEN_ON" /><protected-broadcast android:name="android.intent.action.USER_PRESENT" /><protected-broadcast android:name="android.intent.action.TIME_SET" /><protected-broadcast android:name="android.intent.action.TIME_TICK" /><protected-broadcast android:name="android.intent.action.TIMEZONE_CHANGED" /><protected-broadcast android:name="android.intent.action.DATE_CHANGED" /><protected-broadcast android:name="android.intent.action.PRE_BOOT_COMPLETED" />
靜態(tài)廣播注冊(cè)無效解決
其實(shí)沒啥好說的,靜態(tài)注冊(cè)無效的,動(dòng)態(tài)注冊(cè)就行了,可以在自己應(yīng)用寫一個(gè)服務(wù),
在服務(wù)類里面注冊(cè)一系列廣播,就可以了,也能保障界面退出還能繼續(xù)收到廣播。
詳解Android廣播Broadcast的啟動(dòng)流程
https://www.jb51.net/article/279551.htm#_label1
AMS 四大組件之 Broadcast流程分析
https://blog.csdn.net/zhaozhenhui_1990/article/details/119904083