learning_ai_common_plat/docs/_MobileApps/GOOGLE/README.md
saravanakumardb1 a762c5b07f docs: add Apple App Store + Google Play Store release guides
- APPLE/README.md: API key details, App Store Connect setup, TestFlight workflow, submission checklist, provisioning, screenshots/metadata requirements
- GOOGLE/README.md: Play Console setup, service account config, signing keys, AAB upload, testing tracks, data safety, content rating, submission checklist
2026-04-04 23:37:25 -07:00

12 KiB
Raw Blame History

Google Play Store — Android App Distribution Guide

Google Play Console

Field Value
Console URL play.google.com/console
Developer Account ByteLyst / saravanakumardb1@gmail.com

Registered Apps

Product Package Name Play Console Status
LysnrAI com.bytelyst.lysnrai Needs creation Gradle builds, pending setup
ChronoMind com.chronomind.app Needs creation Gradle builds, pending setup
MindLyst com.mindlyst.android Needs creation KMP shared module, pending setup
JarvisJr com.jarvisjr.app Needs creation Jetpack Compose, pending setup

One-Time Setup

1. Google Play Console Account

If you don't have one yet:

  1. Go to play.google.com/console/signup
  2. Pay the one-time $25 registration fee
  3. Complete identity verification (can take 48 hours)

2. Create a Service Account (for CLI uploads)

  1. Go to Google Cloud Console → IAM → Service Accounts
  2. Select or create a project (e.g., bytelyst-releases)
  3. Click "+ Create Service Account"
    • Name: play-upload
    • Role: (skip — we'll grant access in Play Console)
  4. Click "...""Manage keys""Add Key""Create new key"JSON
  5. Save the JSON key file to this directory and ~/.google-play/
mkdir -p ~/.google-play
cp service-account-key.json ~/.google-play/
chmod 600 ~/.google-play/service-account-key.json
  1. Go to Play Console → Settings → API access
  2. Click "Link" next to Google Cloud project
  3. Under Service Accounts, find play-upload"Grant access"
  4. Set permissions: Release manager (or Admin for full control)
  5. Add the apps it can manage

Creating a New App in Play Console

  1. Go to Play Console → All apps
  2. Click "Create app"
  3. Fill in:
    • App name: Product name (e.g., ChronoMind)
    • Default language: English (United States)
    • App or Game: App
    • Free or Paid: Free
  4. Accept declarations and click "Create app"

After Creation — Complete the Store Listing

Navigate through the Dashboard checklist:

Section Required For
App access If app requires login → provide test credentials
Ads Declare if app contains ads
Content rating Complete IARC questionnaire
Target audience Select age groups
News apps Declare if it's a news app
COVID-19 apps Declare if related
Data safety Privacy questionnaire (like Apple's App Privacy)
Government apps Declare if government-related

Building an Android Release

Signing Key Setup (one-time per app)

# Generate an upload keystore
keytool -genkey -v \
  -keystore ~/keystores/chronomind-upload.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias upload \
  -storepass <PASSWORD> \
  -keypass <PASSWORD> \
  -dname "CN=ByteLyst, O=ByteLyst, L=Dallas, ST=TX, C=US"

⚠️ CRITICAL: Back up the keystore file and passwords. If you lose them, you cannot update the app. Store a copy in this directory.

Configure signing in the app

Create or edit android/keystore.properties (gitignored):

storePassword=<PASSWORD>
keyPassword=<PASSWORD>
keyAlias=upload
storeFile=/Users/<you>/keystores/chronomind-upload.jks

Reference in android/app/build.gradle.kts:

val keystoreProperties = Properties()
val keystoreFile = rootProject.file("keystore.properties")
if (keystoreFile.exists()) keystoreProperties.load(keystoreFile.inputStream())

android {
    signingConfigs {
        create("release") {
            keyAlias = keystoreProperties["keyAlias"] as? String
            keyPassword = keystoreProperties["keyPassword"] as? String
            storeFile = file(keystoreProperties["storeFile"] as? String ?: "")
            storePassword = keystoreProperties["storePassword"] as? String
        }
    }
    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
        }
    }
}

Build the Release AAB

cd android
./gradlew :app:bundleRelease
# Output: app/build/outputs/bundle/release/app-release.aab

Build a Release APK (for direct install)

./gradlew :app:assembleRelease
# Output: app/build/outputs/apk/release/app-release.apk

Uploading to Play Console

Manual Upload (Play Console UI)

  1. Go to app → Production (or Internal testing / Closed testing)
  2. Click "Create new release"
  3. Upload the .aab file
  4. Add release notes
  5. Click "Review release""Start rollout"

CLI Upload via bundletool + Google API

pip install google-api-python-client google-auth

python3 -c "
from googleapiclient.discovery import build
from google.oauth2 import service_account

creds = service_account.Credentials.from_service_account_file(
    '$HOME/.google-play/service-account-key.json',
    scopes=['https://www.googleapis.com/auth/androidpublisher']
)

service = build('androidpublisher', 'v3', credentials=creds)
package = 'com.chronomind.app'

edit = service.edits().insert(body={}, packageName=package).execute()
edit_id = edit['id']

service.edits().bundles().upload(
    editId=edit_id, packageName=package,
    media_body='app/build/outputs/bundle/release/app-release.aab',
    media_mime_type='application/octet-stream'
).execute()

service.edits().tracks().update(
    editId=edit_id, packageName=package, track='internal',
    body={'releases': [{'status': 'completed', 'versionCodes': ['1']}]}
).execute()

service.edits().commit(editId=edit_id, packageName=package).execute()
print('Upload complete!')
"

Add to android/build.gradle.kts:

plugins {
    id("com.github.triplet.play") version "3.11.0"
}

play {
    serviceAccountCredentials.set(file("$HOME/.google-play/service-account-key.json"))
    track.set("internal")  // internal, alpha, beta, production
    defaultToAppBundles.set(true)
}

Then:

./gradlew publishBundle          # Upload AAB to configured track
./gradlew publishInternalBundle  # Upload to internal testing
./gradlew publishAlphaBundle     # Upload to closed testing
./gradlew publishBundle --track production  # Upload to production

Testing Tracks

Track Testers Review Required Purpose
Internal testing Up to 100 (by email) No Quick dev testing
Closed testing (Alpha) Invite-only No (first time: yes) Wider beta
Open testing (Beta) Anyone with link Yes (first time) Public beta
Production Everyone Yes Full release

Internal Testing Setup

  1. Go to app → TestingInternal testing
  2. Click "Create new release"
  3. Upload .aab
  4. Click "Review release""Start rollout"
  5. Go to Testers tab → Create email list → Add tester emails
  6. Share the opt-in link with testers

Play Store Submission Checklist

Required Assets

Asset Spec Notes
App Icon 512×512 PNG 32-bit, no alpha
Feature Graphic 1024×500 PNG or JPG Required for store listing
Screenshots (Phone) 320-3840px, 16:9 or 9:16 Min 2, max 8 per device type
Screenshots (7" Tablet) Same as phone Required if targeting tablets
Screenshots (10" Tablet) Same as phone Required if targeting tablets
Promo Video YouTube URL Optional

Required Metadata

Field Notes
App name Max 30 characters
Short description Max 80 characters
Full description Max 4000 characters
App category Select from predefined list
Contact email Required, public
Privacy Policy URL Required
App type & category App or Game + category

Data Safety Declaration

In Play Console → App content → Data safety:

  • Declare all data types collected
  • Whether data is encrypted in transit
  • Whether users can request deletion
  • Whether data is shared with third parties
  • Purpose of each data type

Content Rating (IARC)

  1. Go to App content → Content rating
  2. Complete the IARC questionnaire
  3. Receive ratings for all regions automatically

Corporate Network / Gradle Proxy

When building on the corporate network:

# Ensure NETWORK=corp is set (switch-network.sh)
echo $GRADLE_OPTS
# Should show -Djavax.net.ssl.trustStore=~/.gradle/ssl/gradle-cacerts.jks

# If not set:
export GRADLE_OPTS="-Djavax.net.ssl.trustStore=$HOME/.gradle/ssl/gradle-cacerts.jks -Djavax.net.ssl.trustStorePassword=changeit"

See learning_ai_common_plat/AGENTS.md § 9 for full proxy setup docs.


Troubleshooting

Error Fix
Keystore was tampered with Wrong password or corrupted keystore
No key with alias 'upload' Check keyAlias in keystore.properties
Version code already exists Bump versionCode in build.gradle.kts
APK/AAB not signed Check signingConfig in release buildType
Deobfuscation file missing Upload mapping.txt alongside the AAB
Data safety form incomplete Complete all sections in App content → Data safety
Target API level Google requires targeting latest Android API (currently 34+)
Gradle proxy failure Set GRADLE_OPTS with truststore (see above)
SDK not found Set sdk.dir in local.properties

Key Files

File Location Purpose
Service Account Key ~/.google-play/service-account-key.json CLI uploads
Upload Keystore ~/keystores/<app>-upload.jks Release signing
keystore.properties android/keystore.properties (gitignored) Local signing config