一、插件介绍

Flutter JSBridge 是一个功能强大的 Flutter 插件,它提供了 Flutter 原生代码与 WebView 中的 JavaScript 代码之间的双向通信能力。通过该插件,开发者可以在 Flutter 应用中轻松实现原生与 Web 内容的无缝交互,构建混合开发应用。

本版本是针对鸿蒙平台(HarmonyOS)进行了专门适配和优化的自定义修改版本,确保在鸿蒙设备上能够稳定高效地运行。

主要功能特点:

  • 支持 Flutter 与 WebView 之间的双向通信
  • 提供简洁的 API 接口,方便调用 JavaScript 函数和注册原生处理程序
  • 支持异步回调,确保通信的可靠性
  • 完全适配鸿蒙平台,支持最新的 Flutter 和鸿蒙 SDK 版本
  • 采用标准的 WebViewJavascriptBridge 协议,兼容性强

二、插件安装与配置

由于这是针对鸿蒙平台的自定义修改版本,我们需要通过 Git 形式引入该依赖包。

2.1 添加依赖

在您的 Flutter 项目中,打开 pubspec.yaml 文件,在 dependencies 部分添加以下配置:

dependencies:
  flutter:
    sdk: flutter
  flutter_jsbridge_plugin_ohos:
    git:
      url: "https://atomgit.com/openharmony-sig/fluttertpc_flutter_jsbridge_plugin.git"
      path: "ohos"
  webview_flutter:
    ^4.0.0

2.2 安装依赖

添加依赖后,执行以下命令安装插件:

flutter pub get

三、API 使用指南

3.1 导入包

在需要使用 JSBridge 的 Dart 文件中,导入相应的包:

import 'package:flutter_jsbridge_plugin_ohos/flutter_jsbridge_plugin_ohos.dart';
import 'package:webview_flutter/webview_flutter.dart';

3.2 初始化 JSBridge

3.2.1 创建 WebView

首先需要创建一个 WebView 实例,并加载网页内容:

WebViewController _controller = WebViewController();


void initState() {
  super.initState();

  // 初始化 WebView
  _controller = WebViewController()
    ..setJavaScriptMode(JavaScriptMode.unrestricted)
    ..setNavigationDelegate(NavigationDelegate(
      onPageFinished: (url) {
        // 网页加载完成后初始化 JSBridge
        _initJsBridge();
      },
      onNavigationRequest: (NavigationRequest request) {
        // 处理 URL 请求,特别是 JSBridge 协议的 URL
        if (_jsBridge.handlerUrl(request.url)) {
          return NavigationDecision.prevent;
        }
        return NavigationDecision.navigate;
      },
    ))
    ..loadRequest(Uri.parse('https://example.com'));
}
3.2.2 初始化 JSBridge
JsBridge _jsBridge = JsBridge();

void _initJsBridge() {
  // 加载 WebView 控制器到 JSBridge
  _jsBridge.loadJs(_controller);

  // 初始化 JSBridge
  _jsBridge.init();

  // 注册原生处理程序
  _registerHandlers();
}

3.3 注册原生处理程序

使用 registerHandler 方法注册原生处理程序,用于处理来自 JavaScript 的调用:

void _registerHandlers() {
  // 注册获取设备信息的处理程序
  _jsBridge.registerHandler(
    'getDeviceInfo',
    (data, function) {
      // 处理来自 JavaScript 的请求
      print('JavaScript 请求获取设备信息: $data');

      // 返回设备信息给 JavaScript
      function({
        'platform': 'HarmonyOS',
        'version': '5.0',
        'model': 'HarmonyOS Device',
      });
    },
  );

  // 注册分享功能的处理程序
  _jsBridge.registerHandler(
    'share',
    (data, function) {
      print('JavaScript 请求分享: $data');

      // 执行分享操作
      _performShare(data);

      // 返回分享结果给 JavaScript
      function({'status': 'success', 'message': '分享成功'});
    },
  );
}

void _performShare(dynamic data) {
  // 实现分享逻辑
  String title = data['title'];
  String content = data['content'];
  String url = data['url'];

  print('分享内容: $title, $content, $url');
  // 调用系统分享功能
}

3.4 调用 JavaScript 处理程序

使用 callHandler 方法调用 JavaScript 中注册的处理程序:

void _callJavaScriptFunction() {
  // 调用 JavaScript 中的 showMessage 函数
  _jsBridge.callHandler(
    'showMessage',
    {'message': 'Hello from Flutter!', 'type': 'success'},
    (data) {
      // 处理 JavaScript 的回调结果
      print('JavaScript 回调: $data');
    },
  );

  // 调用 JavaScript 中的获取用户信息函数
  _jsBridge.callHandler(
    'getUserInfo',
    null,
    (data) {
      print('用户信息: $data');
      // 处理用户信息
    },
  );
}

3.5 JavaScript 端使用

在网页的 JavaScript 代码中,需要初始化 JSBridge 并注册/调用处理程序:

// 等待 JSBridge 准备就绪
document.addEventListener('WebViewJavascriptBridgeReady', function(event) {
  var bridge = event.bridge;

  // 初始化 JSBridge
  bridge.init(function(message, responseCallback) {
    console.log('JS got a message', message);
    responseCallback({'status': 'init_success'});
  });

  // 注册 JavaScript 处理程序
  bridge.registerHandler('showMessage', function(data, responseCallback) {
    console.log('收到 Flutter 消息:', data);

    // 显示消息
    alert(data.message);

    // 返回结果给 Flutter
    responseCallback({'status': 'shown', 'message': '消息已显示'});
  });

  // 注册获取用户信息的处理程序
  bridge.registerHandler('getUserInfo', function(data, responseCallback) {
    responseCallback({
      'name': '张三',
      'age': 25,
      'email': 'zhangsan@example.com'
    });
  });
}, false);

// 调用 Flutter 原生方法
function callFlutterMethod() {
  WebViewJavascriptBridge.callHandler(
    'share',
    {
      'title': '分享标题',
      'content': '分享内容',
      'url': 'https://example.com'
    },
    function(response) {
      console.log('Flutter 分享结果:', response);
    }
  );
}

四、完整示例

下面是一个完整的示例,展示了如何在鸿蒙平台上使用 Flutter JSBridge 插件:

import 'package:flutter/material.dart';
import 'package:flutter_jsbridge_plugin_ohos/flutter_jsbridge_plugin_ohos.dart';
import 'package:webview_flutter/webview_flutter.dart';

class JSBridgeDemoPage extends StatefulWidget {
  const JSBridgeDemoPage({Key? key}) : super(key: key);

  
  _JSBridgeDemoPageState createState() => _JSBridgeDemoPageState();
}

class _JSBridgeDemoPageState extends State<JSBridgeDemoPage> {
  late WebViewController _controller;
  JsBridge _jsBridge = JsBridge();

  final String _htmlContent = '''
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>JSBridge Demo</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            padding: 20px;
            max-width: 600px;
            margin: 0 auto;
        }
        button {
            background-color: #4CAF50;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin: 10px 0;
        }
        button:hover {
            background-color: #45a049;
        }
        #result {
            margin-top: 20px;
            padding: 10px;
            background-color: #f0f0f0;
            border-radius: 4px;
        }
    </style>
</head>
<body>
    <h1>JSBridge Demo</h1>

    <h2>调用 Flutter 原生方法</h2>
    <button onclick="callFlutterGetDeviceInfo()">获取设备信息</button>
    <button onclick="callFlutterShare()">分享内容</button>

    <h2>Flutter 调用 JS 方法</h2>
    <button onclick="setupFlutterCallListener()">监听 Flutter 调用</button>

    <div id="result"></div>

    <script>
        // 等待 JSBridge 准备就绪
        document.addEventListener('WebViewJavascriptBridgeReady', function(event) {
            window.bridge = event.bridge;

            // 初始化 JSBridge
            bridge.init(function(message, responseCallback) {
                console.log('JS got a message', message);
                responseCallback({'status': 'init_success'});
            });

            // 注册 JS 处理程序
            bridge.registerHandler('showMessage', function(data, responseCallback) {
                document.getElementById('result').innerHTML =
                    '<p>收到 Flutter 消息: ' + JSON.stringify(data) + '</p>';
                responseCallback({'status': 'shown', 'message': '消息已显示'});
            });

            document.getElementById('result').innerHTML =
                '<p>JSBridge 初始化成功</p>';
        }, false);

        function callFlutterGetDeviceInfo() {
            window.bridge.callHandler(
                'getDeviceInfo',
                {'param': 'value'},
                function(response) {
                    document.getElementById('result').innerHTML =
                        '<p>设备信息: ' + JSON.stringify(response) + '</p>';
                }
            );
        }

        function callFlutterShare() {
            window.bridge.callHandler(
                'share',
                {
                    'title': 'JSBridge 分享示例',
                    'content': '这是一个来自 JS 的分享内容',
                    'url': 'https://example.com'
                },
                function(response) {
                    document.getElementById('result').innerHTML =
                        '<p>分享结果: ' + JSON.stringify(response) + '</p>';
                }
            );
        }

        function setupFlutterCallListener() {
            document.getElementById('result').innerHTML =
                '<p>已准备好接收 Flutter 调用</p>';
        }
    </script>
</body>
</html>
  ''';

  
  void initState() {
    super.initState();

    // 初始化 WebView
    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(NavigationDelegate(
        onPageFinished: (url) {
          // 网页加载完成后初始化 JSBridge
          _initJsBridge();
        },
        onNavigationRequest: (NavigationRequest request) {
          // 处理 URL 请求,特别是 JSBridge 协议的 URL
          if (_jsBridge.handlerUrl(request.url)) {
            return NavigationDecision.prevent;
          }
          return NavigationDecision.navigate;
        },
      ))
      ..loadHtmlString(_htmlContent);
  }

