Android远程服务一:android AIDL远程服务调用

来源:互联网 发布:腾龙信息网络工程公司 编辑:程序博客网 时间:2024/05/16 02:13

本文转载自:点击打开链接,感谢原文作者的分享,首先通过代码了解Android远程服务。

AIDL是一种远程服务调用机制,写一个简单的例子,我想应该能让大家知道它的基本使用方法。

这个例子实现的是两个应用之间的对象的数据的传递,例子比较简单,不过能体现AIDL的用法也就足够了。
  首先,如果你只需要传递比较简单的数据,比如 java原始类型数据,string charsequence 或者list/map不过list/map中的数据也必须是基本数据类型。那么可以直接传递。例如:
IService.aidl
package com.godxj.android.aidlservice;interface IService{String getString(intfirst);}
保存之后,可以在gen下找到对应的java文件,这里就不说这个java中binder机制了。有兴趣可以去读读它的实现原理。
  其次,如果你需要的传递的是比较复杂的数据,那么就要对数据进行封装,而Parcelable就是一个封装工具--包嘛装数据的!例如:
IService2.aidl
package com.godxj.android.aidlservice;import com.godxj.android.aidlservice.User;interface IService2{String getDouble(in String name, in User first);}

这里的user就是一个对象,这个对象就需要用Parcelable包装一下:
package com.godxj.android.aidlservice; import android.os.Parcel;import android.os.Parcelable; public class User implementsParcelable { private int age;private String name;private String sex; public int getAge() {returnage;} public void setAge(intage) {this.age = age;} public String getName() {returnname;} public void setName(String name) {this.name = name;} public String getSex() {returnsex;} public void setSex(String sex) {this.sex = sex;} @Overridepublic int describeContents() {System.out.println("describeContents");return0;} public static final Parcelable.Creator<User> CREATOR = newCreator<User>() { @Overridepublic User[] newArray(intsize) {return new User[size];} @Overridepublic User createFromParcel(Parcel source) {System.out.println("createFromParcel");User user = newUser();user.age = source.readInt();user.name = source.readString();user.sex = source.readString();return user;}}; @Overridepublic void writeToParcel(Parcel dest, intflags) {System.out.println("writeToParcel");dest.writeInt(age);dest.writeString(name);dest.writeString(sex);} }

当然,这个Parcelable,就是刚才说的装包,writeToParcel这个方法就是装包啦,而Creator里面的createFromParcel这个方法相当于就是解包了。 
重点:
1.在装包的时候装(writeToParcel)的先后顺序,要和解包(createFromParcel)的先后顺序保持一致,不然可能出现数据位置互换的错。
2.每一个被包装(实现了Parcelable)的对象都需要一个单独的aidl文件,如:
User.aidl
package com.godxj.android.aidlservice;parcelable User;

3.每一个aidl文件中出现的被包装的类都需要引入他所在的包,如:import com.godxj.android.aidlservice.User;

4.作为服务程序的那个service,必须要一个匹配的action,如果需要其他的action可以添加在他的后面。如:

<service android:name="com.godxj.android.aidlservice.AIDLServiceImp"><intent-filter ><action android:name="com.godxj.android.aidlservice.IService"/><action android:name="com.godxj.android.aidlservice.action"/></intent-filter></service>


5.客户端需要用到的所有内容,都需要从服务端拷贝过去,如下面两个目录结构:
     服务端                            客户端

  最后一点,也就是代码的实现中。理解起来也不难。

既然是作为服务端,那么必然有一个实现了android.app.service的service,对于大家都知道,启动service可以通过startService也可以通过bindService来启动,而aidl需要使用后者,绑定服务--onBind。可以看到,在这里便是返回一个IBinder给启用它的activity,那么这里返回的,很容易相到就是我们的服务内容了。但是这个返回的IBinder在哪里呢,这个类就是我们编写的aidl服务后,android自己为我们生成的一个IBinder了。在gen目录下可以找到与编写的aidl对应的服务java文件,例如:

public interface IService2 extends android.os.IInterface {/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implementscom.godxj.android.aidlservice.IService2


可以看到,在IService2里面 出现了一个抽象类Stub,而它就是我们需要的IBinder,同时我们也看到了它继承了android.os.Binder。

那么现在就好办了,实例化这个抽象类返回回去,例如:

public class Service2Imp extends IService2.Stub{@Overridepublic String getDouble(String name, User first) throwsRemoteException {System.out.println("....................");System.out.println(" the name = " + name);System.out.println("age = " + first.getAge());System.out.println("name = " + first.getName());System.out.println("sex = " + first.getSex());return"second";}}


那么服务端就算是ok了。

  最后客户端,在启用它的时候使用bindService,而在这里bindService(Intent service,ServiceConnection conn, int flags);可以看到第一和第三个参数都知道什么含义,第二个参数其实就是服务连接操作,可以理解为练上了service然后做什么。既然它需要这样一个对象,那么我们就实例这样一个对象给它,事实上我们实例化之后,正如其名,它就是给我们提供一个练上了干什么,断开了又干什么两个方法。例如:

private ServiceConnection serCon = new ServiceConnection() { @Overridepublic void onServiceDisconnected(ComponentName name) {System.out.println("onServiceDisconnected");} @Overridepublic void onServiceConnected(ComponentName name, IBinder service) {System.out.println("onServiceConnected");// iservice = IService.Stub.asInterface(service);iservice2 = IService2.Stub.asInterface(service);try{// System.out.println(iservice.getString(10));User user = new User();user.setAge(22);user.setName("godxj");user.setSex("boy");iservice2.getDouble("Are You !", user);}catch(Exception e) {e.printStackTrace();}}};


  到这里,AIDL的实现就算是完成了,当然我还是得提醒下,这个服务启动了一定要记得关!unBind还是要的。如:

protected void onDestroy() {super.onDestroy();unbindService(serCon);}

还有两个工程源码附件,可惜CSDN不支持上传。

0 0
原创粉丝点击