21

My app uses In App Billing and it works fine on my phone (Android 2.3.6). But when I run it on the emulator (Android 4.4.2) it keeps crashing when creating the helper for performing in app purchases. It throws a NullPointerException:

mHelper = new IabHelper(MainActivity.this, base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
    public void onIabSetupFinished(IabResult result) {
        if (!result.isSuccess()) {
            Log.d("x", "In-app Billing setup failed: " + result);
        } 
        else {             
            Log.d("x", "In-app Billing is set up OK");
        }                             
    }
});

This answer says I should put the code above in a try-block and put the catch in the answer below it. I get an error when doing that and the recommended solution is putting that in a try-catch block too. Eventhough I did that, it still crashes.

Can anybody tell me how to do this? I'm completely stuck.

Stack trace:

12-24 10:59:51.908: E/AndroidRuntime(2273): FATAL EXCEPTION: main
12-24 10:59:51.908: E/AndroidRuntime(2273): Process: com.sandradiependaal.mediatie, PID: 2273
12-24 10:59:51.908: E/AndroidRuntime(2273): java.lang.NullPointerException
12-24 10:59:51.908: E/AndroidRuntime(2273):     at com.sandradiependaal.meditatie.util.IabHelper.startSetup(IabHelper.java:267)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at com.sandradiependaal.meditatie.MainActivity$4.onItemClick(MainActivity.java:142)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at android.widget.AdapterView.performItemClick(AdapterView.java:299)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at android.widget.AbsListView.performItemClick(AbsListView.java:1113)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:2904)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at android.widget.AbsListView$3.run(AbsListView.java:3638)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at android.os.Handler.handleCallback(Handler.java:733)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at android.os.Handler.dispatchMessage(Handler.java:95)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at android.os.Looper.loop(Looper.java:136)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at android.app.ActivityThread.main(ActivityThread.java:5017)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at java.lang.reflect.Method.invokeNative(Native Method)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at java.lang.reflect.Method.invoke(Method.java:515)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
12-24 10:59:51.908: E/AndroidRuntime(2273):     at dalvik.system.NativeStart.main(Native Method)

IabHelper.java:

 Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
 serviceIntent.setPackage("com.android.vending");
 if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {
     // service available to handle that Intent
     mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
 }
Community
  • 1
  • 1
yoeriboven
  • 3,541
  • 3
  • 25
  • 40

3 Answers3

51

It's because the list returned is not just empty but it's actually null. You can add a simple check if the list is null. Why the implementation doesn't return empty list instead of null is beyond my comprehension but it's just how it's built.

Change to this:

List<ResolveInfo> queryIntentServices = mContext.getPackageManager().queryIntentServices(serviceIntent, 0);
if (queryIntentServices != null && !queryIntentServices.isEmpty()) {
        // service available to handle that Intent
        mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
}

This at least did the trick for me with the emulator. This is not needed in real device if implemented correctly.

frogatto
  • 28,539
  • 11
  • 83
  • 129
user2832636
  • 758
  • 4
  • 8
  • If you look at [the documentation for queryIntentServices()](http://developer.android.com/reference/android/content/pm/PackageManager.html#queryIntentServices(android.content.Intent, int)), it is supposed to return an empty list. I guess it doesn't follow the contract. – Tad Oct 16 '14 at 12:28
  • 3
    a great answer was posted on http://stackoverflow.com/questions/20626870/iab-startsetup-nullpointerexception – cjayem13 Nov 03 '14 at 04:59
  • 1
    Although the code worked on my test phone, on checking google analytics, i got 539 crashes for 'NullPointerException (@IabHelper:startSetup:266) {main}'. No wonder so few people have been able to run my game app. I had just downloaded the game services folder for fresh files too, surprising they still haven't fixed this bug. – Androidcoder Feb 18 '16 at 17:13
8

This seems to be an old thread. Hope this answer helps someone who faces the issue later. BI am facing the same issue at this moment.

IAB helper generates NPE in startSetup() only on emulator. But this happens only on AVDs created with Android x.x.x as target.

Try creating your AVD with Google API as target. IAB helper does not crash there but you still cannot test the actual billing features.

frogatto
  • 28,539
  • 11
  • 83
  • 129
user1837618
  • 103
  • 1
  • 4
4

To test In-app Billing in an application you must install the application on an Android-powered device. You cannot use the Android emulator to test In-app Billing.

http://developer.android.com/google/play/billing/billing_testing.html

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62