Android如何检测其他应用中指定BroadcastReceiver是否存在?
问题:Android 11+ 下检测第三方BroadcastReceiver存在性失败
我尝试向其他应用的CmdReceiver发送广播,同时需要检测该接收器是否存在(不存在则调用showDialogNotFound())。Android 10及以下通过PackageManager.getReceiverInfo()可以正常检测,但Android 11+因安全限制改用有序广播的方式,即使接收器存在,仍会触发showDialogNotFound(),相关代码如下:
原检测代码(Android 11+分支)
val filter = IntentFilter() filter.addAction("android.intent.action.MAIN") val cmdIntent = Intent() cmdIntent.setComponent( ComponentName( pkgName, pkgName + ".CmdReceiver" ) ) cmdIntent.flags = Intent.FLAG_RECEIVER_FOREGROUND cmdIntent.flags = Intent.FLAG_INCLUDE_STOPPED_PACKAGES cmdIntent.putExtra("isOrderedBroadcast", true) sendOrderedBroadcast(cmdIntent, null, object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val result = getResultCode() val resultData = getResultData() if (result == -1 && resultData == "ReceiverFound") { Log.d("MainActivity", "BroadcastReceiver exists!") showDialogFound() } else { showDialogNotFound() } } }, null, Activity.RESULT_CANCELED, null, null)
目标应用CmdReceiver的处理代码(Java)
Boolean isOrderedBroadcast = intent.getBooleanExtra("isOrderedBroadcast", false); if (isOrderedBroadcast) { setResultCode(-1); setResultData("ReceiverFound"); }
问题原因&修正方案
1. Intent Flags赋值错误
连续两次给cmdIntent.flags赋值会导致前一个flag被覆盖,正确的多flag设置需要用按位或合并:
cmdIntent.flags = Intent.FLAG_RECEIVER_FOREGROUND or Intent.FLAG_INCLUDE_STOPPED_PACKAGES
2. 目标接收器的导出属性缺失
Android 12+对跨应用组件调用的权限限制更严格,CmdReceiver必须在Manifest中显式设置android:exported="true",否则其他应用无法访问:
<receiver android:name=".CmdReceiver" android:exported="true"> <!-- 显式调用时intent-filter非必须,若需匹配特定action可添加 --> </receiver>
3. 有序广播的结果判断逻辑优化
- 自定义初始结果码(避免与系统默认码冲突),简化判断逻辑
- 移除冗余的
isOrderedBroadcast额外参数,接收器可直接通过isOrderedBroadcast()方法判断
修正后的检测代码:
val cmdIntent = Intent() cmdIntent.setComponent(ComponentName(pkgName, pkgName + ".CmdReceiver")) cmdIntent.flags = Intent.FLAG_RECEIVER_FOREGROUND or Intent.FLAG_INCLUDE_STOPPED_PACKAGES sendOrderedBroadcast(cmdIntent, null, object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (getResultCode() == -1) { Log.d("MainActivity", "BroadcastReceiver exists!") showDialogFound() } else { showDialogNotFound() } } }, null, -2, null, null)
修正后的目标接收器代码:
if (isOrderedBroadcast()) { setResultCode(-1); }
内容的提问来源于stack exchange,提问作者IsHacker
相关产品推荐
相关产品推荐

