Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。
Aidl文件所在的包名和文件名要相同:
应为用到了parcelable接口,这里先说说它:
Parcelable接口
Android中实现序列化有两个选择:一是实现Serializable接口(是JavaSE本身就支持的),一是实现Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC))。实现Serializable接口非常简单,声明一下就可以了,而实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提高性能。
注:Android中Intent传递对象有两种方法:一是Bundle.putSerializable(Key,Object),另一种是Bundle.putParcelable(Key,Object)。当然这些Object是有一定的条件的,前者是实现了Serializable接口,而后者是实现了Parcelable接口。
HarlaInfo.Java:
package com.harlan.demo.aidl;
import android.os.Parcel;
import android.os.Parcelable;
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 parcel) {
this.name = parcel.readString();
this.age = parcel.readInt();
this.place = parcel.readString();
}
public int describeContents() {
return 0;
}
/**
* 将对象序列化为一个Parcel对象 可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,
* 再通过createFromParcel从流里读取对象 注意:写的顺序和读的顺序必须一致。
*/
public void writeToParcel(Parcel parcel, int arg1) {
parcel.writeString(name);
parcel.writeInt(age);
parcel.writeString(place);
}
public static final Parcelable.Creator<HarlanInfo> CREATOR = new Creator<HarlanInfo>() {
public HarlanInfo createFromParcel(Parcel parcel) {
HarlanInfo harlan=new HarlanInfo(parcel);
return harlan;
}
@Override
public HarlanInfo[] newArray(int size) {
// TODO Auto-generated method stub
return new HarlanInfo [size];
}
};
HarlanInfo.aidl
package com.harlan.demo.aidl;
parcelable HarlanInfo;
定义一个aidl文件,使client端利用回调拿到service的param参数;然后设置到toast上显示出来。
ICallBack.aidl:
package com.harlan.demo.aidl;
interface ICallBack{
void handleByServer(String param);
}
定义这个aidl文件,使client用harlanInfo(client)传数据和到service,service用harlanInfo(service)取得数据;
ExecuteServiceAIDL.aidl:
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);
}
ClientActivity.java:
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");
executeService = ExecuteServiceAIDL.Stub.asInterface(service);
if (executeService != null)
{
handlerInfo();
}
}
};
private void handlerInfo()
{
String mName;
int mAge;
String mPlace;
if (mEditTextName.getText().toString().equals(""))
{
mName = "孤独";
}
else
{
mName = mEditTextName.getText().toString();
}
if (mEditTextAge.getText().toString().equals(""))
{
mAge = 23;
}
else
{
mAge = Integer.parseInt(mEditTextAge.getText().toString());
}
if (mEditTextPlace.getText().toString().equals(""))
{
mPlace = "世界";
}
else
{
mPlace = mEditTextPlace.getText().toString();
}
//将数据传到harlanInfo中
HarlanInfo mInfo = new HarlanInfo();
mInfo.setName(mName);
mInfo.setAge(mAge);
mInfo.setPlace(mPlace);
try
{
HarlanInfo serverInfo = new HarlanInfo();
serverInfo = executeService.getServerHarlanInfo(mInfo, mCallBack);
//拿到service传回的数据
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();
}
};
}
AIDLService.Java:
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()
{
@Override
public HarlanInfo getServerHarlanInfo(HarlanInfo info, ICallBack icallback)
throws RemoteException
{
Log.d(TAG,"getServerHarlanInfo");
mCallBack = icallback;
//传参数给client
mCallBack.handleByServer("The msg is from server");
HarlanInfo newInfo = new HarlanInfo();
//通过HarlanInfo序列化数据 再传给client
newInfo.setName(info.getName()+"幸福");
newInfo.setAge(info.getAge() + 10);
newInfo.setPlace(info.getPlace()+"Home");
return newInfo;
}
};
}
效果图,布局文件自己写
ps:本人也是参考别人的例子写的,中间有解释不对的地方,望轻喷。。。。