Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .github/ci/build/build_hmos.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// -*- mode: groovy -*-
// vim: set filetype=groovy :
@Library('agora-build-pipeline-library') _

buildUtils = new agora.build.BuildUtils()

compileConfig = [
"sourceDir": "api-examples",
"non-publish": [
"command": "./.github/ci/build/build_hmos.sh",
"extraArgs": "",
],
"publish": [
"command": "./.github/ci/build/build_hmos.sh",
"extraArgs": "",
]
]

def doBuild(buildVariables) {
type = params.Package_Publish ? "publish" : "non-publish"
command = compileConfig.get(type).command
preCommand = compileConfig.get(type).get("preCommand", "")
postCommand = compileConfig.get(type).get("postCommand", "")
extraArgs = compileConfig.get(type).extraArgs
extraArgs += " " + params.getOrDefault("extra_args", "")
commandConfig = [
"command": command,
"sourceRoot": "${compileConfig.sourceDir}",
"extraArgs": extraArgs
]
loadResources(["config.json", "artifactory_utils.py"])
buildUtils.customBuild(commandConfig, preCommand, postCommand)
}

def doPublish(buildVariables) {
if (!params.Package_Publish) {
return
}

(shortVersion, releaseVersion) = buildUtils.getBranchVersion()
def archiveInfos = [
[
"type": "ARTIFACTORY",
"archivePattern": "*.zip",
"serverPath": "ApiExample/${shortVersion}/${buildVariables.buildDate}/${env.platform}",
"serverRepo": "SDK_repo"
],
[
"type": "ARTIFACTORY",
"archivePattern": "*.hap",
"serverPath": "ApiExample/${shortVersion}/${buildVariables.buildDate}/${env.platform}",
"serverRepo": "SDK_repo"
]
]
def archiveUrls = (archive.archiveFiles(archiveInfos) ?: []) as Set
if (archiveUrls) {
writeFile(file: "package_urls", text: archiveUrls.join("\n"), encoding: "utf-8")
}
archiveArtifacts(artifacts: "package_urls", allowEmptyArchive: true)
sh "rm -f -- *.zip *.hap"
}

pipelineLoad(this, "ApiExample", "build", "harmonyos", "RTC-Sample")
85 changes: 85 additions & 0 deletions .github/ci/build/build_hmos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env bash
set -euo pipefail

ci_dir="$(cd "$(dirname "$0")" && pwd)"
repo_root="$(cd "${ci_dir}/../../.." && pwd)"
project_dir="${repo_root}/HarmonyOS_NEXT/APIExample"
libs_dir="${project_dir}/entry/libs"
output_dir="${WORKSPACE:-${repo_root}}"

if [[ -z "${sdk_url:-}" ]]; then
echo "[ERROR] sdk_url is required"
exit 1
fi

sdk_file_name="$(basename "${sdk_url%%\?*}")"
if [[ "${sdk_file_name}" != *.zip ]]; then
echo "[ERROR] sdk_url must point to a FULL SDK .zip file: ${sdk_file_name}"
exit 1
fi

stage_dir="$(mktemp -d "${TMPDIR:-/tmp}/apiexample-hmos.XXXXXX")"
trap 'rm -rf "${stage_dir}"' EXIT

sdk_archive="${stage_dir}/${sdk_file_name}"
sdk_extract_dir="${stage_dir}/sdk"
mkdir -p "${sdk_extract_dir}"
curl -fL --retry 3 --output "${sdk_archive}" "${sdk_url}"
unzip -q "${sdk_archive}" -d "${sdk_extract_dir}"

sdk_hars=()
while IFS= read -r sdk_har; do
sdk_hars+=("${sdk_har}")
done < <(find "${sdk_extract_dir}" -type f -path '*/rtc/sdk/AgoraRtcSdk.har')

if [[ "${#sdk_hars[@]}" -ne 1 ]]; then
echo "[ERROR] Expected exactly one rtc/sdk/AgoraRtcSdk.har in ${sdk_file_name}, found ${#sdk_hars[@]}"
exit 1
fi

sdk_har="${sdk_hars[0]}"
sdk_root="${sdk_har%/rtc/sdk/AgoraRtcSdk.har}"
sdk_name="$(basename "${sdk_root}")"

