I created a service which sends commands to an external activity through AIDL: after this activity bind to the service, it sends a callback to the service, and so a two-way communication is established and works correctly.
Instead, the problem arises when I want to change the UI of the application according to commands received from the service. I performed a test with a simple Toast notification, but some errors occur…
The onExecute method of the external activity is called when a new command is received through AIDL. If I remove the Toast notification, everything is working properly, but I need to change the UI according to commands received from the service.
protected void onExecute(Bundle params) {
Log.i(LOG_TAG, "onExecute(): " + params);
if (params.containsKey("command01")) {
Log.i(LOG_TAG, "onExecute(): " + params.getString("command01"));
Toast
.makeText(this, "Command 1...", Toast.LENGTH_SHORT)
.show();
}
else if (params.containsKey("command02")) {
Log.i(LOG_TAG, "onExecute(): " + params.getString("command02"));
Toast
.makeText(this, "Command 2...", Toast.LENGTH_SHORT)
.show();
}
else {
Log.w(LOG_TAG, "onExecute() - unknown command: " + params);
}
}
Below is shown the log recorded by LogCat during the error:
05-07 12:45:30.676: W/dalvikvm(363): JNI WARNING: JNI method called with exception raised
05-07 12:45:30.676: W/dalvikvm(363): in Ldalvik/system/NativeStart;.run ()V (CallStaticVoidMethodV)
05-07 12:45:30.676: W/dalvikvm(363): Pending exception is:
05-07 12:45:30.676: I/dalvikvm(363): Ljava/lang/RuntimeException;: Can't create handler inside thread that has not called Looper.prepare()
05-07 12:45:30.706: I/dalvikvm(363): at android.os.Handler.<init>(Handler.java:121)
05-07 12:45:30.706: I/dalvikvm(363): at android.widget.Toast.<init>(Toast.java:68)
05-07 12:45:30.706: I/dalvikvm(363): at android.widget.Toast.makeText(Toast.java:231)
05-07 12:45:30.706: I/dalvikvm(363): at org.example.android.applicationdemo.ApplicationDemoActivity.onExecute(ApplicationDemoActivity.java:130)
05-07 12:45:30.706: I/dalvikvm(363): at org.example.android.applicationdemo.ApplicationDemoActivity$2.execute(ApplicationDemoActivity.java:100)
05-07 12:45:30.706: I/dalvikvm(363): at org.example.android.servicedemo.IServiceCallback$Stub.onTransact(IServiceCallback.java:55)
05-07 12:45:30.706: I/dalvikvm(363): at android.os.Binder.execTransact(Binder.java:320)
05-07 12:45:30.706: I/dalvikvm(363): at dalvik.system.NativeStart.run(Native Method)
05-07 12:45:30.706: I/dalvikvm(363): "Binder Thread #2" prio=5 tid=8 NATIVE
05-07 12:45:30.706: I/dalvikvm(363): | group="main" sCount=0 dsCount=0 obj=0x405116f0 self=0x1f1590
05-07 12:45:30.706: I/dalvikvm(363): | sysTid=370 nice=0 sched=0/0 cgrp=default handle=2037072
05-07 12:45:30.714: I/dalvikvm(363): | schedstat=( 18375041 37002039 19 )
05-07 12:45:30.714: I/dalvikvm(363): at dalvik.system.NativeStart.run(Native Method)
05-07 12:45:30.714: E/dalvikvm(363): VM aborting
I think you create your Handler inside a method executed on a non-UI thread.
Make your Handler as a global variable.