当前位置: 首页 > article >正文

移动端web页面调用原生jsbridge的封装

为了统一android端和ios端调用原生jsbridge方法统一,且web端不需要使用callback方式接收回调,特封装了以下js工具类:

// 全局回调管理器
window.CallbackManager = {
      callbacks: new Map(),

registerCallback: function (callbackId, callback) {
this.callbacks.set(callbackId, callback);
},

unregisterCallback: function (callbackId) {
this.callbacks.delete(callbackId);
},

invokeCallback: function (callbackId, result) {
    const callback = this.callbacks.get(callbackId);
    console.log("查看回调数据:"+callbackId+"***"+result);
    if (callback) {
        callback(result);
        console.log("执行了回调");
        this.unregisterCallback(callbackId);
    }
},

invokeCallbackForIOS: function (result) {
let decodedResponse = decodeURIComponent(result);
const jsonObject = JSON.parse(decodedResponse);
let callbackId = jsonObject.callbackId

const callback = this.callbacks.get(callbackId);
console.log("查看回调数据:"+callbackId+"***"+result);
if (callback) {
    callback(jsonObject.result);
    console.log("执行了回调");
    this.unregisterCallback(callbackId);
                 }
  }

};

window.mobileNativeMethod= {
callHandler: function (methodName, params, callback) {
    let userAgent = navigator.userAgent;
    if (/iPad|iPhone|iPod/.test(userAgent)) {
 // iOS平台调用原生方法
        let callbackId = Math.random().toString(36).substring(7);
        let jsonParams = JSON.parse(params)
        jsonParams.methodName = methodName
        jsonParams.callbackId = callbackId
        window.webkit.messageHandlers.mobileNativeMethod.postMessage(JSON.stringify(jsonParams));
        CallbackManager.registerCallback(callbackId, callback);

    } else if (userAgent.indexOf('Android') > -1) {
        // Android平台调用原生方法
        if (window.androidJavascript) {
            console.log("查看调用:"+methodName+"***"+params)

            let callbackId = Math.random().toString(36).substring(7);
            window.androidJavascript.callHandler(methodName, params, callbackId);
            CallbackManager.registerCallback(callbackId, callback);
        }
    } else {
        console.warn('Unsupported platform');
    }
  }
};

在web页面移动端统一使用 **window.mobileNativeMethod.callBack(methodName,params, callback)**方法调用原生实现的方法。
methodName是字符串方法名,params是Map参数,如果需要接收回调需要实现callback,如果不需要回调可以省略回调。

此处以android原生端实现的jsbridge为例,示例实现如下:

public class MyWebViewJavaScript {
private final String TAG = “MyWebViewJavaScript”;
private TextView mTvtitle;
private SetWebTitle mSetWebTitle;
List mHandles;
public Map<String, String> callBackIdStack;
private StWebView mWebView;
private Handler mHandler;
//响应数据
private String response = “”;

public interface SetWebTitle {
    void toSetWebTitle(String title);

    void toHideTitleBar(boolean isHide);
}

public WebViewJavaScript(StWebView webview, SetWebTitle setWebTitle) {
    EventBusUtil.register(this);
    this.mWebView = webview;
    callBackIdStack = new HashMap<>();
    mHandler = new Handler(Looper.getMainLooper());
    this.mSetWebTitle = setWebTitle;
    mHandles = new ArrayList<>();
    //缓存相关的js通讯渠道
    mHandles.add(new CacheChannelImpl());
    //公共的js通讯渠道
    mHandles.add(new CommonChannelImpl(mWebView.getContext()));
}

@JavascriptInterface
public void callHandler(String handleName, String jsonArgs, String callbackId) {
    if (mWebView == null) {
        return;
    }

    //设置web页面标题
    if (handleName.equals("setAppBarTitle")) {
        JSONObject jsonObject = JSON.parseObject(jsonArgs);
        String title = jsonObject.getString("title");
        if (null != mSetWebTitle) {
            mSetWebTitle.toSetWebTitle(title);
        } else {
            Log.d(TAG, "Interface SetWebTitle is null");
        }
        return;
    }

    //是否隐藏标题栏
    if (handleName.equals("hideTitleBar")) {
        JSONObject jsonObject = JSON.parseObject(jsonArgs);
        boolean isHide = jsonObject.getBoolean("isHide");
        if (null != mSetWebTitle) {
            mSetWebTitle.toHideTitleBar(isHide);
        } else {
            Log.d(TAG, "Interface SetWebTitle is null");
        }
        return;
    }

    boolean hasMethod = false;
    for (IJsCallHandle handle : mHandles) {
        if (handle.handle(handleName)) {
            if (handle instanceof CacheChannelImpl) {
                handle.run(mWebView, jsonArgs, callbackId, callBackIdStack);
            } else {
                handle.run(mWebView, jsonArgs);
                callBackIdStack.put(handleName, callbackId);
            }
            hasMethod = true;
            break;
        }
    }

    if (!hasMethod) {
        //未实现方法 handleName
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                Gson gson = new GsonBuilder().disableHtmlEscaping() // 禁用 HTML 转义
                        .create();
                HashMap<String, Object> mmap = new HashMap<>();
                mmap.put("result", "");
                mmap.put("code", "error");
                mmap.put("message", String.format("未实现方法%s", handleName));
                mmap.put("methodName", handleName);
                response = gson.toJson(mmap);
                String jsFunctionCall = "javascript:CallbackManager.invokeCallback('" + callbackId + "', '" + response + "')";
                mWebView.loadUrl(jsFunctionCall);
                callBackIdStack.remove(handleName);
            }
        });
    }
  }
}

