歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android 為什麼動態廣播接收器比靜態廣播接收器要接受的早

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

日期:2017/3/1 11:12:07   编辑:Linux編程

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

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

靜態注冊:即在 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