diff --git a/ohos/docs/01_framework/README_EN.md b/ohos/docs/01_framework/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..d07fbd396d37376a539c803a1ad85ffc678f3d6a --- /dev/null +++ b/ohos/docs/01_framework/README_EN.md @@ -0,0 +1,5 @@ +# Framework + +Flutter is a high-performance and cross-device UI framework developed by Google. It allows code reuse across multiple platforms such as iOS, Android, Windows, macOS, and Linux, delivering high-performance applications that feel natural on these platforms. It also supports hybrid development with the native code. Flutter, which is completely free and open source, is being used by more and more developers and organizations around the world. + +For details about Flutter, see [Flutter website](https://docs.flutter.dev). diff --git a/ohos/docs/02_architecture/README_EN.md b/ohos/docs/02_architecture/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..e5b3b860acbdf758f050e14eb8fa812360534f96 --- /dev/null +++ b/ohos/docs/02_architecture/README_EN.md @@ -0,0 +1,3 @@ +# Architecture + +For details about the Flutter architecture, see [Flutter website](https://docs.flutter.dev/resources/architectural-overview). diff --git a/ohos/docs/03_environment/README_EN.md b/ohos/docs/03_environment/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..e1e2876804b97165fd50e1867943d87db737eca4 --- /dev/null +++ b/ohos/docs/03_environment/README_EN.md @@ -0,0 +1,5 @@ +# Environment Setup + +## HarmonyOS Flutter Integration and Compilation Tutorial +1. [HarmonyOS Flutter Environment Setup](./harmonyos-flutter-environment-setup.md) + diff --git a/ohos/docs/03_environment/harmonyos-flutter-environment-setup.md b/ohos/docs/03_environment/harmonyos-flutter-environment-setup.md new file mode 100644 index 0000000000000000000000000000000000000000..5d9b8e97357c926b617c6bc4a2d444f01c084ae8 --- /dev/null +++ b/ohos/docs/03_environment/harmonyos-flutter-environment-setup.md @@ -0,0 +1,229 @@ +# HarmonyOS Flutter Environment Setup + +## Environment Preparation + +### 1. Downloading and Installing the Latest DevEco Studio Development Suite and Its Dependencies + +#### 1.1 Official Download URL +Official download address of the Harmony development suite: https://developer.huawei.com/consumer/cn/download/ + + ``` + Note: +(1) The development suite is supported in Linux, macOS, and Windows systems. +(2) For macOS, enter "uname -m" on the terminal to determine the system architecture and select the corresponding development suite. + If the output is x86_64, the system uses the X86-64 architecture. + If the output is arm64, the system uses the ARM64 architecture. + ``` + +#### 1.2 Download List + +##### (1) Download the latest version of DevEco Studio based on your computer system. + +![](../media/03_1/img_17_EN.png) + + +##### (2) Download an emulator in DevEco Studio if no real HarmonyOS device is available. +For details about how to download and install the emulator, see section 2.2 "Install an emulator." + +##### (3) Download HarmonyOS Flutter. + +Project URL: https://gitee.com/openharmony-sig/flutter_flutter + +Use a code editor to download the repository to your local PC and specify the dev or master branch. The dev branch is continuously updated and has more features than the master branch. + + ``` + 1 git clone https://gitee.com/openharmony-sig/flutter_flutter.git + 2 git checkout -b dev origin/dev + ``` +##### (4) (Optional) Download the Flutter Engine build products. +* Building a Flutter project requires the use of **ohos_debug_unopt_arm64** and **ohos_release_arm64**. +* Add the `--local-engine=src/out/` to the running parameters of the Flutter Tools instruction to specify the engine to be downloaded. Otherwise, the latest engine on the cloud is used by default. Example: flutter build hap [--local-engine=/Users/admin/Documents/flutter_engine/src/out/ohos_debug_unopt_arm64]. +* [Download the build products](https://docs.qq.com/sheet/DUnljRVBYUWZKZEtF?tab=BB08J2). +* The engine path must contain the **src/out** directory. After you decompress the downloaded package of the build products, save it to the local path with the **src/out** directory, for example, **/Users/lihui/Documents/flutter_engine/src/out**. + +![](../media/03_1/img_4_EN.png) + +#### 1.3 Preinstalled Environment Dependencies +* The HarmonyOS SDK requires the Java environment. You can download JDK 17 from the [Oracle website](https://www.oracle.com/java/technologies/downloads/#java17) or OpenJDK website and set up the environment. +* Execute the following instruction to check the JDK installation result: + + ```sh + java -version + ``` + +### 2. How to Install + +#### 2.1 Decompress the component suite package and install the DevEco Studio. + +![](../media/03_1/img_01.png) + +#### 2.2 Install an emulator. +![](../media/03_1/img_18.png) +![](../media/03_1/img_18_1_EN.png) +![](../media/03_1/img_18_2_EN.png) +![](../media/03_1/img_18_3_EN.png) +![](../media/03_1/img_18_4_EN.png) +![](../media/03_1/img_18_5.png) + +#### 2.3 Configure environment variables. +* Use the terminal tool to determine the storage path of the actual environment variables in the current system. Execute the following instruction: + + ```sh + echo $SHELL + ``` + +* If the output is `/bin/bash`, execute the following instruction to open the **.bash_profile** file: + + ```sh + vi ~/.bash_profile + ``` + +* If the output is `/bin/zsh`, execute the following instruction to open the **.zshrc** file: + + ```sh + vi ~/.zshrc + ``` + +* After you get the environment variable storage file, configure the environment variables. For example, open the **bash_profile** file and execute the `vi ~/.bash_profile` instruction. + + ```sh + + # Mirror inside china + export PUB_HOSTED_URL=https://pub.flutter-io.cn + export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn + + # flutter_flutter/bin directory pulled from Flutter pub + export PATH=/Users/admin/ohos/flutter_flutter/bin:$PATH + + # HamonyOS SDK + export TOOL_HOME=/Applications/DevEco-Studio.app/Contents # macOS environment + export DEVECO_SDK_HOME=$TOOL_HOME/sdk # command-line-tools/sdk + export PATH=$TOOL_HOME/tools/ohpm/bin:$PATH # command-line-tools/ohpm/bin + export PATH=$TOOL_HOME/tools/hvigor/bin:$PATH # command-line-tools/hvigor/bin + export PATH=$TOOL_HOME/tools/node/bin:$PATH # command-line-tools/tool/node/bin + export HDC_HOME=$TOOL_HOME/sdk/HarmonyOS-NEXT-DB1/openharmony/toolchains # (Optional) hdc instruction + + # Optional configuration items (required when using the Android Studio or Visual Studio Code to debug. The JDK version is 17.0.12) + JAVA_HOME=/Users/admin/Documents/JDK/jdk-17.0.12.jdk/Contents/Home + PATH=$JAVA_HOME/bin:$PATH:. + export JAVA_HOME + export PATH + + # Optional configuration item (to prevent the creation of subsequent Flutter projects from being affected by the mismatched environment variable of the Gitee download URL for HarmonyOS Flutter) + export FLUTTER_GIT_URL=https://gitee.com/openharmony-sig/flutter_flutter.git + + # Optional configuration item (required only when there is no node environment in the tool file under the command-line-tools directory) + # export NODE_HOME=/Users/lihui/node/node-18.14.1 + # export PATH=$PATH:$NODE_HOME/bin + ``` + +* After all required environment variables are configured, execute the following instruction to update the environment configuration for making it take effect: + + ```sh + source ~/.bash_profile + ``` + +#### 2.4 Run the emulator. + +![](../media/03_1/m1_EN.png) + +Create an emulator. + +![](../media/03_1/img.png) + +Start the emulator. + +![](../media/03_1/m2_EN.png) + +Emulator running effect + +![](../media/03_1/m3_EN.png) + + +## HarmonyOS Flutter Integration and Debugging + +### 1. Checking the Environment +Run `flutter doctor -v` to check whether the environment variable configuration is correct. The check results for both Flutter and OpenHarmony should be **ok**. If there are any prompts indicating missing environment variable configuration, follow the prompts to configure the environment. + +![](../media/03_1/doctor1_EN.png) + + +### 2. Creating a Flutter Project +Create a project and build it. You can find the build products in **${projectName}/ohos/entry/build/default/outputs/default/entry-default-signed.hap**. + +```sh +# Method 1 for project creation: Only the ohos platform is created. +flutter create --platforms ohos + +# Method 2 for project creation: Android, iOS, and ohos platforms are created. +flutter create + +# Go to the root directory of the project and compile the HAP. +flutter build hap --debug +``` + +### 3. Running the Flutter Project on a Real HarmonyOS Device +#### 3.1 Sign the project. +Before running the project on a real device, you need to sign the project. Steps are as follows. +![](../media/03_1/sign01.png) +![](../media/03_1/sign02.png) + +#### 3.2 Run the project on a real device. +* Execute the `flutter devices` instruction to discover a real device and obtain the device ID. + + Method 1: Go to the project directory, compile the HAP in the specified build mode, and install it on the HarmonyOS device. + + ```sh + flutter run --debug -d + ``` + + Method 2: Go to the project root directory, compile the HAP, and install it on the HarmonyOS device. + + ```sh + flutter build hap --debug + hdc -t install + ``` + + Method 3: Use DevEco Studio to set your phone as the real device and start running. + ![](../media/03_1/img12.png) + +### 4. Running the Flutter Project on an Emulator + +#### 4.1 Use DevEco Studio to open the ohos module of the project. + +![](../media/03_1/open_ohos.png) + +#### 4.2 Start the HarmonyOS emulator in DevEco Studio. + +![](../media/03_1/m1_EN.png) + +![](../media/03_1/m2_EN.png) + +![](../media/03_1/m3_EN.png) + +Switch to the HarmonyOS emulator. + +![](../media/03_1/img00_EN.png) + +#### 4.3 Compile and run. + +![](../media/03_1/img9_EN.png) + +![](../media/03_1/img_10_EN.png) + +### 5. FAQs on Emulator Running + +#### 5.1 Unable to Create an Emulator +Case 1: Use an account that has passed real-name authentication to sign in. + + +### 6. FAQs on pub upgrade Instruction + +#### 6.1 Executing the pub upgrade Takes a Long Time +Case 1: A large number of files need to be loaded for the first time. The time required varies greatly depending on the network conditions. Please wait. + +Case 2: Delete the **flutter_flutter/bin/cache** file and try again. + +Case 3: Replace the source of the mirror. Example: + PUB_HOSTED_URL=https://mirrors.tuna.tsinghua.edu.cn/dart-pub + FLUTTER_STORAGE_BASE_URL=https://mirrors.tuna.tsinghua.edu.cn/flutter \ No newline at end of file diff --git a/ohos/docs/04_development/README_EN.md b/ohos/docs/04_development/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..da1263e4b40319e8cc3a1c4299d4e8352a695dab --- /dev/null +++ b/ohos/docs/04_development/README_EN.md @@ -0,0 +1,25 @@ +# Feature Development + +## Adding a Flutter Page to Your HarmonyOS Application + +1. [Using FlutterPage](./using-flutterpage.md) +2. [Using FlutterEntry](./using-flutterentry.md) + +## Using a Flutter Platform Channel in Your HarmonyOS Application + +1. [Using a Flutter Platform Channel](./using-a-flutter-platform-channel.md) + +## Hybrid Rendering with Native Code + +1. [External Texture Adaptation for Flutter](./external-texture-adaptation-for-flutter.md) +2. [Using FlutterEngineGroup](./using-flutterenginegroup.md) +3. [Using a Platform View](./using-a-platform-view.md) +4. [Platform View Same-Layer Rendering Adaptation and Switching](./platform-view-same-layer-rendering-adaptation-and-switching.md) + +## Developing a Flutter Static Library + +1. [Developing a Module](./developing-a-module.md) +2. [Developing a Package](./developing-a-package.md) +3. [Developing a Plugin](./developing-a-plugin.md) +4. [Developing an FFI Plugin](./developing-an-ffi-plugin.md) + diff --git a/ohos/docs/04_development/developing-a-module.md b/ohos/docs/04_development/developing-a-module.md new file mode 100644 index 0000000000000000000000000000000000000000..5156e45bcc26b595f754bbf2df56931d951d520f --- /dev/null +++ b/ohos/docs/04_development/developing-a-module.md @@ -0,0 +1,124 @@ +# Developing a Module + +This topic describes how to reference a flutter_module project in an ohos project. + +- ohos project: a native HarmonyOS project that can be created by DevEco Studio. +- flutter_module project: a Flutter submodule project that can be created by executing Flutter instructions. + +## Environment Setup + +- Use [flutter_flutter](https://gitee.com/openharmony-sig/flutter_flutter) to configure environment variables. +- Use the engine products generated by [flutter_engine](https://gitee.com/openharmony-sig/flutter_engine). + +Use DevEco Studio to create a native HarmonyOS project named **MyApplication**. + +## flutter_module Project Operations + +```sh +# 1. Create a Flutter submodule project. +flutter create -t module my_flutter_module +# 2. Compile and generate flutter_module.har. +cd my_flutter_module +flutter build har --debug +cd - +# 3. Copy EntryAbility.ets and Index.ets to MyApplication. +cp my_flutter_module/.ohos/entry/src/main/ets/entryability/EntryAbility.ets MyApplication/entry/src/main/ets/entryability/EntryAbility.ets +cp my_flutter_module/.ohos/entry/src/main/ets/pages/Index.ets MyApplication/entry/src/main/ets/pages/Index.ets +``` + +## ohos Project Operations + +An ohos project can reference a Flutter project in either of the following ways: + +### Method 1: Referencing the HAP File + +#### 1. Copy the HAP file. + +```sh +cp -r my_flutter_module/.ohos/har/* MyApplication/har/ +``` + +#### 2. Modify the **MyApplication/oh-package.json5** file. + +```json +{ + // ... + "dependencies": { + "flutter_module": "har/flutter_module.har" + }, + "overrides": { + // Conflicts in dependencies need to be eliminated here. + "@ohos/flutter_ohos": "har/flutter.har", + "plugin_xxx": "har/plugin_xxx.har" + } +} +``` + +#### 3. Use DevEco Studio to configure the signature of **MyApplication**. + +#### 4. Run **MyApplication**. + +### Method 2: Directly Referencing the flutter_module Source Code + +#### 1. Copy the flutter_module source code and Flutter-related files. + +```sh +cp -r my_flutter_module/.ohos/flutter_module MyApplication/ +mkdir -p MyApplication/flutter_module/src/main/resources/rawfile +cp -r my_flutter_module/.ohos/flutter_module/src/main/resources/rawfile/flutter_assets MyApplication/flutter_module/src/main/resources/rawfile +cp my_flutter_module/.ohos/har/flutter.har MyApplication/har/flutter.har +``` + +#### 2. Modify the **MyApplication/build-profile.json5** file. + +```json +{ + // ... + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + }, + // The following is the content newly added: + { + "name": "flutter_module", + "srcPath": "./flutter_module", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} +``` + +#### 3. Modify the **MyApplication/oh-package.json5** file. + +```json +{ + // ... + "dependencies": { + "flutter_module": "./flutter_module", + "@ohos/flutter_ohos": "./har/flutter.har" + }, + "overrides": { + "@ohos/flutter_ohos": "./har/flutter.har" + } +} +``` + +#### 4. Use DevEco Studio to configure the signature of **MyApplication**. + +#### 5. Run **MyApplication**. diff --git a/ohos/docs/04_development/developing-a-package.md b/ohos/docs/04_development/developing-a-package.md new file mode 100644 index 0000000000000000000000000000000000000000..b0168afa70b4791bebb37a31197706aa7217b67f --- /dev/null +++ b/ohos/docs/04_development/developing-a-package.md @@ -0,0 +1,13 @@ +# Developing a Package + +For details, see [Developing Dart Packages](https://flutter.dev/docs/packages-and-plugins/developing-packages#dart). + +## 1. Creating a Package + +```sh +flutter create --template=package hello +``` + +## 2. Implementing the Package + +For a dart package, you can implement it by just adding features to the **lib/\.dart** file or to multiple files in the **lib** directory. diff --git a/ohos/docs/04_development/developing-a-plugin.md b/ohos/docs/04_development/developing-a-plugin.md new file mode 100644 index 0000000000000000000000000000000000000000..df81a578de7bb91d12c0d66c905a891744ab4c94 --- /dev/null +++ b/ohos/docs/04_development/developing-a-plugin.md @@ -0,0 +1,96 @@ +# Developing a Plugin + +This topic describes how to develop Flutter packages for the ohos platform. + +## Developing a Package of the Native Plugin Type + +### 1. Creating a Package + +```sh +flutter create --org com.example --template=plugin --platforms=android,ios,ohos hello +``` + +This will create a plugin project in the **hello** directory with the following files: + +`lib/hello.dart` file + +Implementation of the dart plugin APIs. + +`android/src/main/java/com/example/hello/HelloPlugin.kt` file + +Implementation of the native plugin APIs of the Android platform (using the Kotlin programming language). + +`ios/Classes/HelloPlugin.m` file + +Implementation of the native plugin APIs of the iOS platform (using the Objective-C programming language). + +`ohos/hello/src/main/ets/components/plugin/HelloPlugin.ets` file + +Implementation of the native plugin APIs of the ohos platform (using the ArkTS programming language). + +`example/` file + +A Flutter application that requires a plugin and describes how to use it. + +#### 1.1 Specify the supported ohos platforms. + +You can specify the supported platforms by adding keys to the platforms map in **pubspec.yaml**. For example, the following is **flutter: map** of the **hello** plugin, indicating that the plugin can be used in Android, iOS, and ohos platforms: + +```yaml +flutter: + plugin: + platforms: + android: + package: com.example.hello + pluginClass: HelloPlugin + ios: + pluginClass: HelloPlugin + ohos: + pluginClass: HelloPlugin + +environment: + sdk: ">=2.19.6 <3.0.0" + flutter: ">=2.5.0" +``` + +### 2. Implementing a Package + +#### 2.1 Define a package API. + +Open the **hello** home directory and find the **lib/hello.dart** file. + +#### 2.2 Compile the example. + +```sh +cd hello/example +flutter pub get +flutter build hap --debug +``` + +#### 2.3 Add the ohos platform code (.ets). + +You are advised to use DevEco Studio to compile the ohos code. + +1. Start DevEco Studio and open the **hello/example/ohos** directory. +2. Configure signature information. Click **File**->**Project Structure**->**Signing Configs**->**Support HarmonyOS & Automatically generate signature**->**Sign-in**. +3. Log in with your Huawei developer account, return to DevEco Studio, and save the signature. +4. Run the project. + +## Adding the Support for the ohos Platform for an Existing Plugin Project + +```sh +flutter create . --template=plugin --platforms=ohos +``` + +## Developing an FFI Plugin + +```sh +flutter create hello --template=plugin_ffi --platforms=ohos +``` + +## References + +1. [Developing Packages & Plugins](https://docs.flutter.dev/packages-and-plugins/developing-packages) +2. [Developing Plugin Packages](https://docs.flutter.dev/packages-and-plugins/developing-packages#plugin) +3. [OpenHarmony Documentation](https://docs.openharmony.cn/pages/v4.1/en/application-dev/application-dev-guide.md/) +4. [HarmonyOS Documentation](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V2/start-overview-0000001478061421-V2) diff --git a/ohos/docs/04_development/developing-an-ffi-plugin.md b/ohos/docs/04_development/developing-an-ffi-plugin.md new file mode 100644 index 0000000000000000000000000000000000000000..2960a6f16d532790f79db47292bf501f8f66a748 --- /dev/null +++ b/ohos/docs/04_development/developing-an-ffi-plugin.md @@ -0,0 +1,40 @@ +# Developing an FFI Plugin + +For details, see [Developing FFI Plugin Packages](https://docs.flutter.dev/packages-and-plugins/developing-packages#plugin-ffi). + +## 1. Creating a Package + +```sh +flutter create --template=plugin_ffi hello --platforms=android,ios,ohos +``` + +## 2. Building Local Native Code + +Specify the platform to use the FFI plugin in the **pubspec.yaml** file as follows: + +```yaml + plugin: + platforms: + android: + ffiPlugin: true + ohos: + ffiPlugin: true + ios: + ffiPlugin: true +``` + +## 3. Binding Local Native Code + +Bind the local native code in dart to use the code. + +To avoid manual compiling, the code is generated by **package:ffigen** in the header file **src/hello.h**. Execute the following instruction to rebind: + +```sh +dart run ffigen --config ffigen.yaml +``` + +## 4. Calling Local Native Code + +Local native functions that run for a short time can be directly called in any **isolate**. An example function is **sum** in **lib/hello.dart**. + +Local native functions that run for a long time should be called in [helper isolate](https://dart.dev/guides/language/concurrency#background-workers) to avoid frame losses in Flutter applications. An example function is **sumAsync** in **lib/hello.dart**. diff --git a/ohos/docs/04_development/external-texture-adaptation-for-flutter.md b/ohos/docs/04_development/external-texture-adaptation-for-flutter.md new file mode 100644 index 0000000000000000000000000000000000000000..6d593729ec9a70524e7b49777e33e923ad9e68a2 --- /dev/null +++ b/ohos/docs/04_development/external-texture-adaptation-for-flutter.md @@ -0,0 +1,92 @@ +# External Texture Adaptation for Flutter + +Flutter uses external textures on the ohos platform. In the case of camera preview and video playback, the Flutter engine returns a surface ID when a texture is registered. In the case of image display, a texture is registered with the Flutter engine in the form of a PixelMap. + +Generally, to facilitate code reuse, the function code for connecting the ohos platform to the Flutter external texture is encapsulated as a module, and the module is registered as a plugin with the Flutter engine. For details, see https://gitee.com/openharmony-sig/flutter_packages/tree/master/packages/video_player/video_player_ohos/ohos. + +## Camera Preview + +### Demo URL + +https://gitee.com/openharmony-sig/flutter_samples/tree/master/ohos/testcamera + +### How to Implement + +1. Obtain **TextureRegistry** from the **FlutterPluginBinding** input parameter in **onAttachedToEngine** to implement the plugin. + + ![](../media/04_1/dc15b84a4b97ec7f923ffefe121bd346.png) + +2. Implement the response method for texture registration in **onMethodCall**. + + ![](../media/04_1/3f7a2a6befa3459f00a90b6e796839e4.png) + + In **registerCameraTexture** used to register a texture, obtain the texture ID, and then register the texture based on the texture ID with the flutter engine to obtain a surface ID. + + ![](../media/04_1/7ea99353820d6640826bf0bd24dd5f8b.png) + +3. Use the obtained surface ID when starting camera preview. + + ![](../media/04_1/614df503f2164dd4e4a4b4a5e5bc9c87_EN.png) + +4. Call **MethodChannel** at the dart layer to trigger texture registration and start camera preview. + + ![](../media/04_1/62bbfe62e6fecbb269ab9f607fb2cfbf.png) + + Use the obtained texture ID to build a texture widget for image preview. + + ![](../media/04_1/37b3118e6921ff70b1baf4234fcdaa69.png) + +## Video Playback + +### Demo URL + +https://gitee.com/openharmony-sig/flutter_packages/tree/master/packages/video_player/video_player_ohos/example + +### How to Implement + +Video playback uses the same way as camera preview in registering a texture. Steps are as follows: + +1. Implement the native ohos player AVplayer in the **video_player_ohos** plugin. For details, see **https://docs.openharmony.cn/pages/v4.1/en/application-dev/reference/apis-media-kit/_a_v_player.md**. +2. Obtain **TextureRegistry** from the **FlutterPluginBinding** input parameter in **onAttachedToEngine** to implement the plugin (encapsulated in **FlutterState**). + + ![](../media/04_1/50312d42df3346723abf740064ea019b.png) + +3. In the method for creating a video player, you should obtain the texture ID first (from **TextureRegistry** in **FlutterState**), then register the texture with the engine, and obtain the surface ID from the returned **SurfaceTextureEntry** object. + + ![](../media/04_1/e68f5cbb2f98dca205bf51d6ab53ad09_EN.png) + +4. Obtain the surface ID from the video player constructor. + + ![](../media/04_1/d7e3f8d50d8970578c1bfc9bdcb1941c.png) + +5. When the AVplayer is in the **AvplayerStatus.INITIALIZED** state, the surface ID is assigned to the AVplayer. + + ![](../media/04_1/7f03e4b85c4434de763faf2b3d073a6d.png) + +When the AVplayer is created in step 3, the texture ID needs to be returned to the dart layer. Then the dart layer can use the external texture to complete rendering in the texture widget. + +## Image Display + +### Demo URL + +https://gitee.com/openharmony-sig/flutter_samples/tree/master/ohos/testpicture + +### How to Implement + +In the case of image display, no surface is used for connection to the external texture. The texture is registered with the Flutter engine in the form of a PixelMap. + +1. Obtain **TextureRegistry** from the **FlutterPluginBinding** input parameter in **onAttachedToEngine** to implement the plugin. + + ![](../media/04_1/975272fd1c19bb2371545f5d011284bd.png) + +2. Implement the response method for texture registration in **onMethodCall**. + + ![](../media/04_1/ff662b72b643008d3ba214eb3632452e.png) + +3. In the texture registration method, pass in image data to create an **ImageSource** object and then a **PixelMap** object. Then call **registerPixelMap** to register the texture with the Flutter engine, obtain a texture ID, and return it to the dart layer. + + ![](../media/04_1/44c0e7494d3916a7b760fc4ed4cd9668.png) + +4. Use the external texture in the texture widget for rendering. + + ![](../media/04_1/8eff1f85dd7c64952444faf2de19ff89.png) diff --git a/ohos/docs/04_development/platform-view-same-layer-rendering-adaptation-and-switching.md b/ohos/docs/04_development/platform-view-same-layer-rendering-adaptation-and-switching.md new file mode 100644 index 0000000000000000000000000000000000000000..a0d0cc3f4addc9f74edb29362ac0513dfc79c2df --- /dev/null +++ b/ohos/docs/04_development/platform-view-same-layer-rendering-adaptation-and-switching.md @@ -0,0 +1,162 @@ +## Platform View Same-Layer Rendering Adaptation and Switching + + +## Old Solution + +### Overview +Define DynamicView and DVModel at the Flutter adaptation layer. +```java +@Observed +export class DVModel { + id_: number; + compType: string; + params: DVModelParameters; + events: DVModelEvents; + children: DVModelChildren; + builder: Any; + + public getLayoutParams(): DVModelParameters { + return this.params; + } +} +``` +```java +@Component +export struct DynamicView{ + @ObjectLink model:DVModel; + @ObjectLink children:DVModelChildren; + @ObjectLink params:DVModelParameters; + @ObjectLink events:DVModelEvents; + @BuilderParam customBuilder?:($$:BuilderParams)=>void; +} +``` +Use JSON strings to define and generate a DVModel and implement the PlatformView. Place the FlutterView at the bottom layer and the PlatformView implemented by the DynamicView at the top layer. The DynamicView, implemented using ArkUI, is a native rendering product of HarmonyOS. +```java + build() { + Stack() { + XComponent({ id: this.viewId, type: this.xComponentType, libraryname: 'flutter' }) + .focusable(true) + .focusOnTouch(true) + .onLoad((context) => { + this.flutterView?.onSurfaceCreated() + Log.d(TAG, "XComponent onLoad "); + }) + .onDestroy(() => { + Log.d(TAG, "XComponent onDestroy "); + this.flutterView?.onSurfaceDestroyed() + }) + .backgroundColor(Color.Transparent) + + ForEach(this.rootDvModel!!, (child: Any) => { + DynamicView({ + model: child as DVModel, + params: child.params, + events: child.events, + children: child.children, + customBuilder: child.builder + }) + }) + } +``` +There are two major defects when a Flutter page is embedded into the PlatformView: + 1. The PlatformView blocks the FlutterView. + 2. The FlutterView and PlatformView animations are inconsistent during page switching. + + + +## New Solution + +### Overview +The NodeContainer is introduced for same-layer rendering, so that textures of native components can be registered with the Flutter engine and rendered by Flutter. The solution can solve the inherent defects of the old solution. In addition, the PlatformView uses the custom ArkUI component, which complies with the native HarmonyOS application development habits. You are no longer restricted by the DVModel and can get prompts when compiling JSON strings. +```java + build() { + Stack() { + NodeContainer(this.nodeController) + .width(this.storageLinkWidth) + .height(this.storageLinkHeight) + + XComponent({ id: this.viewId, type: this.xComponentType, libraryname: 'flutter' }) + .focusable(true) + .focusOnTouch(true) + .onLoad((context) => { + this.flutterView?.onSurfaceCreated() + Log.d(TAG, "XComponent onLoad "); + }) + .onDestroy(() => { + Log.d(TAG, "XComponent onDestroy "); + this.flutterView?.onSurfaceDestroyed() + }) + .backgroundColor(Color.Transparent) + } + } +``` + + +## Key Solution Differences +Old solution +```java +private model: DVModel = createDVModelFromJson( + { + compType: "Column", + attributes: { height: '200%'}, + children: [ + { + compType: "Text", + attributes: { value: "Native: send data to Dart111111111111111", fontColor: Color.Orange,backgroundColor: Color.Black,height: 100}, + events: { onClick: this.sendMessage }, + }, + { + compType: "Text", + attributes: { value: "Native: data from dart", marginTop: 20 }, + } + ], + } +); +``` +```java +/// Customize the APIs of the PlatformView entity class. +getView(): DVModel { + return this.model; +} +``` +New solution +```java +@Component +struct ButtonComponent { + @Prop params: Params + customView: CustomView = this.params.platformView as CustomView + @StorageLink('numValue') storageLink: string = "first" + @State bkColor: Color = Color.Red + + build() { + Column() { + Button("Send data to Flutter") + .border({ width: 2, color: Color.Blue}) + .backgroundColor(this.bkColor) + .onTouch((event: TouchEvent) => { + console.log("nodeController button on touched") + }) + .onClick((event: ClickEvent) => { + this.customView.sendMessage(); + console.log("nodeController button on click") + }) + + Text(`Data from Flutter: ${this.storageLink}`) + .onTouch((event: TouchEvent) => { + console.log("nodeController text on touched") + }) + + }.alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .direction(Direction.Ltr) + .width('100%') + .height('100%') + } +} +``` +```java +/// Customize the APIs of the PlatformView entity class. +getView(): WrappedBuilder<[Params]> { + return new WrappedBuilder(ButtonBuilder); +} +``` diff --git a/ohos/docs/04_development/using-a-flutter-platform-channel.md b/ohos/docs/04_development/using-a-flutter-platform-channel.md new file mode 100644 index 0000000000000000000000000000000000000000..6afae4152f97733d0b98b8c368aa0a78686dbd57 --- /dev/null +++ b/ohos/docs/04_development/using-a-flutter-platform-channel.md @@ -0,0 +1,114 @@ +# Using a Flutter Platform Channel + +This topic describes how to use a Flutter platform channel in the HarmonyOS Flutter project. + +The following are the key implementation codes. For details about the complete demo, see [channel_demo](https://gitee.com/openharmony-sig/flutter_samples/tree/master/ohos/channel_demo). + +## MethodChannel + +Dart code + +```dart +// Create an instance. +final _platform = const MethodChannel('samples.flutter.dev/battery'); +// Call the getBatteryLevel method. +final result = await _platform.invokeMethod('getBatteryLevel'); +``` + +ets code + +```ts +onAttachedToEngine(binding: FlutterPluginBinding): void { + let that = this; + // Create an instance. + this.channel = new MethodChannel(binding.getBinaryMessenger(), "samples.flutter.dev/battery"); + // Set the callback and call the implementation. + this.channel.setMethodCallHandler({ + onMethodCall(call: MethodCall, result: MethodResult) { + switch (call.method) { + case "getBatteryLevel": + that.api.getBatteryLevel(result); + break; + default: + result.notImplemented(); + break; + } + } + }) +} +``` + +## BasicMessageChannel + +Dart code + +```dart +int count = 0; +// Create an instance. +final _basicChannel = const BasicMessageChannel( + "samples.flutter.dev/basic_channel", StandardMessageCodec()); +// Call a method to obtain the return value from the platform. +String result = await _basicChannel.send(++count) as String; +``` + +ets code + +```ts +onAttachedToEngine(binding: FlutterPluginBinding): void { + // Create an instance. + this.basicChannel = new BasicMessageChannel(binding.getBinaryMessenger(), "samples.flutter.dev/basic_channel", new StandardMessageCodec()); + // Set the callback and call the implementation. + this.basicChannel.setMessageHandler({ + onMessage(message: Any, reply: Reply) { + Log.i(TAG, "message=" + message); + if (message % 2 == 0) { + reply.reply("run with if case."); + } else { + reply.reply("run with else case"); + } + } + }) +} +``` + +## EventChannel + +Dart code + +```dart +// Create an instance. +final _eventChannel = const EventChannel('samples.flutter.dev/event_channel'); +// Enable listening for events. +_eventChannel.receiveBroadcastStream().listen((event) { + setState(() { + message = "EventChannel event=$event"; + }); +}); +``` + +ets code + +```ts +private eventSink?: EventSink; + +onAttachedToEngine(binding: FlutterPluginBinding): void { + let that = this; + // Create an instance. + this.eventChannel = new EventChannel(binding.getBinaryMessenger(), "samples.flutter.dev/event_channel"); + // Set the callback to obtain EventSink. + this.eventChannel.setStreamHandler({ + onListen(args: Any, events: EventSink): void { + that.eventSink = events; + Log.i(TAG, "onListen: " + args); + }, + onCancel(args: Any): void { + that.eventSink = undefined; + Log.i(TAG, "onCancel: " + args); + } + }); +} + +// ... +// After EventSink sends the data, the event listener at the dart layer can receive the sent data. +that.eventSink?.success("Success at " + new Date()); +``` diff --git a/ohos/docs/04_development/using-a-platform-view.md b/ohos/docs/04_development/using-a-platform-view.md new file mode 100644 index 0000000000000000000000000000000000000000..03fea8bdea0251ffec8a796f6b09ae196f84f02f --- /dev/null +++ b/ohos/docs/04_development/using-a-platform-view.md @@ -0,0 +1,408 @@ +## Preparations + +### 1. Configuring the Flutter Development Environment + +For details, see https://gitee.com/openharmony-sig/flutter_flutter/blob/master/README_EN.md. + +### 2. Creating a Project + +1. Execute `flutter create --platforms ohos platform_demo` to create a project. + +2. Execute `cd` to switch to `platform_demo `. Execute `flutter pub get` to download the dependency. + +## Code Implementation + +### 1. At the Native Layer + +1. Use DevEco Studio to open the `platform_demo\ohos` project. + +2. Implement the code in the `platform_demo\ohos\entry\src\main\ets\entryability` directory. + +3. Create a `CustomView.ets` file, which is displayed in the Flutter widget. + + 3.1 Define a `Component` to represent the platform view of ohos. + +```ts +@Component +struct ButtonComponent { + @Prop params: Params + customView: CustomView = this.params.platformView as CustomView + @StorageLink('numValue') storageLink: string = "first" + @State bkColor: Color = Color.Red + + build() { + Column() { + Button("Send data to Flutter") + .border({ width: 2, color: Color.Blue}) + .backgroundColor(this.bkColor) + .onTouch((event: TouchEvent) => { + console.log("nodeController button on touched") + }) + .onClick((event: ClickEvent) => { + this.customView.sendMessage(); + console.log("nodeController button on click") + }) + + Text(`Data from Flutter: ${this.storageLink}`) + .onTouch((event: TouchEvent) => { + console.log("nodeController text on touched") + }) + + }.alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .direction(Direction.Ltr) + .width('100%') + .height('100%') + } +} +``` + +​ 3.2 Define a **builder** method and implement it in the previously mentioned custom **Component**. +```ts +@Builder +function ButtonBuilder(params: Params) { + ButtonComponent({ params: params }) + .backgroundColor(Color.Yellow) +} +``` + +​ 3.3 Inherit **PlatformView** to implement a custom view. Implement the **getView** API to return `WrappedBuilder(ButtonBuilder)` and place it in the previously mentioned **builder** method. +```ts +import MethodChannel, { + MethodCallHandler, + MethodResult + } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import PlatformView, { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'; +import common from '@ohos.app.ability.common'; +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import StandardMethodCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec'; +import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall'; + +@Observed +export class CustomView extends PlatformView implements MethodCallHandler { + numValue: string = "test"; + + methodChannel: MethodChannel; + index: number = 1; + + constructor(context: common.Context, viewId: number, args: ESObject, message: BinaryMessenger) { + super(); + console.log("nodeController viewId:" + viewId) + // Register a message channel based on the requirements. This code is only an example. + this.methodChannel = new MethodChannel(message, `com.rex.custom.ohos/customView${viewId}`, StandardMethodCodec.INSTANCE); + this.methodChannel.setMethodCallHandler(this); + } + + onMethodCall(call: MethodCall, result: MethodResult): void { + // Receive messages from the dart layer. + let method: string = call.method; + let link1: SubscribedAbstractProperty = AppStorage.link('numValue'); + switch (method) { + case 'getMessageFromFlutterView': + let value: ESObject = call.args; + this.numValue = value; + link1.set(value) + console.log("nodeController receive message from dart: " + this.numValue); + result.success(true); + break; + } + } + + public sendMessage = () => { + console.log("nodeController sendMessage") + // Send messages to the dart layer. + this.methodChannel.invokeMethod('getMessageFromOhosView', 'natvie - ' + this.index++); + } + + getView(): WrappedBuilder<[Params]> { + return new WrappedBuilder(ButtonBuilder); + } + + dispose(): void { + } +} +``` + +​ 3.4 Implement a custom `PlatformViewFactory` and use its `create` method to create a custom `PlatformView` instance. + +```ts +import common from '@ohos.app.ability.common'; +import MessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec'; +import PlatformViewFactory from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory'; +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import PlatformView from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'; +import { CustomView } from './CustomView'; + +export class CustomFactory extends PlatformViewFactory { + message: BinaryMessenger; + + constructor(message: BinaryMessenger, createArgsCodes: MessageCodec) { + super(createArgsCodes); + this.message = message; + } + + public create(context: common.Context, viewId: number, args: Object): PlatformView { + return new CustomView(context, viewId, args, this.message); + } +} +``` + +​ 3.5 Create a Custom plugin inherited from the Flutter plugin. Register the custom `PlatformViewFactory` in `onAttachedToEngine`. + +```ts +import { FlutterPlugin, + FlutterPluginBinding } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; +import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec'; +import { CustomFactory } from './CustomFactory'; + +export class CustomPlugin implements FlutterPlugin { + getUniqueClassName(): string { + return 'CustomPlugin'; + } + + onAttachedToEngine(binding: FlutterPluginBinding): void { + binding.getPlatformViewRegistry()?. + registerViewFactory('com.rex.custom.ohos/customView', new CustomFactory(binding.getBinaryMessenger(), StandardMessageCodec.INSTANCE)); + } + + onDetachedFromEngine(binding: FlutterPluginBinding): void {} +} +``` + +​ 3.6 Open the EntryAbility.ets file and add the plugin. (Alternatively, implement the custom platform view in a HarmonyOS plugin and use it in the application. If this is the case, you do not need to add the plugin explicitly.) + +```ts +import { FlutterAbility } from '@ohos/flutter_ohos' +import FlutterEngine from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine'; +import { CustomPlugin } from './CustomPlugin'; +import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant'; + +export default class EntryAbility extends FlutterAbility { + configureFlutterEngine(flutterEngine: FlutterEngine) { + super.configureFlutterEngine(flutterEngine) + GeneratedPluginRegistrant.registerWith(flutterEngine) + this.addPlugin(new CustomPlugin()); + } +} +``` + +### 2. At the Dart Layer + +1. Use the Android Studio to open the `platform_demo` project. + +2. Implement the code in the `platform_demo\lib` directory. + +3. Create a `CustomOhosView` to show the custom view widget on the native side. +The **OhosView** component is the key to bridging the platform view. + +- **viewType**: The value is passed to the native side to notify the plugin for creating the platform view. The platform view should be registered during plugin initialization. +- **onPlatformViewCreated**: a callback when the platform view is successfully created. +- **creationParams**: initialization parameters passed to the platform view. + +Use the `OhosView` component to implement a custom ohos view. `viewType` should be the same as the one specified when the Flutter plugin executes `registerViewFactory` on the ets side. +```dart +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +typedef OnViewCreated = Function(CustomViewController); + +/// Customize the OhosView +class CustomOhosView extends StatefulWidget { + final OnViewCreated onViewCreated; + + const CustomOhosView(this.onViewCreated, {Key? key}) : super(key: key); + + @override + State createState() => _CustomOhosViewState(); +} + +class _CustomOhosViewState extends State { + late MethodChannel _channel; + + @override + Widget build(BuildContext context) { + return _getPlatformFaceView(); + } + + Widget _getPlatformFaceView() { + return OhosView( + viewType: 'com.rex.custom.ohos/customView', + onPlatformViewCreated: _onPlatformViewCreated, + creationParams: const {'initParams': 'hello world'}, + creationParamsCodec: const StandardMessageCodec(), + ); + } + + void _onPlatformViewCreated(int id) { + _channel = MethodChannel('com.rex.custom.ohos/customView$id'); + final controller = CustomViewController._( + _channel, + ); + widget.onViewCreated(controller); + } +} +``` + +4. Create a `CustomViewController` in the file where the `CustomOhosView` is located to implement the interaction between the dart layer and native layer. + +```dart +class CustomViewController { + final MethodChannel _channel; + final StreamController _controller = StreamController(); + + CustomViewController._( + this._channel, + ) { + _channel.setMethodCallHandler( + (call) async { + switch (call.method) { + case 'getMessageFromOhosView': + // Obtain data from the native layer. + final result = call.arguments as String; + _controller.sink.add(result); + break; + } + }, + ); + } + + Stream get customDataStream => _controller.stream; + + // Send data to the native layer. + Future sendMessageToOhosView(String message) async { + await _channel.invokeMethod( + 'getMessageFromFlutterView', + message, + ); + } +} +``` + +5. Modify the code in the `platform_demo\lib\main.dart` file. + +```dart +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'custom_ohos_view.dart'; + +void main() { + runApp(const MaterialApp(home: MyHome())); +} + +class MyHome extends StatelessWidget { + const MyHome({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return const Scaffold( + body: CustomExample(), + ); + } +} + +class CustomExample extends StatefulWidget { + const CustomExample({Key? key}) : super(key: key); + + @override + State createState() => _CustomExampleState(); +} + +class _CustomExampleState extends State { + String receivedData = ''; + CustomViewController? _controller; + + void _onCustomOhosViewCreated(CustomViewController controller) { + _controller = controller; + _controller?.customDataStream.listen((data) { + // Receive data from the ohos device. + setState(() { + receivedData = 'Data from ohos: $data'; + }); + }); + } + + Widget _buildOhosView() { + return Expanded( + child: Container( + color: Colors.blueAccent.withAlpha(60), + child: CustomOhosView(_onCustomOhosViewCreated), + ), + flex: 1, + ); + } + + Widget _buildFlutterView() { + return Expanded( + child: Stack( + alignment: AlignmentDirectional.bottomCenter, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + TextButton( + onPressed: () { + final randomNum = Random().nextInt(10); + _controller + ?.sendMessageToOhosView('flutter - $randomNum '); + }, + child: const Text('Send data to ohos'), + ), + const SizedBox(height: 10), + Text(receivedData), + ], + ), + const Padding( + padding: EdgeInsets.only(bottom: 15), + child: Text( + 'Flutter - View', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + flex: 1, + ); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + _buildOhosView(), + _buildFlutterView(), + ], + ); + } +} +``` + +## Building and Running + +### 1. Signature + +1. Use DevEco Studio to open the `platform_demo\ohos` directory. + +2. Choose `File > Project Structure > Project > Signing Configs`, select `Automatically generate signature`, wait until the automatic signing is complete, and click **OK**. + +### 2. Build and Run + +1. Execute `cd` to switch to the `platform_demo ` directory. + +2. Open the terminal and execute the following instruction to build and run the project: + +```cmd +flutter run -d +``` + +## Demo + +For details, see [platform_demo](https://gitee.com/openharmony-sig/flutter_samples/tree/master/ohos/platform_demo). + + \ No newline at end of file diff --git a/ohos/docs/04_development/using-flutterenginegroup.md b/ohos/docs/04_development/using-flutterenginegroup.md new file mode 100644 index 0000000000000000000000000000000000000000..a1752cf13c37fefe29038e6b1b9a5d59c20300cd --- /dev/null +++ b/ohos/docs/04_development/using-flutterenginegroup.md @@ -0,0 +1,130 @@ +# Using FlutterEngineGroup + +## 1. Changing EntryAbility to Inherit from UIAbility + +```ts +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 { + FlutterManager.getInstance().pushWindowStage(this, windowStage); + windowStage.loadContent('pages/MainPage'); + } + + onWindowStageDestroy() { + FlutterManager.getInstance().popWindowStage(this); + } +} +``` + +## 2. Encapsulating the Attach and Detach Operations of the Flutter Engine + +```ts +export class EngineBindings implements DataModelObserver { + private engine?: FlutterEngine; + private channel?: MethodChannel; + private context: common.Context; + private delegate: EngineBindingsDelegate; + private flutterView: FlutterView; + + 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); + // Execute the following operations in order. + // 1. + await engines.checkLoader(this.context, []); + let options: Options = new Options(this.context).setDartEntrypoint(DartEntrypoint.createDefault()); + // 2. + this.engine = await engines.createAndRunEngineByOptions(options) ?? undefined; + if (!this.engine) { + throw new Error("Create engine failed."); + } + // 3. + this.engine.getLifecycleChannel()?.appIsResumed(); + if (EntryAbility.app) { + // 4. + this.engine.getAbilityControlSurface()?.attachToAbility(EntryAbility.app); + } + // 5. + this.flutterView.attachToFlutterEngine(this.engine); + GeneratedPluginRegistrant.registerWith(this.engine); + + // ... + } + + detach() { + this.flutterView.detachFromFlutterEngine(); + this.engine?.destroy(); + DataModel.instance.removeObserver(this); + this.channel?.setMethodCallHandler(null); + } + + // ... +} +``` + +## 3. Calling the Attach and Detach Operations of the Flutter Engine + +```ts +@Entry() +@Component +struct SingleFlutterPage { + @State viewId: string = ""; + private context = getContext(this) as common.UIAbilityContext + private engineBindings: EngineBindings = new EngineBindings(this.context, this); + + onNext() { + router.pushUrl({ "url": "pages/MainPage" }); + } + + 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(); + } + + build() { + Column() { + FlutterPage({ viewId: this.viewId, xComponentType: XComponentType.TEXTURE }).backgroundColor(Color.Transparent) + } + } +} +``` + +For details about the complete demo, see [multiple_flutters_ohos](https://gitee.com/openharmony-sig/flutter_samples/tree/master/add_to_app/multiple_flutters/multiple_flutters_ohos). diff --git a/ohos/docs/04_development/using-flutterentry.md b/ohos/docs/04_development/using-flutterentry.md new file mode 100644 index 0000000000000000000000000000000000000000..bd991eb7404dc9853cfae0fbe4df1fc648c03d7d --- /dev/null +++ b/ohos/docs/04_development/using-flutterentry.md @@ -0,0 +1,95 @@ +# Using FlutterEntry + +## 1. Making the EntryAbility to Inherit from the UIAbility + +```ts +export default class EntryAbility extends UIAbility implements ExclusiveAppComponent { + + detachFromFlutterEngine(): void { + // throw new Error('Method not implemented.'); + } + + getAppComponent(): UIAbility { + return this; + } + + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + FlutterManager.getInstance().pushUIAbility(this); + } + + onDestroy(): void | Promise { + FlutterManager.getInstance().popUIAbility(this); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + windowStage.getMainWindowSync().setWindowLayoutFullScreen(true); + FlutterManager.getInstance().pushWindowStage(this, windowStage); + windowStage.loadContent('pages/Index'); + } + + onWindowStageDestroy() { + FlutterManager.getInstance().popWindowStage(this); + } +} +``` + +## 2. Making the MyFlutterEntry to Inherit from the FlutterEntry and Registering the Plugin + +```ts +export default class MyFlutterEntry extends FlutterEntry { + configureFlutterEngine(flutterEngine: FlutterEngine): void { + super.configureFlutterEngine(flutterEngine); + GeneratedPluginRegistrant.registerWith(flutterEngine); + this.delegate?.addPlugin(new BatteryPlugin()); + } +} +``` + +## 3. Using the FlutterEntry Together with the FlutterView + +```ts +@Entry +@Component +struct Index { + private flutterEntry: FlutterEntry | null = null; + private flutterView?: FlutterView + + aboutToAppear() { + Log.d("Flutter", "Index aboutToAppear==="); + this.flutterEntry = new MyFlutterEntry(getContext(this)) + this.flutterEntry.aboutToAppear() + this.flutterView = this.flutterEntry.getFlutterView() + } + + aboutToDisappear() { + Log.d("Flutter", "Index aboutToDisappear==="); + this.flutterEntry?.aboutToDisappear() + } + + onPageShow() { + Log.d("Flutter", "Index onPageShow==="); + this.flutterEntry?.onPageShow() + } + + onPageHide() { + Log.d("Flutter", "Index onPageHide==="); + this.flutterEntry?.onPageHide() + } + + build() { + Stack() { + FlutterPage({ viewId: this.flutterView?.getId() }) + Button ('Go to page 2') + .onClick(() => { + try { + router.pushUrl({ url: 'pages/Index2', params: { route: '/second' } }) + } catch (err) { + Log.d("Flutter", "Go to page 2 error ===" + JSON.stringify(err)). + } + }) + } + } +} +``` + +For details about the complete demo, see [flutter_page_sample2](https://gitee.com/openharmony-sig/flutter_samples/tree/master/ohos/flutter_page_sample2). diff --git a/ohos/docs/04_development/using-flutterpage.md b/ohos/docs/04_development/using-flutterpage.md new file mode 100644 index 0000000000000000000000000000000000000000..d36b4d3b2a70d99b82a51239ab4c44fcb797fb02 --- /dev/null +++ b/ohos/docs/04_development/using-flutterpage.md @@ -0,0 +1,40 @@ +# Using FlutterPage + +## 1. Adding a Page to Your HarmonyOS Application + +1. Use DevEco Studio to open the ohos project. +2. Right-click **ohos/entry/src/main/ets/pages** directory and choose **New** > **Page** > **Empty Page** from the shortcut menu. +3. Edit **Page Name** and click **Finish**. + +## 2. Making the EntryAbility to Inherit from the FlutterAbility + +```ts +export default class EntryAbility extends FlutterAbility { + configureFlutterEngine(flutterEngine: FlutterEngine) { + super.configureFlutterEngine(flutterEngine) + GeneratedPluginRegistrant.registerWith(flutterEngine) + } +} +``` + +## 3. Using FlutterPage in the HarmonyOS Application + +```ts +let storage = LocalStorage.getShared() + +@Entry(storage) +@Component +struct Page1 { + private context = getContext(this) as common.UIAbilityContext + @LocalStorageLink('viewId') viewId: string = ""; + + build() { + Stack({ alignContent: Alignment.Top }) { + FlutterPage({ viewId: this.viewId }) + Text('Components overlaid above FlutterPage').margin(30) + } + } +} +``` + +For details about the complete demo, see [flutter_page_sample1](https://gitee.com/openharmony-sig/flutter_samples/tree/master/ohos/flutter_page_sample1). diff --git a/ohos/docs/05_performance/README.md b/ohos/docs/05_performance/README.md index 64431c28a4dc107ec5b76a52d28b9860c78686b7..382b266e93f8f6bb8683ef9850e697739dd9afa7 100644 --- a/ohos/docs/05_performance/README.md +++ b/ohos/docs/05_performance/README.md @@ -2,13 +2,13 @@ flutter鸿蒙化的工程,也可以使用devtools对Dart代码进行调试,具体内容请参考 [DevTools](https://docs.flutter.cn/tools/devtools) -[性能分析定界(OpenHarmony平台)指南](./performance-delimitation.md) +[性能分析定界(OpenHarmony平台)指南](./性能分析定界指南.md) -[性能分析第一步-梳理线程顺序](./performance-threads-sequence.md) +[性能分析第一步-梳理线程顺序](./性能分析第一步-梳理线程顺序.md) -[性能分析-帧渲染跟踪](./performance-frame-rendering-tracking.md) +[性能分析-帧渲染跟踪](./性能分析-帧渲染跟踪.md) -[性能分析-滑动响应时延](./performance-sliding-response-time.md) +[性能分析-滑动响应时延](./性能分析-滑动响应时延.md) ## 环境配置 diff --git a/ohos/docs/05_performance/README_EN.md b/ohos/docs/05_performance/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..821a440c5992ba4d54691e0eb2627199f440ca23 --- /dev/null +++ b/ohos/docs/05_performance/README_EN.md @@ -0,0 +1,21 @@ +# Performance Tuning + +For a HarmonyOS Flutter project, you can use DevTools to debug the Dart code. For details, see [Flutter and Dart DevTools](https://docs.flutter.dev/tools/devtools). + +[Performance Analysis Demarcation Guide](./performance-delimitation.md) + +[The First Step in Performance Analysis – Sorting Out Thread Order](./performance-threads-sequence.md) + +[Performance Analysis - Frame Rendering Trace](./performance-frame-rendering-tracking.md) + +[Performance Analysis - Scroll Response Latency](./performance-sliding-response-time.md) + +## Environment Configurations + +If **http_proxy** and **https_proxy** are set in the environment variables, **no_proxy** should also be set. + +``` +export no_proxy=::1,127.0.0.1,localhost +``` + +You can execute the `flutter doctor -v` instruction to check whether the Flutter development environment is properly configured. diff --git a/ohos/docs/05_performance/performance-delimitation.md b/ohos/docs/05_performance/performance-delimitation.md index 08892de16d12cc66d0b65948bc2ee168aa509702..ebd21380fc995ff0b3666a3e2ca7d060461c5646 100644 --- a/ohos/docs/05_performance/performance-delimitation.md +++ b/ohos/docs/05_performance/performance-delimitation.md @@ -1,53 +1,53 @@ -# 性能分析定界指南 +# Performance Analysis Demarcation Guide +## Prerequisites -## 前置条件 -- OpenHarmony Next系统 -- 前台运行Flutter页面 -- 分析工具 - [DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/) +- OpenHarmony Next system +- A Flutter page running in the foreground +- Analysis tools + [DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/) [SmartPerf](https://gitee.com/openharmony-sig/smartperf) -## Flutter线程介绍 -Flutter 使用多个线程来完成其必要的工作,图层中仅展示了其中两个线程。你写的所有 Dart 代码都在 UI 线程上运行。尽管你没有直接访问其他线程的权限,但是你对 UI 线程的操作会对其他线程产生性能影响。 +## Introduction to Flutter Threads -- 平台线程 -平台的主线,插件代码在这里运行 +Flutter uses multiple threads to complete its necessary work, and the diagram only shows two of them. All the Dart code you write runs on the UI thread. Although you do not have direct access to other threads, your operations on the UI thread can affect the performance of other threads. -- UI 线程 -UI 线程在 Dart VM 中执行 Dart 代码。该线程包括开发者写下的代码和 Flutter 框架根据应用行为生成的代码。当应用创建和展示场景的时候,UI 线程首先建立一个 图层树(layer tree) ,一个包含设备无关的渲染命令的轻量对象,并将图层树发送到 GPU 线程来渲染到设备上。 不要阻塞这个线程! 在性能图层的最低栏展示该线程。 +- Platform Thread + The main thread of the platform, where the plugin code runs. -- Raster 线程 -光栅化线程,又称GPU线程。raster 线程拿到 layer tree,并将它交给 GPU(图形处理单元)。你无法直接与 GPU 线程或其数据通信,但如果该线程变慢,一定是开发者 Dart 代码中的某处导致的。图形库 Skia 在该线程运行,并在性能图层的最顶栏显示该线程。请注意,raster 线程为 GPU 进行栅格化,而线程本身则是在 CPU 上运行的。 +- UI Thread + The UI thread executes Dart code in the Dart VM. This includes code written by developers and code generated by the Flutter framework based on application behavior. When the app creates and displays a scene, the UI thread first builds a layer tree, a lightweight object containing device-independent rendering commands, and sends the layer tree to the GPU thread for rendering on the device. **Do not block this thread!** It is displayed in the bottom bar of the performance overlay. -- I/O线程 -执行高负载的操作(常见的有 I/O)以避免阻塞 UI 或者 raster 线程。这个线程将不会显示在 performance overlay 上。 +- Raster Thread + The raster thread, also known as the GPU thread. The raster thread takes the layer tree and hands it off to the GPU (Graphics Processing Unit). You cannot directly interact with the GPU thread or its data, but if this thread slows down, it is definitely caused by some part of the developer’s Dart code. The Skia graphics library runs on this thread, which is displayed in the top bar of the performance overlay. Note that the raster thread performs rasterization for the GPU but itself runs on the CPU. -- RenderService线程 -RS进程的主线程,由Flutter渲染帧完成后,RS线程进行合成并送显.Texture模式下,Flutter渲染后的buffer与应用的主线程合成后,统一送显,受应用主线程的影响;Surface模式下,Flutter渲染帧单独送显,不受应用主线程影响。 +- I/O Thread + Executes high-load operations (commonly I/O) to avoid blocking the UI or raster threads. This thread will not be shown in the performance overlay. +- RenderService Thread + The main thread of the RS process. After Flutter completes frame rendering, the RS thread performs composition and sends the result to the display. In Texture mode, after the Flutter-rendered buffer is composed with the application’s main thread, it is then sent to display together, and is influenced by the application’s main thread. In Surface mode, the Flutter-rendered frame is sent to display independently and is not affected by the application’s main thread. -## 问题定界 -在DevEco Studio中点击下方的Profiler标签页,打开性能调优工具,抓取应用的trace后,收藏应用进程的<x>.ui <x>.raster 和RenderService的主线程 -![](../media/05/image-1-301.png) +## Problem Demarcation +In DevEco Studio, click the Profiler tab at the bottom to open the performance tuning tool. After capturing the application’s trace, bookmark the application processes `.ui`, `.raster`, and the main thread of RenderService. +![](../media/05/image-1-301.png) -上图的RenderService缺失帧,是因为UI线程单帧耗时较长,超过一帧的时间(120帧率下,一帧是8.33毫秒)。 +In the figure above, the missing frames in RenderService occur because the time taken by the UI thread for a single frame is too long, exceeding the duration of one frame (at a 120 fps rate, one frame is 8.33 ms). ![](../media/05/image-1-302.png) +If, in a single frame rendering process, the total duration of `.ui` and `.raster` exceeds the duration of one frame, the performance issue can be identified as a Flutter problem. Further performance analysis is needed for issue localization. -一帧渲染流程中,<x>.ui 和 <x>.raster加起来的的总时长超过一帧时间,则性能问题能定界是Flutter问题。问题的定位,需要进一步的性能分析。 +## Appendix -## 附 -### DevEco Studio Profiler调优工具介绍 -[DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/profiler-introduce-0000001501850508-V2) +### Introduction to DevEco Studio Profiler Tool -### Fluter 调优介绍 -[Flutter性能调优](https://docs.flutter.cn/perf) +[DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/profiler-introduce-0000001501850508-V2) +### Fluter Performance Tuning Introduction +[Flutter Performance Tuning](https://docs.flutter.cn/perf) \ No newline at end of file diff --git a/ohos/docs/05_performance/performance-frame-rendering-tracking.md b/ohos/docs/05_performance/performance-frame-rendering-tracking.md index 4341063d7b3ef581e46bf02484ceb2ca993f1ae9..7570112088fdbd5d48430c0266edd385aac1a083 100644 --- a/ohos/docs/05_performance/performance-frame-rendering-tracking.md +++ b/ohos/docs/05_performance/performance-frame-rendering-tracking.md @@ -1,40 +1,44 @@ -# 性能分析-帧渲染跟踪 +# Performance Analysis - Frame Rendering Trace -Flutter应用进行性能分析时,需利用分析工具捕获应用的trace数据,并对其进行分析。鉴于Flutter应用中可能会出现需要单独追踪某帧渲染的情况,如帧率卡顿或帧丢失,本文特介绍了一种针对单帧追踪的方法。 +When performing performance analysis on Flutter applications, it is necessary to capture the application’s trace data using analysis tools and then analyze it. In some cases, it may be necessary to trace the rendering of a single frame, for example when dealing with frame rate stutters or dropped frames. This document introduces a method for tracing individual frame rendering. -## 分析工具 -常用的分析工具包括[DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/)及[SmartPerf](https://gitee.com/openharmony-sig/smartperf),建议选用DevEco Studio Profiler性能调优工具。性能调优工具DevEco Studio Profiler的使用方法可查看[DevEco Profiler工具简介](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/deep-recording-V5). + ## Analysis Tools + Commonly used analysis tools include [DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/) and [SmartPerf](https://gitee.com/openharmony-sig/smartperf). It is recommended to use the DevEco Studio Profiler for performance tuning. For more information on using the DevEco Studio Profiler, please refer to the [DevEco Profiler Tool Introduction](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/deep-recording-V5). -## 帧标识 -一帧的渲染流程大致如下: -![](../media/05/image-3-201.png) + ## Frame Identifiers + A single frame’s rendering process is roughly as follows: -掌握帧渲染流程非常重要,同时也需要掌握帧渲染流程的每个单元的匹配。为每个单元寻找一个合适的标识符,能正确匹配渲染流程。 + ![](../media/05/image-3-201_EN.png) -### 第一个标识 frame_number -1.ui和1.raster之间联系的标识符是frame_number。 -收藏该两个线程,将这两个线程关联起来进行观察,会在trace上找到这个标识符,这是Flutter应用帧渲染的第一个标识符。 + It is very important to understand the frame rendering process, and it is equally important to be able to match each unit in the frame rendering process. Finding suitable identifiers for each unit helps correctly match the rendering flow. -- 如果frame_number的标识符未在1.ui和1.raster中出现,表明当前帧不是flutter自渲染,需要重新定界性能问题。 -![](../media/05/image-3-202.png) + ### First Identifier: frame_number -### 第二个标识 ReuseBuffer/acquire buffer + The linkage between 1.ui and 1.raster threads is identified by `frame_number`. + By bookmarking these two threads and correlating them for observation, you will find this identifier in the trace. This is the first identifier for Flutter application frame rendering. -1.raster和render_service之间联系的标识符是ReuseBuffer。 -在1.raster线程"flutter::SkCanvas::Flush"的trace过程中,会向RS进程申请buffer内存,用于存储渲染的帧内容。点击"binder transaction"的trace可以跳转到另一个线程,查看对应的ReuseBuffer的id。 + - If the `frame_number` identifier does not appear in either 1.ui or 1.raster, it indicates that the current frame is not rendered by Flutter. In that case, you need to re-demarcate the performance problem. -![](../media/05/image-3-203.png) + ![](../media/05/image-3-202.png) -在render_service线程"RSMainThread::DoComposition"的trace过程中,会获取buffer内存里的帧内存。"acquire buffer sequence"的trace里就能看到和1.raster线程申请的ReuseBuffer编号是一样的。 + ### Second Identifier: ReuseBuffer/acquire buffer -![](../media/05/image-3-204.png) + The linkage between 1.raster and render_service threads is identified by `ReuseBuffer`. + In the `1.raster` thread trace, during the `"flutter::SkCanvas::Flush"` process, the raster thread requests a buffer from the RS process to store the rendered frame content. By clicking on the `"binder transaction"` in the trace, you can jump to another thread and view the corresponding `ReuseBuffer` ID. + ![](../media/05/image-3-203.png) -- 通过上面展示的两个标识,就能识别flutter应用到RS进程上的帧渲染。而RS进程上后面的单元是怎么识别的,目前还没有直观的trace可以看到,默认连续的线程trace是同一帧(即render_service到RSUniRenderThread,再到RSHardwareThread是连续的)。 + + In the render_service thread, during the `"RSMainThread::DoComposition"` trace process, the frame buffer memory is acquired. In the `"acquire buffer sequence"` trace, you can see that the `ReuseBuffer` number matches the one requested by the `1.raster` thread. + + ![](../media/05/image-3-204.png) + + + - With the two identifiers shown above, you can identify the frame rendering flow from the Flutter application to the RS process. As for how to recognize subsequent units on the RS process side, there is currently no intuitive trace available. By default, continuous thread traces are considered part of the same frame (i.e., from `render_service` to `RSUniRenderThread`, and then to `RSHardwareThread` are considered continuous). diff --git a/ohos/docs/05_performance/performance-sliding-response-time.md b/ohos/docs/05_performance/performance-sliding-response-time.md index 29e92cda592d62eaf50696b63fd0044380cbe4ae..bd504e318180a10526a8e4979c4b960885e62fd5 100644 --- a/ohos/docs/05_performance/performance-sliding-response-time.md +++ b/ohos/docs/05_performance/performance-sliding-response-time.md @@ -1,61 +1,60 @@ -# 性能分析-滑动响应时延 +# Performance Analysis - Scroll Response Latency -本篇文章针对flutter应用的滑动场景,进行响应时延的trace分析。请务必先看完这篇指南[性能分析第一步-梳理线程顺序](./performance-threads-sequence.md)再继续。 +This article focuses on trace analysis of response latency in scrolling scenarios for Flutter applications. Be sure to read [Performance Analysis Step 1 - Sorting Out Thread Order](./performance-threads-sequence.md) before continuing. -## 准备条件 +## Prerequisites -- 了解并能使用性能分析工具[DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/) -- 了解线程渲染顺序([性能分析第一步-梳理线程顺序](./performance-threads-sequence.md)) +- Understand and be able to use the performance analysis tool [DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/) +- Understand thread rendering order ([Performance Analysis Step 1 - Sorting Out Thread Order](./performance-threads-sequence.md)) -## 1. 手指按下 -手指按下是所有点击或滑动事件的大前提,可以知道手指坐标的初始位置和触摸哪个控件等重要信息。 +## 1. Finger Down +A finger-down event is the prerequisite for all tap or scroll events, providing critical information such as the initial coordinates of the finger and which widget is being touched. -mmi_service线程负责触发多模交互事件,由Flutter应用监听和响应触摸事件。 +The `mmi_service` thread is responsible for triggering multi-modal interaction events, which the Flutter application listens to and responds to. +The finger-down touch event is immediately forwarded to the Flutter application. -手指按下的触摸事件,会立即转发给Flutter应用。 - - -在mmi_service线程的"package touchEvent"的trace后面的下一个trace,可以看到"service report touchId:编号, type: down"的trace,type为down,说明是手指按下的触摸事件。而在应用主线程,有"DispatchTouchEvent"的trace,上面有详细坐标打印和触摸事件类型,type数值为0,说明是手指按下的触摸事件。这两个线程上的trace是对应的。 +In the `mmi_service` thread, after the "package touchEvent" trace, you can see a "service report touchId:xxx, type: down" trace, where `type` is `down`, indicating a finger-down touch event. Meanwhile, on the application’s main thread, there is a "DispatchTouchEvent" trace that shows detailed coordinates and the event type. When `type` has a value of `0`, it means a finger-down touch event. These traces on the two threads correspond to each other. ![](../media/05/image-4-201.png) -## 2.手指滑动 -手指滑动的触摸事件,不会立即转发给Flutter应用,而是由vsync-app信号来控制发送。 - +## 2. Finger Move -和手指按下的trace一样,mmi_service线程和应用主线程都有一样的trace可以对应,只是type类型不一样。type为move,数值为2。 +Unlike a finger-down event, a finger-move touch event is not immediately forwarded to the Flutter application. Instead, it is controlled by the vsync-app signal before being sent. +Similar to the finger-down trace, both the `mmi_service` thread and the application’s main thread have corresponding traces, but with a different type. `type = move` corresponds to a value of `2`. -手指滑动的触摸事件需通过flutterSyncName的vsync-app信号触发,之后才能传递到flutter应用主线程。因此,时间顺序是,mmi_service到VSyncGennerator,再到DVSync-app,最后到应用主线程。trace顺序如下图: +The finger-move touch event requires a vsync-app signal named `flutterSyncName` to be triggered before it is passed on to the Flutter application’s main thread. Thus, the chronological order is: `mmi_service` → `VSyncGennerator` → `DVSync-app` → Application main thread. The trace order is shown below: ![](../media/05/image-4-301.png) -- 注意:第一个手指滑动的触摸事件的坐标点和手指按下的触摸事件的坐标点是一样的。 +- Note: The coordinates of the very first finger-move touch event are the same as those of the finger-down event. -## 3.滑动阈值 TouchSlop -TouchSlop是系统所能识别的滑动的最小距离,是一个阈值,称为滑动阈值。用户可以自定义设置控件的滑动阈值,系统默认值是18。 +## 3. TouchSlop Threshold -那么通过查看应用主线程的触摸事件trace的坐标,可以自行计算坐标偏移量是否达到滑动阈值。 +TouchSlop is the minimum recognizable scroll distance, essentially a threshold. Users can customize the widget’s scrolling threshold, with a default system value of 18. +By checking the touch event coordinates in the application’s main thread traces, you can manually calculate the coordinate offset to see if it meets the scrolling threshold. -## 4.滑动首帧 -当手指滑动的触摸事件的滑动距离超过设定的滑动阈值时,Flutter应用会触发update操作。但是,实际的绘制操作需要等待下一帧的到来才能执行。所以滑动开始的第一帧渲染,会在触摸事件满足滑动条件后,还需等待一帧的延迟。 +## 4. The First Scrolling Frame -trace如下图: +When the scrolling distance of the finger-move touch event exceeds the set TouchSlop threshold, the Flutter application triggers an `update` operation. However, actual drawing operations must wait for the arrival of the next frame. Therefore, the rendering of the first frame when scrolling begins involves an additional one-frame delay after the touch event conditions are met. + +The trace is shown below: ![](../media/05/image-4-401.png) -## 5.首帧渲染 -渲染的大致过程看[性能分析-帧渲染跟踪](./performance-frame-rendering-tracking.md),需要准确找到对应的trace。 +## 5. First Frame Rendering + +For a general overview of rendering, see [Performance Analysis - Frame Rendering Tracking](./performance-frame-rendering-tracking.md) to accurately locate corresponding traces. -帧渲染的结束是在RS进程的RSHardwareThread线程上,但是在自动化测试的时候,帧渲染的结束标识是dpu_gfx_primary线程。(dpu_gfx_primary只是一个硬件信号,不详细讲解) +The frame rendering ends on the `RSHardwareThread` thread in the RS process. However, in automated testing, the end of frame rendering is identified by the `dpu_gfx_primary` thread. (The `dpu_gfx_primary` thread is just a hardware signal and will not be explained in detail.) -trace如下图: +The trace is shown below: ![](../media/05/image-4-501.png) -所以从mmi_service线程的手指按下的trace开始,到滑动首帧渲染结束,这花费的时间就是滑动响应时延。 +Therefore, the time from the `mmi_service` thread’s finger-down trace to the end of the first scrolling frame rendering is the scroll response latency. diff --git a/ohos/docs/05_performance/performance-threads-sequence.md b/ohos/docs/05_performance/performance-threads-sequence.md index a75eeb04d2f7a717fc381ea03f0eb3c725413a11..704817aaa34d3fc676fa31ad8cd0eedc0c83404c 100644 --- a/ohos/docs/05_performance/performance-threads-sequence.md +++ b/ohos/docs/05_performance/performance-threads-sequence.md @@ -1,63 +1,74 @@ -# 性能分析第一步-梳理线程顺序 +# The First Step in Performance Analysis – Sorting Out Thread Order -Flutter应用在性能分析的时候,需要使用分析工具去抓取应用的trace,并对trace进行分析。Flutter应用在渲染流程上与几个线程密不可分,而这篇指南里,主要介绍这几个密不可分的线程,以及它们在渲染流程上顺序。 +When performing performance analysis on a Flutter application, it is necessary to use analysis tools to capture the application’s trace and then analyze it. The rendering process of a Flutter application is closely intertwined with several threads. This guide introduces these threads and their order in the rendering process. +## Analysis Tools -## 分析工具 -常用的分析工具有[DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/)和[SmartPerf](https://gitee.com/openharmony-sig/smartperf),推荐使用性能调优工具DevEco Studio Profiler。性能调优工具DevEco Studio Profiler的使用方法可查看[DevEco Profiler工具简介](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/deep-recording-V5). +Common analysis tools include [DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/) and [SmartPerf](https://gitee.com/openharmony-sig/smartperf). It is recommended to use the DevEco Studio Profiler for performance tuning. For instructions on how to use the DevEco Studio Profiler, please refer to the [DevEco Profiler Tool Introduction](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/deep-recording-V5). +## Thread Order -## 线程顺序 -- 掌握分析工具的使用后,便能去抓取Flutter应用的trace。trace中包含了应用运行期间的所有线程,需要先收藏下图的线程,以及按照图中线程的顺序去排序,才能更好的分析Flutter应用性能。下图每个线程的上方用数字标识了其排列的位置。 -- trace收藏线程,后收藏的线程会出现在收藏列表的顶部,所以实际收藏的时候,根据下图的倒序来收藏线程会比较方便。 -- 1)VSyncGennerator 2)DVSync-app 3)mmi_service 4)应用主线程 5)flutter'PointerEvent' 6)1.ui 7)1.raster 8)DVSync-rs 9)render_service 10)RSUniRenderThread 11)RSHardwareThread 12)dpu_gfx_primary +- Once you understand how to use the analysis tools, you can capture the Flutter application’s trace. The trace contains all threads that ran during the application’s execution. To better analyze Flutter’s performance, you need to first bookmark the threads shown in the figure below and then arrange them in the order indicated by the numbers above them. +- When bookmarking threads in the trace, note that threads added later appear at the top of the favorites list. Therefore, it’s more convenient to bookmark the threads in reverse order as shown in the figure. +- The order of threads is: + 1) VSyncGennerator + 2) DVSync-app + 3) mmi_service + 4) Main application thread + 5) flutter’PointerEvent’ + 6) 1.ui + 7) 1.raster + 8) DVSync-rs + 9) render_service + 10) RSUniRenderThread + 11) RSHardwareThread + 12) dpu_gfx_primary -![](../media/05/image-2-201.png) +![](../media/05/image-2-201_EN.png) -分析工具按顺序收藏线程后,线程收藏列表如下图: -![](../media/05/image-2-202.png) +After bookmarking the threads in order, the thread favorites list should look like this: +![](../media/05/image-2-202.png) ![](../media/05/image-2-203.png) - ![](../media/05/image-2-204.png) +## Introduction to the Bookmarked Threads -## 收藏线程介绍 -- VSyncGennerator -软件Vsync信号生成器,提供感知VSync帧的能力 +- **VSyncGennerator** + A software Vsync signal generator that provides the capability to perceive VSync frames. -- DVSync-app -提供给app应用的软件Vsync信号 +- **DVSync-app** + Provides a software Vsync signal to the app application. -- mmi_service -手指触摸屏幕时,触发的多模事件 +- **mmi_service** + Handles multi-modal events triggered when the user touches the screen. -- 应用主线程 -即线程号跟应用进程号一致,同时线程名跟进程名一致的主线程 -平台的主线,插件代码在这里运行 +- **Main Application Thread** + The thread whose ID matches the application’s process ID and whose name matches the process name. + This is the platform’s main thread, where plugin code runs. -- flutter'PointerEvent' -flutter的应用主线程发送触摸事件,到1.ui线程处理触摸事件的过程。这个线程可能会不存在。 +- **flutter'PointerEvent'** + This thread (if it exists) handles the process of sending touch events from the main application thread to the 1.ui thread for processing. -- 1.ui -UI线程,命名为< number >.ui -UI 线程在 Dart VM 中执行 Dart 代码。该线程包括开发者写下的代码和 Flutter 框架根据应用行为生成的代码。当应用创建和展示场景的时候,UI 线程首先建立一个 图层树(layer tree) ,一个包含设备无关的渲染命令的轻量对象,并将图层树发送到 GPU 线程来渲染到设备上。 不要阻塞这个线程! 在性能图层的最低栏展示该线程。 +- **1.ui** + The UI thread, named `.ui`. + The UI thread executes Dart code in the Dart VM. This includes both developer-written code and code generated by the Flutter framework based on application behavior. When the app creates and displays a scene, the UI thread first builds a layer tree—a lightweight object containing device-independent rendering commands—and sends it to the GPU thread for rendering. **Do not block this thread!** In the performance overlay, this thread is displayed at the bottom bar. -- 1.raster -Raster线程,命名为< number >.raster -raster 线程拿到 layer tree,并将它交给 GPU(图形处理单元)。你无法直接与 GPU 线程或其数据通信,但如果该线程变慢,一定是开发者 Dart 代码中的某处导致的。图形库 Skia 在该线程运行,并在性能图层的最顶栏显示该线程。请注意,raster 线程为 GPU 进行栅格化,而线程本身则是在 CPU 上运行的。 +- **1.raster** + The Raster thread, named `.raster`. + The raster thread receives the layer tree and hands it off to the GPU (Graphics Processing Unit). You cannot directly interact with the GPU thread or its data, but if this thread is slow, it is definitely caused by some part of your Dart code. The Skia graphics library runs on this thread, which is displayed at the top bar of the performance overlay. Note that while the raster thread performs rasterization for the GPU, the thread itself runs on the CPU. -- DVSync-rs -提供给RS进程的软件Vsync信号 +- **DVSync-rs** + Provides a software Vsync signal to the RS process. -- render_service -RS进程的主线程,RS送显的第一步 +- **render_service** + The main thread of the RS process, and the first step in RS composition. -- RSUniRenderThread -RS进程的线程,RS送显的第二步 +- **RSUniRenderThread** + A thread in the RS process, responsible for the second step in RS composition. -- RSHardwareThread -RS进程的线程,RS送显的第三步 +- **RSHardwareThread** + A thread in the RS process, responsible for the third step in RS composition. -- dpu_gfx_primary -硬件dpu信号 +- **dpu_gfx_primary** + A hardware DPU signal. diff --git "a/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220-\345\270\247\346\270\262\346\237\223\350\267\237\350\270\252.md" "b/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220-\345\270\247\346\270\262\346\237\223\350\267\237\350\270\252.md" new file mode 100644 index 0000000000000000000000000000000000000000..4341063d7b3ef581e46bf02484ceb2ca993f1ae9 --- /dev/null +++ "b/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220-\345\270\247\346\270\262\346\237\223\350\267\237\350\270\252.md" @@ -0,0 +1,40 @@ +# 性能分析-帧渲染跟踪 + +Flutter应用进行性能分析时,需利用分析工具捕获应用的trace数据,并对其进行分析。鉴于Flutter应用中可能会出现需要单独追踪某帧渲染的情况,如帧率卡顿或帧丢失,本文特介绍了一种针对单帧追踪的方法。 + + +## 分析工具 +常用的分析工具包括[DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/)及[SmartPerf](https://gitee.com/openharmony-sig/smartperf),建议选用DevEco Studio Profiler性能调优工具。性能调优工具DevEco Studio Profiler的使用方法可查看[DevEco Profiler工具简介](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/deep-recording-V5). + + +## 帧标识 +一帧的渲染流程大致如下: + +![](../media/05/image-3-201.png) + + +掌握帧渲染流程非常重要,同时也需要掌握帧渲染流程的每个单元的匹配。为每个单元寻找一个合适的标识符,能正确匹配渲染流程。 + +### 第一个标识 frame_number +1.ui和1.raster之间联系的标识符是frame_number。 +收藏该两个线程,将这两个线程关联起来进行观察,会在trace上找到这个标识符,这是Flutter应用帧渲染的第一个标识符。 + +- 如果frame_number的标识符未在1.ui和1.raster中出现,表明当前帧不是flutter自渲染,需要重新定界性能问题。 + +![](../media/05/image-3-202.png) + +### 第二个标识 ReuseBuffer/acquire buffer + +1.raster和render_service之间联系的标识符是ReuseBuffer。 +在1.raster线程"flutter::SkCanvas::Flush"的trace过程中,会向RS进程申请buffer内存,用于存储渲染的帧内容。点击"binder transaction"的trace可以跳转到另一个线程,查看对应的ReuseBuffer的id。 + +![](../media/05/image-3-203.png) + + +在render_service线程"RSMainThread::DoComposition"的trace过程中,会获取buffer内存里的帧内存。"acquire buffer sequence"的trace里就能看到和1.raster线程申请的ReuseBuffer编号是一样的。 + +![](../media/05/image-3-204.png) + + + +- 通过上面展示的两个标识,就能识别flutter应用到RS进程上的帧渲染。而RS进程上后面的单元是怎么识别的,目前还没有直观的trace可以看到,默认连续的线程trace是同一帧(即render_service到RSUniRenderThread,再到RSHardwareThread是连续的)。 diff --git "a/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220-\346\273\221\345\212\250\345\223\215\345\272\224\346\227\266\345\273\266.md" "b/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220-\346\273\221\345\212\250\345\223\215\345\272\224\346\227\266\345\273\266.md" new file mode 100644 index 0000000000000000000000000000000000000000..29e92cda592d62eaf50696b63fd0044380cbe4ae --- /dev/null +++ "b/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220-\346\273\221\345\212\250\345\223\215\345\272\224\346\227\266\345\273\266.md" @@ -0,0 +1,61 @@ +# 性能分析-滑动响应时延 + +本篇文章针对flutter应用的滑动场景,进行响应时延的trace分析。请务必先看完这篇指南[性能分析第一步-梳理线程顺序](./performance-threads-sequence.md)再继续。 + +## 准备条件 + +- 了解并能使用性能分析工具[DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/) +- 了解线程渲染顺序([性能分析第一步-梳理线程顺序](./performance-threads-sequence.md)) + +## 1. 手指按下 +手指按下是所有点击或滑动事件的大前提,可以知道手指坐标的初始位置和触摸哪个控件等重要信息。 + + +mmi_service线程负责触发多模交互事件,由Flutter应用监听和响应触摸事件。 + + +手指按下的触摸事件,会立即转发给Flutter应用。 + + +在mmi_service线程的"package touchEvent"的trace后面的下一个trace,可以看到"service report touchId:编号, type: down"的trace,type为down,说明是手指按下的触摸事件。而在应用主线程,有"DispatchTouchEvent"的trace,上面有详细坐标打印和触摸事件类型,type数值为0,说明是手指按下的触摸事件。这两个线程上的trace是对应的。 + +![](../media/05/image-4-201.png) + + +## 2.手指滑动 +手指滑动的触摸事件,不会立即转发给Flutter应用,而是由vsync-app信号来控制发送。 + + +和手指按下的trace一样,mmi_service线程和应用主线程都有一样的trace可以对应,只是type类型不一样。type为move,数值为2。 + + +手指滑动的触摸事件需通过flutterSyncName的vsync-app信号触发,之后才能传递到flutter应用主线程。因此,时间顺序是,mmi_service到VSyncGennerator,再到DVSync-app,最后到应用主线程。trace顺序如下图: + +![](../media/05/image-4-301.png) + +- 注意:第一个手指滑动的触摸事件的坐标点和手指按下的触摸事件的坐标点是一样的。 + +## 3.滑动阈值 TouchSlop +TouchSlop是系统所能识别的滑动的最小距离,是一个阈值,称为滑动阈值。用户可以自定义设置控件的滑动阈值,系统默认值是18。 + +那么通过查看应用主线程的触摸事件trace的坐标,可以自行计算坐标偏移量是否达到滑动阈值。 + + +## 4.滑动首帧 +当手指滑动的触摸事件的滑动距离超过设定的滑动阈值时,Flutter应用会触发update操作。但是,实际的绘制操作需要等待下一帧的到来才能执行。所以滑动开始的第一帧渲染,会在触摸事件满足滑动条件后,还需等待一帧的延迟。 + +trace如下图: + +![](../media/05/image-4-401.png) + +## 5.首帧渲染 +渲染的大致过程看[性能分析-帧渲染跟踪](./performance-frame-rendering-tracking.md),需要准确找到对应的trace。 + +帧渲染的结束是在RS进程的RSHardwareThread线程上,但是在自动化测试的时候,帧渲染的结束标识是dpu_gfx_primary线程。(dpu_gfx_primary只是一个硬件信号,不详细讲解) + +trace如下图: + +![](../media/05/image-4-501.png) + + +所以从mmi_service线程的手指按下的trace开始,到滑动首帧渲染结束,这花费的时间就是滑动响应时延。 diff --git "a/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220\345\256\232\347\225\214\346\214\207\345\215\227.md" "b/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220\345\256\232\347\225\214\346\214\207\345\215\227.md" new file mode 100644 index 0000000000000000000000000000000000000000..08892de16d12cc66d0b65948bc2ee168aa509702 --- /dev/null +++ "b/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220\345\256\232\347\225\214\346\214\207\345\215\227.md" @@ -0,0 +1,53 @@ +# 性能分析定界指南 + + +## 前置条件 +- OpenHarmony Next系统 +- 前台运行Flutter页面 +- 分析工具 + [DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/) + [SmartPerf](https://gitee.com/openharmony-sig/smartperf) + + +## Flutter线程介绍 +Flutter 使用多个线程来完成其必要的工作,图层中仅展示了其中两个线程。你写的所有 Dart 代码都在 UI 线程上运行。尽管你没有直接访问其他线程的权限,但是你对 UI 线程的操作会对其他线程产生性能影响。 + +- 平台线程 +平台的主线,插件代码在这里运行 + +- UI 线程 +UI 线程在 Dart VM 中执行 Dart 代码。该线程包括开发者写下的代码和 Flutter 框架根据应用行为生成的代码。当应用创建和展示场景的时候,UI 线程首先建立一个 图层树(layer tree) ,一个包含设备无关的渲染命令的轻量对象,并将图层树发送到 GPU 线程来渲染到设备上。 不要阻塞这个线程! 在性能图层的最低栏展示该线程。 + +- Raster 线程 +光栅化线程,又称GPU线程。raster 线程拿到 layer tree,并将它交给 GPU(图形处理单元)。你无法直接与 GPU 线程或其数据通信,但如果该线程变慢,一定是开发者 Dart 代码中的某处导致的。图形库 Skia 在该线程运行,并在性能图层的最顶栏显示该线程。请注意,raster 线程为 GPU 进行栅格化,而线程本身则是在 CPU 上运行的。 + +- I/O线程 +执行高负载的操作(常见的有 I/O)以避免阻塞 UI 或者 raster 线程。这个线程将不会显示在 performance overlay 上。 + +- RenderService线程 +RS进程的主线程,由Flutter渲染帧完成后,RS线程进行合成并送显.Texture模式下,Flutter渲染后的buffer与应用的主线程合成后,统一送显,受应用主线程的影响;Surface模式下,Flutter渲染帧单独送显,不受应用主线程影响。 + + +## 问题定界 +在DevEco Studio中点击下方的Profiler标签页,打开性能调优工具,抓取应用的trace后,收藏应用进程的<x>.ui <x>.raster 和RenderService的主线程 +![](../media/05/image-1-301.png) + + + + +上图的RenderService缺失帧,是因为UI线程单帧耗时较长,超过一帧的时间(120帧率下,一帧是8.33毫秒)。 + +![](../media/05/image-1-302.png) + + +一帧渲染流程中,<x>.ui 和 <x>.raster加起来的的总时长超过一帧时间,则性能问题能定界是Flutter问题。问题的定位,需要进一步的性能分析。 + + +## 附 +### DevEco Studio Profiler调优工具介绍 +[DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/profiler-introduce-0000001501850508-V2) + +### Fluter 调优介绍 +[Flutter性能调优](https://docs.flutter.cn/perf) + + diff --git "a/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220\347\254\254\344\270\200\346\255\245-\346\242\263\347\220\206\347\272\277\347\250\213\351\241\272\345\272\217.md" "b/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220\347\254\254\344\270\200\346\255\245-\346\242\263\347\220\206\347\272\277\347\250\213\351\241\272\345\272\217.md" new file mode 100644 index 0000000000000000000000000000000000000000..a75eeb04d2f7a717fc381ea03f0eb3c725413a11 --- /dev/null +++ "b/ohos/docs/05_performance/\346\200\247\350\203\275\345\210\206\346\236\220\347\254\254\344\270\200\346\255\245-\346\242\263\347\220\206\347\272\277\347\250\213\351\241\272\345\272\217.md" @@ -0,0 +1,63 @@ +# 性能分析第一步-梳理线程顺序 + +Flutter应用在性能分析的时候,需要使用分析工具去抓取应用的trace,并对trace进行分析。Flutter应用在渲染流程上与几个线程密不可分,而这篇指南里,主要介绍这几个密不可分的线程,以及它们在渲染流程上顺序。 + + +## 分析工具 +常用的分析工具有[DevEco Studio Profiler](https://developer.huawei.com/consumer/cn/download/)和[SmartPerf](https://gitee.com/openharmony-sig/smartperf),推荐使用性能调优工具DevEco Studio Profiler。性能调优工具DevEco Studio Profiler的使用方法可查看[DevEco Profiler工具简介](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/deep-recording-V5). + + +## 线程顺序 +- 掌握分析工具的使用后,便能去抓取Flutter应用的trace。trace中包含了应用运行期间的所有线程,需要先收藏下图的线程,以及按照图中线程的顺序去排序,才能更好的分析Flutter应用性能。下图每个线程的上方用数字标识了其排列的位置。 +- trace收藏线程,后收藏的线程会出现在收藏列表的顶部,所以实际收藏的时候,根据下图的倒序来收藏线程会比较方便。 +- 1)VSyncGennerator 2)DVSync-app 3)mmi_service 4)应用主线程 5)flutter'PointerEvent' 6)1.ui 7)1.raster 8)DVSync-rs 9)render_service 10)RSUniRenderThread 11)RSHardwareThread 12)dpu_gfx_primary + +![](../media/05/image-2-201.png) + +分析工具按顺序收藏线程后,线程收藏列表如下图: +![](../media/05/image-2-202.png) + +![](../media/05/image-2-203.png) + +![](../media/05/image-2-204.png) + + +## 收藏线程介绍 +- VSyncGennerator +软件Vsync信号生成器,提供感知VSync帧的能力 + +- DVSync-app +提供给app应用的软件Vsync信号 + +- mmi_service +手指触摸屏幕时,触发的多模事件 + +- 应用主线程 +即线程号跟应用进程号一致,同时线程名跟进程名一致的主线程 +平台的主线,插件代码在这里运行 + +- flutter'PointerEvent' +flutter的应用主线程发送触摸事件,到1.ui线程处理触摸事件的过程。这个线程可能会不存在。 + +- 1.ui +UI线程,命名为< number >.ui +UI 线程在 Dart VM 中执行 Dart 代码。该线程包括开发者写下的代码和 Flutter 框架根据应用行为生成的代码。当应用创建和展示场景的时候,UI 线程首先建立一个 图层树(layer tree) ,一个包含设备无关的渲染命令的轻量对象,并将图层树发送到 GPU 线程来渲染到设备上。 不要阻塞这个线程! 在性能图层的最低栏展示该线程。 + +- 1.raster +Raster线程,命名为< number >.raster +raster 线程拿到 layer tree,并将它交给 GPU(图形处理单元)。你无法直接与 GPU 线程或其数据通信,但如果该线程变慢,一定是开发者 Dart 代码中的某处导致的。图形库 Skia 在该线程运行,并在性能图层的最顶栏显示该线程。请注意,raster 线程为 GPU 进行栅格化,而线程本身则是在 CPU 上运行的。 + +- DVSync-rs +提供给RS进程的软件Vsync信号 + +- render_service +RS进程的主线程,RS送显的第一步 + +- RSUniRenderThread +RS进程的线程,RS送显的第二步 + +- RSHardwareThread +RS进程的线程,RS送显的第三步 + +- dpu_gfx_primary +硬件dpu信号 diff --git a/ohos/docs/06_debug/README_EN.md b/ohos/docs/06_debug/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..07b59bf7b4a2226f6df6be6e7640c5e15cafc6c8 --- /dev/null +++ b/ohos/docs/06_debug/README_EN.md @@ -0,0 +1,5 @@ +# Debugging + +1. [Debugging Dart Code](./debugging-dart-code.md) +2. [Debugging Your OpenHarmony App/Service](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V2/ohos-debugging-app-0000001545729889-V2) + diff --git a/ohos/docs/06_debug/debugging-dart-code.md b/ohos/docs/06_debug/debugging-dart-code.md new file mode 100644 index 0000000000000000000000000000000000000000..67cc5a899d954de5ed13b3ba1e2a41054bf20346 --- /dev/null +++ b/ohos/docs/06_debug/debugging-dart-code.md @@ -0,0 +1,54 @@ +# Debugging Dart Code + +- Use DevEco Studio to debug ets code. +- Use VS Code and Android Studio to debug dart code. + - You need to add the parameters, for example, `--local-engine=/Users/xxx/ohos/engine/src/out/ohos_debug_unopt_arm64`, when debugging the HarmonyOS Fluffer project. + +## Using VS Code to Debug Dart Code + +Create the **.vscode/launch.json** file in the project directory and enter the parameters as follows: + +``` +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "flutter_sample", + "request": "launch", + "type": "dart", + "args": [ + "--local-engine=/Users/xxx/work/engine_build/engine/src/out/ohos_debug_unopt_arm64" + ] + }, + { + "name": "flutter_sample (profile mode)", + "request": "launch", + "type": "dart", + "flutterMode": "profile", + "args": [ + "--local-engine=/Users/xxx/work/engine_build/engine/src/out/ohos_profile_arm64" + ] + }, + { + "name": "flutter_sample (release mode)", + "request": "launch", + "type": "dart", + "flutterMode": "release", + "args": [ + "--local-engine=/Users/xxx/work/engine_build/engine/src/out/ohos_release_arm64" + ] + } + ] +} +``` + +You can debug the dart code after the modification. + +## Using Android Studio to Debug Dart Code + +![](../media/06/06_android_run_config.png) + +You can debug the dart code after setting the parameters. diff --git a/ohos/docs/07_plugin/README_EN.md b/ohos/docs/07_plugin/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..88a789b10c00bf7c490b0cdfe017d3fd0b618502 --- /dev/null +++ b/ohos/docs/07_plugin/README_EN.md @@ -0,0 +1,5 @@ +# Third-Party Library Access + + + +1. [Developing an ohos Plugin Using Flutter](./developing-an-ohos-plugin-using-flutter.md) diff --git a/ohos/docs/07_plugin/developing-an-ohos-plugin-using-flutter.md b/ohos/docs/07_plugin/developing-an-ohos-plugin-using-flutter.md new file mode 100644 index 0000000000000000000000000000000000000000..e31ea5265a539d42d542b5e72464baa7f4786ac6 --- /dev/null +++ b/ohos/docs/07_plugin/developing-an-ohos-plugin-using-flutter.md @@ -0,0 +1,333 @@ +# Developing an ohos Plugin Using Flutter + +## 1. Preparations + +Set up the Flutter development environment. For details, see https://gitee.com/openharmony-sig/flutter_flutter/blob/master/README_EN.md. + +Download the third-party plugins from the official plugin library in https://pub.dev/. + +This guide uses the adaptation of the **path_provider 2.1.0** plugin as an example. Plugin URL: https://pub-web.flutter-io.cn/packages/path_provider/versions/2.1.0. + +## 2. Plugin Directory + +![image-20240410105254011](../media/07_1/01_Plugin_Directory.png) + +lib: Entry for connecting to the dart code. Through this directory, parameters are received and data is sent to the native platform through the channel. + +android: Native Android implementation directory. + +ios: Native iOS implementation directory. + +example: A Flutter application that describes how to use the plugin. + +README_EN.md: Introduction to the package. + +CHANGELOG.md: Change records of each version. + +LICENSE: A file that contains the license terms of the software package. + +## 3. Creating the ohos Module of the Plugin + +Required Instruction: `flutter create --platforms ohos,android,ios --org ` + +Steps: + +(1) Open the downloaded plugin in Android Studio. + +(2) Open **Terminal** and execute **cd** to go to the plugin directory. + +(3) Execute the `flutter create --platforms ohos path_provider_ohos` instruction to create a Flutter module for the ohos platform. + +Before creating the module, the plugin structure is as below. + +![image-20240410105254011](../media/07_1/02_Flutter_plugin_structure.png) + +After creating the module, you can delete the **.dart_tool** and **.ldea** files from the **path_provider_ohos** directory. + +![image-20240410105254011](../media/07_1/03_HarmonyOS_plugin_structure.png) + + + +## 4. Compiling the Dart APIs and pubspec.yaml File of the ohos Plugin + +You can copy the dart code and **pubspec.yaml** file under **lib** from the **path_provider_android** directory and modify them. + +For the dart code, you only need to change **android** to **ohos**. + +Dart code in the **lib** directory + +![image-20240410105254011](../media/07_1/04_ohos_plugin_dart_side_structure.png) + +pubspec.yaml file + +``` +# Example file content for reference: +name: path_provider_ohos +description: Ohos implementation of the path_provider plugin. +repository: https://gitee.com/openharmony-sig/flutter_packages/tree/master/packages/path_provider/path_provider_ohos +issue_tracker: https://gitee.com/openharmony-sig/flutter_packages/issues +version: 2.2.1 + +environment: + sdk: ">=2.18.0 <4.0.0" + flutter: ">=3.3.0" + +flutter: + plugin: + implements: path_provider + platforms: + ohos: + package: io.flutter.plugins.pathprovider + pluginClass: PathProviderPlugin + dartPluginClass: PathProviderOhos + +dependencies: + flutter: + sdk: flutter + path_provider_platform_interface: ^2.0.1 + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + pigeon: ^9.2.4 + test: ^1.16.0 +``` + +## 5. Building the Native ETS Module of the ohos Plugin + +### 1. Create the ohos plugin module. + +To build a Flutter plugin instead of an application for the ohos platform, delete the original **entry** module and create a static module of the **path_provider** plugin for compiling the ETS native code. + +Steps: + +(1) Use DevEco Studio to open the ohos project in the **path_provider_ohos** directory. + +![image-20240410105254011](../media/07_1/05_The_ohos_project_in_the_HarmonyOS_plugin.png) + +(2) Create a static module named **path_provider**. + +Click `File > New > Module > Static Library > Next` in the upper left corner of DevEco Studio. + +Set **module name** to `path_provider`, retain the default values for other parameters, and click **Finish**. + + + +![image-20240410105254011](../media/07_1/06_Create_new_path_provider_module.png) + +(3) Delete **entry** and other unnecessary directories. + +**entry** directory (used to build an application and is not needed here); + +All files (which are the template code) in the `path_provider > src > main > ets` directory. + +![image-20240410105254011](../media/07_1/07_Delete_entry_and_other_redundant_directories.png) + + + +### 2. Modify related configuration files. + +(1) Add the **libs/flutter.har** dependency to the **oh-package.json5** file in the **path_provider** directory. + +``` +{ + "name": "path_provider", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "Index.ets", + "author": "", + "license": "Apache-2.0", + "dependencies": { + "@ohos/flutter_ohos": "file:libs/flutter.har" // Added dependency. + } +} +``` + +(2) Delete the **flutter.har** dependency from **oh-package.json5** file outside the **path_provider** directory. + +``` +{ + "name": "path_provider_ohos", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.6" + }, +} +``` + +(3) Add **flutter.har** to the **path_provider** directory. + +![image-20240410105254011](../media/07_1/08_Add_flutter.har_file.png) + + + +### 3. Write the ets code. + +You can refer to the Android or iOS directory to build the file structure and code logic. + +For details about the ohos APIs, visit https://gitee.com/openharmony/docs/tree/master/en. + +![image-20240410105254011](../media/07_1/09_Write_ets_code.png) + + + +### 4. Modify the index file. + +``` +# Example file content for reference: +import PathProviderPlugin from './src/main/ets/io/flutter/plugins/pathprovider/PathProviderPlugin' + +export default PathProviderPlugin +``` + +### 5. Pack a HAP file. + +You can pack a HAP file after compiling the code and modifying the configuration. + +Packing tool: DevEco Studio + +Steps: 1. Select the **path_provider** directory. 2. Click **Build** in the menu bar. 3. Click **Make Module'pathprovider'**. 4. Wait until the packing is complete. + +![image-20240410105254011](../media/07_1/10_Steps_for_creating_har_packages_for_the_project.png) + +Expected Result: + +The **path_proivider.har** file is generated in `path_provider > build > default > outputs `. + +![image-20240410105254011](../media/07_1/11_Successfully_converted_to_har_package.png) + + + + + +## 6. Writing an Example + +### 1. Create a Flutter example application on the ohos platform to verify the features of the plugin. + +Execute **cd** to go to the **path_provider_ohos** directory. + +Instruction: `flutter create --platforms ohos example` + +Tool: Android Studio + +![image-20240410105254011](../media/07_1/12_Create_example_command.png) + +![image-20240410105254011](../media/07_1/13_example.png) + +### 2. Modify the dart code. + +Copy the **main.dart** code in `path_provider_android\example\lib` to replace the one in `path_provider_ohos\example\lib`. + +### 3. Modify the **example pubspec.yaml** file. + +``` +#Example file content for reference: +name: path_provider_example +description: Demonstrates how to use the path_provider plugin. +publish_to: none + +environment: + sdk: ">=2.18.0 <4.0.0" + flutter: ">=3.3.0" + +dependencies: + flutter: + sdk: flutter + path_provider: + path: ../../path_provider + path_provider_platform_interface: ^2.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + +flutter: + uses-material-design: true +``` + +## 7. Modifying the pubspec.yaml File of path_provide + +Add ohos in **flutter** > **plugin** > **platforms**. + +Add **path_provider_ohos** in **dependencies**. + +``` +name: path_provider +description: Flutter plugin for getting commonly used locations on host platform file systems, such as the temp and app data directories. +repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 +version: 2.1.0 + +environment: + sdk: ">=2.18.0 <4.0.0" + flutter: ">=3.3.0" + +flutter: + plugin: + platforms: + android: + default_package: path_provider_android + ios: + default_package: path_provider_foundation + linux: + default_package: path_provider_linux + macos: + default_package: path_provider_foundation + windows: + default_package: path_provider_windows + ohos: + default_package: path_provider_ohos # Added here. + +dependencies: + flutter: + sdk: flutter + path_provider_android: ^2.1.0 + path_provider_foundation: ^2.3.0 + path_provider_linux: ^2.2.0 + path_provider_platform_interface: ^2.1.0 + path_provider_windows: ^2.2.0 + path_provider_ohos: + path: ../path_provider_ohos # Added here. + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + plugin_platform_interface: ^2.0.0 + test: ^1.16.0 +``` + +## 8. Running the Example + +### 1. Sign. + +Use Deveco Studio to open the `example > ohos` directory of the third-party library. + +Select `Automatically generate signature` in `File > Project Structure > Project > Signing Configs`, wait until the signature is complete, and click `OK`. + +![image-20240410105254011](../media/07_1/14_Signature.png) + +### 2. Run. + +Execute **cd** to switch to the `path_provider_ohos\example > ohos` directory and execute the following instructions: + +`flutter pub get` + +`flutter run -d ` + +**The figure below shows the effect.** + +![image-20240410105254011](../media/07_1/15_Successful_effect.png) + + \ No newline at end of file diff --git a/ohos/docs/08_FAQ/README.md b/ohos/docs/08_FAQ/README.md index f0d281190d6875ab78694f7eaad468651843bc1c..afb181b55600df3ea0631857aa8d8857e1db314b 100644 --- a/ohos/docs/08_FAQ/README.md +++ b/ohos/docs/08_FAQ/README.md @@ -2,13 +2,13 @@ 整理flutter鸿蒙化开发过程中的常见问题 -1. [环境相关问题](./environment.md) -2. [ohos引擎产物编译相关问题](./ohos_engine.md) -3. [ohos应用编译相关问题](./ohos_hap.md) -4. [ohos代码开发相关问题](./ohos_code.md) -5. [ohos运行相关问题](./ohos_run.md) +1. [环境相关问题](./环境相关问题.md) +2. [ohos引擎产物编译相关问题](./ohos引擎产物编译相关问题.md) +3. [ohos应用编译相关问题](./ohos应用编译相关问题.md) +4. [ohos代码开发相关问题](./ohos代码开发相关问题.md) +5. [ohos运行相关问题](./ohos运行相关问题.md) 6. [功能开发相关问题](../04_development/README.md) -7. [解析flutter相关的cppcrash堆栈](./flutter_cppcrash_guideline.md) +7. [解析flutter相关的cppcrash堆栈](./解析flutter相关的cppcrash堆栈.md) ## flutter鸿蒙化应用相关问题反馈的关键信息模板 diff --git a/ohos/docs/08_FAQ/README_EN.md b/ohos/docs/08_FAQ/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..258e208cdd4f4f22d9cfb1261b958ecfaca08d13 --- /dev/null +++ b/ohos/docs/08_FAQ/README_EN.md @@ -0,0 +1,48 @@ +# FAQs + +You can refer to FAQs related to the following aspects during HarmonyOS Flutter development. + +1. [Environment](./environment.md) +2. [ohos Engine Product Compilation](./ohos-engine-product-compilation.md) +3. [ohos Application Compilation](./ohos-application-compilation.md) +4. [ohos Code Development](./ohos-code.md) +5. [ohos Program Running](./ohos-run.md) +6. [ohos Development](../04_development/README.md) +7. [Parsing Flutter-Related CppCrash Stacks](./flutter-cppcrash-guideline.md) + +## Key Information Template for Feedback on Questions Related to HarmonyOS Flutter Application + +1. IDE version number. Example: + 1. DevEco Studio 5.0.3.300 +2. Device name and system version number of the HarmonyOS device or emulator. You can check them in **Settings** > **About phone**. Example: + 1. HUAWEI Mate 60 Pro, 3.0.0.22(SP81xxxxxx) + 2. Emulator, 3.0.0.22(SP39xxxxxx) +3. Information about the Flutter runtime environment. Example: + 1. `flutter docotr -v` +4. Flutter building or running instructions. Example: + 1. `flutter build hap --debug` + 2. `flutter run -d $DEVICE --debug` +5. Log files. + 1. Building or running logs. Example: + 1. `flutter build hap --debug > build.log 2>&1` + 2. `flutter run -d $DEVICE --debug > run.log 2>&1` + 2. **hilog** file. + 1. Export the `hdc hilog > hilog.log 2>&1` file by using instructions. + 2. The `hdc` tool is stored in the **toolchains** directory of the HamonyOS SDK. + 3. Log files recording crashes. + 1. You can obtain the log file from DevEco Studio. Steps: **DevEco Studio** > **Log** > **FaultLog** > **app bundle name** > **cppcrash/jscrash** > **Time** > **Right-click to export the log files**. + +## --local-engine Parameters + +In **flutter_flutter** of a version later than ecd66426679c18f86a285a1ac6aa605900dcb63a (20:00:49, June 6, 2024, UTC+8), the `--local-engine` parameter is optional and may not be passed. + +## Providing a Demo That Can Be Reproduced + +When providing a demo, you can execute **git** to delete unnecessary files to reduce the size of the application package. + +```sh +git init +git add -A +git commit -m "init" +git clean -dfx +``` diff --git a/ohos/docs/08_FAQ/environment.md b/ohos/docs/08_FAQ/environment.md index 7fcae016e70713dc7cd65e8d4c396583781a02c9..7ad8dfb33bffbca449ea4148897b8edf84e5ab14 100644 --- a/ohos/docs/08_FAQ/environment.md +++ b/ohos/docs/08_FAQ/environment.md @@ -1,10 +1,10 @@ -# 环境相关问题 +# Environment -flutter开发环境配置参考 https://gitee.com/openharmony-sig/flutter_flutter +For details about how to set up the Flutter development environment, see https://gitee.com/openharmony-sig/flutter_flutter/blob/master/README_EN.md -## 建议使用的开发工具版本 +## Recommended Development Tools and Their Versions -### flutter 3.7.12-ohos 版本 +### Flutter 3.7.12-ohos 1. python3.8 - python3.11 2. java17 @@ -13,101 +13,96 @@ flutter开发环境配置参考 https://gitee.com/openharmony-sig/flutter_flutte 5. HamonyOS SDK api11 6. Xcode14.3 -## 断网环境 flutter pub get 执行失败 +## Failure in Running flutter pub get in an Offline Environment -解决方案: -加上 --offline 参数,完整命令 `flutter pub get --offline` +Solution: -## mac环境release版本的应用编译失败 +Add the **--offline** parameter. Complete instruction: `flutter pub get --offline`. -报错日志: +## Failure in Building an Application of the Release Version in the macOS Environment + +Error log: ```log -ProcessPackageException: ProcessException: Found candidates, but lacked sufficient permissions to excute "/Users/xxx/ohos/src/out/ohos_release_arm64/clang_arm4/dart". +ProcessPackageException: ProcessException: Found candidates, but lacked sufficient permissions to execute "/Users/xxx/ohos/src/out/ohos_release_arm64/clang_arm4/dart". Command: /Users/xxx/ohos/src/out/ohos_release_arm64/clang_arm4/dart ``` -解决方案:添加执行权限 +Solution: + +Add the execution permission. ```sh chmod -R +x /Users/xxx/ohos/src/out/ohos_release_arm64/* ``` -mac环境可能还需要手动点击 src/out/ohos_release_arm64/clang_arm64 目录下的 `dart` 和 `gen_snapshot`,并在「设置->隐私与安全->安全性」中允许程序运行。 +In the macOS environment, you may need to manually click `dart` and `gen_snapshot` in the **src/out/ohos_release_arm64/clang_arm64** directory and allow the application to run in **Settings** > **Privacy and Security** > **Security**. -## flutter从Windows复制到linux或mac环境后无法运行 +## Failure in Running a Flutter Program That Is Copied from Windows to Linux or macOS -报错日志: +Error log: ```log curl: (3) Illegal characters found in URL xxx/flutter_flutter/bin/internal/update_dart_sdk.sh: line 156: return: can only return from a function or sourced script curl: (3) Illegal characters found in URL ``` -问题分析:Windows上的换行符和linux/mac不一致导致的。 +Problem analysis: -解决方案: +The newline character on Windows is inconsistent with that on Linux or macOS. + +Solution: ```sh -# 将文件 target_file 中的换行符由 CRLF(\r\n)替换为 LF(\n) +# Replace the newline character in the target_file from CRLF (\r\n) to LF (\n). sed -i "s/\r//" target_file -# 将 bin/dart、bin/*.sh 和 bin/internal/*.version 中的换行符换位LF +# Replace the newline characters in bin/dart, bin/*.sh, and bin/internal/*.version with LF. cd flutter -## linux环境执行 +## Execute the following instruction in the Linux environment: sed -i "s/\r//" bin/dart $(find bin -name "*.sh") $(find bin -name "*.version") -## mac环境执行 +## Execute the following instruction in the macOS environment: sed -i "" "s/\r//" bin/dart $(find bin -name "*.sh") $(find bin -name "*.version") ``` -## ~/.npmrc 的配置 +## Configuring ~/.npmrc ```sh registry=https://repo.huaweicloud.com/repository/npm/ @ohos:registry=https://repo.harmonyos.com/npm/ strict-ssl=false -# 设置代理 +# Set a proxy. # http_proxy=http://user:password@host:8080 # https_proxy=http://user:password@host:8080 ``` -## ~/.ohpmrc 的配置 +## Configuring ~/.ohpmrc ```sh registry=https://repo.harmonyos.com/ohpm/ strict_ssl=false -# 设置代理 +# Set a proxy. # http_proxy=http://user:password@host:8080 # https_proxy=http://user:password@host:8080 ``` -## 模拟器运行默认计数器应用闪退 - -问题分析: +## Default Counter Application Crashes When Running in the Emulator -- FloatingActionButton 在模拟器上不支持,需要在 lib/main.dart 中注释 FloatingActionButton 后再运行到模拟器上。 -- [模拟器与真机的差异](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-emulator-specification-0000001839876358-V5) +Problem analysis: -## [ios][release] GeneratedPluginRegistrant.m Module not found +- **FloatingActionButton** is not supported by the emulator. You need to comment out **FloatingActionButton** in **lib/main.dart** before running the application on the emulator. +- Reference: [Differences Between the Emulator and Real Device](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-emulator-specification-0000001839876358-V5). -问题分析:pubspec.yaml 中新增了flutter插件,但是 Podfile 中没有新增插件相关的pod引用。 +## [ios][release] GeneratedPluginRegistrant.m Module Not Found -解决方案:`rm ios/podfile && flutter clean && flutter run -d ` +Problem analysis: -参考链接:[GeneratedPluginRegistrant.m Module not found](https://github.com/flutter/flutter/issues/43986) +A Flutter plugin is added to the **pubspec.yaml** file, but the **pod** reference related to the plugin does not exist in the **Podfile**. -## 【Windows】 flutter doctor -v 无反应 +Solution: -现象: 配置好环境变量后,执行flutter doctor -v没有反应 +Run the instruction `rm ios/podfile && flutter clean && flutter run -d `. -原因: 可能是没有配置好代理 +Reference: -解决: -- 在系统环境变量中配置http_proxy, https_proxy, no_proxy环境变量 -- http_proxy参考deveco代理配置 -- https_proxy可以等于http_proxy -- no_proxy参考deveco代理配置外,还需要添加 - - localhost - - ::1 - - 127.0.0.1 +[GeneratedPluginRegistrant.m Module not found](https://github.com/flutter/flutter/issues/43986) -执行结果有Flutter和HarmonyOS(表明基础环境配置正确,这两个平台均被支持) -![](../media/08/error.png) + \ No newline at end of file diff --git a/ohos/docs/08_FAQ/flutter-cppcrash-guideline.md b/ohos/docs/08_FAQ/flutter-cppcrash-guideline.md new file mode 100644 index 0000000000000000000000000000000000000000..a4b4b9684028357cbdedc1242bca504ac2a9c9b9 --- /dev/null +++ b/ohos/docs/08_FAQ/flutter-cppcrash-guideline.md @@ -0,0 +1,88 @@ +# Parsing Flutter-Related CppCrash Stacks + +This document introduces how to parse crash stacks related to the `libflutter.so` library in the Flutter-for-OpenHarmony environment. + +## 1. Introduction + +The `llvm-addr2line` tool can convert instruction addresses and executable images into file names, function names, and corresponding source code line numbers. It is typically used on `.so` libraries that contain symbol information. + +## 2. Tool Location + +The `llvm-addr2line` tool is included in the SDK directory of both **DevEco Studio** and **Command Line Tools for HarmonyOS**. The paths are as follows: + +- Windows: `sdk/default/openharmony/native/llvm/bin/llvm-addr2line.exe` +- Linux/Mac: `sdk/default/openharmony/native/llvm/bin/llvm-addr2line` + +You can add the `llvm-addr2line` directory to your `PATH` environment variable, for example: + +```sh +export PATH=/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/native/llvm/bin:$PATH +``` + +## 3. Usage Command + +```sh +llvm-addr2line -f -e so.unstripped/libflutter.so [addr1] [addr2] +``` + +## 4. Obtaining a libflutter.so with Symbols + +### 4.1 Using Locally Compiled Engine Artifacts + +- Debug version: + `src/out/ohos_debug_unopt_arm64/so.unstripped/libflutter.so` + +- Release version: + `src/out/ohos_release_arm64/so.unstripped/libflutter.so` + +- Profile version: + `src/out/ohos_profile_arm64/so.unstripped/libflutter.so` + +### 4.2 Downloading from Cloud Artifacts + +- Find the `flutter_engine` commit ID used by the current `flutter_flutter` version. This can be found in the `flutter_flutter/bin/internal/engine.ohos.version` file. + +- For the commit ID `8ef94277f0029e61ff6a96f630d0f10b60330cd8`, you can download the corresponding version of `libflutter.so` as a zip file from: + + - Debug version: + [https://flutter-ohos.obs.cn-south-1.myhuaweicloud.com/flutter_infra_release/flutter/8ef94277f0029e61ff6a96f630d0f10b60330cd8/ohos-arm64/symbols.zip](https://flutter-ohos.obs.cn-south-1.myhuaweicloud.com/flutter_infra_release/flutter/8ef94277f0029e61ff6a96f630d0f10b60330cd8/ohos-arm64/symbols.zip) + + - Release version: + [https://flutter-ohos.obs.cn-south-1.myhuaweicloud.com/flutter_infra_release/flutter/8ef94277f0029e61ff6a96f630d0f10b60330cd8/ohos-arm64-release/symbols.zip](https://flutter-ohos.obs.cn-south-1.myhuaweicloud.com/flutter_infra_release/flutter/8ef94277f0029e61ff6a96f630d0f10b60330cd8/ohos-arm64-release/symbols.zip) + + - Profile version: + [https://flutter-ohos.obs.cn-south-1.myhuaweicloud.com/flutter_infra_release/flutter/8ef94277f0029e61ff6a96f630d0f10b60330cd8/ohos-arm64-profile/symbols.zip](https://flutter-ohos.obs.cn-south-1.myhuaweicloud.com/flutter_infra_release/flutter/8ef94277f0029e61ff6a96f630d0f10b60330cd8/ohos-arm64-profile/symbols.zip) + +## 5. Example Usage + +Below is an example of a partial crash log related to `libflutter.so`: + +```log +#00 pc 00000000001b5a34 /system/lib/ld-musl-aarch64.so.1(__timedwait_cp+188)(ef860a9c8bd64e964a4dd4ef838876e1) +#01 pc 00000000001b7a3c /system/lib/ld-musl-aarch64.so.1(__pthread_cond_timedwait+188)(ef860a9c8bd64e964a4dd4ef838876e1) +#02 pc 000000000021d450 /data/storage/el1/bundle/libs/arm64/libflutter.so(85c51e03a4f191b946582701e79e1be4a0c83959) +#03 pc 00000000001f21f4 /data/storage/el1/bundle/libs/arm64/libflutter.so(85c51e03a4f191b946582701e79e1be4a0c83959) +``` + +After obtaining the symbolized file `so.unstripped/libflutter.so`, you can convert the addresses in the crash stack to specific code lines. + +Run the command: + +```sh +llvm-addr2line -f -e so.unstripped/libflutter.so 00000000001b5a34 00000000001b7a3c 000000000021d450 00000000001f21f4 +``` + +The parsed result might look like this: + +```log +_ZNSt21_LIBCPP_ABI_NAMESPACE21__libcpp_condvar_waitB6v15004EP14pthread_cond_tP15pthread_mutex_t +/home/hazy/tools/ohos-v5.0.3.900/command-line-tools/sdk/default/openharmony/native/llvm/include/c++/v1/__threading_support:335 +_ZN7flutter16PlatformViewOHOS13NotifyChangedERK7SkISize +/home/hazy/work/engine_build/engine_daily/src/out/ohos_release_arm64/../../flutter/shell/platform/ohos/platform_view_ohos.cpp:192 +``` + +## Additional Resources + +- [Analyzing CppCrash](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/cppcrash-guidelines-V5) +- [flutter_flutter](https://gitee.com/openharmony-sig/flutter_flutter) +- [flutter_engine](https://gitee.com/openharmony-sig/flutter_engine) diff --git a/ohos/docs/08_FAQ/ohos-application-compilation.md b/ohos/docs/08_FAQ/ohos-application-compilation.md new file mode 100644 index 0000000000000000000000000000000000000000..ebed06910b27e5880b0900599ee5ed9e6475d681 --- /dev/null +++ b/ohos/docs/08_FAQ/ohos-application-compilation.md @@ -0,0 +1,125 @@ +# ohos Application Compilation + +## Configure aliases to simplify compilation instructions during routine development. + +Configure aliases in the configuration file of the environment variables to simplify the instructions used for HarmonyOS Flutter. + +- For Windows, use `Git Bash` to execute common Linux instructions. (How to use: Right-click the blank area in the file manager and choose **Git Bash Here** from the shortcut menu.) +- For Linux, modify `~/.bash_profile`. +- For macOS, modify `~/.bash_profile` and add `source ~/.bash_profile` to `~/.zshrc`. + +```sh +# --The --local-engine parameter is optional and points to the self-compiled engine product. You are advised to use this parameter in the Linux or macOS environment. +export ENGINE_DIR=~/ohos/engine +export ENGINE_DEBUG=$ENGINE_DIR/src/out/ohos_debug_unopt_arm64 +export ENGINE_PROFILE=$ENGINE_DIR/src/out/ohos_profile_arm64 +export ENGINE_RELEASE=$ENGINE_DIR/src/out/ohos_release_arm64 + +alias fbuildD="flutter build hap --local-engine=$ENGINE_DEBUG --debug" +alias fbuildP="flutter build hap --local-engine=$ENGINE_PROFILE --profile" +alias fbuildR="flutter build hap --local-engine=$ENGINE_RELEASE --release" +alias frunD="flutter run -d $(hdc list targets) --local-engine=$ENGINE_DEBUG --debug" +alias frunP="flutter run -d $(hdc list targets) --local-engine=$ENGINE_PROFILE --profile" +alias frunR="flutter run -d $(hdc list targets) --local-engine=$ENGINE_RELEASE --release" +``` + +How to use: + +After the configuration, reopen the terminal window. Now you can use the aliases when compiling or running the project. + +```sh +flutter create hello --platforms ohos +cd hello +# Compile the debug version. +fbuildD +# Run the debug version. +frunD +``` + +## White screen occurs after the application is compiled and installed. + +Error log: + +```log +Reason:Signal:SIGSEGV(SEGV_MAPERR)@0x00000086e3272bf8 +LastFatalMessage:Thread:547846269584[FATAL:flutter/runtime/dart_vm_initializer.cc] Error while initializing the Dart VM: Wrong full snapshot version, expected '8af474944053df1f0a3be6e6165fa7cf' found 'adb4292f3ec25074ca70abcd2d5c7251' +``` + +Problem analysis: + +Engine products mismatch the running mode, causing a white screen. + +Solution: + +In the running or compilation instructions, make sure the engine products match the running mode. Reference: + +```sh +flutter run -d --debug +flutter run -d --release +flutter run -d --profile +``` + +## A Flutter plugin before reconstruction uses the reconstructed plugin library, causing an error in compiling applications. + +Error log: + +```log +Oops; flutter has exited unexpectedly: "type 'Null' is not a subtype of type 'List' in type cast". +``` + +Solution: +Update **flutter_flutter** to the latest version of master or dev.(45bd5e627e1f1e5f4d335f205781565f576acc60, 2024-05-10) + +## Dependency conflicts are reported during the running of flutter pub get. + +Error log: + +```log +Resolving dependencies... +Because flutter_cache_manager >=3.0.0-nullsafety.0 <3.3.2 depends on path_provider from hosted and flutter_cache_manager depends on path_provider from git, flutter_cache_manager >=3.0.0-nullsafety.0 <3.3.2 forbidden. +So because xxx depends on flutter_cache_manager 3.3.1, version solving failed. +pub get failed +... +exit code: 1 +``` + +Solution: + +Use `dependency_overrides` to eliminate dependency conflicts. + +```yaml +dependencies: + flutter: + sdk: flutter +dependency_overrides: + path_provider: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + path: packages/path_provider/path_provider + path_provider_ohos: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + path: packages/path_provider/path_provider_ohos +``` + +## The SDK license agreement is not accepted. + +Error log: + +```log +hvigor install success. +> hvigor ERROR: Cause: The SDK license agreement is not accepted. +``` + +Problem analysis: + +The structure of the ohos project is in API version 11, but the SDK used is in API version 12. + +Solution: + +Upgrade the ohos project structure to API version 12. + +Steps: + +1. DevEco Studio -> Migrate Assistant -> 5.0.0 -> Migrate +2. DevEco Studio -> File -> Project Structure -> Compatible SDK -> 5.0.0(12) diff --git a/ohos/docs/08_FAQ/ohos-code.md b/ohos/docs/08_FAQ/ohos-code.md new file mode 100644 index 0000000000000000000000000000000000000000..74155f36a3e496aee628913093e010ad11147656 --- /dev/null +++ b/ohos/docs/08_FAQ/ohos-code.md @@ -0,0 +1,11 @@ +# ohos Code Development + +## Determining Whether the Current Platform is ohos in Dart Code + +```dart +import 'package:flutter/foundation.dart'; + +bool isOhos() { + return defaultTargetPlatform == TargetPlatform.ohos; +} +``` diff --git a/ohos/docs/08_FAQ/ohos-engine-product-compilation.md b/ohos/docs/08_FAQ/ohos-engine-product-compilation.md new file mode 100644 index 0000000000000000000000000000000000000000..c559546935aa951b5697a38903e1380466d37d58 --- /dev/null +++ b/ohos/docs/08_FAQ/ohos-engine-product-compilation.md @@ -0,0 +1,24 @@ +# ohos Engine Product Compilation + +For details about how to set up the Flutter engine environment, see https://gitee.com/openharmony-sig/flutter_engine/blob/master/README_EN.md. + +## Recommended Environment Configuration Version of the HarmonyOS Flutter Engine + +1. Python 3.8-3.11 (Error is reported in version 3.12.) +2. java 17 +3. DevEco-Studio / command-line-tools , 5.0.3.300+ + 1. ohpm, hvigorw, node, and HarmonyOS SDK are included. +4. Xcode14.3 + +## Generating flutter.har file + +1. After the engine product is built, the **flutter.har** file (src/out/ohos_debug_unopt_arm64/flutter.har) is generated. +2. Build the HAP file after copying the **libflutter.so** file (and **libvmservice_snapshot.so** file if in the profile mode) to the **flutter_embedding/flutter/ohos** directory. For details, see [Flutter Engine](https://gitee.com/openharmony-sig/flutter_engine/blob/master/README_EN.md#code-building-at-the-embedding-layer). + +## Debugging the Flutter Engine Using DevEco Studio + +Reference: + +[Debugging-the-engine](https://github.com/flutter/engine/blob/main/docs/Debugging-the-engine.md) + + \ No newline at end of file diff --git a/ohos/docs/08_FAQ/ohos-run.md b/ohos/docs/08_FAQ/ohos-run.md new file mode 100644 index 0000000000000000000000000000000000000000..0d852479062b2d96a4e43971c354e4728dc13c1d --- /dev/null +++ b/ohos/docs/08_FAQ/ohos-run.md @@ -0,0 +1,24 @@ +# ohos Program Running + + +## Runtime Error Occurring at /data/storage/el1/bundle/entry/ets/modules.abc After Compiling HarmonyOS + +Phenomenon: A runtime error occurs after compiling Flutter on HarmonyOS. + +Error message: + +``` +com.wit.appzoo_flutter_v2 is about to exit due to RuntimeError +Error type:ReferenceError +Error name:ReferenceError +Error message:cannot find record 'pkg_modules/.ohpm/connectivity_plus@fhy6p0gmf3puymhvkbu4hxvnutt4mn48tk2kirtanmi=/pkg_modules/connectivity_plus/index', please check the request path.'/data/storage/el1/bundle/entry/ets/modules.abc'. +Stacktrace: +SourceMap is not initialized yet +#00 pc 00000000005fcc0c /system/lib64/platformsdk/libark_jsruntime.so(5144aa99644b9dba57555adfb9e0ede6) +#01 pc 00000000005fd128 /system/lib64/platformsdk/libark_jsruntime.so(5144aa99644b9dba57555adfb9e0ede6) +#02 pc 00000000002ac540 /system/lib64/platformsdk/libark_jsruntime.so(5144aa99644b9dba57555adfb9e0ede6) +``` + +Possible causes: +The file /data/storage/el1/bundle/entry/ets/modules.abc may fail to run properly due to an SDK and image mismatch. The root cause is that the SDK tools and the image version are not aligned. It is recommended to use a matching SDK and mobile image version. Please provide the current mobile version and IDE version screenshots. +If the versions match, please provide the complete logs. diff --git a/ohos/docs/08_FAQ/ohos_code.md "b/ohos/docs/08_FAQ/ohos\344\273\243\347\240\201\345\274\200\345\217\221\347\233\270\345\205\263\351\227\256\351\242\230.md" similarity index 100% rename from ohos/docs/08_FAQ/ohos_code.md rename to "ohos/docs/08_FAQ/ohos\344\273\243\347\240\201\345\274\200\345\217\221\347\233\270\345\205\263\351\227\256\351\242\230.md" diff --git a/ohos/docs/08_FAQ/ohos_hap.md "b/ohos/docs/08_FAQ/ohos\345\272\224\347\224\250\347\274\226\350\257\221\347\233\270\345\205\263\351\227\256\351\242\230.md" similarity index 100% rename from ohos/docs/08_FAQ/ohos_hap.md rename to "ohos/docs/08_FAQ/ohos\345\272\224\347\224\250\347\274\226\350\257\221\347\233\270\345\205\263\351\227\256\351\242\230.md" diff --git a/ohos/docs/08_FAQ/ohos_engine.md "b/ohos/docs/08_FAQ/ohos\345\274\225\346\223\216\344\272\247\347\211\251\347\274\226\350\257\221\347\233\270\345\205\263\351\227\256\351\242\230.md" similarity index 100% rename from ohos/docs/08_FAQ/ohos_engine.md rename to "ohos/docs/08_FAQ/ohos\345\274\225\346\223\216\344\272\247\347\211\251\347\274\226\350\257\221\347\233\270\345\205\263\351\227\256\351\242\230.md" diff --git a/ohos/docs/08_FAQ/ohos_run.md "b/ohos/docs/08_FAQ/ohos\350\277\220\350\241\214\347\233\270\345\205\263\351\227\256\351\242\230.md" similarity index 100% rename from ohos/docs/08_FAQ/ohos_run.md rename to "ohos/docs/08_FAQ/ohos\350\277\220\350\241\214\347\233\270\345\205\263\351\227\256\351\242\230.md" diff --git "a/ohos/docs/08_FAQ/\347\216\257\345\242\203\347\233\270\345\205\263\351\227\256\351\242\230.md" "b/ohos/docs/08_FAQ/\347\216\257\345\242\203\347\233\270\345\205\263\351\227\256\351\242\230.md" new file mode 100644 index 0000000000000000000000000000000000000000..7fcae016e70713dc7cd65e8d4c396583781a02c9 --- /dev/null +++ "b/ohos/docs/08_FAQ/\347\216\257\345\242\203\347\233\270\345\205\263\351\227\256\351\242\230.md" @@ -0,0 +1,113 @@ +# 环境相关问题 + +flutter开发环境配置参考 https://gitee.com/openharmony-sig/flutter_flutter + +## 建议使用的开发工具版本 + +### flutter 3.7.12-ohos 版本 + +1. python3.8 - python3.11 +2. java17 +3. node18 +4. ohpm1.6+ +5. HamonyOS SDK api11 +6. Xcode14.3 + +## 断网环境 flutter pub get 执行失败 + +解决方案: +加上 --offline 参数,完整命令 `flutter pub get --offline` + +## mac环境release版本的应用编译失败 + +报错日志: +```log +ProcessPackageException: ProcessException: Found candidates, but lacked sufficient permissions to excute "/Users/xxx/ohos/src/out/ohos_release_arm64/clang_arm4/dart". + Command: /Users/xxx/ohos/src/out/ohos_release_arm64/clang_arm4/dart +``` + +解决方案:添加执行权限 + +```sh +chmod -R +x /Users/xxx/ohos/src/out/ohos_release_arm64/* +``` + +mac环境可能还需要手动点击 src/out/ohos_release_arm64/clang_arm64 目录下的 `dart` 和 `gen_snapshot`,并在「设置->隐私与安全->安全性」中允许程序运行。 + +## flutter从Windows复制到linux或mac环境后无法运行 + +报错日志: +```log +curl: (3) Illegal characters found in URL +xxx/flutter_flutter/bin/internal/update_dart_sdk.sh: line 156: return: can only return from a function or sourced script +curl: (3) Illegal characters found in URL +``` + +问题分析:Windows上的换行符和linux/mac不一致导致的。 + +解决方案: + +```sh +# 将文件 target_file 中的换行符由 CRLF(\r\n)替换为 LF(\n) +sed -i "s/\r//" target_file +# 将 bin/dart、bin/*.sh 和 bin/internal/*.version 中的换行符换位LF +cd flutter +## linux环境执行 +sed -i "s/\r//" bin/dart $(find bin -name "*.sh") $(find bin -name "*.version") +## mac环境执行 +sed -i "" "s/\r//" bin/dart $(find bin -name "*.sh") $(find bin -name "*.version") +``` + +## ~/.npmrc 的配置 + +```sh +registry=https://repo.huaweicloud.com/repository/npm/ +@ohos:registry=https://repo.harmonyos.com/npm/ +strict-ssl=false +# 设置代理 +# http_proxy=http://user:password@host:8080 +# https_proxy=http://user:password@host:8080 +``` + +## ~/.ohpmrc 的配置 + +```sh +registry=https://repo.harmonyos.com/ohpm/ +strict_ssl=false +# 设置代理 +# http_proxy=http://user:password@host:8080 +# https_proxy=http://user:password@host:8080 +``` + +## 模拟器运行默认计数器应用闪退 + +问题分析: + +- FloatingActionButton 在模拟器上不支持,需要在 lib/main.dart 中注释 FloatingActionButton 后再运行到模拟器上。 +- [模拟器与真机的差异](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-emulator-specification-0000001839876358-V5) + +## [ios][release] GeneratedPluginRegistrant.m Module not found + +问题分析:pubspec.yaml 中新增了flutter插件,但是 Podfile 中没有新增插件相关的pod引用。 + +解决方案:`rm ios/podfile && flutter clean && flutter run -d ` + +参考链接:[GeneratedPluginRegistrant.m Module not found](https://github.com/flutter/flutter/issues/43986) + +## 【Windows】 flutter doctor -v 无反应 + +现象: 配置好环境变量后,执行flutter doctor -v没有反应 + +原因: 可能是没有配置好代理 + +解决: +- 在系统环境变量中配置http_proxy, https_proxy, no_proxy环境变量 +- http_proxy参考deveco代理配置 +- https_proxy可以等于http_proxy +- no_proxy参考deveco代理配置外,还需要添加 + - localhost + - ::1 + - 127.0.0.1 + +执行结果有Flutter和HarmonyOS(表明基础环境配置正确,这两个平台均被支持) +![](../media/08/error.png) diff --git a/ohos/docs/08_FAQ/flutter_cppcrash_guideline.md "b/ohos/docs/08_FAQ/\350\247\243\346\236\220flutter\347\233\270\345\205\263\347\232\204cppcrash\345\240\206\346\240\210.md" similarity index 100% rename from ohos/docs/08_FAQ/flutter_cppcrash_guideline.md rename to "ohos/docs/08_FAQ/\350\247\243\346\236\220flutter\347\233\270\345\205\263\347\232\204cppcrash\345\240\206\346\240\210.md" diff --git a/ohos/docs/09_specifications/README.md b/ohos/docs/09_specifications/README.md index cfafa53e45c8291e05d24116e4819065430f11ff..5d1cc523f6463d1d13c1ef139957f617f33f59c5 100644 --- a/ohos/docs/09_specifications/README.md +++ b/ohos/docs/09_specifications/README.md @@ -1,4 +1,4 @@ # 规格说明 1. [flutter鸿蒙化工程的目录结构](./flutter鸿蒙化工程的目录结构.md) -2. [update_flutter_plugin_structure](./update_flutter_plugin_structure.md) +2. [update_flutter_plugin_structure](./更新Flutter插件项目结构.md) diff --git a/ohos/docs/09_specifications/README_EN.md b/ohos/docs/09_specifications/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..71eb11bcfc3d72c716b891e1d77d3205d36f7c2e --- /dev/null +++ b/ohos/docs/09_specifications/README_EN.md @@ -0,0 +1,5 @@ +# Specifications + +1. [Directory Structure of the HarmonyOS Flutter Project](./directory-structure-of-the-harmonyos-flutter-project.md) +2. [Updating the Flutter Plugin Structure](./update-flutter-plugi-structure.md) + diff --git a/ohos/docs/09_specifications/directory-structure-of-the-harmonyos-flutter-project.md b/ohos/docs/09_specifications/directory-structure-of-the-harmonyos-flutter-project.md new file mode 100644 index 0000000000000000000000000000000000000000..edcddc25321360d2e8200e9f92353bcf097b75d3 --- /dev/null +++ b/ohos/docs/09_specifications/directory-structure-of-the-harmonyos-flutter-project.md @@ -0,0 +1,20 @@ +# Directory Structure of the HarmonyOS Flutter Project + +## Key Files of the HarmonyOS Flutter Project + +1. Configuration files + 1. **ohos/AppScope/app.json5**, a project configuration file, contains the global configuration information of the application, including the bundle name, vendor, and version number of the application. + 2. **ohos/build-profile.json5**, a project configuration file. + 3. **ohos/oh-package.json5**, a project configuration file. + 4. **ohos/entry/build-profile.json5**, a module configuration file. + 5. **ohos/entry/oh-package.json5**, a module configuration file. + 6. **ohos/entry/src/main/module.json5**, a module configuration file, contains the basic configuration information of a module, including the module name, type, description, and supported device types. +2. Code files + 1. **ohos/entry/src/main/entryability/EntryAbility.ets**, an entry file of the application. + 2. **ohos/entry/src/main/pages/Index.ets**, the first page loaded by the application. + +## Outdated Directories or Files to Be Deleted + +1. **ohos/har/har_product/***, copied from the **flutter_flutter** template. +2. **ohos/har/flutter_embedding.har**, replaced by **ohos/har/flutter.har**. +3. **ohos/dta/icudtl.dat**, copied from the **flutter_flutter** template. diff --git a/ohos/docs/09_specifications/update-flutter-plugin-structure.md b/ohos/docs/09_specifications/update-flutter-plugin-structure.md new file mode 100644 index 0000000000000000000000000000000000000000..622600e6c250284c7209271e7eb1bb2d6c71395e --- /dev/null +++ b/ohos/docs/09_specifications/update-flutter-plugin-structure.md @@ -0,0 +1,204 @@ +# Updating the Flutter Plugin Structure + +## Update Details + +- In the **ohos** directory of the Flutter plugin project, the **project** structure is replaced with the **module** structure. +- The HAP files referenced in the Flutter project are stored in the **ohos/har** directory. +- Old module directory from the ohos plugin is deleted. + +## How to Update + +The following uses **integration_test** in [flutter_flutter](https://gitee.com/openharmony-sig/flutter_flutter/blob/master/README_EN.md) as an example. + +### 1. Changing the integration_test/ohos Directory from Project Structure to Module Structure + +```sh +cd flutter_flutter/packages/integration_test +mv ohos/ohos ./ohos2 +rm -rf ohos +mv ohos2 ohos +cd example +flutter pub get +flutter build hap --debug +``` + +An error is reported after executing the `flutter run` instruction. You need to modify the **name** field in the configuration file and the **hvigorfile.ts** file. + +### 2. Updating Code + +#### 2.1 Modify the integration_test/ohos/oh-package.json5 file. + +Before the modification: + +```json +{ + "name": "ohos", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.11" + } +} +``` + +After the modification: + +```json +{ + "name": "integration_test", // The name should be the same as the plugin name in the pubspec.yaml file. + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "Apache-2.0", + "dependencies": { + "@ohos/flutter_ohos": "file:har/flutter.har", + } +} +``` + +#### 2.2 Modify the integration_test/ohos/src/main/module.json5 file. + +Before the modification: + +```json +{ + "module": { + "name": "ohos", + "type": "har", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ] + } +} +``` + +After the modification: + +```json +{ + "module": { + "name": "integration_test", // The name should be the same as the plugin name in the pubspec.yaml file. + "type": "har", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ] + } +} +``` + +#### 2.3 Modify the integration_test/ohos/hvigorfile.ts file. + +Before the modification: + +```json +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. */ +} +``` + +After the modification: + +```json +export { harTasks } from '@ohos/hvigor-ohos-plugin'; +``` + +## Checking the Running Status + +1. Use DevEco Studio to open **integration_test/example** and configure the signature. +2. Execute the following instructions to run the example: + +``` +cd integration_test/example +flutter run -d $DEVICE --debug +``` + +### Paying Attention to the HAP File Reference in the Configuration File When Running the HarmonyOS Application + +The referenced HAP file is in the **ohos/har** directory. + +#### integration_test/example/ohos/oh-package.json5 + +After the modification: + +```json +{ + // ... + "dependencies": { + "@ohos/flutter_ohos": "file:./har/flutter.har" + }, + "overrides": { + "@ohos/flutter_ohos": "file:./har/flutter.har" + } +} +``` + +#### integration_test/example/ohos/entry/oh-package.json5 + +Before the modification: + +```json +{ + // ... + "dependencies": { + "@ohos/integration_test": "file:./har/integration_test.har", + } +} +``` + +After the modification: + +```json +{ + // ... + "dependencies": { + "integration_test": "file:../har/integration_test.har", + } +} +``` + +## Possible Errors + +### 1. no such file or directory + +Error Log: + +```log +hvigor ERROR: ENOENT: no such file or directory, stat 'xxx/flutter_flutter/packages/integration_test/ohos/build/default/cache/default/default@packageHar/ohos/oh_modules/@ohos/flutter_ohos' +``` + +![](../media/09/error1.jpg) + +Solution: + +Manually delete the file reported in the log message. + +### 2. operation not permitted, symlink + +Error Log: + +```log +hvigor ERROR: ENOENT: operation not permitted, symlink +'xxx/webview_flutter_ohos/ohos/webview_flutter/oh_modules/.ohpm/@ohos+flutter_ohos@file+libs+flutter.har/oh_modules/@ohos/flutter_ohos' -> +'xxx/webview_flutter_ohos/ohos/build/default/cache/default/default@PackageHar/webview_flutter/oh_modules/@ohos/flutter_ohos' +``` + +Solution: + +After the code is updated, manually delete some directories that exist before the HAP reconstruction. Example: + +1. flutter_packages/packages/webview_flutter_ohos/ohos/webview_flutter +2. flutter_packages/packages/path_provider_ohos/ohos/path_provider +3. flutter_packages/packages/file_selector_ohos/ohos/FileSelector diff --git a/ohos/docs/09_specifications/update_flutter_plugin_structure.md "b/ohos/docs/09_specifications/\346\233\264\346\226\260Flutter\346\217\222\344\273\266\351\241\271\347\233\256\347\273\223\346\236\204.md" similarity index 100% rename from ohos/docs/09_specifications/update_flutter_plugin_structure.md rename to "ohos/docs/09_specifications/\346\233\264\346\226\260Flutter\346\217\222\344\273\266\351\241\271\347\233\256\347\273\223\346\236\204.md" diff --git a/ohos/docs/10_appendix/README_EN.md b/ohos/docs/10_appendix/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..169717704c6f920b3b05e4b807077565486ae2e8 --- /dev/null +++ b/ohos/docs/10_appendix/README_EN.md @@ -0,0 +1,3 @@ +# Appendix + + diff --git a/ohos/docs/README_EN.md b/ohos/docs/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..672f56d6e607f11f265c5be584c7bfc333827c16 --- /dev/null +++ b/ohos/docs/README_EN.md @@ -0,0 +1,11 @@ +# Documentation Entry + +1. [Framework](./01_framework/README_EN.md) +2. [Architecture](./02_architecture/README_EN.md) +3. [Environment Setup](./03_environment/README_EN.md) +4. [Function Development](./04_development/README_EN.md) +5. [Performance Tuning](./05_performance/README_EN.md) +6. [Debugging](./06_debug/README_EN.md) +7. [Third-Party Library Access](./07_plugin/README_EN.md) +8. [FAQs](./08_FAQ/README_EN.md) +9. [Specifications](./09_specifications/README_EN.md) diff --git a/ohos/docs/media/03_1/doctor1_EN.png b/ohos/docs/media/03_1/doctor1_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..0a3383b8f8a9b99e193b3023d275fe301edeaf26 Binary files /dev/null and b/ohos/docs/media/03_1/doctor1_EN.png differ diff --git a/ohos/docs/media/03_1/img00_EN.png b/ohos/docs/media/03_1/img00_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..e20b7d3c0eb8b59acbd79174afad4076a8f8bb99 Binary files /dev/null and b/ohos/docs/media/03_1/img00_EN.png differ diff --git a/ohos/docs/media/03_1/img9_EN.png b/ohos/docs/media/03_1/img9_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..d9657125d35db13e7b613340f649bcc2f8b240a6 Binary files /dev/null and b/ohos/docs/media/03_1/img9_EN.png differ diff --git a/ohos/docs/media/03_1/img_10_EN.png b/ohos/docs/media/03_1/img_10_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..cea977d1a13c47585eccfb70e776270806f25ed2 Binary files /dev/null and b/ohos/docs/media/03_1/img_10_EN.png differ diff --git a/ohos/docs/media/03_1/img_17_EN.png b/ohos/docs/media/03_1/img_17_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..b62a41f1f84242bfb4b5cf4d1abc9911b176270b Binary files /dev/null and b/ohos/docs/media/03_1/img_17_EN.png differ diff --git a/ohos/docs/media/03_1/img_18_1_EN.png b/ohos/docs/media/03_1/img_18_1_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..9f939e59b6945cd4fd3283f6c67509b8df7a79f4 Binary files /dev/null and b/ohos/docs/media/03_1/img_18_1_EN.png differ diff --git a/ohos/docs/media/03_1/img_18_2_EN.png b/ohos/docs/media/03_1/img_18_2_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..09229f8c7b8b57ed3994337e3e9a4b2c5b51d358 Binary files /dev/null and b/ohos/docs/media/03_1/img_18_2_EN.png differ diff --git a/ohos/docs/media/03_1/img_18_3_EN.png b/ohos/docs/media/03_1/img_18_3_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..8e7fa9eb435aee902c6a5cd94941be6d8fd9225e Binary files /dev/null and b/ohos/docs/media/03_1/img_18_3_EN.png differ diff --git a/ohos/docs/media/03_1/img_18_4_EN.png b/ohos/docs/media/03_1/img_18_4_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..f910c4cbb11a725d0a6d7b86c1dcace4797cc511 Binary files /dev/null and b/ohos/docs/media/03_1/img_18_4_EN.png differ diff --git a/ohos/docs/media/03_1/img_4_EN.png b/ohos/docs/media/03_1/img_4_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..df2a1caf81260a263afc2980522cf5c1a04fb73a Binary files /dev/null and b/ohos/docs/media/03_1/img_4_EN.png differ diff --git a/ohos/docs/media/03_1/m1_EN.png b/ohos/docs/media/03_1/m1_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..0a6a59698b1e17ddf63f65f77ebdb7cc6f4babdb Binary files /dev/null and b/ohos/docs/media/03_1/m1_EN.png differ diff --git a/ohos/docs/media/03_1/m2_EN.png b/ohos/docs/media/03_1/m2_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..d7bf19a736efbe7d1305f965405929abadfb1afb Binary files /dev/null and b/ohos/docs/media/03_1/m2_EN.png differ diff --git a/ohos/docs/media/03_1/m3_EN.png b/ohos/docs/media/03_1/m3_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..b1058efac1eb71a5ce7132256e6559ca28ddcdd8 Binary files /dev/null and b/ohos/docs/media/03_1/m3_EN.png differ diff --git a/ohos/docs/media/04_1/614df503f2164dd4e4a4b4a5e5bc9c87_EN.png b/ohos/docs/media/04_1/614df503f2164dd4e4a4b4a5e5bc9c87_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..769b5cbd8a68594a832ac5d4e6405863b5a27f9c Binary files /dev/null and b/ohos/docs/media/04_1/614df503f2164dd4e4a4b4a5e5bc9c87_EN.png differ diff --git a/ohos/docs/media/04_1/e68f5cbb2f98dca205bf51d6ab53ad09_EN.png b/ohos/docs/media/04_1/e68f5cbb2f98dca205bf51d6ab53ad09_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..8c83144b80ae011721db175a37d80a040883ca10 Binary files /dev/null and b/ohos/docs/media/04_1/e68f5cbb2f98dca205bf51d6ab53ad09_EN.png differ diff --git a/ohos/docs/media/05/image-2-201_EN.png b/ohos/docs/media/05/image-2-201_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..3914bdd6c31bb10a2bca2736f9eb4e38e74569c3 Binary files /dev/null and b/ohos/docs/media/05/image-2-201_EN.png differ diff --git a/ohos/docs/media/05/image-3-201_EN.png b/ohos/docs/media/05/image-3-201_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..6487c5ce5d8ca66ded9330a8aba8c5ecdeb94eb3 Binary files /dev/null and b/ohos/docs/media/05/image-3-201_EN.png differ