最近公司内部组织的一个ANdroid四大组件的培训,由于自己是菜鸟,考试时被老师的一个问题忽悠住了,甚是丢人,估计过两天会被人事总监请喝茶。问题是Remote Service的生命周期是什么,我这一抬眼啊,就直接哆嗦了,什么?Remote是什么东东,RemoteService又是什么东东,其实大概知道就是那个什么AIDL的破玩意儿,之前还写过Demo,准确的说是copy别人的Demo,唉唉。。。所以说还是要自己动手翘翘才能容易理解啊,在大庭广众之下回答不上来,那是相当的没面子啊。事后想想这真是个简单的问题,Local Service,Remote Service不都是Service吗,只怪自己胆小,紧张之余把这个都忘了。话不多说,进入自己的yy当中,完全自己理解,如有错误,敬请谅解啊。
1.最起码知道AIDL全称是什么吧,Android Interface Describe Language,不知道单词对不对,反正就是这个意思。
2.要知道他是干嘛用的吧!进程间通信,就是两个不同进程间通信,就像QQ斗地主和QQ之间进行什么授权,我感觉应该就是用的这个,第一次登录斗地主的时候是要用户名和密码的,如果你装了QQ,那他就直接和QQ之间进行了通信,并且读取了QQ的帐号信息,然后登录斗地主,不知道腾讯的大牛是不是这么做的。
3.我理解的步骤是:利用intent开启远程的Service,然后远程的Service就会启动,并且返回一个Ibinder,我就当他是个大包裹,按了包裹发射器,远程的邮局就向我发射大包裹,导弹里就携带了我需要的东西,美女、钞票,美哉。就是这个Service是另一个进程当中的,所以和我通信,是需要废一番周折的,如果是本地service,也就是同一个进程当中的话,我就直接伸手把美女抱住不就得了。
4.话说AIDL能处理的还真不是美女,钞票啊,他能处理的数据包括JAVA基本数据类型,还有list,map啦,还有就是实现了Parceble接口的实例化对象,这个很好嘛,基本够用了。
接下来就看看代码怎么实现吧:
(1) 间两个工程,Cilent和Server,在两个工程中建相同的一个包,注意!!!包名一定要完全相同,再在包下建立一个完全相同aidl文件,
package com.neil.aidl; interface ICallBack{ void giveCallBack(String parm); }
好了,这是Client的ICallack.aidl,那么Server中的也得有一个和这个一模一样的文件,文件里就定义了一个接口,当然可以是多个接口,想几个就几个,返回值和参数跟是上面4所说的啦。定义好这个爱的了文件,那么在Android工程的gen目录下会自动生成一个JAVA类文件,长什么样子,自己去看就知道了,等他生成了java类以后,我们在客户端服务端就可用他们了,
(2)先来个简单的,进程间传个int吧,
先看服务端代码实现:
public class RemoteService extends Service{ private int count=100; @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); Toast.makeText(getApplicationContext(), "onCrearte", Toast.LENGTH_SHORT).show(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Toast.makeText(getApplicationContext(), "onStartCommand", Toast.LENGTH_SHORT).show(); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub System.out.println("remote onBind "+countservice); Toast.makeText(getApplicationContext(), "onbind", Toast.LENGTH_SHORT).show(); return countservice; } CountService.Stub countservice=new CountService.Stub() { @Override public int getCount() throws RemoteException {return count; } };
话说这里的就是一个Service的继承类,里边的生命周期一目了然,客户点bindService之后,这个service自然会先调用onCreate()方法了,随后就调用了onBind()方法,这个方法返回的是一个什么咧,看看,就是一个CountService的内部类Stub的对象,这个可以在gen下的文件中找到,他继承之binder,所以Service通过onind()方法返回给客户端的是一个Binder对象,而且这个Binder对象还实现了你在aidl文件中定义的那个接口,这下,好办了,你想得到什么,统统放在这个Stub实例中就OK了,当客户端地到之后,就可以取出里边返回的数据
且看客户端是怎么得到这个Binder的
public void bindRemoteService(){ Intent intent=new Intent(); intent.setAction(BIND_ACTION); bindService(intent, mConnection, BIND_AUTO_CREATE); }
这里便就是bindService了,看看里边的参数,第一个就是标志你要开启目标服务的的那个intent对象,第二个就是一个实现了ServiceConnection接口的对象,看看这个ServiceConnection对象
class CountServiceConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub mCountService=CountService.Stub.asInterface(service); showToast("connected"); } @Override public void onServiceDisconnected(ComponentName name) { mCountService=null; showToast("disconnected"); } };
看见没,上面讲到的那个Binder对象就是在这里跑到客户端来的 mCountService=CountService.Stub.asInterface(service);
从这个mountService对象里就能得到在服务端放进去的数据。话说这就是AIDL进行跨进程通信的方法
话说还可以实现双方相互通信,客户端也可以想服务端传输数据,这时候就无所谓Client和Server。具体见Demo了。
http://download.csdn.net/detail/qmc0000/7938223