package com.digitallizard.bbcnewsreader;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.ListIterator;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
public class ServiceManager {
private Context context;
private Messenger resourceMessenger;
private Messenger messenger;
private boolean resourceServiceBound;
private ArrayList<Message> messageQueue;
public interface MessageReceiver {
public void handleMessage(Message msg);
}
static class IncomingHandler extends Handler {
private final WeakReference<MessageReceiver> receiver;
IncomingHandler(MessageReceiver receiver) {
this.receiver = new WeakReference<MessageReceiver>(receiver);
}
@Override
public void handleMessage(Message msg) {
// pass the message on
receiver.get().handleMessage(msg);
}
}
private ServiceConnection resourceServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
resourceServiceBound = true; // flag the service as bound
resourceMessenger = new Messenger(service); // allows us to talk to the service
// try and tell the service that we have connected so it will keep talking to us
sendMessageToService(ResourceService.MSG_REGISTER_CLIENT);
// send any queued messages
ListIterator<Message> iterator = messageQueue.listIterator();
while (iterator.hasNext()) {
sendMessageToService(iterator.next());
}
messageQueue.clear();
}
public void onServiceDisconnected(ComponentName className) {
// this runs if the service randomly disconnects if this happens there are more problems than a missing service
resourceMessenger = null; // as the service no longer exists, destroy its pointer
}
};
public void doBindService() {
// bind the service
context.bindService(new Intent(context, ResourceService.class), resourceServiceConnection, Context.BIND_AUTO_CREATE);
resourceServiceBound = true;
}
public void doUnbindService() {
// disconnect the resource service
// check if the service is bound, if so, disconnect it
if (resourceServiceBound) {
// politely tell the service that we are disconnected
sendMessageToService(ResourceService.MSG_UNREGISTER_CLIENT);
// remove local references to the service
context.unbindService(resourceServiceConnection);
resourceServiceBound = false;
}
}
public void sendMessageToService(Message msg) {
// check the service is bound before trying to send a message
if (resourceServiceBound && resourceMessenger != null) {
try {
resourceMessenger.send(msg); // send the message
} catch (RemoteException e) {
// we are probably shutting down, but report it anyway
Log.e("ERROR", "Unable to send message to service: " + e.getMessage());
}
}
else {
// things haven't initialized yet, queue the message up for sending in a bit
messageQueue.add(msg);
}
}
public void sendMessageToService(int what, Bundle bundle) {
// create a message according to parameters
Message msg = Message.obtain(null, what);
// add the bundle if needed
if (bundle != null) {
msg.setData(bundle);
}
msg.replyTo = messenger; // tell the service to reply to us, if needed
// check the service is bound before trying to send a message
if (resourceServiceBound && resourceMessenger != null) {
try {
resourceMessenger.send(msg); // send the message
} catch (RemoteException e) {
// we are probably shutting down, but report it anyway
Log.e("ERROR", "Unable to send message to service: " + e.getMessage());
}
}
else {
// things haven't initialized yet, queue the message up for sending in a bit
messageQueue.add(msg);
}
}
public void sendMessageToService(int what) {
sendMessageToService(what, null);
}
public ServiceManager(Context context, MessageReceiver receiver) {
this.context = context;
messenger = new Messenger(new IncomingHandler(receiver));
messageQueue = new ArrayList<Message>();
}
}