Android学习笔记 - 广播的注册与接收

这篇具有很好参考价值的文章主要介绍了Android学习笔记 - 广播的注册与接收。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、简介

二、广播接收器的注册


一、简介

广播是Android四大组件之一,是以intent为媒介在组件间进行传播数据的一种机制。

从整体来看,广播主要有三个动作和三个角色。三个动作包含“注册广播接收器”、“发送广播”和“接收广播”;三个动作包含发送方、接收方和中间人。三者关系如下图:

Android学习笔记 - 广播的注册与接收

AMS在其中就是扮演"中间人"的角色。Receiver向AMS注册广播,AMS需要将所有必要的信息以一定的形式记录下来,当Sender发送广播以后,AMS根据广播的信息从数据容器中找到注册该广播的Receiver的信息。此外AMS还要对一些特殊情况进行处理,例如:广播是否被及时消费,如果超时会产生ANR等。


二、广播的注册

实际上,广播的注册最终是由AMS实现的,receiver只需要提供要注册信息(例如:需要监听的广播)即可。

下面列表中的信息便是receiver从AMS中获取到的信息:

Android学习笔记 - 广播的注册与接收

广播的注册分为静态注册和动态注册两种注册方式。

静态注册就是在AndroidManifest文件中注册广播接收器相关信息(BroadcastReceiver和intent-filter),然后在应用安装的时候通过PKMS(PackageManagerService)进行解析,来完成注册。

动态注册是把BroadcastReceiver包装成一个Binder对象,然后创建一个包含BroadcastReceiver和IntentFilter的BroadcastFilter对象,最后将BroadcastFilter对象加入到AMS中的mReceiverResolver变量中。具体流程请看下图:

Android学习笔记 - 广播的注册与接收

  • 当我们需要动态注册广播时,需要调用Context的registerReceiver方法,然后在ContextWrapper的registerReceiver中调用ContextImpl的registerReceiverInternal方法,最终调用其registerReceiver方法。
  @Override
  public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
                                 String broadcastPermission, Handler scheduler, int flags) {
      // 最后调用registerReceiverInternal()方法
      return registerReceiverInternal(receiver, getUserId(),
              filter, broadcastPermission, scheduler, getOuterContext(), flags);
  }

  private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
                                          IntentFilter filter, String broadcastPermission,
                                          Handler scheduler, Context context, int flags) {
      IIntentReceiver rd = null;
      // 将BroadcastReceiver存储到LoadedApk.ReceiverDispatcher对象里,
      // 并通过LoadedApk.ReceiverDispatcher.InnerReceiver的Binder对象和AMS进行通信
      if (receiver != null) {
          if (mPackageInfo != null && context != null) {
              if (scheduler == null) {
                  scheduler = mMainThread.getHandler();
              }
              // 获取IntentReceiver Binder对象
              rd = mPackageInfo.getReceiverDispatcher(
                      receiver, context, scheduler,
                      mMainThread.getInstrumentation(), true);
          } else {
              if (scheduler == null) {
                  scheduler = mMainThread.getHandler();
              }
              // 获取IntentReceiver Binder对象
              rd = new LoadedApk.ReceiverDispatcher(
                      receiver, context, scheduler, null, true).getIIntentReceiver();
          }
      }
      try {
          // 调用AMS.registerReceiverWithFeature
          final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
                  mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
                  filter, broadcastPermission, userId, flags);
          if (intent != null) {
              intent.setExtrasClassLoader(getClassLoader());
              intent.prepareToEnterProcess();
          }
          return intent;
      } catch (RemoteException e) {
          throw e.rethrowFromSystemServer();
      }
  }

}
  • 在ContextImpl的registerReceiverInternal方法中,通过LoadedApk类型的mPackageInfo对象的getReceiverDispatcher方法来获取IIntentReceiver类型的rd对象,用于广播的跨进程服务。然后调用AMS的registerReceiverWithFeature方法,并将rd对象作为参数传入。
