diff --git a/.git-hooks/install-hooks.sh b/.git-hooks/install-hooks.sh index 5c63f9e92..184c45018 100755 --- a/.git-hooks/install-hooks.sh +++ b/.git-hooks/install-hooks.sh @@ -53,9 +53,9 @@ else print_green "pre-commit is already installed!" fi -# Check if gitleaks is installed +# Check if gitleaks is installed (required) if ! command -v gitleaks &> /dev/null; then - print_yellow "gitleaks not found, please install it..." + print_red "❌ gitleaks not found - this is a required security tool!" print_yellow "Installation guide: https://github.com/gitleaks/gitleaks#installing" # Attempt automatic installation (based on OS) @@ -77,6 +77,8 @@ if ! command -v gitleaks &> /dev/null; then print_red "Please install gitleaks manually and try again" exit 1 fi +else + print_green "gitleaks is installed!" fi # Check required files and directories diff --git a/.git-hooks/post-commit b/.git-hooks/post-commit index 74ae8b053..1feac10e8 100755 --- a/.git-hooks/post-commit +++ b/.git-hooks/post-commit @@ -3,21 +3,17 @@ # Check if required hooks are installed if [ ! -f ".git/hooks/commit-msg" ] || [ ! -x ".git/hooks/commit-msg" ]; then echo "============================================================" - echo "Note: Git hooks for checking Chinese characters in commit messages are not installed." + echo "⚠️ Note: Git hooks for checking commit messages are not installed." echo "Please run the following commands to install:" echo "" echo " 1. Install pre-commit:" echo " pip install pre-commit" echo "" - echo " 2. Install pre-commit hook:" - echo " pre-commit install" + echo " 2. Install hooks:" + echo " .git-hooks/install-hooks.sh" echo "" - echo " 3. Install commit-msg hook:" - echo " pre-commit install --hook-type commit-msg" - echo " cp .git-hooks/check-commit-message.sh .git/hooks/commit-msg" - echo " chmod +x .git/hooks/commit-msg" - echo "" - echo "These hooks will help detect sensitive information leaks and Chinese characters in commit messages." + echo "These hooks will help detect sensitive information leaks and" + echo "Chinese characters in commit messages." echo "============================================================" fi diff --git a/.git-hooks/pre-commit b/.git-hooks/pre-commit index 57221d159..e3ccc78e3 100755 --- a/.git-hooks/pre-commit +++ b/.git-hooks/pre-commit @@ -3,8 +3,13 @@ # Check if gitleaks is configured if ! command -v gitleaks &> /dev/null; then echo "============================================================" - echo "Gitleaks not detected. This is a required tool to prevent sensitive information leaks." - echo "Please install gitleaks first: https://github.com/gitleaks/gitleaks#installing" + echo "❌ ERROR: Gitleaks not detected." + echo "This is a required tool to prevent sensitive information leaks." + echo "" + echo "Please install gitleaks first:" + echo " macOS: brew install gitleaks" + echo " Other: https://github.com/gitleaks/gitleaks#installing" + echo "" echo "After installation, run: ./.git-hooks/install-hooks.sh" echo "============================================================" exit 1 @@ -14,12 +19,12 @@ fi if [ -f ".gitleaks.toml" ]; then gitleaks detect --source . --config .gitleaks.toml if [ $? -ne 0 ]; then - echo "Gitleaks detected sensitive information. Commit rejected." + echo "❌ Gitleaks detected sensitive information. Commit rejected." echo "Please review the output above and remove sensitive information." exit 1 fi else - echo "No .gitleaks.toml configuration file found, skipping sensitive information check." + echo "⚠️ No .gitleaks.toml configuration file found, skipping sensitive information check." fi exit 0 \ No newline at end of file diff --git a/.git-hooks/run-gitleaks.sh b/.git-hooks/run-gitleaks.sh new file mode 100755 index 000000000..114e979d1 --- /dev/null +++ b/.git-hooks/run-gitleaks.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Try to find gitleaks in common locations +GITLEAKS_CMD="" + +# Check if gitleaks is in PATH +if command -v gitleaks &> /dev/null; then + GITLEAKS_CMD="gitleaks" +# Check Homebrew locations (Intel Mac) +elif [ -f "/usr/local/bin/gitleaks" ]; then + GITLEAKS_CMD="/usr/local/bin/gitleaks" +# Check Homebrew locations (Apple Silicon Mac) +elif [ -f "/opt/homebrew/bin/gitleaks" ]; then + GITLEAKS_CMD="/opt/homebrew/bin/gitleaks" +# Check if installed via other package managers +elif [ -f "$HOME/.local/bin/gitleaks" ]; then + GITLEAKS_CMD="$HOME/.local/bin/gitleaks" +fi + +# If gitleaks not found, exit with error +if [ -z "$GITLEAKS_CMD" ]; then + echo "============================================================" + echo "❌ ERROR: gitleaks not found!" + echo "" + echo "Please install gitleaks:" + echo " macOS: brew install gitleaks" + echo " Linux: https://github.com/gitleaks/gitleaks#installing" + echo "" + echo "After installation, run: ./.git-hooks/install-hooks.sh" + echo "============================================================" + exit 1 +fi + +# Run gitleaks with provided arguments +exec "$GITLEAKS_CMD" "$@" diff --git a/.github/ci/build/build_android.sh b/.github/ci/build/build_android.sh index b8bd71de6..4bb0e7fba 100644 --- a/.github/ci/build/build_android.sh +++ b/.github/ci/build/build_android.sh @@ -39,6 +39,13 @@ ################################## export PATH=$PATH:/opt/homebrew/bin +# Record build start time +START_TIME=$(date +%s) +echo "==========================================" +echo "Build started at: $(date '+%Y-%m-%d %H:%M:%S')" +echo "==========================================" +echo "" + echo Package_Publish: $Package_Publish echo is_tag_fetch: $is_tag_fetch echo arch: $arch @@ -48,23 +55,108 @@ echo build_date: $build_date echo build_time: $build_time echo release_version: $release_version echo short_version: $short_version +echo BUILD_NUMBER: $BUILD_NUMBER echo pwd: `pwd` echo sdk_url: $sdk_url echo android_direction: $android_direction +echo compile_project: $compile_project +echo compress_apiexample: $compress_apiexample +echo api_examples_shengwang_branch: $api_examples_shengwang_branch + +# Validate required variables +if [ -z "$android_direction" ]; then + echo "Error: android_direction variable is not set" + exit 1 +fi + +# ===== Version Consistency Check ===== +echo "" +echo "==========================================" +echo "Checking version consistency..." +echo "==========================================" + +# Extract version number from branch name (supports formats like dev/4.6.2, release/4.6.2, etc.) +BRANCH_VERSION=$(echo $api_examples_shengwang_branch | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1) + +if [ -z "$BRANCH_VERSION" ]; then + echo "" + echo "==========================================" + echo "❌ CI BUILD FAILED: CANNOT EXTRACT VERSION" + echo "==========================================" + echo "Cannot extract version from branch name: $api_examples_shengwang_branch" + echo "Branch name must contain version number (e.g., dev/4.6.2, release/4.6.2)" + echo "==========================================" + exit 1 +fi + +echo "Branch version: $BRANCH_VERSION" +echo "" + +# Check all gradle.properties files +GRADLE_FILES=( + "Android/APIExample/gradle.properties" + "Android/APIExample-Audio/gradle.properties" + "Android/APIExample-Compose/gradle.properties" +) + +VERSION_MISMATCH=false -unzip_name=Agora_Native_SDK_for_Android_FULL_DEFAULT -zip_name=Agora_Native_SDK_for_Android_FULL_DEFAULT.zip +for gradle_file in "${GRADLE_FILES[@]}"; do + if [ -f "$gradle_file" ]; then + GRADLE_VERSION=$(grep "rtc_sdk_version" "$gradle_file" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') + echo "Checking $gradle_file: $GRADLE_VERSION" + + if [ "$GRADLE_VERSION" != "$BRANCH_VERSION" ]; then + echo "❌ ERROR: Version mismatch in $gradle_file" + echo " Branch version: $BRANCH_VERSION" + echo " Gradle version: $GRADLE_VERSION" + VERSION_MISMATCH=true + else + echo "✅ Version matched: $GRADLE_VERSION" + fi + else + echo "⚠️ Warning: $gradle_file not found" + fi + echo "" +done + +if [ "$VERSION_MISMATCH" = true ]; then + echo "" + echo "==========================================" + echo "❌ CI BUILD FAILED: VERSION MISMATCH" + echo "==========================================" + echo "Branch name contains version: $BRANCH_VERSION" + echo "But gradle.properties has different version(s)" + echo "" + echo "Please update rtc_sdk_version in all gradle.properties files to: $BRANCH_VERSION" + echo "==========================================" + exit 1 +fi + +echo "✅ All version checks passed!" +echo "==========================================" +echo "" + +unzip_name=Shengwang_Native_SDK_for_Android_FULL_DEFAULT +zip_name=Shengwang_Native_SDK_for_Android_FULL_DEFAULT.zip if [ -z "$sdk_url" ] || [ "$sdk_url" = "none" ]; then - echo "sdk_url is empty" + echo "sdk_url is empty, using default SDK structure" echo unzip_name: $unzip_name echo zip_name: $zip_name else zip_name=${sdk_url##*/} echo zip_name: $zip_name + # Download SDK + echo "Downloading SDK from: $sdk_url" # env LC_ALL=en_US.UTF-8 python3 $WORKSPACE/artifactory_utils.py --action=download_file --file=$sdk_url || exit 1 curl -o $zip_name $sdk_url || exit 1 + echo "✅ SDK downloaded successfully" + + # Extract SDK + echo "Extracting SDK package..." 7za x ./$zip_name -y > log.txt + echo "✅ SDK extracted successfully" # Support top-level directory name containing 'Agora' or 'Shengwang' unzip_name=`ls -S -d */ | grep -E 'Agora|Shengwang' | head -n 1 | sed 's/\///g'` @@ -74,38 +166,89 @@ else fi echo unzip_name: $unzip_name + # Clean up unnecessary files + echo "Cleaning up unnecessary files..." rm -rf ./$unzip_name/rtc/bin rm -rf ./$unzip_name/rtc/demo rm -f ./$unzip_name/.commits rm -f ./$unzip_name/spec rm -rf ./$unzip_name/pom + echo "✅ Cleanup completed" fi mkdir -p ./$unzip_name/rtc/samples/${android_direction} || exit 1 rm -rf ./$unzip_name/rtc/samples/${android_direction}/* +echo "" +echo "Copying API Example code from ./Android/${android_direction}..." if [ -d "./Android/${android_direction}" ]; then cp -rf ./Android/${android_direction}/* ./$unzip_name/rtc/samples/${android_direction}/ || exit 1 + echo "✅ API Example code copied successfully" else echo "Error: Source directory ./Android/${android_direction} does not exist" exit 1 fi +echo "" -7za a -tzip result.zip -r $unzip_name > log.txt -mv result.zip $WORKSPACE/withAPIExample_${BUILD_NUMBER}_$zip_name - -if [ $compress_apiexample = true ]; then - onlyCodeZipName=${android_direction}_onlyCode.zip - 7za a -tzip $onlyCodeZipName -r ./$unzip_name/rtc/samples/${android_direction} >> log.txt - mv $onlyCodeZipName $WORKSPACE/APIExample_onlyCode_${BUILD_NUMBER}_$zip_name +if [ "$compress_apiexample" = true ]; then + # Compress only API Example code (without SDK) + echo "Creating code-only package..." + TEMP_ZIP_NAME="temp_code_only.zip" + 7za a -tzip $TEMP_ZIP_NAME -r ./$unzip_name/rtc/samples/${android_direction} > log.txt + echo "✅ Code-only package created" + + # Generate final output zip name with version + OUTPUT_ZIP_NAME="Shengwang_Native_SDK_for_Android_v${BRANCH_VERSION}_${android_direction}_${BUILD_NUMBER}.zip" + echo "Output zip name: $OUTPUT_ZIP_NAME" + mv $TEMP_ZIP_NAME $WORKSPACE/$OUTPUT_ZIP_NAME + + # Display package size + echo "Package size: $(du -h $WORKSPACE/$OUTPUT_ZIP_NAME | cut -f1)" +else + # Compress full SDK with API Example + echo "Creating full package with SDK..." + TEMP_ZIP_NAME="temp_with_sdk.zip" + 7za a -tzip $TEMP_ZIP_NAME -r $unzip_name > log.txt + echo "✅ Full package created" + + # Generate final output zip name with version (with SDK) + OUTPUT_ZIP_NAME="withSDK_Shengwang_Native_SDK_for_Android_v${BRANCH_VERSION}_${android_direction}_${BUILD_NUMBER}.zip" + echo "Output zip name: $OUTPUT_ZIP_NAME" + mv $TEMP_ZIP_NAME $WORKSPACE/$OUTPUT_ZIP_NAME + + # Display package size + echo "Package size: $(du -h $WORKSPACE/$OUTPUT_ZIP_NAME | cut -f1)" fi +echo "" if [ $compile_project = true ]; then + echo "Starting project compilation..." cd ./$unzip_name/rtc/samples/${android_direction} || exit 1 if [ -z "$sdk_url" ] || [ "$sdk_url" = "none" ]; then ./cloud_build.sh false || exit 1 else ./cloud_build.sh true || exit 1 fi + echo "✅ Project compiled successfully" + echo "" +fi + +# Calculate and display build duration +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) +MINUTES=$((DURATION / 60)) +SECONDS=$((DURATION % 60)) + +echo "" +echo "==========================================" +echo "✅ BUILD COMPLETED SUCCESSFULLY" +echo "==========================================" +echo "Completed at: $(date '+%Y-%m-%d %H:%M:%S')" +if [ $MINUTES -gt 0 ]; then + echo "Total duration: ${MINUTES}m ${SECONDS}s" +else + echo "Total duration: ${SECONDS}s" fi +echo "Output package: $OUTPUT_ZIP_NAME" +echo "==========================================" diff --git a/.github/ci/build/build_ios.sh b/.github/ci/build/build_ios.sh index 501c9d80e..d8848889d 100644 --- a/.github/ci/build/build_ios.sh +++ b/.github/ci/build/build_ios.sh @@ -40,6 +40,18 @@ ################################## export PATH=$PATH:/opt/homebrew/bin +echo "==========================================" +echo "=== Git Branch Debug Information ===" +echo "==========================================" +echo "GIT_BRANCH: $GIT_BRANCH" +echo "BRANCH_NAME: $BRANCH_NAME" +echo "CI_COMMIT_REF_NAME: $CI_COMMIT_REF_NAME" +echo "Git branches:" +git branch -a 2>/dev/null || echo "Unable to list git branches" +echo "Current HEAD:" +git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "Unable to get HEAD" +echo "==========================================" + xcode_version=$(xcodebuild -version | grep Xcode | awk '{print $2}') echo "Xcode Version: $xcode_version" echo ios_direction: $ios_direction @@ -106,7 +118,7 @@ echo $WORKSPACE/with${ios_direction}_${BUILD_NUMBER}_$zip_name mv result.zip $WORKSPACE/with${ios_direction}_${BUILD_NUMBER}_$zip_name if [ $compress_apiexample = true ]; then - sdk_version=$(grep "pod 'AgoraRtcEngine_iOS'" ./iOS/${ios_direction}/Podfile | sed -n "s/.*'\([0-9.]*\)'.*/\1/p") + sdk_version=$(grep "pod 'ShengwangRtcEngine_iOS'" ./iOS/${ios_direction}/Podfile | sed -n "s/.*'\([0-9.]*\)'.*/\1/p") echo "sdk_version: $sdk_version" mkdir -p $cn_dir @@ -119,7 +131,7 @@ if [ $compress_apiexample = true ]; then echo "complete compress api example" echo "current path: `pwd`" ls -al - cn_des_path=$WORKSPACE/${apiexample_cn_name}_${sdk_version}_${BUILD_NUMBER}_APIExample.zip + cn_des_path=$WORKSPACE/${apiexample_cn_name}_v${sdk_version}_APIExample_${BUILD_NUMBER}.zip echo "cn_des_path: $cn_des_path" echo "Moving cn_result.zip to $cn_des_path" mv cn_result.zip $cn_des_path diff --git a/.github/ci/build/build_mac.sh b/.github/ci/build/build_mac.sh index 7817751fd..b8e9ba2be 100644 --- a/.github/ci/build/build_mac.sh +++ b/.github/ci/build/build_mac.sh @@ -121,7 +121,7 @@ if [ $compress_apiexample = true ]; then echo "complete compress api example" echo "current path: `pwd`" ls -al - cn_des_path=$WORKSPACE/${apiexample_cn_name}_${sdk_version}_${BUILD_NUMBER}_APIExample.zip + cn_des_path=$WORKSPACE/${apiexample_cn_name}_v${sdk_version}_APIExample_${BUILD_NUMBER}.zip echo "cn_des_path: $cn_des_path" echo "Moving cn_result.zip to $cn_des_path" mv cn_result.zip $cn_des_path @@ -133,6 +133,4 @@ fi # cd ./$unzip_name/samples/APIExample # ./cloud_build.sh || exit 1 # cd - -#fi - - +#fi \ No newline at end of file diff --git a/.github/ci/build/build_windows.bat b/.github/ci/build/build_windows.bat index 0604420e0..1fd3f166f 100644 --- a/.github/ci/build/build_windows.bat +++ b/.github/ci/build/build_windows.bat @@ -10,8 +10,6 @@ REM 'repo:string', REM 'base:string', REM 'arch:string' REM 'output:string' -REM 'short_version:string' -REM 'release_version:string' REM 'build_date:string(yyyyMMdd)', REM 'build_timestamp:string (yyyyMMdd_hhmm)', REM 'platform: string', @@ -46,54 +44,88 @@ echo source_root: %source_root% echo output: C:\\tmp\\%project%_out echo build_date: %build_date% echo build_time: %build_time% -echo release_version: %release_version% -echo short_version: %short_version% echo pwd: %cd% echo sdk_url: %sdk_url% - -set zip_name=Shengwang_Native_SDK_for_Windows_FULL_DEFAULT.zip -if %compile_project% EQU false goto SKIP_DOWNLOAD -set zip_name=%sdk_url% -:LOOP -for /f "tokens=1* delims=" %%a in ("%zip_name%") do ( - set zip_name=%%a - set part2=%%b +REM Version validation: branch name vs install.ps1 SDK version +for /f "tokens=*" %%a in ('powershell -Command "(Get-Content 'windows\APIExample\install.ps1' -Raw) -match '_v([0-9]+\.[0-9]+\.[0-9]+)' | Out-Null; $matches[1]"') do set SDK_VER=%%a +for /f "tokens=*" %%b in ('powershell -Command "'%api_examples_shengwang_branch%' -match '([0-9]+\.[0-9]+\.[0-9]+)' | Out-Null; $matches[1]"') do set BRANCH_VER=%%b +if not "%SDK_VER%"=="%BRANCH_VER%" ( + echo ERROR: Version mismatch - Branch: %BRANCH_VER%, install.ps1: %SDK_VER% + exit /b 1 ) -if "%part2%" EQU "" goto END -set zip_name=%part2% -goto LOOP -:END -echo on -echo zip_name: %zip_name% +echo Version validated: %BRANCH_VER% -dir +REM If sdk_url has a value, replace the URL in install.ps1 +if not "%sdk_url%"=="" ( + if not "%sdk_url%"=="none" ( + echo "Replacing SDK URL in install.ps1" + powershell -Command "(Get-Content windows\APIExample\install.ps1) -replace '\$agora_sdk = ''.*''', ('$agora_sdk = ''' + '%sdk_url%' + '''') | Set-Content windows\APIExample\install.ps1" + ) +) -curl %sdk_url% -o %zip_name% -REM python %WORKSPACE%\\artifactory_utils.py --action=download_file --file=%sdk_url% -7z x ./%zip_name% -y -dir -rmdir /S /Q Shengwang_Native_SDK_for_Windows_FULL\demo -del /F /Q Shengwang_Native_SDK_for_Windows_FULL\commits -del /F /Q Shengwang_Native_SDK_for_Windows_FULL\package_size_report.txt -:SKIP_DOWNLOAD +REM Check compress_apiexample parameter +if "%compress_apiexample%"=="" set compress_apiexample=false +echo compress_apiexample: %compress_apiexample% +REM Check compile_project parameter +if "%compile_project%"=="" set compile_project=false +echo compile_project: %compile_project% -mkdir Shengwang_Native_SDK_for_Windows_FULL\samples -mkdir Shengwang_Native_SDK_for_Windows_FULL\samples\API-example -rmdir /S /Q windows\cicd -del /F /Q windows\APIExample\ci.py -xcopy /Y /E windows\APIExample Shengwang_Native_SDK_for_Windows_FULL\samples\API-example -xcopy /Y /E windows\README.md Shengwang_Native_SDK_for_Windows_FULL\samples\API-example -xcopy /Y /E windows\README.zh.md Shengwang_Native_SDK_for_Windows_FULL\samples\API-example -rmdir /S /Q Shengwang_Native_SDK_for_Windows_FULL\samples\API-example\APIExample\APIExample -dir Shengwang_Native_SDK_for_Windows_FULL\samples\API-example\APIExample -7z a -tzip result.zip -r Shengwang_Native_SDK_for_Windows_FULL -copy result.zip %WORKSPACE%\\withAPIExample_%BUILD_NUMBER%_%zip_name% -del /F result.zip -del /F %WORKSPACE%\\%zip_name% +REM Package APIExample code with dependencies (only when compress_apiexample=true) +REM Run before compile so package content is not affected by compile +set result_zip=APIExample_result.zip +set des_path=%WORKSPACE%\Shengwang_Native_SDK_for_Windows_v%SDK_VER%_APIExample_%BUILD_NUMBER%.zip +if "%compress_apiexample%"=="true" ( + echo "Packaging APIExample code with dependencies..." + + REM Install dependencies (ThirdParty, SDK) in windows\APIExample + echo "Installing dependencies in windows\APIExample..." + cd windows\APIExample + powershell.exe -ExecutionPolicy Bypass -File "install.ps1" + if errorlevel 1 ( + echo install.ps1 failed! + cd ..\.. + exit /b 1 + ) + cd ..\.. + + REM Compress windows\APIExample (code + dependencies) to zip + echo "Compressing APIExample code package..." + del /F /Q %result_zip% 2>nul + 7z a -tzip %result_zip% -r windows\APIExample + if errorlevel 1 ( + echo 7z compression failed! + exit /b 1 + ) + + REM Copy to WORKSPACE with new naming format + echo "Copying %result_zip% to %des_path%" + copy %result_zip% %des_path% + if errorlevel 1 ( + echo copy failed! + exit /b 1 + ) + + REM Clean up temporary zip in repo root + del /F %result_zip% + + echo "Complete: APIExample code package created" + dir %WORKSPACE%\ +) else ( + echo "Skipping APIExample code packaging (compress_apiexample=false)" +) -if %compile_project% EQU false goto FINAL -cd Shengwang_Native_SDK_for_Windows_FULL\samples\API-example -call cloud_build.bat -:FINAL +REM Compile project to generate executable (only when compile_project=true) +if "%compile_project%"=="true" ( + echo "Compiling project to generate executable..." + cd windows\APIExample + call cloud_build.bat + if %ERRORLEVEL% NEQ 0 ( + echo Build failed! + exit /b %ERRORLEVEL% + ) + cd ..\.. +) else ( + echo "Skipping project compilation (compile_project=false)" +) \ No newline at end of file diff --git a/.github/ci/build/build_windows.groovy b/.github/ci/build/build_windows.groovy index e8ba84227..79ecdd71b 100644 --- a/.github/ci/build/build_windows.groovy +++ b/.github/ci/build/build_windows.groovy @@ -6,7 +6,7 @@ import groovy.transform.Field buildUtils = new agora.build.BuildUtils() compileConfig = [ - "sourceDir": "api-examples", + "sourceDir": "api-examples-shengwang", "non-publish": [ "command": "./.github/ci/build/build_windows.bat", "extraArgs": "", diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8cca4020e..6e81c1c34 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: - id: gitleaks name: Detect hardcoded secrets description: Ensures no secrets are committed - entry: gitleaks protect + entry: .git-hooks/run-gitleaks.sh protect args: ["--config=.gitleaks.toml", "--staged", "--verbose"] language: system pass_filenames: false diff --git a/Android/APIExample-Audio/app/build.gradle b/Android/APIExample-Audio/app/build.gradle index 7c707e576..97830bac4 100644 --- a/Android/APIExample-Audio/app/build.gradle +++ b/Android/APIExample-Audio/app/build.gradle @@ -98,23 +98,19 @@ dependencies { // implementation "cn.shengwang.rtc:drm:${agoraSdkVersion}" } + implementation 'androidx.core:core-ktx:1.13.1' implementation 'androidx.appcompat:appcompat:1.7.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation "org.jetbrains.kotlin:kotlin-stdlib:1.8.22" + implementation 'com.google.android.material:material:1.12.0' + implementation 'androidx.constraintlayout:constraintlayout:2.2.0' // Java language implementation - implementation "androidx.navigation:navigation-fragment:2.7.0" - implementation "androidx.navigation:navigation-ui:2.7.0" + implementation "androidx.navigation:navigation-fragment:2.8.5" + implementation "androidx.navigation:navigation-ui:2.8.5" - implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'androidx.recyclerview:recyclerview:1.3.2' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' - implementation 'io.github.luizgrp.sectionedrecyclerviewadapter:sectionedrecyclerviewadapter:1.2.0' - implementation 'de.javagl:obj:0.2.1' - - implementation "com.squareup.okhttp3:okhttp:4.10.0" - implementation "com.squareup.okhttp3:logging-interceptor:4.10.0" + implementation "com.squareup.okhttp3:okhttp:4.12.0" + implementation "com.squareup.okhttp3:logging-interceptor:4.12.0" } diff --git a/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/MainFragment.java b/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/MainFragment.java index 3b843ef71..8b47fec82 100644 --- a/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/MainFragment.java +++ b/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/MainFragment.java @@ -20,9 +20,8 @@ import androidx.recyclerview.widget.RecyclerView; import io.agora.api.example.annotation.Example; -import io.agora.api.example.common.adapter.ExampleSection; +import io.agora.api.example.common.adapter.SectionAdapter; import io.agora.api.example.common.model.Examples; -import io.github.luizgrp.sectionedrecyclerviewadapter.SectionedRecyclerViewAdapter; /** * A fragment representing a list of Items. @@ -78,10 +77,10 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, } else { recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount)); } - SectionedRecyclerViewAdapter sectionedAdapter = new SectionedRecyclerViewAdapter(); - sectionedAdapter.addSection(new ExampleSection(BASIC, Examples.ITEM_MAP.get(BASIC), mListener)); - sectionedAdapter.addSection(new ExampleSection(ADVANCED, Examples.ITEM_MAP.get(ADVANCED), mListener)); - recyclerView.setAdapter(sectionedAdapter); + SectionAdapter adapter = new SectionAdapter(mListener); + adapter.addSection(BASIC, Examples.ITEM_MAP.get(BASIC)); + adapter.addSection(ADVANCED, Examples.ITEM_MAP.get(ADVANCED)); + recyclerView.setAdapter(adapter); } return view; } diff --git a/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/common/adapter/ExampleSection.java b/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/common/adapter/ExampleSection.java deleted file mode 100644 index 31505545d..000000000 --- a/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/common/adapter/ExampleSection.java +++ /dev/null @@ -1,79 +0,0 @@ -package io.agora.api.example.common.adapter; - -import android.view.View; -import android.widget.TextView; - -import androidx.recyclerview.widget.RecyclerView; - -import java.util.List; - -import io.agora.api.example.MainFragment; -import io.agora.api.example.R; -import io.agora.api.example.annotation.Example; -import io.github.luizgrp.sectionedrecyclerviewadapter.Section; -import io.github.luizgrp.sectionedrecyclerviewadapter.SectionParameters; - -public class ExampleSection extends Section { - private final String mTitle; - private final List mValues; - private final MainFragment.OnListFragmentInteractionListener mListener; - - public ExampleSection(String title, List items, MainFragment.OnListFragmentInteractionListener listener) { - super(SectionParameters.builder().headerResourceId(R.layout.layout_main_list_section).itemResourceId(R.layout.layout_main_list_item).build()); - mTitle = title; - mValues = items; - mListener = listener; - } - - @Override - public int getContentItemsTotal() { - return mValues.size(); - } - - @Override - public RecyclerView.ViewHolder getItemViewHolder(View view) { - return new ViewHolder(view); - } - - @Override - public void onBindItemViewHolder(RecyclerView.ViewHolder viewHolder, int position) { - if (viewHolder instanceof ViewHolder) { - ViewHolder holder = (ViewHolder) viewHolder; - holder.mItem = mValues.get(position); - holder.mNameView.setText(holder.mView.getContext().getString(holder.mItem.name())); - - holder.mView.setOnClickListener(v -> { - if (null != mListener) { - // Notify the active callbacks interface (the activity, if the - // fragment is attached to one) that an item has been selected. - mListener.onListFragmentInteraction(holder.mItem); - } - }); - } - } - - @Override - public RecyclerView.ViewHolder getHeaderViewHolder(View view) { - return new ViewHolder(view); - } - - @Override - public void onBindHeaderViewHolder(RecyclerView.ViewHolder viewHolder) { - if (viewHolder instanceof ViewHolder) { - ViewHolder holder = (ViewHolder) viewHolder; - holder.mNameView.setText(mTitle); - } - } - - static class ViewHolder extends RecyclerView.ViewHolder { - final View mView; - final TextView mNameView; - Example mItem; - - ViewHolder(View view) { - super(view); - mView = view; - mNameView = view.findViewById(R.id.item_name); - } - } -} diff --git a/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/common/adapter/SectionAdapter.java b/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/common/adapter/SectionAdapter.java new file mode 100644 index 000000000..4d02cd1cc --- /dev/null +++ b/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/common/adapter/SectionAdapter.java @@ -0,0 +1,104 @@ +package io.agora.api.example.common.adapter; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; + +import io.agora.api.example.MainFragment; +import io.agora.api.example.R; +import io.agora.api.example.annotation.Example; + +/** + * Adapter for multiple sections with headers and items + */ +public class SectionAdapter extends RecyclerView.Adapter { + private static final int TYPE_HEADER = 0; + private static final int TYPE_ITEM = 1; + + private final List items = new ArrayList<>(); + private final MainFragment.OnListFragmentInteractionListener listener; + + public SectionAdapter(MainFragment.OnListFragmentInteractionListener listener) { + this.listener = listener; + } + + public void addSection(String title, List sectionItems) { + items.add(title); + if (sectionItems != null) { + items.addAll(sectionItems); + } + } + + @Override + public int getItemViewType(int position) { + return items.get(position) instanceof String ? TYPE_HEADER : TYPE_ITEM; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if (viewType == TYPE_HEADER) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.layout_main_list_section, parent, false); + return new HeaderViewHolder(view); + } else { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.layout_main_list_item, parent, false); + return new ItemViewHolder(view); + } + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (holder instanceof HeaderViewHolder) { + ((HeaderViewHolder) holder).bind((String) items.get(position)); + } else if (holder instanceof ItemViewHolder) { + ((ItemViewHolder) holder).bind((Example) items.get(position), listener); + } + } + + @Override + public int getItemCount() { + return items.size(); + } + + static class HeaderViewHolder extends RecyclerView.ViewHolder { + final TextView nameView; + + HeaderViewHolder(View view) { + super(view); + nameView = view.findViewById(R.id.item_name); + } + + void bind(String title) { + nameView.setText(title); + } + } + + static class ItemViewHolder extends RecyclerView.ViewHolder { + final View view; + final TextView nameView; + + ItemViewHolder(View itemView) { + super(itemView); + view = itemView; + nameView = itemView.findViewById(R.id.item_name); + } + + void bind(Example item, MainFragment.OnListFragmentInteractionListener listener) { + nameView.setText(view.getContext().getString(item.name())); + view.setOnClickListener(v -> { + if (listener != null) { + listener.onListFragmentInteraction(item); + } + }); + } + } +} diff --git a/Android/APIExample-Audio/build.gradle b/Android/APIExample-Audio/build.gradle index 02b277a8c..f65bc8b21 100644 --- a/Android/APIExample-Audio/build.gradle +++ b/Android/APIExample-Audio/build.gradle @@ -1,5 +1,5 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '8.5.0' apply false + id 'com.android.application' version '8.7.3' apply false id 'org.jetbrains.kotlin.android' version '1.9.24' apply false } diff --git a/Android/APIExample-Audio/cloud_build.sh b/Android/APIExample-Audio/cloud_build.sh index 0b3253e2b..675ad98f6 100755 --- a/Android/APIExample-Audio/cloud_build.sh +++ b/Android/APIExample-Audio/cloud_build.sh @@ -46,23 +46,26 @@ rm -f app/src/main/res/values/string_configs.xml-e ./gradlew clean || exit 1 ./gradlew :app:assembleRelease || exit 1 +# Extract SDK version from gradle.properties SDK_VERSION="" -if [ "$1" = "false" ]; then - sdk_version_file="./gradle.properties" - if [[ -f "$sdk_version_file" ]]; then +sdk_version_file="./gradle.properties" +if [[ -f "$sdk_version_file" ]]; then rtc_sdk_version=$(grep "rtc_sdk_version" "$sdk_version_file" | cut -d'=' -f2) if [[ -n "$rtc_sdk_version" ]]; then SDK_VERSION=$(echo "$rtc_sdk_version" | sed 's/^[ \t]*//;s/[ \t]*$//') + echo "SDK Version from gradle.properties: $SDK_VERSION" else - echo "rtc_sdk_version value not found" + echo "Warning: rtc_sdk_version value not found in gradle.properties" + SDK_VERSION="unknown" fi else - echo "file not found: $sdk_version_file" -fi -else - SDK_VERSION=$(echo $sdk_url | cut -d "/" -f 5) + echo "Warning: gradle.properties file not found" + SDK_VERSION="unknown" fi if [ "$WORKSPACE" != "" ]; then -cp app/build/outputs/apk/release/*.apk $WORKSPACE/APIExample-Audio_${BUILD_NUMBER}_${SDK_VERSION}_$(date "+%Y%m%d%H%M%S").apk + PROJECT_NAME="Shengwang-APIExample-Audio" + APK_NAME="${PROJECT_NAME}_${BUILD_NUMBER}_${SDK_VERSION}_$(date "+%Y%m%d%H%M%S").apk" + echo "Copying APK to: $WORKSPACE/$APK_NAME" + cp app/build/outputs/apk/release/*.apk "$WORKSPACE/$APK_NAME" fi \ No newline at end of file diff --git a/Android/APIExample-Audio/gradle.properties b/Android/APIExample-Audio/gradle.properties index 317242bfe..be8a46849 100644 --- a/Android/APIExample-Audio/gradle.properties +++ b/Android/APIExample-Audio/gradle.properties @@ -23,4 +23,4 @@ android.nonFinalResIds=false # read enable simple filter section on README first before set this flag to TRUE simpleFilter = false -rtc_sdk_version = 4.6.2 \ No newline at end of file +rtc_sdk_version = 4.6.3 \ No newline at end of file diff --git a/Android/APIExample-Audio/gradle/wrapper/gradle-wrapper.properties b/Android/APIExample-Audio/gradle/wrapper/gradle-wrapper.properties index 69b417860..513d9fcaf 100644 --- a/Android/APIExample-Audio/gradle/wrapper/gradle-wrapper.properties +++ b/Android/APIExample-Audio/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.7-bin.zip +distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.9-bin.zip diff --git a/Android/APIExample-Audio/settings.gradle b/Android/APIExample-Audio/settings.gradle index 83ea14178..f0c5c3a53 100644 --- a/Android/APIExample-Audio/settings.gradle +++ b/Android/APIExample-Audio/settings.gradle @@ -25,5 +25,5 @@ dependencyResolutionManagement { maven { url 'https://maven.aliyun.com/repository/central' } } } -rootProject.name = 'APIExample-Audio' +rootProject.name = 'Shengwang-APIExample-Audio' include ':app' diff --git a/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/LiveStreaming.kt b/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/LiveStreaming.kt index 60ca08848..85b580d7c 100644 --- a/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/LiveStreaming.kt +++ b/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/LiveStreaming.kt @@ -367,8 +367,7 @@ private fun LiveStreamingView( ModalBottomSheet( onDismissRequest = { openSettingSheet = false - }, - windowInsets = WindowInsets(0) + } ) { LiveStreamingSettingView( rtcEngine = rtcEngine, diff --git a/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/SpatialSound.kt b/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/SpatialSound.kt index 75c0e069f..2fc0e176c 100644 --- a/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/SpatialSound.kt +++ b/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/SpatialSound.kt @@ -489,7 +489,6 @@ private fun SpatialSoundView( onDismissRequest = { showSetting = false }, - windowInsets = WindowInsets(0), ) { Column( modifier = Modifier diff --git a/Android/APIExample-Compose/cloud_build.sh b/Android/APIExample-Compose/cloud_build.sh index 6a167f993..d465b3cbd 100755 --- a/Android/APIExample-Compose/cloud_build.sh +++ b/Android/APIExample-Compose/cloud_build.sh @@ -46,23 +46,26 @@ fi ./gradlew clean || exit 1 ./gradlew :app:assembleRelease || exit 1 +# Extract SDK version from gradle.properties SDK_VERSION="" -if [ "$1" = "false" ]; then - sdk_version_file="./gradle.properties" - if [[ -f "$sdk_version_file" ]]; then +sdk_version_file="./gradle.properties" +if [[ -f "$sdk_version_file" ]]; then rtc_sdk_version=$(grep "rtc_sdk_version" "$sdk_version_file" | cut -d'=' -f2) if [[ -n "$rtc_sdk_version" ]]; then SDK_VERSION=$(echo "$rtc_sdk_version" | sed 's/^[ \t]*//;s/[ \t]*$//') + echo "SDK Version from gradle.properties: $SDK_VERSION" else - echo "rtc_sdk_version value not found" + echo "Warning: rtc_sdk_version value not found in gradle.properties" + SDK_VERSION="unknown" fi else - echo "file not found: $sdk_version_file" -fi -else - SDK_VERSION=$(echo $sdk_url | cut -d "/" -f 5) + echo "Warning: gradle.properties file not found" + SDK_VERSION="unknown" fi if [ "$WORKSPACE" != "" ]; then -cp app/build/outputs/apk/release/*.apk $WORKSPACE/APIExample-Compose_${BUILD_NUMBER}_${SDK_VERSION}_$(date "+%Y%m%d%H%M%S").apk + PROJECT_NAME="Shengwang-APIExample-Compose" + APK_NAME="${PROJECT_NAME}_${BUILD_NUMBER}_${SDK_VERSION}_$(date "+%Y%m%d%H%M%S").apk" + echo "Copying APK to: $WORKSPACE/$APK_NAME" + cp app/build/outputs/apk/release/*.apk "$WORKSPACE/$APK_NAME" fi \ No newline at end of file diff --git a/Android/APIExample-Compose/gradle.properties b/Android/APIExample-Compose/gradle.properties index 69df9661f..6ba5018a5 100644 --- a/Android/APIExample-Compose/gradle.properties +++ b/Android/APIExample-Compose/gradle.properties @@ -22,4 +22,4 @@ kotlin.code.style=official # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true -rtc_sdk_version = 4.6.2 \ No newline at end of file +rtc_sdk_version = 4.6.3 \ No newline at end of file diff --git a/Android/APIExample-Compose/gradle/libs.versions.toml b/Android/APIExample-Compose/gradle/libs.versions.toml index fa039daab..0e0e8b694 100644 --- a/Android/APIExample-Compose/gradle/libs.versions.toml +++ b/Android/APIExample-Compose/gradle/libs.versions.toml @@ -1,27 +1,24 @@ [versions] -agp = "8.5.0" -datastore = "1.0.0" +agp = "8.7.3" +datastore = "1.1.1" kotlin = "1.9.24" -coreKtx = "1.10.1" +coreKtx = "1.13.1" junit = "4.13.2" junitVersion = "1.2.1" espressoCore = "3.6.1" -lifecycleRuntimeKtx = "2.6.1" -activityCompose = "1.8.2" -composeBom = "2023.08.00" -loggingInterceptor = "4.10.0" -materialIconsExtended = "1.6.0" -navigationCompose = "2.7.7" -#agoraSdk = "4.5.2" -okhttp = "4.10.0" +lifecycleRuntimeKtx = "2.8.7" +activityCompose = "1.9.3" +composeBom = "2024.12.01" +loggingInterceptor = "4.12.0" +materialIconsExtended = "1.7.6" +navigationCompose = "2.8.5" +okhttp = "4.12.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-datastore = { module = "androidx.datastore:datastore", version.ref = "datastore" } androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" } androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "materialIconsExtended" } -#agora-full-sdk = { module = "io.agora.rtc:full-sdk", version.ref = "agoraSdk" } -#agora-full-screen-sharing = { module = "io.agora.rtc:full-screen-sharing", version.ref = "agoraSdk" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } diff --git a/Android/APIExample-Compose/gradle/wrapper/gradle-wrapper.properties b/Android/APIExample-Compose/gradle/wrapper/gradle-wrapper.properties index 8ae2209c3..38556b5f3 100644 --- a/Android/APIExample-Compose/gradle/wrapper/gradle-wrapper.properties +++ b/Android/APIExample-Compose/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Apr 10 23:59:46 CST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.7-bin.zip +distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/Android/APIExample-Compose/settings.gradle.kts b/Android/APIExample-Compose/settings.gradle.kts index 68ab54d64..ec45f6699 100644 --- a/Android/APIExample-Compose/settings.gradle.kts +++ b/Android/APIExample-Compose/settings.gradle.kts @@ -26,5 +26,5 @@ dependencyResolutionManagement { } } -rootProject.name = "APIExample-Compose" +rootProject.name = "Shengwang-APIExample-Compose" include(":app") diff --git a/Android/APIExample/.gitignore b/Android/APIExample/.gitignore index 7ac17864f..9281983f9 100644 --- a/Android/APIExample/.gitignore +++ b/Android/APIExample/.gitignore @@ -25,3 +25,4 @@ AgoraScreenShareExtension.aar /agora-simple-filter/src/main/agoraLibs/ /agora-simple-filter/src/main/libs/ /agora-stream-encrypt/src/main/agoraLibs/ +/automation-test/ diff --git a/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/AgoraBase.h b/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/AgoraBase.h index 99397d4fe..69f80bed6 100644 --- a/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/AgoraBase.h +++ b/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/AgoraBase.h @@ -2631,6 +2631,7 @@ struct WatermarkConfig { enum MultipathMode { /** * Duplicate mode, the same piece of data is redundantly transmitted over all available paths. + * @technical preview */ Duplicate= 0, /** diff --git a/Android/APIExample/agora-stream-encrypt/src/main/cpp/include/agora/AgoraBase.h b/Android/APIExample/agora-stream-encrypt/src/main/cpp/include/agora/AgoraBase.h index 99397d4fe..69f80bed6 100644 --- a/Android/APIExample/agora-stream-encrypt/src/main/cpp/include/agora/AgoraBase.h +++ b/Android/APIExample/agora-stream-encrypt/src/main/cpp/include/agora/AgoraBase.h @@ -2631,6 +2631,7 @@ struct WatermarkConfig { enum MultipathMode { /** * Duplicate mode, the same piece of data is redundantly transmitted over all available paths. + * @technical preview */ Duplicate= 0, /** diff --git a/Android/APIExample/app/build.gradle b/Android/APIExample/app/build.gradle index c750e2c1c..f12013ca8 100644 --- a/Android/APIExample/app/build.gradle +++ b/Android/APIExample/app/build.gradle @@ -118,15 +118,15 @@ dependencies { } + implementation 'androidx.core:core-ktx:1.13.1' implementation 'androidx.appcompat:appcompat:1.7.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'com.google.android.material:material:1.12.0' + implementation 'androidx.constraintlayout:constraintlayout:2.2.0' // Java language implementation - implementation "androidx.navigation:navigation-fragment:2.7.0" - implementation "androidx.navigation:navigation-ui:2.7.0" + implementation "androidx.navigation:navigation-fragment:2.8.5" + implementation "androidx.navigation:navigation-ui:2.8.5" - implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'androidx.recyclerview:recyclerview:1.3.2' if (simpleFilter.toBoolean()) { implementation project(path: ':agora-simple-filter') } @@ -137,11 +137,8 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' - implementation 'io.github.luizgrp.sectionedrecyclerviewadapter:sectionedrecyclerviewadapter:1.2.0' - implementation 'de.javagl:obj:0.2.1' - - implementation "com.squareup.okhttp3:okhttp:4.10.0" - implementation "com.squareup.okhttp3:logging-interceptor:4.10.0" + implementation "com.squareup.okhttp3:okhttp:4.12.0" + implementation "com.squareup.okhttp3:logging-interceptor:4.12.0" implementation 'com.faceunity:core:8.7.0' implementation 'com.faceunity:model:8.7.0' diff --git a/Android/APIExample/app/src/main/java/io/agora/api/example/MainFragment.java b/Android/APIExample/app/src/main/java/io/agora/api/example/MainFragment.java index 54aebb2ec..25e15a2eb 100644 --- a/Android/APIExample/app/src/main/java/io/agora/api/example/MainFragment.java +++ b/Android/APIExample/app/src/main/java/io/agora/api/example/MainFragment.java @@ -20,9 +20,8 @@ import androidx.recyclerview.widget.RecyclerView; import io.agora.api.example.annotation.Example; -import io.agora.api.example.common.adapter.ExampleSection; +import io.agora.api.example.common.adapter.SectionAdapter; import io.agora.api.example.common.model.Examples; -import io.github.luizgrp.sectionedrecyclerviewadapter.SectionedRecyclerViewAdapter; /** * A fragment representing a list of Items. @@ -82,10 +81,10 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, } else { recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount)); } - SectionedRecyclerViewAdapter sectionedAdapter = new SectionedRecyclerViewAdapter(); - sectionedAdapter.addSection(new ExampleSection(BASIC, Examples.ITEM_MAP.get(BASIC), mListener)); - sectionedAdapter.addSection(new ExampleSection(ADVANCED, Examples.ITEM_MAP.get(ADVANCED), mListener)); - recyclerView.setAdapter(sectionedAdapter); + SectionAdapter adapter = new SectionAdapter(mListener); + adapter.addSection(BASIC, Examples.ITEM_MAP.get(BASIC)); + adapter.addSection(ADVANCED, Examples.ITEM_MAP.get(ADVANCED)); + recyclerView.setAdapter(adapter); } return view; } diff --git a/Android/APIExample/app/src/main/java/io/agora/api/example/common/adapter/ExampleSection.java b/Android/APIExample/app/src/main/java/io/agora/api/example/common/adapter/ExampleSection.java deleted file mode 100644 index 775f1ee35..000000000 --- a/Android/APIExample/app/src/main/java/io/agora/api/example/common/adapter/ExampleSection.java +++ /dev/null @@ -1,106 +0,0 @@ -package io.agora.api.example.common.adapter; - -import android.view.View; -import android.widget.TextView; - -import androidx.recyclerview.widget.RecyclerView; - -import java.util.List; - -import io.agora.api.example.MainFragment; -import io.agora.api.example.R; -import io.agora.api.example.annotation.Example; -import io.github.luizgrp.sectionedrecyclerviewadapter.Section; -import io.github.luizgrp.sectionedrecyclerviewadapter.SectionParameters; - -/** - * The type Example section. - */ -public class ExampleSection extends Section { - private final String mTitle; - private final List mValues; - private final MainFragment.OnListFragmentInteractionListener mListener; - - /** - * Instantiates a new Example section. - * - * @param title the title - * @param items the items - * @param listener the listener - */ - public ExampleSection(String title, List items, MainFragment.OnListFragmentInteractionListener listener) { - super(SectionParameters.builder().headerResourceId(R.layout.layout_main_list_section).itemResourceId(R.layout.layout_main_list_item).build()); - mTitle = title; - mValues = items; - mListener = listener; - } - - @Override - public int getContentItemsTotal() { - return mValues.size(); - } - - @Override - public RecyclerView.ViewHolder getItemViewHolder(View view) { - return new ViewHolder(view); - } - - @Override - public void onBindItemViewHolder(RecyclerView.ViewHolder viewHolder, int position) { - if (viewHolder instanceof ViewHolder) { - ViewHolder holder = (ViewHolder) viewHolder; - holder.mItem = mValues.get(position); - holder.mNameView.setText(holder.mView.getContext().getString(holder.mItem.name())); - - holder.mView.setOnClickListener(v -> { - if (null != mListener) { - // Notify the active callbacks interface (the activity, if the - // fragment is attached to one) that an item has been selected. - mListener.onListFragmentInteraction(holder.mItem); - } - }); - } - } - - @Override - public RecyclerView.ViewHolder getHeaderViewHolder(View view) { - return new ViewHolder(view); - } - - @Override - public void onBindHeaderViewHolder(RecyclerView.ViewHolder viewHolder) { - if (viewHolder instanceof ViewHolder) { - ViewHolder holder = (ViewHolder) viewHolder; - holder.mNameView.setText(mTitle); - } - } - - /** - * The type View holder. - */ - static class ViewHolder extends RecyclerView.ViewHolder { - /** - * The M view. - */ - final View mView; - /** - * The M name view. - */ - final TextView mNameView; - /** - * The M item. - */ - Example mItem; - - /** - * Instantiates a new View holder. - * - * @param view the view - */ - ViewHolder(View view) { - super(view); - mView = view; - mNameView = view.findViewById(R.id.item_name); - } - } -} diff --git a/Android/APIExample/app/src/main/java/io/agora/api/example/common/adapter/SectionAdapter.java b/Android/APIExample/app/src/main/java/io/agora/api/example/common/adapter/SectionAdapter.java new file mode 100644 index 000000000..4d02cd1cc --- /dev/null +++ b/Android/APIExample/app/src/main/java/io/agora/api/example/common/adapter/SectionAdapter.java @@ -0,0 +1,104 @@ +package io.agora.api.example.common.adapter; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; + +import io.agora.api.example.MainFragment; +import io.agora.api.example.R; +import io.agora.api.example.annotation.Example; + +/** + * Adapter for multiple sections with headers and items + */ +public class SectionAdapter extends RecyclerView.Adapter { + private static final int TYPE_HEADER = 0; + private static final int TYPE_ITEM = 1; + + private final List items = new ArrayList<>(); + private final MainFragment.OnListFragmentInteractionListener listener; + + public SectionAdapter(MainFragment.OnListFragmentInteractionListener listener) { + this.listener = listener; + } + + public void addSection(String title, List sectionItems) { + items.add(title); + if (sectionItems != null) { + items.addAll(sectionItems); + } + } + + @Override + public int getItemViewType(int position) { + return items.get(position) instanceof String ? TYPE_HEADER : TYPE_ITEM; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if (viewType == TYPE_HEADER) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.layout_main_list_section, parent, false); + return new HeaderViewHolder(view); + } else { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.layout_main_list_item, parent, false); + return new ItemViewHolder(view); + } + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (holder instanceof HeaderViewHolder) { + ((HeaderViewHolder) holder).bind((String) items.get(position)); + } else if (holder instanceof ItemViewHolder) { + ((ItemViewHolder) holder).bind((Example) items.get(position), listener); + } + } + + @Override + public int getItemCount() { + return items.size(); + } + + static class HeaderViewHolder extends RecyclerView.ViewHolder { + final TextView nameView; + + HeaderViewHolder(View view) { + super(view); + nameView = view.findViewById(R.id.item_name); + } + + void bind(String title) { + nameView.setText(title); + } + } + + static class ItemViewHolder extends RecyclerView.ViewHolder { + final View view; + final TextView nameView; + + ItemViewHolder(View itemView) { + super(itemView); + view = itemView; + nameView = itemView.findViewById(R.id.item_name); + } + + void bind(Example item, MainFragment.OnListFragmentInteractionListener listener) { + nameView.setText(view.getContext().getString(item.name())); + view.setOnClickListener(v -> { + if (listener != null) { + listener.onListFragmentInteraction(item); + } + }); + } + } +} diff --git a/Android/APIExample/build.gradle b/Android/APIExample/build.gradle index 2953eba41..5ebc2d319 100644 --- a/Android/APIExample/build.gradle +++ b/Android/APIExample/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '8.5.0' apply false - id 'com.android.library' version '8.5.0' apply false + id 'com.android.application' version '8.7.3' apply false + id 'com.android.library' version '8.7.3' apply false id 'org.jetbrains.kotlin.android' version '1.9.24' apply false id "io.gitlab.arturbosch.detekt" version "1.23.1" apply true id 'de.undercouch.download' version '4.1.2' apply false diff --git a/Android/APIExample/cloud_build.sh b/Android/APIExample/cloud_build.sh index a3a436481..6f4cf9b60 100755 --- a/Android/APIExample/cloud_build.sh +++ b/Android/APIExample/cloud_build.sh @@ -88,23 +88,26 @@ cd - || exit 1 ./gradlew clean || exit 1 ./gradlew :app:assembleRelease || exit 1 +# Extract SDK version from gradle.properties SDK_VERSION="" -if [ "$1" = "false" ]; then - sdk_version_file="./gradle.properties" - if [[ -f "$sdk_version_file" ]]; then +sdk_version_file="./gradle.properties" +if [[ -f "$sdk_version_file" ]]; then rtc_sdk_version=$(grep "rtc_sdk_version" "$sdk_version_file" | cut -d'=' -f2) if [[ -n "$rtc_sdk_version" ]]; then SDK_VERSION=$(echo "$rtc_sdk_version" | sed 's/^[ \t]*//;s/[ \t]*$//') + echo "SDK Version from gradle.properties: $SDK_VERSION" else - echo "rtc_sdk_version value not found" + echo "Warning: rtc_sdk_version value not found in gradle.properties" + SDK_VERSION="unknown" fi else - echo "file not found: $sdk_version_file" -fi -else - SDK_VERSION=$(echo $sdk_url | cut -d "/" -f 5) + echo "Warning: gradle.properties file not found" + SDK_VERSION="unknown" fi if [ "$WORKSPACE" != "" ]; then -cp app/build/outputs/apk/release/*.apk $WORKSPACE/APIExample_${BUILD_NUMBER}_${SDK_VERSION}_$(date "+%Y%m%d%H%M%S").apk + PROJECT_NAME="Shengwang-APIExample" + APK_NAME="${PROJECT_NAME}_${BUILD_NUMBER}_${SDK_VERSION}_$(date "+%Y%m%d%H%M%S").apk" + echo "Copying APK to: $WORKSPACE/$APK_NAME" + cp app/build/outputs/apk/release/*.apk "$WORKSPACE/$APK_NAME" fi \ No newline at end of file diff --git a/Android/APIExample/gradle.properties b/Android/APIExample/gradle.properties index 5d0cc99a9..da3958b21 100644 --- a/Android/APIExample/gradle.properties +++ b/Android/APIExample/gradle.properties @@ -25,4 +25,4 @@ simpleFilter = false # read enable stream encrypt section on README first before set this flag to TRUE streamEncrypt = false -rtc_sdk_version = 4.6.2 +rtc_sdk_version = 4.6.3 diff --git a/Android/APIExample/gradle/wrapper/gradle-wrapper.properties b/Android/APIExample/gradle/wrapper/gradle-wrapper.properties index aebf3a60d..880fc6969 100644 --- a/Android/APIExample/gradle/wrapper/gradle-wrapper.properties +++ b/Android/APIExample/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.7-bin.zip \ No newline at end of file +distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.9-bin.zip \ No newline at end of file diff --git a/Android/APIExample/settings.gradle b/Android/APIExample/settings.gradle index d7b219391..a4f56d1e2 100644 --- a/Android/APIExample/settings.gradle +++ b/Android/APIExample/settings.gradle @@ -29,7 +29,7 @@ dependencyResolutionManagement { maven { url 'https://maven.aliyun.com/repository/central' } } } -rootProject.name = 'APIExample' +rootProject.name = 'Shengwang-APIExample' include ':app' if (simpleFilter.toBoolean()) { include ':agora-simple-filter' diff --git a/iOS/APIExample-Audio/cloud_build.sh b/iOS/APIExample-Audio/cloud_build.sh index 73d2744fa..ddcfc3bc0 100755 --- a/iOS/APIExample-Audio/cloud_build.sh +++ b/iOS/APIExample-Audio/cloud_build.sh @@ -11,6 +11,84 @@ if [ "$BUILD_NUMBER" = "" ]; then BUILD_NUMBER=888 fi +# Version validation logic +echo "Starting branch version validation..." + +# Get current branch name (try multiple methods for CI environments) +BRANCH_NAME="" + +# Method 1: Try environment variable (Jenkins/GitLab CI) +if [ ! -z "$GIT_BRANCH" ]; then + BRANCH_NAME="$GIT_BRANCH" + echo "Branch from GIT_BRANCH: $BRANCH_NAME" +elif [ ! -z "$BRANCH_NAME" ]; then + echo "Branch from BRANCH_NAME: $BRANCH_NAME" +elif [ ! -z "$CI_COMMIT_REF_NAME" ]; then + BRANCH_NAME="$CI_COMMIT_REF_NAME" + echo "Branch from CI_COMMIT_REF_NAME: $BRANCH_NAME" +# Method 2: Try git command +elif [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ "$BRANCH_NAME" = "HEAD" ]; then + # In detached HEAD state, try to get branch from remote + BRANCH_NAME=$(git branch -r --contains HEAD | grep -v HEAD | head -1 | sed 's/^[[:space:]]*origin\///') + echo "Branch from git branch -r: $BRANCH_NAME" + else + echo "Branch from git rev-parse: $BRANCH_NAME" + fi +fi + +# Remove origin/ prefix if present (but keep the rest of the path) +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/^origin\///') + +if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then + echo "Warning: Unable to get Git branch name, skipping version validation" +else + echo "Current branch: $BRANCH_NAME" + + # Extract version from branch name (format: dev/x.x.x) + if [[ $BRANCH_NAME =~ ^dev/([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + BRANCH_VERSION="${BASH_REMATCH[1]}" + echo "Branch version: $BRANCH_VERSION" + + # Read MARKETING_VERSION from project.pbxproj + PBXPROJ_FILE="${PROJECT_PATH}/APIExample-Audio.xcodeproj/project.pbxproj" + if [ ! -f "$PBXPROJ_FILE" ]; then + echo "Error: project.pbxproj file not found: $PBXPROJ_FILE" + exit 1 + fi + + # Extract MARKETING_VERSION for main target + PLIST_VERSION=$(grep -A 2 "@executable_path/Frameworks" "$PBXPROJ_FILE" | grep "MARKETING_VERSION" | head -1 | sed 's/.*MARKETING_VERSION = \([^;]*\);/\1/' | tr -d ' ') + + if [ -z "$PLIST_VERSION" ]; then + echo "Error: Unable to read MARKETING_VERSION from project.pbxproj" + exit 1 + fi + + echo "Info.plist version: $PLIST_VERSION" + + # Compare versions + if [ "$BRANCH_VERSION" != "$PLIST_VERSION" ]; then + echo "Error: Version mismatch!" + echo " Branch version: $BRANCH_VERSION" + echo " Info.plist version: $PLIST_VERSION" + echo "Please ensure the version in branch name matches MARKETING_VERSION in Info.plist" + exit 1 + fi + + echo "✓ Version validation passed: $BRANCH_VERSION" + else + echo "Error: Branch name does not match dev/x.x.x format!" + echo "Current branch: $BRANCH_NAME" + echo "Required format: dev/x.x.x (e.g., dev/4.5.3)" + exit 1 + fi +fi + +echo "Version validation completed" +echo "-----------------------------------" + cd ${PROJECT_PATH} && pod install || exit 1 @@ -123,4 +201,57 @@ rm -rf "${EXPORT_PATH}" rm -rf "${ARCHIVE_PATH}" echo OUTPUT_FILE: $OUTPUT_FILE +echo "" +echo "==========================================" +echo "=== Certificate Expiration Information ===" +echo "==========================================" + +# 获取用于签名的证书信息 +SIGNING_CERT=$(security find-identity -v -p codesigning | grep "iPhone Distribution\|Apple Distribution\|iOS Distribution" | head -1 | awk -F'"' '{print $2}') + +if [ ! -z "$SIGNING_CERT" ]; then + echo "Signing Certificate: $SIGNING_CERT" + + # 获取证书的详细信息 + CERT_INFO=$(security find-certificate -c "$SIGNING_CERT" -p | openssl x509 -noout -dates 2>/dev/null) + + if [ $? -eq 0 ]; then + echo "$CERT_INFO" + + # 提取过期日期 + EXPIRY_DATE=$(echo "$CERT_INFO" | grep "notAfter" | cut -d= -f2) + echo "" + echo "⚠️ Certificate will expire on: $EXPIRY_DATE" + + # 计算剩余天数 + if command -v gdate >/dev/null 2>&1; then + # macOS with GNU coreutils installed + EXPIRY_EPOCH=$(gdate -d "$EXPIRY_DATE" +%s 2>/dev/null) + CURRENT_EPOCH=$(gdate +%s) + else + # macOS default date command + EXPIRY_EPOCH=$(date -j -f "%b %d %T %Y %Z" "$EXPIRY_DATE" +%s 2>/dev/null) + CURRENT_EPOCH=$(date +%s) + fi + + if [ ! -z "$EXPIRY_EPOCH" ] && [ ! -z "$CURRENT_EPOCH" ]; then + DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 )) + echo "📅 Days remaining: $DAYS_LEFT days" + + if [ $DAYS_LEFT -lt 30 ]; then + echo "🚨 WARNING: Certificate will expire in less than 30 days!" + elif [ $DAYS_LEFT -lt 90 ]; then + echo "⚠️ NOTICE: Certificate will expire in less than 90 days" + fi + fi + else + echo "Unable to retrieve certificate expiration information" + fi +else + echo "No distribution certificate found" +fi + +echo "==========================================" +echo "" + diff --git a/iOS/APIExample-Audio/cloud_project.sh b/iOS/APIExample-Audio/cloud_project.sh index d29b833f7..2ddf45388 100755 --- a/iOS/APIExample-Audio/cloud_project.sh +++ b/iOS/APIExample-Audio/cloud_project.sh @@ -9,6 +9,84 @@ if [ "$BUILD_NUMBER" = "" ]; then BUILD_NUMBER=888 fi +# Version validation logic +echo "Starting branch version validation..." + +# Get current branch name (try multiple methods for CI environments) +BRANCH_NAME="" + +# Method 1: Try environment variable (Jenkins/GitLab CI) +if [ ! -z "$GIT_BRANCH" ]; then + BRANCH_NAME="$GIT_BRANCH" + echo "Branch from GIT_BRANCH: $BRANCH_NAME" +elif [ ! -z "$BRANCH_NAME" ]; then + echo "Branch from BRANCH_NAME: $BRANCH_NAME" +elif [ ! -z "$CI_COMMIT_REF_NAME" ]; then + BRANCH_NAME="$CI_COMMIT_REF_NAME" + echo "Branch from CI_COMMIT_REF_NAME: $BRANCH_NAME" +# Method 2: Try git command +elif [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ "$BRANCH_NAME" = "HEAD" ]; then + # In detached HEAD state, try to get branch from remote + BRANCH_NAME=$(git branch -r --contains HEAD | grep -v HEAD | head -1 | sed 's/^[[:space:]]*origin\///') + echo "Branch from git branch -r: $BRANCH_NAME" + else + echo "Branch from git rev-parse: $BRANCH_NAME" + fi +fi + +# Remove origin/ prefix if present (but keep the rest of the path) +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/^origin\///') + +if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then + echo "Warning: Unable to get Git branch name, skipping version validation" +else + echo "Current branch: $BRANCH_NAME" + + # Extract version from branch name (format: dev/x.x.x) + if [[ $BRANCH_NAME =~ ^dev/([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + BRANCH_VERSION="${BASH_REMATCH[1]}" + echo "Branch version: $BRANCH_VERSION" + + # Read MARKETING_VERSION from project.pbxproj + PBXPROJ_FILE="${PROJECT_PATH}/APIExample-Audio.xcodeproj/project.pbxproj" + if [ ! -f "$PBXPROJ_FILE" ]; then + echo "Error: project.pbxproj file not found: $PBXPROJ_FILE" + exit 1 + fi + + # Extract MARKETING_VERSION for main target + PLIST_VERSION=$(grep -A 2 "@executable_path/Frameworks" "$PBXPROJ_FILE" | grep "MARKETING_VERSION" | head -1 | sed 's/.*MARKETING_VERSION = \([^;]*\);/\1/' | tr -d ' ') + + if [ -z "$PLIST_VERSION" ]; then + echo "Error: Unable to read MARKETING_VERSION from project.pbxproj" + exit 1 + fi + + echo "Info.plist version: $PLIST_VERSION" + + # Compare versions + if [ "$BRANCH_VERSION" != "$PLIST_VERSION" ]; then + echo "Error: Version mismatch!" + echo " Branch version: $BRANCH_VERSION" + echo " Info.plist version: $PLIST_VERSION" + echo "Please ensure the version in branch name matches MARKETING_VERSION in Info.plist" + exit 1 + fi + + echo "✓ Version validation passed: $BRANCH_VERSION" + else + echo "Error: Branch name does not match dev/x.x.x format!" + echo "Current branch: $BRANCH_NAME" + echo "Required format: dev/x.x.x (e.g., dev/4.5.3)" + exit 1 + fi +fi + +echo "Version validation completed" +echo "-----------------------------------" + cd ${PROJECT_PATH} && pod install || exit 1 diff --git a/iOS/APIExample-OC/cloud_build.sh b/iOS/APIExample-OC/cloud_build.sh index b9ab73455..8de769a05 100755 --- a/iOS/APIExample-OC/cloud_build.sh +++ b/iOS/APIExample-OC/cloud_build.sh @@ -11,6 +11,84 @@ if [ "$BUILD_NUMBER" = "" ]; then BUILD_NUMBER=888 fi +# Version validation logic +echo "Starting branch version validation..." + +# Get current branch name (try multiple methods for CI environments) +BRANCH_NAME="" + +# Method 1: Try environment variable (Jenkins/GitLab CI) +if [ ! -z "$GIT_BRANCH" ]; then + BRANCH_NAME="$GIT_BRANCH" + echo "Branch from GIT_BRANCH: $BRANCH_NAME" +elif [ ! -z "$BRANCH_NAME" ]; then + echo "Branch from BRANCH_NAME: $BRANCH_NAME" +elif [ ! -z "$CI_COMMIT_REF_NAME" ]; then + BRANCH_NAME="$CI_COMMIT_REF_NAME" + echo "Branch from CI_COMMIT_REF_NAME: $BRANCH_NAME" +# Method 2: Try git command +elif [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ "$BRANCH_NAME" = "HEAD" ]; then + # In detached HEAD state, try to get branch from remote + BRANCH_NAME=$(git branch -r --contains HEAD | grep -v HEAD | head -1 | sed 's/^[[:space:]]*origin\///') + echo "Branch from git branch -r: $BRANCH_NAME" + else + echo "Branch from git rev-parse: $BRANCH_NAME" + fi +fi + +# Remove origin/ prefix if present (but keep the rest of the path) +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/^origin\///') + +if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then + echo "Warning: Unable to get Git branch name, skipping version validation" +else + echo "Current branch: $BRANCH_NAME" + + # Extract version from branch name (format: dev/x.x.x) + if [[ $BRANCH_NAME =~ ^dev/([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + BRANCH_VERSION="${BASH_REMATCH[1]}" + echo "Branch version: $BRANCH_VERSION" + + # Read MARKETING_VERSION from project.pbxproj + PBXPROJ_FILE="${PROJECT_PATH}/APIExample-OC.xcodeproj/project.pbxproj" + if [ ! -f "$PBXPROJ_FILE" ]; then + echo "Error: project.pbxproj file not found: $PBXPROJ_FILE" + exit 1 + fi + + # Extract MARKETING_VERSION for main target + PLIST_VERSION=$(grep -A 2 "@executable_path/Frameworks" "$PBXPROJ_FILE" | grep "MARKETING_VERSION" | head -1 | sed 's/.*MARKETING_VERSION = \([^;]*\);/\1/' | tr -d ' ') + + if [ -z "$PLIST_VERSION" ]; then + echo "Error: Unable to read MARKETING_VERSION from project.pbxproj" + exit 1 + fi + + echo "Info.plist version: $PLIST_VERSION" + + # Compare versions + if [ "$BRANCH_VERSION" != "$PLIST_VERSION" ]; then + echo "Error: Version mismatch!" + echo " Branch version: $BRANCH_VERSION" + echo " Info.plist version: $PLIST_VERSION" + echo "Please ensure the version in branch name matches MARKETING_VERSION in Info.plist" + exit 1 + fi + + echo "✓ Version validation passed: $BRANCH_VERSION" + else + echo "Error: Branch name does not match dev/x.x.x format!" + echo "Current branch: $BRANCH_NAME" + echo "Required format: dev/x.x.x (e.g., dev/4.5.3)" + exit 1 + fi +fi + +echo "Version validation completed" +echo "-----------------------------------" + cd ${PROJECT_PATH} && pod install || exit 1 # 打包环境 @@ -156,4 +234,57 @@ rm -rf "${EXPORT_PATH}" rm -rf "${ARCHIVE_PATH}" echo OUTPUT_FILE: $OUTPUT_FILE +echo "" +echo "==========================================" +echo "=== Certificate Expiration Information ===" +echo "==========================================" + +# 获取用于签名的证书信息 +SIGNING_CERT=$(security find-identity -v -p codesigning | grep "iPhone Distribution\|Apple Distribution\|iOS Distribution" | head -1 | awk -F'"' '{print $2}') + +if [ ! -z "$SIGNING_CERT" ]; then + echo "Signing Certificate: $SIGNING_CERT" + + # 获取证书的详细信息 + CERT_INFO=$(security find-certificate -c "$SIGNING_CERT" -p | openssl x509 -noout -dates 2>/dev/null) + + if [ $? -eq 0 ]; then + echo "$CERT_INFO" + + # 提取过期日期 + EXPIRY_DATE=$(echo "$CERT_INFO" | grep "notAfter" | cut -d= -f2) + echo "" + echo "⚠️ Certificate will expire on: $EXPIRY_DATE" + + # 计算剩余天数 + if command -v gdate >/dev/null 2>&1; then + # macOS with GNU coreutils installed + EXPIRY_EPOCH=$(gdate -d "$EXPIRY_DATE" +%s 2>/dev/null) + CURRENT_EPOCH=$(gdate +%s) + else + # macOS default date command + EXPIRY_EPOCH=$(date -j -f "%b %d %T %Y %Z" "$EXPIRY_DATE" +%s 2>/dev/null) + CURRENT_EPOCH=$(date +%s) + fi + + if [ ! -z "$EXPIRY_EPOCH" ] && [ ! -z "$CURRENT_EPOCH" ]; then + DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 )) + echo "📅 Days remaining: $DAYS_LEFT days" + + if [ $DAYS_LEFT -lt 30 ]; then + echo "🚨 WARNING: Certificate will expire in less than 30 days!" + elif [ $DAYS_LEFT -lt 90 ]; then + echo "⚠️ NOTICE: Certificate will expire in less than 90 days" + fi + fi + else + echo "Unable to retrieve certificate expiration information" + fi +else + echo "No distribution certificate found" +fi + +echo "==========================================" +echo "" + diff --git a/iOS/APIExample-OC/cloud_project.sh b/iOS/APIExample-OC/cloud_project.sh index d29b833f7..3fb18857e 100755 --- a/iOS/APIExample-OC/cloud_project.sh +++ b/iOS/APIExample-OC/cloud_project.sh @@ -9,6 +9,84 @@ if [ "$BUILD_NUMBER" = "" ]; then BUILD_NUMBER=888 fi +# Version validation logic +echo "Starting branch version validation..." + +# Get current branch name (try multiple methods for CI environments) +BRANCH_NAME="" + +# Method 1: Try environment variable (Jenkins/GitLab CI) +if [ ! -z "$GIT_BRANCH" ]; then + BRANCH_NAME="$GIT_BRANCH" + echo "Branch from GIT_BRANCH: $BRANCH_NAME" +elif [ ! -z "$BRANCH_NAME" ]; then + echo "Branch from BRANCH_NAME: $BRANCH_NAME" +elif [ ! -z "$CI_COMMIT_REF_NAME" ]; then + BRANCH_NAME="$CI_COMMIT_REF_NAME" + echo "Branch from CI_COMMIT_REF_NAME: $BRANCH_NAME" +# Method 2: Try git command +elif [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ "$BRANCH_NAME" = "HEAD" ]; then + # In detached HEAD state, try to get branch from remote + BRANCH_NAME=$(git branch -r --contains HEAD | grep -v HEAD | head -1 | sed 's/^[[:space:]]*origin\///') + echo "Branch from git branch -r: $BRANCH_NAME" + else + echo "Branch from git rev-parse: $BRANCH_NAME" + fi +fi + +# Remove origin/ prefix if present (but keep the rest of the path) +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/^origin\///') + +if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then + echo "Warning: Unable to get Git branch name, skipping version validation" +else + echo "Current branch: $BRANCH_NAME" + + # Extract version from branch name (format: dev/x.x.x) + if [[ $BRANCH_NAME =~ ^dev/([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + BRANCH_VERSION="${BASH_REMATCH[1]}" + echo "Branch version: $BRANCH_VERSION" + + # Read MARKETING_VERSION from project.pbxproj + PBXPROJ_FILE="${PROJECT_PATH}/APIExample-OC.xcodeproj/project.pbxproj" + if [ ! -f "$PBXPROJ_FILE" ]; then + echo "Error: project.pbxproj file not found: $PBXPROJ_FILE" + exit 1 + fi + + # Extract MARKETING_VERSION for main target + PLIST_VERSION=$(grep -A 2 "@executable_path/Frameworks" "$PBXPROJ_FILE" | grep "MARKETING_VERSION" | head -1 | sed 's/.*MARKETING_VERSION = \([^;]*\);/\1/' | tr -d ' ') + + if [ -z "$PLIST_VERSION" ]; then + echo "Error: Unable to read MARKETING_VERSION from project.pbxproj" + exit 1 + fi + + echo "Info.plist version: $PLIST_VERSION" + + # Compare versions + if [ "$BRANCH_VERSION" != "$PLIST_VERSION" ]; then + echo "Error: Version mismatch!" + echo " Branch version: $BRANCH_VERSION" + echo " Info.plist version: $PLIST_VERSION" + echo "Please ensure the version in branch name matches MARKETING_VERSION in Info.plist" + exit 1 + fi + + echo "✓ Version validation passed: $BRANCH_VERSION" + else + echo "Error: Branch name does not match dev/x.x.x format!" + echo "Current branch: $BRANCH_NAME" + echo "Required format: dev/x.x.x (e.g., dev/4.5.3)" + exit 1 + fi +fi + +echo "Version validation completed" +echo "-----------------------------------" + cd ${PROJECT_PATH} && pod install || exit 1 diff --git a/iOS/APIExample-SwiftUI/cloud_build.sh b/iOS/APIExample-SwiftUI/cloud_build.sh index b31879c68..0cb703a92 100755 --- a/iOS/APIExample-SwiftUI/cloud_build.sh +++ b/iOS/APIExample-SwiftUI/cloud_build.sh @@ -11,6 +11,84 @@ if [ "$BUILD_NUMBER" = "" ]; then BUILD_NUMBER=888 fi +# Version validation logic +echo "Starting branch version validation..." + +# Get current branch name (try multiple methods for CI environments) +BRANCH_NAME="" + +# Method 1: Try environment variable (Jenkins/GitLab CI) +if [ ! -z "$GIT_BRANCH" ]; then + BRANCH_NAME="$GIT_BRANCH" + echo "Branch from GIT_BRANCH: $BRANCH_NAME" +elif [ ! -z "$BRANCH_NAME" ]; then + echo "Branch from BRANCH_NAME: $BRANCH_NAME" +elif [ ! -z "$CI_COMMIT_REF_NAME" ]; then + BRANCH_NAME="$CI_COMMIT_REF_NAME" + echo "Branch from CI_COMMIT_REF_NAME: $BRANCH_NAME" +# Method 2: Try git command +elif [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ "$BRANCH_NAME" = "HEAD" ]; then + # In detached HEAD state, try to get branch from remote + BRANCH_NAME=$(git branch -r --contains HEAD | grep -v HEAD | head -1 | sed 's/^[[:space:]]*origin\///') + echo "Branch from git branch -r: $BRANCH_NAME" + else + echo "Branch from git rev-parse: $BRANCH_NAME" + fi +fi + +# Remove origin/ prefix if present (but keep the rest of the path) +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/^origin\///') + +if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then + echo "Warning: Unable to get Git branch name, skipping version validation" +else + echo "Current branch: $BRANCH_NAME" + + # Extract version from branch name (format: dev/x.x.x) + if [[ $BRANCH_NAME =~ ^dev/([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + BRANCH_VERSION="${BASH_REMATCH[1]}" + echo "Branch version: $BRANCH_VERSION" + + # Read MARKETING_VERSION from project.pbxproj + PBXPROJ_FILE="${PROJECT_PATH}/APIExample-SwiftUI.xcodeproj/project.pbxproj" + if [ ! -f "$PBXPROJ_FILE" ]; then + echo "Error: project.pbxproj file not found: $PBXPROJ_FILE" + exit 1 + fi + + # Extract MARKETING_VERSION for main target + PLIST_VERSION=$(grep -A 2 "@executable_path/Frameworks" "$PBXPROJ_FILE" | grep "MARKETING_VERSION" | head -1 | sed 's/.*MARKETING_VERSION = \([^;]*\);/\1/' | tr -d ' ') + + if [ -z "$PLIST_VERSION" ]; then + echo "Error: Unable to read MARKETING_VERSION from project.pbxproj" + exit 1 + fi + + echo "Info.plist version: $PLIST_VERSION" + + # Compare versions + if [ "$BRANCH_VERSION" != "$PLIST_VERSION" ]; then + echo "Error: Version mismatch!" + echo " Branch version: $BRANCH_VERSION" + echo " Info.plist version: $PLIST_VERSION" + echo "Please ensure the version in branch name matches MARKETING_VERSION in Info.plist" + exit 1 + fi + + echo "✓ Version validation passed: $BRANCH_VERSION" + else + echo "Error: Branch name does not match dev/x.x.x format!" + echo "Current branch: $BRANCH_NAME" + echo "Required format: dev/x.x.x (e.g., dev/4.5.3)" + exit 1 + fi +fi + +echo "Version validation completed" +echo "-----------------------------------" + cd ${PROJECT_PATH} pod install || exit 1 @@ -135,4 +213,57 @@ rm -rf "${EXPORT_PATH}" rm -rf "${ARCHIVE_PATH}" echo OUTPUT_FILE: $OUTPUT_FILE +echo "" +echo "==========================================" +echo "=== Certificate Expiration Information ===" +echo "==========================================" + +# 获取用于签名的证书信息 +SIGNING_CERT=$(security find-identity -v -p codesigning | grep "iPhone Distribution\|Apple Distribution\|iOS Distribution" | head -1 | awk -F'"' '{print $2}') + +if [ ! -z "$SIGNING_CERT" ]; then + echo "Signing Certificate: $SIGNING_CERT" + + # 获取证书的详细信息 + CERT_INFO=$(security find-certificate -c "$SIGNING_CERT" -p | openssl x509 -noout -dates 2>/dev/null) + + if [ $? -eq 0 ]; then + echo "$CERT_INFO" + + # 提取过期日期 + EXPIRY_DATE=$(echo "$CERT_INFO" | grep "notAfter" | cut -d= -f2) + echo "" + echo "⚠️ Certificate will expire on: $EXPIRY_DATE" + + # 计算剩余天数 + if command -v gdate >/dev/null 2>&1; then + # macOS with GNU coreutils installed + EXPIRY_EPOCH=$(gdate -d "$EXPIRY_DATE" +%s 2>/dev/null) + CURRENT_EPOCH=$(gdate +%s) + else + # macOS default date command + EXPIRY_EPOCH=$(date -j -f "%b %d %T %Y %Z" "$EXPIRY_DATE" +%s 2>/dev/null) + CURRENT_EPOCH=$(date +%s) + fi + + if [ ! -z "$EXPIRY_EPOCH" ] && [ ! -z "$CURRENT_EPOCH" ]; then + DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 )) + echo "📅 Days remaining: $DAYS_LEFT days" + + if [ $DAYS_LEFT -lt 30 ]; then + echo "🚨 WARNING: Certificate will expire in less than 30 days!" + elif [ $DAYS_LEFT -lt 90 ]; then + echo "⚠️ NOTICE: Certificate will expire in less than 90 days" + fi + fi + else + echo "Unable to retrieve certificate expiration information" + fi +else + echo "No distribution certificate found" +fi + +echo "==========================================" +echo "" + diff --git a/iOS/APIExample-SwiftUI/cloud_project.sh b/iOS/APIExample-SwiftUI/cloud_project.sh index d29b833f7..fee7c0b4a 100755 --- a/iOS/APIExample-SwiftUI/cloud_project.sh +++ b/iOS/APIExample-SwiftUI/cloud_project.sh @@ -9,6 +9,84 @@ if [ "$BUILD_NUMBER" = "" ]; then BUILD_NUMBER=888 fi +# Version validation logic +echo "Starting branch version validation..." + +# Get current branch name (try multiple methods for CI environments) +BRANCH_NAME="" + +# Method 1: Try environment variable (Jenkins/GitLab CI) +if [ ! -z "$GIT_BRANCH" ]; then + BRANCH_NAME="$GIT_BRANCH" + echo "Branch from GIT_BRANCH: $BRANCH_NAME" +elif [ ! -z "$BRANCH_NAME" ]; then + echo "Branch from BRANCH_NAME: $BRANCH_NAME" +elif [ ! -z "$CI_COMMIT_REF_NAME" ]; then + BRANCH_NAME="$CI_COMMIT_REF_NAME" + echo "Branch from CI_COMMIT_REF_NAME: $BRANCH_NAME" +# Method 2: Try git command +elif [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ "$BRANCH_NAME" = "HEAD" ]; then + # In detached HEAD state, try to get branch from remote + BRANCH_NAME=$(git branch -r --contains HEAD | grep -v HEAD | head -1 | sed 's/^[[:space:]]*origin\///') + echo "Branch from git branch -r: $BRANCH_NAME" + else + echo "Branch from git rev-parse: $BRANCH_NAME" + fi +fi + +# Remove origin/ prefix if present (but keep the rest of the path) +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/^origin\///') + +if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then + echo "Warning: Unable to get Git branch name, skipping version validation" +else + echo "Current branch: $BRANCH_NAME" + + # Extract version from branch name (format: dev/x.x.x) + if [[ $BRANCH_NAME =~ ^dev/([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + BRANCH_VERSION="${BASH_REMATCH[1]}" + echo "Branch version: $BRANCH_VERSION" + + # Read MARKETING_VERSION from project.pbxproj + PBXPROJ_FILE="${PROJECT_PATH}/APIExample-SwiftUI.xcodeproj/project.pbxproj" + if [ ! -f "$PBXPROJ_FILE" ]; then + echo "Error: project.pbxproj file not found: $PBXPROJ_FILE" + exit 1 + fi + + # Extract MARKETING_VERSION for main target + PLIST_VERSION=$(grep -A 2 "@executable_path/Frameworks" "$PBXPROJ_FILE" | grep "MARKETING_VERSION" | head -1 | sed 's/.*MARKETING_VERSION = \([^;]*\);/\1/' | tr -d ' ') + + if [ -z "$PLIST_VERSION" ]; then + echo "Error: Unable to read MARKETING_VERSION from project.pbxproj" + exit 1 + fi + + echo "Info.plist version: $PLIST_VERSION" + + # Compare versions + if [ "$BRANCH_VERSION" != "$PLIST_VERSION" ]; then + echo "Error: Version mismatch!" + echo " Branch version: $BRANCH_VERSION" + echo " Info.plist version: $PLIST_VERSION" + echo "Please ensure the version in branch name matches MARKETING_VERSION in Info.plist" + exit 1 + fi + + echo "✓ Version validation passed: $BRANCH_VERSION" + else + echo "Error: Branch name does not match dev/x.x.x format!" + echo "Current branch: $BRANCH_NAME" + echo "Required format: dev/x.x.x (e.g., dev/4.5.3)" + exit 1 + fi +fi + +echo "Version validation completed" +echo "-----------------------------------" + cd ${PROJECT_PATH} && pod install || exit 1 diff --git a/iOS/APIExample/APIExample.xcodeproj/project.pbxproj b/iOS/APIExample/APIExample.xcodeproj/project.pbxproj index 8e58f525a..d149529d7 100644 --- a/iOS/APIExample/APIExample.xcodeproj/project.pbxproj +++ b/iOS/APIExample/APIExample.xcodeproj/project.pbxproj @@ -1736,10 +1736,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-APIExample/Pods-APIExample-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-APIExample/Pods-APIExample-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-APIExample/Pods-APIExample-frameworks.sh\"\n"; @@ -2742,7 +2746,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 4.6.2; + MARKETING_VERSION = 4.5.3; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -2813,7 +2817,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 4.6.2; + MARKETING_VERSION = 4.5.3; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", diff --git a/iOS/APIExample/cloud_build.sh b/iOS/APIExample/cloud_build.sh index 9721709b4..0106b4814 100755 --- a/iOS/APIExample/cloud_build.sh +++ b/iOS/APIExample/cloud_build.sh @@ -11,6 +11,85 @@ if [ "$BUILD_NUMBER" = "" ]; then BUILD_NUMBER=888 fi +# Version validation logic +echo "Starting branch version validation..." + +# Get current branch name (try multiple methods for CI environments) +BRANCH_NAME="" + +# Method 1: Try environment variable (Jenkins/GitLab CI) +if [ ! -z "$GIT_BRANCH" ]; then + BRANCH_NAME="$GIT_BRANCH" + echo "Branch from GIT_BRANCH: $BRANCH_NAME" +elif [ ! -z "$BRANCH_NAME" ]; then + echo "Branch from BRANCH_NAME: $BRANCH_NAME" +elif [ ! -z "$CI_COMMIT_REF_NAME" ]; then + BRANCH_NAME="$CI_COMMIT_REF_NAME" + echo "Branch from CI_COMMIT_REF_NAME: $BRANCH_NAME" +# Method 2: Try git command +elif [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ "$BRANCH_NAME" = "HEAD" ]; then + # In detached HEAD state, try to get branch from remote + BRANCH_NAME=$(git branch -r --contains HEAD | grep -v HEAD | head -1 | sed 's/^[[:space:]]*origin\///') + echo "Branch from git branch -r: $BRANCH_NAME" + else + echo "Branch from git rev-parse: $BRANCH_NAME" + fi +fi + +# Remove origin/ prefix if present (but keep the rest of the path) +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/^origin\///') + +if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then + echo "Warning: Unable to get Git branch name, skipping version validation" +else + echo "Current branch: $BRANCH_NAME" + + # Extract version from branch name (format: dev/x.x.x) + if [[ $BRANCH_NAME =~ ^dev/([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + BRANCH_VERSION="${BASH_REMATCH[1]}" + echo "Branch version: $BRANCH_VERSION" + + # Read MARKETING_VERSION from project.pbxproj + PBXPROJ_FILE="${PROJECT_PATH}/APIExample.xcodeproj/project.pbxproj" + if [ ! -f "$PBXPROJ_FILE" ]; then + echo "Error: project.pbxproj file not found: $PBXPROJ_FILE" + exit 1 + fi + + # Extract MARKETING_VERSION for main target (skip Extension targets) + # Look for the version that appears with @executable_path/Frameworks (main app) + PLIST_VERSION=$(grep -A 2 "@executable_path/Frameworks" "$PBXPROJ_FILE" | grep "MARKETING_VERSION" | head -1 | sed 's/.*MARKETING_VERSION = \([^;]*\);/\1/' | tr -d ' ') + + if [ -z "$PLIST_VERSION" ]; then + echo "Error: Unable to read MARKETING_VERSION from project.pbxproj" + exit 1 + fi + + echo "Info.plist version: $PLIST_VERSION" + + # Compare versions + if [ "$BRANCH_VERSION" != "$PLIST_VERSION" ]; then + echo "Error: Version mismatch!" + echo " Branch version: $BRANCH_VERSION" + echo " Info.plist version: $PLIST_VERSION" + echo "Please ensure the version in branch name matches MARKETING_VERSION in Info.plist" + exit 1 + fi + + echo "✓ Version validation passed: $BRANCH_VERSION" + else + echo "Error: Branch name does not match dev/x.x.x format!" + echo "Current branch: $BRANCH_NAME" + echo "Required format: dev/x.x.x (e.g., dev/4.5.3)" + exit 1 + fi +fi + +echo "Version validation completed" +echo "-----------------------------------" + cd ${PROJECT_PATH} @@ -205,4 +284,57 @@ rm -rf "${EXPORT_PATH}" rm -rf "${ARCHIVE_PATH}" echo OUTPUT_FILE: $OUTPUT_FILE +echo "" +echo "==========================================" +echo "=== Certificate Expiration Information ===" +echo "==========================================" + +# 获取用于签名的证书信息 +SIGNING_CERT=$(security find-identity -v -p codesigning | grep "iPhone Distribution\|Apple Distribution\|iOS Distribution" | head -1 | awk -F'"' '{print $2}') + +if [ ! -z "$SIGNING_CERT" ]; then + echo "Signing Certificate: $SIGNING_CERT" + + # 获取证书的详细信息 + CERT_INFO=$(security find-certificate -c "$SIGNING_CERT" -p | openssl x509 -noout -dates 2>/dev/null) + + if [ $? -eq 0 ]; then + echo "$CERT_INFO" + + # 提取过期日期 + EXPIRY_DATE=$(echo "$CERT_INFO" | grep "notAfter" | cut -d= -f2) + echo "" + echo "⚠️ Certificate will expire on: $EXPIRY_DATE" + + # 计算剩余天数 + if command -v gdate >/dev/null 2>&1; then + # macOS with GNU coreutils installed + EXPIRY_EPOCH=$(gdate -d "$EXPIRY_DATE" +%s 2>/dev/null) + CURRENT_EPOCH=$(gdate +%s) + else + # macOS default date command + EXPIRY_EPOCH=$(date -j -f "%b %d %T %Y %Z" "$EXPIRY_DATE" +%s 2>/dev/null) + CURRENT_EPOCH=$(date +%s) + fi + + if [ ! -z "$EXPIRY_EPOCH" ] && [ ! -z "$CURRENT_EPOCH" ]; then + DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 )) + echo "📅 Days remaining: $DAYS_LEFT days" + + if [ $DAYS_LEFT -lt 30 ]; then + echo "🚨 WARNING: Certificate will expire in less than 30 days!" + elif [ $DAYS_LEFT -lt 90 ]; then + echo "⚠️ NOTICE: Certificate will expire in less than 90 days" + fi + fi + else + echo "Unable to retrieve certificate expiration information" + fi +else + echo "No distribution certificate found" +fi + +echo "==========================================" +echo "" + diff --git a/iOS/APIExample/cloud_project.sh b/iOS/APIExample/cloud_project.sh index 52c7e703e..839242e9d 100755 --- a/iOS/APIExample/cloud_project.sh +++ b/iOS/APIExample/cloud_project.sh @@ -9,6 +9,85 @@ if [ "$BUILD_NUMBER" = "" ]; then BUILD_NUMBER=888 fi +# Version validation logic +echo "Starting branch version validation..." + +# Get current branch name (try multiple methods for CI environments) +BRANCH_NAME="" + +# Method 1: Try environment variable (Jenkins/GitLab CI) +if [ ! -z "$GIT_BRANCH" ]; then + BRANCH_NAME="$GIT_BRANCH" + echo "Branch from GIT_BRANCH: $BRANCH_NAME" +elif [ ! -z "$BRANCH_NAME" ]; then + echo "Branch from BRANCH_NAME: $BRANCH_NAME" +elif [ ! -z "$CI_COMMIT_REF_NAME" ]; then + BRANCH_NAME="$CI_COMMIT_REF_NAME" + echo "Branch from CI_COMMIT_REF_NAME: $BRANCH_NAME" +# Method 2: Try git command +elif [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ "$BRANCH_NAME" = "HEAD" ]; then + # In detached HEAD state, try to get branch from remote + BRANCH_NAME=$(git branch -r --contains HEAD | grep -v HEAD | head -1 | sed 's/^[[:space:]]*origin\///') + echo "Branch from git branch -r: $BRANCH_NAME" + else + echo "Branch from git rev-parse: $BRANCH_NAME" + fi +fi + +# Remove origin/ prefix if present (but keep the rest of the path) +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/^origin\///') + +if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then + echo "Warning: Unable to get Git branch name, skipping version validation" +else + echo "Current branch: $BRANCH_NAME" + + # Extract version from branch name (format: dev/x.x.x) + if [[ $BRANCH_NAME =~ ^dev/([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + BRANCH_VERSION="${BASH_REMATCH[1]}" + echo "Branch version: $BRANCH_VERSION" + + # Read MARKETING_VERSION from project.pbxproj + PBXPROJ_FILE="${PROJECT_PATH}/APIExample.xcodeproj/project.pbxproj" + if [ ! -f "$PBXPROJ_FILE" ]; then + echo "Error: project.pbxproj file not found: $PBXPROJ_FILE" + exit 1 + fi + + # Extract MARKETING_VERSION for main target (skip Extension targets) + # Look for the version that appears with @executable_path/Frameworks (main app) + PLIST_VERSION=$(grep -A 2 "@executable_path/Frameworks" "$PBXPROJ_FILE" | grep "MARKETING_VERSION" | head -1 | sed 's/.*MARKETING_VERSION = \([^;]*\);/\1/' | tr -d ' ') + + if [ -z "$PLIST_VERSION" ]; then + echo "Error: Unable to read MARKETING_VERSION from project.pbxproj" + exit 1 + fi + + echo "Info.plist version: $PLIST_VERSION" + + # Compare versions + if [ "$BRANCH_VERSION" != "$PLIST_VERSION" ]; then + echo "Error: Version mismatch!" + echo " Branch version: $BRANCH_VERSION" + echo " Info.plist version: $PLIST_VERSION" + echo "Please ensure the version in branch name matches MARKETING_VERSION in Info.plist" + exit 1 + fi + + echo "✓ Version validation passed: $BRANCH_VERSION" + else + echo "Error: Branch name does not match dev/x.x.x format!" + echo "Current branch: $BRANCH_NAME" + echo "Required format: dev/x.x.x (e.g., dev/4.5.3)" + exit 1 + fi +fi + +echo "Version validation completed" +echo "-----------------------------------" + #下载美颜资源 echo "start download bytedance resource : $bytedance_lib" curl -L -O "$bytedance_lib" diff --git a/macOS/APIExample.xcodeproj/project.pbxproj b/macOS/APIExample.xcodeproj/project.pbxproj index 9a8f83228..0454b17ea 100644 --- a/macOS/APIExample.xcodeproj/project.pbxproj +++ b/macOS/APIExample.xcodeproj/project.pbxproj @@ -1189,10 +1189,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-APIExample/Pods-APIExample-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-APIExample/Pods-APIExample-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-APIExample/Pods-APIExample-frameworks.sh\"\n"; @@ -1819,7 +1823,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 4.6.2; + MARKETING_VERSION = 4.5.3; PRODUCT_BUNDLE_IDENTIFIER = io.agora.api.examples; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1851,7 +1855,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 4.6.2; + MARKETING_VERSION = 4.5.3; PRODUCT_BUNDLE_IDENTIFIER = io.agora.api.examples; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/macOS/cloud_build.sh b/macOS/cloud_build.sh index ecf482327..adaf6647d 100755 --- a/macOS/cloud_build.sh +++ b/macOS/cloud_build.sh @@ -11,6 +11,85 @@ if [ "$BUILD_NUMBER" = "" ]; then BUILD_NUMBER=888 fi +# Version validation logic +echo "Starting branch version validation..." + +# Get current branch name (try multiple methods for CI environments) +BRANCH_NAME="" + +# Method 1: Try environment variable (Jenkins/GitLab CI) +if [ ! -z "$GIT_BRANCH" ]; then + BRANCH_NAME="$GIT_BRANCH" + echo "Branch from GIT_BRANCH: $BRANCH_NAME" +elif [ ! -z "$BRANCH_NAME" ]; then + echo "Branch from BRANCH_NAME: $BRANCH_NAME" +elif [ ! -z "$CI_COMMIT_REF_NAME" ]; then + BRANCH_NAME="$CI_COMMIT_REF_NAME" + echo "Branch from CI_COMMIT_REF_NAME: $BRANCH_NAME" +# Method 2: Try git command +elif [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ "$BRANCH_NAME" = "HEAD" ]; then + # In detached HEAD state, try to get branch from remote + BRANCH_NAME=$(git branch -r --contains HEAD | grep -v HEAD | head -1 | sed 's/^[[:space:]]*origin\///') + echo "Branch from git branch -r: $BRANCH_NAME" + else + echo "Branch from git rev-parse: $BRANCH_NAME" + fi +fi + +# Remove origin/ prefix if present (but keep the rest of the path) +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/^origin\///') + +if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then + echo "Warning: Unable to get Git branch name, skipping version validation" +else + echo "Current branch: $BRANCH_NAME" + + # Extract version from branch name (format: dev/x.x.x) + if [[ $BRANCH_NAME =~ ^dev/([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + BRANCH_VERSION="${BASH_REMATCH[1]}" + echo "Branch version: $BRANCH_VERSION" + + # Read MARKETING_VERSION from project.pbxproj + PBXPROJ_FILE="${PROJECT_PATH}/APIExample.xcodeproj/project.pbxproj" + if [ ! -f "$PBXPROJ_FILE" ]; then + echo "Error: project.pbxproj file not found: $PBXPROJ_FILE" + exit 1 + fi + + # Extract MARKETING_VERSION for main target (skip Extension targets) + # Look for the version that appears with @executable_path/Frameworks (main app) + PLIST_VERSION=$(grep -A 2 "@executable_path/../Frameworks" "$PBXPROJ_FILE" | grep "MARKETING_VERSION" | head -1 | sed 's/.*MARKETING_VERSION = \([^;]*\);/\1/' | tr -d ' ') + + if [ -z "$PLIST_VERSION" ]; then + echo "Error: Unable to read MARKETING_VERSION from project.pbxproj" + exit 1 + fi + + echo "Info.plist version: $PLIST_VERSION" + + # Compare versions + if [ "$BRANCH_VERSION" != "$PLIST_VERSION" ]; then + echo "Error: Version mismatch!" + echo " Branch version: $BRANCH_VERSION" + echo " Info.plist version: $PLIST_VERSION" + echo "Please ensure the version in branch name matches MARKETING_VERSION in Info.plist" + exit 1 + fi + + echo "✓ Version validation passed: $BRANCH_VERSION" + else + echo "Error: Branch name does not match dev/x.x.x format!" + echo "Current branch: $BRANCH_NAME" + echo "Required format: dev/x.x.x (e.g., dev/4.5.3)" + exit 1 + fi +fi + +echo "Version validation completed" +echo "-----------------------------------" + cd ${PROJECT_PATH} && pod install || exit 1 @@ -107,4 +186,57 @@ rm -rf *.xcarchive rm -rf *.xcarchive.zip echo OUTPUT_FILE: $OUTPUT_FILE +echo "" +echo "==========================================" +echo "=== Certificate Expiration Information ===" +echo "==========================================" + +# 获取用于签名的证书信息 (macOS) +SIGNING_CERT=$(security find-identity -v -p codesigning | grep "Developer ID Application\|Mac Developer\|Apple Development" | head -1 | awk -F'"' '{print $2}') + +if [ ! -z "$SIGNING_CERT" ]; then + echo "Signing Certificate: $SIGNING_CERT" + + # 获取证书的详细信息 + CERT_INFO=$(security find-certificate -c "$SIGNING_CERT" -p | openssl x509 -noout -dates 2>/dev/null) + + if [ $? -eq 0 ]; then + echo "$CERT_INFO" + + # 提取过期日期 + EXPIRY_DATE=$(echo "$CERT_INFO" | grep "notAfter" | cut -d= -f2) + echo "" + echo "⚠️ Certificate will expire on: $EXPIRY_DATE" + + # 计算剩余天数 + if command -v gdate >/dev/null 2>&1; then + # macOS with GNU coreutils installed + EXPIRY_EPOCH=$(gdate -d "$EXPIRY_DATE" +%s 2>/dev/null) + CURRENT_EPOCH=$(gdate +%s) + else + # macOS default date command + EXPIRY_EPOCH=$(date -j -f "%b %d %T %Y %Z" "$EXPIRY_DATE" +%s 2>/dev/null) + CURRENT_EPOCH=$(date +%s) + fi + + if [ ! -z "$EXPIRY_EPOCH" ] && [ ! -z "$CURRENT_EPOCH" ]; then + DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 )) + echo "📅 Days remaining: $DAYS_LEFT days" + + if [ $DAYS_LEFT -lt 30 ]; then + echo "🚨 WARNING: Certificate will expire in less than 30 days!" + elif [ $DAYS_LEFT -lt 90 ]; then + echo "⚠️ NOTICE: Certificate will expire in less than 90 days" + fi + fi + else + echo "Unable to retrieve certificate expiration information" + fi +else + echo "No distribution certificate found" +fi + +echo "==========================================" +echo "" + diff --git a/macOS/cloud_project.sh b/macOS/cloud_project.sh index d29b833f7..b6b92486e 100755 --- a/macOS/cloud_project.sh +++ b/macOS/cloud_project.sh @@ -9,6 +9,85 @@ if [ "$BUILD_NUMBER" = "" ]; then BUILD_NUMBER=888 fi +# Version validation logic +echo "Starting branch version validation..." + +# Get current branch name (try multiple methods for CI environments) +BRANCH_NAME="" + +# Method 1: Try environment variable (Jenkins/GitLab CI) +if [ ! -z "$GIT_BRANCH" ]; then + BRANCH_NAME="$GIT_BRANCH" + echo "Branch from GIT_BRANCH: $BRANCH_NAME" +elif [ ! -z "$BRANCH_NAME" ]; then + echo "Branch from BRANCH_NAME: $BRANCH_NAME" +elif [ ! -z "$CI_COMMIT_REF_NAME" ]; then + BRANCH_NAME="$CI_COMMIT_REF_NAME" + echo "Branch from CI_COMMIT_REF_NAME: $BRANCH_NAME" +# Method 2: Try git command +elif [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ "$BRANCH_NAME" = "HEAD" ]; then + # In detached HEAD state, try to get branch from remote + BRANCH_NAME=$(git branch -r --contains HEAD | grep -v HEAD | head -1 | sed 's/^[[:space:]]*origin\///') + echo "Branch from git branch -r: $BRANCH_NAME" + else + echo "Branch from git rev-parse: $BRANCH_NAME" + fi +fi + +# Remove origin/ prefix if present (but keep the rest of the path) +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/^origin\///') + +if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then + echo "Warning: Unable to get Git branch name, skipping version validation" +else + echo "Current branch: $BRANCH_NAME" + + # Extract version from branch name (format: dev/x.x.x) + if [[ $BRANCH_NAME =~ ^dev/([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + BRANCH_VERSION="${BASH_REMATCH[1]}" + echo "Branch version: $BRANCH_VERSION" + + # Read MARKETING_VERSION from project.pbxproj + PBXPROJ_FILE="${PROJECT_PATH}/APIExample.xcodeproj/project.pbxproj" + if [ ! -f "$PBXPROJ_FILE" ]; then + echo "Error: project.pbxproj file not found: $PBXPROJ_FILE" + exit 1 + fi + + # Extract MARKETING_VERSION for main target (skip Extension targets) + # Look for the version that appears with @executable_path/../Frameworks (main app) + PLIST_VERSION=$(grep -A 2 "@executable_path/../Frameworks" "$PBXPROJ_FILE" | grep "MARKETING_VERSION" | head -1 | sed 's/.*MARKETING_VERSION = \([^;]*\);/\1/' | tr -d ' ') + + if [ -z "$PLIST_VERSION" ]; then + echo "Error: Unable to read MARKETING_VERSION from project.pbxproj" + exit 1 + fi + + echo "Info.plist version: $PLIST_VERSION" + + # Compare versions + if [ "$BRANCH_VERSION" != "$PLIST_VERSION" ]; then + echo "Error: Version mismatch!" + echo " Branch version: $BRANCH_VERSION" + echo " Info.plist version: $PLIST_VERSION" + echo "Please ensure the version in branch name matches MARKETING_VERSION in Info.plist" + exit 1 + fi + + echo "✓ Version validation passed: $BRANCH_VERSION" + else + echo "Error: Branch name does not match dev/x.x.x format!" + echo "Current branch: $BRANCH_NAME" + echo "Required format: dev/x.x.x (e.g., dev/4.5.3)" + exit 1 + fi +fi + +echo "Version validation completed" +echo "-----------------------------------" + cd ${PROJECT_PATH} && pod install || exit 1 diff --git a/windows/APIExample/ci.py b/windows/APIExample/ci.py deleted file mode 100644 index e48cce24b..000000000 --- a/windows/APIExample/ci.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: UTF-8 -*- -import re -import os - -def main(): - - appId = r'""' - if "AGORA_APP_ID" in os.environ: - appId = os.environ["AGORA_APP_ID"] - appString = "\""+appId+"\"" - else: - appString = str(appId) - f = open("./APIExample/stdafx.h", 'r+') - content = f.read() - contentNew = re.sub(r'""', appString, content) - f.seek(0) - f.write(contentNew) - f.truncate() - -if __name__ == "__main__": - main() diff --git a/windows/APIExample/cloud_build.bat b/windows/APIExample/cloud_build.bat index 6df7200fb..59621cf6f 100644 --- a/windows/APIExample/cloud_build.bat +++ b/windows/APIExample/cloud_build.bat @@ -1,10 +1,81 @@ +@echo off +setlocal enabledelayedexpansion + echo "compile start..." -call installThirdParty.bat -"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\MSBuild.exe" "APIExample.sln" /p:platform="Win32" /p:configuration="Release" -7z a -tzip result.zip -r Release +REM --- 1. Install Dependencies --- +powershell.exe -ExecutionPolicy Bypass -File "%~dp0install.ps1" + +REM --- 2. Find MSBuild --- +set "MSBuildPath=" +set "vswhere=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" + +if exist "!vswhere!" ( + for /f "usebackq tokens=*" %%i in (`"!vswhere!" -latest -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe`) do set "MSBuildPath=%%i" +) + +if not defined MSBuildPath ( + for %%p in ( + "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\MSBuild.exe" + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe" + "C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" + ) do if exist %%p set "MSBuildPath=%%p" +) + +if not defined MSBuildPath ( + echo Error: MSBuild not found. + exit /b 1 +) + +echo Using MSBuild at: "!MSBuildPath!" + +REM --- 3. Build --- +"!MSBuildPath!" "APIExample.sln" /p:platform="Win32" /p:configuration="Release" +if %ERRORLEVEL% NEQ 0 ( + echo Build failed! + exit /b %ERRORLEVEL% +) + +echo "compile done." + +REM --- 4. Package (Clean Output) --- +echo Preparing clean output directory... +rmdir /S /Q Output 2>nul +mkdir Output + +REM Copy executables and DLLs from Release +xcopy /Y /S Release\*.exe Output\ >nul 2>&1 +xcopy /Y /S Release\*.dll Output\ >nul 2>&1 + +REM Copy resources +xcopy /Y /S /I APIExample\res Output\res >nul 2>&1 +xcopy /Y APIExample\*.ini Output\ >nul 2>&1 + +REM Copy SDK and ThirdParty DLLs +xcopy /Y sdk\*.dll Output\ >nul 2>&1 +xcopy /Y ThirdParty\libFFmpeg\*.dll Output\ >nul 2>&1 + +echo Packaging... +set "result_zip=result.zip" +del /F /Q !result_zip! 2>nul + +REM Try 7z, fallback to PowerShell +where 7z >nul 2>nul +if %ERRORLEVEL% EQU 0 ( + 7z a -tzip !result_zip! .\Output\* >nul +) else ( + "C:\Program Files\7-Zip\7z.exe" a -tzip !result_zip! .\Output\* >nul 2>nul + if %ERRORLEVEL% NEQ 0 ( + powershell -command "Compress-Archive -Path '.\Output\*' -DestinationPath '!result_zip!' -Force" + ) +) + +REM Copy to WORKSPACE with original naming format set h=%time:~0,2% set h=%h: =0% -copy result.zip %WORKSPACE%\\APIExample_windows_%BUILD_NUMBER%_%date:~4,2%%date:~7,2%%h%%time:~3,2%_Release_exe.zip -del /F result.zip -echo "compile done." \ No newline at end of file +if not defined WORKSPACE set WORKSPACE=%~dp0 +copy !result_zip! "%WORKSPACE%\\APIExample_windows_%BUILD_NUMBER%_%date:~4,2%%date:~7,2%%h%%time:~3,2%_Release_exe.zip" +del /F /Q !result_zip! 2>nul +rmdir /S /Q Output 2>nul + +echo Build and Package done. \ No newline at end of file diff --git a/windows/APIExample/install.ps1 b/windows/APIExample/install.ps1 index 9090f6c1d..683b9a5aa 100644 --- a/windows/APIExample/install.ps1 +++ b/windows/APIExample/install.ps1 @@ -1,4 +1,4 @@ -$agora_sdk = 'https://download.shengwang.cn/sdk/release/Shengwang_Native_SDK_for_Windows_v4.6.2_FULL.zip' +$agora_sdk = 'https://download.shengwang.cn/sdk/release/Shengwang_Native_SDK_for_Windows_v4.5.3_FULL.zip' $ThirdPartysrc = 'https://fullapp.oss-cn-beijing.aliyuncs.com/API-Examples/ThirdParty.zip' $ThirdPartydes = 'ThirdParty.zip' $agora_des = 'AgoraSdk.zip' @@ -24,20 +24,54 @@ if (-not (Test-Path sdk)){ Copy-Item $agora_local_sdk\high_level_api\include\* sdk\high_level_api\include -Recurse }else{ echo "download $agora_des" + echo "Downloading SDK from: $agora_sdk" + mkdir sdk mkdir sdk\x64 mkdir sdk\high_level_api mkdir sdk\high_level_api\include - (New-Object System.Net.WebClient).DownloadFile($agora_sdk,$agora_des) - Unblock-File $agora_des - Expand-Archive -Path $agora_des -DestinationPath . -Force - Move-Item Shengwang_Native_SDK_for_Windows_FULL\sdk\x86\* sdk - Move-Item Shengwang_Native_SDK_for_Windows_FULL\sdk\x86_64\* sdk\x64 - Move-Item Shengwang_Native_SDK_for_Windows_FULL\sdk\high_level_api\include\* sdk\high_level_api\include - Remove-Item $agora_des -Recurse -Force - Remove-Item Shengwang_Native_SDK_for_Windows_FULL -Recurse -Force + + # Use system temporary directory for extraction to avoid path length issues + $tempBasePath = [System.IO.Path]::GetTempPath() + $tempExtractPath = Join-Path $tempBasePath "RtcSdkExtract_$(Get-Random)" + $tempZipPath = Join-Path $tempBasePath $agora_des + + try { + (New-Object System.Net.WebClient).DownloadFile($agora_sdk, $tempZipPath) + Unblock-File $tempZipPath + Expand-Archive -Path $tempZipPath -DestinationPath $tempExtractPath -Force + + $extractedSdkPath = (Get-ChildItem -Path $tempExtractPath -Directory | Select-Object -First 1).FullName + Move-Item (Join-Path $extractedSdkPath "sdk\x86\*") sdk -Force + Move-Item (Join-Path $extractedSdkPath "sdk\x86_64\*") sdk\x64 -Force + Move-Item (Join-Path $extractedSdkPath "sdk\high_level_api\include\*") sdk\high_level_api\include -Force + } + finally { + # Clean up temporary files + if (Test-Path $tempZipPath) { Remove-Item $tempZipPath -Force -ErrorAction SilentlyContinue } + if (Test-Path $tempExtractPath) { Remove-Item $tempExtractPath -Recurse -Force -ErrorAction SilentlyContinue } + } } } - +# Validation: check each folder has at least one direct child (non-empty), output to console only +$allOk = $true +foreach ($dir in @("ThirdParty", "sdk", "sdk\x64", "sdk\high_level_api\include")) { + $p = Join-Path $PSScriptRoot $dir + $n = 0 + if (Test-Path $p -PathType Container) { + try { $n = (Get-ChildItem $p -ErrorAction SilentlyContinue).Count } catch { Write-Host "[FAIL] $dir | $_" -ForegroundColor Red; $allOk = $false; continue } + } + $ok = $n -ge 1 + if (-not $ok) { $allOk = $false } + if ($ok) { Write-Host "[PASS] $dir (items=$n)" } else { Write-Host "[FAIL] $dir (items=$n)" } +} +if ($allOk) { + Write-Host "Result: All passed." + Write-Host "Dependencies are installed; you can proceed to the next step." -ForegroundColor Green +} else { + Write-Host "Result: Validation failed." -ForegroundColor Red + Write-Host "Please check network and download, ensure ThirdParty and sdk are not empty, then retry." -ForegroundColor Red + exit 1 +} diff --git a/windows/APIExample/installThirdParty.bat b/windows/APIExample/installThirdParty.bat index b64d1fc4a..ff0d1aa12 100644 --- a/windows/APIExample/installThirdParty.bat +++ b/windows/APIExample/installThirdParty.bat @@ -1,4 +1,6 @@ cd /d %~dp0 -powershell.exe -command ^ - "& {set-executionpolicy Remotesigned -Scope Process; ./'install.ps1'}" +powershell.exe -Command "Unblock-File -Path '%~dp0install.ps1'" +powershell.exe -File "%~dp0install.ps1" + +pause diff --git a/windows/README.md b/windows/README.md index 3c10e12b8..2cdb371b3 100644 --- a/windows/README.md +++ b/windows/README.md @@ -36,6 +36,8 @@ To build and run the sample application, get an App ID: You can directly run `APIExample/installThirdParty.bat` to automatically environment configuration.Once the configuration is complete, open the project with VS2017, select the x86 version to compile and run. +> If you run into permission or execution policy errors, try running as administrator, or adjust the local PowerShell execution policy and try again. + ## Basic Scene diff --git a/windows/README.zh.md b/windows/README.zh.md index ebde19d87..8ee92750b 100644 --- a/windows/README.zh.md +++ b/windows/README.zh.md @@ -40,7 +40,9 @@ ### 编译项目 **这个开源示例项目使用了Agora RTC SDK,DirectShow SDK,MeidaPlayer SDK。** -你可以通过直接运行`APIExample/installThirdParty.bat`来自动进行依赖下载与环境配置。配置完成后使用vs2017打开项目,选择x86版本进行编译就可以运行了。 +你可以通过直接运行`APIExample/installThirdParty.bat`来自动进行依赖下载与环境配置。配置完成后使用vs2017打开项目,选择x86版本进行编译就可以运行了。 + +> 若遇权限或执行策略报错,可尝试以管理员运行,或调整本机 PowerShell 执行策略后再试。 ## 基础场景 diff --git a/windows/cicd/templates/build-Windows.yml b/windows/cicd/templates/build-Windows.yml index 3b791bfc0..62d60b7d6 100644 --- a/windows/cicd/templates/build-Windows.yml +++ b/windows/cicd/templates/build-Windows.yml @@ -30,10 +30,6 @@ jobs: steps: - script: echo "$(WindowsRTCSDK)" && ls - script: cd ${{ parameters.workingDirectory }} && installThirdParty.bat - - script: cd ${{ parameters.workingDirectory }} && ls && python ci.py - env: - AGORA_APP_ID: $(agora.appId) - - task: VSBuild@1 inputs: solution: '$(solution)'