Android中Activity与Service的双向通讯

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();
		
	}

}







  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值