One instance of BillingClient throughout app
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.
It looks like this can be done with architecture components. I.e. in your application's OnCreate, call:
ProcessLifecycleOwner.get().lifecycle.addObserver(billingClient)
And just inject the billingClient into the activities that need it.
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.