Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Billing 4.0.0 - No purchase result querySkuDetailsAsync()

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();

                }
            });
        }
    });
}

'''

like image 642
Maasaivatar Avatar asked Jun 01 '21 05:06

Maasaivatar


People also ask

What is COM Android vending billing?

What is uses-permission:'com. android. vending. BILLING' ? It is the permission required for integration of Billing in your android application.

What does Google play in app billing API version is less than 3 mean?

Usually the BILLING_UNAVAILABLE error means that your Android device is running an unsupported version of Android or Play services. Other things to check when you get this error: Are you logged in to the correct Google Account on the device/emulator? Try logging out and logging back in.


2 Answers

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.

like image 165
Maasaivatar Avatar answered Oct 04 '22 02:10

Maasaivatar


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
        }));
like image 40
hej2010 Avatar answered Oct 04 '22 04:10

hej2010