天天看点

BroadcastReceiver详解BroadcastReceiver详解

BroadcastReceiver详解

使用方式

在Manifest.xml文件中注册

<receiver
  android:name=".test.broadcast.MyTestReceiver"
  android:enabled="true"
  android:exported="true">
  <intent-filter>
      <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
      <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
      <action android:name="android.intent.action.SCREEN_ON" />
      <action android:name="android.intent.action.SCREEN_OFF" />
      <action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
      <action android:name="android.intent.action.CONFIGURATION_CHANGED" />
      <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
      <action android:name="android.intent.action.USER_PRESENT" />
  </intent-filter>
</receiver>
           

在Manifesh.xml文件中注册自定义的BroadcastReceiver,当意图过滤器中的动作发生时,会回调BroadcastReceiver中的onRecevie方法.

public class MyTestReceiver extends BroadcastReceiver {
    private static final String TAG = "MyTestReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null) {
            String action = intent.getAction();
            Log.d(TAG, "onReceive: receive action is " + action);
        }
    }
}
           

代码中动态注册

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);

registerReceiver(new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
      String action = intent == null ? "" : intent.getAction();
      if (Intent.ACTION_SCREEN_OFF.equalsIgnoreCase(action)) {
          Log.i(TAG, "onReceive: 屏幕关闭");
      }
      context.unregisterReceiver(this);
  }
}, intentFilter);
           

在Activity上下文中调用registerReceiver方法,动态注册一个广播接收者,同时指定了意图过滤器。

这里要注意注册的BroadcastReceiver最好是静态类,防止内存泄漏。否则要及时取消注册。

原理

注册通知

静态注册

通过PackageManagerService安装应用时,会解析安装包中的Manifest.xml文件,存储解析到Receiver标签对应的广播接收器。

通过Unix Socket接收需要安装的Apk文件
//android/os/FileBridge.java

public class FileBridge extends Thread {
    private static final int MSG_LENGTH = 8;
    private final FileDescriptor mServer = new FileDescriptor();
    private final FileDescriptor mClient = new FileDescriptor();
    
    private FileDescriptor mTarget;

    //构造函数
    //创建Unix Domain Socket的客户端和服务端,然后会将代表客户端的文件描述符发送给客户端进程
    public FileBridge() {
        try {
            Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mServer, mClient);
        } catch (ErrnoException e) {
            throw new RuntimeException("Failed to create bridge");
        }
    }
    
    //mTarget文件描述符用来存储客户端进程发送过来的Apk文件数据
    public void setTargetFile(FileDescriptor target) {
        mTarget = target;
    }

    public FileDescriptor getClientSocket() {
        return mClient;
    }
    
    //这是一个线程,不停监听Socket的Server端
    @Override
    public void run() {
        final byte[] temp = new byte[8192];//读缓冲区
        //读取Socket的Server端,如果没有数据会阻塞
        //每次先读取8字节,前4个字节代表数据类型,后4四个字节代表数据长度
        while (IoBridge.read(mServer, temp, 0, MSG_LENGTH) == MSG_LENGTH) {
            //按照大端序读取前4字节
            final int cmd = Memory.peekInt(temp, 0, ByteOrder.BIG_ENDIAN);
            //数据写入,将apk文件数据写入到mTraget代表的文件描述中
            if (cmd == CMD_WRITE) {
                int len = Memory.peekInt(temp, 4, ByteOrder.BIG_ENDIAN);
               while (len > 0) {
                   int n = IoBridge.read(mServer, temp, 0, Math.min(temp.length, len));
                   if (n == -1) {
                       throw new IOException(
                               "Unexpected EOF; still expected " + len + " bytes");
                   }
                   IoBridge.write(mTarget, temp, 0, n);
                   len -= n;
               }
            //数据同步,并回显给客户端确认
            } else if (cmd == CMD_FSYNC) {
                Os.fsync(mTarget);
                IoBridge.write(mServer, temp, 0, MSG_LENGTH);
            //关闭消息通道,并回显给客户端确认
            } else if (cmd == CMD_CLOSE) {
                Os.fsync(mTarget);
               Os.close(mTarget);
               mClosed = true;
               IoBridge.write(mServer, temp, 0, MSG_LENGTH);
               break;
            }
        }
        
    }
}
           
验证APK合法性
  1. 包名、版本号
  2. 签名(V2+V1)sudo
  3. 其他应用验证package-verifier
  4. 应用申请的权限,需要用户确认
  5. 拷贝安装包到data/data/{包名}/目录下,并且复制Native库到lib目录下
