前端时间项目运用到AIDL,关于AIDL客户端以及AIDL服务端网络上没有一个比较完备的Demo.
而参考Demo无疑是一个比较快速的学习方法.因此,我写了一个Demo.
供大家参考,也非常欢迎大家对其中写的不好的地方进行指正.
好了,首先简述下基本功能:
在AIDL 客户端三个EditText中输入三个值,点击提交按钮,将这三个值传入到AIDL服务端进行处理.
服务端处理后会执行客户端的回调函数:在AIDL客户端界面进行刷新,并显示一个toast.
接下来看看代码结构:
需要注意的是,两个工程中com.harlan.demo.aidl包内部的文件必须保持一致.
(1)HarlanInfo.java:这是包中唯一的一个java文件,是一个数据结构,该类实现了Parcelable接口
[java] view plaincopyprint?
- package com.harlan.demo.aidl;
- import android.os.Parcel;
- import android.os.Parcelable;
- /**
- *
- * <一句话功能简述>
- * Parcelable是Android特有的功能,效率比实现Serializable接口高
- *
- * @author Administrator
- * @version [版本号, 2012-12-10]
- * @see [相关类/方法]
- * @since [产品/模块版本]
- */
- public class HarlanInfo implements Parcelable
- {
- private String name;
- private int age;
- private String place;
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- public int getAge()
- {
- return age;
- }
- public void setAge(int age)
- {
- this.age = age;
- }
- public String getPlace()
- {
- return place;
- }
- public void setPlace(String place)
- {
- this.place = place;
- }
- /**
- * <默认构造函数>
- */
- public HarlanInfo()
- {
- }
- /**
- * <默认构造函数>
- */
- public HarlanInfo(Parcel in)
- {
- //注意顺序
- name = in.readString();
- age = in.readInt();
- place = in.readString();
- }
- /**
- * seems meaningless
- * return 0;
- */
- @Override
- public int describeContents()
- {
- return 0;
- }
- /**
- * 将对象序列化为一个Parcel对象
- * 可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,
- * 再通过createFromParcel从流里读取对象
- * 注意:写的顺序和读的顺序必须一致。
- */
- @Override
- public void writeToParcel(Parcel dest, int flags)
- {
- dest.writeString(name);
- dest.writeInt(age);
- dest.writeString(place);
- }
- /**
- * 实例化静态内部对象CREATOR实现接口Parcelable.Creator
- * public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写
- */
- public static final Parcelable.Creator<HarlanInfo> CREATOR = new Creator<HarlanInfo>(){
- //将Parcel对象反序列化为HarlanInfo
- @Override
- public HarlanInfo createFromParcel(Parcel source)
- {
- HarlanInfo hlInfo = new HarlanInfo(source);
- return hlInfo;
- }
- @Override
- public HarlanInfo[] newArray(int size)
- {
- return new HarlanInfo[size];
- }
- };
- }
(2)HarlanInfo.aidl :协同HarlanInfo.java文件"作战",缺一不可.
[java] view plaincopyprint?
- package com.harlan.demo.aidl;
- parcelable HarlanInfo;
(3)ICallBack.aidl:
这是客户端回调方法的接口,在客户端实现其具体方法,在服务端调用执行.
[java] view plaincopyprint?
- package com.harlan.demo.aidl;
- interface ICallBack{
- /**
- *callback of AIDLClient
- *handle by server
- **/
- void handleByServer(String param);
- }
(4)ExecuteService.aidl:
这是从服务端获取数据方法的接口,在服务端实现其具体方法,在客户端调用执行.
参数info是由用户输入的数据构成的,同时传递的还要客户端回调方法的句柄,从而服务端可以调用客户端的回调方法.
该方法返回一个HarlanInfo的数据类型,客户端获得此数据,在界面上进行相应的显示.
[java] view plaincopyprint?
- package com.harlan.demo.aidl;
- import com.harlan.demo.aidl.HarlanInfo;
- import com.harlan.demo.aidl.ICallBack;
- interface ExecuteServiceAIDL
- {
- /**
- *get info from server and
- *Transfer a callback methods handle;
- *if occur error ,will be return null
- *对于非基本数据类型和String和CharSequence类型,要加上方向指示
- *包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。
- */
- HarlanInfo getServerHarlanInfo(in HarlanInfo info,ICallBack icallback);
- }
好了,现在对com.harlan.demo.aidl包已经大致了解,build一下project,发现gen文件夹下面多出来一个包:
包中文件可以随便看看,不看也没事.因为你只要在客户端服务端相应的位置实现对应的接口就可以了.
先来看看服务端,因为服务端相对简单些,不需要界面什么的,只是一个Service.
上代码:
[java] view plaincopyprint?
- package com.harlan.demo.service;
- import android.app.Service;
- import android.content.Intent;
- import android.os.IBinder;
- import android.os.RemoteException;
- import android.util.Log;
- import com.harlan.demo.aidl.ExecuteServiceAIDL;
- import com.harlan.demo.aidl.HarlanInfo;
- import com.harlan.demo.aidl.ICallBack;
- public class AIDLService extends Service
- {
- public static final String TAG = "AIDLService";
- private ICallBack mCallBack;
- /**
- * 绑定服务
- */
- @Override
- public IBinder onBind(Intent intent)
- {
- // TODO Auto-generated method stub
- return mBinder;
- }
- /**
- * 创建服务
- */
- @Override
- public void onCreate()
- {
- super.onCreate();
- }
- /**
- * 销毁服务
- */
- @Override
- public void onDestroy()
- {
- super.onDestroy();
- }
- /**
- * 启动服务
- */
- @Override
- public void onStart(Intent intent, int startId)
- {
- super.onStart(intent, startId);
- }
- /**
- * 解绑服务
- */
- @Override
- public boolean onUnbind(Intent intent)
- {
- mCallBack = null;
- return super.onUnbind(intent);
- }
- ExecuteServiceAIDL.Stub mBinder = new ExecuteServiceAIDL.Stub()
- {
- //这里实现了getServiceHarlanInfo接口
- @Override
- public HarlanInfo getServerHarlanInfo(HarlanInfo info, ICallBack icallback)
- throws RemoteException
- {
- Log.d(TAG,"getServerHarlanInfo");
- mCallBack = icallback;
- mCallBack.handleByServer("The msg is from server");
- HarlanInfo newInfo = new HarlanInfo();
- newInfo.setName(info.getName().toLowerCase());
- newInfo.setAge(info.getAge() + 10);
- newInfo.setPlace("Home");
- return newInfo;
- }
- };
- }
一目了然,服务端主要的功能就是实现了aidl中的getServerHarlanInfo(HarlanInfo info, ICallBack icallback)接口.返回了一个mBinder供客户端调用.
写好了服务,还得在Manifest文件里面配置一下:
[java] view plaincopyprint?
- <service
- android:name=".AIDLService">
- <intent-filter>
- <action android:name="com.harlan.demo.aidl.service"/>
- </intent-filter>
- lt;/service>
服务端写好了,就来客户端的了.客户端主要是一个activity,界面相对简单,如图所示:
界面布局相对简单,就不贴代码了.
下面贴ClientActivity的代码:
[java] view plaincopyprint?
- package com.harlan.demo.activity;
- import android.app.Activity;
- import android.content.ComponentName;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.os.Bundle;
- import android.os.IBinder;
- import android.os.RemoteException;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.Toast;
- import com.harlan.demo.aidl.ExecuteServiceAIDL;
- import com.harlan.demo.aidl.HarlanInfo;
- import com.harlan.demo.aidl.ICallBack;
- public class ClientActivity extends Activity
- {
- public static final String TAG = "ClientActivity";
- private static final String BIND_ACTION = "com.harlan.demo.aidl.service";
- private EditText mEditTextName;
- private EditText mEditTextAge;
- private EditText mEditTextPlace;
- private Button mButtonCommit;
- private ExecuteServiceAIDL executeService;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_client);
- getView();
- //用户点击提交按钮,将数据传至服务端进行处理
- mButtonCommit.setOnClickListener(new View.OnClickListener()
- {
- @Override
- public void onClick(View v)
- {
- //绑定服务
- getServiceConnect();
- }
- });
- }
- private void getView()
- {
- 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);
- }
- private void getServiceConnect()
- {
- Intent it = new Intent();
- it.setAction(BIND_ACTION);
- startService(it);
- bindService(it, mserviceConnection, BIND_AUTO_CREATE);
- }
- ServiceConnection mserviceConnection = new ServiceConnection()
- {
- @Override
- public void onServiceDisconnected(ComponentName name)
- {
- Log.d(TAG, "onServiceDisconnected");
- }
- @Override
- public void onServiceConnected(ComponentName name, IBinder service)
- {
- Log.d(TAG, "onServiceConnected");
- //获取服务端传过来的IBinder对象,通过该对象调用服务端的方法
- executeService = ExecuteServiceAIDL.Stub.asInterface(service);
- if (executeService != null)
- {
- handlerInfo();
- }
- }
- };
- private void handlerInfo()
- {
- String mName;
- int mAge;
- String mPlace;
- 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();
- }
- HarlanInfo mInfo = new HarlanInfo();
- mInfo.setName(mName);
- mInfo.setAge(mAge);
- mInfo.setPlace(mPlace);
- try
- {
- HarlanInfo serverInfo = new HarlanInfo();
- //调用服务端的方法
- serverInfo = executeService.getServerHarlanInfo(mInfo, mCallBack);
- //更新界面
- mEditTextName.setText(serverInfo.getName());
- mEditTextAge.setText(String.valueOf(serverInfo.getAge()));
- mEditTextPlace.setText(serverInfo.getPlace());
- unbindService(mserviceConnection);
- }
- catch (RemoteException e)
- {
- e.printStackTrace();
- }
- }
- ICallBack.Stub mCallBack = new ICallBack.Stub()
- {
- //客户端回调方法的具体实现
- @Override
- public void handleByServer(String param)
- throws RemoteException
- {
- Toast.makeText(getApplicationContext(), param, Toast.LENGTH_LONG).show();
- }
- };
- }
服务端调用客户端回调方法,在界面上显示一个toast.客户端根据服务端传回来的数据,刷新界面.
最后运行结果如图所示:
具体的Demo已经上传至CSDN,下载地址:http://download.csdn.net/detail/singleton1900/4928804