Android源码笔记--BroadcastReceiver管理

1.BroadcastReceiver的理解

        BroadcastReceiver本质就是通过Intent来执行应用中的一个方法,在应用中不需要长期存在。BroadcastReceiver可以分两类:1.1 静态接收者 1.2 动态接收者,如果不需要接收广播了,可以通过unregisterReceiver()接口取消注册。BroadcastReceiver的onReceive()方法如果长时间不返回,会引发ANR,因此如果要执行耗时的操作,必须在其他线程中完成,并且不建议在广播中new线程。广播从发送的方式来划分:1.3 普通广播(无序广播) 1.4有序广播(串行广播) 1.5粘性广播:能发给系统中以后注册的接收者,甚至是新安装的应用中的接收者,而前面两种广播只能发给系统已经注册的接收者。粘性广播有两种,一种是普通粘性广播,通过sendStickyBroadcast()方法发送,另一种是有序粘性广播,通过sendStickyOrderedBroadcast()方法发送。

2.广播的注册流程

MainActivity.java中广播注册过程

BroadcastReceiver mBroadcastReceiver = new MyBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BROADCAST_ACTION);
        registerReceiver(mBroadcastReceiver, intentFilter);
		
 class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
        }
    }
#ContextWrapper
@Override
    public Intent registerReceiver(
        BroadcastReceiver receiver, IntentFilter filter) {
        return mBase.registerReceiver(receiver, filter);
    }	
#Context
@Nullable
    public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,
                                            IntentFilter filter);

#ContextImpl

 @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());
    }
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) {
    IIntentReceiver rd = null;
    if (receiver != null) {
        if (mPackageInfo != null && context != null) {
            if (scheduler == null) {
                //将主线程Handler赋予scheuler
                scheduler = mMainThread.getHandler();
            }
            //获取IIntentReceiver对象
            rd = mPackageInfo.getReceiverDispatcher(
                receiver, context, scheduler,
                mMainThread.getInstrumentation(), true);
        } else {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            }
            rd = new LoadedApk.ReceiverDispatcher(
                  receiver, context, scheduler, null, true).getIIntentReceiver();
        }
    }
    try {
        //调用AMP.registerReceiver 
        return ActivityManagerNative.getDefault().registerReceiver(
                mMainThread.getApplicationThread(), mBasePackageName,
                rd, filter, broadcastPermission, userId);
    } catch (RemoteException e) {
        return null;
    }
}

#LoadedApk.java

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;
        //此处registered=true,则进入该分支
        if (registered) {
            map = mReceivers.get(context);
            if (map != null) {
                rd = map.get(r);
            }
        }

        if (rd == null) {
            //当广播分发者为空,则创建ReceiverDispatcher
            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 {
            //验证广播分发者的context、handler是否一致
            rd.validate(context, handler);
        }
        rd.mForgotten = false;
        //获取IIntentReceiver对象
        return rd.getIIntentReceiver();
    }
}

ActivityManagerNative.getDefault()返回的是ActivityManagerProxy对象,简称AMP. 该方法中参数有mMainThread.getApplicationThread()返回的是ApplicationThread。

# ActivityManagerNative

 public Intent registerReceiver(IApplicationThread caller, String packageName,
            IIntentReceiver receiver,
            IntentFilter filter, String perm, int userId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(packageName);
        data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
        filter.writeToParcel(data, 0);
        data.writeString(perm);
        data.writeInt(userId);
		//向服务端AMS发起注册广播的动作
        mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
        reply.readException();
        Intent intent = null;
        int haveIntent = reply.readInt();
        if (haveIntent != 0) {
            intent = Intent.CREATOR.createFromParcel(reply);
        }
        reply.recycle();
        data.recycle();
        return intent;
    }