解析Apk文件
  1. 添加apk文件路径到AssetManager管理中
  2. 解析Manifest.xml文件信息到Package类中,区分是多个apk文件安装,还是单个apk文件安装
  3. 验证该安装包是否只用于测试
  4. 为Package类填充证书和签名信息
  5. 是否覆盖安装,需要验证签名是否一致、包配置是否一致等。还要替换应用资源
//frameworks/base/core/java/android/content/pm/PackageParser.java

private boolean parseBaseApplication(Package owner, Resources res,
            XmlResourceParser parser, int flags, String[] outError)
    ... 
    
    final int innerDepth = parser.getDepth();
    int type;
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
          && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth))     
          {
         String tagName = parser.getName();
          if (tagName.equals("activity")) {
              Activity a = parseActivity(owner, res, parser, flags, outError, 
                                        false,owner.baseHardwareAccelerated);
              owner.activities.add(a);
          } else if (tagName.equals("receiver")) {
              Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
              owner.receivers.add(a);
        
          } else if (tagName.equals("service")) {
          ...
    }
}
           

从上面解析过程可以看出,Android系统把Activity和BroadcastReceiver都当做了Activity类型来存储的。

parseActivity方法中,还会继续解析里面的intent-filter标签,以及其action/category/data等子标签。

所有从Manifest.xml文件中解析出来的数据,会存储到Package类中。

public final static class Package {
    public String packageName;
    public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
    public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
    ...
 }
           
保存组件信息

将Package类中的四大组件信息以及整个Package信息保存到PackageManagerService中。同时还会保存到Settings类中,Settings类代表了系统的动态设置信息。

//PackageManagerService.java

//系统中所有程序信息
final ArrayMap<String, PackageParser.Package> mPackages =
            new ArrayMap<String, PackageParser.Package>();

// 系统中所有程序的四大组件信息
final ActivityIntentResolver mActivities =
       new ActivityIntentResolver();
final ActivityIntentResolver mReceivers =
       new ActivityIntentResolver();
final ServiceIntentResolver mServices = new ServiceIntentResolver();
final ProviderIntentResolver mProviders = new ProviderIntentResolver();

//扫描包信息
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
            final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
            throws PackageManagerException {
    // Add the new setting to mSettings
    mSettings.insertPackageSettingLPw(pkgSetting, pkg);
    // Add the new setting to mPackages
    mPackages.put(pkg.applicationInfo.packageName, pkg);
    
    
    ...
    
    //保存Package中的BroadcastReceiver信息
    N = pkg.receivers.size();
    r = null;
    for (i=0; i<N; i++) {
        //这里把Receiver当做Activity来处理
        PackageParser.Activity a = pkg.receivers.get(i);
        a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                a.info.processName, pkg.applicationInfo.uid);
        mReceivers.addActivity(a, "receiver");
        if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
            if (r == null) {
            
                r = new StringBuilder(256);
            } else {
                r.append(' ');
            }
            r.append(a.info.name);
        }
    }
}

           

动态注册

通过ActivityManagerServer注册
//frameworks/base/core/java/android/app/ContextImpl.java

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) {
                    scheduler = mMainThread.getHandler();
                }
                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 {
            final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName,
                    rd, filter, broadcastPermission, userId);
            if (intent != null) {
                intent.setExtrasClassLoader(getClassLoader());
                intent.prepareToEnterProcess();
            }
            return intent;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
           

我们在Context上下文中调用registerReceiver(BroadcastReceiver, IntentFilter)方法动态注册一个广播时,会先保存到ActivityManagerServer中。

//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
    
    ...
    
    //如果调用者传入BroadcastReceiver是null,代表想要获得一个粘性广播
    //粘性广播直接通过registerReceiver方法的返回值返回给调用者。
    Intent sticky = allSticky != null ? allSticky.get(0) : null;
    if (receiver == null) {
      return sticky;
    }

    //将BroadcastReceiver存储到一个HashMap中
    ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
    if (rl == null) {
        //ReceiverList是一个ArrayList子类,用来存储BroadcastReceiver和对应的过滤器
    rl = new ReceiverList(this, callerApp, callingPid, callingUid,
       userId, receiver);
        if (rl.app != null) {
            rl.app.receivers.add(rl);
        } else {
            try {
               receiver.asBinder().linkToDeath(rl, 0);
            } catch (RemoteException e) {
               return sticky;
            }
            rl.linkedToDeath = true;
        }
        mRegisteredReceivers.put(receiver.asBinder(), rl);
    }
    //保存过滤器到IntentResolver中
    BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId);
    rl.add(bf);  
    mReceiverResolver.addFilter(bf);
}
           

