diff --git a/README-zh_CN.md b/README-zh_CN.md index 34c14bc..8ba7457 100644 --- a/README-zh_CN.md +++ b/README-zh_CN.md @@ -355,6 +355,8 @@ Compose 源码 } ``` + 接下来在DevEco Studio中构建鸿蒙应用,安装到真机/模拟器运行。也可以在 composeApp 中执行 `startHarmonyAppDebug` 或 `startHarmonyAppRelease` gradle任务,完成整个kotlin项目构建,复制产物,鸿蒙项目构建,发送真机/模拟器运行流程。 + ### 在Compose中使用ArkUI ovCompose可与ArkUI框架混排。您可以将 Compose Multiplatform 嵌入到 ArkUI 应用中,也可以将原生 ArkUI diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 9fbb36d..1ac14eb 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -140,3 +140,117 @@ arrayOf("debug", "release").forEach { type -> } } } + +arrayOf("debug", "release").forEach { type -> + + tasks.register("startHarmonyApp${type.capitalizeUS()}") { + group = "harmony" + dependsOn("link${type.capitalizeUS()}SharedOhosArm64") + + // Disable configuration cache for this task + notCompatibleWithConfigurationCache("Uses project.exec and file() at execution time") + + // Move problematic property evaluations to doLast to avoid configuration cache issues + val harmonyAppDir: String by project + val absoluteHarmonyAppDir = if (File(harmonyAppDir).isAbsolute) harmonyAppDir else + rootProject.file(harmonyAppDir).absolutePath + + into(rootProject.file(absoluteHarmonyAppDir)) + from("build/bin/ohosArm64/${type}Shared/libkn_api.h") { + into("entry/src/main/cpp/include/") + } + from(project.file("build/bin/ohosArm64/${type}Shared/libkn.so")) { + into("entry/libs/arm64-v8a/") + } + + outputs.upToDateWhen { false } + doLast { + val appJsonContent = file("$absoluteHarmonyAppDir/AppScope/app.json5").readText() + val bundleNameRegex = """"bundleName"\s*:\s*"([^"]+)"""".toRegex() + val bundleName = bundleNameRegex.find(appJsonContent)?.groupValues?.get(1) ?: error("bundleName not found") + val devEcoStudioDir: String by project + val harmonyAppEntryModuleDir: String by project + val hFileDir: String by project + val soFileDir: String by project + val abilityName: String by project + val nodeHome = "$devEcoStudioDir/Contents/tools/node" + val devEcoSdkHome = "$devEcoStudioDir/Contents/sdk" + + if (!File(devEcoStudioDir).exists()) { + throw GradleException("Provided DevEco Studio install path doesn't exist: $devEcoStudioDir") + } + fun execAtHarmonyAppDir(cmd: List) { + val result = project.exec { + environment(mapOf("NODE_HOME" to nodeHome, "DEVECO_SDK_HOME" to devEcoSdkHome)) + commandLine(cmd) + workingDir(absoluteHarmonyAppDir) + isIgnoreExitValue = true + } + if (result.exitValue != 0) { + throw GradleException("${cmd.joinToString(" ")}\nFailed with exit code ${result.exitValue}\nTry to reproduce this in DevEco Studio's command line, otherwise you would need to setup some enviroment parameters") + } + } + + println("=== Step 1: Install OHPM dependencies ===") + execAtHarmonyAppDir(listOf( + "$devEcoStudioDir/Contents/tools/ohpm/bin/ohpm", + "install", + "--all", + "--registry", + "https://ohpm.openharmony.cn/ohpm/", + "--strict_ssl", + "true" + )) + + println("=== Step 2: Run hvigor sync ===") + execAtHarmonyAppDir(listOf( + "$devEcoStudioDir/Contents/tools/node/bin/node", + "$devEcoStudioDir/Contents/tools/hvigor/bin/hvigorw.js", + "--sync", + "-p", "product=default", + "-p", "buildMode=${type}", + "--analyze=false", + "--parallel", + "--incremental", + "--daemon" + )) + + println("=== Step 3: Build HAP ===") + execAtHarmonyAppDir(listOf( + "$devEcoStudioDir/Contents/tools/node/bin/node", + "$devEcoStudioDir/Contents/tools/hvigor/bin/hvigorw.js", + "--mode", "module", + "-p", "module=entry@default", + "-p", "product=default", + "-p", "buildMode=${type}", + "-p", "requiredDeviceType=phone", + "assembleHap", + "--analyze=false", + "--parallel", + "--incremental", + "--daemon" + )) + + println("=== Step 4: Install HAP to device via hdc ===") + val hapFolder = File("$absoluteHarmonyAppDir/$harmonyAppEntryModuleDir/build/default/outputs/default/") + val hapFile = File(hapFolder, "entry-default-signed.hap").takeIf { it.exists() } ?: File(hapFolder, "entry-default-unsigned.hap") + + execAtHarmonyAppDir(listOf( + "$devEcoStudioDir/Contents/sdk/default/openharmony/toolchains/hdc", + "install", + hapFile.absolutePath + )) + + println("=== Step 5: Launch app on device ===") + println("Ability: $abilityName, Bundle: $bundleName") + execAtHarmonyAppDir(listOf( + "$devEcoStudioDir/Contents/sdk/default/openharmony/toolchains/hdc", + "shell", + "aa", + "start", + "-a", abilityName, + "-b", bundleName + )) + } + } +} diff --git a/gradle.properties b/gradle.properties index 964007c..c948440 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,18 @@ org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 #Android android.nonTransitiveRClass=true -android.useAndroidX=true \ No newline at end of file +android.useAndroidX=true + +# Settings for startHarmonyApp gradle task +# DevEco Studio install path +devEcoStudioDir=/Applications/DevEco-Studio.app +# harmony project root folder, absolute path or relative to this project root +harmonyAppDir=harmonyApp +# Folder name of entry module in harmony app +harmonyAppEntryModuleDir=entry/ +# Where header artifact of kotlin project should go +hFileDir=src/main/cpp/include/ +# Where so artifact of kotlin project should go +soFileDir=libs/arm64-v8a/ +# The ability to start, click run in DevEco Studio, this comes after 'hdc shell aa start -a' in run log +abilityName = EntryAbility diff --git a/harmonyApp/entry/.gitignore b/harmonyApp/entry/.gitignore index e2713a2..51e3e7b 100644 --- a/harmonyApp/entry/.gitignore +++ b/harmonyApp/entry/.gitignore @@ -1,3 +1,4 @@ +/libs/arm64-v8a/ /node_modules /oh_modules /.preview diff --git a/harmonyApp/entry/libs/arm64-v8a/libkn.so b/harmonyApp/entry/libs/arm64-v8a/libkn.so deleted file mode 100755 index c378e8b..0000000 Binary files a/harmonyApp/entry/libs/arm64-v8a/libkn.so and /dev/null differ