前端时间项目运用到AIDL,关于AIDL客户端以及AIDL服务端网络上没有一个比较完备的Demo.

而参考Demo无疑是一个比较快速的学习方法.因此,我写了一个Demo.

供大家参考,也非常欢迎大家对其中写的不好的地方进行指正.

好了,首先简述下基本功能:

在AIDL 客户端三个EditText中输入三个值,点击提交按钮,将这三个值传入到AIDL服务端进行处理.

服务端处理后会执行客户端的回调函数:在AIDL客户端界面进行刷新,并显示一个toast.

接下来看看代码结构:

需要注意的是,两个工程中com.harlan.demo.aidl包内部的文件必须保持一致.

(1)HarlanInfo.java:这是包中唯一的一个java文件,是一个数据结构,该类实现了Parcelable接口

[java]view plaincopyprint?

packagecom.harlan.demo.aidl;

importandroid.os.Parcel;

importandroid.os.Parcelable;

/**

*

*<一句话功能简述>

*Parcelable是Android特有的功能,效率比实现Serializable接口高

*

*@authorAdministrator

*@version[版本号,2012-12-10]

*@see[相关类/方法]

*@since[产品/模块版本]

*/

publicclassHarlanInfoimplementsParcelable

{

privateStringname;

privateintage;

privateStringplace;

publicStringgetName()

{

returnname;

}

publicvoidsetName(Stringname)

{

this.name=name;

}

publicintgetAge()

{

returnage;

}

publicvoidsetAge(intage)

{

this.age=age;

}

publicStringgetPlace()

{

returnplace;

}

publicvoidsetPlace(Stringplace)

{

this.place=place;

}

/**

*<默认构造函数>

*/

publicHarlanInfo()

{

}

/**

*<默认构造函数>

*/

publicHarlanInfo(Parcelin)

{

//注意顺序

name=in.readString();

age=in.readInt();

place=in.readString();

}

/**

*seemsmeaningless

*return0;

*/

@Override

publicintdescribeContents()

{

return0;

}

/**

*将对象序列化为一个Parcel对象

*可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,

*再通过createFromParcel从流里读取对象

*注意:写的顺序和读的顺序必须一致。

*/

@Override

publicvoidwriteToParcel(Parceldest,intflags)

{

dest.writeString(name);

dest.writeInt(age);

dest.writeString(place);

}

/**

*实例化静态内部对象CREATOR实现接口Parcelable.Creator

*publicstaticfinal一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写

*/

publicstaticfinalParcelable.Creator<HarlanInfo>CREATOR=newCreator<HarlanInfo>(){

//将Parcel对象反序列化为HarlanInfo

@Override

publicHarlanInfocreateFromParcel(Parcelsource)

{

HarlanInfohlInfo=newHarlanInfo(source);

returnhlInfo;

}

@Override

publicHarlanInfo[]newArray(intsize)

{

returnnewHarlanInfo[size];

}

};

}

(2)HarlanInfo.aidl :协同HarlanInfo.java文件"作战",缺一不可.

[java]view plaincopyprint?

packagecom.harlan.demo.aidl;

parcelableHarlanInfo;

(3)ICallBack.aidl:
这是客户端回调方法的接口,在客户端实现其具体方法,在服务端调用执行.

[java]view plaincopyprint?

packagecom.harlan.demo.aidl;

interfaceICallBack{

/**

*callbackofAIDLClient

*handlebyserver

**/

voidhandleByServer(Stringparam);

}

(4)ExecuteService.aidl:

这是从服务端获取数据方法的接口,在服务端实现其具体方法,在客户端调用执行.

参数info是由用户输入的数据构成的,同时传递的还要客户端回调方法的句柄,从而服务端可以调用客户端的回调方法.

该方法返回一个HarlanInfo的数据类型,客户端获得此数据,在界面上进行相应的显示.

[java]view plaincopyprint?

packagecom.harlan.demo.aidl;

importcom.harlan.demo.aidl.HarlanInfo;

importcom.harlan.demo.aidl.ICallBack;

interfaceExecuteServiceAIDL

{

/**

*getinfofromserverand

*Transferacallbackmethodshandle;

*ifoccurerror,willbereturnnull

*对于非基本数据类型和String和CharSequence类型,要加上方向指示

*包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。

*/

HarlanInfogetServerHarlanInfo(inHarlanInfoinfo,ICallBackicallback);

}


好了,现在对com.harlan.demo.aidl包已经大致了解,build一下project,发现gen文件夹下面多出来一个包:


包中文件可以随便看看,不看也没事.因为你只要在客户端服务端相应的位置实现对应的接口就可以了.

先来看看服务端,因为服务端相对简单些,不需要界面什么的,只是一个Service.

上代码:

[java]view plaincopyprint?

packagecom.harlan.demo.service;

importandroid.app.Service;

importandroid.content.Intent;

importandroid.os.IBinder;

importandroid.os.RemoteException;

importandroid.util.Log;

importcom.harlan.demo.aidl.ExecuteServiceAIDL;

importcom.harlan.demo.aidl.HarlanInfo;

importcom.harlan.demo.aidl.ICallBack;

publicclassAIDLServiceextendsService

