name: Build Android TV APK on: workflow_dispatch: inputs: base_url: description: '服务端 Base URL,不需要带 /tv,例如 https://example.com 或 http://192.168.1.10:3000' required: true default: 'http://192.168.1.10:3000' type: string app_name: description: 'Android TV 应用名称' required: true default: 'MoonTVPlus TV' type: string version_name: description: '版本名' required: false default: '1.0.0' type: string version_code: description: '版本号,必须是整数' required: false default: '1' type: string concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: contents: read actions: read jobs: build: name: Build Android TV APK (${{ matrix.variant }}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - variant: standard-webview flavor: webview flavor_task: Webview min_sdk: '23' label: webview-android6plus - variant: compat-webview flavor: webview flavor_task: Webview min_sdk: '21' label: webview-android5plus - variant: standard-gecko flavor: gecko flavor_task: Gecko min_sdk: '23' label: geckoview-android6plus - variant: compat-gecko flavor: gecko flavor_task: Gecko min_sdk: '21' label: geckoview-android5plus steps: - name: Checkout source code uses: actions/checkout@v4 - name: Setup Java uses: actions/setup-java@v4 with: distribution: temurin java-version: '17' - name: Setup Android SDK uses: android-actions/setup-android@v3 - name: Install Android SDK packages run: | sdkmanager "platforms;android-35" "build-tools;35.0.0" - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: gradle-version: '8.10.2' - name: Prepare Android TV icon from public/logo.png run: | cp public/logo.png apps/android-tv/app/src/main/res/drawable/logo.png - name: Decode Android signing keystore id: signing env: ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} run: | if [ -n "$ANDROID_KEYSTORE_BASE64" ] && [ -n "$ANDROID_KEYSTORE_PASSWORD" ] && [ -n "$ANDROID_KEY_ALIAS" ] && [ -n "$ANDROID_KEY_PASSWORD" ]; then echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > /tmp/android-tv-release.keystore echo "build_type=release" >> "$GITHUB_OUTPUT" echo "build_type_task=Release" >> "$GITHUB_OUTPUT" echo "apk_suffix=release" >> "$GITHUB_OUTPUT" echo "artifact_suffix=release-signed" >> "$GITHUB_OUTPUT" else echo "Android signing secrets are not fully set, building debug APK only." echo "build_type=debug" >> "$GITHUB_OUTPUT" echo "build_type_task=Debug" >> "$GITHUB_OUTPUT" echo "apk_suffix=debug" >> "$GITHUB_OUTPUT" echo "artifact_suffix=debug" >> "$GITHUB_OUTPUT" fi - name: Build APK working-directory: apps/android-tv env: BASE_URL: ${{ inputs.base_url }} APP_NAME: ${{ inputs.app_name }} VERSION_NAME: ${{ inputs.version_name }} VERSION_CODE: ${{ inputs.version_code }} MIN_SDK: ${{ matrix.min_sdk }} ANDROID_KEYSTORE_PATH: /tmp/android-tv-release.keystore ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} run: | gradle assemble${{ matrix.flavor_task }}${{ steps.signing.outputs.build_type_task }} \ -PBASE_URL="$BASE_URL" \ -PAPP_NAME="$APP_NAME" \ -PVERSION_NAME="$VERSION_NAME" \ -PVERSION_CODE="$VERSION_CODE" \ -PMIN_SDK="$MIN_SDK" - name: Collect APK artifacts run: | mkdir -p /tmp/android-tv-apks cp \ "apps/android-tv/app/build/outputs/apk/${{ matrix.flavor }}/${{ steps.signing.outputs.build_type }}/app-${{ matrix.flavor }}-${{ steps.signing.outputs.apk_suffix }}.apk" \ "/tmp/android-tv-apks/moontvplus-tv-${{ inputs.version_name }}-${{ matrix.label }}-${{ steps.signing.outputs.artifact_suffix }}.apk" ls -lh /tmp/android-tv-apks - name: Upload APK artifacts uses: actions/upload-artifact@v4 with: name: moontvplus-android-tv-${{ inputs.version_name }}-${{ matrix.label }} path: /tmp/android-tv-apks/*.apk if-no-files-found: error retention-days: 30