Android 点击应用内购买时应用崩溃

Android App crashing on click of in-app purchase

我参考了 Android 文档来实施应用内购买以移除广告。 https://developer.android.com/google/play/billing/integrate

这是我的代码:

public static final String AD_REMOVAL_SKU = "remove_ads";

private void LoadBillingInfo() {
        PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
            @Override
            public void onPurchasesUpdated(@NonNull BillingResult billingResult, List<Purchase> purchases) {
                // To be implemented in a later section.
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) {
                    for (Purchase purchase : purchases) {
                        if (purchase.getSku().equals(AD_REMOVAL_SKU)) {
                            //Acknowledge the payment
                            AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = new AcknowledgePurchaseResponseListener() {
                                @Override
                                public void onAcknowledgePurchaseResponse(@NonNull BillingResult billingResult) {
                                    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                                        areAdsRemoved = true;
                                        sharedPreferences.edit().putBoolean(AD_REMOVAL_SKU, areAdsRemoved).apply();
                                        DestroyBannerAd();
                                        Log.i("LOG", "Congrats! You are Ad free!");
                                        Toast.makeText(MainActivity.this, "Congrats! You are Ad free!", Toast.LENGTH_SHORT).show();
                                    }
                                }
                            };
                            if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
                                if (!purchase.isAcknowledged()) {
                                    AcknowledgePurchaseParams acknowledgePurchaseParams =
                                            AcknowledgePurchaseParams.newBuilder()
                                                    .setPurchaseToken(purchase.getPurchaseToken())
                                                    .build();
                                    billingClient.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
                                }
                            }
                        }
                    }
                }
            }
        };

        billingClient = BillingClient.newBuilder(this)
                .setListener(purchasesUpdatedListener)
                .enablePendingPurchases()
                .build();

        StartBillingConnection();
    }

private void StartBillingConnection() {
        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.
                    if (HasNetwork()) {
                        isBillingClientReady = true;
                        Toast.makeText(MainActivity.this, "onBillingSetupFinished", Toast.LENGTH_SHORT).show();
                        Log.i("LOG", "onBillingSetupFinished");
                        Log.i("LOG", "Response code: " + billingResult.getResponseCode());
                    }
                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
                isBillingClientReady = false;
                Toast.makeText(MainActivity.this, "onBillingServiceDisconnected", Toast.LENGTH_SHORT).show();
                Log.i("LOG", "onBillingServiceDisconnected");
                if (HasNetwork()) {
                    StartBillingConnection();
                }
            }
        });
    }

    private void MakePayment() {
        final SkuDetails[] skuDetail = new SkuDetails[1];
        Log.i("LOG", "1");
        List<String> skuList = new ArrayList<>();
        Log.i("LOG", "2");
        skuList.add(AD_REMOVAL_SKU);
        Log.i("LOG", "3");
        SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
        Log.i("LOG", "4");
        params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
        Log.i("LOG", "5");
        billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
            @Override
            public void onSkuDetailsResponse(@NonNull BillingResult billingResult, List<SkuDetails> skuDetailsList) {
                Log.i("LOG", "6");
                // Process the result.
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
                        && skuDetailsList != null) {
                    Log.i("LOG", "7");
                    for (Object skuDetailsObject : skuDetailsList) {
                        Log.i("LOG", "8");
                        SkuDetails skuDetails = (SkuDetails) skuDetailsObject;
                        Log.i("LOG", "9");
                        String sku = skuDetails.getSku();
                        Log.i("LOG", "10");
                        if (AD_REMOVAL_SKU.equals(sku)) {
                            Toast.makeText(MainActivity.this, "Right Inside", Toast.LENGTH_SHORT).show();
                            Log.i("LOG", "Right Inside");
                            skuDetail[0] = skuDetails;
                        }
                    }
                }
            }
        });

        Toast.makeText(this, skuDetail[0].getSku() + " " + skuDetail[0].getTitle(), Toast.LENGTH_LONG).show();
        Log.i("LOG", skuDetail[0].getSku() + " " + skuDetail[0].getTitle());

// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
        BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
                .setSkuDetails(skuDetail[0])
                .build();
        billingClient.launchBillingFlow(this, billingFlowParams);
    }

我称之为 onClick:

if (!areAdsRemoved) {
                    if (isBillingClientReady) {
                        MakePayment();
                    } else {
                        Log.i("LOG", "Sorry! You are unable to make the payment due to network connectivity issues");
                        Toast.makeText(this,
                                "Sorry! You are unable to make the payment due to network connectivity issues",
                                Toast.LENGTH_LONG).show();
                        LoadBillingInfo();
                    }
                }

但是,当我点击删除广告的按钮时,应用程序崩溃了。
所以,我把 Log 语句放在各处。我发现 Log.i("LOG", "5"); 是最后打印的 Log 语句。

当应用程序崩溃时,我收到此错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String b.a.a.a.j.a()' on a null object reference
        at b.d.b.b.a0.a.a(:17)
        at a.b.o.i.g.e()
        at a.b.o.i.g.s(:1)
        at b.d.b.b.z.h$a.onClick()
        at android.view.View.performClick(View.java:5637)
        at android.view.View$PerformClick.run(View.java:22433)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6126)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

我找不到解决这个问题的办法...
有人遇到过这个问题吗?请帮忙!

skuDetail[0] 为空。将取消引用它的代码移动到数据可用的异步回调