{

publicstaticfinalStringTAG="AIDLService";

privateICallBackmCallBack;

/**

*绑定服务

*/

@Override

publicIBinderonBind(Intentintent)

{

//TODOAuto-generatedmethodstub

returnmBinder;

}

/**

*创建服务

*/

@Override

publicvoidonCreate()

{

super.onCreate();

}

/**

*销毁服务

*/

@Override

publicvoidonDestroy()

{

super.onDestroy();

}

/**

*启动服务

*/

@Override

publicvoidonStart(Intentintent,intstartId)

{

super.onStart(intent,startId);

}

/**

*解绑服务

*/

@Override

publicbooleanonUnbind(Intentintent)

{

mCallBack=null;

returnsuper.onUnbind(intent);

}

ExecuteServiceAIDL.StubmBinder=newExecuteServiceAIDL.Stub()

{

//这里实现了getServiceHarlanInfo接口

@Override

publicHarlanInfogetServerHarlanInfo(HarlanInfoinfo,ICallBackicallback)

throwsRemoteException

{

Log.d(TAG,"getServerHarlanInfo");

mCallBack=icallback;

mCallBack.handleByServer("Themsgisfromserver");

HarlanInfonewInfo=newHarlanInfo();

newInfo.setName(info.getName().toLowerCase());

newInfo.setAge(info.getAge()+10);

newInfo.setPlace("Home");

returnnewInfo;

}

};

}

一目了然,服务端主要的功能就是实现了aidl中的getServerHarlanInfo(HarlanInfo info, ICallBack icallback)接口.返回了一个mBinder供客户端调用.

写好了服务,还得在Manifest文件里面配置一下:

[java]view plaincopyprint?

<service

android:name=".AIDLService">

<intent-filter>

<actionandroid:name="com.harlan.demo.aidl.service"/>

</intent-filter>

lt;/service>

服务端写好了,就来客户端的了.客户端主要是一个activity,界面相对简单,如图所示:

界面布局相对简单,就不贴代码了.

下面贴ClientActivity的代码:

[java]view plaincopyprint?

packagecom.harlan.demo.activity;

importandroid.app.Activity;

importandroid.content.ComponentName;

importandroid.content.Intent;

importandroid.content.ServiceConnection;

importandroid.os.Bundle;

importandroid.os.IBinder;

importandroid.os.RemoteException;

importandroid.util.Log;

importandroid.view.View;

importandroid.widget.Button;

importandroid.widget.EditText;

importandroid.widget.Toast;

importcom.harlan.demo.aidl.ExecuteServiceAIDL;

importcom.harlan.demo.aidl.HarlanInfo;

importcom.harlan.demo.aidl.ICallBack;

publicclassClientActivityextendsActivity

{

publicstaticfinalStringTAG="ClientActivity";

privatestaticfinalStringBIND_ACTION="com.harlan.demo.aidl.service";

privateEditTextmEditTextName;

privateEditTextmEditTextAge;

privateEditTextmEditTextPlace;

privateButtonmButtonCommit;

privateExecuteServiceAIDLexecuteService;

@Override

protectedvoidonCreate(BundlesavedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_client);

getView();

//用户点击提交按钮,将数据传至服务端进行处理

mButtonCommit.setOnClickListener(newView.OnClickListener()

{

@Override

publicvoidonClick(Viewv)

{

//绑定服务

getServiceConnect();

}

});

}

privatevoidgetView()

{

mEditTextName=(EditText)findViewById(R.id.editText_name);

mEditTextAge=(EditText)findViewById(R.id.editText_age);

mEditTextPlace=(EditText)findViewById(R.id.editText_place);

mButtonCommit=(Button)findViewById(R.id.button_commit);

}

privatevoidgetServiceConnect()

{

Intentit=newIntent();

it.setAction(BIND_ACTION);

startService(it);

bindService(it,mserviceConnection,BIND_AUTO_CREATE);

}

ServiceConnectionmserviceConnection=newServiceConnection()

{

@Override

publicvoidonServiceDisconnected(ComponentNamename)

{

Log.d(TAG,"onServiceDisconnected");

}

@Override

publicvoidonServiceConnected(ComponentNamename,IBinderservice)

{

Log.d(TAG,"onServiceConnected");

//获取服务端传过来的IBinder对象,通过该对象调用服务端的方法

executeService=ExecuteServiceAIDL.Stub.asInterface(service);

if(executeService!=null)

{

handlerInfo();

}

}

};

privatevoidhandlerInfo()

{

StringmName;

intmAge;

StringmPlace;

if(mEditTextName.getText().toString().equals(""))

{

mEditTextName.setText("Harlan");

mName="Harlan";

}

else

{

mName=mEditTextName.getText().toString();

}

if(mEditTextAge.getText().toString().equals(""))

{

mAge=22;

}

else

{

mAge=Integer.parseInt(mEditTextAge.getText().toString());

}

if(mEditTextPlace.getText().toString().equals(""))

{

mPlace="Nanjing";

}

else

{

mPlace=mEditTextPlace.getText().toString();

}

HarlanInfomInfo=newHarlanInfo();

mInfo.setName(mName);

mInfo.setAge(mAge);

mInfo.setPlace(mPlace);

try

{

HarlanInfoserverInfo=newHarlanInfo();

//调用服务端的方法

serverInfo=executeService.getServerHarlanInfo(mInfo,mCallBack);

//更新界面

mEditTextName.setText(serverInfo.getName());

mEditTextAge.setText(String.valueOf(serverInfo.getAge()));

mEditTextPlace.setText(serverInfo.getPlace());

unbindService(mserviceConnection);

}

catch(RemoteExceptione)

{

e.printStackTrace();

}

}

ICallBack.StubmCallBack=newICallBack.Stub()

{

//客户端回调方法的具体实现

@Override

publicvoidhandleByServer(Stringparam)

throwsRemoteException

{

Toast.makeText(getApplicationContext(),param,Toast.LENGTH_LONG).show();

}

};

}

服务端调用客户端回调方法,在界面上显示一个toast.客户端根据服务端传回来的数据,刷新界面.

最后运行结果如图所示:

具体的Demo已经上传至CSDN,下载地址:http://download.csdn.net/detail/singleton1900/4928804