【Android】Android Broadcast源码解析

本文详细解析了Android中Broadcast的工作原理,包括静态广播的注册、动态广播的注册、广播发送、粘性广播的实现、广播队列的工作方式,以及并行和串行处理的流程。通过对源码的分析,阐述了Android广播系统的内部机制。
摘要由CSDN通过智能技术生成

Android Broadcast源码解析

一、静态广播的注册

静态广播是通过PackageManagerService在启动的时候扫描已安装的应用去注册的。
在PackageManagerService的构造方法中,会去扫描应用安装目录,顺序是先扫描系统应用安装目录再扫描第三方应用安装目录。
PackageManagerService.scanDirLI就是用于扫描目录的方法,由于代码比较少,这里我们直接把它贴了上来:

private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
   
   String[] files = dir.list();
   if (files == null) {
   
       return;
   }

   int i;
   for (i=0; i<files.length; i++) {
   
       File file = new File(dir, files[i]);
       if (!isPackageFilename(files[i])) {
   
           continue;
       }
       PackageParser.Package pkg = scanPackageLI(file,
               flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
       if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
               mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
   
           file.delete();
       }
   }
}

private static final boolean isPackageFilename(String name) {
   
   return name != null && name.endsWith(".apk");
}

可以看到,它通过File.list方法列出目录下的所有后缀为".apk"的文件传给scanPackageLI去处理。
而scanPackageLI(File scanFile,int parseFlags, int scanMode, long currentTime, UserHandle user)内部会调用它的重载方法scanPackageLI(PackageParser.Package pkg,int parseFlags, int scanMode, long currentTime, UserHandle user):

private PackageParser.Package scanPackageLI(File scanFile,int parseFlags, int scanMode, long currentTime, UserHandle user) {
   
  ...
  final PackageParser.Package pkg = pp.parsePackage(scanFile,scanPath, mMetrics, parseFlags);
  ...
  PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime, user);
  ...
}

在这个scanPackageLIl里面会解析Package并且将AndroidManifest.xml中注册的BroadcastReceiver保存下来:

...
N = pkg.receivers.size();
r = null;
for (i=0; i<N; i++) {
   
   PackageParser.Activity a = pkg.receivers.get(i);
   a.info.processName = fixProcessName(pkg.applicationInfo.processName,
           a.info.processName, pkg.applicationInfo.uid);
   mReceivers.addActivity(a, "receiver");
   ...
}
...

所以从上面获取静态广播的流程可以看出来:系统应用的广播先于第三方应用的广播注册,而安装在同一个目录下的应用的静态广播的注册顺序是按照File.list列出来的apk的顺序注册的。他们的注册顺序就决定了它们接收广播的顺序。
通过静态广播的注册流程,我们已经将静态广播注册到了PackageManagerService的mReceivers中,而我们可以使用PackageManagerService.queryIntentReceivers方法查询intent对应的静态广播

public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags, int userId) {
   
   if (!sUserManager.exists(userId)) return Collections.emptyList();
   ComponentName comp = intent.getComponent();
   if (comp == null) {
   
       if (intent.getSelector() != null) {
   
           intent = intent.getSelector();
           comp = intent.getComponent();
       }
   }
   if (comp != null) {
   
       List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
       ActivityInfo ai = getReceiverInfo(comp, flags, userId);
       if (ai != null) {
   
           ResolveInfo ri = new ResolveInfo();
           ri.activityInfo = ai;
           list.add(ri);
       }
       return list;
   }

   synchronized (mPackages) {
   
       String pkgName = intent.getPackage();
       if (pkgName 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值