public class ActivityManagerService extends IActivityManager.Stub {

  public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
                                            String callerFeatureId, IIntentReceiver receiver, IntentFilter filter,
                                            String permission, int userId, int flags) {
      //...
      synchronized (this) {
          // 根据IntentReceiver查看缓存中是否有ReceiverList
          ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
          // 创建一个新的ReceiverList,并把IntentReceiver传入其中
          if (rl == null) {
              rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                      userId, receiver);
              mRegisteredReceivers.put(receiver.asBinder(), rl); // 增加到缓存中
          }
          // 创建一个BroadcastFilter对象,并把ReceiverList对象和IntentFilter对象传入其中
          BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
                  permission, callingUid, userId, instantApp, visibleToInstantApps);
          // 向ReceiverList对象增加BroadcastFilter对象
          rl.add(bf);
          // 向mReceiverResolver变量增加BroadcastFilter对象
          mReceiverResolver.addFilter(bf);
          
          // ...
          return sticky;
      }
  }

}

在AMS的registerReceiverWithFeature方法中首先获取ReceiverList集合,该集合用于存储广播接收器,然后再创建一个用于描述注册的广播接收器,并添加到ReceiverList中,最后将BroadcastFilter添加到mReceiverResolver中,这样AMS接收到广播时就可以从mReceiverResolver中找到对应的广播接收者。


三、广播的发送

广播可以发出多种类型:

普通广播(无序广播):使用sendBroadcast发送的广播,这种广播可以依次传递到各个处理器处理。

有序广播:使用sendOrderedBroadcast发送广播。这种广播在处理器端的处理顺序是按照处理器的不同优先级来区分的,高优先级的处理器会优先解获这个信息,并且可以将这个信息删除。

粘性广播:使用sendStickyBroadcast发送广播。粘性广播在发送后就一直存在于系统的消息容器中,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则移植在消息容器中处于等待状态,粘性广播的receiver如果被销毁,那么下次重建时会自动接收到消息数据。

注意:普通广播和粘性广播不能被截获,而有序广播是可以被截获的。

下面是广播发送的流程图:

Android学习笔记 - 广播的注册与接收

从图中我们可以看出,广播的发送分为两个部分,分别是ContextImpl --> AMS,AMS --> BroadcastReceiver。

接下来我就以无序广播作为例子进行叙述:

ContextImpl到AMS的调用过程

 当我们需要发送无序广播时,需要调用context的sendBroadcast方法,然后在ContextWrapper的sendBroadcast中调用ContextImpl的sendBroadcast方法,最终调用AMS的broadcastIntentWithFeature方法。

ContextWrapper.sendBroadcast()方法源码:

public class ContextWrapper extends Context {                                                             
                                                                                                        
  Context mBase;                                                                                        
                                                                                                        
  @Override                                                                                             
  public void sendBroadcast(Intent intent) {                                                            
      mBase.sendBroadcast(intent);                                                                      
  }                                                                                                     
                                                                                                        
  @Override                                                                                             
  public void sendBroadcast(Intent intent, String receiverPermission) {                                 
      mBase.sendBroadcast(intent, receiverPermission);                                                  
  }                                                                                                     
}

ContextImpl.sendBroadcast()源码:

class ContextImpl extends Context {                                                                       
                                                                                                        
  public void sendBroadcast(Intent intent) {                                                            
      warnIfCallingFromSystemProcess();                                                                 
      String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());                           
      try {                                                                                             
          intent.prepareToLeaveProcess(this);                                                           
          // 调用AMS的broadcastIntentWithFeature方法                                                         
          ActivityManager.getService().broadcastIntentWithFeature(                                      
                  mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,        
                  null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false,       
                  false, getUserId());                                                                  
      } catch (RemoteException e) {                                                                     
          throw e.rethrowFromSystemServer();                                                            
      }                                                                                                 
  }

