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

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

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


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


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

Activity相关代码:

<span style="font-family:Microsoft YaHei;font-size:14px;">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) {
<span style="white-space:pre">		</span>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);
	}
}
</span>
Service相关代码:

<span style="font-family:Microsoft YaHei;font-size:14px;">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的相关方法,验证通信
		}
	}

}
</span>

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

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

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

<span style="font-family:Microsoft YaHei;font-size:14px;"><service
            android:name="com.example.aidl.RemoteService"
            android:process=":remote" >
            <intent-filter>
                <action android:name="com.example.aidl.RemoteService" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service></span>
好了,这下启动服务之后,它就属于远程服务了,它与Activity不属于同一个进程,在Android中一个进程则是一个虚拟机。

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


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

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


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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值