Skip to content

Add kotlin snippets for User Billing #975

Draft
sidd607 wants to merge 3 commits into
mainfrom
play-billing-snippets
Draft

Add kotlin snippets for User Billing #975
sidd607 wants to merge 3 commits into
mainfrom
play-billing-snippets

Conversation

@sidd607

@sidd607 sidd607 commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Add Kotlin code snippets for Play Billing Choice integration

Description

This PR adds the Kotlin code snippets for the Billing Choice integration guidance to the playbilling module.

The snippets have been implemented in a new file: playbilling/src/main/java/com/example/pbl/kotlin/billingchoice/Integration.kt.

To support the new Billing Choice APIs, the Play Billing Library dependency has been upgraded to 9.1.0.

Changes in addition to the snippet

  • Fix Double-Resume Crash: suspendCancellableCoroutine could attempt to resume a continuation multiple times if the billing service disconnected after a successful connection. Added continuation.isActive checks to safeguard this.
  • Idiomatic Kotlin (SAM Conversions): Refactored createBillingProgramReportingDetailsAsync to use a lambda instead of an anonymous BillingProgramReportingDetailsListener object.

@sidd607 sidd607 requested a review from a team as a code owner July 3, 2026 11:19
@snippet-bot

snippet-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

Here is the summary of changes.

You are about to add 15 region tags.

This comment is generated by snippet-bot.
If you find problems with this result, please file an issue at:
https://github.com/googleapis/repo-automation-bots/issues.
To update this comment, add snippet-bot:force-run label or use the checkbox below:

  • Refresh this comment

@sidd607 sidd607 requested a review from trwhite-google July 3, 2026 11:19

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the playbilling dependency to version 9.1.0 and introduces a new Integration class to handle various Google Play Billing Choice integration scenarios. The review feedback highlights a critical issue where the class-level billingClient property is shadowed locally within connection methods instead of being reassigned, which requires changing the property to a var. Additionally, several redundant self-assignments and an unused import should be cleaned up to improve code quality.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

private val activity: Activity,
private val billingClient: BillingClient,
private val developerProvidedBillingListener: DeveloperProvidedBillingListener,
private val purchasesUpdatedListener: PurchasesUpdatedListener

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The billingClient property is declared as a read-only val. However, inside startConnectionGoogleRenderedInApp and startConnectionDeveloperRenderedInApp, a new BillingClient instance is built locally and shadows this property. This local instance is discarded after the connection method finishes, meaning other methods in this class will continue to use the original, unconfigured billingClient passed to the constructor.\n\nTo fix this, change private val billingClient to private var billingClient so that the newly configured instance can be reassigned to the class property.

Suggested change
private val purchasesUpdatedListener: PurchasesUpdatedListener
private var billingClient: BillingClient,

// pending purchases support, and the billing choice params.
val billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases(pendingPurchasesParams)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Remove the val keyword to reassign the newly built and configured BillingClient to the class-level billingClient property instead of shadowing it.

Suggested change
.enablePendingPurchases(pendingPurchasesParams)
billingClient = BillingClient.newBuilder(context)

val billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases(pendingPurchasesParams)
.enableBillingProgram(params)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Remove the val keyword to reassign the newly built and configured BillingClient to the class-level billingClient property instead of shadowing it.

Suggested change
.enableBillingProgram(params)
billingClient = BillingClient.newBuilder(context)

import com.android.billingclient.api.BillingProgramAvailabilityDetails.BillingChoiceAvailabilityDetails.ChoiceScreenType
import com.android.billingclient.api.BillingProgramReportingDetailsParams
import com.android.billingclient.api.BillingProgramReportingDetailsParams.DeveloperBillingType
import com.android.billingclient.api.BillingResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The import com.android.billingclient.api.BillingProgramReportingDetailsListener is unused and can be safely removed.

val activity: Activity = activity

val params = LaunchExternalLinkParams.newBuilder()
.setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This self-assignment is redundant and triggers a compiler warning because activity is already available as a class property. You can safely remove this line.

val externalTransactionId = externalTransactionId

val developerBillingOptionParams = DeveloperBillingOptionParams.newBuilder()
.setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This self-assignment is redundant and triggers a compiler warning because externalTransactionId is already available as a parameter of the function. You can safely remove this line.

val externalTransactionId = externalTransactionId

// 1. Construct DeveloperBillingOptionParams indicating the billing program
val developerBillingOptionParams = DeveloperBillingOptionParams.newBuilder()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This self-assignment is redundant and triggers a compiler warning because externalTransactionId is already available as a parameter of the function. You can safely remove this line.

@sidd607 sidd607 marked this pull request as draft July 3, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant