name: android-ci on: push: branches: - main - android-*.*.x tags: - "android-*" pull_request: branches: - "*" concurrency: # cancel jobs on PRs only group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: pre_job: runs-on: ubuntu-latest outputs: should_skip: ${{ github.event_name != 'workflow_dispatch' && steps.changed-files.outputs.android_any_modified != 'true' }} steps: - uses: actions/checkout@v4 with: submodules: recursive - name: Get all Android files that have changed if: github.event_name != 'workflow_dispatch' id: changed-files uses: tj-actions/changed-files@v45 with: files_yaml_from_source_file: .github/changed-files.yml android-build: runs-on: ubuntu-24.04 needs: - pre_job if: needs.pre_job.outputs.should_skip != 'true' defaults: run: working-directory: platform/android env: BUILDTYPE: Debug IS_LOCAL_DEVELOPMENT: false MLN_ANDROID_STL: c++_static steps: - name: Free Disk Space (Ubuntu) if: startsWith(runner.name, 'GitHub Actions') uses: jlumbroso/free-disk-space@main with: tool-cache: false android: false dotnet: true haskell: true large-packages: true docker-images: true swap-storage: false - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - run: echo "cmake.dir=$(dirname "$(dirname "$(command -v cmake)")")" >> local.properties - uses: actions/setup-java@v4 with: distribution: "temurin" java-version: "17" - name: Get CMake and Ninja uses: lukka/get-cmake@latest with: cmakeVersion: 3.24.1 ninjaVersion: latest - name: Cache node modules uses: actions/cache@v4 env: cache-name: cache-node-modules with: path: ~/.npm key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: npm install run: npm install --ignore-scripts working-directory: . - name: run platform/android/scripts/generate-style-code.mjs run: node platform/android/scripts/generate-style-code.mjs working-directory: . - run: | python3 -m venv venv source venv/bin/activate pip3 install pre-commit - run: | source venv/bin/activate pre-commit run clang-format --all-files continue-on-error: true # this can mean files are modified, which is not an error - run: | source venv/bin/activate pre-commit run clang-format --all-files rm -rf venv - uses: infotroph/tree-is-clean@v1 with: check_untracked: true - uses: hendrikmuhs/ccache-action@v1.2 with: key: ${{ github.job }} append-timestamp: false max-size: 5G - name: restore-gradle-cache uses: actions/cache@v4 env: cache-name: gradle-v1 with: path: ~/.gradle key: ${{ env.cache-name }}-${{ hashFiles('platform/android/buildSrc/src/main/kotlin/maplibre.dependencies.gradle.kts') }}-${{ hashFiles('platform/android/build.gradle.kts') }}-${{ hashFiles('platform/android/local.properties') }}-${{ hashFiles('platform/android/gradle/wrapper/gradle-wrapper.properties') }} restore-keys: | - ${{ env.cache-name }} - name: Check code style run: make android-check - name: Run Android unit tests run: make run-android-unit-test - name: Build libmaplibre.so for arm-v8 run: make android-lib-arm-v8 - name: Build API documentation run: ./gradlew dokkaHtml - name: Build Examples documentation run: make mkdocs-build - name: Copy developer config with API key for UI tests if: github.ref == 'refs/heads/main' run: | MAPLIBRE_DEVELOPER_CONFIG_XML='${{ secrets.MAPLIBRE_DEVELOPER_CONFIG_XML }}' if [ -n "${MAPLIBRE_DEVELOPER_CONFIG_XML}" ]; then echo "${MAPLIBRE_DEVELOPER_CONFIG_XML}" > MapLibreAndroidTestApp/src/main/res/values/developer-config.xml else echo "No secrets.MAPLIBRE_DEVELOPER_CONFIG_XML variable set, not copying..." fi - name: Build Benchmark, copy to platform/android run: | ./gradlew assembleDrawableRelease assembleDrawableReleaseAndroidTest -PtestBuildType=release cp MapLibreAndroidTestApp/build/outputs/apk/drawable/release/MapLibreAndroidTestApp-drawable-release.apk . cp MapLibreAndroidTestApp/build/outputs/apk/androidTest/drawable/release/MapLibreAndroidTestApp-drawable-release-androidTest.apk . # https://developer.android.com/guide/practices/page-sizes - name: Check alignment of .apk run: | unzip -o MapLibreAndroidTestApp/build/outputs/apk/drawable/release/MapLibreAndroidTestApp-drawable-release.apk -d /tmp/my_apk_out scripts/check-alignment.sh /tmp/my_apk_out - name: Create artifact for benchmark APKs uses: actions/upload-artifact@v4 with: if-no-files-found: error name: benchmarkAPKs path: | platform/android/MapLibreAndroidTestApp-drawable-release.apk platform/android/MapLibreAndroidTestApp-drawable-release-androidTest.apk - if: github.event_name == 'pull_request' uses: ./.github/actions/save-pr-number - name: Build Instrumentation Tests, copy to platform/android run: | ./gradlew assembleLegacyDebug assembleLegacyDebugAndroidTest -PtestBuildType=debug cp MapLibreAndroidTestApp/build/outputs/apk/legacy/debug/MapLibreAndroidTestApp-legacy-debug.apk InstrumentationTestApp.apk cp MapLibreAndroidTestApp/build/outputs/apk/androidTest/legacy/debug/MapLibreAndroidTestApp-legacy-debug-androidTest.apk InstrumentationTests.apk - name: Upload android-ui-test uses: actions/upload-artifact@v4 with: if-no-files-found: error name: android-ui-test path: | platform/android/InstrumentationTestApp.apk platform/android/InstrumentationTests.apk android-build-cpp-test: runs-on: ubuntu-24.04 needs: - pre_job if: needs.pre_job.outputs.should_skip != 'true' defaults: run: working-directory: test/android steps: - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - uses: actions/setup-java@v4 with: distribution: "temurin" java-version: "17" - name: Get CMake and Ninja uses: lukka/get-cmake@latest with: cmakeVersion: 3.24.1 ninjaVersion: latest - uses: hendrikmuhs/ccache-action@v1.2 with: key: ${{ github.job }} append-timestamp: false max-size: 5G - name: Create data.zip in assets directory run: zip -r test/android/app/src/main/assets/data.zip -@ < test/android/app/src/main/assets/to_zip.txt working-directory: . - name: Build C++ Unit Tests App run: | ./gradlew assembleDebug assembleAndroidTest cp app/build/outputs/apk/debug/app-debug.apk . cp app/build/outputs/apk/androidTest/release/app-release-androidTest.apk . - name: Store C++ Unit Tests .apk files uses: actions/upload-artifact@v4 with: name: android-cpp-tests if-no-files-found: error path: | ./test/android/app-debug.apk ./test/android/app-release-androidTest.apk android-build-render-test: strategy: fail-fast: false matrix: flavor: [opengl, vulkan] runs-on: ubuntu-24.04 needs: - pre_job if: needs.pre_job.outputs.should_skip != 'true' steps: - name: Free Disk Space (Ubuntu) if: startsWith(runner.name, 'GitHub Actions') uses: jlumbroso/free-disk-space@main with: tool-cache: false android: false dotnet: true haskell: true large-packages: true docker-images: true swap-storage: false - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - uses: hendrikmuhs/ccache-action@v1.2 with: key: ${{ github.job }} append-timestamp: false max-size: 5G - name: Get CMake and Ninja uses: lukka/get-cmake@latest with: cmakeVersion: 3.24.1 ninjaVersion: latest - uses: actions/setup-java@v4 with: distribution: "temurin" java-version: "17" - name: Build and Upload Render Test APKs (${{ matrix.flavor }}) uses: ./.github/actions/android-build-and-upload-render-test with: flavor: ${{ matrix.flavor }} android-ci-result: runs-on: ubuntu-latest if: needs.pre_job.outputs.should_skip != 'true' && always() needs: - pre_job - android-build - android-build-cpp-test - android-build-render-test steps: - name: Mark result as failed if: needs.android-build.result != 'success' run: exit 1