diff --git a/OAT.xml b/OAT.xml
new file mode 100644
index 0000000000000000000000000000000000000000..92678038849d209ab31fc90f4e2c04e70da1d01e
--- /dev/null
+++ b/OAT.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ohos/.gitignore b/ohos/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..96486fd9302436d1f5334df3e5240c1ea252e7e9
--- /dev/null
+++ b/ohos/.gitignore
@@ -0,0 +1,30 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+.packages
+build/
diff --git a/ohos/.metadata b/ohos/.metadata
new file mode 100644
index 0000000000000000000000000000000000000000..f3ef596bb8d41ac0ed1bfe3aaf8ac70453047bab
--- /dev/null
+++ b/ohos/.metadata
@@ -0,0 +1,30 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+ revision: 6e880180d1be82672dba0917db429179217f1172
+ channel: master
+
+project_type: plugin
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: 6e880180d1be82672dba0917db429179217f1172
+ base_revision: 6e880180d1be82672dba0917db429179217f1172
+ - platform: ohos
+ create_revision: 6e880180d1be82672dba0917db429179217f1172
+ base_revision: 6e880180d1be82672dba0917db429179217f1172
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/ohos/CHANGELOG.md b/ohos/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..abd84ca152910f0f8124ed1c63a1b2b4378c2dc4
--- /dev/null
+++ b/ohos/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 1.0.0
+
+* Support OpenHarmony.
\ No newline at end of file
diff --git a/ohos/LICENSE b/ohos/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..8940a4be1b58ad5cb489af72ac1c7ec91d496532
--- /dev/null
+++ b/ohos/LICENSE
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/ohos/README.md b/ohos/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..25466349fd208bfb597c64186ac3b3a6188effee
--- /dev/null
+++ b/ohos/README.md
@@ -0,0 +1,70 @@
+# flutter_jsbridge_plugin_ohos
+
+# Add JsBridge Plugin to the WebView
+
+[A Flutter plugin that provides a JsBridge on WebView widget.](https://pub.dev/packages/bridge_webview_flutter)
+
+This plugin must introduce [webview_flutter](https://pub.dev/packages/webview_flutter)
+
+## Getting Started
+
+This project is a starting point for a Flutter
+[plug-in package](https://flutter.dev/developing-packages/),
+a specialized package that includes platform-specific implementation code for
+Ohos.
+
+For help getting started with Flutter development, view the
+[online documentation](https://flutter.dev/docs), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
+
+## Usage
+
+```yaml
+dependencies:
+ flutter_jsbridge_plugin: 0.0.5
+ flutter_jsbridge_plugin_ohos: 1.0.0
+```
+
+### Init JsBridge and register handler
+
+```
+...
+final JsBridge _jsBridge = JsBridge();
+...
+WebView(
+ initialUrl: "https://www.baidu.com?timeStamp=${new DateTime.now().millisecondsSinceEpoch}",
+ javascriptMode: JavascriptMode.unrestricted,
+ onWebViewCreated: (WebViewController webViewController) async {
+ _jsBridge.loadJs(webViewController);
+ _controller.complete(webViewController);
+ _jsBridge.registerHandler("getToken", onCallBack: (data, func) {
+ // return token to js
+ func({"token": "token"});
+ });
+ _jsBridge.registerHandler("IAPpayment", onCallBack: (data, func) {
+ print("js call flutter iap");
+ });
+ _jsBridge.registerHandler("back", onCallBack: (data, func) {
+ print("js call flutter back");
+ });
+ },
+ navigationDelegate: (NavigationRequest request) {
+ if (_jsBridge.handlerUrl(request.url)) {
+ return NavigationDecision.navigate;
+ }
+ return NavigationDecision.prevent;
+ },
+ onPageStarted: (url) {
+ _jsBridge.init();
+ },
+))
+
+```
+
+## JS Usage
+[js file](https://github.com/epoll-j/flutter_jsbridge_plugin/blob/master/JSBridge.js)
+
+## 支持格式
+| 格式 |android|ios| OpenHarmony |
+|:-----------------|:----:|:----:|:--------------:|
+| getPlatformVersion|✅ | ✅ | ✅ |
\ No newline at end of file
diff --git a/ohos/analysis_options.yaml b/ohos/analysis_options.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a5744c1cfbe77ae2daba29c74156c617b5f09b77
--- /dev/null
+++ b/ohos/analysis_options.yaml
@@ -0,0 +1,4 @@
+include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/ohos/example/.gitignore b/ohos/example/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..24476c5d1eb55824c76d8b01a3965f94abad1ef8
--- /dev/null
+++ b/ohos/example/.gitignore
@@ -0,0 +1,44 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/ohos/example/README.md b/ohos/example/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a9f56a84083227c141d80df7504e8ba219205787
--- /dev/null
+++ b/ohos/example/README.md
@@ -0,0 +1,16 @@
+# flutter_jsbridge_plugin_ohos_example
+
+Demonstrates how to use the flutter_jsbridge_plugin_ohos plugin.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
+
+For help getting started with Flutter development, view the
+[online documentation](https://docs.flutter.dev/), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
diff --git a/ohos/example/analysis_options.yaml b/ohos/example/analysis_options.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..61b6c4de17c96863d24279f06b85e01b6ebbdb34
--- /dev/null
+++ b/ohos/example/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/ohos/example/lib/main.dart b/ohos/example/lib/main.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d12eaef5ef720c4cd6b44c674aacff982a978b62
--- /dev/null
+++ b/ohos/example/lib/main.dart
@@ -0,0 +1,105 @@
+import 'package:flutter/material.dart';
+import 'dart:async';
+
+import 'package:flutter/services.dart';
+import 'package:flutter_jsbridge_plugin_ohos/flutterjsbridgeplugin.dart';
+import 'package:flutter_jsbridge_plugin_ohos/js_bridge.dart';
+import 'package:webview_flutter/webview_flutter.dart';
+
+void main() {
+ runApp(MyApp());
+}
+
+class MyApp extends StatefulWidget {
+ @override
+ _MyAppState createState() => _MyAppState();
+}
+
+class _MyAppState extends State {
+ String _platformVersion = 'Unknown';
+
+ final Completer _controller = Completer();
+ final JsBridge _jsBridge = JsBridge();
+ late final WebViewController _webcontroller;
+
+ @override
+ void initState() {
+ super.initState();
+ initPlatformState();
+
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ try{
+ _jsBridge.loadJs(_webcontroller);
+ _controller.complete(_webcontroller);
+ _jsBridge.registerHandler("getToken", onCallBack: (data, func) {
+ // return token to js
+ func({"token": "token"});
+ });
+ _jsBridge.registerHandler("IAPpayment", onCallBack: (data, func) {
+ print("js call flutter iap");
+ });
+ _jsBridge.registerHandler("back", onCallBack: (data, func) {
+ print("js call flutter back");
+ });
+ }catch(error){
+ print('main WidgetsBinding error:$error');
+ }
+ });
+
+ _webcontroller = WebViewController()
+ ..setJavaScriptMode(JavaScriptMode.unrestricted)
+ ..setBackgroundColor(const Color(0x00000000))
+ ..setNavigationDelegate(
+ NavigationDelegate(
+ onProgress: (int progress) {
+ // Update loading bar.
+ },
+ onPageStarted: (String url) {
+ _jsBridge.init();
+ },
+ onPageFinished: (String url) {},
+ onWebResourceError: (WebResourceError error) {},
+ onNavigationRequest: (NavigationRequest request) {
+ if (_jsBridge.handlerUrl(request.url)) {
+ return NavigationDecision.navigate;
+ }
+ return NavigationDecision.prevent;
+ },
+ ),
+ )
+ ..loadRequest(Uri.parse('https://juejin.cn?timeStamp=${new DateTime.now().millisecondsSinceEpoch}'));
+ }
+
+ // Platform messages are asynchronous, so we initialize in an async method.
+ Future initPlatformState() async {
+ String platformVersion;
+ // Platform messages may fail, so we use a try/catch PlatformException.
+ try {
+ platformVersion = await Flutterjsbridgeplugin.platformVersion;
+ } on PlatformException {
+ platformVersion = 'Failed to get platform version.';
+ }
+
+ // If the widget was removed from the tree while the asynchronous platform
+ // message was in flight, we want to discard the reply rather than calling
+ // setState to update our non-existent appearance.
+ if (!mounted) return;
+
+ setState(() {
+ _platformVersion = platformVersion;
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ home: Scaffold(
+ appBar: AppBar(
+ title: const Text('Plugin example app'),
+ ),
+ body: WebViewWidget(
+ controller: _webcontroller,
+ )),
+ );
+ }
+}
diff --git a/ohos/example/ohos/.gitignore b/ohos/example/ohos/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..6ca13b3170eec5dd5ac5ad7f1c4dd0118845f473
--- /dev/null
+++ b/ohos/example/ohos/.gitignore
@@ -0,0 +1,19 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+*.har
+**/BuildProfile.ets
+**/oh-package-lock.json5
+
+**/src/main/resources/rawfile/flutter_assets/
+**/libs/arm64-v8a/libapp.so
+**/libs/arm64-v8a/libflutter.so
+**/libs/arm64-v8a/libvmservice_snapshot.so
diff --git a/ohos/example/ohos/AppScope/app.json5 b/ohos/example/ohos/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..c55462f2651c174b9e0c3421215edf0c0b9bc06f
--- /dev/null
+++ b/ohos/example/ohos/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.flutter_jsbridge_plugin.flutter_jsbridge_plugin_ohos_example",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:app_icon",
+ "label": "$string:app_name"
+ }
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/AppScope/resources/base/element/string.json b/ohos/example/ohos/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..e37bfeaa2424e7ae5bf288873f72cea8f722b307
--- /dev/null
+++ b/ohos/example/ohos/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "flutter_jsbridge_plugin_ohos_example"
+ }
+ ]
+}
diff --git a/ohos/example/ohos/AppScope/resources/base/media/app_icon.png b/ohos/example/ohos/AppScope/resources/base/media/app_icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/ohos/example/ohos/AppScope/resources/base/media/app_icon.png differ
diff --git a/ohos/example/ohos/build-profile.json5 b/ohos/example/ohos/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..1d12140d202702d7c73d64f1b291fe5c45a660ce
--- /dev/null
+++ b/ohos/example/ohos/build-profile.json5
@@ -0,0 +1,27 @@
+{
+ "app": {
+ "signingConfigs": [],
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compatibleSdkVersion": "5.0.0(12)",
+ "runtimeOS": "HarmonyOS"
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/.gitignore b/ohos/example/ohos/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..2795a1c5b1fe53659dd1b71d90ba0592eaf7e043
--- /dev/null
+++ b/ohos/example/ohos/entry/.gitignore
@@ -0,0 +1,7 @@
+
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/build-profile.json5 b/ohos/example/ohos/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..633d360fbc91a3186a23b66ab71b27e5618944cb
--- /dev/null
+++ b/ohos/example/ohos/entry/build-profile.json5
@@ -0,0 +1,29 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+{
+ "apiType": 'stageMode',
+ "buildOption": {
+ },
+ "targets": [
+ {
+ "name": "default",
+ "runtimeOS": "HarmonyOS"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/hvigorfile.ts b/ohos/example/ohos/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..894fc15c6b793f085e6c8506e43d719af658e8ff
--- /dev/null
+++ b/ohos/example/ohos/entry/hvigorfile.ts
@@ -0,0 +1,17 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+export { hapTasks } from '@ohos/hvigor-ohos-plugin';
diff --git a/ohos/example/ohos/entry/oh-package.json5 b/ohos/example/ohos/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..2d0901c4c2867015b44260b308fb176c4e02a1da
--- /dev/null
+++ b/ohos/example/ohos/entry/oh-package.json5
@@ -0,0 +1,12 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {
+ "flutter_jsbridge_plugin_ohos": "file:../har/flutter_jsbridge_plugin_ohos.har",
+ "webview_flutter_ohos": "file:../har/webview_flutter_ohos.har"
+ }
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets b/ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8bc48be8773196f34cccb15cf517f87f5c6b94d2
--- /dev/null
+++ b/ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,24 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
+import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
+
+export default class EntryAbility extends FlutterAbility {
+ configureFlutterEngine(flutterEngine: FlutterEngine) {
+ super.configureFlutterEngine(flutterEngine)
+ GeneratedPluginRegistrant.registerWith(flutterEngine)
+ }
+}
diff --git a/ohos/example/ohos/entry/src/main/ets/pages/Index.ets b/ohos/example/ohos/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..1125f9fdd95f4310a182c1c9e3680f37f73686c9
--- /dev/null
+++ b/ohos/example/ohos/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import common from '@ohos.app.ability.common';
+import { FlutterPage } from '@ohos/flutter_ohos'
+
+let storage = LocalStorage.getShared()
+const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'
+
+@Entry(storage)
+@Component
+struct Index {
+ private context = getContext(this) as common.UIAbilityContext
+ @LocalStorageLink('viewId') viewId: string = "";
+
+ build() {
+ Column() {
+ FlutterPage({ viewId: this.viewId })
+ }
+ }
+
+ onBackPress(): boolean {
+ this.context.eventHub.emit(EVENT_BACK_PRESS)
+ return true
+ }
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets b/ohos/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets
new file mode 100644
index 0000000000000000000000000000000000000000..bec4c450be4871a2d2d4e9eda16d46f806651ea2
--- /dev/null
+++ b/ohos/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { FlutterEngine, Log } from '@ohos/flutter_ohos';
+import FlutterJsbridgePluginOhosPlugin from 'flutter_jsbridge_plugin_ohos';
+import WebViewFlutterPlugin from 'webview_flutter_ohos';
+
+/**
+ * Generated file. Do not edit.
+ * This file is generated by the Flutter tool based on the
+ * plugins that support the Ohos platform.
+ */
+
+const TAG = "GeneratedPluginRegistrant";
+
+export class GeneratedPluginRegistrant {
+
+ static registerWith(flutterEngine: FlutterEngine) {
+ try {
+ flutterEngine.getPlugins()?.add(new FlutterJsbridgePluginOhosPlugin());
+ flutterEngine.getPlugins()?.add(new WebViewFlutterPlugin());
+ } catch (e) {
+ Log.e(
+ TAG,
+ "Tried to register plugins with FlutterEngine ("
+ + flutterEngine
+ + ") failed.");
+ Log.e(TAG, "Received exception while registering", e);
+ }
+ }
+}
diff --git a/ohos/example/ohos/entry/src/main/module.json5 b/ohos/example/ohos/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..7bbf78b18f39991b1404061c7437538c7d532bb7
--- /dev/null
+++ b/ohos/example/ohos/entry/src/main/module.json5
@@ -0,0 +1,53 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "phone"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:icon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "requestPermissions": [
+ {"name" : "ohos.permission.INTERNET"},
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/main/resources/base/element/color.json b/ohos/example/ohos/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/ohos/example/ohos/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/main/resources/base/element/string.json b/ohos/example/ohos/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..d33431df1fff34b989432821612f808bcf4a70b3
--- /dev/null
+++ b/ohos/example/ohos/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "flutter_jsbridge_plugin_ohos_example"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/main/resources/base/media/icon.png b/ohos/example/ohos/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/ohos/example/ohos/entry/src/main/resources/base/media/icon.png differ
diff --git a/ohos/example/ohos/entry/src/main/resources/base/profile/main_pages.json b/ohos/example/ohos/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce
--- /dev/null
+++ b/ohos/example/ohos/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/ohos/example/ohos/entry/src/main/resources/en_US/element/string.json b/ohos/example/ohos/entry/src/main/resources/en_US/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..d33431df1fff34b989432821612f808bcf4a70b3
--- /dev/null
+++ b/ohos/example/ohos/entry/src/main/resources/en_US/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "flutter_jsbridge_plugin_ohos_example"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/main/resources/zh_CN/element/string.json b/ohos/example/ohos/entry/src/main/resources/zh_CN/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..1b2ce0ce2b531d4ef1b0b7a9af66c09a7809a8fd
--- /dev/null
+++ b/ohos/example/ohos/entry/src/main/resources/zh_CN/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "模块描述"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "flutter_jsbridge_plugin_ohos_example"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets b/ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..25d4c71ff3cd584f5d64f6f8c0ac864928c234c4
--- /dev/null
+++ b/ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import hilog from '@ohos.hilog';
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
+
+export default function abilityTest() {
+ describe('ActsAbilityTest', function () {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(function () {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ })
+ beforeEach(function () {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ })
+ afterEach(function () {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ })
+ afterAll(function () {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ })
+ it('assertContain',0, function () {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
+ let a = 'abc'
+ let b = 'b'
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b)
+ expect(a).assertEqual(a)
+ })
+ })
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets b/ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..f4140030e65d20df6af30a6bf51e464dea8f8aa6
--- /dev/null
+++ b/ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,20 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import abilityTest from './Ability.test'
+
+export default function testsuite() {
+ abilityTest()
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets b/ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..4ca645e6013cfce8e7dbb728313cb8840c4da660
--- /dev/null
+++ b/ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import UIAbility from '@ohos.app.ability.UIAbility';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import hilog from '@ohos.hilog';
+import { Hypium } from '@ohos/hypium';
+import testsuite from '../test/List.test';
+import window from '@ohos.window';
+
+export default class TestAbility extends UIAbility {
+ onCreate(want, launchParam) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:'+ JSON.stringify(launchParam) ?? '');
+ var abilityDelegator: any
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ var abilityDelegatorArguments: any
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
+ Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
+ }
+
+ onDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
+ windowStage.loadContent('testability/pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
+ JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
+ }
+
+ onForeground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
+ }
+
+ onBackground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
+ }
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets b/ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..cef0447cd2f137ef82d223ead2e156808878ab90
--- /dev/null
+++ b/ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import hilog from '@ohos.hilog';
+
+@Entry
+@Component
+struct Index {
+ aboutToAppear() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear');
+ }
+ @State message: string = 'Hello World'
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ Button() {
+ Text('next page')
+ .fontSize(20)
+ .fontWeight(FontWeight.Bold)
+ }.type(ButtonType.Capsule)
+ .margin({
+ top: 20
+ })
+ .backgroundColor('#0D9FFB')
+ .width('35%')
+ .height('5%')
+ .onClick(()=>{
+ })
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+ }
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1def08f2e9dcbfa3454a07b7a3b82b173bb90d02
--- /dev/null
+++ b/ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import hilog from '@ohos.hilog';
+import TestRunner from '@ohos.application.testRunner';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+
+var abilityDelegator = undefined
+var abilityDelegatorArguments = undefined
+
+async function onAbilityCreateCallback() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
+}
+
+async function addAbilityMonitorCallback(err: any) {
+ hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
+}
+
+export default class OpenHarmonyTestRunner implements TestRunner {
+ constructor() {
+ }
+
+ onPrepare() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
+ }
+
+ async onRun() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility'
+ let lMonitor = {
+ abilityName: testAbilityName,
+ onAbilityCreate: onAbilityCreateCallback,
+ };
+ abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
+ var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName
+ var debug = abilityDelegatorArguments.parameters['-D']
+ if (debug == 'true')
+ {
+ cmd += ' -D'
+ }
+ hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd);
+ abilityDelegator.executeShellCommand(cmd,
+ (err: any, d: any) => {
+ hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? '');
+ hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? '');
+ hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? '');
+ })
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
+ }
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/ohosTest/module.json5 b/ohos/example/ohos/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..fab77ce2e0c61e3ad010bab5b27ccbd15f9a8c96
--- /dev/null
+++ b/ohos/example/ohos/entry/src/ohosTest/module.json5
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "description": "$string:module_test_desc",
+ "mainElement": "TestAbility",
+ "deviceTypes": [
+ "phone"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:test_pages",
+ "abilities": [
+ {
+ "name": "TestAbility",
+ "srcEntry": "./ets/testability/TestAbility.ets",
+ "description": "$string:TestAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:TestAbility_label",
+ "exported": true,
+ "startWindowIcon": "$media:icon",
+ "startWindowBackground": "$color:start_window_background",
+ "skills": [
+ {
+ "actions": [
+ "action.system.home"
+ ],
+ "entities": [
+ "entity.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/ohos/example/ohos/entry/src/ohosTest/resources/base/element/color.json b/ohos/example/ohos/entry/src/ohosTest/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/ohos/example/ohos/entry/src/ohosTest/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/ohosTest/resources/base/element/string.json b/ohos/example/ohos/entry/src/ohosTest/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..65d8fa5a7cf54aa3943dcd0214f58d1771bc1f6c
--- /dev/null
+++ b/ohos/example/ohos/entry/src/ohosTest/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_test_desc",
+ "value": "test ability description"
+ },
+ {
+ "name": "TestAbility_desc",
+ "value": "the test ability"
+ },
+ {
+ "name": "TestAbility_label",
+ "value": "test label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/entry/src/ohosTest/resources/base/media/icon.png b/ohos/example/ohos/entry/src/ohosTest/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/ohos/example/ohos/entry/src/ohosTest/resources/base/media/icon.png differ
diff --git a/ohos/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json b/ohos/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..b7e7343cacb32ce982a45e76daad86e435e054fe
--- /dev/null
+++ b/ohos/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "testability/pages/Index"
+ ]
+}
diff --git a/ohos/example/ohos/hvigor/hvigor-config.json5 b/ohos/example/ohos/hvigor/hvigor-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..3bcb859e88b72cc2dcc6ec1bc89d26a6411cb2d8
--- /dev/null
+++ b/ohos/example/ohos/hvigor/hvigor-config.json5
@@ -0,0 +1,23 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+{
+ "modelVersion": "5.0.0",
+ "dependencies": {
+ },
+ "properties": {
+ "ohos.nativeResolver": false
+ }
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/hvigorfile.ts b/ohos/example/ohos/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8f2d2aafe6d6a3a71a9944ebd0c91fbc308ac9d1
--- /dev/null
+++ b/ohos/example/ohos/hvigorfile.ts
@@ -0,0 +1,21 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
\ No newline at end of file
diff --git a/ohos/example/ohos/oh-package.json5 b/ohos/example/ohos/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..da05f53534e027d70bb597a37f3fbf0b47cc53dd
--- /dev/null
+++ b/ohos/example/ohos/oh-package.json5
@@ -0,0 +1,21 @@
+{
+ "modelVersion": "5.0.0",
+ "name": "flutter_jsbridge_plugin_ohos_example",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {
+ "@ohos/flutter_ohos": "file:./har/flutter.har"
+ },
+ "devDependencies": {
+ "@ohos/hypium": "1.0.6"
+ },
+ "overrides": {
+ "@ohos/flutter_ohos": "file:./har/flutter.har",
+ "flutter_jsbridge_plugin_ohos": "file:./har/flutter_jsbridge_plugin_ohos.har",
+ "webview_flutter_ohos": "file:./har/webview_flutter_ohos.har",
+ "@ohos/flutter_module": "file:./entry"
+ }
+}
\ No newline at end of file
diff --git a/ohos/example/pubspec.yaml b/ohos/example/pubspec.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c6a20028faa586a9ebc29932c4f7c57b09bf9a8f
--- /dev/null
+++ b/ohos/example/pubspec.yaml
@@ -0,0 +1,87 @@
+name: flutter_jsbridge_plugin_ohos_example
+description: Demonstrates how to use the flutter_jsbridge_plugin_ohos plugin.
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+environment:
+ sdk: '>=2.19.6 <3.0.0'
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+ flutter:
+ sdk: flutter
+
+ flutter_jsbridge_plugin_ohos:
+ # When depending on this package from a real application you should use:
+ # flutter_jsbridge_plugin_ohos: ^x.y.z
+ # See https://dart.dev/tools/pub/dependencies#version-constraints
+ # The example app is bundled with the plugin so we use a path dependency on
+ # the parent directory to use the current plugin's version.
+ path: ../
+
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.2
+ webview_flutter:
+ git:
+ url: "https://gitee.com/openharmony-sig/flutter_packages.git"
+ path: "packages/webview_flutter-v4.4.4/webview_flutter"
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+ espresso: ^0.2.0
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^2.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/ohos/example/test/widget_test.dart b/ohos/example/test/widget_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..a600522e285561e167889eb4ccd1006f3349bbac
--- /dev/null
+++ b/ohos/example/test/widget_test.dart
@@ -0,0 +1,27 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility in the flutter_test package. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:flutter_jsbridge_plugin_ohos_example/main.dart';
+
+void main() {
+ testWidgets('Verify Platform version', (WidgetTester tester) async {
+ // Build our app and trigger a frame.
+ await tester.pumpWidget(const MyApp());
+
+ // Verify that platform version is retrieved.
+ expect(
+ find.byWidgetPredicate(
+ (Widget widget) => widget is Text &&
+ widget.data!.startsWith('Running on:'),
+ ),
+ findsOneWidget,
+ );
+ });
+}
diff --git a/ohos/lib/flutterjsbridgeplugin.dart b/ohos/lib/flutterjsbridgeplugin.dart
new file mode 100644
index 0000000000000000000000000000000000000000..92fa795b34ebde6ef19197721b1b1d738130c70c
--- /dev/null
+++ b/ohos/lib/flutterjsbridgeplugin.dart
@@ -0,0 +1,34 @@
+import 'dart:async';
+import 'package:flutter/services.dart';
+
+class Flutterjsbridgeplugin {
+ static const MethodChannel _channel =
+ MethodChannel('flutterjsbridgeplugin');
+
+ Flutterjsbridgeplugin() {
+ _channel.setMethodCallHandler(_onMethodCall);
+ }
+
+ static Future get platformVersion async {
+ final String version = await _channel.invokeMethod('getPlatformVersion');
+ print('get platformVersion version: $version');
+ return version;
+ }
+
+ static Future get scrpit async {
+ final String initScript = await _channel.invokeMethod("getScript");
+ return "javascript:$initScript";
+ }
+
+ Future isMainThread() async {
+ return await _channel.invokeMethod("isMainThread");
+ }
+
+ Future handlerReturnData(String url) async {
+ return await _channel.invokeMethod("handlerReturnData", url);
+ }
+
+ Future _onMethodCall(MethodCall call) async {
+ return false;
+ }
+}
diff --git a/ohos/lib/init_script.dart b/ohos/lib/init_script.dart
new file mode 100644
index 0000000000000000000000000000000000000000..fcbd257fceaefbf9467c9837d9c30ac4446dda8a
--- /dev/null
+++ b/ohos/lib/init_script.dart
@@ -0,0 +1,242 @@
+// ignore: non_constant_identifier_names
+String init_script_android = '''
+(function() {
+ if (window.WebViewJavascriptBridge) {
+ return;
+ }
+
+ var lastCallTime = 0;
+ var stoId = null;
+ var FETCH_QUEUE = 50;
+
+ var messagingIframe;
+ var sendMessageQueue = [];
+ var receiveMessageQueue = [];
+ var messageHandlers = {};
+ var timer = null;
+
+ var CUSTOM_PROTOCOL_SCHEME = 'jsbridge';
+ var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/';
+
+ var responseCallbacks = {};
+ var uniqueId = 1;
+
+ var base64encodechars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ function base64encode(str) {
+ if (str === undefined) {
+ return str;
+ }
+
+ var out, i, len;
+ var c1, c2, c3;
+ len = str.length;
+ i = 0;
+ out = "";
+ while (i < len) {
+ c1 = str.charCodeAt(i++) & 0xff;
+ if (i == len) {
+ out += base64encodechars.charAt(c1 >> 2);
+ out += base64encodechars.charAt((c1 & 0x3) << 4);
+ out += "==";
+ break;
+ }
+ c2 = str.charCodeAt(i++);
+ if (i == len) {
+ out += base64encodechars.charAt(c1 >> 2);
+ out += base64encodechars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
+ out += base64encodechars.charAt((c2 & 0xf) << 2);
+ out += "=";
+ break;
+ }
+ c3 = str.charCodeAt(i++);
+ out += base64encodechars.charAt(c1 >> 2);
+ out += base64encodechars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
+ out += base64encodechars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6));
+ out += base64encodechars.charAt(c3 & 0x3f);
+ }
+ return out;
+ }
+
+
+ function _createQueueReadyIframe(doc) {
+// messagingIframe = doc.createElement('iframe');
+// messagingIframe.style.display = 'none';
+// doc.documentElement.appendChild(messagingIframe);
+ }
+
+ function isAndroid() {
+ var ua = navigator.userAgent.toLowerCase();
+ var isA = ua.indexOf("android") > -1;
+ if (isA) {
+ return true;
+ }
+ return false;
+ }
+
+ function isIphone() {
+ var ua = navigator.userAgent.toLowerCase();
+ var isIph = ua.indexOf("iphone") > -1;
+ if (isIph) {
+ return true;
+ }
+ return false;
+ }
+
+ //set default messageHandler
+ function init(messageHandler) {
+ if (WebViewJavascriptBridge._messageHandler) {
+ throw new Error('WebViewJavascriptBridge.init called twice');
+ }
+ WebViewJavascriptBridge._messageHandler = messageHandler;
+ var receivedMessages = receiveMessageQueue;
+ receiveMessageQueue = null;
+ for (var i = 0; i < receivedMessages.length; i++) {
+ _dispatchMessageFromNative(receivedMessages[i]);
+ }
+ }
+
+ function send(data, responseCallback) {
+ _doSend({
+ data: data
+ }, responseCallback);
+ }
+
+ function registerHandler(handlerName, handler) {
+ messageHandlers[handlerName] = handler;
+ }
+
+ function callHandler(handlerName, data, responseCallback) {
+ console.log(handlerName);
+ _doSend({
+ handlerName: handlerName,
+ data: data
+ }, responseCallback);
+ }
+
+ //sendMessage add message, 触发native处理 sendMessage
+ function _doSend(message, responseCallback) {
+ console.log('send');
+ if (responseCallback) {
+ var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();
+ responseCallbacks[callbackId] = responseCallback;
+ message.callbackId = callbackId;
+ }
+ sendMessageQueue.push(message);
+ if (!timer) {
+ timer = setTimeout(function() {
+ _getIframe().src = CUSTOM_PROTOCOL_SCHEME + '://return/sendMsg/' + encodeURIComponent(JSON.stringify(sendMessageQueue));
+ sendMessageQueue = [];
+ timer = null;
+ }, 30);
+ }
+ }
+
+ // 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容
+ function _fetchQueue() {
+ if (sendMessageQueue.length === 0) {
+ return;
+ }
+
+ if (new Date().getTime() - lastCallTime < FETCH_QUEUE) {
+ if (!stoId) {
+ stoId = setTimeout(_fetchQueue, FETCH_QUEUE);
+ }
+ return;
+ }
+
+ lastCallTime = new Date().getTime();
+ stoId = null;
+
+ var messageQueueString = JSON.stringify(sendMessageQueue);
+ sendMessageQueue = [];
+ if (messageQueueString === '[]') {
+ return;
+ }
+
+ _getIframe().src = CUSTOM_PROTOCOL_SCHEME + '://return/sendMsg/' + encodeURIComponent(messageQueueString);
+
+// var messageQueueString = JSON.stringify(sendMessageQueue);
+// sendMessageQueue = [];
+// //add by hq
+// if (isIphone()) {
+// return messageQueueString;
+// //android can't read directly the return data, so we can reload iframe src to communicate with java
+// } else if (isAndroid()) {
+// messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/sendMsg/' + encodeURIComponent(messageQueueString);
+// }
+ }
+
+ //提供给native使用,
+ function _dispatchMessageFromNative(messageJSON) {
+ setTimeout(function() {
+ var message = JSON.parse(messageJSON);
+ var responseCallback;
+ //java call finished, now need to call js callback function
+ if (message.responseId) {
+ responseCallback = responseCallbacks[message.responseId];
+ if (!responseCallback) {
+ return;
+ }
+ responseCallback(message.responseData);
+ delete responseCallbacks[message.responseId];
+ } else {
+ //直接发送
+ if (message.callbackId) {
+ var callbackResponseId = message.callbackId;
+ responseCallback = function(responseData) {
+ _doSend({
+ responseId: callbackResponseId,
+ responseData: responseData
+ });
+ };
+ }
+ var handler = WebViewJavascriptBridge._messageHandler;
+ if (message.handlerName) {
+ handler = messageHandlers[message.handlerName];
+ }
+ //查找指定handler
+ try {
+ handler(message.data, responseCallback);
+ } catch (exception) {
+ if (typeof console != 'undefined') {
+ console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception);
+ }
+ }
+ }
+ });
+ }
+
+ //提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以
+ function _handleMessageFromNative(messageJSON) {
+// if (receiveMessageQueue) {
+// receiveMessageQueue.push(messageJSON);
+// } else {
+ _dispatchMessageFromNative(messageJSON);
+// }
+ }
+
+ function _getIframe() {
+ if (typeof(messagingIframe) == 'undefined') {
+ messagingIframe = document.createElement('iframe');
+ messagingIframe.style.display = 'none';
+ document.documentElement.appendChild(messagingIframe);
+ }
+ return messagingIframe;
+ }
+
+ var WebViewJavascriptBridge = window.WebViewJavascriptBridge = {
+ init: init,
+ send: send,
+ registerHandler: registerHandler,
+ callHandler: callHandler,
+ _handleMessageFromNative: _handleMessageFromNative,
+ _fetchQueue: _fetchQueue
+ };
+
+ var doc = document;
+// _createQueueReadyIframe(doc);
+ var readyEvent = doc.createEvent('Events');
+ readyEvent.initEvent('WebViewJavascriptBridgeReady');
+ readyEvent.bridge = WebViewJavascriptBridge;
+ doc.dispatchEvent(readyEvent);
+})();''';
\ No newline at end of file
diff --git a/ohos/lib/js_bridge.dart b/ohos/lib/js_bridge.dart
new file mode 100644
index 0000000000000000000000000000000000000000..6668981f976ef269c85e0df9f3463265576170bc
--- /dev/null
+++ b/ohos/lib/js_bridge.dart
@@ -0,0 +1,124 @@
+import 'dart:io';
+
+import 'package:webview_flutter/webview_flutter.dart';
+import 'dart:convert' as convert;
+import 'package:sprintf/sprintf.dart';
+
+import 'init_script.dart';
+import 'js_obj.dart';
+
+typedef CallBackFunction = void Function(dynamic data);
+typedef BridgeHandler = void Function(dynamic data, CallBackFunction function);
+
+class JsBridge {
+ WebViewController _webViewController = WebViewController();
+ Map _callbacks = Map();
+ Map _handlers = Map();
+ int _uniqueId = 0;
+ static final String _protocolScheme = "jsbridge://";
+ final String _fetchData = "${_protocolScheme}return/fetch";
+ final String _returnData = "${_protocolScheme}return/sendMsg/";
+ String _dartToJs =
+ "javascript:WebViewJavascriptBridge._handleMessageFromNative('%s');";
+
+ void loadJs(WebViewController controller) {
+ _webViewController = controller;
+ init();
+ }
+
+ void init() {
+ if (_webViewController == null) {
+ throw "WebViewController must not null";
+ }
+
+ _loadJs(init_script_android);
+ }
+
+ bool handlerUrl(String url) {
+ return _handlerReturnData(url);
+ }
+
+ bool _handlerReturnData(String url) {
+ if (url.startsWith(_protocolScheme)) {
+ if (url == _fetchData) {
+ _fetchQueue();
+ } else {
+ List list = JsMsg.fromList(convert
+ .jsonDecode(Uri.decodeComponent(url).replaceAll(_returnData, "")));
+ print(list);
+ for (JsMsg msg in list) {
+ print(msg);
+ if (msg.responseId != null) {
+
+ } else {
+ late CallBackFunction function;
+ if (msg.callbackId != null) {
+ if (msg.callbackId != null) {
+ function = (dynamic data) {
+ JsMsg callbackMsg = JsMsg();
+ callbackMsg.responseId = msg.callbackId;
+ callbackMsg.responseData = convert.jsonEncode(data);
+ // 发送
+ _loadJs(sprintf(_dartToJs, [_replaceJson(callbackMsg.toJson())]));
+ };
+ }
+ } else {
+ function = (dynamic data) {};
+ }
+ BridgeHandler? handler;
+ if (msg.handlerName != null) {
+ handler = _handlers[msg.handlerName];
+ }
+ if (handler != null) {
+ handler.call(msg.data, function);
+ }
+ }
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ void _fetchQueue() {
+ _loadJs("WebViewJavascriptBridge._fetchQueue()");
+ }
+
+ void callHandler(String handlerName,
+ {dynamic data, required CallBackFunction onCallBack}) {
+ JsRequest request = JsRequest();
+ request.handlerName = handlerName;
+ if (data != null) {
+ if (data is String) {
+ request.data = data;
+ } else {
+ request.data = convert.jsonEncode(data);
+ }
+ }
+ request.callbackId = _generateId();
+ if (onCallBack != null) {
+ _callbacks[request.callbackId] = onCallBack;
+ }
+ _loadJs(sprintf(_dartToJs, [_replaceJson(request.toJson())]));
+ }
+
+ void registerHandler(String handlerName,
+ {dynamic data, required BridgeHandler onCallBack}) {
+ if (onCallBack != null) {
+ _handlers[handlerName] = onCallBack;
+ }
+ }
+
+ String _generateId() {
+ return "flutter_cb_${_uniqueId++}";
+ }
+
+ String _replaceJson(String json) {
+ json = json.replaceAll("\\", "\\\\");
+ return json;
+ }
+
+ void _loadJs(String script) {
+ _webViewController.runJavaScript(script);
+ }
+}
diff --git a/ohos/lib/js_obj.dart b/ohos/lib/js_obj.dart
new file mode 100644
index 0000000000000000000000000000000000000000..8b0fdc04cff23ed4ba347e594da2edcda5f2fe59
--- /dev/null
+++ b/ohos/lib/js_obj.dart
@@ -0,0 +1,59 @@
+import 'dart:convert' as convert;
+
+class JsRequest {
+ late String callbackId;
+ late String data;
+ late String handlerName;
+
+ String toJson() {
+ return convert.jsonEncode({
+ "callbackId": callbackId ?? "",
+ "data": data ?? "",
+ "handlerName": handlerName ?? ""
+ });
+ }
+}
+
+class JsMsg {
+ late String callbackId; //callbackId
+ late String responseId; //responseId
+ late String responseData; //responseData
+ late String data; //data of message
+ late String handlerName;
+
+ JsMsg();
+
+ static List fromList(List list) {
+ List msgList = [];
+ for (Map json in list) {
+ JsMsg msg = JsMsg();
+ msg.callbackId = json["callbackId"];
+ msg.responseId = json["responseId"];
+ msg.responseData = convert.jsonEncode(json["responseData"]);
+ msg.data = convert.jsonEncode(json["data"]);
+ msg.handlerName = json["handlerName"];
+ msgList.add(msg);
+ }
+ return msgList;
+ }
+
+ factory JsMsg.formJson(Map json) {
+ JsMsg msg = JsMsg();
+ msg.callbackId = json["callbackId"];
+ msg.responseId = json["responseId"];
+ msg.responseData = convert.jsonEncode(json["responseData"]);
+ msg.data = convert.jsonEncode(json["data"]);
+ msg.handlerName = json["handlerName"];
+ return msg;
+ }
+
+ String toJson() {
+ return convert.jsonEncode({
+ "callbackId": callbackId ?? "",
+ "responseId": responseId ?? "",
+ "responseData": responseData ?? "",
+ "data": data ?? "",
+ "handlerName": handlerName ?? ""
+ });
+ }
+}
diff --git a/ohos/ohos/.gitignore b/ohos/ohos/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c0f9ca4c47ca2d6aea523c5e0cf3331566bbf88a
--- /dev/null
+++ b/ohos/ohos/.gitignore
@@ -0,0 +1,9 @@
+/node_modules
+/oh_modules
+/.preview
+/.idea
+/build
+/.cxx
+/.test
+/BuildProfile.ets
+/oh-package-lock.json5
diff --git a/ohos/ohos/build-profile.json5 b/ohos/ohos/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..79961f96a6fe0507354b7952a378c3be2ae4bfab
--- /dev/null
+++ b/ohos/ohos/build-profile.json5
@@ -0,0 +1,10 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ },
+ "targets": [
+ {
+ "name": "default"
+ }
+ ]
+}
diff --git a/ohos/ohos/hvigorfile.ts b/ohos/ohos/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..47e6e1f81d365872f101585f5dbf816bcad65864
--- /dev/null
+++ b/ohos/ohos/hvigorfile.ts
@@ -0,0 +1,2 @@
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+export { harTasks } from '@ohos/hvigor-ohos-plugin';
\ No newline at end of file
diff --git a/ohos/ohos/index.ets b/ohos/ohos/index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..2097fefff82a5daa34bcb68803473645b6155e95
--- /dev/null
+++ b/ohos/ohos/index.ets
@@ -0,0 +1,17 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import FlutterJsbridgePluginOhosPlugin from './src/main/ets/components/plugin/FlutterJsbridgePluginOhosPlugin';
+export default FlutterJsbridgePluginOhosPlugin;
diff --git a/ohos/ohos/oh-package.json5 b/ohos/ohos/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..f089a4c2d68452c0c24e6c58b2ba8c8f69fbf048
--- /dev/null
+++ b/ohos/ohos/oh-package.json5
@@ -0,0 +1,11 @@
+{
+ "name": "flutter_jsbridge_plugin_ohos",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "index.ets",
+ "author": "",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ohos/flutter_ohos": "file:./har/flutter.har"
+ }
+}
diff --git a/ohos/ohos/src/main/ets/components/plugin/FlutterJsbridgePluginOhosPlugin.ets b/ohos/ohos/src/main/ets/components/plugin/FlutterJsbridgePluginOhosPlugin.ets
new file mode 100644
index 0000000000000000000000000000000000000000..56941ae87693b8d8a55582ddc0fdeb27ad11600b
--- /dev/null
+++ b/ohos/ohos/src/main/ets/components/plugin/FlutterJsbridgePluginOhosPlugin.ets
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2024 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ FlutterPlugin,
+ FlutterPluginBinding,
+ MethodCall,
+ MethodCallHandler,
+ MethodChannel,
+ MethodResult,
+} from '@ohos/flutter_ohos';
+
+import { deviceInfo } from '@kit.BasicServicesKit';
+
+/** FlutterJsbridgePluginOhosPlugin **/
+export default class FlutterJsbridgePluginOhosPlugin implements FlutterPlugin, MethodCallHandler {
+ private channel: MethodChannel | null = null;
+
+ getUniqueClassName(): string {
+ return "FlutterJsbridgePluginOhosPlugin"
+ }
+
+ onAttachedToEngine(binding: FlutterPluginBinding): void {
+ this.channel = new MethodChannel(binding.getBinaryMessenger(), "flutterjsbridgeplugin");
+ this.channel.setMethodCallHandler(this)
+ }
+
+ onDetachedFromEngine(binding: FlutterPluginBinding): void {
+ if (this.channel != null) {
+ this.channel.setMethodCallHandler(null)
+ }
+ }
+
+ onMethodCall(call: MethodCall, result: MethodResult): void {
+ if (call.method == "getPlatformVersion") {
+ result.success(this.getVersion())
+ } else {
+ result.notImplemented()
+ }
+ }
+
+ //手机系统版本号
+ private getVersion(): string{
+ let osFullNameInfo: string = deviceInfo.osFullName;
+ return osFullNameInfo;
+ }
+}
\ No newline at end of file
diff --git a/ohos/ohos/src/main/module.json5 b/ohos/ohos/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..b570c1ae72da5c8af06922bc57ff72ccea0d1272
--- /dev/null
+++ b/ohos/ohos/src/main/module.json5
@@ -0,0 +1,10 @@
+{
+ "module": {
+ "name": "flutter_jsbridge_plugin_ohos",
+ "type": "har",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ]
+ }
+}
diff --git a/ohos/pubspec.yaml b/ohos/pubspec.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ac2315993e23926bd8086746fdcb3ec1875b17eb
--- /dev/null
+++ b/ohos/pubspec.yaml
@@ -0,0 +1,76 @@
+name: flutter_jsbridge_plugin_ohos
+description: use jsbridge to webview in flutter.
+version: 1.0.0
+homepage: https://gitee.com/openharmony-sig/fluttertpc_flutter_jsbridge_plugin
+
+environment:
+ sdk: '>=2.19.6 <3.0.0'
+ flutter: ">=2.5.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+ plugin_platform_interface: ^2.0.2
+ sprintf: ^7.0.0
+ webview_flutter:
+ git:
+ url: "https://gitee.com/openharmony-sig/flutter_packages.git"
+ path: "packages/webview_flutter-v4.4.4/webview_flutter"
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+ flutter_lints: ^2.0.0
+ build_runner: ^2.1.4
+ pigeon: ^9.2.4
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+ # This section identifies this Flutter project as a plugin project.
+ # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
+ # which should be registered in the plugin registry. This is required for
+ # using method channels.
+ # The Android 'package' specifies package in which the registered class is.
+ # This is required for using method channels on Android.
+ # The 'ffiPlugin' specifies that native code should be built and bundled.
+ # This is required for using `dart:ffi`.
+ # All these are used by the tooling to maintain consistency when
+ # adding or updating assets for this project.
+ plugin:
+ platforms:
+ ohos:
+ package: com.flutter_jsbridge_plugin.flutter_jsbridge_plugin_ohos
+ pluginClass: FlutterJsbridgePluginOhosPlugin
+
+ # To add assets to your plugin package, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+ #
+ # For details regarding assets in packages, see
+ # https://flutter.dev/assets-and-images/#from-packages
+ #
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # To add custom fonts to your plugin package, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts in packages, see
+ # https://flutter.dev/custom-fonts/#from-packages
diff --git a/ohos/test/flutter_jsbridge_plugin_ohos_test.dart b/ohos/test/flutter_jsbridge_plugin_ohos_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..91fb2bc68d9815b277ba6c1c9ff97ea49e6ff59e
--- /dev/null
+++ b/ohos/test/flutter_jsbridge_plugin_ohos_test.dart
@@ -0,0 +1,20 @@
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:flutter_jsbridge_plugin_ohos/flutterjsbridgeplugin.dart';
+
+void main() {
+ const MethodChannel channel = MethodChannel('flutterjsbridgeplugin');
+ TestWidgetsFlutterBinding.ensureInitialized();
+ setUp(() {
+ channel.setMockMethodCallHandler((MethodCall methodCall) async {
+ return '42';
+ });
+ });
+ tearDown(() {
+ channel.setMockMethodCallHandler(null);
+ });
+ test('getPlatformVersion', () async {
+ expect(await Flutterjsbridgeplugin.platformVersion, '42');
+ });
+}
+