Skip to content

Latest commit

 

History

History
265 lines (194 loc) · 6.39 KB

File metadata and controls

265 lines (194 loc) · 6.39 KB

Android

Artifacts

APK - Android Package Kit

MyApp.apk

  • device installable containing all resources
  • can be installed via Google Play or manually (sideloaded)
  • usually larger because they contain all possible resources for different devices, including images and code

AAB - Android Application Bundle

MyApp.aab

  • contains all resources but Google Play Store uses it to generate optimized APKs for different devices
  • AABs are designed to result in smaller APKs, faster downloads and less space used on devices
  • can only be installed via Google Play Store
  • cannot be installed directly

Install Android SDK

On Ubuntu:

apt-get install -y android-sdk google-android-build-tools-34.0.0-installer
export ANDROID_HOME="/usr/lib/android-sdk"

On Mac, it's easier using DevOps-Bash-tools to download and install Android SDK and command line tools:

install_android_sdk.sh
install_android_commandlinetools.sh

Set your shell environment variables:

export ANDROID_HOME="$HOME/Android/Sdk"
export PATH="$PATH:$ANDROID_HOME/platform-tools"
export PATH="$PATH:$ANDROID_HOME/cmdline-tools/latest/bin"

Accept all the licenses so that Gradle builds don't error out:

yes | sdkmanager --licenses
sdkmanager --list

Install build-tools version 34.0.0:

sdkmanager "build-tools;34.0.0"

Add to PATH:

export PATH="$PATH:$ANDROID_HOME/build-tools/34.0.0"

Build

Build with Gradle

See gradle page.

./gradlew clean assembleRelease \
        -Dorg.gradle.jvmargs="\
            -Xmx4G \
            -Dkotlin.daemon.jvm.options=-Xmx2G \
            -XX:+HeapDumpOnOutOfMemoryError \
            -XX:+UseParallelGC \
            -Dfile.encoding=UTF-8 \
        " \
        --build-cache \
        --stacktrace \
        --info

results in an .apk artifact such as:

app/build/outputs/apk/release/app-release.apk

Build with Fastlane

Recommended to use Fastlane which has a gradle action but can also handle signing and other things.

Signing

apksigner

Signing with apksigner

Newer recommended command.

apksigner \
    sign \
    --ks "$JKS" \
    --ks-pass  "pass:$JKS_KEYSTORE_PASSWORD" \
    --key-pass "pass:$JKS_KEY_PASSWORD" \
    --ks-key-alias "$JKS_KEY_ALIAS" \
    --v1-signing-enabled true \
    --v2-signing-enabled true \
    --verbose \
    "$APK"

Verify with apksigner

This actually exits non-zero if it fails to verify, unlike jarsigner which only exits non-zero if there is an error. This makes this the better choice for scripting and CI/CD.

apksigner verify --verbose "$APK"
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): true
Verified using v3.1 scheme (APK Signature Scheme v3.1): false
Verified using v4 scheme (APK Signature Scheme v4): false
Verified for SourceStamp: false
Number of signers: 1

Fails to verify is signed with the older jarsigner:

DOES NOT VERIFY
ERROR: Target SDK version 34 requires a minimum of signature scheme v2; the APK is not signed with this or a later signature scheme

jarsigner

Signing with jarsigner

Older method, if you sign with jarsigner, you won't be able to verify with apksigner in your CI/CD pipelines.

jarsigner \
    -keystore "$JKS" \
    -storepass "$JKS_KEYSTORE_PASSWORD" \
    -keypass "$JKS_KEY_PASSWORD" \
    -sigalg SHA256withRSA \
    -digestalg SHA-256 \
    -verbose \
    "$APK" \
    "$JKS_KEY_ALIAS"

Verify with jarsigner

Does not exit non-zero if jar is unsigned and fails to verify.

It only exits non-zero if there is an error.

Use newer apksigner command instead.

jarsigner -verify "$$APK"
jar verified.

or:

  s = signature was verified
  m = entry is listed in manifest
  k = at least one certificate was found in keystore

no manifest.

jar is unsigned.

Fastlane Signing

Fastlane can also do the signing, see this fastlane/Fastfile template.

Ensure the following environment variables are set:

  • JKS
  • JKS_KEYSTORE_PASSWORD
  • JKS_KEY_ALIAS
  • JKS_KEY_PASSWORD

and then set the following properties in the gradle action in the fastlane/Fastfile:

    gradle(
      # don't waste the cache with a clean, 1min30sec => 5min30sec
      #task: 'clean bundleRelease',
      task: "assembleRelease",
      flags: "-Dorg.gradle.jvmargs=\"-Xmx4G -Dkotlin.daemon.jvm.options=-Xmx2G -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -Dfile.encoding=UTF-8\" --build-cache --no-daemon --stacktrace --info",
      properties: {
        "android.injected.signing.store.file" => ENV["JKS"],
        "android.injected.signing.store.password" => ENV["JKS_KEYSTORE_PASSWORD"],
        "android.injected.signing.key.alias" => ENV["JKS_KEY_ALIAS"],
        "android.injected.signing.key.password" => ENV["JKS_KEY_PASSWORD"],
        "android.injected.signing.v2.signing.enabled" => "true",
        "android.injected.signing.v1.signing.enabled" => "true"
      }

Google Play Store

https://play.google.com/console/developers

https://docs.fastlane.tools/getting-started/android/setup/#setting-up-supply

Upload your APK here to distribute to users.

See also Fastlane doc section on uploading to Google Play Store.