同一应用内Custom Tabs中App Links无法生效的技术咨询
我之前也遇到过一模一样的问题!当Custom Tabs和App Links属于同一个应用包名时,Chrome确实会跳过App Links的触发逻辑,直接在Tab里加载目标URL——这是因为Chrome默认认为同包名下的网页导航应该保持在Custom Tabs内,维持连贯的网页体验。针对你的注册流程场景,这里有几个可行的解决办法:
1. 用CustomTabsCallback拦截跳转,手动触发App Links
你可以通过监听Custom Tabs的导航事件,在目标URL触发时手动拉起原生App的跳转逻辑,同时关闭Custom Tabs:
// 声明全局CustomTabsSession变量 private CustomTabsSession customTabsSession; // 创建CustomTabsCallback监听导航事件 CustomTabsCallback navigationCallback = new CustomTabsCallback() { @Override public void onNavigationEvent(int eventType, Bundle extras) { super.onNavigationEvent(eventType, extras); // 监听跳转开始事件 if (eventType == CustomTabsCallback.NAVIGATION_STARTED) { String targetUrl = extras.getString(CustomTabsCallback.EXTRA_URL); // 校验是否是你要触发App Links的目标URL if (isTargetAppLink(targetUrl)) { // 手动构建App Links跳转Intent Intent appLinkIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(targetUrl)); appLinkIntent.setPackage(getPackageName()); // 指定当前包名,确保触发App Links startActivity(appLinkIntent); // 关闭当前Custom Tabs if (customTabsSession != null) { customTabsSession.closeTab(); } } } } }; // 绑定Chrome的CustomTabsService,关联回调 CustomTabsClient.bindCustomTabsService(this, "com.android.chrome", new CustomTabsServiceConnection() { @Override public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) { client.warmup(0L); customTabsSession = client.newSession(navigationCallback); CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(customTabsSession); // 配置Custom Tabs的样式(比如关闭按钮) builder.setCloseButtonIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_close)); CustomTabsIntent customTabsIntent = builder.build(); // 启动Custom Tabs加载初始注册页面 customTabsIntent.launchUrl(MainActivity.this, Uri.parse(initialRegistrationUrl)); } @Override public void onServiceDisconnected(ComponentName name) { customTabsSession = null; } });
注意:isTargetAppLink()需要你自己实现,用来判断当前URL是否匹配你的App Links规则(比如包含特定域名或路径)。
2. 调整assetlinks.json配置(辅助优化)
虽然包名相同,但你可以在assetlinks.json中明确声明URL的处理权限,强化Chrome对App Links的识别:
[{ "relation": ["delegate_permission/common.handle_all_urls"], "target": { "namespace": "android_app", "package_name": "your.app.package.name", "sha256_cert_fingerprints": ["your_app_sha256_fingerprint"] } }]
这个配置主要是加固App Links的有效性,但同一应用内的Custom Tabs跳转还是需要配合上面的拦截逻辑才能生效。
3. 替代方案:改用WebView实现注册流程
如果Custom Tabs的配置太繁琐,直接用WebView可能更灵活。你可以在WebView的shouldOverrideUrlLoading方法中拦截目标URL,手动触发App Links跳转:
WebView registrationWebView = findViewById(R.id.webview_registration); registrationWebView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); if (isTargetAppLink(url)) { // 触发App Links跳转 Intent appLinkIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(appLinkIntent); // 返回true表示拦截该跳转,不在WebView中加载 return true; } return super.shouldOverrideUrlLoading(view, request); } }); // 加载初始注册页面 registrationWebView.loadUrl(initialRegistrationUrl);
这个方案对注册流程来说更可控,你还可以自定义WebView的导航栏、进度条等,适配App的整体风格。
总结一下:核心问题是Chrome对同包名Custom Tabs的导航逻辑限制,所以要么拦截跳转手动触发App Links,要么改用WebView实现更灵活的URL控制。
内容的提问来源于stack exchange,提问作者Filip Marusca

