Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One instance of BillingClient throughout app

I have an app that has many activities. One of the activity is for showing purchase options.

In the sample apps for the billing library (https://github.com/googlesamples/android-play-billing), BillingClientLifecycle and BillingManager are used, both of which are associated to a single activity, so the connection is opened/closed when the activity is created/destroyed.

However in an app with many activities, it seems not ideal to do this separately for different activities. I also want to check on app start whether the subscriptions are valid.

I am thinking of creating the BillingClient in the app's Application subclass. However if I do this, I would only be opening the BillingClient connection and not closing it (as there's no onDestroy method in there). Has anyone done this before and hit any issues? Also is this against best practices and will it cause any issues with network / performance?

like image 394
mliu Avatar asked Nov 02 '18 02:11

mliu


People also ask

What is BillingClient in Android?

↳ com.android.billingclient.api.BillingClient. Main interface for communication between the library and user application code. It provides convenience methods for in-app billing. You can create one instance of this class for your application and use it to process in-app billing operations.

How do you acknowledge in-app purchases?

To acknowledge non-consumable purchases, use either BillingClient. acknowledgePurchase() from the Google Play Billing Library or Product. Purchases. Acknowledge from the Google Play Developer API.

What is in-app purchase in Android?

With some apps, you can buy additional content or services within the app. We call these "in-app purchases." Here are some examples of in-app purchases: A sword that gives you more power in a game. A key that unlocks more features of an app.

Is billingclient asynchronous or synchronous?

It provides synchronous (blocking) and asynchronous (non-blocking) methods for many common in-app billing operations. It's strongly recommended that you instantiate only one BillingClient instance at one time to avoid multiple PurchasesUpdatedListener.onPurchasesUpdated (BillingResult, List) callbacks for a single event.

What are the functions of billingclient?

Initiates the billing flow for an in-app purchase or subscription. Initiates a flow to confirm the change of price for an item subscribed by the user. Constructs a new BillingClient.Builder instance. Returns the most recent purchase made by the user for each SKU, even if that purchase is expired, canceled, or consumed.

What is play billing library for Android?

Exploring the Play Billing Library for Android. In-app billing is a powerful part of the Android framework that allows us to easily monetise our applications with in-app purchases and subscriptions. Google previously provided us with the in-app billing which allows us to implement this within our apps.

Is the billing library a replacement for in-app billing?

The documentation does not state the library as a replacement, but more as an easier way of implementing in-app billing. However, the library does allow you to reduce the amount of code required to implement in-app billing.


2 Answers

I read through the sources of BillingClientImpl.java in billing-1.2.2-sources.jar, and I believe it is safe to use BillingClient as an application singleton, even if this means never calling BillingClient.endConnection().

BillingClientImpl.java doesn't need/use an Activity in its constructor; it uses a Context, and all it does is call context.getApplicationContext() to store the app context. The launchBillingFlow method does have an Activity parameter, but the activity isn't stored; its only purpose is to call activity.startActivity(intent) with the billing intent.

BillingClient.startConnection calls context.registerReceiver to register its own BillingBroadcastReceiver as a BroadcastReceiver, then calls context.bindService to bind a service connection. (Again, both of these calls are executed against the app context mApplicationContext, not on any particular Activity.)

As long as the billing client is required for the lifetime of the app, it's safe and acceptable to call registerReceiver and bindService in Application.onCreate() and to never call unregisterReceiver or unbindService.

This would not be safe if the registerReceiver and/or bindService calls used an Activity context, because the ServiceConnection would leak when the Activity was destroyed, but when the app is destroyed, its process terminates, and all of its service connections are automatically cleaned up.

like image 71
Dan Fabulich Avatar answered Sep 28 '22 04:09

Dan Fabulich


Regarding the updated 2.x version of the billing library, a quote from the TrivialDriveKotlin official demo app BillingRepository sources:

Notice that the connection to [playStoreBillingClient] is created using the applicationContext. This means the instance is not [Activity]-specific. And since it's also not expensive, it can remain open for the life of the entire [Application]. So whether it is (re)created for each [Activity] or [Fragment] or is kept open for the life of the application is a matter of choice.

I guess this applies to the first version too.

like image 35
Valeriy Katkov Avatar answered Sep 28 '22 04:09

Valeriy Katkov