Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Google Play Store publishing and management expertise
.claude/skills/a5c-ai-google-play-console/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-13 | ✗→✓ | ▲ Improved | 184% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 114% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 192% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 94% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 123% | 0% |
This skill provides comprehensive capabilities for Google Play Store publishing and management. It enables interaction with Google Play Developer API, store listing management, release track configuration, and app lifecycle management.
bash - Execute bundletool, Gradle, and Google Cloud commandsread - Analyze store listing files and configurationswrite - Generate metadata files and API configurationsedit - Update Play Store metadataglob - Search for metadata and graphics filesgrep - Search for patterns in configurationsThis skill integrates with the following processes:
android-playstore-publishing.js - Play Store publishingbeta-testing-setup.js - Beta distributionapp-store-optimization.js - ASO optimizationautomated-release-management.js - Release automationbash# Create service account in Google Cloud Console # 1. Go to Google Cloud Console # 2. Create new service account # 3. Grant "Service Account User" role # 4. Create JSON key file # Link to Play Console # 1. Go to Play Console > Settings > API access # 2. Link Google Cloud project # 3. Grant permissions to service account
json{ "type": "service_account", "project_id": "your-project-id", "private_key_id": "key-id", "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n", "client_email": "service-account@project.iam.gserviceaccount.com", "client_id": "123456789", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token" }
ruby# fastlane/Fastfile lane :deploy_production do gradle( task: "bundle", build_type: "Release" ) supply( track: "production", aab: "./app/build/outputs/bundle/release/app-release.aab", json_key: "./fastlane/play-store-key.json", package_name: "com.example.myapp", # Rollout percentage (0.0 to 1.0) rollout: "0.1", # Skip metadata upload skip_upload_metadata: false, skip_upload_images: false, skip_upload_screenshots: false, skip_upload_changelogs: false, # Release notes release_status: "completed", # Version code version_code: 42, # Mapping file for crash reports mapping: "./app/build/outputs/mapping/release/mapping.txt" ) end lane :deploy_beta do gradle(task: "bundle", build_type: "Release") supply( track: "beta", aab: "./app/build/outputs/bundle/release/app-release.aab", json_key: "./fastlane/play-store-key.json" ) end lane :promote_to_production do supply( track: "beta", track_promote_to: "production", json_key: "./fastlane/play-store-key.json", rollout: "0.2" ) end
fastlane/metadata/android/
├── en-US/
│ ├── title.txt # Max 30 chars
│ ├── short_description.txt # Max 80 chars
│ ├── full_description.txt # Max 4000 chars
│ ├── changelogs/
│ │ ├── default.txt
│ │ ├── 42.txt # Version code specific
│ │ └── 43.txt
│ └── images/
│ ├── phoneScreenshots/
│ │ ├── 1_home.png
│ │ ├── 2_feature.png
│ │ └── 3_settings.png
│ ├── sevenInchScreenshots/
│ ├── tenInchScreenshots/
│ ├── tvScreenshots/
│ ├── wearScreenshots/
│ ├── featureGraphic.png # 1024x500
│ ├── icon.png # 512x512
│ ├── promoGraphic.png # 180x120
│ └── tvBanner.png # 1280x720
├── es-ES/
│ └── ... (same structure)
└── default.txt # Default language codekotlin// Example: Publishing via Google Play Developer API import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport import com.google.api.client.json.gson.GsonFactory import com.google.api.services.androidpublisher.AndroidPublisher import com.google.api.services.androidpublisher.model.* import com.google.auth.http.HttpCredentialsAdapter import com.google.auth.oauth2.GoogleCredentials import java.io.FileInputStream class PlayStorePublisher( private val packageName: String, credentialsPath: String ) { private val publisher: AndroidPublisher init { val credentials = GoogleCredentials .fromStream(FileInputStream(credentialsPath)) .createScoped(listOf("https://www.googleapis.com/auth/androidpublisher")) publisher = AndroidPublisher.Builder( GoogleNetHttpTransport.newTrustedTransport(), GsonFactory.getDefaultInstance(), HttpCredentialsAdapter(credentials) ) .setApplicationName("MyApp Publisher") .build() } fun uploadAndPublish(aabPath: String, track: String, releaseNotes: Map<String, String>) { val edits = publisher.edits() // Create edit val edit = edits.insert(packageName, null).execute() val editId = edit.id try { // Upload AAB val aabFile = java.io.File(aabPath) val uploadResponse = edits.bundles() .upload(packageName, editId, FileContent("application/octet-stream", aabFile)) .execute() val versionCode = uploadResponse.versionCode // Create release val release = TrackRelease().apply { this.versionCodes = listOf(versionCode.toLong()) this.status = "completed" this.releaseNotes = releaseNotes.map { (lang, notes) -> LocalizedText().apply { language = lang text = notes } } } // Update track val trackConfig = Track().apply { this.track = track this.releases = listOf(release) } edits.tracks() .update(packageName, editId, track, trackConfig) .execute() // Commit edit edits.commit(packageName, editId).execute() println("Successfully published version $versionCode to $track") } catch (e: Exception) { // Delete edit on failure edits.delete(packageName, editId).execute() throw e } } }
yaml# data_safety.yaml data_collection: - category: "Personal info" types: - "Name" - "Email address" purposes: - "App functionality" - "Account management" is_optional: false - category: "Financial info" types: - "Purchase history" purposes: - "App functionality" is_optional: false data_sharing: - category: "Analytics" shared_with: "Third parties" purpose: "Analytics" security_practices: data_encrypted_in_transit: true data_deletion_available: true independent_security_review: false
bash# Validate AAB bundletool validate --bundle=app-release.aab # Build APKs from AAB bundletool build-apks \ --bundle=app-release.aab \ --output=app.apks \ --ks=release.keystore \ --ks-key-alias=release \ --ks-pass=pass:password # Install APKs on device bundletool install-apks --apks=app.apks # Get device spec bundletool get-device-spec --output=device-spec.json # Build APKs for specific device bundletool build-apks \ --bundle=app-release.aab \ --output=device.apks \ --device-spec=device-spec.json
kotlin// build.gradle.kts android { defaultConfig { // Auto-increment version code based on CI build number val buildNumber = System.getenv("BUILD_NUMBER")?.toIntOrNull() ?: 1 versionCode = buildNumber versionName = "1.0.${buildNumber}" } }
fastlane-cicd - Build automationkotlin-compose - Android developmentfirebase-mobile - Firebase integration| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 14,168 | 20,633 | +46% | 1 | 1 | 0% | 2,311 | 4,474 | +94% | 0 | 0 | — |
case-02 | pass→pass | 10,437 | 8,314 | -20% | 1 | 1 | 0% | 1,934 | 4,319 | +123% | 0 | 0 | — |
case-03 | pass→pass | 4,581 | 3,981 | -13% | 1 | 1 | 0% | 806 | 3,571 | +343% | 0 | 0 | — |
case-04 | pass→pass | 2,693 | 2,973 | +10% | 1 | 1 | 0% | 469 | 3,510 | +648% | 0 | 0 | — |
case-05 | pass→pass | 4,123 | 2,705 | -34% | 1 | 1 | 0% | 813 | 3,426 | +321% | 0 | 0 | — |
case-06 | pass→pass | 7,027 | 4,928 | -30% | 1 | 1 | 0% | 1,430 | 4,025 | +181% | 0 | 0 | — |
case-07 | pass→pass | 4,106 | 2,826 | -31% | 1 | 1 | 0% | 832 | 3,468 | +317% | 0 | 0 | — |
case-08 | pass→pass | 10,121 | 4,629 | -54% | 1 | 1 | 0% | 1,611 | 3,781 | +135% | 0 | 0 | — |
case-09 | pass→pass | 5,335 | 3,909 | -27% | 1 | 1 | 0% | 1,036 | 3,693 | +256% | 0 | 0 | — |
case-10 | pass→pass | 5,505 | 3,438 | -38% | 1 | 1 | 0% | 989 | 3,531 | +257% | 0 | 0 | — |
case-11 | pass→pass | 5,123 | 2,774 | -46% | 1 | 1 | 0% | 697 | 3,335 | +378% | 0 | 0 | — |
case-12 | pass→pass | 2,768 | 2,691 | -3% | 1 | 1 | 0% | 535 | 3,276 | +512% | 0 | 0 | — |
case-13 | fail→pass | 8,196 | 3,898 | -52% | 1 | 1 | 0% | 1,296 | 3,682 | +184% | 0 | 0 | — |
case-14 | fail→fail | 6,352 | 7,385 | +16% | 1 | 1 | 0% | 1,273 | 4,047 | +218% | 0 | 0 | — |
case-15 | fail→pass | 11,098 | 5,457 | -51% | 1 | 1 | 0% | 1,898 | 4,053 | +114% | 0 | 0 | — |
case-16 | fail→pass | 6,915 | 7,353 | +6% | 1 | 1 | 0% | 1,394 | 4,075 | +192% | 0 | 0 | — |
case-17 | pass→pass | 10,910 | 4,223 | -61% | 1 | 1 | 0% | 2,262 | 3,884 | +72% | 0 | 0 | — |
case-18 | pass→pass | 3,305 | 23,357 | +607% | 1 | 1 | 0% | 550 | 3,466 | +530% | 0 | 0 | — |
case-19 | pass→pass | 12,918 | 12,932 | +0% | 1 | 1 | 0% | 2,129 | 4,970 | +133% | 0 | 0 | — |
case-20 | pass→pass | 7,426 | 5,481 | -26% | 1 | 1 | 0% | 1,440 | 3,996 | +178% | 0 | 0 | — |
case-21 | pass→pass | 11,466 | 7,718 | -33% | 1 | 1 | 0% | 1,824 | 4,534 | +149% | 0 | 0 | — |
case-22 | pass→pass | 13,471 | 12,036 | -11% | 1 | 1 | 0% | 2,828 | 5,547 | +96% | 0 | 0 | — |
case-23 | pass→pass | 11,627 | 11,772 | +1% | 1 | 1 | 0% | 1,912 | 4,844 | +153% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +13 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.