mkdir -p "${libs_dir}"
cp -f "${sdk_har}" "${libs_dir}/AgoraRtcSdk.har"

package_metadata="${stage_dir}/oh-package.json5"
tar -xOzf "${sdk_har}" package/oh-package.json5 > "${package_metadata}"
detected_version="$(python3 -c 'import json, sys; print(json.load(open(sys.argv[1]))["version"])' "${package_metadata}")"
export SDK_VERSION="${SDK_VERSION:-${detected_version}}"

sample_dir="${sdk_root}/rtc/samples/API-Example"
rm -rf "${sample_dir}"
mkdir -p "${sample_dir}"
rsync -a \
--exclude '.hvigor/' \
--exclude 'build/' \
--exclude 'oh_modules/' \
"${project_dir}/" "${sample_dir}/"

build_number="${BUILD_NUMBER:-local}"
timestamp="$(date '+%Y%m%d%H%M%S')"
export ARTIFACT_TIMESTAMP="${timestamp}"
zip_file="${repo_root}/APIExample_${build_number}_${SDK_VERSION}_${timestamp}.zip"
(
cd "$(dirname "${sdk_root}")"
zip -qry "${zip_file}" "${sdk_name}"
)

if [[ "${compile_project:-true}" == "true" ]]; then
"${project_dir}/cloud_build.sh"

hap_file="${project_dir}/APIExample_${build_number}_${SDK_VERSION}_${timestamp}.hap"
if [[ ! -s "${hap_file}" ]]; then
echo "[ERROR] No signed HAP was produced"
exit 1
fi
cp -f "${hap_file}" "${output_dir}/"
fi

if [[ "${output_dir}" != "${repo_root}" ]]; then
cp -f "${zip_file}" "${output_dir}/"
fi

echo "[INFO] HarmonyOS artifacts are ready in ${output_dir}"
120 changes: 120 additions & 0 deletions HarmonyOS_NEXT/APIExample/cloud_build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/env bash
set -euo pipefail
umask 077

project_dir="$(cd "$(dirname "$0")" && pwd)"
deveco_home="${DEVECO_HOME:-/Applications/DevEco-Studio.app/Contents}"
ohpm_bin="${OHPM_BIN:-${deveco_home}/tools/ohpm/bin/ohpm}"
hvigor_bin="${HVIGOR_BIN:-${deveco_home}/tools/hvigor/bin/hvigorw}"
java_bin="${JAVA_BIN:-${deveco_home}/jbr/Contents/Home/bin/java}"
node_home="${HMOS_NODE_HOME:-${deveco_home}/tools/node}"
node_bin="${node_home}/bin/node"
deveco_sdk_home="${deveco_home}/sdk"
sign_tool="${HMOS_SIGN_TOOL_JAR:-${deveco_home}/sdk/default/openharmony/toolchains/lib/hap-sign-tool.jar}"

signing_dir="${HMOS_SIGN_CONFIG_DIR:-/Users/admin/.ohos/config/apiexample-config}"
profile_file="${HMOS_PROFILE_FILE:-${signing_dir}/debugDebug.p7b}"
keystore_file="${HMOS_KEYSTORE_FILE:-${signing_dir}/wayang.p12}"
certificate_file="${HMOS_CERTIFICATE_FILE:-${signing_dir}/wayangAgora.cer}"

require_file() {
if [[ ! -f "$1" ]]; then
echo "[ERROR] Required file not found: $1"
exit 1
fi
}

require_executable() {
if [[ ! -x "$1" ]]; then
echo "[ERROR] Required executable not found: $1"
exit 1
fi
}

require_directory() {
if [[ ! -d "$1" ]]; then
echo "[ERROR] Required directory not found: $1"
exit 1
fi
}

if [[ -z "${APP_ID:-}" ]]; then
echo "[ERROR] APP_ID is required"
exit 1
fi
if [[ -z "${HMOS_KEY_PWD:-}" ]]; then
echo "[ERROR] HMOS_KEY_PWD is required"
exit 1
fi

require_executable "${ohpm_bin}"
require_executable "${hvigor_bin}"
require_executable "${java_bin}"
require_executable "${node_bin}"
require_directory "${deveco_sdk_home}"
require_file "${sign_tool}"
require_file "${profile_file}"
require_file "${keystore_file}"
require_file "${certificate_file}"