ContextImpl.sendBroadcast()中最后还是调用了AMS中的broadcastIntentWithFeature()方法。

ActivityManagerService.broadcastIntentWithFeature()源码:

public class ActivityManagerService extends IActivityManager.Stub {

  public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
                                              Intent intent, String resolvedType, IIntentReceiver resultTo,
                                              int resultCode, String resultData, Bundle resultExtras,
                                              String[] requiredPermissions, int appOp, Bundle bOptions,
                                              boolean serialized, boolean sticky, int userId) {
      enforceNotIsolatedCaller("broadcastIntent");
      synchronized (this) {
          intent = verifyBroadcastLocked(intent);

          final ProcessRecord callerApp = getRecordForAppLocked(caller);
          final int callingPid = Binder.getCallingPid();
          final int callingUid = Binder.getCallingUid();

          final long origId = Binder.clearCallingIdentity();
          try {
              return broadcastIntentLocked(callerApp,
                      callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
                      intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                      requiredPermissions, appOp, bOptions, serialized, sticky,
                      callingPid, callingUid, callingUid, callingPid, userId);
          } finally {
              Binder.restoreCallingIdentity(origId);
          }
      }
  }

在broadcastIntentWithFeature中首先调用verifyBroadcastLocked方法来检验广播的合法性。继而在调用broadcastIntentLocked方法。下面我们先看verifyBroadcastLocked源码。

verifyBroadcastLocked()源码:

final Intent verifyBroadcastLocked(Intent intent) {
	// Refuse possible leaked file descriptors
	if (intent != null && intent.hasFileDescriptors() == true) { //1
		throw new IllegalArgumentException("File descriptors passed in Intent");
	}
	int flags = intent.getFlags(); //2
	if(!mProcessesReady) {
	if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0){ //3
	}else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){ //4
		Slog.e(TAG,"Attempt to launch receivers of broadcast intent " + intent
				+ "before boot completion");
		throw new IllegalStateException("Cannot broadcast before boot completed"');
	}
	}
	if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) !=0) {
		throw new llegalArgumentException(
				Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
	}
	return intent;
}

在注释1验证了intent是否为空和文件描述符;在注释2获取intent中的flag,注释3表示若此时系统正处于启动过程中,判断flag值,若flag为FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT(启动检测时只接受动态注册的广播接收器)则不做处理,如flag为FLAG_RECEIVER_REGISTERED_ONLY(只接受动态注册的广播接收者)则会抛出异常。

broadcastIntentLocked源码:

