I'm trying to create a simple multiplayer game. There's a WorkerService which is supposed to handle all network communication and all interaction between this service and my Activities is done with AIDL. I think this is a standard approach - to enable two way interaction I use also an IWorkerCallback interface (also AIDL).
The problem is that callbacks have to change things in UI which may be done only in UI thread. I've created a Handler (in UI thread) and believed that this is an obvious solution. But, surprisingly, it's not working.
My LoungeActivity calls startServer() method of IWorker interface. Corresponding method of my WorkerService does some job and makes a callback - this works fine. Then WorkerService spawns a new thread and callback from this thread results in a bad Exception being thrown:
Can't create handler inside thread that has not called Looper.prepare()
Here's some code to make it clear:
startServer() implementation:
private void startServerImpl(String name, float latStart, float latEnd,
float lonStart, float lonEnd)
{
// some instructions here
// this works fine:
callback.notifySocketCreated();
// my naughty thread:
new ServerThread().start();
// some instructions here
}
ServerThread code:
private class ServerThread extends Thread {
@Override
public void run()
{
//some instructions here
// this call will cause an error
callback.notifyGameRegistered();
}
}
Every method from callback looks like that:
public void notifyGameRegistered() throws RemoteException
{
handler.dispatchMessage(handler.obtainMessage(CALLBACK_GAME_REGISTERED));
}
In Handler's handleMessage() method I'm doing a simple switch(msg.what) and in every case there's a simple UI modification (showing a Toast, changing Text, etc.).
I have no idea why is this Exception thrown.. I've managed to fix it by packing code into a Runnable and calling runOnUiThread() but it still makes me curious - shouldn't a Handler always run in thread that created it? Or maybe I'm doing something wrong?