Android 13扫描QR码无法唤起APP,默认打开浏览器求助
核心问题分析
Android 13(API 33)引入了更严格的包可见性限制,同时部分默认相机APP对自定义Scheme的处理逻辑发生变化,导致你的nm:// Scheme无法被正确识别唤起APP,转而跳转到浏览器。另外你的Broadcast Receiver代码存在未注册的问题,实际并未生效。
分步解决
1. 添加包可见性声明
在AndroidManifest.xml的<manifest>标签内添加<queries>,声明需要交互的相机应用(以常见相机包为例,可根据实际支持的相机APP补充):
<queries> <!-- Google相机 --> <package android:name="com.google.android.GoogleCamera" /> <!-- 通用系统相机包名 --> <package android:name="com.android.camera2" /> <!-- 通过Intent Action匹配相机类应用 --> <intent> <action android:name="android.media.action.IMAGE_CAPTURE" /> </intent> </queries>
这一步是让Android系统允许你的APP被相机APP发现,否则相机无法唤起你的应用。
2. 完善Activity的Intent Filter
虽然现有Filter在低版本有效,但Android 13下可补充更明确的规则,避免被系统判定为无效Scheme:
<intent-filter android:priority="999"> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <!-- 明确Scheme并补充host,增强匹配精度 --> <data android:scheme="nm" android:host="*"/> <!-- 匹配任意host,可根据你的QR码内容调整 --> </intent-filter>
- 添加
android:priority="999":提高APP在Scheme匹配时的优先级,超过浏览器默认优先级。 - 补充
android:host="*":部分相机APP要求Scheme必须包含host才会识别为应用跳转,而非网页链接。
3. 修复Broadcast Receiver的无效问题
你当前的onBroadcastReceived函数仅创建了Receiver实例,未完成注册,根本不会收到任何广播。如果确实需要通过Broadcast Receiver处理相机扫描事件:
静态注册(推荐)
在AndroidManifest.xml的<application>标签内添加Receiver注册:
<receiver android:name=".your.package.YourScanReceiver" <!-- 替换为你的Receiver类路径 --> android:exported="true"> <intent-filter> <!-- 替换为目标相机扫描后发送的广播Action,需确认相机APP的广播规则 --> <action android:name="com.android.camera.action.SCAN_RESULT" /> </intent-filter> </receiver>
然后创建独立的Receiver类:
class YourScanReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val scanResult = intent.getStringExtra("scan_result") if (scanResult?.startsWith("nm://") == true) { val launchIntent = Intent(context, MainActivity::class.java) launchIntent.data = Uri.parse(scanResult) launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(launchIntent) } } }
动态注册(可选)
如果需要在Activity生命周期内注册,可在MainActivity的onCreate中添加:
private lateinit var scanReceiver: BroadcastReceiver override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ...其他代码 scanReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val scanResult = intent.getStringExtra("scan_result") scanResult?.takeIf { it.startsWith("nm://") }?.let { val launchIntent = Intent(context, MainActivity::class.java) launchIntent.data = Uri.parse(it) launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(launchIntent) } } } val filter = IntentFilter("com.android.camera.action.SCAN_RESULT") registerReceiver(scanReceiver, filter) } override fun onDestroy() { super.onDestroy() unregisterReceiver(scanReceiver) // 记得注销Receiver }
注意:不同厂商的相机APP发送的广播Action和Extra字段可能不同,需自行确认目标相机的广播规则。如果核心需求是通过Scheme唤起APP,无需依赖Broadcast Receiver,完善Intent Filter即可。
4. 验证QR码内容
确保QR码内容严格为nm://xxx格式,无多余前缀或拼写错误(比如误写为http://nm://xxx),否则会被浏览器识别为网页链接。
测试验证
完成修改后重新打包安装APP,在Android 13设备上用默认相机扫描QR码,即可正常唤起你的APP。
内容的提问来源于stack exchange,提问作者hajer

