4

I am trying to implement in-app purchases in my Android app.

So basically, the user is supposed to click the 'Remove Ads' menu button which sets up the billingClient and eventually processes the in-app purchase.

Here's my code:

public class PlayersActivity extends AppCompatActivity {

    SharedPreferences prefs;

    boolean adFree;

    BillingClient billingClient;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view);

        prefs = this.getSharedPreferences("package_name", Context.MODE_PRIVATE);
        adFree = prefs.getBoolean("adFree", false);

        if (!adFree) {
            MobileAds.initialize(this, new OnInitializationCompleteListener() {
                @Override
                public void onInitializationComplete(InitializationStatus initializationStatus) {

                }
            });

            AdView mAdView = findViewById(R.id.listBannerAd);
            AdRequest adRequest = new AdRequest.Builder().build();
            mAdView.loadAd(adRequest);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_history, menu);
        
        MenuItem item6 = menu.findItem(R.id.action_remove_ads);
        if (!adFree) {
            item6.setVisible(true);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_remove_ads:
                setUpBillingClient();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

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

            ConsumeResponseListener listener = (billingResult, purchaseToken) -> {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    prefs.edit().putBoolean("adFree", true).apply();
                }
            };

            billingClient.consumeAsync(consumeParams, listener);
        }
    }

    private final PurchasesUpdatedListener purchasesUpdatedListener = (billingResult, purchases) -> {
        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
                && purchases != null) {
            for (Purchase purchase : purchases) {
                handlePurchase(purchase);
            }
        }
    };

    private void setUpBillingClient() {
        Log.v("InAppPurchase", "billingclientsetup");
        billingClient = BillingClient.newBuilder(this)
                .setListener(purchasesUpdatedListener)
                .enablePendingPurchases()
                .build();
        startConnection();
    }

    private void startConnection() {
        Log.v("InAppPurchase", "startconnection");
        billingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(BillingResult billingResult) {
                Log.v("InAppPurchase", "billing setup finished");
                if (billingResult.getResponseCode() ==  BillingClient.BillingResponseCode.OK) {
                    queryAvailableProducts();
                }
            }
            @Override
            public void onBillingServiceDisconnected() {
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
                Log.v("InAppPurchase", "billing disconnected");
            }
        });
    }

    private void queryAvailableProducts() {
        Log.v("InAppPurchase", "queryavailableproducts");
        List<String> skuList = new ArrayList<>();
        skuList.add("remove_ads");
        SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
        params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
        billingClient.querySkuDetailsAsync(params.build(), (billingResult, list) -> {
            Log.v("InAppPurchases", billingResult.getResponseCode() + "response");
            Log.v("InAppPurchases", list + "list");
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
                    && list != null && !list.isEmpty()) {
                Log.v("InAppPurchase", list.get(0).getDescription().toString());
                BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
                        .setSkuDetails(list.get(0))
                        .build();
                billingClient.launchBillingFlow(PlayersActivity.this, billingFlowParams);
            }
        });
    }
}


However, in the logs, I can see that an empty list is printed from the function in querySkuDetailsAsync. The response code is 0.

I have tried the solutions in other StackOverflow questions, like ensuring that the app is published to the Google Play Store and making sure that the in-app purchase is set up properly in the Play Console.

Is there anything wrong in the way I've implemented it?

Will Zap
  • 83
  • 8
  • 1
    check this: https://stackoverflow.com/questions/46782353/android-play-billing-library-onskudetailsresponse-responsecode-is-0-but-the-si – Cube Jul 20 '21 at 09:47

0 Answers0