#ActivityManagerService
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) {
       ...
        int callingUid;
        int callingPid;
        boolean instantApp;
        synchronized(this) {
            if (caller != null) {
			//查询调用者的进程信息
                callerApp = getRecordForAppLocked(caller);
               ...
            instantApp = isInstantApp(callerApp, callerPackage, callingUid);
            userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                    ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
			//获取IntentFilter中的actions,就是在intentFilter.addAction(BROADCAST_ACTION);中需要
			//监听的广播action
            Iterator<String> actions = filter.actionsIterator();
            if (actions == null) {
                ArrayList<String> noAction = new ArrayList<String>(1);
                noAction.add(null);
                actions = noAction.iterator();
            }
		...
    ArrayList<Intent> allSticky = null;
      if (stickyIntents != null) {
        final ContentResolver resolver = mContext.getContentResolver();
        for (int i = 0, N = stickyIntents.size(); i < N; i++) {
            Intent intent = stickyIntents.get(i);
            //查询匹配的sticky广播 
            if (filter.match(resolver, intent, true, TAG) >= 0) {
                if (allSticky == null) {
                    allSticky = new ArrayList<Intent>();
                }
                //匹配成功,则将给intent添加到allSticky队列
                allSticky.add(intent);
            }
        }
    }
    //当IIntentReceiver为空,则直接返回第一个sticky Intent,
    Intent sticky = allSticky != null ? allSticky.get(0) : null;
    if (receiver == null) {
        return sticky;
    }
        synchronized (this) {
          //创建BroadcastFilter对象,并添加到接收者队列
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
            rl.add(bf);
            if (!bf.debugCheck()) {
                Slog.w(TAG, "==> For Dynamic broadcast");
            }
			 //新创建的广播过滤者,添加到ReceiverResolver队列
            mReceiverResolver.addFilter(bf);

            // Enqueue broadcasts for all existing stickies that match
            // this filter.
			 //所有匹配该filter的sticky广播执行入队操作
            //如果没有使用sendStickyBroadcast,则allSticky=null。
            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);
					//根据intent返回前台或后台广播队列
                    BroadcastQueue queue = broadcastQueueForIntent(intent);
					//创建BroadcastRecord
                    BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                            null, -1, -1, false, null, null, AppOpsManager.OP_NONE, null, receivers,
                            null, 0, null, null, false, true, true, -1);
					//该广播加入到并行广播队列
                    queue.enqueueParallelBroadcastLocked(r);
					//调度广播,发送BROADCAST_INTENT_MSG消息,触发处理下一个广播。
                    queue.scheduleBroadcastsLocked();
                }
            }
            return sticky;
        }
    }
# IntentFilter
public final int match(ContentResolver resolver, Intent intent,
            boolean resolve, String logTag) {
        String type = resolve ? intent.resolveType(resolver) : intent.getType();
        return match(intent.getAction(), type, intent.getScheme(),
                     intent.getData(), intent.getCategories(), logTag);
    }
public final int match(String action, String type, String scheme,
            Uri data, Set<String> categories, String logTag) {
		//不存在匹配的action
        if (action != null && !matchAction(action)) {
            if (false) Log.v(
                logTag, "No matching action " + action + " for " + this);
            return NO_MATCH_ACTION;
        }
		 //不存在匹配的type或data
        int dataMatch = matchData(type, scheme, data);
        if (dataMatch < 0) {
           ...
            return dataMatch;
        }
		//不存在匹配的category
        String categoryMismatch = matchCategories(categories);
        if (categoryMismatch != null) {
            if (false) {
                Log.v(logTag, "No matching category " + categoryMismatch + " for " + this);
            }
            return NO_MATCH_CATEGORY;
        }
        // It would be nice to treat container activities as more
        // important than ones that can be embedded, but this is not the way...
        if (false) {
            if (categories != null) {
                dataMatch -= mCategories.size() - categories.size();
            }
        }
        return dataMatch;
    }
