PurchaseUpdateListner returning Null List of purchase

131 views Asked by At

Please refer to the earlier question for a more comprehensive understanding Q1, followed by Q2.

I have identified the reason why my handlePurchase() method is not being invoked. In a previous successful purchase, the method did not get called, and even in that instance, the SharedPreferences were not accessed.

Now, the method is correctly entering the appropriate if statement where the PurchaseResponse Code is ITEM_ALREADY_OWNED. However, the purchases variable is being populated with an empty value, not a null value. This is causing an issue for the handlePurchase() method, as it expects the purchase variable to contain some information.

Here is the relevant code:

    public class HelpActivity extends AppCompatActivity {
    AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = new AcknowledgePurchaseResponseListener() {
        @Override
        public void onAcknowledgePurchaseResponse(@NonNull BillingResult billingResult) {
            Toast.makeText(HelpActivity.this, "Acknowledge", Toast.LENGTH_SHORT).show();
        }
    };
    private BillingClient billingClient;
    private final PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
        @Override
        public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null && !purchases.isEmpty()) {
                Purchase purchase = purchases.get(0);
                handlePurchase(purchase);


            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
                // Handle an error caused by a user cancelling the purchase flow.
                Toast.makeText(HelpActivity.this, "Purchase Canceled", Toast.LENGTH_SHORT).show();
                //Note!!!! only this toast message is being shown in this entre process
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
                Toast.makeText(HelpActivity.this, "You already own the item, Please restore the purchase ", Toast.LENGTH_SHORT).show();

            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.BILLING_UNAVAILABLE) {

                Toast.makeText(HelpActivity.this, "BILLING_UNAVAILABLE", Toast.LENGTH_SHORT).show();
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ERROR) {

                Toast.makeText(HelpActivity.this, "ERROR", Toast.LENGTH_SHORT).show();
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.DEVELOPER_ERROR) {

                Toast.makeText(HelpActivity.this, "DEVELOPER_ERROR", Toast.LENGTH_SHORT).show();
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_NOT_OWNED) {

                Toast.makeText(HelpActivity.this, "ITEM_NOT_OWNED", Toast.LENGTH_SHORT).show();
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_UNAVAILABLE) {

                Toast.makeText(HelpActivity.this, "ITEM_UNAVAILABLE", Toast.LENGTH_SHORT).show();
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED) {

                Toast.makeText(HelpActivity.this, "FEATURE_NOT_SUPPORTED", Toast.LENGTH_SHORT).show();
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.NETWORK_ERROR) {

                Toast.makeText(HelpActivity.this, "FEATURE_NOT_SUPPORTED", Toast.LENGTH_SHORT).show();
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.SERVICE_DISCONNECTED) {

                Toast.makeText(HelpActivity.this, "SERVICE_DISCONNECTED", Toast.LENGTH_SHORT).show();
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE) {

                Toast.makeText(HelpActivity.this, "SERVICE_UNAVAILABLE", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(HelpActivity.this, " Debug:-" + billingResult.getDebugMessage(), Toast.LENGTH_SHORT).show();
            }
        }
    };
    private MaterialButton removeAdsBtn;
    private MaterialButton restorePurchaseBtn;

    private ProductDetails productDetailsFinal;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_help_avtivity);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); // Set vertical orientation
        Window window = this.getWindow();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.setStatusBarColor(this.getResources().getColor(R.color.black));
        }
        setupBillingClient();
        restorePurchaseBtn = findViewById(R.id.restoreAdsBtn);
        removeAdsBtn = findViewById(R.id.removeAdsBtn);
        // Initialize BillingClient


        restorePurchaseBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                restorePurchases();
            }
        });
        removeAdsBtn.setOnClickListener(view -> {
            // Call the method to initiate the billing flow

            initiateBillingFlow();
            billingClient = null;

        });
    }

    public void setupBillingClient() {
        billingClient = BillingClient.newBuilder(this).setListener(purchasesUpdatedListener).enablePendingPurchases().build();


        establishConnection();
    }

    void establishConnection() {

        billingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(@NonNull BillingResult billingResult) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    // The BillingClient is ready. You can query purchases here.
                    QueryPurchase();
                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
                establishConnection();
            }
        });
    }

    public void QueryPurchase() {
        QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder().setProductList(ImmutableList.of(QueryProductDetailsParams.Product.newBuilder().setProductId("removeads_rickroll").setProductType(BillingClient.ProductType.INAPP).build())).build();

        billingClient.queryProductDetailsAsync(queryProductDetailsParams, (billingResult, productDetailsList) -> {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                // Check if the productDetailsList is not empty
                if (!productDetailsList.isEmpty()) {

                    for (ProductDetails productDetails : productDetailsList) {
                        productDetailsFinal = productDetails;
                    }


                } else {
                    Toast.makeText(HelpActivity.this, "(QueryPurchase) No Product Details Available", Toast.LENGTH_SHORT).show();

                }
            }
        });
    }

    public void initiateBillingFlow() {
        if (productDetailsFinal != null) {
            ImmutableList<BillingFlowParams.ProductDetailsParams> productDetailsParamsList =
                    ImmutableList.of(
                            BillingFlowParams.ProductDetailsParams.newBuilder()
                                    .setProductDetails(productDetailsFinal)
                                    .build());
            BillingFlowParams billingFlowParams =
                    BillingFlowParams.newBuilder()
                            .setProductDetailsParamsList(productDetailsParamsList)
                            .build();

            billingClient.launchBillingFlow(HelpActivity.this, billingFlowParams);
        } else {
            Toast.makeText(HelpActivity.this, "(initiateBillingFlow) No Product Details Available", Toast.LENGTH_SHORT).show();

        }
    }


    private void handlePurchase(Purchase purchase) {
        ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();

        ConsumeResponseListener listener = (billingResult, purchaseToken) -> {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                // Handle the success of the consume operation.
            }
        };
        billingClient.consumeAsync(consumeParams, listener);

        if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
            //Verify Purchase
            if (!verifyValidSignature(purchase.getOriginalJson(), purchase.getSignature())) {
                Toast.makeText(this, "Error:- Invalid Purchase", Toast.LENGTH_SHORT).show();
                return;
            }
            if (!purchase.isAcknowledged()) {
                AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();
                billingClient.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
                // Grant the user access to remove ads
                // Save the purchase details to SharedPreferences to remember the purchase
                Toast.makeText(HelpActivity.this, "Thank you for the purchase", Toast.LENGTH_SHORT).show();
                Toast.makeText(HelpActivity.this, "Restarting the app, Please wait ...", Toast.LENGTH_SHORT).show();
                SharedPreferences preferences = getSharedPreferences("adremoveSP", MODE_PRIVATE);
                SharedPreferences.Editor editor = preferences.edit();
                editor.putBoolean("ads_removed", true);
                editor.apply();
                System.exit(0);

            }
        } else if (purchase.getPurchaseState() == Purchase.PurchaseState.UNSPECIFIED_STATE) {
            Toast.makeText(this, "UNSPECIFIED_STATE", Toast.LENGTH_SHORT).show();
        } else if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING) {
            Toast.makeText(this, "PENDING", Toast.LENGTH_SHORT).show();
        }


    }

    private boolean verifyValidSignature(String originalJson, String signature) {
        try {
            String base64Key = "<My Base64Key>";
            return Verify.verifyPurchase(base64Key, originalJson, signature);
        } catch (IOException e) {
            return false;
        }
    }

    public void restorePurchases() {
/*
        Toast.makeText(HelpActivity.this,"Entered into restorePurchase",Toast.LENGTH_SHORT).show();
*/
        if (productDetailsFinal!= null || !productDetailsFinal.getProductId().isEmpty()) {
            Toast.makeText(HelpActivity.this,"Entered into restorePurchase purchae available",Toast.LENGTH_SHORT).show();

            Toast.makeText(HelpActivity.this, "Successfully restored", Toast.LENGTH_SHORT).show();

            SharedPreferences preferences = getSharedPreferences("adremoveSP", MODE_PRIVATE);
            SharedPreferences.Editor editor = preferences.edit();
            editor.putBoolean("ads_removed", true);
            editor.apply();
            System.exit(0);
        } else {

            Toast.makeText(HelpActivity.this, "Oops, No purchase found.", Toast.LENGTH_SHORT).show();
            SharedPreferences preferences = getSharedPreferences("adremoveSP", MODE_PRIVATE);
            SharedPreferences.Editor editor = preferences.edit();
            editor.putBoolean("ads_removed", false);
            editor.apply();


        }
    }
/*    protected void onResume() {
        super.onResume();
        billingClient.queryPurchasesAsync(QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP).build(), (billingResult, list) -> {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                for (Purchase purchase : list) {
                    if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED && !purchase.isAcknowledged()) {
                        handlePurchase(purchase);
                    }
                }
            }
        });
    }*/

}

now as i have added !purchase.IsEmpty() now the app is goin in the last else statement , and there to the billingResult is null where i added

billingResult.getDebugMessage()

Please could anyone help me with this , im stuck on this from a week now

Edit :- As the List Of Purchase was returing null and this condition

billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED && purchases != null && !purchases.isEmpty()

in the previous code was not getting executed due to empty list , now i have passed just a toast message there and removed the && purchases != null && !purchases.isEmpty() , now im thinking to use a seprate restore button that restore any previous purchase , but then im confusd about how would i get the purchase list , i dont know what is right and wrong

0

There are 0 answers