Android AIDL详解

Android_AIDL

1.     AIDL (Android Interface DefinitionLanguage )接口描述语言

2.     AIDL 适用于 进程间通信,并且与Service端多个线程并发的情况,如果只是单个线程 可以使用 Messenger ,如果不需要IPC 可以使用Binder

3.     AIDL语法:基础数据类型都可以适用,List Map等有限适用。static field 不适用。

要使用AIDL我们需要两个应用程序,一个作为Service端,一个作为Client端。详细步骤如下:

基本使用步骤:

第一步:在Service端建立.aidl文件。实际实现的接口是在 gen中自动生成的对应的抽象内部类 Stub。注意:

1、导入包名,不能在src目录下创建,否则在实现的时候找到Stub类。

2如果有使用Object对象,需要该对象 implement Parcelable 接口,并且需要导入该接口包名+类名,如果是primitivetype 不需要这步。

3、定义方法名称。

4所有的.aidl文件以及需要传递的对象接口需要在Service 与Client中各一份,并且包名要和服务器端的一样(建议从服务器端拷贝)。

示例代码:

package com.example.android_aidl_host.aidl;

interface IRemoteService{

    int getId();

   void setId(int id);

}

第二步:在Service中实现.aidl 接口(通常在service中实现)。

 

public class MyHostService extends Service{

    privateint id;

 

    @Override

    publicIBinder onBind(Intent intent) {

       //TODO Auto-generated method stub

       returnbind;

    }

 

    privatefinal IRemoteService.Stub bind = new IRemoteService.Stub() {

 

       @Override

       publicint getId() throws RemoteException {

           //TODO Auto-generated method stub

           returnid;

       }

 

       @Override

       publicvoid setId(int id) throws RemoteException {

           //TODO Auto-generated method stub

           MyHostService.this.id= id;

       }

    };

}

注意:在服务器端建立好service要在manifest文件中进行注册,并且为其加上action属性。我的配置如下:

<serviceandroid:name="com.example.android_aidl_host.MyHostService">

            <intent-filter>

                //其它程序通过此入口获得数据,就好比ContentProvider

                <actionandroid:name="com.xz.apk"/>

            </intent-filter>

</service>

经过以上两步服务器的代码就已经完成了,就等其它进程来获取数据了。下面来写Client端的代码。

第一步:在Activity中通过Intent意图绑定service。

Intent service = new Intent("com.xz.apk");//必须与服务器端一致

bindService(service, new MyConn(),BIND_AUTO_CREATE);

第二步:获取服务返回的stub对象。

iService = IRemoteService.Stub.asInterface(service);

完整的Activity代码如下:

public class MainActivity extends Activity {

    //aidl文件生成的java文件名

IRemoteService iService;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

          //绑定service

        Intent service = new Intent("com.xz.apk");

        bindService(service, new MyConn(),BIND_AUTO_CREATE);

    }

    public void changId(View view) {

        switch (view.getId()) {

        case R.id.set://客户端的set按钮

            try {

                   //调用服务器端的setId()方法

                iService.setId(200);

            } catch (RemoteException e) {

                e.printStackTrace();

            }

            break;

        case R.id.get: //客户端的get按钮

            try {

                   //调用服务器端的getId()方法

                iService.getId();

                Log.e("DDDDD",iService.getId() + "");

            } catch (RemoteException e) {

                e.printStackTrace();

            }

            break;

        default:

            break;

        }

    }

    private class MyConn implements ServiceConnection {

        @Override

        public void onServiceConnected(ComponentName name, IBinder service){

           //通过自动生成的Stub内部类,调用asInterface()方法实例化IRemoteService对象

iService =IRemoteService.Stub.asInterface(service);

        }

        @Override

        public void onServiceDisconnected(ComponentName name) {

            // TODO Auto-generatedmethod stub

        }

    }

}

 

Demo2:通过AIDL传递对象(Person),此实例既传递了普通数据又传递了对象。

1、定义该对象Person,并实现Parcelable。

2、添加Person.aidl文件,并采用如下方式编写导入Person

   注意Person文件和Person.aidl文件必须放在同一个包中并且两者要同时存在,否则报错。

3、需要在引用到Person的.aidl文件中import+Person所在包名

4、需要在服务端和客户端都添加 Person.aidl与 Person.java文件并且需要一致。

Person类代码:

package com.example.android_aidl_mydemo_server.aidls;

import android.os.Parcel;

import android.os.Parcelable;

public class Person implements Parcelable {

    String name;

    int age;

    //省略了相应的getset方法

    /**

     * 在想要进行序列号传递的实体类内部一定要声明该常量。常量名只能是CREATOR,类型也必须是

     * Parcelable.Creator<T>

     */ 

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

       