发送、接收通知

当应用程序或系统程序发出一个广播时,会调用到ActivityManagerService中,ActivityManagerService会从自己保存的BroadcastReceiver列表和PackageManagerService保存的BroadcastReceiver列表中找出符合意图过滤器的广播接收者,然后向其发送广播。

//ActivityManagerService.java

final int broadcastIntentLocked(ProcessRecord callerApp,
            String callerPackage, 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 userId) {
            
    //1. 默认不给已经stopped停止的应用发送广播
    
    //2. 如果没有完成开机操作,例如正在升级系统,只允许注册广播,不能发送
    
    //3. 如果广播指定的目的用户,那么这个用户必须处于运行状态
    
    //4. 验证是否是系统应用发出的受保护的广播。受保护的广播只能由系统应用发出。
    //系统应用的判断标准是用户id:ROOT_UID/SYSTEM_UID/PHONE_UID/BLUETOOTH_UID/NFC_UID,或者是常驻应用
    
    //5. 窗口小部件的配置和更新广播也不能由应用发出。由于历史原因,它们并不是受保护的广播,需要单独判断
    
    //6. 对特殊广播的处理:由PackageManager发出的应用被删除或变更的广播,
    //需要ActivityManagerService作出对应的操作,例如从最近使用应用中删除它们的Activity。
    //特殊类型的广播处理完成后,就直接返回了
    
    //7. 从PackageManagerService中查询符合过滤器条件的广播接受者List<ResolveInfo>,这里就是应用安装时,解析出来的静态注册的广播接受者。
     List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
                        .queryIntentReceivers(intent, resolvedType, pmFlags,
                                                 user).getList();
    
    //8. 从ActivityManagerService的ContentResolver中查询符合条件的广播接受者,这里代表通过代码动态注册的广播接受者
     registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false, userId);
   
    
    //9. 将两个列表按照优先级合并成一个列表
    
    //10. 构造一个BroadcastRecord,添加到队列BroadcastQueue中,然后开始调度执行。
}

           
//BroasdcastQueue.java

public final class BroadcastQueue {

    final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
    final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>();

    //11. BroadcastQueue中的广播被分为并发广播和顺序广播。并发广播会立即被执行,而不需要等待其他的广播执行完毕。顺序广播则会逐一执行。
    //我们在注册广播时可以指定是否是顺序广播,或者粘性广播被认为是并发广播
    
    
    final void processNextBroadcast(boolean fromMsg) {
        BroadcastRecord r;
        
        //12. 开始处理列表中的广播。先处理并发广播
        
        //13. 如果处理广播的进程不存在,还需要等待进程的创建
        
        //14. 处理动态注册的广播,在BroadcastQueue中以BroadcastFilter形式存储
        performReceiveLocked(filter.receiverList.app, 
                            filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
                        
        //15. 处理静态注册的广播,如果需要,还要提前唤起对应进程。如果目标进程开始运行后,再分发对应的广播
        String targetProcess = info.activityInfo.processName;
        ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                        info.activityInfo.applicationInfo.uid, false);
        app.addPackage(info.activityInfo.packageName,
                            info.activityInfo.applicationInfo.versionCode, 
                            mService.mProcessStats);
        processCurBroadcastLocked(r, app);
        
        
    }
}
           

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) {
        app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser,
                             app.repProcState);
    } else {
        receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
    }
}
           

processCurBroadcastLocked方法如下:

private final void processCurBroadcastLocked(BroadcastRecord r,
            ProcessRecord app) throws RemoteException {
            
    app.thread.scheduleReceiver(new Intent(r.intent), 
                            r.curReceiver,
                            mService.compatibilityInfoForPackageLocked(
                            r.curReceiver.applicationInfo),
                            r.resultCode, 
                            r.resultData, 
                            r.resultExtras, 
                            r.ordered, 
                            r.userId,
                            app.repProcState);
}
           

取消注册

取消动态注册的广播接收器

前面说过动态注册的广播接收器是存储在ActivityManagerService中的,那么取消注册的时候,也是通过跨进程通信,告知ActivityManagerService移除指定的广播接收器。

