Javascript 和 APP 端通信方式
- WebView JavaScript Bridge
- React Native、Flutter 等跨平台框架
- JavaScript 嵌入到原生应用
- WebSocket 或网络请求
WebView JavaScript Bridge
WebView JavaScript Bridge 是一种在 WebView(Web 视图)和原生代码之间建立通信通道的机制,使得 JavaScript 和原生代码可以相互调用,并在移动应用中实现更加丰富的交互体验。
其原理主要包括以下几个步骤:
- 创建通信接口
- 在原生应用的代码中,首先需要创建一个通信接口,该接口可以被 JavaScript 调用,并且可以执行一些原生操作。这个接口可以是一个类、一个方法、一个对象等,具体取决于不同的框架和实现方式。
- 注入 JavaScript Bridge
- 当 WebView 加载页面时,原生应用需要向 WebView 注入一个 JavaScript Bridge,以便 JavaScript 可以通过它与原生代码进行通信。JavaScript Bridge 通常是一个 JavaScript 对象,它提供了一系列方法,用于调用原生代码中定义的接口。
- JavaScript 调用原生接口
- 在 JavaScript 中,当需要调用原生代码时,可以通过 JavaScript Bridge 提供的方法来调用原生接口。例如,可以调用一个名为 callNative 的方法,并传递需要执行的原生操作和参数。
- 原生代码执行操作
- 当 JavaScript 调用了原生接口后,JavaScript Bridge 会将调用请求传递给原生代码。原生代码接收到请求后,会执行相应的操作,并返回执行结果。
- 原生代码调用 JavaScript 方法
- 在一些情况下,原生代码可能需要调用 JavaScript 中的方法。为了实现这一点,原生代码可以通过 JavaScript Bridge 提供的方法,调用 JavaScript 中定义的函数或方法,并传递参数。
- 处理通信过程中的回调和错误
- 通信过程中可能会发生错误或需要处理异步操作的结果。因此,在通信接口中通常会提供回调函数或者 Promise 等机制,用于处理异步操作的结果或者向 JavaScript 返回执行结果。
示例代码
- 首先,我们需要在原生应用中创建一个通信接口,其中包含一个方法 showToast:
import android.content.Context;
import android.webkit.JavascriptInterface;
import android.widget.Toast;
public class JavaScriptInterface {
private Context mContext;
public JavaScriptInterface(Context context) {
mContext = context;
}
@JavascriptInterface
public void showToast(String message) {
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
}
- 然后,在原生应用中的 WebView 中注入 JavaScript Bridge:
WebView webView = findViewById(R.id.webView);
JavaScriptInterface jsInterface = new JavaScriptInterface(this);
webView.addJavascriptInterface(jsInterface, "AndroidBridge");
- 在 JavaScript 中,可以通过 AndroidBridge.showToast 方法调用原生代码中定义的 showToast 方法来显示 Toast 消息:
function showToastFromNative() {
AndroidBridge.showToast("Hello from JavaScript!");
}
React Native、Flutter 等跨平台框架
React Native 是一种跨平台移动应用开发框架,它允许开发者使用 JavaScript 和 React 来构建原生移动应用。
React Native 的实现原理可以分为以下几个关键点:
- JavaScript Core(JS Core)
- React Native 应用的核心是 JavaScript 代码。在 React Native 应用启动时,JavaScript 代码会被加载和解释执行。JavaScript 代码负责处理应用的逻辑、状态管理、UI 渲染等任务。
- React 架构
- React 是一个用于构建用户界面的 JavaScript 库。React Native 基于 React 架构,使用 React 的组件化和声明式编程模型来构建用户界面。开发者使用 React 组件来描述应用的界面结构和行为,React 负责将组件渲染为原生 UI 元素。
- 原生模块
- React Native 提供了一系列的原生模块,用于访问设备的原生功能,如网络请求、文件系统、摄像头、地理位置等。这些原生模块通过 JavaScript Bridge 暴露给 JavaScript 环境,允许开发者在 JavaScript 中调用原生功能。
- JavaScript Bridge
- React Native 使用 JavaScript Bridge 在 JavaScript 和原生代码之间建立通信通道。JavaScript Bridge 允许 JavaScript 代码调用原生模块提供的接口,并且可以在原生代码中调用 JavaScript 代码提供的方法。这样,React Native 应用可以利用原生功能,并实现与原生应用相同的性能和用户体验。
- 布局引擎
- React Native 使用 Flexbox 布局引擎来实现组件的布局和排列。开发者可以使用 Flexbox 布局来构建灵活和自适应的界面,使得应用能够适应不同尺寸和分辨率的设备。
- 渲染引擎
- React Native 使用原生平台的渲染引擎来将 React 组件渲染为原生 UI 元素。
- 在 iOS 平台上,React Native 使用 iOS 的 UIView、CALayer 等原生组件来渲染界面。
- 在 Android 平台上,React Native 使用 Android 的 View、Drawable 等原生组件来渲染界面。
prompt
通过设置 webview 的 WebChromeClient 重写 onJsPrompt 方法,可以拦截 window 对象的 prompt 方法。
- 安卓端
class MyWebChromeClient extends WebChromeClient{
//通过prompt方式交互需要重写onJsPrompt
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
if (!TextUtils.isEmpty(url) && url.startsWith("file://")) {
if(dispatchUrl("Prompt",defaultValue)){
//回调js
result.confirm();
return true;
}
}
return super.onJsPrompt(view, url, message, defaultValue, result);
}
}
- web 端
function invoke(time) {
const opt = {
time
}
const cmd = 'kg.openApp' // 命令字
const url = `SCHEME://qmkg.kg.qq.com/api/${cmd}?t=${opt.time}`
window.prompt(url)
}
url scheme 介绍
url scheme是一种类似于url的链接,是为了方便app直接互相调用设计的:具体为:可以用系统的 OpenURI 打开类似与url的链接(可拼入参数),然后系统会进行判断,如果是系统的 url scheme,则打开系统应用,否则找看是否有app注册中scheme,打开对应app,需要注意的是,这种scheme必须原生app注册后才会生效,如微信的scheme为 weixin://
调用过程(如用 iframe.src),然后native用某种方法捕获对应的url触发事件,然后拿到当前触发url,根据定好的协议(scheme://method/?params=xxx),然后native拦截该请求分析当前触发了哪种方法,然后根据定义来实现
客户端捕获url
安卓捕获 url scheme:shouldoverrideurlloading 捕获到url进行分析 ios: 在 UIWebView WKWebview 内发起的所有网络请求,都可以通过 delegate函数在native层得到通知,通过 shouldStartLoadWithRequest捕获webview中触发的url scheme
大致流程:h5 --> 通过某种方式触发一个url --> native捕获到url,进行分析 -->原生做处理 --> 如果需要回调 native再调用h5的JSBridge对象传递回调
缺点:
- 速度可能稍慢一点,url长度会有限制,需要定义url结构解析较为复杂 相较于注入api形式有以下有优点:
- Android4.2 一下,addJavaScriptInterface方式有安全漏洞
- ios7以下,js无法调用native
- url scheme交互方式是一套现有的成熟方案,可以兼容各种版本
作者:大桔子1223 链接:https://juejin.cn/post/7034474588704768013 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
WebSocket 或网络请求
可以通过 WebSocket 或网络请求的方式,在 JavaScript 和原生代码之间进行通信。
例如,你可以在 JavaScript 中发起网络请求,然后在原生代码中处理这些请求并返回结果,或者你可以使用 WebSocket 在 JavaScript 和原生代码之间实时传递消息。