         /***

         * 根据序列号的Parcel对象,反序列号为原本的实体对象

         * 读出顺序要和writeToParcel的写入顺序相同

         */ 

        public Person createFromParcel(Parcel in) {

//            String name =source.readString(); 

//              int age =source.readInt(); 

//              String sex =source.readString(); 

//              Beauty beauty =new Beauty(); 

//             beauty.setName(name); 

//              beauty.setAge(age); 

//             beauty.setSex(sex); 

//               

//              returnbeauty; 

            return new Person(in);

        }

        /**

         * 创建一个要序列号的实体类的数组,数组中存储的都设置为null

         */ 

        public Person[] newArray(int size) {

            return new Person[size];

        }

    };

    public Person() {   }

    private Person(Parcel in) {

        readFromParcel(in);

    }

    public int describeContents() {

        return 0;

    }

    public void readFromParcel(Parcel in) {

        age = in.readInt();

        name = in.readString();

    }

    /**

     * 将对象序列号dest 就是对象即将写入的目的对象 flags有关对象序列号的方式的标识

* 这里要注意,写入的顺序要和在createFromParcel方法中读出的顺序完全相同。例如这里先

*写入的为name

     * 那么在createFromParcel就要先读name

     */

    public void writeToParcel(Parcel dest, int flags) {

        dest.writeInt(age);

        dest.writeString(name);

    }

}

Person.aidl文件:

packagecom.example.android_aidl_mydemo_server.aidls;

parcelable Person;

InData.aidl文件:

packagecom.example.android_aidl_mydemo_server.aidls;

import com.example.android_aidl_mydemo_server.aidls.Person;

interface InData{

String getName();

void setName(String name);

Person getPerson();

}

服务器端的service文件:

package com.example.android_aidl_mydemo_server;

import com.example.android_aidl_mydemo_server.aidls.InData;

import com.example.android_aidl_mydemo_server.aidls.Person;

import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.os.RemoteException;

public class MyServer extends Service {

    String name = "JACK";

    @Override

    public IBinder onBind(Intent arg0) {

        // TODO Auto-generatedmethod stub

        returnbinder;

    }

 

    private final InData.Stub binder = new InData.Stub() {

        @Override

        public String getName()throws RemoteException {

            // TODO Auto-generatedmethod stub

            returnname;

        }

        @Override

        public void setName(String name) throws RemoteException {

            // TODO Auto-generatedmethod stub

            MyServer.this.name = name;

        }

        @Override

        publicPersongetPerson() throws RemoteException {

            // TODO Auto-generatedmethod stub

            Person person = new Person();

            return person;

        }

    };

}

一说到service我又想起了一定不要忘记在manifest注册并加上action属性!

客户端MainActivity的代码:

package com.example.android_aidl_mydemo_client;

 

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.Menu;

 

import com.example.android_aidl_mydemo_server.aidls.InData;

import com.example.android_aidl_mydemo_server.aidls.Person;

 

 

public class MainActivity extends Activity {

    InData inData;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

    Intentservice=newIntent("com.ssss.xz.apk");

    bindService(service, new MyConnection(),BIND_AUTO_CREATE);

    }

    private class MyConnection implements ServiceConnection{

 

        @Override

        public void onServiceConnected(ComponentName name, IBinder service){

            // TODO Auto-generatedmethod stub

            inData=InData.Stub.asInterface(service);

            try {

                Log.e("SSSSSS",inData.getName());

                inData.setName("Hello AIDL");

                Log.e("SSSSSS",inData.getName());

                Person user=inData.getPerson();

                Log.e("HHHHHHHH",user.getName());

                Log.e("HHHHHHHH",user.getAge()+"");

            } catch (RemoteException e) {

                // TODO Auto-generatedcatch block

                e.printStackTrace();

            }

       

        }

 

        @Override

        public void onServiceDisconnected(ComponentName name) {

            // TODO Auto-generatedmethod stub

            inData=null;

        }

    }

    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; thisadds items to the action bar if it is present.

        getMenuInflater().inflate(R.menu.main, menu);

        return true;

    }

}

在写这篇文章之前,看了相关的官方文档,在网上也查了相应的资料。当时有一篇文章写的很详细,但是现在忘记地址了,所以这篇文章可能会和大神写的有点类似,在此说声抱歉。但我保证两个Demo都是自己写的。OK,关于aidl我所知道的一切都已经说了。剩余的交给童鞋们了。

源码就不加了,上面都写的差不多了。

猜你喜欢

转载自blog.csdn.net/lmpt90/article/details/40212125