Android 13部分设备(多为三星)Deep Link报错问题咨询
问题背景
在多数Android 13版本的三星设备上出现Deep Link跳转异常,但同系统的Galaxy Note20和Google Pixel设备无此问题。已完成AndroidManifest.xml的相关配置,并实现了浏览器包名获取及Intent构建的Kotlin逻辑,需排查Android 13系统更新中可能引发该问题的因素。
当前配置与代码实现
AndroidManifest.xml配置
<queries> <intent> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" /> </intent> </queries> ... <intent-filter android:autoVerify="true" tools:targetApi="m"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:host="halilozel.com.tr" android:scheme="halilozel" /> </intent-filter>
浏览器包名获取逻辑
fun getBrowserPackageName(context: Context): String? { val browserPackageName: MutableList<String> = ArrayList() try { val intent = Intent(Intent.ACTION_VIEW) intent.data = Uri.parse("http://www.aornzmenswqdt.mrgsscqsbgs") val pm = context.packageManager val browserList: List<ResolveInfo> = pm.queryIntentActivities(intent, 0) for (info in browserList) { browserPackageName.add(info.activityInfo.packageName) } } catch (e: Exception) { e.printStackTrace() } return when { browserPackageName.isEmpty() -> null browserPackageName.contains(PACKAGE_NAME_CHROME) -> PACKAGE_NAME_CHROME browserPackageName.contains(PACKAGE_NAME_OPERA) -> PACKAGE_NAME_OPERA else -> browserPackageName[0] } }
浏览器Intent构建逻辑
fun Context.getBrowserIntent(url: String): Intent { val browserPackageName = getBrowserPackageName(this) if (browserPackageName != null) { val intent = packageManager.getLaunchIntentForPackage(browserPackageName) if (intent != null) { return intent.apply { data = Uri.parse(url) } } } val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("http://")) val resolveInfo = packageManager.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY) if (resolveInfo != null) { val packageName: String = resolveInfo.activityInfo.packageName val intent = packageManager.getLaunchIntentForPackage(packageName) if (intent != null) { return intent.apply { data = Uri.parse(url) } } } return Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, Intent.CATEGORY_APP_BROWSER).apply { data = Uri.parse(url) } }
Android 13相关更新点及可能原因
1. 包可见性(Package Visibility)强化
Android 13收紧了应用对其他应用的可见性限制,即使配置了<queries>,也可能因匹配规则不精确导致无法获取目标应用信息:
- 当前
<queries>仅针对httpsscheme配置,未包含自定义schemehalilozel,三星设备上的默认浏览器(Samsung Internet)可能因无法匹配到对应Intent规则,导致queryIntentActivities返回为空。 - 部分三星定制系统对系统应用的可见性有额外限制,需明确指定包名或更精确的Intent过滤规则。
2. Deep Link自动验证(AutoVerify)逻辑调整
Android 13对android:autoVerify="true"的验证流程和失败处理逻辑有调整:
- 若
assetlinks.json文件验证失败,三星设备可能直接跳过Deep Link跳转至浏览器,而非像旧版本设备那样保留 fallback 逻辑。Note20可能因系统版本分支差异,仍使用旧的验证兼容逻辑。 - 三星浏览器对验证通过的Deep Link优先级处理与Pixel/Note20不同,导致跳转逻辑异常。
3. Intent解析行为变更
Android 13修改了queryIntentActivities和resolveActivity的返回规则:
getBrowserPackageName中使用无效HTTP域名查询浏览器,三星浏览器可能对无效URL的Intent匹配做了限制,返回的浏览器列表为空,后续getBrowserIntent只能走兜底逻辑,而兜底逻辑未正确处理自定义scheme的Deep Link。- 使用
getLaunchIntentForPackage获取浏览器启动Intent后直接设置data,部分三星浏览器的启动Intent(ACTION_MAIN)不支持携带自定义scheme的data,导致跳转无效。
4. 自定义Scheme处理限制
Android 13对非HTTP/HTTPS的自定义scheme跳转增加了安全限制,三星设备的系统浏览器可能默认拦截未验证的自定义scheme,需用户手动授权或应用满足更严格的验证条件,而Note20/Pixel的浏览器版本未启用该限制。
建议排查与修复方向
补充Package Visibility配置
在<queries>中添加自定义scheme的Intent规则,确保能匹配到支持该scheme的应用:<queries> <!-- 原有https scheme配置 --> <intent> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" /> </intent> <!-- 添加自定义scheme配置 --> <intent> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="halilozel" /> </intent> <!-- 可选:添加三星浏览器包名,确保可见性 --> <package android:name="com.sec.android.app.sbrowser" /> </queries>调整浏览器Intent查询逻辑
替换无效HTTP域名查询,改用自定义scheme的URL,确保能获取到支持Deep Link的应用列表:val intent = Intent(Intent.ACTION_VIEW) intent.data = Uri.parse("halilozel://halilozel.com.tr") // 使用自定义scheme的有效链接修正Intent构建方式
不要使用getLaunchIntentForPackage,直接构造ACTION_VIEW的Intent并指定包名,确保携带的data能被正确识别:fun Context.getBrowserIntent(url: String): Intent { val browserPackageName = getBrowserPackageName(this) if (browserPackageName != null) { return Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { setPackage(browserPackageName) addCategory(Intent.CATEGORY_BROWSABLE) } } // 兜底逻辑也直接用ACTION_VIEW Intent return Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { addCategory(Intent.CATEGORY_BROWSABLE) addCategory(Intent.CATEGORY_DEFAULT) } }检查AutoVerify状态
通过ADB命令查看Deep Link验证结果:adb shell dumpsys package domain-preferred-apps确认
halilozel.com.tr的验证状态,若验证失败,需检查assetlinks.json文件的格式、位置及权限是否符合要求。
内容的提问来源于stack exchange,提问作者Halil Ozel

