Android Billing 4.0.0 - No purchase result querySkuDetailsAsync()
Asked Answered
D

2

7

I migrated Google Play Billing Library in Android Studio from 3.0.3 (was working fine) to 4.0.0. I've checked my Google Play Billing and all seems OK and the SKU status is ACTIVE (no red flags). I've tried my best to follow migration instructions @ https://developer.android.com/google/play/billing/integrate#establish_a_connection_to_google_play

So far, all I can muster is an OK connection to Google Play Billing, that is, after onBillingSetupFinished() method, the BillingClient.BillingResponseCode.OK responds nicely, without error messages.

My problem begins somehere with the call to querySkuDetailsAsync(): There is no response here, not even an error notification. The google website puts a lot of stress emphasis on this call so I sense this is where the fun begins.

I have provided the sample code with the problem. I have used many many fixes from Stack Overflow but now I'm really really stuck and really need this to work.

My problem code below:

'''

/*
//Using the following library in build.graddle for app module
    dependencies {
        def billing_version = "4.0.0"
        implementation "com.android.billingclient:billing:$billing_version"
}

*/

StringBuilder builder4SKUInfo;
private void get_Subscribe2_Characters() {

    Subscribe2_Characters_Button.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            //I Toggle Visibility of Views Here


            billingClient.startConnection(new BillingClientStateListener() {

                //Android Studio auto-prompts to generate onBillingSetupFinished & onBillingServiceDisconnected

                @Override
                public void onBillingSetupFinished(@NonNull BillingResult billingResultC) {
                    if (billingResultC.getResponseCode() == BillingClient.BillingResponseCode.OK) {

                        //BillingResponseCode is OK here: Works Just Fine!
                        //The problem starts below


                        String skuToSell = "MySKU_Character_001"; //In my project, the SKU is cut-pasted from Google Play Console
                        List<String> skuList = new ArrayList<> ();
                        skuList.add(skuToSell);


                        SkuDetailsParams.Builder params = SkuDetailsParams
                                .newBuilder()
                                .setSkusList(sku_Details)  //
                                .setType(BillingClient.SkuType.SUBS);

                        billingClient.querySkuDetailsAsync(params.build(),
                                new SkuDetailsResponseListener() {
                                    @Override
                                    public void onSkuDetailsResponse(@NonNull BillingResult billingResult, @NonNull List<SkuDetails> PurchaseDetailsList) {

                                        //NOTHING!  Not getting BillingResult
                                        //Problem seems to at this point

                                        if (PurchaseDetailsList.size() > 0) {

                                            //NOTHING!  Not getting size

                                            for (SkuDetails PurchaseSKU_Info : PurchaseDetailsList) {

                                                builder4SKUInfo = new StringBuilder(300);

                                                if (PurchaseSKU_Info.getSku().contains("MySKU_Character_001")) {


                                                    String getSKUInfo = (
                                                            "\nTitle [Query]: " + PurchaseSKU_Info.getTitle()
                                                                    + "\n\nDetails: " + PurchaseSKU_Info.getDescription()
                                                                    + "\n\nDuration: " + PurchaseSKU_Info.getSubscriptionPeriod()
                                                                    + "\n\nPrice" + PurchaseSKU_Info.getPrice()
                                                                    + "\n\nAvoid Problems:\nUpdated Subscription Settings on Google Play"
                                                                    + "\n\nIMPORTANT: NOT Transferable"
                                                                    + "\n\n      For this device only\n");
                                                    //+ "\nOther SKUs: " + SKU_Info.getSku()
                                                    //"001 = " + billingResultB.getResponseCode()
                                                    //+ "\nList Size: " + PurchaseDetailsList.size());

                                                    builder4SKUInfo.append(getSKUInfo); //The result I need to use elsewhere

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

                                            //No Google Play response for this

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

                                            //No Google Play response for this


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

                                            //Do something about cancels

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

                                            //No Google Play response for this

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

                                            //No Google Play response for this

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

                                            //No Google Play response for this

                                        } else {

                                            //Following Toast does not show

                                            String SomethingWrong = "Somethings is Wrong" +
                                                    "\nUpdate Your Google Play Billing Info" +
                                                    "\nCheck Internet Connection";

                                            Toast.makeText(KH.this, SomethingWrong, Toast.LENGTH_LONG).show();

                                        }
                                    }
                                });
                    }
                }


                @Override
                public void onBillingServiceDisconnected() {

                    //Following Toast does not show

                    String BillingServiceDisconnected = "Billing Service Disconnected" +
                            "\nUpdate Your Google Play Billing Info" +
                            "\nCheck Internet Connection";

                    Toast.makeText(KH.this, BillingServiceDisconnected, Toast.LENGTH_LONG).show();

                }
            });
        }
    });
}

'''

Dermot answered 1/6, 2021 at 5:15 Comment(2)
sku_Details it's not declared anywhere ... ?????Lissa
@Lissa . . . "sku_Details" is delcared as a MutableLiveData HashMap in the GitHub example by Google. You can then transport the Map and "Do Stuff" like add SKUs, detect purchase state, etc. The Map is in a separate class from Main. Here's the GitHub link to the Map architectureDermot
D
7

So I braved to ask the folks at Google on the issue tracker page and they appropriately and promptly responded, "We now post the results to the background thread instead of the UIThread . . ."

Right away, I knew I had the wrong approach. If the result is delivered to background thread, I had to ditch the 3.x billing approach and start from scratch.

I reached back again to Google for an example and they sent me their GitHub @ https://github.com/android/play-billing-samples/tree/main/TrivialDriveJava

The example is akin to an "Intent" but with a lot more code declaration than function selection: has several classes, methods and files to work through. So to fix billing 4.x, the easiest path was to just rip the example into my app, whittled down the errors, gray out methods I don't need and finally overlay my views, refactor classes (fix errors again) and create new user workflows.

Dermot answered 8/6, 2021 at 6:9 Comment(1)
Thanks for your answer. On my side I open a custom dialog (myDialog.show) in the onSkuDetailsResponse callback. It worked perfectly with 3.0.3, but not anymore with the 4.0.0. So I guess it's because my dialog is now "showed" in the background thread instead of UI one previously. I will stay on 3.0.3Myalgia
N
3

Following @Maasaivatar's answer, it works after running the SkuDetailsResponseListener on the main thread:

billingClient.querySkuDetailsAsync(params.build(), (billingResult, list) -> 
    runOnUiThread(() -> {
            // same code as before
        }));
Nissa answered 11/8, 2021 at 12:26 Comment(2)
This works. But is there any issue by using this approach? Anyone please explain?Cynarra
Thanks! I also did that for the onQueryPurchasesResponse listener of queryPurchasesAsync.Naught

© 2022 - 2024 — McMap. All rights reserved.