Reputation: 449
I'm having some serious problems trying to implement in-app purchases on my otherwise completed app. I have a class, BaseActivity, that all my other classes extend. This is where my toolbars, nav drawers, and IabHelper are set up.
BaseActivity.java:
public abstract class BaseActivity extends AppCompatActivity implements IabBroadcastReceiver.IabBroadcastListener{
public boolean m30paid = false;
public boolean m31paid = false;
public boolean m32paid = false;
public boolean m37paid = false;
static final String ITEM_SKU = "android.test.purchased";
IabHelper mHelper;
IabBroadcastReceiver mBroadcastReceiver;
private final String LOG = BaseActivity.class.getSimpleName();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String base64EncodedPublicKey = "********KEY HERE*********";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
Log.d(LOG, "Problem setting up in app billing: " + result);
}
else Log.d(LOG, "set up correctly!");
if (mHelper == null) return;
}
});
mBroadcastReceiver = new IabBroadcastReceiver(this);
IntentFilter broadcastFilter = new IntentFilter(IabBroadcastReceiver.ACTION);
registerReceiver(mBroadcastReceiver, broadcastFilter);
//IAB fully set up, query inventory
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data)
{
if (!mHelper.handleActivityResult(requestCode,
resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onDestroy() {
super.onDestroy();
// very important:
if (mBroadcastReceiver != null) {
unregisterReceiver(mBroadcastReceiver);
}
// very important:
Log.d(LOG, "Destroying helper.");
if (mHelper != null) {
mHelper.disposeWhenFinished();
mHelper = null;
}
}
@Override
public void receivedBroadcast() {
}
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
Log.d(LOG, "Query inventory finished.");
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
// Is it a failure?
if (result.isFailure()) {
complain("Failed to query inventory: " + result);
return;
}
Log.d(LOG, "Query inventory was successful.");
/*
* Check for items we own. Notice that for each purchase, we check
* the developer payload to see if it's correct! See
* verifyDeveloperPayload().
*/
}};
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(LOG, "Purchase finished: " + result + ", purchase: " + purchase);
// if we were disposed of in the meantime, quit.
if (mHelper == null) return;
if (result.isFailure()) {
complain("Error purchasing: " + result);
return;
} else if (purchase.getSku().equalsIgnoreCase("workout_30")) {
m30paid = true;
}
Log.d(LOG, "Purchase successful.");
}
};
void alert(String message) {
AlertDialog.Builder bld = new AlertDialog.Builder(this);
bld.setMessage(message);
bld.setNeutralButton("OK", null);
Log.d(LOG, "Showing alert dialog: " + message);
bld.create().show();
}
public void complain(String message) {
Log.e(LOG, "**** TrivialDrive Error: "+ message);
alert("Error: " + message);
}
From there, I try to set launchPurchaseFlow on button click in another class.
Purchases.java:
public class purchases extends BaseActivity {
IabHelper mHelper;
static final String ITEM_SKU = "android.test.purchased";
IabBroadcastReceiver mBroadcastReceiver;
Context mContext;
Activity mActivity = this;
static final int RC_REQUEST = 10001;
private Button btn30;
static final String SKU_W30 = "workout_30";
String payload = "";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.purchases);
mToolBar = activateToolbar();
setUpNavigationDrawer();
getSupportActionBar().setTitle("Purchases");
btn30 = (Button) findViewById(R.id.btn30);
Button btn31 = (Button) findViewById(R.id.btn31);
Button btn32 = (Button) findViewById(R.id.btn32);
Button btn37 = (Button) findViewById(R.id.btn37);
btn30.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mHelper.launchPurchaseFlow(purchases.this, SKU_W30, RC_REQUEST, mPurchaseFinishedListener, payload);
} catch (IabHelper.IabAsyncInProgressException e) {
complain("Error");
}
}
});
}
}
The error I'm getting when I click the button is:
FATAL EXCEPTION: main
Process: com.bestworkouts.sheikoworkout, PID: 4118
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.bestworkouts.sheikoworkout.util.IabHelper.launchPurchaseFlow(android.app.Activity, java.lang.String, int, com.bestworkouts.sheikoworkout.util.IabHelper$OnIabPurchaseFinishedListener, java.lang.String)' on a null object reference
at com.bestworkouts.sheikoworkout.purchases$1.onClick(purchases.java:41)
at android.view.View.performClick(View.java:5697)
at android.widget.TextView.performClick(TextView.java:10814)
at android.view.View$PerformClick.run(View.java:22526)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Basically what I want it to do is in the onIabPurchaseFinished, change a boolean value to true. I have an if statement on my expLV so if the boolean is false it says you need to purchase this, if it's true, it gives access. This part is working good so far, but I can't seem to get past this error to see if it properly changes the boolean value and unlocks the data.
I'm not sure what I'm missing, and I've been messing it and dealing with multiple errors for 2 days now.. any help greatly appreciated!
Upvotes: 1
Views: 506
Reputation: 10309
Subclass variable mHelper
isn't initialised. Try removing IabHelper mHelper;
from purchase
class which extends BaseActivity
where mHelper
is initialised.
Declaring mHelper
in subclass will hide superclass mHelper
variable.
Upvotes: 1