当前位置:   article > 正文

Android中AIDL的简单使用(Hello world)_android aidl使用

android aidl使用

AIDL:Android Interface Definition Language(Android接口定义语言)

作用:跨进程通讯。如A应用调用B应用提供的接口

代码实现过程简述:

A应用创建aidl接口,并且创建一个Service来实现这个接口(在onBind方法里面return我们这个接口的实例)。

把A应用创建的aidl文件原封不动的搬至B应用中(注意包名类名都要一样),B应用bindService的方式来绑定A应用创建的这个Service,从而调用A应用提供的接口。

实现:

一、A应用(服务端)(提供接口被调用者):

1、创建AIDL文件:

Android Studio在项目main目录右键新建,找到AIDL,它会帮我们创建文件夹和文件,默认名字IMyAidlInterface,开发者根据需求修改名字

里面有:

  1. interface IMyAidlInterface {
  2. /**
  3. * Demonstrates some basic types that you can use as parameters
  4. * and return values in AIDL.
  5. */
  6. void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
  7. double aDouble, String aString);
  8. //上面这个是新建的时候自己生成的,可以去掉,我们自己新建以下方法,一个get(从服务端取值),一个set(传值给服务端)
  9. String getHelloString();
  10. void setHelloString(String string);
  11. }

写了之后make project一下,会自动生成IMyAidlInterface类。

2、创建service:(不需要A应用手动startService,B应用bindService的时候这个服务就会自动起来)

  1. public class AidlTestService extends Service {
  2. private String hello;
  3. @Override
  4. public void onCreate() {
  5. super.onCreate();
  6. hello = "hello";
  7. }
  8. @Nullable
  9. @Override
  10. public IBinder onBind(Intent intent) {
  11. return new MyBinder();
  12. }
  13. public class MyBinder extends IMyAidlInterface.Stub{
  14. @Override
  15. public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
  16. Log.i("xaeHu", "basicTypes: \nanInt = "+anInt
  17. +"\naLong = "+aLong
  18. +"\naBoolean = "+aBoolean
  19. +"\naFloat = "+aFloat
  20. +"\naDouble = "+aDouble
  21. +"\naString = "+aString
  22. );
  23. }
  24. @Override
  25. public String getHelloString() throws RemoteException {
  26. return hello;
  27. }
  28. @Override
  29. public void setHelloString(String string) throws RemoteException {
  30. hello = string;
  31. }
  32. }
  33. }

3、清单文件声明这个service:(网上有说这个name需要全称,我这里实际没有用全称也能绑定成功)

  1. <service android:name=".AidlTestService"
  2. android:enabled="true"
  3. android:exported="true" />

A应用的工作完成,接下来是B应用如何使用这个接口:

二、B应用(客户端)(接口调用者):

1、清单文件声明A应用的包名:(Android11新增,如果项目targetSdk>=30的话需要这一步,否则bindService是调不起来A应用的服务的)(这个坑网上很多AIDL的教程博客都没有说)

  1. <!-- 配置服务端的包名-->
  2. <queries>
  3. <package android:name="com.example.myapplication" />
  4. </queries>

2、把A应用创建的AIDL文件包括A应用包名一起复制到B应用main目录下:

我这边A应用包名是“com.example.myapplication”,B应用包名是“com.example.myapplication2”

 注意aidl的包名要与A应用一致,否者调用方法的时候会报异常:java.lang.SecurityException: Binder invocation to an incorrect interface

放进来之后make project一下,会自动生成IMyAidlInterface类。

3、绑定服务,调用aidl接口提供的方法:

比如直接在MainActivity的onCreate里面去绑定服务:

  1. public class MainActivity extends AppCompatActivity{
  2. private IMyAidlInterface myAidlInterface;
  3. private final ServiceConnection connection = new ServiceConnection() {
  4. @Override
  5. public void onServiceConnected(ComponentName name, IBinder service) {
  6. myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
  7. }
  8. @Override
  9. public void onServiceDisconnected(ComponentName name) {
  10. myAidlInterface = null;
  11. }
  12. };
  13. @Override
  14. protected void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.activity_main);
  17. //点击按钮一去绑定服务
  18. findViewById(R.id.btn1).setOnClickListener(v -> {
  19. Intent intent = new Intent();
  20. intent.setComponent(new ComponentName("com.example.myapplication","com.example.myapplication.AidlTestService"));
  21. boolean re = bindService(intent, connection, Context.BIND_AUTO_CREATE);
  22. Log.i("xaeHu", "bindService: "+re);
  23. });
  24. //点击按钮2调用set方法
  25. findViewById(R.id.btn2).setOnClickListener(v -> {
  26. if(myAidlInterface != null){
  27. try {
  28. myAidlInterface.setHelloString("hello world");
  29. } catch (RemoteException e) {
  30. e.printStackTrace();
  31. }
  32. }else {
  33. Log.e("xaeHu", "btn2 onclick: myAidlInterface == null");
  34. }
  35. });
  36. //点击按钮3调用get方法
  37. findViewById(R.id.btn3).setOnClickListener(v -> {
  38. if(myAidlInterface != null){
  39. try {
  40. Toast.makeText(this, myAidlInterface.getHelloString(), Toast.LENGTH_SHORT).show();
  41. } catch (RemoteException e) {
  42. e.printStackTrace();
  43. }
  44. }else {
  45. Log.e("xaeHu", "btn3 onclick: myAidlInterface == null");
  46. }
  47. });
  48. }
  49. @Override
  50. protected void onDestroy() {
  51. super.onDestroy();
  52. unbindService(connection);
  53. }
  54. }