export NODE_HOME="${node_home}"
export PATH="${node_home}/bin:${PATH}"
export DEVECO_SDK_HOME="${deveco_sdk_home}"

app_id="${APP_ID}"
app_id="${app_id#\'}"
app_id="${app_id%\'}"
app_id="${app_id#\"}"
app_id="${app_id%\"}"
if [[ ! "${app_id}" =~ ^[[:xdigit:]]{32}$ ]]; then
echo "[ERROR] APP_ID must be a 32-character hexadecimal value"
exit 1
fi
escaped_app_id="${app_id//&/\\&}"

key_center="${project_dir}/entry/src/main/ets/common/KeyCenter.ets"
sed -E -i '' \
"s#^export const AppID: string[[:space:]]*=.*\$#export const AppID: string = '${escaped_app_id}'#" \
"${key_center}"
sed -E -i '' \
"s#^export const AppCertificate: string[[:space:]]*=.*\$#export const AppCertificate: string = ''#" \
"${key_center}"

"${java_bin}" -version
(
cd "${project_dir}"
"${ohpm_bin}" install
cd "${project_dir}/entry"
"${ohpm_bin}" install
cd "${project_dir}"
"${hvigor_bin}" clean --no-daemon
"${hvigor_bin}" assembleHap --mode module -p product=default -p buildMode=debug --no-daemon
)

unsigned_hap="${project_dir}/entry/build/default/outputs/default/entry-default-unsigned.hap"
require_file "${unsigned_hap}"

build_number="${BUILD_NUMBER:-local}"
sdk_version="${SDK_VERSION:-unknown}"
artifact_timestamp="${ARTIFACT_TIMESTAMP:-$(date '+%Y%m%d%H%M%S')}"
signed_hap="${project_dir}/APIExample_${build_number}_${sdk_version}_${artifact_timestamp}.hap"

"${java_bin}" -jar "${sign_tool}" sign-app \
-keyAlias "${HMOS_KEY_PWD}" \
-signAlg "SHA256withECDSA" \
-mode "localSign" \
-appCertFile "${certificate_file}" \
-profileFile "${profile_file}" \
-keystoreFile "${keystore_file}" \
-inFile "${unsigned_hap}" \
-outFile "${signed_hap}" \
-keyPwd "${HMOS_KEY_PWD}" \
-keystorePwd "${HMOS_KEY_PWD}" \
-signCode "1"

if [[ ! -s "${signed_hap}" ]]; then
echo "[ERROR] Signed HAP was not produced"
exit 1
fi

echo "[INFO] Signed HAP: ${signed_hap}"
17 changes: 9 additions & 8 deletions HarmonyOS_NEXT/APIExample/entry/oh-package-lock.json5

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion HarmonyOS_NEXT/APIExample/entry/src/main/ets/pages/Data.ets
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,22 @@ export const ADVANCE_ITEMS: ExampleItem[] =
title: $r('app.string.item_joinmultichannel'),
url: 'pages/advance/JoinMultiChannel'
},
{
title: $r('app.string.item_useraccount'),
url: 'pages/advance/UserAccount'
},
{
title: $r('app.string.item_mediametadata'),
url: 'pages/advance/MediaMetadataWrap'
},
{
title: $r('app.string.item_voiceeffects'),
url: 'pages/advance/VoiceEffects'
},
{
title: $r('app.string.item_videobeauty'),
url: 'pages/advance/VideoBeauty'
},
{
title: $r('app.string.item_customaudiosource'),
url: 'pages/advance/CustomAudioSource'
Expand Down Expand Up @@ -103,4 +115,4 @@ export class GlobalInfo {
frameRate: 15,
orientationMode: OrientationMode.ORIENTATION_MODE_ADAPTIVE
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ struct CustomVideoSource {
VideoPixelFormat.VIDEO_PIXEL_I420);
frame.buffer = frameBuffer.buffer as ArrayBuffer;
frame.rotation = 0;
frame.yStride = width;
frame.stride = width;
frame.height = height;
frame.timestamp = 0;
let ret = this.rtcEngine?.pushExternalVideoFrame(frame)
Expand Down Expand Up @@ -248,4 +248,4 @@ struct CustomVideoSource {
}
.backgroundColor($r('app.color.background_shallow_grey'))
}
}
}
Loading
Loading