diff --git a/add_to_app/multiple_web_flutters/README.md b/add_to_app/multiple_web_flutters/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9abb1a62a3a4f0c61c2155a519f7ef390e7dc4ca --- /dev/null +++ b/add_to_app/multiple_web_flutters/README.md @@ -0,0 +1,87 @@ +# multiple_flutters + +This is a sample that shows how to use the Flutter Engine Groups API to embed +multiple instances of Flutter into an existing Android or iOS project. + +## Getting Started + +For iOS instructions, see: +[multiple_flutters_ios](./multiple_flutters_ios/README.md). + +For Android instructions, see: +[multiple_flutters_android](./multiple_flutters_android/README.md). + +For Ohos instructions, see: +[multiple_flutters_ohos](./multiple_flutters_ohos/README.md). + +## Requirements + +* Flutter -- after Flutter v2 +* Android + * Android Studio +* iOS + * Xcode + * Cocoapods +* Ohos + * DevEco-Studio + +## Flutter Engine Group + +These examples use the Flutter Engine Group APIs on the host platform which +allows engines to share memory and CPU intensive resources. This leads to easier +embedding of Flutter into an existing app since multiple entrypoints can be +maintained via a FlutterFragment on Android or a UIViewController on iOS. +Before FlutterEngineGroup, users had to juggle the usage of a small number of +engines judiciously. + +More info on those API's can be found in the source +code: + +- iOS - + [FlutterEngineGroup.h](https://github.com/flutter/engine/blob/master/shell/platform/darwin/ios/framework/Headers/FlutterEngineGroup.h) +- Android - + [FlutterEngineGroup.java](https://github.com/flutter/engine/blob/master/shell/platform/android/io/flutter/embedding/engine/FlutterEngineGroup.java) +- Ohos - + [FlutterEngineGroup.ets](https://gitee.com/openharmony-sig/flutter_engine/blob/master/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngineGroup.ets) + +## Important Files + +### iOS + +- [DataModel.swift](./multiple_flutters_ios/MultipleFluttersIos/HostViewController.swift) + — Observable data model that is the source of truth for the host platform and Flutter. +- [HostViewController.swift](./multiple_flutters_ios/MultipleFluttersIos/HostViewController.swift) + — A UIViewController that synchronizes to the DataModel. +- [main.dart](./multiple_flutters_module/lib/main.dart) — The Flutter source + code. +- [SingleFlutterViewController.swift](./multiple_flutters_ios/MultipleFluttersIos/SingleFlutterViewController.swift) + — A subclass of FlutterViewController that synchronizes with the DataModel. +- [DoubleFlutterViewController.swift](./multiple_flutters_ios/MultipleFluttersIos/DoubleFlutterViewController.swift) + — A UIViewController that embeds multiple Flutter instances. + +### Android + +## Data Synchronization Description + +This sample code performs data synchronization to share data between the host +platform and multiple instances of Flutter by combining the +[Observer design pattern](https://en.wikipedia.org/wiki/Observer_pattern) and +[Flutter platform channels](https://flutter.dev/docs/development/platform-integration/platform-channels). +Here is how it works: + +- The definitive source of truth for the data lives in the host platform data + model. +- Every host view displaying Flutter content maintains: a Flutter engine, a + bidirectional platform channel, and a subscription to the host data model. +- Flutter instances maintain a copy of the data they are interested in reading, + and this data is seeded by the host when the instance is first displayed. +- Mutations from Flutter code are sent to the host platform via the channel. The + host platform performs the mutations, and then notifies all host view + controllers and Flutter engines of the new value. +- Mutations from host code happen directly on the data model who notifies host + view controllers and Flutter engines of the new value. + +This is just one possible way to synchronize the data between the host platform +and multiple Flutter instances. A more complete implementation is proposed in +the work of +[flutter/issues/72030](https://github.com/flutter/flutter/issues/72030). diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_module/.gitignore b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..28ac2a22de28c2d2e04066735cbbf26fec4f71c1 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/.gitignore @@ -0,0 +1,51 @@ +.DS_Store +.dart_tool/ + +.packages +.pub/ + +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +migrate_working_dir/ + +*.swp +profile + +DerivedData/ + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +build/ +.android/ +.ios/ +.ohos/ +.flutter-plugins +.flutter-plugins-dependencies + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_module/.metadata b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/.metadata new file mode 100644 index 0000000000000000000000000000000000000000..bdc27cb22d105e29a04d78bd5e098a32c79ecd47 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/.metadata @@ -0,0 +1,10 @@ +# 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 and should not be manually edited. + +version: + revision: 1d3f6971600f6e3fb144a30fab2b889e34af0c22 + channel: master + +project_type: module diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_module/README.md b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7a3fcbd3788de865edc0e3053869ca11c756a2a5 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/README.md @@ -0,0 +1,11 @@ +# multiple_web_flutters_module + +A new Flutter module project. + +## Getting Started + +For help getting started with Flutter development, view the online +[documentation](https://flutter.dev/). + +For instructions integrating Flutter modules to your existing applications, +see the [add-to-app documentation](https://flutter.dev/docs/development/add-to-app). diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_module/analysis_options.yaml b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/analysis_options.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a5744c1cfbe77ae2daba29c74156c617b5f09b77 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/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/add_to_app/multiple_web_flutters/multiple_web_flutters_module/lib/main.dart b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/lib/main.dart new file mode 100644 index 0000000000000000000000000000000000000000..9e9b5d60307648fb41d42cd0d9c6910e4a0f6ca4 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/lib/main.dart @@ -0,0 +1,200 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:url_launcher/url_launcher.dart' as launcher; + +import 'package:webview_flutter/webview_flutter.dart'; +import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; +import 'package:webview_flutter_android/webview_flutter_android.dart'; +import 'package:webview_flutter_ohos/webview_flutter_ohos.dart'; + +void main() { + WidgetsFlutterBinding.ensureInitialized(); + runApp( + LayoutBuilder( + builder: (context, constraints) { + if (constraints.maxWidth != 0) { + return const MyApp(color: Colors.blue); + } else { + return Container(); + } + }, + ), + ); +} + +@pragma('vm:entry-point') +void topMain() => runApp(const MyApp(color: Colors.green)); + +@pragma('vm:entry-point') +void bottomMain() => runApp(const MyApp(color: Colors.purple)); + +class MyApp extends StatelessWidget { + const MyApp({super.key, required this.color}); + + final MaterialColor color; + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + colorSchemeSeed: color, + useMaterial3: true, + appBarTheme: AppBarTheme( + backgroundColor: color, + foregroundColor: Colors.white, + elevation: 8, + ), + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + int? _counter = 0; + late MethodChannel _channel; + late WebViewController controller; + @override + void initState() { + super.initState(); + _channel = const MethodChannel('multiple-flutters'); + _channel.setMethodCallHandler((call) async { + if (call.method == "setCount") { + // A notification that the host platform's data model has been updated. + setState(() { + _counter = call.arguments as int?; + }); + } else { + throw Exception('not implemented ${call.method}'); + } + }); + + onWebViewCreated(); + } + + void _incrementCounter() { + // Mutations to the data model are forwarded to the host platform. + _channel.invokeMethod("incrementCount", _counter); + } + + void onWebViewCreated() { + // #docregion platform_features + late final PlatformWebViewControllerCreationParams params; + if (WebViewPlatform.instance is WebKitWebViewPlatform) { + params = WebKitWebViewControllerCreationParams( + allowsInlineMediaPlayback: true, + mediaTypesRequiringUserAction: const {}, + ); + } else { + params = const PlatformWebViewControllerCreationParams(); + } + + controller = WebViewController.fromPlatformCreationParams(params); + // #enddocregion platform_features + + controller.setJavaScriptMode(JavaScriptMode.unrestricted); + controller.setBackgroundColor(Colors.red); + controller.setUserAgent( + "Mozilla/5.0 (Phone; ohos; OpenHarmony 5.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 ArkWeb/4.1.6.1 Mobile"); + // controller.addJavaScriptChannel("ScrollHeightNotifier", + // onMessageReceived: widget + // .nestedWebviewController.scrollHeightNotifierJavascriptChannel); + // controller.addJavaScriptChannel("tdx_flutter_messageHandler", + // onMessageReceived: tdxMessageHandlers); + controller.setNavigationDelegate(NavigationDelegate( + onPageStarted: (url) {}, + onPageFinished: (url) {}, + onWebResourceError: (error) {}, + onProgress: (progress) {}, + onNavigationRequest: (request) { + return NavigationDecision.navigate; + }, + )); + controller.enableZoom(false); + if (controller.platform is OhosWebViewController) { + // if (webDebug) { + OhosWebViewController.enableDebugging(true); + // } + (controller.platform as OhosWebViewController) + .setMediaPlaybackRequiresUserGesture(false); + } + // #enddocregion platform_features + controller.loadRequest(Uri.parse("https://www.baidu.com")); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'You have pushed the button this many times:', + ), + Text( + '$_counter', + style: Theme.of(context).textTheme.headlineMedium, + ), + TextButton( + onPressed: _incrementCounter, + child: const Text('Add'), + ), + TextButton( + onPressed: () { + _channel.invokeMethod("next", _counter); + }, + child: const Text('Next'), + ), + ElevatedButton( + onPressed: () async { + // Use the url_launcher plugin to open the Flutter docs in + // a browser. + final url = Uri.parse('https://flutter.dev/docs'); + if (await launcher.canLaunchUrl(url)) { + await launcher.launchUrl(url); + } + }, + child: const Text('Open Flutter Docs'), + ), + Expanded( + child: WebViewWidget( + // gestureRecognizers: >{ + // Factory( + // () { + // return VerticalDragGestureRecognizer(); + // }, + // ), + // Factory( + // () { + // return HorizontalDragGestureRecognizer(); + // }, + // ) + // }, + controller: controller, + ), + ) + ], + ), + ), + ); + } +} diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_module/pubspec.yaml b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/pubspec.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dfa4be8b91e5339e6bf83fb6303a8268c5f9268c --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_module/pubspec.yaml @@ -0,0 +1,39 @@ +name: multiple_web_flutters_module +description: A new Flutter module project. + +version: 1.0.0+1 + +environment: + sdk: '>=2.19.5 <4.0.0' + +dependencies: + flutter: + sdk: flutter + url_launcher: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + path: packages/url_launcher/url_launcher + webview_flutter: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + path: packages/webview_flutter/webview_flutter + # webview_flutter: + # path: ../webview_flutter1/webview_flutter + + + + cupertino_icons: ^1.0.0 + +dev_dependencies: + # analysis_defaults: + # path: ../../../analysis_defaults + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true + + module: + androidX: true + androidPackage: com.example.multiple_flutters_module + iosBundleIdentifier: com.example.multipleFluttersModule diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/.gitignore b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/AppScope/app.json5 b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3fc4293c065adc6b854bdf26aa42728b789037a7 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.example.multiple_web_flutters_ohos", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/AppScope/resources/base/element/string.json b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..3170a18d22004c254a34c944433b6eb5a0ea23d1 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "multiple_web_flutters_ohos" + } + ] +} diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/AppScope/resources/base/media/app_icon.png b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/AppScope/resources/base/media/app_icon.png differ diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/README.md b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c84b383ecedb66a8bc860e33fbe4fe6e7a02990d --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/README.md @@ -0,0 +1,20 @@ +# multiple_flutters_ohos + +This is an add-to-app sample that uses the Flutter engine group API to host +multiple instances of Flutter in the app. + +## Getting Started + +```sh +cd ../multiple_flutters_module +flutter pub get +flutter build har --local-engine=$ENGINE_DEBUG --debug +cd - +cp -r ../multiple_flutters_module/.ohos/har/* ./har/ +open -a "Deveco-Studio" ../multiple_flutters_ohos/ # macOS command +# Config signing configs: (File->Project Structure->Signing Configs->Support HarmonyOS & Automaticlally generate signature->OK) +# (build and run) +``` + +For more information see +[multiple_flutters_module](../multiple_flutters_module/README.md). diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/build-profile.json5 b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d92e897983be1a817b8c961df2d2644474d95a33 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/build-profile.json5 @@ -0,0 +1,28 @@ +{ + "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/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/.gitignore b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/build-profile.json5 b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..633d360fbc91a3186a23b66ab71b27e5618944cb --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_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/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/hvigorfile.ts b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..1a8e6468d98a9d9455a254df6bb13cadcfaab599 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/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 { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/oh-package.json5 b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9a47509ed2b3ebf197600da26c86ced5bfffecfe --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* +* 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. +*/ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + }, +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/entryability/EntryAbility.ets b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..3ab8fc9dfa81a4beea5476ca61a414d32dcfd028 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,52 @@ +/* +* 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 { ExclusiveAppComponent, FlutterManager } from '@ohos/flutter_ohos'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; + +export default class EntryAbility extends UIAbility implements ExclusiveAppComponent{ + detachFromFlutterEngine(): void { + // throw new Error('Method not implemented.'); + } + + getAppComponent(): UIAbility { + return this; + } + + static app?: EntryAbility; + + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + FlutterManager.getInstance().pushUIAbility(this); + EntryAbility.app = this; + } + + onDestroy(): void | Promise { + FlutterManager.getInstance().popUIAbility(this); + EntryAbility.app = undefined; + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + windowStage.getMainWindowSync().setWindowLayoutFullScreen(true); + FlutterManager.getInstance().pushWindowStage(this, windowStage); + windowStage.loadContent('pages/SingleFlutterPage'); + } + + onWindowStageDestroy() { + FlutterManager.getInstance().popWindowStage(this); + } +} diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/DataModel.ets b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/DataModel.ets new file mode 100644 index 0000000000000000000000000000000000000000..db303e6b7484bef08f1beb0d88e240e4c0bb339e --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/DataModel.ets @@ -0,0 +1,54 @@ +/* +* 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 { ArrayList } from '@kit.ArkTS'; +import { Log } from '@ohos/flutter_ohos'; + +export interface DataModelObserver { + onCountUpdate(newCount: number): void; +} + +export class DataModel { + public static instance = new DataModel(); + private counter = 0; + private observers: ArrayList = new ArrayList(); + + private constructor() { + } + + public increase() { + this.setCounter(++this.counter); + } + + public setCounter(newCounter: number): void { + Log.i("Multi->setCounter", "newCounter=" + newCounter); + this.observers.forEach(observer => { + observer?.onCountUpdate(this.counter); + }); + this.counter = newCounter; + } + + public getCounter(): number { + return this.counter; + } + + addObserver(observer: DataModelObserver): void { + this.observers.add(observer); + } + + removeObserver(observer: DataModelObserver): boolean { + return this.observers.remove(observer); + } +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/DataSource.ets b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/DataSource.ets new file mode 100644 index 0000000000000000000000000000000000000000..a02192f0d51ffb83244deaecc6335707b285dbd0 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/DataSource.ets @@ -0,0 +1,106 @@ +/* +* 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 { Log } from '@ohos/flutter_ohos'; + +export class BasicDataSource implements IDataSource { + private listeners: DataChangeListener[] = []; + private originDataArray: T[] = []; + + public totalCount(): number { + return this.originDataArray.length; + } + + public getData(index: number): T { + return this.originDataArray[index]; + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + console.info('add listener'); + this.listeners.push(listener); + } + } + + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + console.info('remove listener'); + this.listeners.splice(pos, 1); + } + } + + notifyDataReload(): void { + this.listeners.forEach(listener => { + listener.onDataReloaded(); + }) + } + + notifyDataAdd(index: number): void { + this.listeners.forEach(listener => { + listener.onDataAdd(index); + }) + } + + notifyDataChange(index: number): void { + this.listeners.forEach(listener => { + listener.onDataChange(index); + }) + } + + notifyDataDelete(index: number): void { + this.listeners.forEach(listener => { + listener.onDataDelete(index); + }) + } + + notifyDataMove(from: number, to: number): void { + this.listeners.forEach(listener => { + listener.onDataMove(from, to); + }) + } +} + +export class MyDataSource extends BasicDataSource { + private dataArray: T[] = []; + + public totalCount(): number { + return this.dataArray.length; + } + + public getData(index: number): T { + return this.dataArray[index]; + } + + public add(index: number, data: T): void { + this.dataArray.splice(index, 0, data); + this.notifyDataAdd(index); + } + + public push(data: T): void { + this.dataArray.push(data); + this.notifyDataAdd(this.dataArray.length - 1); + } + + public delete(index: number): void { + this.dataArray.splice(index, 1); + this.notifyDataDelete(index); + } + + public clear(): void { + this.dataArray.splice(0, this.totalCount()); + this.notifyDataReload(); + } +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/DoubleFlutterPage.ets b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/DoubleFlutterPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..e9b55234f3bc1e74dd38177d0a1b8edc18a64bf0 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/DoubleFlutterPage.ets @@ -0,0 +1,62 @@ +/* +* 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 { FlutterPage, Log } from '@ohos/flutter_ohos'; +import router from '@ohos.router'; +import { EngineBindings } from './EngineBindings'; +import { common } from '@kit.AbilityKit'; + +@Entry() +@Component +struct DoubleFlutterPage { + @State topViewId: string = ""; + @State bottomViewId: string = ""; + private context = getContext(this) as common.UIAbilityContext; + private topBindings: EngineBindings = new EngineBindings(this.context, this); + private bottomBindings: EngineBindings = new EngineBindings(this.context, this); + + onNext() { + router.pushUrl({ "url": "pages/MainPage" }); + } + + aboutToAppear() { + this.topViewId = this.topBindings.getFlutterViewId(); + this.bottomViewId = this.bottomBindings.getFlutterViewId(); + Log.i("Multi->aboutToAppear", "DoubleFlutterPage, topId=" + this.topViewId + ", bottomId=" + this.bottomViewId); + this.topBindings.attach(); + this.bottomBindings.attach(); + } + + aboutToDisappear(): void { + this.topBindings.detach(); + this.bottomBindings.detach(); + } + + build() { + Column() { + FlutterPage({ viewId: this.topViewId, xComponentType: XComponentType.TEXTURE }) + .height('50%') + .backgroundColor(Color.Transparent) + FlutterPage({ + viewId: this.bottomViewId, + xComponentType: XComponentType.TEXTURE, + checkFullScreen: false, + checkKeyboard: false + }) + .height('50%') + .backgroundColor(Color.Transparent) + } + } +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/EngineBindings.ets b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/EngineBindings.ets new file mode 100644 index 0000000000000000000000000000000000000000..03f45af587f4ac695ba5091c76a50d1b530a83f7 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/EngineBindings.ets @@ -0,0 +1,119 @@ +/* +* 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, FlutterManager, FlutterView, Log, MethodCall, MethodChannel } from '@ohos/flutter_ohos'; +import { DataModel, DataModelObserver } from './DataModel'; +import { common } from '@kit.AbilityKit'; +import FlutterEngineGroup, { Options } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroup'; +import { MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import { DartEntrypoint } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartExecutor'; +// import { GeneratedPluginRegistrant } from 'flutter_module'; +import EntryAbility from '../entryability/EntryAbility'; +import TextInputPlugin from '@ohos/flutter_ohos/src/main/ets/plugin/editing/TextInputPlugin'; +import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant'; + +const engines: FlutterEngineGroup = new FlutterEngineGroup(); +const engineList: Map = new Map(); + +export interface EngineBindingsDelegate { + onNext(): void; +} + +export class EngineBindings implements DataModelObserver { + private engine?: FlutterEngine; + private channel?: MethodChannel; + private context: common.Context; + private delegate: EngineBindingsDelegate; + private flutterView: FlutterView; + protected textInputPlugin?: TextInputPlugin; + private firstLoading: boolean = true + + constructor(context: common.Context, delegate: EngineBindingsDelegate) { + this.context = context; + this.delegate = delegate; + this.flutterView = FlutterManager.getInstance().createFlutterView(context); + } + + getFlutterViewId() { + return this.flutterView.getId(); + } + + async attach() { + if (this.engine) { + Log.i("Multi->attach", "engine is "); + return; + } + DataModel.instance.addObserver(this); + await engines.checkLoader(this.context, []); + let options: Options = new Options(this.context).setDartEntrypoint(DartEntrypoint.createDefault()); + this.engine = await engines.createAndRunEngineByOptions(options) ?? undefined; + if (!this.engine) { + throw new Error("Create engine failed."); + } + this.engine.getLifecycleChannel()?.appIsResumed(); + this.textInputPlugin = new TextInputPlugin(this.engine.getTextInputChannel()!); + if (EntryAbility.app) { + this.engine.getAbilityControlSurface()?.attachToAbility(EntryAbility.app); + } + this.flutterView.attachToFlutterEngine(this.engine); + GeneratedPluginRegistrant.registerWith(this.engine); + + engineList.set(this.flutterView.getId(), this.engine) + + this.channel = new MethodChannel(this.engine.dartExecutor.getBinaryMessenger(), "multiple-flutters"); + this.channel?.invokeMethod("setCount", DataModel.instance.getCounter()); + let delegate = this.delegate; + this.channel?.setMethodCallHandler({ + onMethodCall(call: MethodCall, result: MethodResult) { + Log.i("Multi->onMethodCall", "method=" + call.method); + switch (call.method) { + case "incrementCount": + DataModel.instance.increase(); + result.success(null); + break; + case "next": + delegate.onNext(); + result.success(null); + break; + default: + result.notImplemented(); + break; + } + } + }) + } + + detach() { + this.flutterView.detachFromFlutterEngine(); + this.engine?.destroy(); + DataModel.instance.removeObserver(this); + this.channel?.setMethodCallHandler(null); + } + + pageShow() { + if (!this.firstLoading) { + this.flutterView.attachToFlutterEngine(engineList.get(this.flutterView.getId())) + } + } + + pageHide() { + this.firstLoading = false + this.flutterView.detachFromFlutterEngine() + } + + onCountUpdate(newCount: number): void { + this.channel?.invokeMethod("setCount", newCount); + } +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/LazyListFlutterPage.ets b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/LazyListFlutterPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..8dbcc8bf41ab97edc499312de8a743a5397b80f9 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/LazyListFlutterPage.ets @@ -0,0 +1,161 @@ +/* +* 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 { FlutterManager, FlutterPage, Log } from '@ohos/flutter_ohos'; +import router from '@ohos.router'; +import { EngineBindings } from './EngineBindings'; +import { common } from '@kit.AbilityKit'; +import { JSON } from '@kit.ArkTS'; +import { MyDataSource } from './DataSource'; + +const TAG = "LazyListFlutterPage"; +const MY_DATA_SOURCE: MyDataSource = new MyDataSource(); + +@Entry() +@Component +struct LazyListFlutterPage { + @State itemHeight: number = 400; + @State message: string = ""; + private isFullScreen: boolean = true; + + onNext() { + router.pushUrl({ "url": "pages/MainPage" }); + } + + aboutToAppear() { + MY_DATA_SOURCE.clear(); + this.loadMore(); + } + + build() { + Column() { + List() { + ListItem() { + Row() { + Column() { + Button("切换高度").onClick(() => this.changeHeight()).margin(10) + Button("加载更多").onClick(() => this.loadMore()).margin(10) + Button("切换全屏").onClick(() => this.toggleFullScreen()).margin(10) + }.width('100%') + }.backgroundColor(Color.Orange).height(this.itemHeight) + } + + LazyForEach(MY_DATA_SOURCE, (item: MyItemData, index: number) => { + ListItem() { + MyFlutterItem({ + index: index, + itemHeight: this.itemHeight + (index % 3) * 100, + }) + } + // String(index) 作为key会导致复用场景异常 + // (item: MyItemData, index: number) => String(index) + }, (item: MyItemData, index: number) => index.toString()) + + ListItem() { + Row() { + Column() { + Button("切换高度").onClick(() => this.changeHeight()).margin(10) + Button("加载更多").onClick(() => this.loadMore()).margin(10) + }.width('100%') + }.backgroundColor(Color.Red).height(this.itemHeight) + } + } + .width("100%") + .height("100%") + } + } + + toggleFullScreen(): void { + let window = FlutterManager.getInstance() + .getWindowStage(FlutterManager.getInstance().getUIAbility(getContext(this))); + this.isFullScreen = !this.isFullScreen; + window.getMainWindowSync().setWindowLayoutFullScreen(this.isFullScreen); + } + + private async loadMore() { + for (let i = 0; i < 10; i++) { + MY_DATA_SOURCE.push(new MyItemData((i % 3) * 100)); + } + } + + private changeHeight(): void { + this.itemHeight = this.itemHeight < 600 ? this.itemHeight + 20 : 400; + console.log("onAreaChange, itemHeight=" + this.itemHeight); + } +} + +@Component +@Reusable +struct MyFlutterItem { + @Prop itemHeight: number; + @Prop index: number; + + private viewId: string = ""; + private binding: EngineBindings = new EngineBindings(getContext(this), this); + + aboutToAppear() { + this.init(); + Log.i(TAG, JSON.stringify({ + "name+xx ": "aboutToAppear", + "index": this.index, + "UniqueId": this.getUniqueId(), + "viewId": this.viewId, + "flutterView.getId()": this.binding.getFlutterViewId(), + })) + } + + aboutToDisappear(): void { + Log.i(TAG, JSON.stringify({ + "name+xx ": "aboutToDisappear", + "index": this.index, + "UniqueId": this.getUniqueId(), + "viewId": this.viewId, + "flutterView.getId()": this.binding.getFlutterViewId(), + })) + this.binding.detach(); + } + + onNext() { + router.pushUrl({url: "pages/MainPage"}); + } + + async init() { + this.viewId = this.binding.getFlutterViewId(); + await this.binding.attach(); + } + + build() { + Row() { + Flex({direction: FlexDirection.Column}) { + Row().height(4).width("100%").backgroundColor(Color.Black) + Text(JSON.stringify({"index": this.index, "viewId": this.viewId, "itemHeight": this.itemHeight})) + FlutterPage({ + viewId: this.viewId, + checkFullScreen: false, + checkKeyboard: false + }).height(this.itemHeight) + Row().height(20).width("100%").backgroundColor(Color.Green) + }.backgroundColor(Color.Yellow).margin(10) + }.justifyContent(FlexAlign.Center) + } +} + +class MyItemData { + height: number; + + constructor(height: number) { + this.height = height; + } +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/MainPage.ets b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/MainPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..11a7ffa3c44ab2d5f55e5398d4422a1b9d16fef9 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/MainPage.ets @@ -0,0 +1,88 @@ +/* +* 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 { DataModel } from './DataModel'; +import router from '@ohos.router'; + +@Entry() +@Component +struct MainPage { + @State mainIdentifier: number = 0; + + onCountUpdate(newCount: number) { + this.mainIdentifier = newCount; + } + + aboutToAppear(): void { + this.mainIdentifier = DataModel.instance.getCounter(); + DataModel.instance.addObserver(this); + } + + aboutToDisappear(): void { + DataModel.instance.removeObserver(this); + } + + onClickNext() { + let num = this.mainIdentifier % 3; + if (num == 1) { + router.pushUrl({ + "url": "pages/DoubleFlutterPage", + }); + } else if (num == 2) { + router.pushUrl({ + "url": "pages/LazyListFlutterPage", + }); + } else { + router.pushUrl({ + "url": "pages/SingleFlutterPage", + }); + } + } + + onClickAdd() { + DataModel.instance.increase(); + } + + build() { + Row() { + Column() { + Row() { + Text("Count:") + Text(String(this.mainIdentifier)) + } + }.width('50%') + .height('100%') + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + + Column() { + Button("Add").onClick(() => { + this.onClickAdd(); + }).margin(2) + Button("Next").onClick(() => { + this.onClickNext(); + }).margin(2) + } + .width('50%') + .height('100%') + .padding(20) + .alignItems(HorizontalAlign.End) + .justifyContent(FlexAlign.End) + }.width('100%') + .height('100%') + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.SpaceBetween) + } +} diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/SingleFlutterPage.ets b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/SingleFlutterPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..0657fb12790877449fcb48042fb9b3cda1a371d4 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/pages/SingleFlutterPage.ets @@ -0,0 +1,78 @@ +/* +* 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 { FlutterPage, Log } from '@ohos/flutter_ohos'; +import router from '@ohos.router'; +import { EngineBindings } from './EngineBindings'; +import { common } from '@kit.AbilityKit'; +import { FlutterPage, Log } from '@ohos/flutter_ohos'; + +const TAG = "SingleFlutterPage"; + +@Entry() +@Component +struct SingleFlutterPage { + @State viewId: string = ""; + private context = getContext(this) as common.UIAbilityContext + private engineBindings: EngineBindings = new EngineBindings(this.context, this); + @State private viewHeight: number = 300; + + onNext() { + router.pushUrl({ "url": "pages/SingleFlutterPage" }); + } + + aboutToAppear() { + Log.i("Multi->aboutToAppear", "SingleFlutterPage"); + this.viewId = this.engineBindings.getFlutterViewId(); + Log.i("Multi->aboutToAppear", "SingleFlutterPage, id=" + this.viewId); + this.engineBindings.attach(); + } + + aboutToDisappear(): void { + this.engineBindings.detach(); + } + + onPageShow(): void { + this.engineBindings.pageShow() + } + + onPageHide(): void { + this.engineBindings.pageHide() + } + + build() { + Column() { + // Row() { + // Button("切换高度").onClick(() => { + // this.viewHeight = this.viewHeight < 600 ? (this.viewHeight + 20) : 300 + // Log.i(TAG, JSON.stringify({ + // "name": "切换高度", + // "viewHeight": this.viewHeight + // })) + // }) + // Button("attach").onClick(() => { + // this.engineBindings.attach(); + // }) + // Button("detach").onClick(() => { + // this.engineBindings.detach(); + // }) + // }.height(200).alignItems(VerticalAlign.Center) + Row().height(44) + Row() { + FlutterPage({ viewId: this.viewId, checkFullScreen: false, checkKeyboard: false}) + } + } + } +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets new file mode 100644 index 0000000000000000000000000000000000000000..8c2779f86b3e9140312d78377d21cfcb65ae635f --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2024 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 UrlLauncherPlugin from '@ohos/url_launcher_ohos'; +import WebViewFlutterPlugin from '@ohos/webview_flutter_ohos'; + +// import UrlLauncherPlugin from 'url_launcher_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 UrlLauncherPlugin()); + 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/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/module.json5 b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..82b949f920ee2c90aab8e38bf926523ad6de7182 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/module.json5 @@ -0,0 +1,55 @@ +/* +* 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/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/element/color.json b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_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/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/element/string.json b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_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": "label" + } + ] +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/background.png b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/background.png differ diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/foreground.png b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/foreground.png differ diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/icon.png b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/icon.png differ diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/layered_image.json b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/startIcon.png b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/media/startIcon.png differ diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/profile/backup_config.json b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/profile/main_pages.json b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..ae4aa89902b794f98f55cd35d98193bf7255d9ff --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,8 @@ +{ + "src": [ + "pages/MainPage", + "pages/SingleFlutterPage", + "pages/DoubleFlutterPage", + "pages/LazyListFlutterPage" + ] +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/en_US/element/string.json b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_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": "label" + } + ] +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/zh_CN/element/string.json b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..597ecf95e61d7e30367c22fe2f8638008361b044 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_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": "label" + } + ] +} \ No newline at end of file diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/hvigor/hvigor-config.json5 b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..06b2783670a348f95533b352c1ceda909a842bbc --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/hvigor/hvigor-config.json5 @@ -0,0 +1,22 @@ +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/hvigorfile.ts b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775 --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/hvigorfile.ts @@ -0,0 +1,6 @@ +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. */ +} diff --git a/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/oh-package.json5 b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..7f3e64c530ce6166a2636e7e16247abb0524954e --- /dev/null +++ b/add_to_app/multiple_web_flutters/multiple_web_flutters_ohos/oh-package.json5 @@ -0,0 +1,23 @@ +{ + "modelVersion": "5.0.0", + "name": "multiple_web_flutters_ohos", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "@ohos/flutter_ohos": "file:./har/flutter.har", + "@ohos/url_launcher_ohos": "file:./har/url_launcher_ohos.har", + "@ohos/webview_flutter_ohos": "file:./har/webview_flutter_ohos.har", + "flutter_module": "./har/flutter_module.har", + }, + "devDependencies": { + "@ohos/hypium": "1.0.6" + }, + "overrides": { + "@ohos/flutter_ohos": "file:./har/flutter.har", + "url_launcher_ohos": "./har/url_launcher_ohos.har" + }, + "dynamicDependencies": {} +}