WebView无法调起微信、支付宝 (net::ERR_UNKN

2016-12-07  本文已影响22981人  元亨利贞o

一. 问题
最近app出了个问题, 就是在webview中无法调起微信、支付宝。
错误页面如下:

failed.png

可以看到两个失败的页面加载的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

上一篇 下一篇

猜你喜欢

热点阅读