@GuardedBy("this")
final int broadcastIntentLocked(ProcessRecord callerApp,
                                String callerPackage, String callerFeatureId, Intent intent, String
                                        resolvedType,
                                IIntentReceiver resultTo, int resultCode, String resultData,
                                Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
                                boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
                                int realCallingPid, int userId) {
    return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,
            resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,
            appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid,
            realCallingPid, userId, false /* allowBackgroundActivityStarts */,
            null /*broadcastWhitelist*/);
}

  @GuardedBy("this")
  final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
                                  @Nullable String callerFeatureId, Intent intent, String resolvedType,
                                  IIntentReceiver resultTo, int resultCode, String resultData,
                                  Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
                                  boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
                                  int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
                                  @Nullable int[] broadcastWhitelist) {

      intent = new Intent(intent);
      //增加该flag,则广播不会发送给已停止的package
      intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
      //...
      // ...广播权限验证
      // ... 处理系统相关广播
      // ...增加sticky广播

      // 通过Intent查询到对应的广播接收器
      List receivers = null; // 静态广播接收器
      List<BroadcastFilter> registeredReceivers = null; //动态广播接收器
      //当允许静态接收者处理该广播,则通过PKMS根据Intent查询相应的静态receivers
      if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
          receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
      }
      if (intent.getComponent() == null) {
          if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
           ...
          } else {
              // 查询相应的动态注册的广播
              registeredReceivers = mReceiverResolver.queryIntent(intent,
                      resolvedType, false, userId);
          }
      }

      int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
      // 处理并行广播,并且只给动态广播接收器并行处理
      if (!ordered && NR > 0) {
          // 根据Intent查询是前台还是后台BroadcastQueue
          final BroadcastQueue queue = broadcastQueueForIntent(intent);
          // 创建一个BroadcastRecord,参数有Intent和registeredReceivers
          BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                  callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                  requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                  resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                  allowBackgroundActivityStarts, timeoutExempt);
          if (!replaced) {
              // 将BroadcastRecord加入到mParallelBroadcasts队列
              queue.enqueueParallelBroadcastLocked(r);
              // 执行队列
              queue.scheduleBroadcastsLocked();
          }
          // 如果是并行广播,执行完成后动态广播接收器清空处理
          registeredReceivers = null;
          NR = 0;
      }

      //...

      //如果此时registeredReceivers不为null,则表明这是一个串行广播
      // 则将registeredReceivers合并到receivers一起执行串行处理
      int NT = receivers != null ? receivers.size() : 0;
      int it = 0;
      ResolveInfo curt = null;
      BroadcastFilter curr = null;
      while (it < NT && ir < NR) {
          if (curt == null) {
              curt = (ResolveInfo) receivers.get(it);
          }
          if (curr == null) {
              curr = registeredReceivers.get(ir);
          }
          if (curr.getPriority() >= curt.priority) {
              receivers.add(it, curr);
              ir++;
              curr = null;
              it++;
              NT++;
          } else {
              it++;
              curt = null;
          }
      }
      while (ir < NR) {
          if (receivers == null) {
              receivers = new ArrayList();
          }
          receivers.add(registeredReceivers.get(ir));
          ir++;
      }

      // receivers执行串行广播
      if ((receivers != null && receivers.size() > 0)
              || resultTo != null) {
          //根据intent的flag来判断前台队列或者后台队列
          BroadcastQueue queue = broadcastQueueForIntent(intent); //1
          //创建BroadcastRecord
          BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                  callerPackage, callingPid, callingUid, resolvedType,
                  requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                  resultData, resultExtras, ordered, sticky, false, userId);

          boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
          if (!replaced) {
              //将BroadcastRecord加入到有序广播队列
              queue.enqueueOrderedBroadcastLocked(r);
              //处理广播
              queue.scheduleBroadcastsLocked(); //2
          }
      }

      return ActivityManager.BROADCAST_SUCCESS;
  }

在broadcastIntentLocked方法中

  1. 通过intent去packageManagerService和ActivityManagerService.mReceiverResolver变量中查询到对应的广播接收器,其中变量receivers存储静态接收器,registeredReceivers变量存储动态接收器。
  2. 如果发送的是并行广播,则查看是否有对应的动态广播接收器,并创建一个拥有Intent和registeredReceivers的BroadcastRecord对象,并保存在BroadcastQueue.mParallelBroadcasts变量中,最终执行queue.schedulecastsLocked()处理广播,并把registeredReceivers消息制空。
  3. 如果regigteredReceivers不为null, 说明发送的是串行广播,则把registeredReceivers合并到receivers变量,一起串行执行。
  4. 对receivers进行串行执行,创建一个拥有intent和receivers的BroadcastRecord对象,并保存到队列的mOrderedBroadcasts变量中,最终执行queue.scheduleBroadcastsLocked()处理广播。

到这里便是ContextImpl到AMS的全部过程,下面便来看AMS到BroadcastReceiver的调用过程。

AMS到BroadcastReceiver的调用过程

下面先看scheduleBroadcastsLocked()的源码,看它是如何处理广播的。

scheduleBroadcastsLocked()源码:

public final class BroadcastQueue {


