Android广播机制(3) 粘性广播的内部机制

要了解粘性广播,我们只需要简单地学习粘性广播用到的几个关键的类与结构
源码路径:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

只需要分析下广播的注册函数即可,因为我们知道粘性广播是在注册的时候马上返回的,下面的函数我只保留与粘性广播关键的部分

 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
        ArrayList<Intent> stickyIntents = null;  //粘性广播
            int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
            while (actions.hasNext()) {
                String action = actions.next();
                for (int id : userIds) {//mStickyBroadcasts保留着系统所有的粘性广播
                    ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
                    if (stickies != null) {
                        ArrayList<Intent> intents = stickies.get(action);  
                        if (intents != null) {
                            if (stickyIntents == null) {
                                stickyIntents = new ArrayList<Intent>();   
                            }
                            stickyIntents.addAll(intents);
                        }
                    }
                }
            }
        }
        //到此为止stickyIntents是系统中所有的粘性的intent

        ArrayList<Intent> allSticky = null;
        if (stickyIntents != null) {
            final ContentResolver resolver = mContext.getContentResolver();
            // Look for any matching sticky broadcasts...
            for (int i = 0, N = stickyIntents.size(); i < N; i++) {
                Intent intent = stickyIntents.get(i);
                // If intent has scheme "content", it will need to acccess
                // provider that needs to lock mProviderMap in ActivityThread
                // and also it may need to wait application response, so we
                // cannot lock ActivityManagerService here.
                if (filter.match(resolver, intent, true, TAG) >= 0) {
                    if (allSticky == null) {
                        allSticky = new ArrayList<Intent>();
                    }
                    allSticky.add(intent); 
                }
            }
        }
        //allSticky就是与本次注册intentfilter匹配的粘性广播
 
            if (allSticky != null) {
                ArrayList receivers = new ArrayList();
                receivers.add(bf);

                final int stickyCount = allSticky.size();
                for (int i = 0; i < stickyCount; i++) {
                    Intent intent = allSticky.get(i);   //处理粘性广播
                    BroadcastQueue queue = broadcastQueueForIntent(intent);
                    BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                            null, -1, -1, null, null, AppOpsManager.OP_NONE, null, receivers,
                            null, 0, null, null, false, true, true, -1);
                    queue.enqueueParallelBroadcastLocked(r);
                    queue.scheduleBroadcastsLocked();
                }
            }

            return sticky;
        }
    }

比较关键的数据结构是
1.mStickyBroadcasts,key是用户的id,data是广播intent数组。由此可见,粘性广播是分用户的,用户1发出的粘性广播,用户2可能收不到。
2.stickyIntents 保存的是系统所有粘性广播intent
3.allSticky 保存的是与本次registerReceiver(BroadcastReceiver receiver, IntentFilter intent)中intent匹配的粘性广播的intent

为了直观看到这三者,可以是用adb shell dumpsys activity -a 命令查看

  Sticky broadcasts for user 0:

  * Sticky action com.android.ims.IMS_SERVICE_DOWN:

    Intent: act=com.android.ims.IMS_SERVICE_DOWN flg=0x20000010

      Bundle[mParcelledData.dataSize=52]

  * Sticky action com.example.stickybroadcastdemo.stickybrocast:

    Intent: act=com.example.stickybroadcastdemo.stickybrocast flg=0x10

  * Sticky action com.android.ims.IMS_SERVICE_UP:

    Intent: act=com.android.ims.IMS_SERVICE_UP flg=0x20000010

      Bundle[mParcelledData.dataSize=52]

  * Sticky action com.google.android.apps.gmm.NAVIGATION_STATE:

    Intent: act=com.google.android.apps.gmm.NAVIGATION_STATE flg=0x10 pkg=com.google.android.googlequicksearchbox

      Bundle[mParcelledData.dataSize=248]

    Intent: act=com.google.android.apps.gmm.NAVIGATION_STATE flg=0x10 pkg=com.google.android.gms

      Bundle[mParcelledData.dataSize=248]

上面是user 0的粘性广播,其中的Sticky action com.example.stickybroadcastdemo.stickybrocast就是通过代码实现的

sendStickyBroadcast(new Intent("com.example.stickybroadcastdemo.stickybrocast"));  //发送粘性广播
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容