简单的AIDL调用就搞定啦。

进阶:

上面的演示是传递基本数据类型为参数的,接下来通过AIDL传递对象

先在aidl文件夹中创建实体对象文件,再在java文件夹中创建实体类,不然的话在java中创建了实体类,再在aidl中创建相同的名字会提示错误。

A应用中:

比如我们创建Student对象,在aidl文件夹中就是Student.aidl,里面代码很简单:

  1. package com.example.myapplication;
  2. parcelable Student;

然后再在java中创建Student.java,注意需要实现Parcelable:

  1. public class Student implements Parcelable {
  2. private int id;
  3. private String name;
  4. private int age;
  5. private int sex;
  6. public Student() {
  7. }
  8. public Student(int id, String name, int age, int sex) {
  9. this.id = id;
  10. this.name = name;
  11. this.age = age;
  12. this.sex = sex;
  13. }
  14. protected Student(Parcel in) {
  15. id = in.readInt();
  16. name = in.readString();
  17. age = in.readInt();
  18. sex = in.readInt();
  19. }
  20. public static final Creator<Student> CREATOR = new Creator<Student>() {
  21. @Override
  22. public Student createFromParcel(Parcel in) {
  23. return new Student(in);
  24. }
  25. @Override
  26. public Student[] newArray(int size) {
  27. return new Student[size];
  28. }
  29. };
  30. public String getName() {
  31. return name;
  32. }
  33. public int getAge() {
  34. return age;
  35. }
  36. public int getSex() {
  37. return sex;
  38. }
  39. public int getId() {
  40. return id;
  41. }
  42. @Override
  43. public int describeContents() {
  44. return 0;
  45. }
  46. @Override
  47. public void writeToParcel(@NonNull Parcel dest, int flags) {
  48. dest.writeInt(id);
  49. dest.writeString(name);
  50. dest.writeInt(age);
  51. dest.writeInt(sex);
  52. }
  53. @Override
  54. public String toString() {
  55. return "Student{" +
  56. "id=" + id +
  57. ", name='" + name + '\'' +
  58. ", age=" + age +
  59. ", sex=" + sex +
  60. '}';
  61. }
  62. }

在aidl接口中添加方法:(注意addStudent(in Student student);参数需要添加in表示接收参数,另外有out、inout)

  1. // IMyAidlInterface.aidl
  2. package com.example.myapplication;
  3. import com.example.myapplication.Student;
  4. // Declare any non-default types here with import statements
  5. interface IMyAidlInterface {
  6. /**
  7. * Demonstrates some basic types that you can use as parameters
  8. * and return values in AIDL.
  9. */
  10. void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
  11. double aDouble, String aString);
  12. String getHelloString();
  13. void setHelloString(String string);
  14. void addStudent(in Student student);
  15. Student getStudent(int id);
  16. }

服务中实现这两个方法:

  1. private Map<Integer,Student> studentMap;
  2. @Override
  3. public void addStudent(Student student) throws RemoteException {
  4. Log.i("xaeHu", "addStudent: "+student);
  5. if(studentMap == null){
  6. studentMap = new HashMap<>();
  7. }
  8. studentMap.put(student.getId(), student);
  9. }
  10. @Override
  11. public Student getStudent(int id) throws RemoteException {
  12. if(studentMap != null){
  13. Student student = studentMap.get(id);
  14. Log.i("xaeHu", id + " -> getStudent: "+student);
  15. return student;
  16. }
  17. Log.i("xaeHu", id + " -> getStudent: null");
  18. return null;
  19. }

B应用:

同样的把aidl文件和类搬过来,注意实体对象的包名需要与A应用包名一致:

然后同样的,在绑定服务之后就可以调用了:

  1. myAidlInterface.addStudent(new Student(1,"student1",26,0));
  2. myAidlInterface.addStudent(new Student(2,"student2",27,1));
  3. Log.i("xaeHu", "getStudent1: "+myAidlInterface.getStudent(1));
  4. Log.i("xaeHu", "getStudent2: "+myAidlInterface.getStudent(2));

 

完。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/245346
推荐阅读
相关标签
  

闽ICP备14008679号