[ 转]android开发AIDL实例

本文转自:http://blog.csdn.net/wangkuifeng0118/article/details/7277680

由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象。在Android平台,一个进程通常不能访问另一个进程的内存空间。但是android提供了AIDL可以用来进程间数据传递。

         AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
    AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。

          下面通过一个实例来演示AIDL,因为是进程之间数据传递,所以这里要使用建立android工程,一个是AIDL的服务端另一个是客户端.

          服务端的实现步骤:

        1.创建.aidl文件      IMyService.aidl

        

package cn.com.karl.aidl;
import cn.com.karl.aidl.Person;

interface IMyService {
     void savePersonInfo(in Person person);
     List<Person> getAllPerson();
     String sayHello();
}

 

     
       因为这里用到了Peson对象,所以要创建一个person类。Person类,是一个序列化的类,这里使用Parcelable 接口来序列化,是Android提供的一个比Serializable 效率更高的序列化类。

       

public class Person implements Parcelable {

    private String name;
    private String telNumber;
    private int age;

    public Person() {}

    public Person(Parcel pl){
            name = pl.readString();
            telNumber = pl.readString();
            age = pl.readInt();
    }

    public String getName() {
            return name;
    }

    public void setName(String name) {
            this.name = name;
    }

    public String getTelNumber() {
            return telNumber;
    }

    public void setTelNumber(String telNumber) {
            this.telNumber = telNumber;
    }

    public int getAge() {
            return age;
    }

    public void setAge(int age) {
            this.age = age;
    }

    @Override
    public int describeContents() {
            return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(name);
            dest.writeString(telNumber);
            dest.writeInt(age);
    }

    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {

            @Override
            public Person createFromParcel(Parcel source) {
                    return new Person(source);
            }

            @Override
            public Person[] newArray(int size) {
                    return new Person[size];
            }

    };
}

           然后创建Person.aidl文件,注意这里的parcelable小写。

         

  1. package cn.com.karl.aidl;  
  2. parcelable Person;  

        上面的IMyService.aidl保存以后会在gen的相应目录下启动生成如下代码:

 

Binder

package cn.com.karl.aidl;
public interface IMyService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements cn.com.karl.aidl.IMyService
{
private static final java.lang.String DESCRIPTOR = "cn.com.karl.aidl.IMyService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an cn.com.karl.aidl.IMyService interface,
* generating a proxy if needed.
*/
public static cn.com.karl.aidl.IMyService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof cn.com.karl.aidl.IMyService))) {
return ((cn.com.karl.aidl.IMyService)iin);
}
return new cn.com.karl.aidl.IMyService.Stub.Proxy(obj);
}
public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_savePersonInfo:
{
data.enforceInterface(DESCRIPTOR);
cn.com.karl.aidl.Person _arg0;
if ((0!=data.readInt())) {
_arg0 = cn.com.karl.aidl.Person.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.savePersonInfo(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getAllPerson:
{
data.enforceInterface(DESCRIPTOR);
java.util.List<cn.com.karl.aidl.Person> _result = this.getAllPerson();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_sayHello:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.sayHello();
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements cn.com.karl.aidl.IMyService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
public void savePersonInfo(cn.com.karl.aidl.Person person) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((person!=null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_savePersonInfo, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public java.util.List<cn.com.karl.aidl.Person> getAllPerson() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<cn.com.karl.aidl.Person> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getAllPerson, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(cn.com.karl.aidl.Person.CREATOR);
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public java.lang.String sayHello() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_sayHello, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_savePersonInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getAllPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_sayHello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
public void savePersonInfo(cn.com.karl.aidl.Person person) throws android.os.RemoteException;
public java.util.List<cn.com.karl.aidl.Person> getAllPerson() throws android.os.RemoteException;
public java.lang.String sayHello() throws android.os.RemoteException;
}

      因为sub类实现了Binder接口,所以以后会使用这个类。

 

         2.实现service类
         

public class RemoteService extends Service {

    private LinkedList<Person> personList = new LinkedList<Person>();
   
    @Override
    public IBinder onBind(Intent intent) {
            return mBinder;
    }

    private final IMyService.Stub mBinder = new IMyService.Stub(){

            @Override
            public void savePersonInfo(Person person) throws RemoteException {
                    if (person != null){
                            personList.add(person);
                    }
            }

            @Override
            public List<Person> getAllPerson() throws RemoteException {
                    return personList;
            }

@Override
public String sayHello() throws RemoteException {
// TODO Auto-generated method stub
return "欢迎你通过AIDL访问服务器端";
}
    };
}


         3.客户端实现步骤:

 

          首先建立一个项目,把服务端的

             包和类一起拷贝到客户端项目中。因为客户端要和服务端通信,必须要使用同一个aidl。

         然后构造客户端的activity类:

       

public class RemoteClientActivity extends Activity {
    /** Called when the activity is first created. */
private TextView textHello,textPerson;
private IMyService myService;
private Button btnSave;
private Button btnGet;
private static Boolean mIsRemoteBound=false;
private ServiceConnection conn=new ServiceConnection() {

@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
myService=null;
}

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
myService=IMyService.Stub.asInterface(service);
try {
textHello.setText(myService.sayHello());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        textHello=(TextView) this.findViewById(R.id.textHello);
        btnSave=(Button) this.findViewById(R.id.btnSave);
        btnGet=(Button) this.findViewById(R.id.btnGet);
        textPerson=(TextView) this.findViewById(R.id.textPerson);
        if(mIsRemoteBound){
        unbindService(conn);
        }else{
        Intent intent=new Intent("cn.com.karl.aidl.RemoteService");
        bindService(intent, conn, BIND_AUTO_CREATE);
        }
        mIsRemoteBound = !mIsRemoteBound;
        btnSave.setOnClickListener(new OnClickListener() {
          private int index = 0;

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
   Person person = new Person();
                   index = index + 1;
                   person.setName("Person" + index);
                   person.setAge(20);
                   person.setTelNumber("123456");
                   try {
                   myService.savePersonInfo(person);
                   } catch (RemoteException e) {
                           e.printStackTrace();
                   }
}
});
        btnGet.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
  List<Person> list = null;

                  try {
                          list = myService.getAllPerson();
                  } catch (RemoteException e) {
                          e.printStackTrace();
                  }

                  if (list != null){
                          StringBuilder text = new StringBuilder();

                          for(Person person : list){
                                  text.append("\n联系人:");
                                  text.append(person.getName());
                                  text.append("\n             年龄:");
                                  text.append(person.getAge());
                                  text.append("\n 电话:");
                                  text.append(person.getTelNumber());
                          }

                          textPerson.setText(text);
                  }else {
                          Toast.makeText(RemoteClientActivity.this, "得到数据出错",
                                          Toast.LENGTH_SHORT).show();
                  }
}
});
    }
}


              最后不要忘记注册service:

 

           

  <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".RemoteService">
            <intent-filter >
                <action android:name="cn.com.karl.aidl.RemoteService"></action>
            </intent-filter>
        </service>
    </application>


           启动service的时候使用了隐士意图。

 

          运行服务端工程.

        

         服务端已经启动,然后运行客户端工程:

        

         OK,已经从服务端得到了数据,第一句话就是从服务端得到的,下面看看,传递对象和获取对象与服务端。

          点击添加联系人,然后点击获取联系人按钮:

          

posted on 2013-04-08 12:10  freeliver54  阅读(506)  评论(0编辑  收藏  举报

导航