2020import com .android .billingclient .api .BillingClientStateListener ;
2121import com .android .billingclient .api .BillingFlowParams ;
2222import com .android .billingclient .api .BillingResult ;
23+ import com .android .billingclient .api .PendingPurchasesParams ;
24+ import com .android .billingclient .api .ProductDetails ;
2325import com .android .billingclient .api .Purchase ;
2426import com .android .billingclient .api .PurchasesUpdatedListener ;
25- import com .android .billingclient .api .SkuDetails ;
26- import com .android .billingclient .api .SkuDetailsParams ;
27+ import com .android .billingclient .api .QueryProductDetailsParams ;
2728import com .gianlu .commonutils .R ;
2829import com .gianlu .commonutils .dialogs .DialogUtils ;
2930import com .gianlu .commonutils .ui .Toaster ;
3031import com .google .android .material .dialog .MaterialAlertDialogBuilder ;
3132
32- import java .util .Arrays ;
33+ import java .util .ArrayList ;
3334import java .util .List ;
3435
3536public class PreferencesBillingHelper {
3637 private static final String TAG = PreferencesBillingHelper .class .getSimpleName ();
3738 private final Object billingReady = new Object ();
3839 private final DialogUtils .ShowStuffInterface listener ;
39- private final List <String > products ;
40+ private final List <QueryProductDetailsParams . Product > products ;
4041 private BillingClient billingClient ;
4142 private boolean destroyed = false ;
4243
4344 public PreferencesBillingHelper (@ NonNull DialogUtils .ShowStuffInterface listener , String ... products ) {
4445 this .listener = listener ;
45- this .products = Arrays .asList (products );
46+ this .products = new ArrayList <>();
47+ for (String product : products ) {
48+ this .products .add (QueryProductDetailsParams .Product .newBuilder ()
49+ .setProductId (product )
50+ .setProductType (BillingClient .ProductType .INAPP )
51+ .build ());
52+ }
4653 }
4754
4855 public void onStart (@ NonNull Activity activity ) {
4956 if (destroyed ) throw new IllegalStateException ();
5057
51- billingClient = BillingClient .newBuilder (activity ).enablePendingPurchases ().setListener (new InternalListener ()).build ();
58+ billingClient = BillingClient .newBuilder (activity )
59+ .enablePendingPurchases (PendingPurchasesParams .newBuilder ()
60+ .enableOneTimeProducts ()
61+ .enablePrepaidPlans ()
62+ .build ())
63+ .setListener (new InternalListener ()).build ();
5264 billingClient .startConnection (new BillingClientStateListener () {
5365 private boolean retried = false ;
5466
@@ -85,20 +97,22 @@ public void onDestroy() {
8597 }
8698 }
8799
88- private void buyProduct (@ NonNull Activity activity , @ NonNull SkuDetails product ) {
100+ private void buyProduct (@ NonNull Activity activity , @ NonNull ProductDetails product ) {
89101 BillingFlowParams flowParams = BillingFlowParams .newBuilder ()
90- .setSkuDetails (product )
102+ .setProductDetailsParamsList (List .of (BillingFlowParams .ProductDetailsParams .newBuilder ()
103+ .setProductDetails (product )
104+ .build ()))
91105 .build ();
92106
93107 BillingResult result = billingClient .launchBillingFlow (activity , flowParams );
94108 if (result .getResponseCode () != BillingResponseCode .OK )
95109 handleBillingErrors (result .getResponseCode ());
96110 }
97111
98- private void showDonateDialog (@ NonNull Activity activity , List <SkuDetails > products ) {
112+ private void showDonateDialog (@ NonNull Activity activity , List <ProductDetails > products ) {
99113 RecyclerView list = new RecyclerView (activity );
100114 list .setLayoutManager (new LinearLayoutManager (activity , RecyclerView .VERTICAL , false ));
101- list .setAdapter (new SkuAdapter (activity , products , product -> {
115+ list .setAdapter (new ProductAdapter (activity , products , product -> {
102116 buyProduct (activity , product );
103117 listener .dismissDialog ();
104118 }));
@@ -114,15 +128,12 @@ public void donate(@NonNull Activity activity, boolean wasWaiting) {
114128 listener .showDialog (DialogUtils .progressDialog (activity , R .string .connectingBillingService ));
115129
116130 if (billingClient != null && billingClient .isReady ()) {
117- SkuDetailsParams .Builder params = SkuDetailsParams .newBuilder ();
118- params .setSkusList (products ).setType (BillingClient .SkuType .INAPP );
119- billingClient .querySkuDetailsAsync (params .build (), (billingResult , skuDetailsList ) -> {
131+ billingClient .queryProductDetailsAsync (QueryProductDetailsParams .newBuilder ().setProductList (products ).build (), (billingResult , productDetailsList ) -> {
120132 listener .dismissDialog ();
121133
122134 if (billingResult .getResponseCode () == BillingResponseCode .OK )
123- showDonateDialog (activity , skuDetailsList );
124- else
125- handleBillingErrors (billingResult .getResponseCode ());
135+ showDonateDialog (activity , productDetailsList .getProductDetailsList ());
136+ else handleBillingErrors (billingResult .getResponseCode ());
126137 });
127138 } else {
128139 new Thread () {
@@ -151,7 +162,6 @@ private void handleBillingErrors(@BillingResponseCode int code) {
151162 case BillingResponseCode .BILLING_UNAVAILABLE :
152163 case BillingResponseCode .SERVICE_UNAVAILABLE :
153164 case BillingResponseCode .SERVICE_DISCONNECTED :
154- case BillingResponseCode .SERVICE_TIMEOUT :
155165 listener .showToast (Toaster .build ().message (R .string .failedBillingConnection ));
156166 break ;
157167 case BillingResponseCode .USER_CANCELED :
@@ -170,12 +180,12 @@ private void handleBillingErrors(@BillingResponseCode int code) {
170180 }
171181 }
172182
173- public static class SkuAdapter extends RecyclerView .Adapter <SkuAdapter .ViewHolder > {
174- private final List <SkuDetails > products ;
183+ public static class ProductAdapter extends RecyclerView .Adapter <ProductAdapter .ViewHolder > {
184+ private final List <ProductDetails > products ;
175185 private final Listener listener ;
176186 private final LayoutInflater inflater ;
177187
178- SkuAdapter (Context context , List <SkuDetails > products , Listener listener ) {
188+ ProductAdapter (Context context , List <ProductDetails > products , Listener listener ) {
179189 this .products = products ;
180190 this .listener = listener ;
181191 this .inflater = LayoutInflater .from (context );
@@ -189,9 +199,9 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
189199
190200 @ Override
191201 public void onBindViewHolder (@ NonNull ViewHolder holder , int position ) {
192- final SkuDetails item = products .get (position );
202+ final ProductDetails item = products .get (position );
193203
194- switch (item .getSku ()) {
204+ switch (item .getProductId ()) {
195205 case "donation.lemonade" :
196206 holder .icon .setImageResource (R .drawable .ic_juice_64dp );
197207 break ;
@@ -212,9 +222,16 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
212222 break ;
213223 }
214224
225+ final String price ;
226+ if (item .getOneTimePurchaseOfferDetails () != null ) {
227+ price = item .getOneTimePurchaseOfferDetails ().getFormattedPrice ();
228+ } else {
229+ price = "???" ;
230+ }
231+
215232 holder .title .setText (item .getTitle ());
216233 holder .description .setText (item .getDescription ());
217- holder .buy .setText (item . getPrice () );
234+ holder .buy .setText (price );
218235 holder .buy .setOnClickListener (view -> {
219236 if (listener != null ) listener .onItemSelected (item );
220237 });
@@ -230,7 +247,7 @@ public int getItemCount() {
230247 }
231248
232249 public interface Listener {
233- void onItemSelected (@ NonNull SkuDetails product );
250+ void onItemSelected (@ NonNull ProductDetails product );
234251 }
235252
236253 class ViewHolder extends RecyclerView .ViewHolder {
0 commit comments