  public void scheduleBroadcastsLocked() {
      if (mBroadcastsScheduled) {
          return;
      }
      // 发送BROADCAST_INTENT_MSG类型消息
      mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
      mBroadcastsScheduled = true;

  }
}
  private final class BroadcastHandler extends Handler {
      public BroadcastHandler(Looper looper) {
          super(looper, null, true);
      }

      @Override
      public void handleMessage(Message msg) {
          switch (msg.what) {
              // 执行此消息
              case BROADCAST_INTENT_MSG: {
                  processNextBroadcast(true);
              }
              break;
          }
      }
  }
  final void processNextBroadcast(boolean fromMsg) {
      synchronized (mService) {
          processNextBroadcastLocked(fromMsg, false);
      }
  }

scheduleBroadcastsLocked方法中向scheduleBroadcastsLocked类型的mHandler对象发送了BROADCAST_INTENT_MSG类型的消息,handler在收到这个消息后就调用processNextBroadcast方法进行处理,这个方法对无序广播和有序广播分别进行处理,目的是将广播发送给广播接收者。

processNextBroadcastLocked() 源码:


  final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
      BroadcastRecord r;
      //...
      //处理并行广播
      while (mParallelBroadcasts.size() > 0) { //1
          //把mParallelBroadcasts队列的BroadcastRecord执行完
          r = mParallelBroadcasts.remove(0); //2
          r.dispatchTime = SystemClock.uptimeMillis();
          r.dispatchClockTime = System.currentTimeMillis();
          // r.receivers就是AMS的registeredReceivers变量
          final int N = r.receivers.size();

          for (int i = 0; i < N; i++) {
              Object target = r.receivers.get(i);
              //分发广播给已注册的receiver
              deliverToRegisteredReceiverLocked(r, (BroadcastFilter) target, false, i); \\3
          }
          addBroadcastToHistoryLocked(r);
      }

      // 处理当前有序广播
      do {
          // 获取BroadcastRecord
          final long now = SystemClock.uptimeMillis();
          r = mDispatcher.getNextBroadcastLocked(now);

          //没有更多的广播等待处理
          if (r == null) {
              mDispatcher.scheduleDeferralCheckLocked(false);
              mService.scheduleAppGcsLocked();
              if (looped) {
                  mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
              }
              if (mService.mUserController.mBootCompleted && mLogLatencyMetrics) {
                  mLogLatencyMetrics = false;
              }
              return;
          }

          boolean forceReceive = false;
          // 获取Receivers的大小
          int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;

          //当广播处理时间超时,则强制结束这条广播
          if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0) {
              if ((numReceivers > 0) &&
                      (now > r.dispatchTime + (2 * mConstants.TIMEOUT * numReceivers))) {
                  broadcastTimeoutLocked(false); // forcibly finish this broadcast
                  forceReceive = true;
                  r.state = BroadcastRecord.IDLE;
              }
          }
          //...
          if (r.receivers == null || r.nextReceiver >= numReceivers
                  || r.resultAbort || forceReceive) {
              if (r.resultTo != null) {
                  //...
                  //处理广播消息消息,调用到onReceive()
                  performReceiveLocked(r.callerApp, r.resultTo,
                          new Intent(r.intent), r.resultCode,
                          r.resultData, r.resultExtras, false, false, r.userId);
                  //...
              }

              //...
              mDispatcher.retireBroadcastLocked(r);
              r = null;
              looped = true;
              continue;
          }
          //..
      } while (r == null);


      //获取下一个receiver的index
      int recIdx = r.nextReceiver++;

      r.receiverTime = SystemClock.uptimeMillis();
      if (recIdx == 0) {
          r.dispatchTime = r.receiverTime;
          r.dispatchClockTime = System.currentTimeMillis();
      }
      if (!mPendingBroadcastTimeoutMessage) {
          long timeoutTime = r.receiverTime + mTimeoutPeriod;
          //设置广播超时时间,发送BROADCAST_TIMEOUT_MSG
          setBroadcastTimeoutLocked(timeoutTime);
      }

      final BroadcastOptions brOptions = r.options;
       //获取下一个广播接收者
      final Object nextReceiver = r.receivers.get(recIdx);

      if (nextReceiver instanceof BroadcastFilter) {
          //对于动态注册的广播接收者,deliverToRegisteredReceiverLocked处理广播
          BroadcastFilter filter = (BroadcastFilter) nextReceiver;
          deliverToRegisteredReceiverLocked(r, filter, r.ordered);
          if (r.receiver == null || !r.ordered) {
              r.state = BroadcastRecord.IDLE;
              scheduleBroadcastsLocked();
          } else {
              ...
          }
          return;
      }

      //对于静态注册的广播接收者
      ResolveInfo info = (ResolveInfo) nextReceiver;
      ComponentName component = new ComponentName(
              info.activityInfo.applicationInfo.packageName,
              info.activityInfo.name);
         ...
       //执行各种权限检测,此处省略,当权限不满足时skip=true

      if (skip) {
          r.receiver = null;
          r.curFilter = null;
          r.state = BroadcastRecord.IDLE;
          scheduleBroadcastsLocked();
          return;
      }

      r.state = BroadcastRecord.APP_RECEIVE;
      String targetProcess = info.activityInfo.processName;
      r.curComponent = component;
      final int receiverUid = info.activityInfo.applicationInfo.uid;
      if (r.callingUid != Process.SYSTEM_UID && isSingleton
              && mService.isValidSingletonCall(r.callingUid, receiverUid)) {
          info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
      }
      r.curReceiver = info.activityInfo;
      ...
      //Broadcast正在执行中,stopped状态设置成false
      AppGlobals.getPackageManager().setPackageStoppedState(
              r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
      //该receiver所对应的进程已经运行,则直接处理
      ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
              info.activityInfo.applicationInfo.uid, false);
      if (app != null && app.thread != null) {
          try {
              app.addPackage(info.activityInfo.packageName,
                      info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
              processCurBroadcastLocked(r, app);
              return;
          } catch (RemoteException e) {
          } catch (RuntimeException e) {
              finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false);
              scheduleBroadcastsLocked();
              r.state = BroadcastRecord.IDLE; //启动receiver失败则重置状态
              return;
          }
      }

      //该receiver所对应的进程尚未启动,则创建该进程
      if ((r.curApp=mService.startProcessLocked(targetProcess,
              info.activityInfo.applicationInfo, true,
              r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
              "broadcast", r.curComponent,
              (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
              == null) {
          //创建失败,则结束该receiver
          finishReceiverLocked(r, r.resultCode, r.resultData,
                  r.resultExtras, r.resultAbort, false);
          scheduleBroadcastsLocked();
          r.state = BroadcastRecord.IDLE;
          return;
      }
      mPendingBroadcast = r;
      mPendingBroadcastRecvIndex = recIdx;
      //...
  }
  • 注释1的mParallelBroadcasts列表用来存储无序广播,通过while循环将mParallelBroadcasts列表中的无序广播发送给对应的广播接收者。
  • 注释2获取每一个mParallelBroadcasts列表中存储的BroadcastRecord类型的r对象。
  • 注释3通过deliverToRegisteredReceiverLocked方法将这些r对象描述的广播发送给对应的广播接收者。

deliverToRegisteredReceiverLocked()源码:

  private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
                                                 BroadcastFilter filter, boolean ordered, int index) {
      //...
      // 调用performReceiveLocked方法
      performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
              new Intent(r.intent), r.resultCode, r.resultData,
              r.resultExtras, r.ordered, r.initialSticky, r.userId);

      //...
  }

