h5 和native 互動那些事兒

5個月後玩翻天發表於2018-11-06

前端菜菜一枚,寫下關於h5 和native 互動那些事情。偏前端,各種理論知識,不在贅述。之前有各位大牛已經寫過。我只寫程式碼,有問題,下面留言


/* 關於h5 和native 之間的互動 JSBridge 解決問題,偏向前端
 * 使用URL 攔截方式,借用iframe 
 */

    /**
     * ios,使用自有shouldStartLoadWithRequest 方法
     * 安卓:shouldOverrideUrlLoading
     * html5:掛載到window 物件上
     * 
     */複製程式碼

html5部分:
dom:

 <button onclick="showLoading()"> showLoading</button>
  <button onclick="closeLoading()"> closeLoading</button>
  <button onclick="showAlert()">showAlert</button>
  <button onclick="toast()">toast</button>
  <button onclick="pending_payment()">pending_payment</button>


script:



 var bridge = {
      'linkNative': function (func, type, params, callback) {
        var funcId = 'cb_' + +new Date()
         window[funcId] = callback || function () { }
        params = params || {}

        var req = {
          handler: func,
          params: params || undefined,
          callback: callback && funcId
        }
        var src = 'test://' + type + '?' + JSON.stringify(req)

        var frag = document.createElement('iframe')
        frag.style.display = 'none'

        frag.src = src
        document.body.appendChild(frag);
        setTimeout(function () {
          document.body.removeChild(frag)
        }, 1000)
      },
      'showLoading': function () {

        this.linkNative('showLoading', 'functional')
        return this
      },
      'closeLoading': function () {
        this.linkNative('closeLoading', 'functional')
        return this
      },
      'showAlert': function (params) {
        this.linkNative('showAlert', 'functional', params)
      },
      'toast': function (params) {
        this.linkNative('toast', 'functional', params)
        return this
      },
      // 發起支付請求
      'pending_payment': function (params, callback) {
        this.linkNative('pending_payment', 'business', params, callback)
      }
    }




    //開啟loading
    function showLoading() {
      console.log('a')
      bridge.showLoading()
    }
    function closeLoading() {
      bridge.closeLoading()
    }
    function showAlert() {
      bridge.showAlert('我點選了showAlert')
    }
    function toast() {
      var params = {
        data: "我是toast"
      }
      bridge.toast(params)
    }
    function pending_payment() {
      var params = {
        orderId: '12uroi2u4oifjidsafj',
        time: '1234234392483294829',
        name: '張三'
      }
      bridge.pending_payment(params, function () {
     
        bridge.showAlert('支付的回撥函式')
        //其他業務程式碼
      })
    }複製程式碼


這是在和native端約定好的協議和方法 test,functional,buness

複製程式碼


參考:https://juejin.im/post/5bda6f276fb9a0226d18931f

安卓demo:
JSonUtils.java


package com.example.zhangyuke.mywebview;

import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import com.alibaba.fastjson.JSONObject;



public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private WebView wb;
    private String URL_HOST_STARTWITH_FUNCATIONAL = "test://functional";
    private String URL_HOST_STARTWITH_BUSINSS = "test://business";
    private String URL_QUERY_KEY_HANDLER = "handler";
    private String URL_SHOW_LOADING = "showLoading";
    private String URL_CLOSE_LOADING = "closeLoading";
    private String URL_SHOW_ALERT="showAlert";
    private String URL_TOAST="toast";
    private String URL_PENDING_PAYMENT="pending_payment";
    private String URL_QUERY_KEY_CALLBACK="callback";

    private String URL_QUERY_PARAMS="params";
    private String URL_DATA="data";
    private String ORDER_ID="orderId";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        wb = findViewById(R.id.wb);
        //支援js語言
        wb.getSettings().setJavaScriptEnabled(true);
        //縮放至螢幕的大小
        wb.getSettings().setLoadWithOverviewMode(true);
        //支援縮放
        wb.getSettings().setSupportZoom(true);
        //webview去載入網頁
        wb.loadUrl("http://www.jiaxinying.cn./bridge/");
        //設定用自己的瀏覽器開啟
        wb.setWebViewClient(new MyWebViewClient());


    }

    private boolean baseParseShouldOverrideUrlLoading(WebView view, String url, Uri uri) {
        if (url.startsWith(URL_HOST_STARTWITH_FUNCATIONAL)) {
            JSONObject queryObject = JSonUtils.parseObjectWithoutException(uri.getQuery());
            String jsCallback = queryObject.getString(URL_QUERY_KEY_CALLBACK);
            String action = queryObject.getString(URL_QUERY_KEY_HANDLER);
            Log.d(TAG, "test://functional: handler: " + action);
            if (URL_SHOW_LOADING.equals(action)) {
                Toast.makeText(this, "載入進度條", Toast.LENGTH_SHORT).show();
                return true;
            } else if (URL_CLOSE_LOADING.equals(action)) { // 設定標題
                Toast.makeText(this, "關閉進度條", Toast.LENGTH_SHORT).show();
                return true;
            }else if (URL_SHOW_ALERT.equals(action)){
                String params = queryObject.getString(URL_QUERY_PARAMS);
                if (!TextUtils.isEmpty(params)) {
                    Toast.makeText(this, params, Toast.LENGTH_SHORT).show();
                }
            }else if (URL_TOAST.equals(action)){
                String params = queryObject.getString(URL_QUERY_PARAMS);
                if (!TextUtils.isEmpty(params)){
                    JSONObject paramsObject=JSonUtils.parseObjectWithoutException(params);
                    if (paramsObject!=null){
                        String data = paramsObject.getString(URL_DATA);
                        Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
                    }
                }
            }

        } else if (url.startsWith(URL_HOST_STARTWITH_BUSINSS)){
            JSONObject queryObject = JSonUtils.parseObjectWithoutException(uri.getQuery());
            String jsCallback = queryObject.getString(URL_QUERY_KEY_CALLBACK);
            String action = queryObject.getString(URL_QUERY_KEY_HANDLER);
            if (URL_PENDING_PAYMENT.equals(action)){
                String params = queryObject.getString(URL_QUERY_PARAMS);
                if (!TextUtils.isEmpty(params)){
                    JSONObject paramsObject=JSonUtils.parseObjectWithoutException(params);
                    if (paramsObject!=null){
                        String order = paramsObject.getString(ORDER_ID);
//                        Toast.makeText(this, order, Toast.LENGTH_SHORT).show();
                    }
                }
                callBackToJs(jsCallback,"");
            }
        }
        return false;
    }

    //js回撥
    private void callBackToJs(String callbackFunc, String callbackParam) {
        if (TextUtils.isEmpty(callbackFunc)) {
            Log.e(TAG,"callback Func is Null");
        } else {
            wb.loadUrl("javascript:" + callbackFunc + "(" + callbackParam + ")");
        }
    }

    class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            Log.i(TAG,"webView shouldOverrideUrl: " + url);
            Uri uri = Uri.parse(url);
            return baseParseShouldOverrideUrlLoading(view, url, uri);

        }
    }


}
複製程式碼

MainActivity.java

package com.example.zhangyuke.mywebview;

import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;


import java.text.DateFormat;
import java.util.logging.Logger;

/**
 * Created by zhangyuke on 2018/11/6.
 */

public final class JSonUtils {
    private static final String TAG = JSonUtils.class.getSimpleName();

    private JSonUtils() {
        //Utility classes should not have a public or default constructor.
    }

    public static <T> T parseObjectWithoutException(String text, Class<T> clazz) {
        try {
            return JSON.parseObject(text, clazz);
        } catch (Exception ex) {
            Log.e(TAG, "parseObjectWithoutException, exception = " + ex.getMessage());
            return null;
        }
    }

    public static JSONObject parseObjectWithoutException(String text) {
        try {
            return JSON.parseObject(text);
        } catch (Exception ex) {
            Log.e(TAG, "parseObjectWithoutException, exception = " + ex.getMessage());
            return null;
        }
    }
}
複製程式碼

最後,感謝我司阿珂。提供安卓demo文件。


相關文章