2 广播的发送过程
#ContextImpl.java
public void sendBroadcast(Intent intent) {
    warnIfCallingFromSystemProcess();
    String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
    try {
        intent.prepareToLeaveProcess();
        // 调用AMP.broadcastIntent 
        ActivityManagerNative.getDefault().broadcastIntent(
                mMainThread.getApplicationThread(), intent, resolvedType, null,
                Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                getUserId());
    } catch (RemoteException e) {
        ...
    }
}
#ActivityManagerNative.java
public int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String[] requiredPermissions, int appOp, Bundle options, boolean serialized, boolean sticky, int userId) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    intent.writeToParcel(data, 0);
    data.writeString(resolvedType);
    data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
    data.writeInt(resultCode);
    data.writeString(resultData);
    data.writeBundle(map);
    data.writeStringArray(requiredPermissions);
    data.writeInt(appOp);
    data.writeBundle(options);
    data.writeInt(serialized ? 1 : 0);
    data.writeInt(sticky ? 1 : 0);
    data.writeInt(userId);

    mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
    reply.readException();
    int res = reply.readInt();
    reply.recycle();
    data.recycle();
    return res;
} 
#ActivityManagerService.java
public final int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle options, boolean serialized, boolean sticky, int userId) {
    enforceNotIsolatedCaller("broadcastIntent");
    synchronized(this) {
        //验证广播intent是否有效
        intent = verifyBroadcastLocked(intent);
        //获取调用者进程记录对象
        final ProcessRecord callerApp = getRecordForAppLocked(caller);
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
   
        int res = broadcastIntentLocked(callerApp,
                callerApp != null ? callerApp.info.packageName : null,
                intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                requiredPermissions, appOp, null, serialized, sticky,
                callingPid, callingUid, userId);
        Binder.restoreCallingIdentity(origId);
        return res;
    }
}
# ActivityManagerService
private final int broadcastIntentLocked(ProcessRecord callerApp,
			String callerPackage, Intent intent, String resolvedType,
			IIntentReceiver resultTo, int resultCode, String resultData,
			Bundle map, String requiredPermission,
			boolean ordered, boolean sticky, int callingPid, int callingUid) {
		intent = new Intent(intent);
		......
		// Figure out who all will receive this broadcast.
		List receivers = null;
		List<BroadcastFilter> registeredReceivers = null;
		try {
			if (intent.getComponent() != null) {
				......
			} else {
				......
				//首先是根据intent找出相应的广播接收器
				registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
			}
		} catch (RemoteException ex) {
			......
		}
		//查看有没有相同的intent还未被处理,如果有的话,就有当前这个新的intent来替换旧的intent
		final boolean replacePending =
			(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
 
		int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
		if (!ordered && NR > 0) {
			// If we are not serializing this broadcast, then send the
			// registered receivers separately so they don't wait for the
			// components to be launched.
			BroadcastRecord r = new BroadcastRecord(intent, callerApp,
				callerPackage, callingPid, callingUid, requiredPermission,
				registeredReceivers, resultTo, resultCode, resultData, map,
				ordered, sticky, false);
			......
			boolean replaced = false;
			if (replacePending) {
				for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
					if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
						......
						mParallelBroadcasts.set(i, r);
						replaced = true;
						break;
					}
				}
			}
 //得到的replaced变量的值也为false,于是,就会把这个广播记录块r放在ActivityManagerService的成员变量mParcelBroadcasts中,
 //等待进一步处理;进一步处理的操作由函数scheduleBroadcastsLocked进行
			if (!replaced) {
				mParallelBroadcasts.add(r); 
				scheduleBroadcastsLocked();
			}
 
			registeredReceivers = null;
			NR = 0;
		}
}
private final void scheduleBroadcastsLocked() {
		......
 
		if (mBroadcastsScheduled) {
			return;
		}
 
		mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
		mBroadcastsScheduled = true;
	}
}

      这里的mBroadcastsScheduled表示ActivityManagerService当前是不是正在处理其它广播,如果是的话,这里就先不处理直返回了,保证所有广播串行处理。注意这里处理广播的方式,它是通过消息循环来处理,每当ActivityManagerService接收到一个广播时,它就把这个广播放进自己的消息队列去就完事了,根本不管这个广播后续是处理的,因此,这里我们可以看出广播的发送和处理是异步的。这里的成员变量mHandler是一个在ActivityManagerService内部定义的Handler类变量,通过它的sendEmptyMessage函数把一个类型为BROADCAST_INTENT_MSG的空消息放进ActivityManagerService的消息队列中去。这里的空消息是指这个消息除了有类型信息之外,没有任何其它额外的信息,因为前面已经把要处理的广播信息都保存mParcelBroadcasts中了,等处理这个消息时,从mParcelBroadcasts就可以读回相关的广播信息了.

#ActivityManagerService

final Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			......
			case BROADCAST_INTENT_MSG: {
				......
				processNextBroadcast(true);
			} break;
			......
			}
		}
	}