这里省去了大部分的代码,这些代码是用来检查广播发送者和广播接收者的权限,如果通过了权限的检测则会调用 performReceiveLocked 方法。

performReceiveLocked()源码:

  void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
                            Intent intent, int resultCode, String data, Bundle extras,
                            boolean ordered, boolean sticky, int sendingUser)
          throws RemoteException {
      if (app != null) { \\1
          // 如果ProcessRecord != null,且ApplicationThread不为空
          if (app.thread != null) { \\2
              try {
                  // 调用ApplicationThread.scheduleRegisteredReceiver
                  app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                          data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
              } catch (RemoteException ex) {
                  synchronized (mService) {
                      app.scheduleCrash("can't deliver broadcast");
                  }
                  throw ex;
              }
          } else {
              // Application has died. Receiver doesn't exist.
              throw new RemoteException("app.thread must not be null");
          }
      } else {
          // 如果ProcessRecord为空
          receiver.performReceive(intent, resultCode, data, extras, ordered,
                  sticky, sendingUser);
      }
  }

注释1和注释2处的代码表示如果广播接收者所在的应用程序进行存在并且正在运行,则执行 scheduleRegisteredReceiver 对广播进行回调。

scheduleRegisteredReceiver()源码:

  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);
      // 调用IntentReceiver的performReceive方法
      receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
              sticky, sendingUser); \\1
  }

