App实现JSBridge的最佳方案

Posted datian1234

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了App实现JSBridge的最佳方案相关的知识,希望对你有一定的参考价值。

前沿

写这篇文章的主要目的是对 App 的 JSBridge 做一个全面的介绍,同时根据不同的使用场景总结出一份 App 实现 JSBridge 的最佳方案。对于没有接触过 App 的同学能够对 JSBridge 有个大致的概念,对于做过 App 的 JSBridge 开发的同学也能有更系统的认识,也是自己对于相关知识点的归纳总结。

一、概念

什么是 JSBridge ?

JSBridge 的全称:JavaScript Bridge,中文名 JS桥JS桥接器

JSBridge 是一种用于在 androidios 应用与 H5 之间进行通信的技术。它允许应用开发者在原生代码中调用 JavaScript 函数,以及 在JavaScript 中调用原生代码函数。其通常用于移动应用开发中,可以使用 JSBridge 技术在原生应用中嵌入网页,并在网页与原生应用之间进行交互。

二、原理

JSBridge 通过在 WebView 中注册 JavaScript 函数来实现通信。WebView 是一种在应用中嵌入网页的组件,可以在应用中显示网页内容。JSBridge 通过在 WebView 中注册 javascript 函数,并在原生代码中调用这些函数来实现通信

例如,下面是一个使用 JSBridge 实现通信的示例代码:

/* Android 端实现 */
// 在WebView中注册JavaScript函数
webView.loadUrl("javascript:function myFunction()  /* JavaScript code here */ ");

// 在原生代码中调用JavaScript函数
webView.loadUrl("javascript:myFunction()");

/* iOS 端实现 */
// 在WebView中注册JavaScript函数
[self.webView stringByEvaluatingJavaScriptFromString:@"function myFunction()  /* JavaScript code here */ "];

// 在原生代码中调用JavaScript函数
[self.webView stringByEvaluatingJavaScriptFromString:@"myFunction()"];

上面的代码通过在 WebView 中注册 JavaScript 函数 myFunction,并在原生代码中调用这个函数来实现通信。

在实际开发中,我们一般是创建一个 JSBridge 对象,然后通过 WebView 的 addJavascriptInterface 方法进行注册。

// WebView 的 addJavascriptInterface 方法源码
public void addJavascriptInterface(Object object, String name) 
  checkThread();
  if (object == null) 
    throw new NullPointerException("Cannot add a null object");
  
  if (name == null || name.length() == 0) 
    throw new IllegalArgumentException("Invalid name");
  
  mJavascriptInterfaces.put(name, object);

该方法首先检查当前线程是否是 UI 线程,以确保添加桥接对象的操作是在 UI 线程中进行的。接着,该方法会检查桥接对象和名称的有效性,确保它们都不为空。最后,该方法会把桥接对象与名称关联起来,并存储到 WebView 的 mJavascriptInterfaces 对象中。

当网页加载完成后,WebView 会把桥接对象的方法注入到网页中,使得网页能够调用这些方法。当网页中的 JavaScript 代码调用桥接对象的方法时,WebView 会把该方法调用映射到原生代码中,从而实现网页与原生应用之间的交互。

addJavascriptInterface 方法的主要作用是把桥接对象的方法注入到网页中,使得网页能够调用这些方法。它的具体实现方式可能会因平台而异,但是它的基本原理是一致的。

三、原生实现

以 H5 获取 App 的版本号为例。Android相关源码

要实现一个获取 App 版本号的 JSBridge,需要在 H5 中编写 JavaScript 代码,并在 Android 原生代码中实现对应的原生方法。

首先,需要在 H5 中编写 JavaScript 代码,用于调用 Android 的原生方法。例如,可以在 H5 中定义一个函数,用于调用 Android 的原生方法:

// assets/index.html
function getAppVersion() 
    // 通过JSBridge调用Android的原生方法
    JSBridge.getAppVersion(function(version) 
        // 在这里处理获取到的Android版本号
    );

然后,需要在 Android 的原生代码中实现对应的原生方法。例如,可以实现一个名为 getAppVersion 的方法,用于在 H5 中调用:

// com.fitem.webviewdemo.AppJSBridge
@JavascriptInterface
public String getAppVersion() 
    // 获取App版本号
    String version = BuildConfig.VERSION_NAME;

    // 将App版本号返回给H5
    return version;

最后通过 Webview 注入定义的 JavascriptInterface 方法的对象,在 H5 生成 window.jsBridge 对象进行调用。

// com.fitem.webviewdemo.MainActivity.kt
webView.addJavascriptInterface(jsBridge, "jsBridge")

iOS 的实现和 Android 类似:

- (void)getIOSVersion:(WVJBResponseCallback)callback 
    // 获取App版本号
    let version = Bundle.main.object(forInfoDictionaryKey: 
    "CFBundleShortVersionString") as! String

    // 将App版本号返回给H5
    callback(version);


// 在网页加载完成后设置JSBridge
- (void)webViewDidFinishLoad:(UIWebView *)webView 
    // 设置JSBridge
    [WebViewJavascriptBridge enableLogging];
    self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
    [self.bridge setWebViewDelegate:self];


四、跨平台(Flutter)

1. JSBridge 实现

Flutter 实现 JSBridge 功能的插件有很多,但基本上大多数都是基于原生的 JSBridge 能力实现。这里主要介绍官方的 webview_flutter 插件。

webview_flutter 插件实现 App 与 H5 之前的通信分为:App 发送消息到 H5H5 发送消息到 APP 两部分。

H5 发送消息到 APP。首先在 Flutter 应用中添加 WebView 组件,并设置 JavascriptChannel

      WebView(
        initialUrl: 'https://www.example.com',
        javascriptMode: JavascriptMode.unrestricted,
        javascriptChannels: 
          // 设置JavascriptChannel
          JavascriptChannel(
            name: 'JSBridge',
            onMessageReceived: (JavascriptMessage message) 
              // 在这里处理来自H5的消息
            ,
          ),
        ,
      ),

在H5中,可以通过 JSBridge 对象来调用原生方法:

// 通过JSBridge调用原生方法
window.jsBridge.postMessage('Hello, world!');

App 发送消息到 H5。 在 Flutter 中,通过 WebViewController 的 runJavascrip 调用 H5 中 window 对象的方法

controller.runJavascript("receiveMessage($json.encode(res))")

在 H5 中,可以通过 onmessage 事件来接收来自原生的消息:

  // 接收来自原生的消息
  window.receiveMessage = function receiveMessage(message) 
    console.log(message);
  ;

2. 局限性

webview_flutter 最大的局限在于 App 端与 H5 端之间的通信只支持单向通信,无法通过一次调用直接获取另一端的返回值。

五、App 实现 JSBridge 的最佳方案

1. 实现目标

  1. H5 兼容原生老版本 JSBridge。

  2. 支持两端双向通信。针对 webview_flutter 的单向通信的局限性进行改造优化,使其能支持返回值的回调。

2. NativeBridge 插件开发

NativeBridge 本质上是对 webview_flutter 的单向通信能力进行扩展封装

NativeBridge 插件的使用和实现原理,请阅读之前的文章《Flutter插件之NativeBridge》和《NativeBridge实现原理解析》。

3. 实现效果

  1. H5 支持原生老版本 JSBridge 兼容。
  // 获取app版本号 返回String
  async getVersionCode() 
    // 是否是新的JSBridge
    if (this.isNewJSBridge()) 
      return await window.jsBridgeHelper.sendMessage('getVersionCode', null)
     else 
      return window.iLotJsBridge.getVersionCode()
    
  
  1. 支持两端双向通信。
  // H5 获取 App 的值
  const versionNo = await jsBridge.getVersionCode()

  // App 获取 H5 的值
  var isHome = await NativeBridgeHelper.sendMessage("isHome", null, webViewController).future ?? false;
  1. 新增超时连接机制

就像网络请求一样,我们不能让代码执行一直阻塞在获取返回值的位置上。因为单向发送消息是不可靠的,可能存在消息丢失,或者另一端不响应消息的情况。因此我们需要类似网络请求一样,增加超时回调机制。

   // 增加回调异常容错机制,避免消息丢失导致一直阻塞
   Future.delayed(const Duration(milliseconds: 100), ()
     var completer = _popCallback(callbackId);
     completer?.complete(Future.value(null));
   );

总结

我们首先介绍了 JSBridge 的概念和原理,然后通过在 Android 、iOS 和 Flutter 中实现 JSBridge 来理解原生和 Flutter 之前的差异,最后总结了在 App 中实现 JSBridge 的最佳方案,方案包括支持原生和 Flutter 的兼容,并优化 webview_flutter 只支持单向通信的局限性和增加超时回调机制。

相关文章:《Flutter插件之NativeBridge》《NativeBridge实现原理解析》

源码:Android原生实现Flutter实现源码

作者:Fitem
链接:https://juejin.cn/post/7177407635317063735

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集

二、源码解析合集


三、开源框架合集


欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓

以上是关于App实现JSBridge的最佳方案的主要内容,如果未能解决你的问题,请参考以下文章

android与js的交互之jsbridge使用

android与js的交互之jsbridge使用

JSBridge(Android和IOS平台)的设计和实现

一文搞懂jsBridge的运行机制

一文搞懂jsBridge的运行机制

纵享丝滑Android WebView H5 秒开方案总结