当前位置: 首页 > article >正文

【Android】静态广播接收不到问题分析思路

参考资料:

Android 静态广播注册流程(广播2)-CSDN博客

Android广播发送流程(广播3)_android 发送广播-CSDN博客

https://zhuanlan.zhihu.com/p/347227068

在Android中,静态广播如果静态广播不能接收,我们可以从整个流程中去分析,是否注册成功了,或者是在发送过程中出现了问题,参考资料中的流程可以去看几遍。

在dump信息中,可以通过查看receiver的信息,

Receiver Resolver Table:

Non-Data Actions:

      android.intent.action.PACKAGE_REMOVED:

        88141ab com.example.test/.AppInstallReceiver

这里一般不会出现问题,

dumpsys activity broadcast-stats 可以看到一些信息。

如果出现类似下面的log

11-24 20:43:28.929  1748  3469 W BroadcastQueue: Background execution not allowed: receiving Intent { act=android.intent.action.PACKAGE_REPLACED dat=package: flg=0x4000010 (has extras) } to com.smile.gifmaker/com.yxcorp.gifshow.ad.detail.AppInstalledReceiver

这一种也比较直观,查看BroadcastQueue.java可以找到对应的代码,

final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj)里面

可以参考

https://zhuanlan.zhihu.com/p/347227068

如果没有直观的BroadcastQueue 的log,还是要看看广播发送流程,

参考 Android广播发送流程(广播3)_android 发送广播-CSDN博客

    private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
                                                        int callingUid, int[] users, int[] broadcastAllowList) {
        // TODO: come back and remove this assumption to triage all broadcasts
        int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;

        List<ResolveInfo> receivers = null;
        try {
            HashSet<ComponentName> singleUserReceivers = null;
            boolean scannedFirstReceivers = false;
            for (int user : users) {
                // Skip users that have Shell restrictions
                //如果调用者是shell,而且该user不允许shell调试,则跳过
                if (callingUid == SHELL_UID
                        && mUserController.hasUserRestriction(
                        UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
                    continue;
                }
                //静态广播通过PMS去查询接收者
                List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
                        .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
                if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
                    // If this is not the system user, we need to check for
                    // any receivers that should be filtered out.
                    for (int i=0; i<newReceivers.size(); i++) {
                        ResolveInfo ri = newReceivers.get(i);
                        //如果取出来的ResolveInfo包含了只允许系统接收的flag(FLAG_SYSTEM_USER_ONLY),
                        //则从筛选出来的列表中移除这个接收者
                        if ((ri.activityInfo.flags&ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
                            newReceivers.remove(i);
                            i--;
                        }
                    }
                }
                //如果到目前为止newReceivers(ResolveInfo列表)为null或者空的
                if (newReceivers != null && newReceivers.size() == 0) {
                    newReceivers = null;
                }
                if (receivers == null) {
                    //如果receivers(最后返回的结果)为null,则先将newReceivers赋值给receivers
                    receivers = newReceivers;
                } else if (newReceivers != null) {
                    // We need to concatenate the additional receivers
                    // found with what we have do far.  This would be easy,
                    // but we also need to de-dup any receivers that are
                    // singleUser.
                    //scannedFirstReceivers默认是fasle,也就是第一次跑到这段代码会进来,只进来一次
                    //receivers此时已经赋值过一次,这里是users第二次和以上循环才可能会进来
                    if (!scannedFirstReceivers) {
                        // Collect any single user receivers we had already retrieved.
                        scannedFirstReceivers = true;
                        // 遍历之前的receivers(这里receivers没有判空逻辑,只看这段逻辑不太严谨,
                        // 没有出错是由于newReceivers有判空)
                        for (int i=0; i<receivers.size(); i++) {
                            ResolveInfo ri = receivers.get(i);
                            //如果接收者包含FLAG_SINGLE_USER的flag
                            if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
                                ComponentName cn = new ComponentName(
                                        ri.activityInfo.packageName, ri.activityInfo.name);
                                if (singleUserReceivers == null) {
                                    singleUserReceivers = new HashSet<ComponentName>();
                                }
                                //则把这类组件add到singleUserReceivers中
                                singleUserReceivers.add(cn);
                            }
                        }
                    }
                    // Add the new results to the existing results, tracking
                    // and de-dupping single user receivers.
                    // 遍历新的users中获取的newReceivers
                    for (int i=0; i<newReceivers.size(); i++) {
                        ResolveInfo ri = newReceivers.get(i);
                        //如果也是带有FLAG_SINGLE_USER的flag,只发送给单个user
                        if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
                            ComponentName cn = new ComponentName(
                                    ri.activityInfo.packageName, ri.activityInfo.name);
                            if (singleUserReceivers == null) {
                                singleUserReceivers = new HashSet<ComponentName>();
                            }
                            //如果之前还没有添加过,才进行receivers添加
                            if (!singleUserReceivers.contains(cn)) {
                                //而且将单个用户接受者ComponentName cn添加到ComponentName中
                                singleUserReceivers.add(cn);
                                receivers.add(ri);
                            }
                        } else {
                            //其它情况则直接加入该接收者到receivers
                            receivers.add(ri);
                        }
                    }
                }
            }
        } catch (RemoteException ex) {
            // pm is in same process, this will never happen.
        }
        //如果带有broadcastAllowList,允许接收该广播uid的列表
        if (receivers != null && broadcastAllowList != null) {
            for (int i = receivers.size() - 1; i >= 0; i--) {
                final int receiverAppId = UserHandle.getAppId(
                        receivers.get(i).activityInfo.applicationInfo.uid);
                //接受者的uid如果是app进程,而且不在允许接收该广播uid的列表,则移除查询到的接收者
                if (receiverAppId >= Process.FIRST_APPLICATION_UID
                        && Arrays.binarySearch(broadcastAllowList, receiverAppId) < 0) {
                    receivers.remove(i);
                }
            }
        }
        //返回接受者
        return receivers;
    }