CommonChannelImpl的实现示例:

public class CommonChannelImpl implements IJsCallHandle {
private Map<String, Boolean> methods = new HashMap<String, Boolean>();
private String mHandleName = "";
private Context mContext;

public CommonChannelImpl(Context context) {
    this.mContext = context;
    //权限请求
    methods.put("requestPermission", false);
    //获取应用基本信息
    methods.put("getAppInfo", false);
    //web页面导航返回
    methods.put("NavigatorPop", false);
    //打开浏览器
    methods.put("openBrowser", false);
    //跳转页面
    methods.put("jumpPage", false);
    //打电话
    methods.put("callPhone", false);
}

@Override
public boolean handle(String handleName) {
    if (methods.containsKey(handleName)) {
        mHandleName = handleName;
        methods.put(handleName, true);
        return true;
    }
    return false;
}

@Override
public void run(StWebView webView, String jsonArgs) {
    long requestCode = 0;
    if (!TextUtils.isEmpty(jsonArgs)) {
        JSONObject jobj = JSON.parseObject(jsonArgs);
        if (jobj.containsKey("requestCode")) {
            requestCode = jobj.getLong("requestCode");
        }
    }
    switch (mHandleName) {
        case "requestPermission":
            EventMessage<Object> eventMessage1 = new EventMessage<>(0, requestCode, "module-permission", mHandleName, jsonArgs);
            EventBusUtil.sendEvent(eventMessage1);
            break;
        case "getAppInfo":
            EventMessage<Object> eventMessage = new EventMessage<>(0, requestCode, "component-phoneinfo", mHandleName, jsonArgs);
            EventBusUtil.sendEvent(eventMessage);
            break;
        case "NavigatorPop":
            Handler mainHandler = new Handler(Looper.getMainLooper());
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (webView.canGoBack()) {
                        webView.goBack();
                    } else {
                        if (mContext instanceof AppCompatActivity) {
                            ((AppCompatActivity) mContext).finish();
                        }
                    }
                }
            });
            break;
        case "openBrowser":
            JSONObject jsonObject = JSON.parseObject(jsonArgs);
            if (jsonObject != null) {
                String url = jsonObject.getString("url");
                if (!url.contains("http")) {
                    url = "http://" + url;
                }
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse(url));
                mContext.startActivity(intent);
            }
            break;
        case "jumpPage":
            JSONObject jsonObject1 = JSON.parseObject(jsonArgs);
            String pageUrl = jsonObject1.getString("pageUrl");
            JSONObject params = jsonObject1.getJSONObject("params");
            Map<String, Object> map = new HashMap<>();
            for (String key : params.keySet()) {
                map.put(key, params.get(key));
            }
            ARouterHelper.navigateToFlutterPage(pageUrl, map);
            break;
        case "callPhone":
            JSONObject jsonObject2 = JSON.parseObject(jsonArgs);
            String number = jsonObject2.getString("number");
            Intent intent = new Intent(Intent.ACTION_DIAL);
            intent.setData(Uri.parse("tel:" + number));
            mContext.startActivity(intent);
            break;
        default:
            break;
    }
  }
}

http://www.kler.cn/a/400234.html

相关文章:

  • java ssm 高速公路管理系统 公路收费管理 高速收费管理 源码 jsp
  • 【Android】Proxyman 抓 HTTP 数据包
  • 4 设计模式原则之接口隔离原则
  • 【开源风云】从若依系列脚手架汲取编程之道(七)
  • 【青牛科技】D7312带 ALC 双通道前置放大器电路
  • C语言常用语句总结
  • 跨平台WPF框架Avalonia教程 三
  • C++20中的Concepts与TypeScript
  • 雨晨 Fix 24H2 Windows 11 iot 企业版 ltsc 2024 极简 2合1 26100.2448
  • Gradle 8 使用教程:Maven 仓库导入、依赖管理与 TOML 配置详解
  • Node.js 中如何实现延迟和超时 ?
  • Linux环境基础开发工具的使用(yum、vim、gcc、g++、gdb、make/Makefile)
  • PyTorch使用教程-深度学习框架
  • 第十七天 Scikit-learn入门
  • 【ChatGPT】让ChatGPT生成特定时间段或主题的文章
  • springboot 文件高效上传
  • django-ninja 实现cors跨域请求
  • 蓝桥杯-洛谷刷题-day4(C++)
  • 全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS简介
  • 编程软件---git