Play Store Release
Prepare signing, Play Console configuration, internal testing, and rollout.
Android distribution means a signed App Bundle, Play Console setup, real testing tracks, and production Supabase / RevenueCat wiring. In-App Updates, In-App Review, and real purchases only behave correctly in Play-delivered builds.
Pre-flight
| Item | Where |
|---|---|
| Package name | applicationId = "com.soarstarter.kotlin" in app/build.gradle.kts |
| Version | versionName = "1.0.0", versionCode = 1 |
| SDK levels | minSdk = 26, targetSdk = 37 |
| Signing | RELEASE_* keys in git-ignored local.properties |
| Legal links | LEGAL_TERMS_URL, LEGAL_PRIVACY_URL, LEGAL_EULA_URL |
| App Links | LINKING_DOMAIN + hosted .well-known/assetlinks.json |
| Monetization | Google Play products + RevenueCat pro entitlement |
| Backend | Production Supabase project, migrations, functions, and secrets |
Change applicationId before your first Play upload if you are shipping under
your own package. After the first upload, the package name is effectively the
app identity.
Signing
Generate an upload keystore once:
keytool -genkey -v -keystore soar-upload.jks -keyalg RSA -keysize 2048 \
-validity 10000 -alias soar-uploadAdd the release keys to local.properties:
RELEASE_STORE_FILE=soar-upload.jks
RELEASE_STORE_PASSWORD=your_store_password
RELEASE_KEY_ALIAS=soar-upload
RELEASE_KEY_PASSWORD=your_key_passwordThe Gradle signing config degrades gracefully. If RELEASE_STORE_FILE is empty
or points to a missing file, debug and CI builds still work, while the release
artifact remains unsigned. For Play, prefer Play App Signing and use this
keystore as the upload key.
App Links
LINKING_DOMAIN is used as the Android manifest host placeholder. To make
HTTPS App Links verify, host:
https://<your-domain>/.well-known/assetlinks.jsonThe file must include your package name and the SHA-256 fingerprint of the
release signing certificate. Keep soar:// for local custom-scheme links, but
use verified App Links for public URLs.
Products and entitlement
The template expects the RevenueCat entitlement id pro and these product ids:
| Product id | Store type |
|---|---|
pro_monthly | Google Play monthly auto-renewing subscription |
pro_yearly | Google Play yearly auto-renewing subscription |
pro_lifetime | Google Play one-time in-app product |
Attach the products to the RevenueCat pro entitlement and the current Android
offering. The app renders whichever packages the offering returns.
The app does not use RevenueCat CustomerInfo as the entitlement source of
truth. Purchases flow through the revenuecat-webhook Edge Function into
public.subscriptions with provider = play_store; EntitlementController
reads that Supabase row.
Data safety
Play Console asks what the APK/AAB and enabled services collect. The table below matches the template's shipped integrations. If you ship without a key or remove a feature, adjust the declaration.
| Data type | Collected | Purpose | Source |
|---|---|---|---|
| Email address | Yes | Account management, auth | Supabase Auth |
| User IDs | Yes | Account management, analytics, entitlement lookup | Supabase / PostHog / RevenueCat |
| Name and profile info | If user enters it | App functionality | profiles table |
| Photos or files | If user uploads | App functionality | Supabase Storage sample |
| Todos / user content | Yes, if used | App functionality | todos table |
| App interactions | If PostHog key is set | Analytics | PostHog |
| Crash logs and diagnostics | If Sentry DSN is set | App stability | Sentry |
| Device or advertising IDs | If analytics/FCM are shipped | Analytics, push delivery | PostHog / Firebase / AD_ID permission |
Declare encrypted in transit for networked data. Provide a privacy policy URL;
it should match LEGAL_PRIVACY_URL.
The in-app delete-account action is currently client-side cleanup: it deletes
the user's todos, nulls profile fields, and signs out locally. It does not
delete the Supabase Auth user. Google Play's account-deletion policy expects a
real deletion path, so port or add a server-side delete-account Edge Function
before release.
Build and upload
Run the quality gate first:
./gradlew testDebugUnitTest lintDebugBuild the App Bundle:
./gradlew bundleReleaseThe output is:
app/build/outputs/bundle/release/app-release.aabUpload the .aab to Internal testing first. Add testers, install from the Play
opt-in link, then test the Play-only surfaces from that installed build:
| Surface | What to verify |
|---|---|
| Purchases | License tester can buy, webhook writes subscriptions, Pro guides unlock |
| FCM | google-services.json is present, send-test-push function sends a notification |
| In-App Updates | MIN_APP_VERSION / LATEST_APP_VERSION strategy does not nag the current version |
| In-App Review | Trigger logic can request Play review without crashing |
| App Links | HTTPS links open the app after domain verification |
Promote Internal to Closed, Open, or Production when the release build has been smoke-tested.
Review notes
Mention these items in Play review notes:
| Topic | Note |
|---|---|
| In-app purchase | Monthly, yearly, and optional lifetime products unlock Pro developer guides under Showcase |
| Test path | Reviewer can open Home or Me -> Subscription to reach the paywall |
| Promo codes | Redeem code opens Google Play redemption |
| Account-gated screens | Reviewers can create an email/password account |
| Delete account | Provide the in-app path and the external account-deletion URL |
Release checklist
versionCodeis higher than the last Play upload.- Release keystore exists and
bundleReleasecreates a signed.aab. SUPABASE_URLandSUPABASE_PUBLISHABLE_KEYpoint to the production project.- Missing
todos/profilesschema has been applied if the template repo has not yet added those migrations. revenuecat-webhookis deployed withREVENUECAT_WEBHOOK_AUTH.send-test-pushis deployed with Firebase Admin secrets if reviewers should test push.REVENUECAT_ANDROID_KEYis set and Play products are active.APP_UPDATE_URLpoints to the Play listing once it exists.- Legal URLs resolve over HTTPS.
- App icon, feature graphic, phone screenshots, and tablet screenshots are uploaded.
- Data safety, privacy policy, app access, ads, content rating, and target audience forms are complete.
