Skip to content
Getting Started

Android Quickstart

Set up Gradle builds, test runs, and Play Store uploads with shipit.

Get your first Android build shipped with ShipItSwifty.

Prerequisites

  • An Android project with a gradlew wrapper at the project root
  • A Google Play service account JSON key (for Play Store uploads)
  • bundletool on PATH (for validate bundle: brew install bundletool)

1. Install ShipItSwifty

# From source
git clone https://github.com/shipitswifty/shipitswifty
cd shipitswifty
swift build -c release
cp .build/release/shipit /usr/local/bin/shipit

2. Auto-detect your project

Run generate from your Android project root. ShipItSwifty detects gradlew, walks through the missing values, and writes an Android-ready Shipfile.yml:

cd /path/to/MyAndroidApp
shipit generate --goal beta --platform android

If Google Play upload is enabled, generate now asks which Play track that workflow should target.

The generated setup includes:

  • Detected platform (.android)
  • Required secrets (GOOGLE_PLAY_SERVICE_ACCOUNT_JSON)
  • A ready-to-use Shipfile.yml draft
  • The next recommended command

3. Create a Shipfile

shipit generate --goal beta --platform android --non-interactive

Or write one manually:

# Shipfile.yml
platform: android
 
android:
  module: app
  build_variant: release
  package_name: com.example.myapp
  keystore_path: ./certs/release.keystore
  keystore_password: ${ANDROID_KEYSTORE_PASSWORD}
  keystore_alias: release
  key_password: ${ANDROID_KEY_PASSWORD}
 
workflows:
  beta:
    - action: test
    - action: archive
    - action: validate-bundle
    - action: play-store
      options:
        track: internal

4. Set credentials

export ANDROID_KEYSTORE_PASSWORD=...
export ANDROID_KEY_PASSWORD=...
export GOOGLE_PLAY_SERVICE_ACCOUNT_JSON="$(cat service-account.json)"

5. Run a dry-run

shipit run beta --dry-run --output json

Human output for shipit run beta now prints a short summary for each workflow step when available, including test counts, version strings, and archive artifact filenames.

6. Ship it

shipit run beta --ci --output json

Individual commands

# Build APK
shipit build --platform android
 
# Run unit tests
shipit test --platform android
 
# Run a specific Gradle test task
shipit test --platform android --task testProdDebugUnitTest
 
# Run a root-level aggregate Gradle test task
shipit test --platform android --module "" --task testDebugUnitTest
 
# Build AAB
shipit archive --platform android
 
# Run lint
shipit lint --platform android
 
# Validate the AAB before uploading
shipit validate bundle --bundle ./app/build/outputs/bundle/release/app-release.aab
 
# Upload to Google Play
shipit play-store --platform android --track internal

Platform auto-detection

When --platform is omitted, ShipItSwifty checks the current directory:

File foundDetected platform
gradlew or build.gradle.ktsAndroid
*.xcworkspace or *.xcodeprojiOS
(nothing)iOS (default)

Google Play service account setup

Use these values for Android setup:

  • package_name — Your Android application ID, usually applicationId in app/build.gradle or app/build.gradle.kts (for example com.example.myapp)
  • track — Set this on each play-store workflow step, or pass --track on the CLI. Valid values are typically internal, alpha, beta, or production
  • GOOGLE_PLAY_SERVICE_ACCOUNT_JSON — Raw contents of the service account key JSON file
  • GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_PATH — Local filesystem path to that JSON key file

Set up Play API access:

  1. Open Google Cloud Console and create or choose a project.
  2. Go to APIs & Services and enable the Google Play Developer API.
  3. Go to Service Accounts and create a service account.
  4. Create and download a JSON key for that service account.
  5. Open Google Play Console -> Users and permissions.
  6. Click Invite new users and paste the service account email address.
  7. Under the App permissions tab, add your specific app and grant the permissions needed for your target track.
  8. Click Invite user.

Important: Only the Play Console account owner can invite new users. If you don't see the invite option, ask the account owner to perform steps 5-8.

Note: You do not need to link your Google Cloud project to Play Console. Inviting the service account email directly via Users and permissions is sufficient.

Required permissions (under App permissions for your app):

  • View app information and download bulk reports (read-only)
  • Release apps to testing tracks for internal, alpha, or beta
  • Release to production, exclude devices, and use Play App Signing if you want production rollout
  • Manage store presence only if you also update store listings via the API

Then set one of these:

export GOOGLE_PLAY_SERVICE_ACCOUNT_JSON="$(cat service-account.json)"
 
# or
export GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_PATH=./service-account.json

Notes:

  • shipit generate --platform android can usually infer package_name, but the source of truth is your Gradle applicationId.
  • track must match the kind of release you intend to publish. For early testing, start with internal.

Troubleshooting

gradlew: Permission denied

chmod +x ./gradlew

bundletool: command not found

brew install bundletool

Google Play upload failed: 401

Check that your service account has the required permissions in Google Play Console (not just Google Cloud Console). See the setup steps above.

Google Play upload failed: 403 — PERMISSION_DENIED

This means the service account lacks the required Play Console permissions for your app. Fix:

  1. Go to Users & permissions in Play Console.
  2. Find your service account email and click it.
  3. Under App permissions, ensure your app is listed and the account has at least Release apps to testing tracks (or Release to production... for production uploads).
  4. Verify the Google Play Developer API is enabled in your Google Cloud project.
  5. If you recently changed permissions, wait a few minutes for propagation.
  6. Confirm you're using the correct service account JSON key. The email in the key must match the invited user in Play Console.

Common cause: The service account was granted only account-level permissions but not app-level permissions for the specific package. Always check the App permissions tab.

Build uses gradle instead of ./gradlew

ShipItSwifty uses ./gradlew when it exists in the working directory or the configured gradlew_path. If neither is present, it falls back to gradle on PATH. Set android.gradlew_path in Shipfile.yml to override.