• [ 转]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,已经从服务端得到了数据,第一句话就是从服务端得到的,下面看看,传递对象和获取对象与服务端。

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

              

  • 相关阅读:
    MSXML 解析XML文件
    内存泄露
    TCHAR CHAR LPTSTR LPCTSTR
    union过代理存根
    jquery placeholder
    SASS 编译后去掉缓存文件和map文件
    js冒泡排序
    android 下滤镜效果的实现
    ViewPagger介绍
    android下实现对wifi连接的监听
  • 原文地址:https://www.cnblogs.com/freeliver54/p/3007169.html
Copyright © 2020-2023  润新知