AndroidでWindVaneを使って出会った穴

14613 ワード

最近ではAndroidでH 5ページを表示する必要があり、H 5とNativeの間に多くのインタラクションがあるため、WindVaneを採用しています.
1.WindowVane JsBridgeの使い方
プロフィール:
WindVane JsBridgeは、JSとNativeとの間の通信リンクを提供し、この通信基盤に基づいて、Nativeは、いくつかのサービスAPIがJS呼び出しに提供されることを暴露し、方法によって値またはイベントを返してデータをJSに返すことができる.
JS側はClassName.HandlerNameを使用してJsBridgeを呼び出し、WindVaneはClassNameとHandlerNameに基づいて対応するNativeメソッドを見つけます.
JSPBridgeの登録:
JsBridgeはWindVaneに登録する必要があり、JSが対応するNativeメソッドを正しく呼び出すことができます.
Androidは静的登録方法のみを提供しています.
public class MyJSBridge extends WVApiPlugin {


    @Override
    public boolean execute(String action, String params, WVCallBackContext wvCallBackContext) {
        if ("showToast".equals(action)) {
            showToast(params, wvCallBackContext);
            return true;
        }
        return false;
    }

    private void showToast(String params, WVCallBackContext wvCallBackContext) {
        if (params != null && params.length() > 0) {
            try {
                JSONObject jsonObject = new JSONObject(params);
                String content = jsonObject.optString("content");
                Toast.makeText(mContext, content, Toast.LENGTH_SHORT).show();
                wvCallBackContext.success();
            } catch (JSONException e) {
                e.printStackTrace();
                wvCallBackContext.error();
            }
        } else {
            wvCallBackContext.error();
        }
    }
}

特定のクラスを登録します.WVPluginManager.registerPlugin("MyJSBridge", MyJSBridge.class);
注意:第1パラメータはクラス名であり、「MyJsBridge」の具体的な文字列のクラス名でなければならない.「MyJsBridge.class.getSimpleName()」のように動的に取得されたクラス名ではない.Releaseパッケージではクラスが混同され、取得されたクラス名は「MyJsBridge」ではないからだ.これにより、クラス混同が行われていないため、Debugパッケージで正しくデバッグできますが、Releaseでエラーが発生します.
jsコードで呼び出すには、次の手順に従います.
var params = {
    'content': 'Something to Native',
};
window.WindVane.call('MyJSBridge', 'showToast', params, function(e) {
    alert('success' + JSON.stringify(e));
}, function(e) {
    alert('failure' + JSON.stringify(e));
});

さらに、WindVaneは、上述のH 5がJsBridgeを介してNativeを呼び出す方法に加えて、標準的なイベントメカニズムを提供する.
ここでH 5はNativeにイベントを送信する:
var params = {
    event: 'eventName',
    param: {
        //         。
    }
};
window.WindVane.call('WVStandardEventCenter','postNotificationToNative', params, function(e) {
    alert('success');
}, function(e) {
    alert('failure: ' + JSON.stringify(e));
});

AndroidではWVEventListenerインタフェースを実装する必要があります.
@import android.taobao.windvane.service;
@import android.taobao.windvane.standardmodal
//   ,           Listener。
public class JsEventListener implements WVEventListener {
    @Override
    public WVEventResult onEvent(int id, WVEventContext ctx, Object... obj) {
        //           ,WVEventId.H5TONATIVE_EVENT    H5        。
        if (id == WVEventId.H5TONATIVE_EVENT) {
            if (obj[0] instanceof String) {
                String params = (String)obj[0];
                //     params     event   param   JSON String,        。
            }
        }
        return null;
    }
}
//   ,     。
WVEventService.getInstance().addEventListener(new JsEventListener());

この上の2つの方法は,H 5がNativeと対話できる.第1の方法は、主にH 5がデバイス情報、ユーザ情報などのいくつかのNativeのいくつかの情報を取得するために使用される.第2の方法は、主にH 5がUI変更のためにNativeにいくつかのデータ通知を伝達する.
2.Httpsへのアクセスに関するリンク
Httpsリンクにアクセスすると、証明書検証の問題で通常SSL検証エラーが発生し、ページのロードに失敗します.WebViewClientクラスには、次の方法があります.
    /**
     * Notify the host application that an SSL error occurred while loading a
     * resource. The host application must call either handler.cancel() or
     * handler.proceed(). Note that the decision may be retained for use in
     * response to future SSL errors. The default behavior is to cancel the
     * load.
     *
     * @param view The WebView that is initiating the callback.
     * @param handler An SslErrorHandler object that will handle the user's
     *            response.
     * @param error The SSL error object.
     */
    public void onReceivedSslError(WebView view, SslErrorHandler handler,
            SslError error) {
        handler.cancel();
    }

前述したように、SSL検証エラーが発生した場合、デフォルトではリクエストがキャンセルされます.これにより、WebViewはH 5ページをロードしましたが、H 5は表示できません.したがって、SSLエラーに関係なくWebViewにH 5ページのロードを継続させるには、WebViewClientクラスのonReceivedSslErrorメソッドを上書きする必要があります.
   @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                //     super,          ,        handler.cancel()
                //          ,  SSL  ,      
                handler.proceed();
            }

3.クラスメソッドとクラスメソッドの混同について
Releaseパッケージを発行する場合、クラスとクラスメソッドの混同が行われますが、最初の静的登録メソッドを使用する場合、H 5がNativeに通知するとエラーが発生します.Serializableインタフェースを実装し,逆シーケンス化する簡単な方法がある.
public class MyJSBridge extends WVApiPlugin implements Serializable

しかし,この方法の前提はproguard−rules.proファイルにSerializableインタフェースを実現するクラスとクラスを調製する方法が混同されないことである.構成のルールは次のとおりです.
-keep class * implements java.io.Serializable

-keepclassmembers class * implements java.io.Serializable {
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient ;
    !private ;
    !private ;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

この方法に加えて、同じように、プロジェクトのproguard-rules.proファイルに混同されないクラスメソッドとクラスメソッドを構成することもできます.構成のルールと例については、ProGuard manualを参照してください.
しかし、これが混同されないと、逆コンパイルでソースコードが表示されやすいので、コードを書くときはできるだけコードの安全性に注意してください.
4.WebViewメモリ漏洩
WindVaneのWVWebViewを使用すると、次のようなメッセージが表示されます.
WVWebViewを直接使用することもできますが、WVWebViewを直接使用する場合は、対応するライフサイクルで処理され、特に破棄される場合に注意する必要があります.このwebviewを夫viewから削除してから呼び出すwebviewのdestroy操作を必ず行います.
実際には、WVWebViewを使用してもWebViewを単独で使用してもメモリ漏洩に注意しなければならないため、ActivityやFragmentでは必ずWebViewを破棄しなければならない.
   @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mWebView != null) {
            //      destroy()  ,    if (isDestroyed()) return;     ,   onDetachedFromWindow(), 
            // destory()
            ViewParent parent = mWebView.getParent();
            if (parent != null) {
                ((ViewGroup) parent).removeView(mWebView);
            }
            //         ,       ,           
            mWebView.getSettings().setJavaScriptEnabled(false);
            mWebView.clearHistory();
            mWebView.clearCache(true);
            mWebView.onPause();
            mWebView.removeAllViews();
            mWebView.destroyDrawingCache();
            mWebView.destroy();
        }
    }

5.テクニックを使う
スクロールバーを非表示:
 webView.setVerticalScrollBarEnabled(false);
 webView.setHorizontalScrollBarEnabled(false);

スクロール禁止:
webView.setFocusable(false);
webView.setFocusableInTouchMode(false);

加速レンダリング:
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        webView.setWebViewClient(new WebViewClient() {

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
            }

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                //     super,          ,        handler.cancel()
                // super.onReceivedSslError(view, handler, error);
                //          ,  SSL  ,      
                handler.proceed();
            }
        });

JavaScriptインタフェースへのアクセス:
webView.getSettings().setJavaScriptEnabled(true);

ホワイトスクリーン、DOM storageをサポートする必要があります:
webView.getSettings().setDomStorageEnabled(true);

参考:1.Android 5.1 WebViewメモリリーク分析2.Disable scrolling in webview?