Chrome Custom Tabs如何区分关闭与重定向并设置Activity返回结果
问题说明
首先说结论:Chrome Custom Tabs 没有开放任何API允许调用方自定义关闭按钮触发的Activity返回结果。所有用户主动点关闭、浏览器异常退出、重定向后Custom Tabs自动退栈的场景,都会固定返回RESULT_CANCELED状态,返回的intent里也没有附带可区分场景的字段,你不可能直接通过返回码本身区分是用户主动关闭,还是触发重定向回到了应用。
可行实现方案
你只能通过重定向链路的专属标识做场景区分,根据你的业务场景选下面两种实现方式就行:
方案1:通过DeepLink/AppLink接收重定向(官方推荐,兼容性最好)
这是OAuth授权、支付跳转这类场景的标准实现:
- 先给应用配置专属自定义Scheme或者App Link作为重定向目标地址,比如
your-app://custom-tab-callback?flow=auth - 启动Custom Tabs之前,在当前页面的页面级缓存(比如ViewModel成员变量、页面的onSaveInstanceState状态)里存一个布尔标记
customTabsFlowRunning = true - 重定向触发时,系统会通过你在Manifest里配置的intent-filter唤起对应页面,你在解析到重定向参数的时候,先把
customTabsFlowRunning置为false,直接处理重定向对应的业务逻辑 - 当你收到Custom Tabs的
RESULT_CANCELED回调时,先检查这个标记位:- 如果标记已经是false,说明之前已经处理过重定向事件,这次cancel是重定向后Custom Tabs自动关闭触发的,直接忽略即可
- 如果标记还是true,说明是用户主动点击关闭按钮退出了Custom Tabs,走对应的取消业务逻辑就行
踩坑提示:重定向触发DeepLink跳回你应用的时候,Custom Tabs本身的退栈行为依然会触发一次
RESULT_CANCELED回调,这就是你之前没法区分两种场景的根本原因,不要试图从这个cancel回调的参数里找区分字段,根本不存在。
方案2:在启动Custom Tabs的原页面直接接收重定向
如果你不想让重定向走全局intent-filter新开页面实例,想直接在启动Custom Tabs的原Activity里拿到重定向参数,可以配合PendingIntent实现:
- 调用原Activity的
createPendingResult方法生成专属PendingIntent,给它分配和启动Custom Tabs不同的requestCode,用来区分重定向回调 - 通过
CustomTabsIntent.Builder的相关配置把重定向事件绑定到这个PendingIntent上,重定向触发时参数会直接带回原Activity的onActivityResult回调 - 标记位判断逻辑和方案1完全一致:收到重定向回调就把流程标记为已完成,后续收到的cancel回调直接忽略。
注意事项
- 不要尝试用反射修改Custom Tabs的返回逻辑,Chrome、Edge、三星浏览器等不同支持Custom Tabs的浏览器实现差异极大,反射方案没有任何兼容性保障,线上大概率出诡异问题
- 你问题里贴的启动代码少了标准的launchUrl调用,直接给intent设置data在部分浏览器上会出现兼容问题,建议改成标准写法:
fun launchURL(context: Context, url: String, requestCode: Int) { val builder = CustomTabsIntent.Builder() val customTabsIntent = builder.build() // 替换直接设置intent.data的写法,用SDK提供的标准launchUrl方法 customTabsIntent.launchUrl(context, Uri.parse(url)) (context as Activity).startActivityForResult(customTabsIntent.intent, requestCode) }
- 如果项目已经用了AndroidX Activity Result API,建议把上述标记位判断逻辑封装成自定义的ActivityResultContract,避免每个业务页面写重复的判断代码。
内容的提问来源于stack exchange,提问作者Peter Helmy
相关产品推荐
相关产品推荐

