欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android进程通信(AIDL快速实现inder进程通信)

程序员文章站 2022-09-02 21:05:47
AIDL概念Android提供的一种快速实现binder进程通信的工具,也可以不用AIDL,自己实现binder来达到同样的效果,但是会比较复杂,后面我会写文章来细说。AIDL支持的基本类型 : String,int,long,boolean,float,double,ArrayList,HashMap,Parcelable为什么要用AIDL因为可以让我们更轻松的使用binder,专注写client、service,而不必太关心ServiceManager、Binder驱动,那么问题又来了,...

AIDL概念

Android提供的一种快速实现binder进程通信的工具,也可以不用AIDL,自己实现binder来达到同样的效果,但是会比较复杂,后面我会写文章来细说。

AIDL支持的数据类型 : String,int,long,boolean,float,double,ArrayList,HashMap,Parcelable等

为什么要用AIDL

因为可以让我们更轻松的使用binder,专注写client、service,而不必关心ServiceManager、Binder驱动,那么问题又来了,为什么要用binder来进程通信呢?后续有文章单独来说,那问题又又来了,Android为什么需要进程通信呢?进程通信的方式有哪些呢?一个个问题是不是纷至沓来,感觉压的自己透不过气,一定要知道个所以然呢?客官莫急,且听我细细道来。但是当前第一步就是要学会用AIDL实现跨进程的通信!

第一步

Android进程通信(AIDL快速实现inder进程通信)

新建AIDL文件,会在src/main下面自动新建一个叫aidl的文件夹

// Declare any non-default types here with import statements /**除了默认的基本类型,就是下面直接生成出来的方法自带的这6种类型不需要import之外,其他的都需要手动import
 - 其他类型包括下面几种:
*List 接口(会自动将List接口转为 ArrayList),且集合的每个元素都必须要么是基本类型,要么是Parcelable实现类
*Map 接口(会自动将 Map 接口转为 HashMap),且每个元素的 key 和 value 要么是基本类型,要么是Parcelable实现类
*Parcelable 的实现类
*AIDL 接口本身
*/ import com.ly.aidltest.Student; interface IMyAidlInterface { /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     * 默认的方法不用管
     */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); //定义两个方法,也就是提供给客户端的服务 List<Student> getStudent(); //这里的in 是有讲究的 void addStudent(in Student stu); } 
注意事项

所有非基本类型的参数都需要标签来表明这个数据的去向:

  • in,表示此变量由客户端设置
  • out,表示此变量由服务端设置
  • inout,表示此变量可由客户端和服务端设置

此时可以rebuild一下
Android进程通信(AIDL快速实现inder进程通信)

第二步

定义上面AIDL文件用到的java对象

public class Student implements Parcelable { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } protected Student(Parcel in) { name = in.readString(); age = in.readInt(); } public static final Creator<Student> CREATOR = new Creator<Student>() { @Override public Student createFromParcel(Parcel in) { return new Student(in); } @Override public Student[] newArray(int size) { return new Student[size]; } }; public String getName() { return name; } public void setName(String name) { this.name = name; } 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.writeInt(age); } } 

除了定义Java对象之外,还需要一步,复制第一步新建的xxx.aidl文件,重命名为java对象同样的名字:
Android进程通信(AIDL快速实现inder进程通信)

第三步

新建service服务端

public class MyService extends Service { private List<Student> list = new ArrayList<>(); private static final String TAG = "MyService"; @Override public void onCreate() { super.onCreate(); Log.e(TAG, "onCreate: "); list.add(new Student("小明", 12)); list.add(new Student("小红", 13)); list.add(new Student("小军", 14)); } private IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public List<Student> getStudent() throws RemoteException { return list; } @Override public void addStudent(Student stu) throws RemoteException { Log.e(TAG, "setStudent: " ); list.add(stu); } }; @Nullable @Override public IBinder onBind(Intent intent) { Log.e(TAG, "onBind: " ); return mBinder; } } 

并在manifest里面声明

<service android:name=".MyService"/> 

第四步

客户端启动服务端

public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private IMyAidlInterface sub; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { sub = IMyAidlInterface.Stub.asInterface(service); try { List<Student> list = sub.getStudent(); for(Student s : list){ Log.e(TAG, "onServiceConnected: "+s.getName()+" age:"+s.getAge()); } } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindService(new Intent(this,MyService.class),connection,BIND_AUTO_CREATE); } } 

达到的初步结果就是
客户端可以跨进程拿到服务端的数据
可以测试一下
Android进程通信(AIDL快速实现inder进程通信)
Android进程通信(AIDL快速实现inder进程通信)

补充点
//manifest中: <service
            android:name=".MyService" android:process=":another"> <intent-filter> <action android:name="com.ly.aidltest.MyService" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service> //activity中: Intent intent = new Intent(); //5.0之后如果使用隐式启动service需要加上package,防止冲突,当然如果启动的是别的APP的service,要用目标的名字 intent.setPackage(getPackageName()); intent.setAction("com.ly.aidltest.MyService"); bindService(intent,connection,BIND_AUTO_CREATE); 
  1. Service可以通过隐式启动
  2. 若客户端组件和服务分开在不同APP,必须要把该Parcelable实现类.java文件拷贝到客户端所在的APP,包路径要一致

本文地址:https://blog.csdn.net/u012346890/article/details/107787568