skill: add Android skills
This commit is contained in:
93
.agents/skills/play-billing-library-version-upgrade/SKILL.md
Normal file
93
.agents/skills/play-billing-library-version-upgrade/SKILL.md
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
name: play-billing-library-version-upgrade
|
||||
description: Use this skill when upgrading or migrating an Android project from any
|
||||
legacy Google Play Billing Library (PBL) version to the latest stable version of
|
||||
PBL.
|
||||
license: Complete terms in LICENSE.txt
|
||||
metadata:
|
||||
author: Google LLC
|
||||
last-updated: '2026-07-02'
|
||||
keywords:
|
||||
- android
|
||||
- play billing
|
||||
- play billing library
|
||||
- pbl
|
||||
- upgrade
|
||||
- migration
|
||||
- deprecation
|
||||
- google play
|
||||
---
|
||||
|
||||
## Phase 0: Intent Message
|
||||
|
||||
**Reporting Action**: Before proceeding, immediately tell the user: "I will
|
||||
upgrade Play Billing Library to the latest version."
|
||||
|
||||
## Phase 1: Discovery \& Situational Awareness
|
||||
|
||||
1. **Primary Check (Build Version)** : Locate the project's billing dependency (e.g., `com.android.billingclient:billing`) in `build.gradle`, `build.gradle.kts`, or `libs.versions.toml`.
|
||||
2. **Initial Compilation Test**: Attempt to sync and build the project immediately.
|
||||
3. **Fallback Discovery (Effective Version)** :
|
||||
- **Trigger**: Only if the build fails immediately, scan the source code for deprecated artifacts.
|
||||
- **Logic** : The presence of deprecated APIs indicates the **"Effective
|
||||
Version"** ---defined as the version where those specific APIs were **last
|
||||
available**, not when they were introduced.
|
||||
- **Example** : If `SkuDetails` is present, treat the baseline as **PBL v7** or earlier (regardless of the version string in `build.gradle`).
|
||||
4. **Identify Target \& Path** : Access the version tool or release notes to find the latest stable version and calculate a \[Direct/Stepped\] migration path based on the **Effective Version** baseline.
|
||||
|
||||
- **Calculate Migration Path** :
|
||||
- If the **Effective Version** is within 2 major versions of the target: Plan a **Direct Migration**.
|
||||
- If it is more than 2 major versions behind: Plan a **Stepped
|
||||
Migration**. Migrate by two major versions at a time (e.g., v4 -\> v6 -\> v8) until you are within two versions of the target.
|
||||
- **Reporting Action**: Before proceeding, tell the user: "I've detected you are effectively on PBL \[Current\] and the latest is \[Target\]. I am planning a \[direct/stepped\] migration path."
|
||||
|
||||
## Phase 2: Contextual Document Mapping \& Planning
|
||||
|
||||
For every major version jump identified in your path, you **MUST** synthesize
|
||||
instructions from:
|
||||
|
||||
- **[Migration Guide](https://developer.android.com/google/play/billing/migrate-gpblv%5BX%5D)** (where `[X]` is the target major version).
|
||||
- **Release Highlights** : The "Deprecations" and "Breaking Changes" sections of the relevant [Release Notes](references/android/google/play/billing/release-notes.md).
|
||||
- **Developer Documentation**: Consult your knowledge of the Google Play Billing documentation regarding the relevant features used in this app (e.g., Subscriptions, One-Time Products).
|
||||
- **Develop the Plan**: Identify every specific code change required (API removals, class replacements, logic shifts) and print this out as a checklist.
|
||||
|
||||
## Phase 3: Instructions for Execution
|
||||
|
||||
*Reporting Action: For each of the following steps, give a brief explanation of
|
||||
what you will be doing prior to execution, and a brief summary of what you
|
||||
accomplished afterwards.*
|
||||
|
||||
### Step 1: SDK \& Environment Alignment
|
||||
|
||||
- **Action** : Update `build.gradle` to meet SDK requirements (e.g., "PBL 9 requires `compileSdk` 35").
|
||||
- **Gradle Version**: Verify if the new library requires a newer Android Gradle Plugin (AGP) or Kotlin version.
|
||||
|
||||
### Step 2: Intent-based Refactoring
|
||||
|
||||
Analyze the intent of the existing code rather than performing purely textual
|
||||
string replacement.
|
||||
|
||||
- **Action** : You **MUST** follow all deprecation instructions and refactor patterns from **both** the [references/migration-logic.md](references/migration-logic.md) section, the official migration guides, and the general documentation pages identified in Phase 2.
|
||||
- **Verification** : Verify you are doing **all steps from all documentation** and then making sure you follow the specific directions from the checklist in the references.
|
||||
|
||||
### Step 3: Sequential Verification (Only applicable for Stepped Migrations)
|
||||
|
||||
1. **Upgrade** to the first major intermediate version in your path.
|
||||
2. **Run `./gradlew assembleDebug`** to verify no intermediate breaking changes were missed.
|
||||
3. **Repeat** until you reach the final target version.
|
||||
|
||||
### Step 4: Final Validation Checklist
|
||||
|
||||
1. **Smart Checklist Verification**:
|
||||
2. Open [references/version-checklist.md](references/version-checklist.md) and locate the **Smart Version-Specific Checklist**.
|
||||
3. **Action**: For every version between your \[Detected Effective Version\] and \[Detected New Version\], verify that every item has been addressed in the code using "Find in Files" or structural analysis.
|
||||
4. **Tests** : Run all unit and implementation tests (`./gradlew test`).
|
||||
5. **Clean Build** : Verify the project completes a full clean build: `./gradlew clean assembleDebug`. Then, run `./gradlew sync` and `./gradlew build` so that the user can immediately test the new version manually.
|
||||
|
||||
## Final Report
|
||||
|
||||
Explain the "Why" to the developer:
|
||||
|
||||
- "I updated your SDK to \[Version\] because PBL \[Version\] requires it for \[Reason from docs\]."
|
||||
- "I removed your custom `retryConnection()` logic because it is now handled natively by the library using `enableAutoServiceReconnection()`."
|
||||
- "Successfully upgraded from PBL \[Old\] to PBL \[New\] and verified with unit tests. Based on an analysis of features in the latest library and this application's current feature set, I suggest exploring \[New Feature\] (e.g., Prepaid Plans or Installments) from the latest release because it is now available but not yet implemented."
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,78 @@
|
||||
## High-Impact Migration Logic
|
||||
|
||||
### 1. Connection Management (The v8+ Reconnection Shift)
|
||||
|
||||
**Intent**: Move from developer-managed state (manual retries) to
|
||||
library-managed state.
|
||||
|
||||
- **Remove** : Manual `startConnection()` calls or retry timers inside `onServiceDisconnected()`.
|
||||
- **Add** : `.enableAutoServiceReconnection()` to `BillingClient.Builder`.
|
||||
- **Logic** : In v8+, the library handles transient disconnections. Your `onServiceDisconnected` must only be used for logging or updating UI state (e.g., "Billing service temporarily unavailable").
|
||||
|
||||
### 2. Product Querying \& Models (The v5-v8 Architectural Shift)
|
||||
|
||||
**Intent**: Support the "One Product, Multiple Offers" model introduced in v5
|
||||
and refined in v8.
|
||||
|
||||
- **Data Model Swap** :
|
||||
- **Legacy** : `SkuDetails` (1:1 mapping of ID to price).
|
||||
- **Modern** : `ProductDetails`. A single `ProductDetails` can contain multiple `SubscriptionOfferDetails` (Base Plans + Offers).
|
||||
- **Result Handling (v8+ Logic)** :
|
||||
- **Change** : `queryProductDetailsAsync` no longer returns a list in the listener.
|
||||
- **New Intent** : You must receive a `QueryProductDetailsResult` object.
|
||||
- **Refactor** : `kotlin
|
||||
// PBL 8+ Pattern
|
||||
billingClient.queryProductDetailsAsync(params) { result: QueryProductDetailsResult ->
|
||||
val responseCode = result.billingResult.responseCode
|
||||
val productDetailsList = result.productDetailsList // Retrieve list from result object
|
||||
// Process list...
|
||||
}`
|
||||
|
||||
### 3. Subscription Modernization (v6 \& v7)
|
||||
|
||||
**Intent**: Support "Base Plans" and "Offers" instead of legacy standalone SKUs.
|
||||
|
||||
- **Subscription Upgrades/Downgrades (v6+)**:
|
||||
|
||||
- **Legacy** : `setOldSkuPurchaseToken()` in `BillingFlowParams`.
|
||||
- **Modern** : Use `SubscriptionUpdateParams`. You must specify the `PurchaseToken` of the existing subscription and the `ReplacementMode` (which replaces the deprecated `ProrationMode`).
|
||||
- **Logic** : Verify that the `ReplacementMode` matches the business intent (e.g., `CHARGE_FULL_PRICE` versus `WITH_TIME_PRORATION`).
|
||||
- **Installment Plans (v7+)**:
|
||||
|
||||
- **Intent**: Allow users to pay for a subscription in monthly installments.
|
||||
- **Check** : Look for `InstallmentPlanDetails` within `SubscriptionOfferDetails`. If the app supports high-ticket subscriptions, it is mandatory to implement the `installmentPlanDetails` UI.
|
||||
|
||||
### 4. Purchase Handling \& History (v6+)
|
||||
|
||||
**Intent**: Move away from local-only purchase caches to real-time status
|
||||
checks.
|
||||
|
||||
- **Active Purchases** :
|
||||
- **Deprecated** : `queryPurchases()` (synchronous).
|
||||
- **Mandatory** : `queryPurchasesAsync()`. You must pass `QueryPurchasesParams` containing the `ProductType` (`INAPP` or `SUBS`).
|
||||
- **Purchase History (Pagination Intent)** :
|
||||
- **v6+ Change** : `queryPurchaseHistoryAsync` is optimized for pagination.
|
||||
- **Logic** : If the app has thousands of historical transactions, verify you are using the `PurchaseHistoryRecord` list correctly to avoid memory overhead.
|
||||
|
||||
### 5. Security \& Pending Transactions (The "Always On" Rule)
|
||||
|
||||
- **Mandatory** : `enablePendingPurchases()` has been required since v3, but in v8+, verify that it is called before `.build()`. You must also include `.enableOneTimeProducts()` on the `enablePendingPurchases()` builder.
|
||||
- **Optional** : If the app sells prepaid subscriptions, you must also include `.enablePrepaidPlans()`.
|
||||
- **Intent**: This handles "Slow/Delayed" payments (like cash or bank transfers). Without this, the app will crash on initialization in modern versions.
|
||||
|
||||
### 6. SDK \& Environment Requirements
|
||||
|
||||
- **PBL 7.0** : Requires `compileSdk 34` or higher.
|
||||
- **PBL 8.0** : Requires `compileSdk 34` or higher.
|
||||
- **PBL 9.0** : Requires `compileSdk 35` or higher.
|
||||
- **Kotlin** : Verify that `kotlin-stdlib` is updated to at least 1.9.x to support new library coroutine extensions.
|
||||
|
||||
### 7. User-Facing Features (Post-Upgrade Recommendations)
|
||||
|
||||
Once the upgrade is complete, the following features are enabled by these
|
||||
versions:
|
||||
|
||||
- **v7** : **Installments** (Monthly payments for annual plans).
|
||||
- **v8** : **Prepaid Plans** (Users can top-up time without auto-renewing).
|
||||
- **v8** : **Personalized Pricing** (Show legal disclosure if price varies by user).
|
||||
- **v9** : **In-App Price Reviews** (Users can accept upcoming subscription price increases directly inside the app without leaving for the Play Store; capped by Google at a maximum of once every 7 days).
|
||||
@@ -0,0 +1,54 @@
|
||||
## Play Billing Library: Smart Version-Specific Checklist
|
||||
|
||||
Use this checklist to verify that every technical requirement between your
|
||||
\[Current Version\] and \[Target Version\] has been met.
|
||||
|
||||
## PBL v1.x through v3.x
|
||||
|
||||
- \[ \] **\[v1.0\] Builder Pattern** : Verify `BillingClient.newBuilder(context)` is used.
|
||||
- \[ \] **\[v2.0\] Mandatory Acknowledgment** : Verify `acknowledgePurchase()` or `consumeAsync()` is called within 3 days.
|
||||
- \[ \] **\[v2.0\] Response Types** : Logic must handle `BillingResult` objects instead of raw integers.
|
||||
- \[ \] **\[v3.0\] Legacy Removal** : Verify `ChildDirected` and `UnderAgeOfConsent` parameters are deleted.
|
||||
|
||||
## PBL v4.x Series
|
||||
|
||||
- \[ \] **Async Purchasing** : Confirm `queryPurchases()` is replaced with `queryPurchasesAsync()`.
|
||||
- \[ \] **Multi-SKU Accessors** : Replace `getSku()` with `getSkus()` (returns a list) in `Purchase` objects.
|
||||
- \[ \] **Subscription Refactor** : Verify `setSubscriptionUpdateParams()` is used for change logic.
|
||||
|
||||
## PBL v5.x Series
|
||||
|
||||
- \[ \] **Data Model Swap** : Replace all instances of `SkuDetails` with `ProductDetails`.
|
||||
- \[ \] **Personalized Pricing** : Implement `setIsOfferPersonalized()` for EU price disclosures.
|
||||
|
||||
## PBL v6.x Series
|
||||
|
||||
- \[ \] **Replacement Mode** : Replace `ProrationMode` with the `ReplacementMode` enum.
|
||||
- \[ \] **User Choice Billing** : Replace `AlternativeBillingListener` with `UserChoiceBillingListener`.
|
||||
|
||||
## PBL v7.x Series
|
||||
|
||||
- \[ \] **SDK Compliance** : `compileSdk` is set to 34 or higher.
|
||||
- \[ \] **Pending Purchases** : Replace parameterless `enablePendingPurchases()` with `enablePendingPurchases(PendingPurchaseParams)`.
|
||||
- \[ \] **API Cleanup** : Replace `setOldSkuPurchaseToken()` with `setOldPurchaseToken()`.
|
||||
|
||||
## PBL v8.x Series
|
||||
|
||||
- \[ \] **SDK Compliance** : `compileSdk` is set to 34 or higher.
|
||||
- \[ \] **Terminology Shift**: Rename "in-app items" to "one-time products" in UI/strings.
|
||||
- \[ \] **Signature Enforcement** : `onProductDetailsResponse` signature MUST be `(BillingResult, QueryProductDetailsResult)`.
|
||||
- \[ \] **SUBS Offer Token** : For `SUBS` type, `ProductDetailsParams` MUST include an `offerToken`.
|
||||
- \[ \] **Auto-Reconnection** : Verify `enableAutoServiceReconnection()` is used in the builder.
|
||||
- \[ \] **Min SDK Increase** : Verify `minSdkVersion` is at least 23.
|
||||
|
||||
## PBL v9.x Series
|
||||
|
||||
- \[ \] **SDK Compliance** : `compileSdk` is set to 35 or higher.
|
||||
- \[ \] **API Removals** : Ensure all usages of `SkuDetails`, `SkuDetailsParams`, and `SkuDetailsResponseListener` are removed and replaced with their `ProductDetails` equivalents.
|
||||
- \[ \] **Blocked Store Error Handling** : If targeting restricted device modes (e.g., kids modes), ensure `androidx.core` is at v1.9+ and update error logic to catch `BILLING_UNAVAILABLE` instead of `ERROR`.
|
||||
- \[ \] **External Payment Program Null-Safety** : If using developer-provided billing, update `DeveloperProvidedBillingDetails.getLinkUri()` logic to explicitly check for both `null` and empty string (`""`) values before parsing.
|
||||
|
||||
## Future Versions (PBL 10.0.0+)
|
||||
|
||||
- \[ \] **Dynamic Checklist Generation** : For any version \>=10.0.0, you **MUST** synthesize a new checklist for each new version header found in the [Release Notes](https://developer.android.com/google/play/billing/release-notes).
|
||||
- \[ \] **Identify Version Delta** : Review "Breaking Changes" and "Removed APIs" for the new version and create a list of terms to `grep`.
|
||||
Reference in New Issue
Block a user