I am trying to implement the in-App purchase code in my android app. The idea is that when I press the button "botonComprar", it activates the purchase flow, but when I press it I get this error:
NullPointerException: Attempt to invoke virtual method 'void com.android.billingclient.api.BillingClient.startConnection(com.android.billingclient.api.BillingClientStateListener)' on a null object reference
This is my code, the error it's supposed to be on "establishConnection()" but I do not understand what is happening. Thank you in advanced.
BillingClient billingClient;
Prefs prefs;
ProductDetails productDetails;
//Button botonComprar = (Button) findViewById(R.id.botonEmpezar);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_no_adds);
PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
// To be implemented in a later section.
}
};
BillingClient billingClient = BillingClient.newBuilder(this)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases()
.build();
establishConnection();
}
void establishConnection() {
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
showProducts();
}
}
@Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
establishConnection();
}
});
}
void showProducts() {
QueryProductDetailsParams queryProductDetailsParams =
QueryProductDetailsParams.newBuilder()
.setProductList(
ImmutableList.of(
QueryProductDetailsParams.Product.newBuilder()
.setProductId("noanunciosymasextras")
.setProductType(BillingClient.ProductType.SUBS)
.build()))
.build();
billingClient.queryProductDetailsAsync(
queryProductDetailsParams,
new ProductDetailsResponseListener() {
public void onProductDetailsResponse(BillingResult billingResult,
List<ProductDetails> productDetailsList) {
// check billingResult
// process returned productDetailsList
}
}
);
}
public void botonComprar (View view){
BillingFlowParams billingFlowParams =
BillingFlowParams.newBuilder()
.setProductDetailsParamsList(
ImmutableList.of(
BillingFlowParams.ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.build()
)
)
.build();
billingClient.launchBillingFlow(this, billingFlowParams);
}
void handlePurchase(Purchase purchases) {
if(!purchases.isAcknowledged()){
billingClient.acknowledgePurchase(AcknowledgePurchaseParams
.newBuilder()
.setPurchaseToken(purchases.getPurchaseToken())
.build(), billingResult -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
//Setting setIsRemoveAd to true
// true - No ads
// false - showing ads.
prefs.setIsRemoveAd(true);
// goBack();
}
});
}
}
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);
}
}
}
}
);
}
Did not know how to solve it, and still don't. So I decided to start over and following this tutorial. I works perfectly.