//ActivityManagerService.java

final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();

public void unregisterReceiver(IIntentReceiver receiver) {
   final long origId = Binder.clearCallingIdentity();
   try {
       boolean doTrim = false;

       synchronized(this) {
           ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
           if (rl != null) {
               final BroadcastRecord r = rl.curBroadcast;
               if (r != null && r == r.queue.getMatchingOrderedReceiver(r)) {
                   final boolean doNext = r.queue.finishReceiverLocked(
                           r, r.resultCode, r.resultData, r.resultExtras,
                           r.resultAbort, false);
                   if (doNext) {
                       doTrim = true;
                       r.queue.processNextBroadcast(false);
                   }
               }

               if (rl.app != null) {
                   rl.app.receivers.remove(rl);
               }
               //从HashMap中移除BroadcastReceiver
               //从IntentResolver中移除对应的过滤器
               removeReceiverLocked(rl);
               if (rl.linkedToDeath) {
                   rl.linkedToDeath = false;
                   rl.receiver.asBinder().unlinkToDeath(rl, 0);
               }
           }
       }

       // If we actually concluded any broadcasts, we might now be able
       // to trim the recipients' apps from our working set
       if (doTrim) {
           trimApplications();
           return;
       }

   } finally {
       Binder.restoreCallingIdentity(origId);
   }
}


void removeReceiverLocked(ReceiverList rl) {
   mRegisteredReceivers.remove(rl.receiver.asBinder());
   for (int i = rl.size() - 1; i >= 0; i--) {
       mReceiverResolver.removeFilter(rl.get(i));
   }
}
           

取消静态注册的广播接收器

静态注册的广播接收者理论上是无法取消注册的,因为它们是写死在Manifest.xml文件中,并在应用安装时就被记录到PackageManagerService中的,并且PackageManagerService类并没有提供移除Receiver信息的接口。

那么静态注册的广播接收器就不能取消了么?

当然不是,这里我们可以采用迂回的方式达到目的。

在从PackageManagerService中查询符合条件的广播接收器列表时,IntentResolver会检查每个过滤器对应的BroadcastReceiver是否被禁用了,如果被禁用了就会忽略掉这个BroadcastReceiver,从而达到和取消注册同样的效果。

下面是禁用或启动某个组件的代码:

//禁用xxx.class代表的组件,如果是广播接收器,则不会再接收到广播
ComponentName componentName = new ComponentName(this, xxx.class);
        getPackageManager().setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

//启用xxx.class代表的组件
ComponentName componentName = new ComponentName(this, xxx.class);
        getPackageManager().setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
           

当我们通过PackageManagerService禁用某个组件时,PackageManagerService做了两件事:

  1. 前面在静态注册流程中提高,从Manifest.xml解析出来的组件也会存储到Setting中一份,标识了组件的状态。所以第一个要先修改Setting中的组件状态。如下面代码所示:
//PackageManagerService.java

private void setEnabledSetting(final String packageName, String className, int newState,
            final int flags, int userId, String callingPackage) {
    PackageSetting pkgSetting;
    pkgSetting = mSettings.mPackages.get(packageName);
    pkgSetting.setEnabled(newState, userId, callingPackage);
}
           

将某个组件的状态改为禁用后,当再次向PackageManagerService查询静态注册的组件时就会把禁用掉的组件过滤掉,不会返回给ActivityManagerService。

//PackageManagerService.java

//ActivityIntentResolver类的方法
//根据ActivityIntentInfo创建一个ResolveInfo
@Override
protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
      int match, int userId) {
      
      //向Setting类查询对应的组件是否被启用了
      if (!mSettings.isEnabledAndMatchLPr(info.activity.info, mFlags, userId)) {
           return null;
       }
}
           
  1. 第二件事会调用通过ActivityManagerService发送一个Intent.ACTION_PACKAGE_CHANGED类型的广播,告知ActivityManagerService有个组件被禁用了,如果有正在排队发送的广播需要移除掉。

这个流程和普通应用发送广播的流程是一样的,区别是ActivityManagerService在检查到此类型的广播时,会自己处理掉,而不会真正的发送出去,为你Intent.ACTION_PACKAGE_CHANGED广播属于受保护的广播,只能系统代码能发送。

ActivityManagerService的处理逻辑如下:

//ActivityManagerService.java

