歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android 為什麼動態廣播接收器比靜態廣播接收器要接受的早

如果,在短信攔截的軟件中,程序員們就發現了這個問題。 同一優先級的廣播接收器,動態的要比靜態注冊的早。

動態注冊:即由代碼注冊的廣播接收器

靜態注冊:即在 AndroidManifest.xml 中注冊的廣播接收器

優先級: 當廣播為有序發送的時候,要按這個排序並順序發送。

sendBroadcast 發送的是無序廣播。

sendOrderedBroadcast 發送的是有序廣播。

好了,現在尋找問題原因,在找原因前肯定有這樣的想法,一個有序隊列,既然允許有相同的優先級存在,那麼在同優先級內要不然有排序子因素,要不基就是按照某種操作可能影響順序。後者可能性很大。

打開源碼,順著 動態注冊廣播接受器 找,最後是 ActivityManagerService.java 這個文件找到了 registerReceiver 的實現。

同地也看到,存儲的廣播接收器列表是 HashMap mRegisteredReceivers 這個變理。

裡面有一段代碼為:

  1. ReceiverList rl  
  2.     = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());  
  3. if (rl == null) {  
  4.     rl = new ReceiverList(this, callerApp,  
  5.             Binder.getCallingPid(),  
  6.             Binder.getCallingUid(), receiver);  
  7.     if (rl.app != null) {  
  8.         rl.app.receivers.add(rl);  
  9.     } else {  
  10.         try {  
  11.             receiver.asBinder().linkToDeath(rl, 0);  
  12.         } catch (RemoteException e) {  
  13.             return sticky;  
  14.         }  
  15.         rl.linkedToDeath = true;  
  16.     }  
  17.     mRegisteredReceivers.put(receiver.asBinder(), rl);  
  18. }  

在裡面查找有沒有這個 Receiver , 如果沒有 put 進去。 

看到這裡貌似沒有對廣播的順序做處理。是不是有別的地方做排序呢,找找成員變理,發現一個可疑的變量:

final ArrayList<BroadcastRecord> mOrderedBroadcasts

沒錯,感覺就應該是它了。 

找找對它的操作,只有一處 mOrderedBroadcasts.set ,把代碼摘錄一下: 

 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
                    callerPackage, callingPid, callingUid, requiredPermission,
                    receivers, resultTo, resultCode, resultData, map, ordered,
                    sticky, false); 

mOrderedBroadcasts.set(i, r);

在這裡放入了一個 BroadcastRecord 對像,而這個對像中主要的東西其實是 receivers

向上跟蹤

  1. int NT = receivers != null ? receivers.size() : 0;  
  2. int it = 0;  
  3. ResolveInfo curt = null;  
  4. BroadcastFilter curr = null;  
  5. while (it < NT && ir < NR) {  
  6.     if (curt == null) {  
  7.         curt = (ResolveInfo)receivers.get(it);  
  8.     }  
  9.     if (curr == null) {  
  10.         curr = registeredReceivers.get(ir);  
  11.     }  
  12.     if (curr.getPriority() >= curt.priority) {  
  13.         // Insert this broadcast record into the final list.   
  14.         receivers.add(it, curr);  
  15.         ir++;  
  16.         curr = null;  
  17.         it++;  
  18.         NT++;  
  19.     } else {  
  20.         // Skip to the next ResolveInfo in the final list.   
  21.         it++;  
  22.         curt = null;  
  23.     }  
  24. }  

發現了一段 對 receivers 排序的代碼,並且判斷也是 priority 的值,用的是 >=  方式

感覺的找到了地方,但是對 Activity Manager Service 這個模塊卻更加的不懂了,以後有機會一定要分析一下這塊是怎樣設計的,才能確定本文的問題所在。

Copyright © Linux教程網 All Rights Reserved