本文介绍通过自定义 url scheme 实现外部浏览器操作完成后自动唤起 android 应用并传递回调数据,无需用户手动切回应用,提升 oauth、支付、授权等流程的无缝体验。
本文介绍通过自定义 url scheme 实现外部浏览器操作完成后自动唤起 android 应用并传递回调数据,无需用户手动切回应用,提升 oauth、支付、授权等流程的无缝体验。
在 Android 开发中,当应用跳转至外部浏览器(如 Chrome)执行授权或支付等操作后,常需依赖用户手动返回原应用才能继续流程——这不仅破坏用户体验,还易导致流程中断或超时。理想方案是:浏览器完成操作后,通过特定回调 URL 自动拉起应用,并将结果数据带回前台 Activity。核心实现不依赖 WebSocket 或 Notification Handler(二者适用于长连接或服务端主动推送,与此场景不匹配),也不需要 startActivityForResult(该 API 已废弃,且无法解决后台唤起问题),而是基于 Android 的 Intent 机制 + 自定义 Scheme + onNewIntent() 生命周期回调。
✅ 正确实现步骤
1. 定义自定义 Scheme 并配置 Intent Filter
在 AndroidManifest.xml 中为接收回调的 Activity 添加如下 intent-filter(注意:不要使用 http://127.0.0.1 等无效 host,应使用专属 scheme):
<activity android:name=".CallbackActivity" android:exported="true"><intent-filter><action android:name="android.intent.action.VIEW"></action><category android:name="android.intent.category.DEFAULT"></category><category android:name="android.intent.category.BROWSABLE"></category><!-- 关键:声明自定义 scheme,例如 "myapp" --><data android:scheme="myapp"></data></intent-filter></activity>
⚠️ 注意:android:exported="true" 在 Android 12+ 是必需项; 中仅需 scheme,无需 host 或 port,避免兼容性问题。
2. 构造带回调地址的跳转 Intent
启动浏览器时,将回调 URL 作为参数传入(部分 SDK 或 H5 页面会读取 Referer 或 redirect_uri,但更可靠的方式是直接拼接至目标 URL):
String callbackUrl = "myapp://callback";
String targetUrl = exe + "?redirect_uri=" + Uri.encode(callbackUrl); // 示例:向网页传递回调地址
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(targetUrl));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setPackage("com.android.chrome"); // 可选:指定 Chrome,若未安装则 fallback 到系统浏览器
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
// 降级处理:尝试默认浏览器
intent.setPackage(null);
context.startActivity(intent);
}
? 提示:确保网页侧在完成操作后,执行 window.location.href = "myapp://callback?code=xxx&state=yyy",触发系统唤起你的应用。
3. 在 Activity 中捕获回调数据
在 CallbackActivity(即声明了上述 intent-filter 的 Activity)中重写 onNewIntent(),用于处理应用已在后台运行时的回调:
@Override
protected void onNewIntent(@NonNull Intent intent) {
super.onNewIntent(intent);
setIntent(intent); // 必须调用,否则 getIntent() 仍返回旧 Intent
handleCallbackIntent(intent);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 首次启动时也需处理 Intent(冷启动场景)
handleCallbackIntent(getIntent());
}
private void handleCallbackIntent(Intent intent) {
Uri data = intent.getData();
if (data != null && "myapp".equals(data.getScheme())) {
String code = data.getQueryParameter("code");
String state = data.getQueryParameter("state");
// ✅ 解析参数,执行业务逻辑(如换取 token、跳转主界面等)
processAuthResult(code, state);
}
}
4. 优化用户体验:自动返回主界面
为避免用户停留在空白的 CallbackActivity,可在处理完回调后立即跳转并关闭该页:
private void processAuthResult(String code, String state) {
// 1. 执行业务逻辑(如网络请求)
// 2. 启动主 Activity 并清理任务栈
Intent mainIntent = new Intent(this, MainActivity.class);
mainIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP |
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(mainIntent);
finish(); // 关闭 CallbackActivity
}
? 关键注意事项
- Scheme 命名规范:建议全小写、无下划线、避免与通用协议(如 http, https)冲突,例如 myapp, com.example.auth。
-
Android 12+ 适配:必须为
显式声明 android:exported="true",否则隐式 Intent 将被拒绝。 - H5 侧配合:确保网页端正确构造并跳转 myapp://... URL;若使用 WebView 内嵌,需通过 shouldOverrideUrlLoading 拦截;若为外部浏览器,则依赖其对自定义 Scheme 的支持(Chrome、Safari 均支持)。
- 备选方案:若需更高可靠性(如应对 iOS Universal Links / Android App Links),可进一步配置 assetlinks.json 实现 HTTPS 回调,但本方案已覆盖绝大多数 Android 场景。
通过以上设计,用户完成浏览器操作后,系统将自动拉起你的应用,onNewIntent() 即刻捕获参数,整个流程零手动切换,真正实现“无缝回调”。











