android framework开发之广播broadcast源码分析2-千里马

107 篇文章 12 订阅
72 篇文章 0 订阅

hi,上一节我们主要分析了broadcast的发送部分,本节我们来分析一下接受部分,即一般我们作为一个广播接受者是怎么一步步被AMS发送过来的信息的。
一般我们注册成为一个广播监听接受者都是调用Context.java中的如下方法:

    public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,
                                            IntentFilter filter);

这里一样其实最后都会调用到ContextImpl.java中:

   @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        return registerReceiver(receiver, filter, null, null);
    }
       @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
            String broadcastPermission, Handler scheduler) {
        return registerReceiverInternal(receiver, getUserId(),
                filter, broadcastPermission, scheduler, getOuterContext(), 0);
    }

最后会调用到registerReceiverInternal方法:

 private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
        IIntentReceiver rd = null;
        if (receiver != null) {
            if (mPackageInfo != null && context != null) {
            //构造出IIntentReceiver
                rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);
            } 
        }
        try {
        //调用 ActivityManager对应的registerReceiver方法来注册到AMS且把rd传递进去
            final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);
            return intent;
        } 
    }

这里主要其实就分为2部分:
1、构造出一个IIntentReceiver对象

   rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);

这里会调用到getReceiverDispatcher方法:

public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
            Context context, Handler handler,
            Instrumentation instrumentation, boolean registered) {
        synchronized (mReceivers) {
            LoadedApk.ReceiverDispatcher rd = null;
            ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
            //判断是否已经缓存了对应的IIntentReceiver对象
            if (registered) {
                map = mReceivers.get(context);
                if (map != null) {
                    rd = map.get(r);
                }
            }
            //没有缓存则直接进行构造
            if (rd == null) {
                rd = new ReceiverDispatcher(r, context, handler,
                        instrumentation, registered);
                if (registered) {
                    if (map == null) {
                        map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                        mReceivers.put(context, map);
                    }
                    map.put(r, rd);
                }
            } else {
                rd.validate(context, handler);
            }
            rd.mForgotten = false;
            return rd.getIIntentReceiver();
        }
    }

这里应该比较容易看懂,就是简单的判断是否有缓存,没有就再进行构造,但是这里要注意哦,返回要求是IIntentReceiver类型,而new的是一个ReceiverDispatcher类型,那么这个IIntentReceiver是哪里构造来的呢?这里就要看ReceiverDispatcher构造源码了:

  ReceiverDispatcher(BroadcastReceiver receiver, Context context,
                Handler activityThread, Instrumentation instrumentation,
                boolean registered) {
            if (activityThread == null) {
                throw new NullPointerException("Handler must not be null");
            }

            mIIntentReceiver = new InnerReceiver(this, !registered);//这个地方new出来了这个InnerReceiver对象
            mReceiver = receiver;
            mContext = context;
            mActivityThread = activityThread;
            mInstrumentation = instrumentation;
            mRegistered = registered;
            mLocation = new IntentReceiverLeaked(null);
            mLocation.fillInStackTrace();
        }

这里的

 final static class InnerReceiver extends IIntentReceiver.Stub {
            final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
            final LoadedApk.ReceiverDispatcher mStrongRef;

            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
                mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                mStrongRef = strong ? rd : null;
            }

            @Override
            public void performReceive(Intent intent, int resultCode, String data,
                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) 
                //省略部分
                }
            }
        }

这里最后发现InnerReceiver其实是实现了IIntentReceiver.Stub 这个跨进程对象的一个实体,也就是我们说的Binder的实现端,服务端,因为这里我们注册广播属于接受者,当然是由客户端调用到我们这端,所以当然就是服务端。

2、调用 ActivityManager对应的registerReceiver方法来注册到AMS且把rd传递进去
这里就是调用了:

ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);

这个方法一看大家就应该知道最后会跨进程调用到AMS中:

 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) {
   //省略部分
        synchronized (this) {
           //省略部分
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            if (rl == null) {
            //根据receiver创建出一个ReceiverList,为啥是个List?因为很有可能一个Receiver可能接受多个广播
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
               //省略部分
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            } 
               //省略部分
               //构造出对应的BroadcastFilter,主要为了方便到时候发端方便寻找到这个接受端
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
            if (rl.containsFilter(filter)) {
               
            } else {
                rl.add(bf);//bf被添加到了对应的rl
                mReceiverResolver.addFilter(bf);
            }

           //省略部分
        }
    }

这里其实就是在AMS中把广播的对应ReceiverList创建出来,而且与Filter进行映射好,这样广播接受者在AMS中的注册就算完成

总结图如下:
在这里插入图片描述
最后宣传一下课程:

[入门课,实战课,跨进程专题
ps需要学习深入framework课程和课程优惠
(可以加我qq:2102309716 优惠购买)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值