Reputation: 4234
I'm trying to implement in-app billing to my application.
I'm reading the guide on developer.android.com, looking at their example application.
I started to write basic methods for check if In-App billing is supported, but when i try to call sendBillingRequest i receive the following error:
05-17 14:23:30.479: W/System.err(15332): java.lang.NullPointerException
05-17 14:23:30.489: W/System.err(15332): at resistorcalc.main.billing.BillingService.checkBilling(BillingService.java:63)
05-17 14:23:30.489: W/System.err(15332): at resistorcalc.main.SupportusActivity.onCreate(SupportusActivity.java:24)
05-17 14:23:30.499: W/System.err(15332): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-17 14:23:30.509: W/System.err(15332): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
05-17 14:23:30.509: W/System.err(15332): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
05-17 14:23:30.519: W/System.err(15332): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
05-17 14:23:30.529: W/System.err(15332): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
05-17 14:23:30.539: W/System.err(15332): at android.os.Handler.dispatchMessage(Handler.java:99)
05-17 14:23:30.539: W/System.err(15332): at android.os.Looper.loop(Looper.java:130)
05-17 14:23:30.549: W/System.err(15332): at android.app.ActivityThread.main(ActivityThread.java:3687)
05-17 14:23:30.549: W/System.err(15332): at java.lang.reflect.Method.invokeNative(Native Method)
05-17 14:23:30.549: W/System.err(15332): at java.lang.reflect.Method.invoke(Method.java:507)
05-17 14:23:30.549: W/System.err(15332): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
05-17 14:23:30.559: W/System.err(15332): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
05-17 14:23:30.559: W/System.err(15332): at dalvik.system.NativeStart.main(Native Method)
The billingService Class is:
package resistorcalc.main.billing;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.android.vending.billing.IMarketBillingService;
public class BillingService extends Service implements ServiceConnection {
private static final String TAG = "BillingService";
private IMarketBillingService mService;
public BillingService(){
super();
}
@Override
public void onCreate() {
super.onCreate();
try {
Log.i(TAG, "Service starting with onCreate");
boolean bindResult = bindService(new Intent("com.android.vending.billing.MarketBillingService.BIND"), this, Context.BIND_AUTO_CREATE);
if(bindResult){
Log.i(TAG,"Market Billing Service Successfully Bound");
} else {
Log.e(TAG,"Market Billing Service could not be bound.");
}
} catch (SecurityException e){
Log.e(TAG,"Market Billing Service could not be bound. SecurityException: "+e);
}
}
public void setContext(Context context) {
attachBaseContext(context);
}
/**
* The Android system calls this when we are connected to the MarketBillingService.
*/
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "MarketBillingService connected.");
mService = IMarketBillingService.Stub.asInterface(service);
}
protected Bundle makeRequestBundle(String method) {
Bundle request = new Bundle();
request.putString(BillingConst.BILLING_REQUEST_METHOD, method);
request.putInt(BillingConst.BILLING_REQUEST_API_VERSION, 1);
request.putString(BillingConst.BILLING_PACKAGE_NAME, getPackageName());
return request;
}
public boolean checkBilling(){
try {
Bundle request = makeRequestBundle("CHECK_BILLING_SUPPORTED");
Bundle response = mService.sendBillingRequest(request);
int code = response.getInt("RESPONSE_CODE");
if(code==0){
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
System.err.print(e.getMessage());
return false;
}
}
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
The exception occur on that line:
Bundle response = mService.sendBillingRequest(request);
This happens because the mService variable is null. The mService variable is initialized on that method:
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "MarketBillingService connected.");
mService = IMarketBillingService.Stub.asInterface(service);
}
(as written in the that guide: http://developer.android.com/guide/market/billing/billing_integrate.html#billing-service) The problem is that onServiceConnected is never called.
The activity that launch the service:
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.supportus);
mBillingService = new BillingService();
mBillingService.setContext(this);
Intent intent = new Intent();
intent.setClass(this, BillingService.class);
startService(intent);
if(mBillingService.checkBilling()){
Toast.makeText(this, "TRUE", Toast.LENGTH_SHORT);
} else {
Toast.makeText(this, "FALSE", Toast.LENGTH_SHORT);
}
}
I cannot understand what is the problem. Why the onCreate and onServiceConnected method aren't called? Looking at the service lifceycle the BillingService onCreate method should be called with a startService. Where did I wrong
Upvotes: 3
Views: 2402
Reputation: 4234
FInally i found the solution on that problem. And it was my fault.
The error was in the manifest, in fact i declared in the service as
<service android:name=".BillingService" />
But the BillingService class was in a subpackage (resistorcalc.main.billing). Then i replaced the line with:
<service android:name=".billing.BillingService" />
And the service started to work.
Upvotes: 1
Reputation: 40347
onServiceConnected() is not being called before you try to use mService. That is because your activity's onServiceConnected() cannot be called until its onCreate() returns, which it has not yet done.
Basically you need to make your call to checkBilling() later, after the service has connected. You might do it in response to the service connection, or you might do it later when the user actually tries to do something.
Upvotes: 1