private final void processNextBroadcast(boolean fromMsg) {
		synchronized(this) {
			BroadcastRecord r;
			......
			if (fromMsg) {
				mBroadcastsScheduled = false;
			}
			// First, deliver any non-serialized broadcasts right away.
			while (mParallelBroadcasts.size() > 0) {
				r = mParallelBroadcasts.remove(0);
				......
				final int N = r.receivers.size();
				......
				for (int i=0; i<N; i++) {
					Object target = r.receivers.get(i);
					......
					deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
				}
				addBroadcastToHistoryLocked(r);
	......
}

       这里传进来的参数fromMsg为true,于是把mBroadcastScheduled重新设为false,这样,下一个广播就能进入到消息队列中进行处理了。广播记录块BroadcastRecord的receivers列表中包含了要接收这个广播的目标列表,即前面我们注册的广播接收器,用BroadcastFilter来表示,这里while循环中的for循环就是把这个广播发送给每一个订阅了该广播的接收器了,通deliverToRegisteredReceiverLocked函数执行.

#ActivityManagerService

private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
			BroadcastFilter filter, boolean ordered) {
		boolean skip = false;
		...
			try {
				......
				performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
					new Intent(r.intent), r.resultCode,
					r.resultData, r.resultExtras, r.ordered, r.initialSticky);
				......
			} catch (RemoteException e) {
				......
	......
}
static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
			Intent intent, int resultCode, String data, Bundle extras,
			boolean ordered, boolean sticky) throws RemoteException {
		// Send the intent to the receiver asynchronously using one-way binder calls.
		if (app != null && app.thread != null) {
			// If we have an app thread, do the call through that so it is
			// correctly ordered with other one-way calls.
			app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
					data, extras, ordered, sticky);
		} else {
			......
		}
	}
注:没标明类的方法说明最近的类相同。

#ActivityThread #ApplicationThreadProxy

public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                int resultCode, String dataStr, Bundle extras, boolean ordered,
                boolean sticky, int sendingUser, int processState) throws RemoteException {
            updateProcessState(processState, false);
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

#LoadedApk   #InnerReceiver

final class LoadedApk {  
	...... 
	static final class ReceiverDispatcher {  
 
		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) {
                final LoadedApk.ReceiverDispatcher rd;
                if (intent == null) {
                    Log.wtf(TAG, "Null intent received");
                    rd = null;
                } else {
                    rd = mDispatcher.get();
                }
             ...
                if (rd != null) {
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                } else {
                    ...
                    IActivityManager mgr = ActivityManagerNative.getDefault();
                    try {
                        if (extras != null) {
                            extras.setAllowFds(false);
                        }
                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }
	}
#InnerReceiver
public void performReceive(Intent intent, int resultCode, String data,
                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            final Args args = new Args(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
            if (intent == null) {
                Log.wtf(TAG, "Null intent received");
            } else {
                if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                    Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
                            + " seq=" + seq + " to " + mReceiver);
                }
            }
            if (intent == null || !mActivityThread.post(args)) {
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManagerNative.getDefault();
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing sync broadcast to " + mReceiver);
                    args.sendFinished(mgr);
                }
            }
        }
}	
final class LoadedApk { 		
static final class ReceiverDispatcher {
		......
		final class Args implements Runnable {
			......
			public void run() {
				BroadcastReceiver receiver = mReceiver;
				Intent intent = mCurIntent;
			
				try {
					ClassLoader cl =  mReceiver.getClass().getClassLoader();
					intent.setExtrasClassLoader(cl);
					if (mCurMap != null) {
						mCurMap.setClassLoader(cl);
					}
					receiver.setOrderedHint(true);
					receiver.setResult(mCurCode, mCurData, mCurMap);
					receiver.clearAbortBroadcast();
					receiver.setOrderedHint(mCurOrdered);
					receiver.setInitialStickyHint(mCurSticky);
					receiver.onReceive(mContext, intent);
				} catch (Exception e) {
	}
}		
      这里的receiver是ReceiverDispatcher类的成员变量,它的类型是BroadcastReceiver,这里它就是MainActivity注册广播接收器时创建的BroadcastReceiver实例了。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值