注释1处调用了IIntentReceiver类的performReceive方法。这里实现的是LoadedApk.ReceiverDispater.InnerReceiver()

final static class InnerReceiver extends IIntentReceiver.Stub {
          final WeakReference<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 (rd != null) {
                  // 调用ReceiverDispatcher的performReceive方法
                  rd.performReceive(intent, resultCode, data, extras,
                          ordered, sticky, sendingUser); //1
              }
              //...
          }
      }

注释1调用了ReceiverDispatcher类的performReceive方法:

performReceive()源码:

     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); //1
          //...
          // 通过Handler执行args的Runnable
          if (intent == null || !mActivityThread.post(args.getRunnable())) { //2
              if (mRegistered && ordered) {
                  IActivityManager mgr = ActivityManager.getService();

                  args.sendFinished(mgr);
              }
          }
      }

注释1将广播的intent等信息封装成为Args对象,并在注释2调用mActivityThread的post方法执行了args的Runnable。这个mActivityThread是一个Handler对象,具体指向的就是H,注释2处的代码就是将args的Runnable通过H发送到主线程的消息队列中。

final class Args extends BroadcastReceiver.PendingResult {

          public final Runnable getRunnable() {
              return () -> {
                  final BroadcastReceiver receiver = mReceiver;
                  //...
                  try {
                      ClassLoader cl = mReceiver.getClass().getClassLoader();
                      intent.setExtrasClassLoader(cl);
                      intent.prepareToEnterProcess();
                      setExtrasClassLoader(cl);
                      receiver.setPendingResult(this);
                      // 调用BroadcastReceiver的onReceive方法
                      receiver.onReceive(mContext, intent); //1
                  } catch (Exception e) {
                      //...
                  }

                  if (receiver.getPendingResult() != null) {
                      finish();
                  }
              };
          }
      }

在注释1执行了广播接收者的onReceive方法,这样注册的广播接收者就收到了广播并得到了intent。

以上便是广播的注册和发送、接收的全部过程了。文章来源地址https://www.toymoban.com/news/detail-422804.html

