Android廣播有兩個很重要的要素: android
1 廣播 - 用於發送廣播 app
有序廣播 - 被廣播接收器接收後,可被終止,沒法往下繼續傳達。 典型表明:短信廣播 ui
普通廣播 - 發送至每個已經註冊(訂閱)的廣播接收器,沒法被終止。 典型表明:開機啓動廣播 this
2 廣播接收器 - 用於訂閱廣播後接收廣播 spa
靜態註冊廣播 - 在AndroidManifest.xml中設置,程序不用啓動亦可接收。 典型表明:不少開機啓動的APP,都是接收開機啓動廣播帶起服務的。 rest
動態註冊廣播 - 代碼中註冊廣播,程序未啓動時,沒法接收廣播。 典型表明:Go短信,將Go短信強行中止,Go短信沒法接收短信。 code
廣播註冊過程和接收廣播順序過程 component
圖1 註冊廣播流程簡圖 xml
靜態廣播接收器 由PackageManagerService負責,當手機啓動時(或者新安裝了應用),PackageManagerService負責掃描手機中全部已安裝的APP應用(題外話,肯定再也不使用的APP須要卸載了),將AndroidManifest.xml中 有關注冊廣播的信息 解析出來,存儲至一個全局靜態變量當中 mReceivers。 blog
須要注意的是:
1 PackageManagerService掃描目錄的順序以下:
system/framework
system/app
vendor/app
data/app
drm/app-private
2 當處於同一目錄下時:按照file.list()的返回順序。(題外話:由於在data/app下的應用都是用戶安裝的,而且都是以com.xxx.xxx-1.apk 的形式出現,因此若是打算作手機管家之類的應用,須要好好的研究下包名,爭取在file.list()的獨木橋下搶的頭籌---優先接收開機啓動完成的廣播。)
3 在此處並未對 接收順序作完整的排序。(注意修飾詞完整的,畢竟先掃描的固然會有必定優先級)
動態廣播接收器 由ActivityManagerService負責,當APP的服務或者進程起來以後,執行了註冊廣播接收的代碼邏輯,即進行加載,最後會存儲在一個全局靜態變量
mReceiverResolver中。
須要注意的是:
1 這個並不是是一成不變的,當程序被殺死以後, 已註冊的動態廣播接收器也會被移出mReceiverResolver,直到下次程序啓動,再進行動態廣播的註冊,固然這裏面的順序也已經變動了一次。
2 這裏也並沒完整的進行廣播的排序,只記錄的註冊的前後順序,並未有結合優先級的處理。
當有廣播發出時,接收順序以下:
接下來請看代碼以片斷:
1 private final int broadcastIntentLocked(ProcessRecord callerApp, 2 String callerPackage, Intent intent, String resolvedType, 3 IIntentReceiver resultTo, int resultCode, String resultData, 4 Bundle map, String requiredPermission, 5 boolean ordered, boolean sticky, int callingPid, int callingUid) { 6 7 ………… 8 ………… 9 10 // 靜態廣播接收器list 11 List receivers = null; 12 13 // 動態廣播接收器List 14 List<BroadcastFilter> registeredReceivers = null; 15 16 // 獲取靜態廣播接收器mReceivers 17 try { 18 if (intent.getComponent() != null) { 19 // Broadcast is going to one specific receiver class... 20 ActivityInfo ai = AppGlobals.getPackageManager(). 21 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS); 22 if (ai != null) { 23 receivers = new ArrayList(); 24 ResolveInfo ri = new ResolveInfo(); 25 ri.activityInfo = ai; 26 receivers.add(ri); 27 } 28 } else { 29 // Need to resolve the intent to interested receivers... 30 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) 31 == 0) { 32 receivers = 33 AppGlobals.getPackageManager().queryIntentReceivers( 34 intent, resolvedType, STOCK_PM_FLAGS); 35 } 36 // 獲取動態廣播接收器mReceiverResolver 37 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false); 38 } 39 } catch (RemoteException ex) { 40 // pm is in same process, this will never happen. 41 } 42 43 final boolean replacePending = 44 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0; 45 46 int NR = registeredReceivers != null ? registeredReceivers.size() : 0; 47 …… 48 // 若是接收到的廣播 是普通廣播。 49 if (!ordered && NR > 0) { 50 // If we are not serializing this broadcast, then send the 51 // registered receivers separately so they don't wait for the 52 // components to be launched. 53 BroadcastRecord r = new BroadcastRecord(intent, callerApp, 54 callerPackage, callingPid, callingUid, requiredPermission, 55 registeredReceivers, resultTo, resultCode, resultData, map, 56 ordered, sticky, false); 57 58 // 很明顯接收到普通廣播以後,在這隻處理了動態廣播 registeredReceivers,對於普通廣播而言,動態廣播接收器要優先於靜態廣播接收器 無關設置的優先級 59 boolean replaced = false; 60 if (replacePending) { 61 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) { 62 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) { 63 if (DEBUG_BROADCAST) Slog.v(TAG, 64 "***** DROPPING PARALLEL: " + intent); 65 mParallelBroadcasts.set(i, r); 66 replaced = true; 67 break; 68 } 69 } 70 } 71 if (!replaced) { 72 mParallelBroadcasts.add(r); 73 scheduleBroadcastsLocked(); 74 } 75 //將registeredReceivers置爲null,後面只處理靜態廣播接收器,因此不會有衝突。 76 registeredReceivers = null; 77 NR = 0; 78 } 79 80 //若是是有序廣播,將靜態廣播接收器和動態廣播接收器組合成一個最終的順序 81 int ir = 0; 82 if (receivers != null) { 83 ... 84 //合併的過程,注意順序 85 int NT = receivers != null ? receivers.size() : 0; 86 int it = 0; 87 ResolveInfo curt = null; 88 BroadcastFilter curr = null; 89 while (it < NT && ir < NR) { 90 if (curt == null) { 91 curt = (ResolveInfo)receivers.get(it); 92 } 93 if (curr == null) { 94 curr = registeredReceivers.get(ir); 95 } 96 //若是動態廣播接收器優先級高於或者等於靜態廣播接收器,那麼就插到前面 97 //很明顯動態的要在靜態的前面 98 if (curr.getPriority() >= curt.priority) { 99 // Insert this broadcast record into the final list. 100 receivers.add(it, curr); 101 ir++; 102 curr = null; 103 it++; 104 NT++; 105 } else { 106 // Skip to the next ResolveInfo in the final list. 107 it++; 108 curt = null; 109 } 110 } 111 }
最後舉個例子:
(如下的靜A 表示靜態廣播接收器,同理動B。)
1 靜A (優先級1)
2 動B(優先級1)
3 靜C (優先級2,後掃描)
4 靜D (優先級2,先掃描)
5 動E (優先級2,先註冊)
6 動F (優先級2,後註冊)
當來了一個 有序廣播,接收順序以下:動E > 動F > 靜D > 靜C > 動B > 靜A
當來了一個 普通廣播,接收順序以下:動E > 動F > 動B > 靜D > 靜C > 靜A