11package com .badlogic .gdx .pay .android .googlebilling ;
22
33import android .app .Activity ;
4+ import android .os .Handler ;
5+ import android .os .Looper ;
46import com .android .billingclient .api .*;
57import com .android .billingclient .api .BillingClient .ProductType ;
68import com .badlogic .gdx .Gdx ;
1618 * <p>
1719 * <a href="https://developer.android.com/google/play/billing/billing_java_kotlin">Reference docs</a>
1820 * <p>
21+ * Exponential back-off copied from (a clone of) an
22+ * <a href="https://github.com/john990/play-billing-samples/blob/main/TrivialDriveJava/app/src/main/java/com/sample/android/trivialdrivesample/billing/BillingDataSource.java">Android
23+ * sample</a>.
24+ * <p>
1925 * Created by Benjamin Schulte on 07.07.2018.
2026 */
2127
2228public class PurchaseManagerGoogleBilling implements PurchaseManager , PurchasesUpdatedListener {
2329 private static final String TAG = "GdxPay/GoogleBilling" ;
30+ private static final long RECONNECT_TIMER_START_MILLISECONDS = 1000L ;
31+ private static final long RECONNECT_TIMER_MAX_TIME_MILLISECONDS = 1000L * 60L * 15L ; // 15 mins
32+ private static final Handler handler = new Handler (Looper .getMainLooper ());
2433
2534 private final Map <String , Information > informationMap = new ConcurrentHashMap <>();
2635 private final Activity activity ;
@@ -30,6 +39,8 @@ public class PurchaseManagerGoogleBilling implements PurchaseManager, PurchasesU
3039 private BillingClient mBillingClient ;
3140 private PurchaseObserver observer ;
3241 private PurchaseManagerConfig config ;
42+ private boolean hasBillingSetupFinishedSuccessfully = false ;
43+ private long reconnectMilliseconds = RECONNECT_TIMER_START_MILLISECONDS ;
3344
3445 public PurchaseManagerGoogleBilling (Activity activity ) {
3546 this .activity = activity ;
@@ -58,23 +69,22 @@ public void install(PurchaseObserver observer, PurchaseManagerConfig config, boo
5869 // make sure to call the observer again
5970 installationComplete = false ;
6071
61- startServiceConnection (new Runnable () {
62- @ Override
63- public void run () {
64- // it might happen that this was already disposed until the service connection was established
65- if (PurchaseManagerGoogleBilling .this .observer == null )
66- return ;
72+ startServiceConnection (this ::handleBillingSetupFinished );
73+ }
6774
68- if (!serviceConnected )
69- PurchaseManagerGoogleBilling .this .observer .handleInstallError (
70- new GdxPayException ("Connection to Play Billing not possible" ));
71- else
72- fetchOfferDetails ();
73- }
74- });
75+ private void handleBillingSetupFinished () {
76+ // it might happen that this was already disposed until the service connection was established
77+ if (PurchaseManagerGoogleBilling .this .observer == null )
78+ return ;
79+
80+ if (!serviceConnected )
81+ PurchaseManagerGoogleBilling .this .observer .handleInstallError (
82+ new GdxPayException ("Connection to Play Billing not possible" ));
83+ else
84+ fetchOfferDetails ();
7585 }
7686
77- private void startServiceConnection (final Runnable excecuteOnSetupFinished ) {
87+ private void startServiceConnection (final Runnable executeOnSetupFinished ) {
7888 mBillingClient .startConnection (new BillingClientStateListener () {
7989 @ Override
8090 public void onBillingSetupFinished (@ Nonnull BillingResult result ) {
@@ -83,19 +93,39 @@ public void onBillingSetupFinished(@Nonnull BillingResult result) {
8393 Gdx .app .debug (TAG , "Setup finished. Response code: " + billingResponseCode );
8494
8595 serviceConnected = (billingResponseCode == BillingClient .BillingResponseCode .OK );
96+ if (serviceConnected ) {
97+ reconnectMilliseconds = RECONNECT_TIMER_START_MILLISECONDS ;
98+ hasBillingSetupFinishedSuccessfully = true ;
99+ } else {
100+ reconnectWithService ();
101+ }
86102
87- if (excecuteOnSetupFinished != null ) {
88- excecuteOnSetupFinished .run ();
103+ if (executeOnSetupFinished != null ) {
104+ executeOnSetupFinished .run ();
89105 }
90106 }
91107
92108 @ Override
93109 public void onBillingServiceDisconnected () {
94110 serviceConnected = false ;
111+ reconnectWithService ();
95112 }
96113 });
97114 }
98115
116+ private void reconnectWithService () {
117+ handler .postDelayed (new Runnable () {
118+ @ Override
119+ public void run () {
120+ Runnable executeOnSetupFinished = hasBillingSetupFinishedSuccessfully
121+ ? null
122+ : PurchaseManagerGoogleBilling .this ::handleBillingSetupFinished ;
123+ startServiceConnection (executeOnSetupFinished );
124+ }
125+ }, reconnectMilliseconds );
126+ reconnectMilliseconds = Math .min (reconnectMilliseconds * 2 , RECONNECT_TIMER_MAX_TIME_MILLISECONDS );
127+ }
128+
99129 private void fetchOfferDetails () {
100130 Gdx .app .debug (TAG ,"Called fetchOfferDetails()" );
101131 productDetailsMap .clear ();
0 commit comments