Flutter跨平台开发鸿蒙化JS-Dart通信桥接组件使用指南

1. 插件介绍

JS-Dart通信桥接组件是一个专为OpenHarmony平台优化的Flutter插件,用于实现JavaScript(WebView)与Dart(Flutter)之间的双向通信。该组件提供了一套完整的通信机制,支持异步调用、回调处理和错误管理,适用于需要在Flutter应用中嵌入Web内容并实现复杂交互的场景。

核心功能

  • 支持JS调用Dart方法并获取返回值
  • 支持Dart调用JS方法并获取返回值
  • 提供异步通信机制
  • 完整的错误处理流程
  • 支持参数和返回值的序列化与反序列化
  • 与OpenHarmony WebView完美集成

2. 环境设置

在使用该组件之前,需要确保开发环境满足以下要求:

Flutter环境

  • Flutter SDK: ≥2.19.6
  • Dart SDK: ≥2.19.6

OpenHarmony环境

  • OpenHarmony SDK API: ≥9
  • DevEco Studio: ≥3.0

项目配置

确保项目已正确配置OpenHarmony开发环境,并已创建Flutter for OpenHarmony项目。

3. 包的引入

由于该组件是自定义修改版本,需要以git形式通过AtomGit引入。在项目的pubspec.yaml文件中添加以下依赖:

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter

  webview_flutter:
    git:
      url: "https://atomgit.com/openharmony-tpc/flutter_packages.git"
      path: "packages/webview_flutter/webview_flutter"

然后运行以下命令安装依赖:

bash 复制代码
flutter pub get

4. API调用与使用示例

4.1 WebView初始化

首先,需要初始化WebView并配置JavaScript支持:

dart 复制代码
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'js_bridge.dart';

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

  @override
  State<WebPage> createState() => _WebPageState();
}

class _WebPageState extends State<WebPage> {
  late WebViewController controller;
  final JSBridge _jsBridge = JSBridge();

  @override
  void initState() {
    super.initState();
    _initWebView();
    _initJsBridge();

    Future.delayed(const Duration(seconds: 1), () {
      controller.loadFlutterAsset("assets/html/index.html");
    });
  }

  _initWebView() async {
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..addJavaScriptChannel(
        JSBridge.name,
        onMessageReceived: (JavaScriptMessage message) {
          _jsBridge.receiverMessage(message.message);
        },
      )
      ..setNavigationDelegate(NavigationDelegate(
        onUrlChange: (change) {
          _jsBridge.injectBridgeJS(controller);
        },
      ));
  }

  _initJsBridge() {
    _jsBridge.messageExecutor = controller.runJavaScript;

    // 注册Dart方法供JS调用
    _jsBridge.register("getToken", (data, callback) {
      print("JS调用了getToken方法,参数:$data");
      // 模拟异步操作
      Future.delayed(const Duration(seconds: 1), () {
        callback("flutter_token_123"); // 返回结果给JS
      });
    });
  }

  // 其他代码...
}

4.2 JS调用Dart方法

在HTML页面中,通过注入的bridge对象调用Dart方法:

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
    <p id="demo">WebView Content</p>
    <button type="button" onclick="jsCallAsync()">调用Dart方法</button>

    <script>
        async function jsCallAsync() {
            var param = { "userId": "12345" };
            let result = await window.bridge.call("getToken", param);
            document.getElementById("demo").innerHTML = "从Dart获取的Token: " + result;
        }
    </script>
</body>
</html>

4.3 Dart调用JS方法

在Dart代码中,通过JSBridge调用JS方法:

dart 复制代码
_callJsMethod() {
  var param = {"userName": "flutter_user"};
  _jsBridge.call(
    "userInfo",
    param,
    callback: (responseData) {
      print("JS返回结果: $responseData");
      setState(() {
        message = "JS返回结果: $responseData";
      });
    },
    errorCallback: (errorMessage) {
      print("调用JS方法出错: $errorMessage");
    },
  );
}

4.4 JS注册方法供Dart调用

在JS代码中注册方法供Dart调用:

javascript 复制代码
// 注册JS方法
window.bridge.register("userInfo", function(data, callback) {
    console.log("Dart调用了userInfo方法,参数:", data);
    var result = { "name": "JS User", "id": "js_123" };
    callback(result); // 返回结果给Dart
});

5. 资源配置

5.1 添加本地HTML和JS文件

将HTML和JS文件放在项目的assets目录下:

复制代码
assets/
├── html/
│   └── index.html
└── js/
    └── bridge.js

5.2 配置pubspec.yaml

pubspec.yaml文件中配置资源路径:

yaml 复制代码
flutter:
  assets:
    - assets/html/
    - assets/js/

5.3 OpenHarmony权限配置

ohos/entry/src/main/module.json5文件中添加网络权限(如果需要加载远程内容):

