Android远程服务与本地服务的特点以及功能差异

最近又重新看了点IPC的相关知识,以前看过不少Binder的知识,看到c++层思路就很模糊了,回头再看也算是一种学习。

IPC全称为:interprocess communication内部进程间通信,官方地址:http://developer.android.com/intl/zh-cn/guide/components/aidl.html,网上对这一块介绍的资料也着实不少,入门的话还是推荐看老罗的。


鉴于以前也知识看看相关知识,从来也没动手去做过,于是就照着官方文档开始动手创建Demo, 在按照官方文档实现之后,我察觉到有一个需求,官方只是说客户端可以调用远程服务端,那么远程服务端想要调用客户端可不可以呢?


为了尽快实现需求,那我就先将服务启动在本地,也就是说与Service与Activity处于同一进程,进行测试。它的结果是可行的,相关代码如下:

Activity相关代码:

public class MainActivity extends ActionBarActivity implements ServiceConnection, IServiceConnect {
	public final static String TAG = "MainActivity";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		...

		bindService(new Intent("com.example.aidl.RemoteService"), this, BIND_AUTO_CREATE);
	}

	@Override
	public void onServiceConnected(ComponentName name, IBinder service) {
		Log.e(TAG, "MainActivity onServiceConnected " + name + " - " + service);
		if (service instanceof ServiceBinder) {
			ServiceBinder new_name = (ServiceBinder) service;
			// 获取服务的引用,使服务与Activity建立双向关系
			RemoteService service2 = new_name.getService();
			service2.setmServiceConnect(this);
		}
	}

	...

	@Override
	public void callback() {
		// 这种模式只有在同一进程中的服务才可以被使用
		Log.e(TAG, "MainActivity 被服务端调用");
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		unbindService(this);
	}
}
Service相关代码:

public class RemoteService extends Service implements Runnable {
	public final static String TAG = "RemoteService";
	public IServiceConnect mServiceConnect;
	...

	@Override
	public IBinder onBind(Intent intent) {
		Log.i(TAG, "RemoteService onBind");
		return new ServiceBinder(this);//返回含有服务引用的内部类
	}

	public static class ServiceBinder extends Binder {
		private RemoteService service;

		public ServiceBinder(RemoteService service) {
			super();
			this.service = service;
		}

		public RemoteService getService() {
			return service;
		}
	}

	public void setmServiceConnect(IServiceConnect mServiceConnect) {
		this.mServiceConnect = mServiceConnect;
		new Handler().postDelayed(RemoteService.this, 3000);//当建立连接之后启动一个任务
	}

	@Override
	public void run() {
		if (mServiceConnect != null) {
			mServiceConnect.callback();//调用Activity的相关方法,验证通信
		}
	}

}

上述结果是可以在同一进程的Activity与Service间互相通信的,因为在onServiceConnected中回调的Binder对象则为刚刚Service返回的对象,在Activity中打印的Log如下:

那么跨进程间互相通信可不可以呢?

我们在Service的Manifest文件中给Service添加Process属性,属性值为:remote:


            
                

                
            
        
好了,这下启动服务之后,它就属于远程服务了,它与Activity不属于同一个进程,在Android中一个进程则是一个虚拟机。

如果我再按照刚才的方法进行测试,服务是启动了,但是Activity收到的Binder对象却是这样的:

Android远程服务与本地服务的特点以及功能差异_第1张图片
这里是说,返回的组件名称为RemoteService,但是返回的Binder对象则为BinderProxy,这个BinderProxy则为RemoteService远程服务在本地的代理,熟悉AIDL的相关信息的人,肯定知道Proxy知道是什么。
那么我们在这里可不可以从Proxy对象中把远程的RemoteService对象拿到呢,我们看一下调试信息:

Android远程服务与本地服务的特点以及功能差异_第2张图片

我们看到在Proxy中的并没有RemoteService的引用,嗯,因为IPC通信,是跨进程的,我们都是通过代理与服务打交道的,所以...


那么回到标题,说说远程服务与本地服务的特点与差异:

其实都是服务,提供的功能一致,只是一个在本地,一个在其它进程,所以,服务与客户端打交道的时候就有了不同,要谨慎对待。

你可能感兴趣的:(移动开发,c/c++,运维)