到了这里,关于Android学习笔记 - 广播的注册与接收的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 安卓广播发送接收流程

    本文基于Andorid 11。 动态注册广播接收器,参数:BroadcastReceiver, IntentFilter。 静态注册广播,安卓8以后除几个特殊的广播外,静态注册方式只能接收显示广播。 查看动态注册广播流程: 1.2 ContextImpl.registerReceiverInternal 传入IIntentReceiver对象作为参数,调用AMS.registerReceiverWithFea

    2024年04月17日
    浏览(51)
  • 安卓开发之广播接收器

    搞安全的,用到哪学到哪 1.发送广播的逻辑(需要先定义Intent方法,再进行send) 2.接收广播的逻辑(继承BroadcastReceiver方法) 3.开关控制广播,也就是注册广播的过程(对应的register方法) Notice:广播注册又有动态注册和静态注册 MainActicity 广播接收类 效果  有序广播 描述

    2024年02月10日
    浏览(41)
  • Qt网络编程 (udp广播和接收例)

    使用两个项目 1 sender 用来广播\\\"hello world\\\"; 2 receiver 用来接收广播信息 1 创建Qdialog类 2 在sender.pro 中添加 QT +=network 一行代码 3 在sender.h 中声明类 class QUdpSocket; 在声明一个私有对象 QUdpSocket *sender; 4 在ui界面拖入一个按钮 用来触发广播信息 其槽函数如下 在sender.cpp 构造函数中添

    2024年02月11日
    浏览(42)
  • TCP/IP UDP广播无法发送或接收

    在看《TCP/IP 网络编程》这本书的时候,看到广播那一节,跟着书上写代码,怎么写都不行,广播就是没法发送/接收,发送端一直在发送数据,接收端就是没有反应。 对了好几遍源码,没有问题。实在是愁人。 最后查了很多资料,确定是网卡的问题。 现在的计算机都是多网

    2024年02月04日
    浏览(51)
  • QT网络编程之实现UDP广播发送和接收

    一.UDP广播介绍 UDP广播地址固定IP地址为:XXX.XXX.XXX.255。 如果向全网段发送广播消息,那么广播地址为:255.255.255.255; 如果向单个网段发送广播消息,例如你的IP是192.168.31.104,那么广播地址为192.168.31.255。 广播消息接收方需要绑定0.0.0.0地址并监听指定端口即可收到广播的群

    2024年03月25日
    浏览(67)
  • C/C++ Socket UDP 广播消息的发送与接收

    局域网内全网段广播消息的IP地址为:255.255.255.255,向该IP地址发送广播消息,局域网下的任何网段的客户机都能收到广播。 对于发送端,如果你只想给某个特定的网段发送消息,例如你的IP地址为192.168.31.107,那么你的广播地址是192.168.31.255,向该广播地址发送广播消息,只

    2024年02月12日
    浏览(39)
  • Android笔记(十七):PendingIntent简介

    PendingIntent翻译成中文为“待定意图”,这个翻译很好地表示了它的涵义。PendingIntent描述了封装Intent意图以及该意图要执行的目标操作。PendingIntent封装Intent的目标行为的执行是必须满足一定条件,只有条件满足,才会触发意图的目标操作。 获取PendingIntent对象有以下几种方式

    2024年02月04日
    浏览(42)
  • CAN通讯配置及接收报文--学习笔记1~2

    硬件设备 STM32F103C8T6工控板、USB转TLL接口、TLL转CAN串口小板,继电器,降压模块,警示灯 软件工具 CANPro协议分析平台、CubeMX、MDK-ARM 实现过程及功能 基础功能:PC端通过CANPro设置报文,发出串口信号经过USB和串口小板转成CAN信号,在单片机上接收特定ID的报文,通过判断需要

    2024年02月09日
    浏览(38)
  • 【Android 记事本,笔记本,可注册登录,增删改查(附源码)】

    简介 用Sqlite做数据库,用来存储账号以及笔记信息,实现了账号的注册以及登录功能,笔记方面实现了新增、删除、修改、搜索功能,列表展示笔记使用的是listView(懒得弄分割线,就使用listView的默认分割线了); 运行效果 代码讲解 我代码里使用了两个依赖,一个是工具

    2024年02月04日
    浏览(47)
  • STM32学习笔记(五)433M无线发射接收模块

    数据发射模块的工作频率为315M,采用声表谐振器SAW稳频,频率稳定度极高,当环境温度在-25~+85度之间变化时,频飘仅为3ppm 单片机供电VCC GND接单片机 接收到信号,接收模块对应针脚输出高电平 有D0 D1 D2 D3,对应遥控器的ABCD 需求:按下遥控器A按键,LED1亮1秒;按下遥控器

    2024年02月14日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包