您的位置:首页 > 移动开发 > Android开发

Android中Activity与Service的双向通讯

2015-11-11 23:48 447 查看

1. Activity与本地Service的双向通讯

Activity和本地的Service都是在主线程中,是两个组件(对象)。所以本质上来讲,Activity和本地Service之间其实是同一个进程(主线程)内对象之间的通讯,而不涉及任何跨进程的东西。

对象之间的通讯,抽象出来就是对象A与对象B之间通讯,通讯方式是A持有B的实例即可。Activity和本地service之间的通讯即是Activity在绑定的时候获得被绑定Service的实例,然后即可在Activity中对Service进行调用。

那Service如何主动向Activity进行消息传递呢?由于Activity与Service同属与主线程,主线程只有一个消息队列MessageQueue,那么只要通过Handler即可。具体来讲:

Activity中定义Handler activityHandler,绑定Service后将activityHandler传递到Service;Service中定义Handler serviceHandler,Activity持有了Service的实例,自然可以获得该serviceHandler。原理图即:



图1,主线程中的Activity持有Service实例,共享主线程的消息队列
通讯方式:

Activity→Servic:通过serviceHandler发送Message,service中定义的serviceHandler会处理该消息;
Service→Activiy:通过activityHandler发送消息,Activity中固定翼的activity会处理该消息

2. Activity与Service的跨进程双向通讯

在AndroidManifest.xml中配置Service时:

<service android:name="RemoteService"
android:process=":remote">

这样,该Service就属于新的进程。跨进程通讯采用Binder机制,比较复杂。抽象来讲就是,进程A与进程B在内存空间中属于不连续的区域,需要操作系统作为中介获得彼此的相对地址。这时候进程A与进程B通讯采用Messenger。

具体来讲,Activity中定义Messenger activityMessenger,Messenger在定义的时候封装该进程的一个Handler acitivityHandler,acitivityHandler中包括了消息处理的回调函数。Service中也定义Messenger serviceMessenger,初始化时也封装了该进程的一个Handler serviceHandler,serviceHandler中包括了消息处理的回调函数。原理图:



图2,两个进程交换Messenger(封装了各自的Handler)
通讯方式:

Activity→Servic:通过serviceMessenger发送Message,service中定义的serviceHandler会处理该消息;

Service→Activiy:通过activityMessenger发送消息,Activity中定义的activity会处理该消息

附件是我写了个ThreadTest来测试了以上的内容。MainActivity定义了绑定了本地的Service和远程的Service。

下面是函数部分:

/**
* Activity绑定了两个Service:
* <p>主线程的LocalService:持有其实例,并将handler句柄传递过去</p>
* <p>新进程的RemoteService:持有定义在RremoteService中的mRemoteMessenger,其中包含了定义在RremoteService的Handler。
* 通过mRemoteMessenger可以将主线程的消息发送到新进程.将主线程中的mLocalMessenger封装为一个消息通过mRemoteMessenger发送到新进程,这样新进程就可以通过mLocalMessenger向主线程发消息了</p>
* */
public class MainActivity extends AppCompatActivity {
private Handler activityHandler,serviceHandler;//handler实现同一个线程中的Activity与Service的双向消息处理
private LocalService localService;//Activity通过binder持有localService的实例
private ServiceConnection mLocalConnection,mRemotecConnection ;
private boolean mLocalBound,mRemoteBound;
private Message message;
private Messenger mRemoteMessenger ,mLocalMessenger;//Messenger实现不同进程的Activity与Service的双向消息处理
public static final int LOCAL_MESSENGER=0X000;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initHandler();
initService();
initThread();

}
public void initThread() {
new Thread(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(5000*2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
message=serviceHandler.obtainMessage();
message.what=0x101;
message.sendToTarget();

try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
message=activityHandler.obtainMessage();
message.what=0x102;
message.sendToTarget();

try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
message=new Message();
message.what=0x103;
try {
mRemoteMessenger.send(message);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}).start();
}

@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Intent localintent = new Intent(this, LocalService.class);
bindService(localintent, mLocalConnection, Context.BIND_AUTO_CREATE);
Intent remoteIntent=new Intent(this,RemoteService.class);
bindService(remoteIntent, mRemotecConnection, Context.BIND_AUTO_CREATE);

}

@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
if (mLocalBound) {
unbindService(mLocalConnection);
mLocalBound=false;
}
if (mRemoteBound) {
unbindService(mRemotecConnection);
mRemoteBound=false;
}
}

private void initService(){
mLocalConnection=new ServiceConnection() {

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
LocalService.LocalBinder localBinder=(LocalService.LocalBinder)service;
localService=localBinder.getService();
localService.setHandler(activityHandler);//将本地的handler传给service
serviceHandler=localBinder.getHandler();//从service中获得其中的handler
mLocalBound=true;
}

@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
mLocalBound=false;
}

};

mRemotecConnection=new ServiceConnection() {

@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
mRemoteMessenger=null;
mRemoteBound=false;

}

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mRemoteMessenger=new Messenger(service);
Message message=new Message();
message.what=LOCAL_MESSENGER;
message.obj=mLocalMessenger;
try {
mRemoteMessenger.send(message);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mRemoteBound=true;
}
};
}
private void initHandler(){
activityHandler = new Handler() {
@SuppressLint("HandlerLeak")
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0x100:
Toast.makeText(MainActivity.this, "来自LocalService:0x100,本地处理", Toast.LENGTH_SHORT).show();
break;
case 0x102:
Toast.makeText(MainActivity.this, "本地:0x103", Toast.LENGTH_SHORT).show();
break;
case 0x104:
Toast.makeText(MainActivity.this, "来自remoteService:0x104,本地处理", Toast.LENGTH_SHORT).show();
break;
}
}
};
mLocalMessenger=new Messenger(activityHandler);//Messenger的初始化封装了本进程的Handler
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}


/**
* 主线程中的service;
* <p>Activity→Service:将LocalService和Service中的Handler封装到IBinder,通过binder机制与Activity进行通信,Activity持有LocalService及其Handler的实例.</p>
* <p>Service→Activity:Activity持有了LocalService的实例,就将Activity中定义的Handler交给Service.</p>
* */

public class LocalService extends Service{
private final IBinder mBinder = new LocalBinder();
private Handler serviceHandler,activityHandler;//主线程的Handler在service中的句柄
private Message message;//Service中的所有消息
/**
* 将LocalService封装到IBinder中
* */
public class LocalBinder extends Binder{

LocalService getService(){
return LocalService.this;
}
Handler getHandler(){
return serviceHandler;
}
}
/**
* 接收来自Activity的Handler
* */
public void setHandler(Handler handler){
activityHandler=handler;
}

@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
initHandler();
initThread();
}
private void initHandler(){
serviceHandler = new Handler() {
@SuppressLint("HandlerLeak")
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0x101:
Toast.makeText(LocalService.this, "消息来自Activity:0x101。在LocalService中处理!", Toast.LENGTH_SHORT).show();
break;

}
}
};
}

/**
*将IBinder返回
* */
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mBinder;
}
public void initThread() {
new Thread(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
message=activityHandler.obtainMessage();
message.what=0x100;
message.sendToTarget();

}
}).start();

}

}


/**
* Activity绑定了两个Service:
* <p>主线程的LocalService:持有其实例,并将handler句柄传递过去</p>
* <p>新进程的RemoteService:持有定义在RremoteService中的mRemoteMessenger,其中包含了定义在RremoteService的Handler。
* 通过mRemoteMessenger可以将主线程的消息发送到新进程.将主线程中的mLocalMessenger封装为一个消息通过mRemoteMessenger发送到新进程,这样新进程就可以通过mLocalMessenger向主线程发消息了</p>
* */
public class RemoteService extends Service{
private Handler remoteHandler;
private Messenger mRemoteMessenger ,mLocalMessenger;
private Message message;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mRemoteMessenger.getBinder();
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
initHandler();
mRemoteMessenger=new Messenger(remoteHandler);	//Messenger的初始化封装了本进程的Handler
message=new Message();
initThread();
}
@SuppressLint("HandlerLeak")
private void initHandler(){
remoteHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MainActivity.LOCAL_MESSENGER:
mLocalMessenger=(Messenger) msg.obj;
break;
case 0x103:
Toast.makeText(RemoteService.this, "来自Activity:0x103,remoteService处理!", Toast.LENGTH_SHORT).show();
break;

}
}
};

}
public void initThread() {
new Thread(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(5000*4);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
message.what=0x104;
try {
mLocalMessenger.send(message);
} catch (RemoteException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
message.what=0x106;
try {
mLocalMessenger.send(message);
} catch (RemoteException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

}
}).start();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: