Android原生とH 5のインタラクションの実現

10481 ワード

モバイルインターネットの急速な発展に伴い、従来の開発速度は市場の需要を満たすことができなくなった.原生H 5混合開発が誕生し、現在、市場では多くの主流応用が混合開発に用いられている.例えば、支付宝、美団などである.以下、私自身の開発経験と結びつけて、混合開発に対する認識と実現方式を簡単に話します.
ハイブリッド開発の利点
利点は明らかで、フロントエンドエンジニアが1つのページを書くことで、複数のプラットフォームが実行でき、androidとiosエンジニアの多くのことを節約し、無形に開発効率を高め、開発コストを節約した.
欠点
使用したことのある人なら誰でも知っているように、H 5のインタフェースは携帯電話に表示され、クリック、タッチ、スライドなどのイベントへの応答は原生コントロールほどスムーズではなく、カートンも現れる.これも普通で、体験がオリジナルコントロールと同じように良ければ、android(ios)エンジニアには何もありません.
H 5原生を呼び出す方式
方法はいろいろあるかもしれませんが、私自身の開発経験に基づいて、私は2つの方法に触れたことがあります.
第1種
1.まずWebViewを初期化する
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true); //   WebView   js

2.jsに呼び出し可能なメソッドを提供するためのクラスJavaScriptMetMetodを作成する
3.このクラスの構築方法を作成し、2つのパラメータ、WebViewオブジェクトとコンテキストオブジェクトを提供する
private Context mContext;
    private WebView mWebView;
    public JavaScriptMethod(Context context, WebView webView) {
        mContext = context;
        mWebView = webView;
    }

4.androidとjsが通信するインタフェース、すなわち文字列マッピングオブジェクトとして文字列定数を作成する
public static final String JAVAINTERFACE = "javaInterface";

5.次に、js呼び出しを作成する方法です.メソッドのパラメータはjson文字列を受信します(注意:Android 4.2以降、コードセキュリティを向上させるために、メソッドは注釈@JavascriptInterfaceを使用する必要があります.そうしないと呼び出せません).
@JavascriptInterface
    //andorid4.2(  android4.2)  ,       ,js    android  
    public void showToast(String json){
        Toast.makeText(context, json, Toast.LENGTH_SHORT).show();
    }

6.WebView初期化コードで次のコードを実行します.
//          
    JavaScriptMetod m = new JavaScriptMetod(this, webview);
    //      js,            ,  js            
    //                
    webview.addJavascriptInterface(m, JavaScriptMetod.javaInterface);

これでjsでJavaScriptMettodのメソッドを呼び出すことができます.呼び出し方法は次のようになります.
//     json  
    var json = {"name":"javascript"};
    //javaInterface             
    window.javaInterface.showToast(JSON.stringify(json));

ネット上でjsとandroidの原生的なインタラクションを紹介する文章の中で、大部分は上のような方式ですが、この方式はios、つまりwindowには適用されません.javaInterface.showToast(JSON.stringify(json))のようなjsコードはiosには適用されませんが、以上の方法ではandroidとiosのそれぞれにjsコードを1セット書かなければなりません.これは明らかに不合理であるため,実際の開発では次の2つ目の方法が一般的に用いられる.
第2種
この方法は、jsがurl要求を発行し、必要なパラメータをurlに追加することを意味する.Android端末はwebViewを通ります.setWebViewClient()urlをブロックし、urlに含まれるパラメータを解析し、パラメータ情報に基づいて対応する操作を行います.
1.メソッドと同様に、まずwebviewを初期化する必要がある
    WebSettings settings = webview.getSettings();
    settings.setJavaScriptEnabled(true); //   WebView   js

2.まずjsのコードがどのように書かれているかを見て、
$("#showtoast").click(function () {
        var json = {"data": "I am a toast"};
       window.location.href="protocol://android?code=toast&data="+JSON.stringify(json);
    });
    $("#call").click(function () {
        var json = {"data": "10086"};
       window.location.href="protocol://android?code=call&data="+JSON.stringify(json);
    });

ここでは、android表示トーストと電話の操作をそれぞれ制御する2つのクリックイベントを定義します.ここで、protocol://androidカスタムH 5とandroid間の通信プロトコルをhttpリクエストと区別する.codeは行う操作を規定し,dataは伝送されるデータである.
2.androidのコード
webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                /**
                 *         url    pre,    http      android     
                 */
                String pre = "protocol://android";
                if (!url.contains(pre)) {
                    // url http  , webview  url
                    return false;
                }
                // url   android     ,    url           
                Map map = getParamsMap(url, pre);
                String code = map.get("code");
                String data = map.get("data");
                parseCode(code, data);
                return true;
            }
        });

ここで、getParamsMap()メソッドは、ブロックされたurlからcode、dataパラメータ、parseCode()メソッドを解析し、コードは以下の通りです.
private Map<String, String> getParamsMap(String url, String pre) {
        ArrayMap<String, String> queryStringMap = new ArrayMap<>();
        if (url.contains(pre)) {
            int index = url.indexOf(pre);
            int end = index + pre.length();
            String queryString = url.substring(end + 1);

            String[] queryStringSplit = queryString.split("&");

            String[] queryStringParam;
            for (String qs : queryStringSplit) {
                if (qs.toLowerCase().startsWith("data=")) {
                    //    data ,  data   &   
                    int dataIndex = queryString.indexOf("data=");
                    String dataValue = queryString.substring(dataIndex + 5);
                    queryStringMap.put("data", dataValue);
                } else {
                    queryStringParam = qs.split("=");

                    String value = "";
                    if (queryStringParam.length > 1) {
                        //          , “key=”  
                        value = queryStringParam[1];
                    }
                    queryStringMap.put(queryStringParam[0].toLowerCase(), value);
                }
            }
        }
        return queryStringMap;
    }

    private void parseCode(String code, String data) {
        if(code.equals("call")) {
            try {
                JSONObject json = new JSONObject(data);
                String phone = json.optString("data");
                //        ,      
                PhoneUtils.call(this, phone);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return;
        }
        if(code.equals("toast")) {
            try {
                JSONObject json = new JSONObject(data);
                String toast = json.optString("data");
                Toast.makeText(this, toast, Toast.LENGTH_SHORT).show();
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return;
        }
    }

最後に、shouldOverrideUrlLoading()メソッドの戻り値の問題について特に説明します.このメソッドの戻り値は3つあります.
1.trueを返します.すなわち、コードロジックに基づいて対応する操作を実行し、webviewはurlをロードしません.
2.falseを返し、対応するコードを実行する以外、webviewはurlをロードします.
3.superを返します.shouldOverrideUrlLoading()は、親クラスにポイントを入れると、falseが戻ってくるのか見えます.