I have a Service
that starts a new Thread
that handles network activity. I have my Activity
, Service
, and Thread
all in separate files. I am trying to set up communication between them using a Messenger
created by passing the Messenger
an extended Handler
. I've figured out how to make the Service
and Activity
talk to each other fine, but I can't figure out how to give my Service
a target to allow it to send messages to the separate Thread
.
This is what I am trying now, but the message from Service
to Thread
is never sent...
Service
public class TCPSocketService extends Service {
//Messengers
private Messenger clientMessenger;
private Messenger socketMessenger;
//Message Incoming Handlers
private Messenger clientIncomingHandler;
private Messenger socketIncomingHandler;
@Override
public void onCreate() {
Log.d("Service", "TCPSocketService created");
isConnected = false;
clientIncomingHandler = new Messenger(new ClientToServiceIncomingHandler());
}
@Override
public IBinder onBind(Intent intent) {
return clientIncomingHandler.getBinder();
}
/*
* Event Handlers for Messages received from Client
*/
/**
* Called when {@link Service} receives the HELLO message from Client
* Registers {@link Messenger} that represents the Client's Incoming Message Handler
*
* @param msg {@link Message} object containing {@link Messenger} for responses
*/
private void onHello(Message msg) {
registerClient(msg.replyTo);
}
/**
* Called when {@link Service} receives the START_THREAD message from Client
* Initializes and starts a new {@link Thread} with {@link SocketThread} class
*/
private void onStartThread() {
socketThread = new SocketThread(ip, port);
new Thread(socketThread).start();
socketMessenger = new Messenger(new SocketToServiceIncomingHandler(socketThread.getLooper()));
//Tell Client thread has started
Message msg = Message.obtain();
msg.what = Event.THREAD_STARTED;
messageClient(msg);
}
/**
* Called when {@link Service} receives the CONNECT message from Client
* Sends the {@link Thread} a {@link Message} telling him to connect to server
*/
private void onConnect() {
Message msg = Message.obtain();
msg.what = Event.CONNECT;
msg.replyTo = socketMessenger;
messageSocket(msg);
}
/*
* Support functions
*/
/**
*
* @param client
*/
private void registerClient(Messenger client) {
clientMessenger = client;
Message msg = Message.obtain();
msg.what = Event.HELLO;
messageClient(msg);
}
/**
*
* @param msg
*/
private void messageClient(Message msg) {
try {
clientMessenger.send(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @param msg
*/
private void messageSocket(Message msg) {
try {
socketMessenger.send(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Incoming Handler for messages coming from Client
*/
private class ClientToServiceIncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case Event.HELLO:
Log.d("Service", "Client said HELLO");
onHello(msg);
break;
case Event.START_THREAD:
Log.d("Service", "Client said START_THREAD");
onStartThread();
break;
case Event.CONNECT:
Log.d("Service", "Client said CONNECT");
onConnect();
default:
Log.e("Service", "Client said some weird shit");
super.handleMessage(msg);
}
}
}
/**
* Incoming Handler for messages coming from Socket
*/
private class SocketToServiceIncomingHandler extends Handler {
public SocketToServiceIncomingHandler(Looper mainLooper) {
super(mainLooper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Event.CONNECTED:
Log.d("Service", "Socket said CONNECTED");
onConnected();
break;
case Event.DISCONNECTED:
Log.d("Service", "Socket said DISCONNECTED");
onDisconnected();
break;
default:
super.handleMessage(msg);
}
}
}
}
Thread
public class SocketThread implements Runnable {
//Properties
private Handler serviceIncomingHandler;
//Target to send Messages to Serivce
private Messenger serviceMessenger;
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
Log.d("Socket", "New thread started...");
Looper.prepare();
serviceIncomingHandler = new ServiceToSocketIncomingHandler();
Looper.loop();
}
/*
* Event Handlers for Messages from Service
*/
private void onConnect(Messenger serviceReplyTo) {
serviceMessenger = serviceReplyTo;
Message msg = Message.obtain();
if (socket.isConnected()) {
msg.what = Event.CONNECTED;
} else {
msg.what = Event.DISCONNECTED;
}
messageService(msg);
}
/*
* Support methods
*/
public Looper getLooper() {
return Looper.getMainLooper();
}
public void stopLooper() {
serviceIncomingHandler.getLooper().quit();
}
private void messageService(Message msg) {
try {
serviceMessenger.send(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
private class ServiceToSocketIncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Event.CONNECT:
Log.d("Socket", "Service said CONNECT");
onConnect(msg.replyTo);
break;
case Event.DISCONNECT:
Log.d("Socket", "Service said DISCONNECT");
onDisconnect();
break;
case Event.NEW_PICTURE:
Log.d("Socket", "Service said NEW_PICTURE");
onNewPicture(msg.obj);
break;
default:
Log.e("Socket", "Service said some weird shit...");
super.handleMessage(msg);
}
}
}
}
LogCat Ouput
Client(451): Binding to Service...
Service(451): TCPSocketService created
Service(451): Started...
Client(451): Binded to service
Service(451): Client said HELLO
Client(451): Service said HELLO
Service(451): Client said START_THREAD
Socket(451): New thread started...
Client(451): Service said THREAD_STARTED
Service(451): Client said CONNECT
Is there anyway to accomplish getting the Thread's Incoming Handler target so that I can send Messages to them from my Service
class?
Thanks in advance for any help!
I managed to get this working by making my SocketThread
class extend Thread
instead of implements Runnable
. Then, I created a Looper
object in the class and made a method in the SocketThread
class that returned the Looper
and one that returned the Handler
. This way, the TCPSocketService
creates a SocketThread
object, and asks for it's Looper
and Handler
, so it can start sending messages back and forth.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments