【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
代码细节很多,还是要仔细查看,还是那句话,"只在此山中,云深不知处"