Edit: Please see my answer below for my solution.
I'm receiving a NullPointerException error when trying to check owned items using getPurchases()
and I'm not sure why as I've followed the documentation. I'm finding that the documentation can be misleading at times, so here I am.
I've set up In-app billing such that it initializes okay and I get a success message. After it is initialized, I want to check if the user has previously purchased item(s) and display a button based on the result. Here is my code so far and below is my LogCat. The error appears at the beginning of the try/catch.
public class MainActivity extends Activity
{
IabHelper mHelper;
IInAppBillingService mService;
private Button buyButton;
AdView adView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adView = (AdView)this.findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
buyButton = (Button)findViewById(R.id.buyButton);
String base64EncodedPublicKey = "public_key";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener()
{
@Override
public void onIabSetupFinished(IabResult result)
{
if(!result.isSuccess())
{
Log.d("TEST", "In-app Billing setup failed: " + result);
}
else
{
Log.d("TEST", "In-app Billing is set up OK"); //This passes!
}
}
});
bindService(new Intent("com.android.vending.billing.InAppBillingService.BIND"), mServiceConn, Context.BIND_AUTO_CREATE);
try
{
Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null); //This is line 66 referenced in LogCat error
if(ownedItems.getInt("RESPONSE_CODE") == 0)
{
ArrayList ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE");
String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
for(int i=0; i<purchaseDataList.size(); ++i)
{
String purchaseData = (String) purchaseDataList.get(i);
String signature = (String) signatureList.get(i);
String sku = (String) ownedSkus.get(i);
Log.d("TEST", "Purchased: "+i+ " -> "+sku);
}
}
else
{
Log.d("TEST", "Not Items Owned!");
}
}
catch(RemoteException e)
{
//TODO: Error, unable to get owned items
e.printStackTrace();
Log.d("TEST", "owned items check failed: "+e);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
ServiceConnection mServiceConn = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
mService = IInAppBillingService.Stub.asInterface(service);
Log.d("TEST", "mService ready to go!"); //This displays if try/catch above is commented out. Is it not waiting for mService to be initialized before running try/catch?
}
@Override
public void onServiceDisconnected(ComponentName name)
{
mService = null;
}
};
@Override
public void onDestroy()
{
super.onDestroy();
if(mServiceConn != null)
{
unbindService(mServiceConn);
}
}
}
And the Logcat errors
01-04 22:39:35.052: E/AndroidRuntime(32375): FATAL EXCEPTION: main
01-04 22:39:35.052: E/AndroidRuntime(32375): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.iab/com.test.iab.MainActivity}: java.lang.NullPointerException
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread.access$600(ActivityThread.java:141)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.os.Handler.dispatchMessage(Handler.java:99)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.os.Looper.loop(Looper.java:137)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread.main(ActivityThread.java:5041)
01-04 22:39:35.052: E/AndroidRuntime(32375): at java.lang.reflect.Method.invokeNative(Native Method)
01-04 22:39:35.052: E/AndroidRuntime(32375): at java.lang.reflect.Method.invoke(Method.java:511)
01-04 22:39:35.052: E/AndroidRuntime(32375): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
01-04 22:39:35.052: E/AndroidRuntime(32375): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
01-04 22:39:35.052: E/AndroidRuntime(32375): at dalvik.system.NativeStart.main(Native Method)
01-04 22:39:35.052: E/AndroidRuntime(32375): Caused by: java.lang.NullPointerException
01-04 22:39:35.052: E/AndroidRuntime(32375): at com.test.iab.MainActivity.onCreate(MainActivity.java:66)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.Activity.performCreate(Activity.java:5104)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
01-04 22:39:35.052: E/AndroidRuntime(32375): ... 11 more
01-04 22:39:35.083: E/GooglePlayServicesUtil(32375): The Google Play services resources were not found. Check your project configuration to ensure that the resources are included.
My guess is that I'm not initializing mService correctly? But I don't understand if I'm not because I believe I did it exactly as the documentation outlines. Thanks for guidance.