一. 问题
最近app出了个问题, 就是在webview中无法调起微信、支付宝。
错误页面如下:
可以看到两个失败的页面加载的url都是自定义scheme开头的(alipays://
、weixin://
)。webview只能识别http://
或https://
开头的url, 因此如果要识别其他的scheme (如: alipays、weixin、mailto、tel ... 等等), 你就要自行处理. 一般其他的scheme都是由原生APP处理, 即用一个Intent去调起能处理此scheme开头的url的APP. 代码如下:
//customUrl是一个由自定义的scheme开头的url, 如: alipays://appid=2387834&user=......
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(customUrl));
startActivity(intent);
APP中, 如果你的某个页面要支持某个scheme可以像如下这样定义:
Gmail中自定义的scheme
<activity
android:autoRemoveFromRecents="true"
android:documentLaunchMode="1"
android:exported="true"
android:label="@string/app_name"
android:name="com.google.android.gm.ComposeActivityGmailExternal"
android:theme="@style/ComposeTheme">
<intent-filter>
<action android:name="android.intent.action.SENDTO"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="mailto"/> <!-- 自定义scheme -->
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="mailto"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<!-- 自定义scheme、host、...... 等属性 -->
<data android:host="ui.email2.android.com" android:pathPrefix="/compose" android:scheme="content"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:host="gmail-ls"/>
<data android:scheme="gmail2from"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.google.android.voicesearch.SELF_NOTE"/>
<data android:mimeType="*/*"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="*/*"/>
</intent-filter>
</activity>
微信中自定义的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);
关于自定义Scheme可以参考官网说明: https://developer.android.com/training/basics/intents/filters.html
网友评论