private void cleanupDisabledPackageComponentsLocked(
            String packageName, int userId, boolean killProcess, String[] changedClasses) {
        
    //1. 遍历禁用的组件,从PackageManagerService中查询对应组件是否已经被禁用
    //找出还没有被禁用的组件,如果已经禁用了就不管了
    try {
          enabled = pm.getComponentEnabledSetting(
                  new ComponentName(packageName, changedClass),
                  (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_SYSTEM);
      } catch (Exception e) {
          // As above, probably racing with uninstall.
          return;
      }
      if (enabled != PackageManager.COMPONENT_ENABLED_STATE_ENABLED
              && enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
          if (disabledClasses == null) {
              disabledClasses = new ArraySet<>(changedClasses.length);
          }
          //disabledClasses代表了实际将要被禁用的组件
          disabledClasses.add(changedClass);
      }
      

  //遍历ActivityManagerService存储的广播接收器,查看是否有需要禁用的
   for (int i = mBroadcastQueues.length - 1; i >= 0; i--) {
       mBroadcastQueues[i].cleanupDisabledPackageReceiversLocked(
               packageName, disabledClasses, userId, true);
   }
               
}

           

通过以上两个步骤就实现了禁用静态注册的广播接收器的目的。

与LocalBroadcastReceiver区别

LocalBroadcastReceiver就比较简单了,就是一个单例类+消息转发。不需要与ActivityManagerService或PackageManagerService服务进行跨进程通信。

LocalBroadcastReceiver是线程安全的,注册或发送广播时都是用Synchronized关键字包裹起来。

获取LocalBroadcastReceiver单例

@NonNull
public static LocalBroadcastManager getInstance(@NonNull Context context) {
   synchronized (mLock) {
       if (mInstance == null) {
           mInstance = new LocalBroadcastManager(context.getApplicationContext());
       }
       return mInstance;
   }
}

private LocalBroadcastManager(Context context) {
   mAppContext = context;
   mHandler = new Handler(context.getMainLooper()) {

       @Override
       public void handleMessage(Message msg) {
           switch (msg.what) {
               case MSG_EXEC_PENDING_BROADCASTS:
                   executePendingBroadcasts();
                   break;
               default:
                   super.handleMessage(msg);
           }
       }
   };
}
           

在构造LocalBroadcastReceiver实例时,会创建一个Handler,用于在主线程发送通知。

注册广播

private final HashMap<BroadcastReceiver, ArrayList<ReceiverRecord>> mReceivers
            = new HashMap<>();
private final HashMap<String, ArrayList<ReceiverRecord>> mActions = new HashMap<>();

public void registerReceiver(@NonNull BroadcastReceiver receiver,
            @NonNull IntentFilter filter) {
   synchronized (mReceivers) {
        //使用ReceiverRecord记录一个BroadcastReceiver和IntentFilter
        //使用HashMap记录一个BroadcastReceiver与多个ReceiverRecord关系
        //因为对同一个BroadcastReceiver允许注册多次
       ReceiverRecord entry = new ReceiverRecord(filter, receiver);
       ArrayList<ReceiverRecord> filters = mReceivers.get(receiver);
       if (filters == null) {
           filters = new ArrayList<>(1);
           mReceivers.put(receiver, filters);
       }
       filters.add(entry);
       for (int i=0; i<filter.countActions(); i++) {
           String action = filter.getAction(i);
        //使用HashMap记录每个Action和多个ReceiverRecord的关系
        //便于发送广播时查找对应的Receiver
           ArrayList<ReceiverRecord> entries = mActions.get(action);
           if (entries == null) {
               entries = new ArrayList<ReceiverRecord>(1);
               mActions.put(action, entries);
           }
           entries.add(entry);
       }
   }
}
           

发送广播

在主线程接收广播

private final ArrayList<BroadcastRecord> mPendingBroadcasts = new ArrayList<>();

public boolean sendBroadcast(@NonNull Intent intent) {
    
    ...
    
    //找出接受者,存储到列表mPendingBroadcasts中,等待被发送
    mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
    //向主线程发送一个消息,开始分发mPendingBroadcasts中的广播
    if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
        mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
    }
}
           

在当前调用线程接收广播

public void sendBroadcastSync(@NonNull Intent intent) {
   if (sendBroadcast(intent)) {
        //找到符合条件的接受者后,立即在当前线程去执行分发逻辑,而不等待主线程分发
        //也就是此方法会BroadcastReceiver的onReceive方法执行后,才会返回
       executePendingBroadcasts();
   }
}