  void _initJsBridge() {
    // 加载 WebView 控制器到 JSBridge
    _jsBridge.loadJs(_controller);

    // 初始化 JSBridge
    _jsBridge.init();

    // 注册原生处理程序
    _registerHandlers();
  }

  void _registerHandlers() {
    // 注册获取设备信息的处理程序
    _jsBridge.registerHandler(
      'getDeviceInfo',
      (data, function) {
        print('JavaScript 请求获取设备信息: $data');

        // 返回设备信息给 JavaScript
        function({
          'platform': 'HarmonyOS',
          'version': '5.0',
          'model': 'HarmonyOS Device',
          'manufacturer': 'Huawei'
        });
      },
    );

    // 注册分享功能的处理程序
    _jsBridge.registerHandler(
      'share',
      (data, function) {
        print('JavaScript 请求分享: $data');

        // 模拟分享操作
        String title = data['title'];
        String content = data['content'];
        String url = data['url'];

        print('分享内容: $title, $content, $url');

        // 返回分享结果给 JavaScript
        function({'status': 'success', 'message': '分享成功'});
      },
    );
  }

  void _callJavaScriptFunction() {
    // 调用 JavaScript 中的 showMessage 函数
    _jsBridge.callHandler(
      'showMessage',
      {'message': 'Hello from Flutter!', 'type': 'success'},
      (data) {
        // 处理 JavaScript 的回调结果
        print('JavaScript 回调: $data');
      },
    );
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('JSBridge 鸿蒙平台演示'),
      ),
      body: Column(
        children: [
          Expanded(
            child: WebViewWidget(controller: _controller),
          ),
          Container(
            padding: const EdgeInsets.all(16.0),
            child: ElevatedButton(
              onPressed: _callJavaScriptFunction,
              child: const Text('调用 JS 方法'),
            ),
          ),
        ],
      ),
    );
  }
}

五、约束与限制

5.1 兼容性

该插件已在以下环境中测试通过:

  1. Flutter: 3.7.12-ohos-1.1.3; SDK: 5.0.0(12); IDE: DevEco Studio: 5.1.0.828; ROM: 5.1.0.130 SP8;
  2. Flutter: 3.22.1-ohos-1.0.3; SDK: 5.0.0(12); IDE: DevEco Studio: 5.1.0.828; ROM: 5.1.0.130 SP8;

5.2 注意事项

  1. 确保在 WebView 加载完成后再初始化 JSBridge
  2. 需要在 NavigationDelegate 的 onNavigationRequest 中调用 handlerUrl 方法处理 JSBridge 协议的 URL
  3. 注册的处理程序名称在 JavaScript 和 Flutter 端必须保持一致
  4. 传递的数据必须是可序列化的类型,避免传递复杂对象
  5. 鸿蒙平台不支持 Flutterjsbridgeplugin 类中的 scrpit、isMainThread 和 handlerReturnData 方法

六、总结

Flutter JSBridge 鸿蒙平台版是一个功能强大的插件,它为开发者提供了在鸿蒙设备上实现 Flutter 与 WebView 之间双向通信的能力。该插件提供了丰富的 API,包括加载 WebView 控制器、初始化桥接器、处理 URL 协议方案、调用 JS 处理程序和注册原生处理程序等功能。

通过本指南的学习,您应该已经掌握了该插件的基本使用方法和最佳实践。无论是调用 JavaScript 函数获取 Web 内容的数据,还是注册原生处理程序让 JavaScript 调用 Flutter 原生功能,该插件都能提供简洁、高效的解决方案。

如果您在使用过程中遇到任何问题或有任何建议,欢迎加入开源鸿蒙跨平台社区进行交流和讨论。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