Android Quickstart
Set up Gradle builds, test runs, and Play Store uploads with shipit.
On this page
Get your first Android build shipped with ShipItSwifty.
Prerequisites
- An Android project with a
gradlewwrapper at the project root - A Google Play service account JSON key (for Play Store uploads)
bundletoolon PATH (forvalidate 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/shipit2. 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 androidIf 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.ymldraft - The next recommended command
3. Create a Shipfile
shipit generate --goal beta --platform android --non-interactiveOr 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: internal4. 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 jsonHuman 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 jsonIndividual 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 internalPlatform auto-detection
When --platform is omitted, ShipItSwifty checks the current directory:
| File found | Detected platform |
|---|---|
gradlew or build.gradle.kts | Android |
*.xcworkspace or *.xcodeproj | iOS |
| (nothing) | iOS (default) |
Google Play service account setup
Use these values for Android setup:
package_name— Your Android application ID, usuallyapplicationIdinapp/build.gradleorapp/build.gradle.kts(for examplecom.example.myapp)track— Set this on eachplay-storeworkflow step, or pass--trackon the CLI. Valid values are typicallyinternal,alpha,beta, orproductionGOOGLE_PLAY_SERVICE_ACCOUNT_JSON— Raw contents of the service account key JSON fileGOOGLE_PLAY_SERVICE_ACCOUNT_JSON_PATH— Local filesystem path to that JSON key file
Set up Play API access:
- Open Google Cloud Console and create or choose a project.
- Go to APIs & Services and enable the
Google Play Developer API. - Go to Service Accounts and create a service account.
- Create and download a JSON key for that service account.
- Open Google Play Console -> Users and permissions.
- Click Invite new users and paste the service account email address.
- Under the App permissions tab, add your specific app and grant the permissions needed for your target track.
- 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 tracksforinternal,alpha, orbetaRelease to production, exclude devices, and use Play App Signingif you want production rolloutManage store presenceonly 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.jsonNotes:
shipit generate --platform androidcan usually inferpackage_name, but the source of truth is your GradleapplicationId.trackmust match the kind of release you intend to publish. For early testing, start withinternal.
Troubleshooting
gradlew: Permission denied
chmod +x ./gradlewbundletool: command not found
brew install bundletoolGoogle 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:
- Go to Users & permissions in Play Console.
- Find your service account email and click it.
- Under App permissions, ensure your app is listed and the account has at least
Release apps to testing tracks(orRelease to production...for production uploads). - Verify the
Google Play Developer APIis enabled in your Google Cloud project. - If you recently changed permissions, wait a few minutes for propagation.
- 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.