Android WebView 在华为 MATE PRO 40 上无法调起支付宝
结论
这类问题通常不是”华为 MATE 40 Pro 不支持支付宝”,而是支付跳转链路在特定系统版本、WebView 版本或审核环境下遇到了兼容性问题。
建议先排查以下几项:
- 是否处理了
alipays://、alipay://、intent://等实际跳转形式,而不只是判断字符串是否以"alipay"开头。 - 是否同时实现了新旧两个
shouldOverrideUrlLoading()回调,并正确处理返回值。 - Android 11 及以上系统是否因为”应用包可见性”限制,把已经安装的支付宝误判为未安装。
- 审核设备是否安装并启用了支付宝,是否使用了应用分身、隐私空间或受管控账户。
- 支付页面是否通过
window.open()、新窗口、302 重定向或中间页拉起支付宝。 - 是否捕获后忽略了
ActivityNotFoundException、URISyntaxException等异常,导致审核人员点击后只看到”没有反应”。
只判断 URI 是否以 "alipay" 开头,覆盖不了所有支付跳转情况。
推荐的 WebView 跳转处理方式
不要只做简单的前缀匹配。可以先放行普通 HTTP 链接,再把其他外部协议交给系统处理。
private boolean handleUrl(Context context, String url) {
if (url == null || url.isEmpty()) {
return false;
}
Uri uri = Uri.parse(url);
String scheme = uri.getScheme();
// 普通网页继续由 WebView 加载
if ("http".equalsIgnoreCase(scheme)
|| "https".equalsIgnoreCase(scheme)) {
return false;
}
try {
Intent intent;
if ("intent".equalsIgnoreCase(scheme)) {
intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
// 防止外部页面借此启动不必要的内部组件
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setComponent(null);
intent.setSelector(null);
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
String fallbackUrl =
intent.getStringExtra("browser_fallback_url");
if (fallbackUrl != null
&& (fallbackUrl.startsWith("https://")
|| fallbackUrl.startsWith("http://"))) {
return false;
}
throw e;
}
} else {
intent = new Intent(Intent.ACTION_VIEW, uri);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
context.startActivity(intent);
}
return true;
} catch (ActivityNotFoundException e) {
// 设备未安装可处理该协议的应用,或相关组件被禁用
showPayError("未检测到可用的支付宝,请确认支付宝已安装并启用");
return true;
} catch (URISyntaxException | SecurityException e) {
// 建议同时记录原始 URL、系统版本和 WebView 版本
reportPayLaunchError(url, e);
showPayError("无法打开支付宝,请稍后重试");
return true;
}
}
还要同时实现新旧两个 shouldOverrideUrlLoading() 回调,以兼容不同系统和 WebView 的行为:
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(
WebView view,
WebResourceRequest request
) {
return handleUrl(view.getContext(), request.getUrl().toString());
}
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(
WebView view,
String url
) {
return handleUrl(view.getContext(), url);
}
});
返回值的含义需要特别注意:
- 返回
true,表示应用已经处理该 URL,WebView 不应继续加载。 - 返回
false,表示该 URL 仍由 WebView 加载。
如果已经启动支付宝却返回 false,部分 WebView 版本还会继续尝试加载自定义协议,可能出现错误页、白屏或跳转被覆盖。
排查 Android 11 的应用包可见性
MATE 40 Pro 的审核设备可能运行 Android 11 或更高版本。从 Android 11 开始,系统会限制应用查询其他已安装应用。
如果代码在跳转前调用了以下方法:
getPackageManager().getPackageInfo(...);
resolveActivity(...);
queryIntentActivities(...);
即使设备已经安装支付宝,也可能因为应用没有声明查询范围而返回”未安装”,或者查询不到对应的 Activity。可以根据实际查询方式,在 AndroidManifest.xml 中添加 <queries>:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<queries>
<package android:name="com.eg.android.AlipayGphone" />
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="alipays" />
</intent>
</queries>
<application>
...
</application>
</manifest>
<queries> 主要影响”查询是否存在”的逻辑。直接调用 startActivity() 和提前使用 resolveActivity() 检查并不完全相同。因此,不建议仅凭一次查询结果阻止支付跳转。更稳妥的做法是直接尝试启动,并捕获 ActivityNotFoundException。
支付宝的包名、Scheme 和接入方式,应以当前使用的支付宝官方 SDK 或支付产品文档为准,不要只依赖硬编码字符串。
检查真实跳转 URL
代码判断字符串以 "alipay" 开头,不等于支付页面最终一定会产生这种 URL。实际链路中可能出现:
alipays://...
alipay://...
intent://...
https://...
跳转也可能先经过多个 HTTP 302 重定向,最后才进入自定义 Scheme。建议记录以下信息:
- 用户点击支付按钮时的页面 URL。
shouldOverrideUrlLoading()收到的完整 URL。- Scheme、Host 和重定向次数。
- 是否执行了
startActivity()。 - 捕获到的异常类型和异常信息。
- Android 版本、WebView 版本和支付宝版本。
- 支付页面返回的订单或接口错误码,但不要记录完整支付参数、Token 或签名。
如果日志只写”进入了支付方法”,仍然无法判断问题出在网页、WebView,还是系统 Intent 阶段。
检查新窗口和 JavaScript 跳转
部分商城支付页不会直接修改当前页面地址,而是调用:
window.open(payUrl)
或者使用:
<a href="..." target="_blank">
遇到这种情况,URL 可能进入 WebChromeClient.onCreateWindow(),而不是预期中的 shouldOverrideUrlLoading()。如果商城确实通过新窗口跳转,需要补充相应处理:
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSupportMultipleWindows(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onCreateWindow(
WebView view,
boolean isDialog,
boolean isUserGesture,
Message resultMsg
) {
WebView newWebView = new WebView(view.getContext());
newWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(
WebView view,
WebResourceRequest request
) {
return handleUrl(view.getContext(),
request.getUrl().toString());
}
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(
WebView view,
String url
) {
return handleUrl(view.getContext(), url);
}
});
WebView.WebViewTransport transport =
(WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(newWebView);
resultMsg.sendToTarget();
return true;
}
});
是否要开启多窗口,需要根据商城页面的具体实现决定。如果可以修改 H5,更推荐在当前页面完成跳转,以减少临时 WebView 引起的生命周期、Cookie 和内存问题。
检查审核环境
审核报告只能说明支付在特定测试环境中没有成功拉起,不能直接证明这是机型硬件问题。还需要确认:
- 审核设备是否安装了支付宝。
- 支付宝是否被停用、冻结或限制后台启动。
- 测试账号是否处于隐私空间、访客模式或工作资料中。
- 应用和支付宝是否位于不同的用户空间。
- 是否使用了应用分身。
- 是否出现过系统弹窗,但被测试人员拒绝。
- 网络环境是否导致支付中间页未能取得有效跳转地址。
- 测试订单是否失效、重复支付或被风控拦截。
找不到可处理该协议的应用时,至少要向用户显示明确提示,不能让按钮点击后静默失败。
还应检查的 WebView 配置
如果支付页面本身没有正常加载,流程可能根本没有执行到拉起支付宝这一步。可以继续检查:
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setCookieEnabled(true);
其中,setCookieEnabled() 不是 WebSettings 的方法。Cookie 应通过 CookieManager 配置:
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.setAcceptThirdPartyCookies(webView, true);
是否必须开启第三方 Cookie,要根据商城的登录和支付链路决定。此外还要检查:
- HTTPS 页面中是否加载了 HTTP 资源。
- H5 是否依赖第三方 Cookie 或本地存储。
- 是否存在证书错误,以及
onReceivedSslError()是否处理不当。 - Release 包是否因为混淆、渠道配置、签名或域名环境不同,表现与本地测试包不一致。
- 华为市场审核包是否连接正式环境,而本地测试使用测试环境。
- 支付返回页是否被错误的应用深链配置拦截。
不要通过无条件调用 handler.proceed() 绕过 HTTPS 证书错误。这会带来严重的安全风险,也可能影响应用审核。
没有真机时的验证办法
可以先制作一个最小测试页面,分别测试以下链接:
<a href="alipays://platformapi/startapp">测试 alipays</a>
<a href="intent://example#Intent;scheme=alipays;end">测试 intent</a>
<a href="https://example.com">测试 HTTPS</a>
这些示例只用于验证 WebView 回调和 Intent 分支,不代表有效的支付宝业务地址。
测试时应使用与审核包完全相同的 Release 构建,再通过云真机、远程设备测试服务,或能提供该机型的测试人员复现。复现过程中,应重点获取完整的跳转 URL 和异常日志,而不只是录制一段”点击无反应”的视频。
综合现有信息,建议优先检查 intent:// 是否遗漏、Android 11 包可见性判断是否误判、是否只实现了一个 shouldOverrideUrlLoading() 回调,以及支付页是否通过新窗口发起跳转。这几项最容易造成”手头设备正常,但特定审核设备无法拉起”的差异。
备注:内容仅供参考。
