I am trying to get my first Android service to work. I have this service that basically generates random number. I want it to update the text on the Android’s view using this service. I am dispatching an AsyncTask and it successfuly updates the text but for some reason I get this exception in Log. Here’s the exception:
03-20 09:58:37.242: ERROR/AndroidRuntime(594): FATAL EXCEPTION: AsyncTask #1
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:200)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
at java.lang.Thread.run(Thread.java:1096)
Caused by: java.lang.NullPointerException
at com.denniss.Main$2.doInBackground(Main.java:51)
at com.denniss.Main$2.doInBackground(Main.java:47)
at android.os.AsyncTask$2.call(AsyncTask.java:185)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
... 4 more
03-20 09:58:37.272: WARN/ActivityManager(58): Force finishing activity com.denniss/.Main
03-20 09:58:39.051: ERROR/ActivityThread(594): Activity com.denniss.Main has leaked ServiceConnection com.denniss.Main$1@44e87110 that was originally bound here
android.app.ServiceConnectionLeaked: Activity com.denniss.Main has leaked ServiceConnection com.denniss.Main$1@44e87110 that was originally bound here
at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:1121)
at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:1016)
at android.app.ContextImpl.bindService(ContextImpl.java:863)
at android.content.ContextWrapper.bindService(ContextWrapper.java:347)
at com.denniss.Main.onStart(Main.java:73)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129)
at android.app.Activity.performStart(Activity.java:3781)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2636)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
at android.app.ActivityThread.access$2300(ActivityThread.java:125)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
Main.java
public class Main extends Activity {
private IRandomNumberService randomNumberService;
private int currentNumber = -1;
private boolean connected = false;
private TextView randomNumberText;
private ServiceConnection serviceConnection;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("******** onCreate");
setContentView(R.layout.main);
randomNumberText = (TextView) findViewById(R.id.random_number);
serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder service) {
System.out.println("onService Connected Called");
currentNumber = 1;
randomNumberService = IRandomNumberService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName componentName) {
System.out.println("Service Disconnected");
randomNumberService = null;
}
};
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
try {
currentNumber = randomNumberService.getRandomNumber();
System.out.println("Current Number: " + currentNumber);
} catch (RemoteException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
System.out.println("Setting Current Number: " + currentNumber);
randomNumberText.setText(new Integer(currentNumber).toString());
}
}.execute();
}
@Override
protected void onStart() {
super.onStart();
System.out.println("******** on Start");
if (!connected) {
connected = bindService(new Intent(Main.this, RandomNumberService.class), serviceConnection, Context.BIND_AUTO_CREATE);
Log.i("Service Status: ", "Connected? " + connected);
}
if (!connected) {
throw new RuntimeException("Cannot connect to service");
}
}
}
It looks like randomNumberService is null and when you call randomNumberService.getRandomNumber(); it throws the null pointer exception.
You should wait until your service is connected before you execute your Async task since it is dependent on your service connecting. Likely the service that fetches randomNumberService isn’t completing fast enough for your Async task to have a valid value for randomNumberService