这里看看

ResolveInfo

代码细节很多,还是要仔细查看,还是那句话,"只在此山中,云深不知处"


http://www.kler.cn/a/409804.html

相关文章:

  • 深入浅出:JVM 的架构与运行机制
  • 【网络通信】数据集合集!
  • 图像标签格式转换
  • Redis 常用数据类型插入性能对比:循环插入 vs. 批量插入
  • opencv-python 分离边缘粘连的物体(距离变换)
  • 【模块一】kubernetes容器编排进阶实战之pod生命周期、探针简介、类型及示例
  • 谷粒商城篇章12--P326-P339--Sentinel/Sleuth+Zipkin服务链路追踪【分布式高级篇九】
  • C++网络编程之多播
  • Js-函数-03
  • 【redis 】string类型详解
  • 工程化RAG-无法评估,就无法改进
  • 宝可梦GO如何超越李飞飞的空间智能?150万亿参数解锁现实边界 | LeetTalk Daily...
  • 新版布谷直播软件源码开发搭建功能更新明细
  • STM32 USART串口发送
  • 【Leetcode 每日一题】743. 网络延迟时间
  • Ant Design Vue中使用change方法时如何传递自定义参数
  • Lumos学习王佩丰Excel第十六讲:简单文本函数
  • 快速排序&Lambda表达式
  • 深度学习中的循环神经网络(RNN)与时间序列预测
  • 我的创作之路:机缘、收获、日常与未来的憧憬
  • 基础免杀 从.rsrc加载shellcode上线
  • 融合模型VotingRegressor 在线性数据上的比对与应用
  • Flutter 设计模式全面解析:抽象工厂
  • 3dm 格式详解,javascript加载导出3dm文件示例
  • Nginx防御机制
  • 数据结构——停车场管理问题