AIDL实践二:自定义数据类型

来源:互联网 发布:2015全国交通事故数据 编辑:程序博客网 时间:2024/06/05 22:32

AIDL实践一:自定义类型传递

本文是慕课网视频的练习,视频网址:http://www.imooc.com/learn/606
- 开发工具: Android Studio

一.编写服务端:

  1. 创建项目
  2. 在java目录同级下创建aidl文件夹
    创建IPersonAidl.aidl文件,文件内容如下:
// IAddAidl.aidlpackage com.lyj.aidldemo2;// Declare any non-default types here with import statementsimport com.lyj.aidldemo2.Person;interface IPersonAidl {    //注意  in 表示输入,否则编译不过    List<Person> addPerson(in Person person);}

在java文件夹下创建类Person.java,有年龄和姓名两个字段,并实现Parcelable接口,代码如下:

//实现Parcelablepublic class Person implements Parcelable{    private int age;    private String name;    public Person(int age, String name) {        this.age = age;        this.name = name;    }    public Person(Parcel in) {    //注意,此处顺序要和writeToParcel中的顺序一致        age = in.readInt();        name = in.readString();    }    public static final Creator<Person> CREATOR = new Creator<Person>() {        @Override        public Person createFromParcel(Parcel in) {            return new Person(in);        }        @Override        public Person[] newArray(int size) {            return new Person[size];        }    };    @Override    public int describeContents() {        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeInt(age);        dest.writeString(name);    }//重写toString方法    @Override    public String toString() {        return "Person{" +                "age=" + age +                ", name='" + name + '\'' +                '}';    }}

在Aidl文件夹中创建Person.java同名的Person.aidl文件,文件内容如下:

package com.lyj.aidldemo2;parcelable Person;
  1. 在Java目录下创建远程服务IMyService,代码如下
public class IMyService extends Service {    private List<Person> persons;    @Nullable    @Override    public IBinder onBind(Intent intent) {        //绑定服务时初始化persons对象        persons = new ArrayList<Person>();        return iBinder;    }    //实例化iBinder对象,实现IPersonAidl的方法    private IBinder iBinder = new IPersonAidl.Stub(){        @Override        public List<Person> addPerson(Person person) throws RemoteException {            persons.add(person);            return persons;        }    };}

在这个类中,实现了IAddAidl中的方法,在客户端绑定服务的时候,返回iBinder

  1. 在Manifest中注册:
<service android:name=".MyService"            android:process=":remote"            android:exported="true"/>

process 表示是一个远程服务
exported属性值为true,表示其它app可以引用这个服务。

到目前为止,服务端的工作已经完成了。

二.客户端编写

  1. 新建一个项目或新建一个module,名字为client
  2. 将服务端的aidl文件夹拷贝到client下,和java目录同级,注意,拷贝后检查包名一定要和服务端的包名一样
  3. 在java下新建一个包,包名和服务端Person.java的包名一致,将person.java拷贝到此包下面,然后编译
  4. 编写客户端布局和代码
    • 布局就是两个edittext输入年龄和姓名,一个button点击时触发远程服务的addPerson方法,一个TextView显示结果,此处就略去
    • 代码如下:
public class MainActivity extends AppCompatActivity {    private EditText et_name,et_age;    private Button btn_print;    private TextView tv_content;    private IPersonAidl iPersonAidl;    private ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            iPersonAidl = IPersonAidl.Stub.asInterface(service);        }        @Override        public void onServiceDisconnected(ComponentName name) {            iPersonAidl = null;        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initAction();        bindService();    }    private void initAction() {        btn_print.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                String name = et_name.getText().toString().trim();                int age = Integer.parseInt(et_age.getText().toString().trim());                Person person = new Person(age,name);                try {                    List<Person> persons =  iPersonAidl.addPerson(person);                    tv_content.setText(persons.get(0).toString());                } catch (RemoteException e) {                    e.printStackTrace();                }            }        });    }    private void bindService() {        Intent intent = new Intent();        intent.setComponent(new ComponentName("com.lyj.aidldemo2","com.lyj.aidldemo2.IMyService"));        bindService(intent,conn, Context.BIND_AUTO_CREATE);    }    private void initView() {        et_age = (EditText) findViewById(R.id.et_age);        et_name = (EditText) findViewById(R.id.et_name);        btn_print = (Button) findViewById(R.id.btn_print);        tv_content = (TextView) findViewById(R.id.tv_content);    }    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(conn);    }}

首先,在onCreate()的时候绑定了服务
其次,在服务连接(onServiceConnect())时,获取IPersonAidl对象,
最后,在点击的时候,iAddAidl调用其addPerson(Person person)方法

三.运行

先运行服务端app,然后运行客户端app,在客户端的app中并未实现加到方法,却调用服务端的方法,实现了加的运算。

四.总结:

可以看到,自定义类型的传递和基本类型的传递还是很相似的,但是要注意一下几点:1. Person.java 和 Person.aidl文件名要相同,且Person.java中必须实现序列化2. aidi接口中要输入的参数前面要加 in ,否则编译不过,会报如下错误:
C:\LYJ\new\AidlDemo2\app\src\main\aidl\com\lyj\aidldemo2\IPersonAidl.aidl:9 parameter 1: 'Person person' can be an out parameter, so you must declare it as in, out or inout.Error:Execution failed for task ':app:compileDebugAidl'.> java.lang.RuntimeException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'C:\Users\yu\AppData\Local\Android\sdk\build-tools\22.0.1\aidl.exe'' finished with non-zero exit value 1
3. 在客户端拷贝包的时候一定要把aidl文件和java文件都拷过去,拷完检查包名是否完整
0 0
原创粉丝点击