一. 问题情景
最近开发时遇到一个充值缴费bug,就是当我们选择以微信方式进行交费充值时不能正常跳转到微信页面,始终提示异常,如下图
可以看到失败的页面加载的url是自定义scheme开头的(weixin://
)。默认情况下webview只能识别http://
或https://
开头的url, 因此如果要识别其他的scheme (如: alipays、weixin、mailto、tel ... 等等), 你就要自行处理. 一般其他的scheme都是由原生APP处理, 即用一个Intent去调起能处理此scheme开头的url的APP. 代码如下:
//customUrl是一个由自定义的scheme开头的url, 如: alipays://appid=211985831&user=......
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(customUrl));
startActivity(intent);
APP中如果你的某个页面要支持某个scheme可以像微信一样如下这样定义:
<activity
android:excludeFromRecents="true"
android:exported="true"
android:launchMode="singleTop"
android:name="com.tencent.mm.plugin.base.stub.WXCustomSchemeEntryActivity"
android:taskAffinity=".wxpayentry"
android:theme="@style/m4">
<intent-filter>
<data android:scheme="weixin"/> <!-- 自定义的scheme -->
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
必须注意的是, 用intent处理自定义的scheme开头的url时, 代码必须加上try...catch... , 应为如果你的手机上没有安装处理那个scheme的应用 (整个手机上没有一个应用能处理那个scheme), 那么就会crash (这跟隐式启动Activity是一个道理)!
二. 解决方法
给WebView设置WebViewClient并重写WebViewClient的shouldOverrideUrlLoading()方法,完整代码如下:
WebViewClient webViewClient = new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if(url == null) return false;
try {
if(url.startsWith("weixin://") || url.startsWith("alipays://") ||
url.startsWith("mailto://") || url.startsWith("tel://")
//其他自定义的scheme
) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
} catch (Exception e) { //防止crash (如果手机上没有安装处理某个scheme开头的url的APP, 会导致crash)
return false;
}
//处理http和https开头的url
wv.loadUrl(url);
return true;
}
};
webview.setWebViewClient(webViewClient);
最后运行项目,如果之前微信未登录会跳转到登录页面(下左图),如果登录了会跳转到支付页面(下右图)。