1. 程式人生 > >WebView無法調起微信、支付寶 (net::ERR_UNKNOWN_URL_SCHEME)

WebView無法調起微信、支付寶 (net::ERR_UNKNOWN_URL_SCHEME)

一. 問題情景

最近開發時遇到一個充值繳費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);

最後執行專案,如果之前微信未登入會跳轉到登入頁面(下左圖),如果登入了會跳轉到支付頁面(下右圖)。