我的应用程序的结构由在后台运行的服务组成广播接收器正在监听。
下图描述了我的应用程序聊天的结构和工作流程(请按照字母顺序)
这是我在聊天窗口活动中的代码:
this.service = new ServiceManager(this, PushService.class,
new Handler() {
@Override
public void handleMessage(Message msg) {
// Receive message from service
switch (msg.what) {
case 10:
reloadMessagesInTheChat();
// Play sound
if (mp.isPlaying())
mp.stop();
mp.start();
break;
default:
showErrorMsssage("Some messages arrived");
super.handleMessage(msg);
break;
}
}
});
this.service.start();
// Now sending the message (I do it initially to tell the service which user is in the chat now, such that it forwards messages to this receiver, instead of creating notifications)
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
try {
service.send(Message.obtain(null, 10, user_id, 0));
} catch (RemoteException e) {
e.printStackTrace();
// This is just a Toast Message:
showErrorMsssage("Couldn't send messages to the service");
}
}
}, 1000);
这是来自服务的代码:
首先这是路由消息的条件
if(connectedChatUser != ChatUserInTheReceivedMessage ){
// Create Notification with Pending Intent to open chat windows with the user
}
else{
send(Message.obtain(null, 10, "ID_OF_THE_CHATTER" , 0));
}
这是服务的重要部分:
ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler.
private class IncomingHandler extends Handler {
// Handler of incoming messages from clients.
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
default:
//super.handleMessage(msg);
onReceiveMessage(msg);
}
}
}
private int connectedChatUser = 0;
private int contactList = 0;
/*@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY; // run until explicitly stopped.
}*/
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
protected void send(Message msg) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
mClients.get(i).send(msg);
}
catch (RemoteException e) {
// The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop.
mClients.remove(i);
}
}
}
这是服务中的接收器,最初接收打开的聊天窗口的 ID
public void onReceiveMessage(Message msg) {
if (msg.what == CHAT_USER) {
// User ID sent from the activity initially
connectedChatUser = msg.arg1;
}
// Other cases aren't important as they cause no problem
}
最后Activity中的Service就是这个类的一个实例:
public class ServiceManager {
private Class<? extends PushService> mServiceClass;
private Context mActivity;
private boolean mIsBound;
private Messenger mService = null;
private Handler mIncomingHandler = null;
private final Messenger mMessenger = new Messenger(new IncomingHandler());
private class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
if (mIncomingHandler != null) {
if(GlobalSettings.dev)Log.i("ServiceHandler", "Incoming message. Passing to handler: "+msg);
mIncomingHandler.handleMessage(msg);
}
}
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
//textStatus.setText("Attached.");
if(GlobalSettings.dev)Log.i("ServiceHandler", "Attached.");
try {
Message msg = Message.obtain(null, AbstractService.MSG_REGISTER_CLIENT);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
// In this case the service has crashed before we could even do anything with it
}
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been unexpectedly disconnected - process crashed.
mService = null;
//textStatus.setText("Disconnected.");
if(GlobalSettings.dev)Log.i("ServiceHandler", "Disconnected.");
}
};
public ServiceManager(Context context, Class<? extends PushService> serviceClass, Handler incomingHandler) {
this.mActivity = context;
this.mServiceClass = serviceClass;
this.mIncomingHandler = incomingHandler;
if (isRunning()) {
doBindService();
}
}
public void start() {
doStartService();
doBindService();
}
public void stop() {
doUnbindService();
doStopService();
}
/**
* Use with caution (only in Activity.onDestroy())!
*/
public void unbind() {
doUnbindService();
}
public boolean isRunning() {
ActivityManager manager = (ActivityManager) mActivity.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (mServiceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
public void send(Message msg) throws RemoteException {
if (mIsBound) {
if (mService != null) {
mService.send(msg);
}
}
else{
if(GlobalSettings.dev)Log.d("From Activity to service:","Failed as it's not bound");
}
}
private void doStartService() {
mActivity.startService(new Intent(mActivity, mServiceClass));
}
private void doStopService() {
mActivity.stopService(new Intent(mActivity, mServiceClass));
}
private void doBindService() {
mActivity.bindService(new Intent(mActivity, mServiceClass), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
private void doUnbindService() {
if (mIsBound) {
// If we have received the service, and hence registered with it, then now is the time to unregister.
if (mService != null) {
try {
Message msg = Message.obtain(null, AbstractService.MSG_UNREGISTER_CLIENT);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
// There is nothing special we need to do if the service has crashed.
}
}
// Detach our existing connection.
mActivity.unbindService(mConnection);
mIsBound = false;
//textStatus.setText("Unbinding.");
if(GlobalSettings.dev)Log.i("ServiceHandler", "Unbinding.");
}
}
}