仿微信实现jsbridge通信,封装js-sdk

一、常用通信方式JavascriptInterface

JavascriptInterface这个比较常见不多说了

 

二、通过JSBridge

这种方式主要是为了实现前端异步调用native方法,并回传数据

思路也就是 h5-->android, android--->h5,

消息回传:

 "javascript:JSBridge.onFinish('%s', %s);"
 wx.showToast({ 'msg': 'Hello JSBridge' }, function (res) {
              alert(JSON.stringify(res))
            })

主要代码如下:

1.js实现

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Carson</title>
    <script>
        var callbacks = {};

        var getParam = function (obj) {
            if (obj && typeof obj === 'object') {
                return JSON.stringify(obj);
            } else {
                return obj || '';
            }
        }
        var getPort = function () {
            return Math.floor(Math.random() * (1 << 30));
        }

        var JSBridge = {
            call: function (className, method, params, callback) {
                var port = getPort();
                callbacks[port] = callback;
                var uri = 'jsbridge://' + className + ':' + port + '/' + method + '?' + getParam(params);
                window.prompt(uri, "");
            }
            onFinish: function (port, jsonObj) {
                var callback = callbacks[port];
                callback && callback(jsonObj);
                delete callbacks[port];
            }
        }

        JSBridge.onPayFinished = function(res){
               alert(JSON.stringify(res))
        }
        var wx = {
           showToast: function(param, callback) {
                JSBridge.call('NativeApi', 'showToast', param, callback);
            }
        }

        // <!--由于对象映射,所以调用test对象等于调用Android映射的对象-->
        var callAndroid = function () {
            // 下面会调用java中的 bridge.showToast方法
            wx.showToast({ 'msg': 'Hello JSBridge' }, function (res) {
              alert(JSON.stringify(res))
            })
        }
    </script>
</head>

<body>
<!--点击按钮则调用callAndroid函数-->
<button type="button" id="button1"
        style="width: 500px; height: 100px; font-size:40px; margin-left:40px; margin-top:60px;"
        onclick="callAndroid()">点击调用Android中方法
</button>

</body>

</html>

 

2.android

webview启动后注册接口,这里注册主要是为了把方法加入容器,h5调用时候可以找到:
JSBridge.register(NativeApi.class.getSimpleName(), NativeApi.class);

webview 设置接口client:
private JSBridgeWebChromeClient webChromeClient = new JSBridgeWebChromeClient();
webview.setWebChromeClient(webChromeClient);


public class JSBridgeWebChromeClient extends WebChromeClient {
        @Override
        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
            result.confirm(JSBridge.callJava(view, message));
            return true;
        }
}


主要通过prompt获取数据,并处理:JSBridge.callJava(view, message)

callJava方法中有一个反射,通过h5传递过来的类、方法、参数、端口进行反射到具体方法,具体方法处理后,根据port调用固定的"javascript:JSBridge.onFinish('%s', %s);",传递回h5端口及参数



import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import com.tencent.smtt.sdk.WebView;

import org.json.JSONObject;

import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

/**
 * js通信异步方式
 */

public class JSBridge {

    private static Map<String, HashMap<String, Method>> exposedMethods = new HashMap<>();
    private static Map<String, Object> exposedObjects = new HashMap<>();

    /**
     * 注册
     *
     * @param exposedName className
     * @param clazz       class
     */
    public static void register(String exposedName, Class<? extends ICallBack> clazz) {
        if (!exposedMethods.containsKey(exposedName)) {
            try {
                exposedMethods.put(exposedName, getAllMethod(clazz));
                exposedObjects.put(exposedName, clazz.newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static HashMap<String, Method> getAllMethod(Class injectedCls) throws Exception {
        HashMap<String, Method> mMethodsMap = new HashMap<>();
        Method[] methods = injectedCls.getDeclaredMethods();
        for (Method method : methods) {
            int Modifiers = method.getModifiers();
            if (Modifiers == Modifier.PUBLIC) {
                String name = method.getName();
                mMethodsMap.put(name, method);
            }
        }
        return mMethodsMap;
    }


    // 调用java逻辑
    public static String callJava(WebView webView, String uriString) {
        String methodName = "";
        String className = "";
        String param = "{}";
        String port = "";
        if (!TextUtils.isEmpty(uriString) && uriString.startsWith("jsbridge")) {
            Uri uri = Uri.parse(uriString);
            className = uri.getHost();
            param = uri.getQuery();
            port = uri.getPort() + "";
            String path = uri.getPath();
            if (!TextUtils.isEmpty(path)) {
                methodName = path.replace("/", "");
            }
            //jsbridge://className:callbackAddress/methodName?jsonObj
            // 基于上面的className、methodName和port path调用对应类的方法
            if (exposedMethods.containsKey(className)) {
                HashMap<String, Method> methodHashMap = exposedMethods.get(className);

                if (methodHashMap != null && methodHashMap.size() != 0 && methodHashMap.containsKey(methodName)) {
                    Method method = methodHashMap.get(methodName);
                    if (method != null) {
                        try {
                            Object o = exposedObjects.get(className);
                            method.invoke(o, webView, param, new Callback(webView, port));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return null;
    }

    // 上述程序的callback.apply方法实现如下: 即通过webView.loadUrl实现java调用js的方法
    public static class Callback {
        private static Handler mHandler = new Handler(Looper.getMainLooper());
        private static final String CALLBACK_JS_FORMAT = "javascript:JSBridge.onFinish('%s', %s);";
        private String mPort;
        private WeakReference<WebView> mWebViewRef;

        public Callback(WebView view, String port) {
            mWebViewRef = new WeakReference<>(view);
            mPort = port;
        }

        public void apply(JSONObject jsonObject) {
            final String execJs = String.format(CALLBACK_JS_FORMAT, mPort, String.valueOf(jsonObject));
            if (mWebViewRef != null && mWebViewRef.get() != null) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mWebViewRef.get().loadUrl(execJs);
                    }
                });
            }
        }
    }
}
import org.json.JSONObject;

/**
 * js callback 父类
 */
public class ICallBack {

    public JSONObject getJSONObject(int code, String success, JSONObject object) {
        try {
            JSONObject obj = new JSONObject();
            obj.put("code", code + "");
            obj.put("success", success);
            obj.put("data", object);
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public void dealCallback(JSBridge.Callback callback, JSONObject object) {
        try {
            callback.apply(getJSONObject(0, "ok", object));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void successCallBack(JSBridge.Callback callback) {
        if (null != callback) {
            try {
                JSONObject object = new JSONObject();
                object.put("status", true);
                dealCallback(callback, object);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void failCallBack(JSBridge.Callback callback) {
        if (null != callback) {
            try {
                JSONObject object = new JSONObject();
                object.put("status", true);
                dealCallback(callback, object);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

import org.json.JSONObject;

/**
 * js通信异步方式-数据处理
 */
public class NativeApi extends ICallBack {

    // 直接进入showToast函数的实现
    public void showToast(WebView webView, String message, final JSBridge.Callback callback) {
        Toast.makeText(webView.getContext(), message, Toast.LENGTH_SHORT).show();
        if (null != callback) {
            try {
                JSONObject object = new JSONObject();
                object.put("key1", "value1");
                dealCallback(callback, object);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值