json5 复制代码
{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "...",
    "mainElement": "...",
    "deviceTypes": ["phone", "tablet"],
    "distro": {
      "deliveryWithInstall": true,
      "moduleName": "entry",
      "moduleType": "entry"
    },
    "abilities": [...],
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

6. 完整示例

6.1 Dart端完整代码

dart 复制代码
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'js_bridge.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'JS-Dart Bridge Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const WebPage(),
    );
  }
}

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

  @override
  State<WebPage> createState() => _WebPageState();
}

class _WebPageState extends State<WebPage> {
  late WebViewController controller;
  String message = "初始化中...";
  final JSBridge _jsBridge = JSBridge();

  @override
  void initState() {
    super.initState();
    _initWebView();
    _initJsBridge();

    Future.delayed(const Duration(seconds: 1), () {
      controller.loadFlutterAsset("assets/html/index.html");
    });
  }

  _initWebView() async {
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..addJavaScriptChannel(
        "flutterObj",
        onMessageReceived: (JavaScriptMessage message) {
          setState(() {
            this.message = message.message;
          });
        },
      )
      ..addJavaScriptChannel(
        JSBridge.name,
        onMessageReceived: (JavaScriptMessage message) {
          _jsBridge.receiverMessage(message.message);
        },
      )
      ..setNavigationDelegate(NavigationDelegate(
        onUrlChange: (change) {
          _jsBridge.injectBridgeJS(controller);
        },
      ));
  }

  _initJsBridge() {
    _jsBridge.messageExecutor = controller.runJavaScript;

    _jsBridge.register("getToken", (data, callback) {
      print("JS调用了getToken方法,参数:$data");
      Future.delayed(const Duration(seconds: 1), () {
        callback("flutter_token_123");
      });
    });

    _jsBridge.register("testCallback", (data, callback) {
      print("JS调用了testCallback方法,参数:$data");
    });
  }

  _callJsBridge() {
    var param = {"userName": "flutter_user"};
    _jsBridge.call(
      "userInfo",
      param,
      callback: (responseData) {
        setState(() {
          message = "JS返回结果: $responseData";
        });
      },
      errorCallback: (errorMessage) {
        setState(() {
          message = "调用JS方法出错: $errorMessage";
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('JS-Dart Bridge Demo')),
      body: Column(children: [
        ElevatedButton(
          onPressed: () => _callJsBridge(),
          child: const Text("调用JS方法"),
        ),
        Text(message),
        Expanded(
          child: WebViewWidget(controller: controller),
        )
      ]),
    );
  }
}

6.2 HTML端完整代码

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
    <p id="demo">WebView Content</p>
    <button type="button" onclick="callFlutterFunction()">发送消息给Flutter</button>
    <button type="button" onclick="jsCallAsync()">调用Dart方法</button>

    <script>
        var count = 0;

        function callFlutterFunction() {
            flutterObj.postMessage('JS 调用了 Flutter ' + (++count));
        }

        async function jsCallAsync() {
            var param = { "userId": "12345" };
            let result = await window.bridge.call("getToken", param);
            document.getElementById("demo").innerHTML = "从Dart获取的Token: " + result;
        }

        // 注册JS方法供Dart调用
        window.bridge.register("userInfo", function(data, callback) {
            console.log("Dart调用了userInfo方法,参数:", data);
            var result = { "name": "JS User", "id": "js_123" };
            callback(result);
        });
    </script>
</body>
</html>

7. 总结

JS-Dart通信桥接组件为OpenHarmony平台上的Flutter应用提供了强大的WebView与Flutter通信能力。该组件支持双向通信、异步调用、回调处理和错误管理,适用于需要在Flutter应用中嵌入Web内容并实现复杂交互的场景。

通过本指南,您可以快速了解该组件的使用方法,包括环境设置、包的引入、API调用和完整示例。该组件已经过OpenHarmony平台优化,确保在OpenHarmony设备上稳定运行。

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

相关推荐
TAEHENGV3 分钟前
React Native for OpenHarmony 实战:数学练习实现
javascript·react native·react.js
CDwenhuohuo3 分钟前
安卓app巨坑 nvue后者页面要写画笔绘制功能nvue canvas
前端·javascript·vue.js
弓.长.7 分钟前
React Native 鸿蒙跨平台开发:长按菜单效果
react native·react.js·harmonyos
No Silver Bullet8 分钟前
HarmonyOS NEXT开发进阶(二十):纯血鸿蒙应用(HarmonyOS NEXT)在尝试解析域名时失败问题修复
华为·harmonyos
小白阿龙9 分钟前
鸿蒙+flutter 跨平台开发——决策工具的开发实现
flutter·华为·harmonyos·鸿蒙
Never_Satisfied13 分钟前
在JavaScript / HTML中,HTML元素自定义属性使用指南
开发语言·javascript·html
前端 贾公子19 分钟前
husky 9.0升级指南
javascript
IT陈图图29 分钟前
Flutter × OpenHarmony 实战:构建智能汇率转换金额输入框
flutter·开源·鸿蒙·openharmony
欣然~31 分钟前
鸿蒙系统专利管理系统
华为·harmonyos
南村群童欺我老无力.35 分钟前
Flutter 框架跨平台鸿蒙开发 - 打造经典连连看游戏
flutter·游戏·华为·harmonyos