赞
踩
阅读本篇文章前, 请先查看一下笔者之前的写的两篇博客文章: Android Service知识 和 Android AIDL使用
进程间通信涉及到客户端和服务端, 肯定有绑定服务的过程, 所以要阅读一下Android Service相关的知识, 跨进程通信的媒介aidl文件,我们也必须要了解怎么创建的,有什么规则,所以请先阅读一下Android AIDL使用这篇文章.
本文重点讲解一下AIDL文件结构以及类中每个方法的含义. 然后把AIDL中每个方法的用途理解清楚后, 我们就不依赖AS自带的工具创建, 而是自己手动去写一个AIDL文件, 在手写的代码中添加自己的日志, 根据打印理清楚客户端与服务端跨进程通信的流程图, 目的加深对IPC机制的理解.
这是我创建的一个 IStudentService.aidl 里面有三个方法,然后build一下,系统自动为我们生成一个IStudentService.java类. 先大致看一下类结构和方法:
- public interface IStudentService extends android.os.IInterface {
- /**
- * Default implementation for IStudentService.
- */
- public static class Default implements com.example.mysevicejava.IStudentService {
- /**
- * Demonstrates some basic types that you can use as parameters
- * and return values in AIDL.
- *///定向tag
- @Override
- public java.lang.String getString() throws android.os.RemoteException {
- return null;
- }
-
- @Override
- public void addStudent(com.example.mysevicejava.Student student) throws android.os.RemoteException {
- }
- //void test(in PathParceTest obb);
-
- @Override
- public java.util.List<com.example.mysevicejava.Student> getStudentList() throws android.os.RemoteException {
- return null;
- }
-
- @Override
- public android.os.IBinder asBinder() {
- return null;
- }
- }
-
- /**
- * Local-side IPC implementation stub class.
- * 1. Stub是一个抽象类 最终的实现是在service中.
- * 2. 同时继承拓展了android.os.Binder.
- * 3. Stub 是 IStudentService接口的具体实现类.
- */
- public static abstract class Stub extends android.os.Binder implements com.example.mysevicejava.IStudentService {
- private static final java.lang.String DESCRIPTOR = "com.example.mysevicejava.IStudentService";
-
- /**
- * Construct the stub at attach it to the interface.
- */
- public Stub() {
- this.attachInterface(this, DESCRIPTOR);
- }
-
- /**
- * Cast an IBinder object into an com.example.mysevicejava.IStudentService interface,
- * generating a proxy if needed.
- 这个是方法是在静态抽象类 Stub中, 作用: 用于服务端的Binder对象转换成客户端所需的AIDL接口类型的对象, 此转换过程是区分进程的,如果Client 和 Service端在统一进程中, 那么此方法返回的就是服务端的Stub对象本身, 如果是跨进程的话, 则返回的是Stub.proxy对象.
- */
- public static com.example.mysevicejava.IStudentService asInterface(android.os.IBinder obj) {
- if ((obj == null)) {
- return null;
- }
- android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
- if (((iin != null) && (iin instanceof com.example.mysevicejava.IStudentService))) {
- return ((com.example.mysevicejava.IStudentService) iin);
- }
- return new com.example.mysevicejava.IStudentService.Stub.Proxy(obj);
- }
-
- @Override
- 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 {
- java.lang.String descriptor = DESCRIPTOR;
- switch (code) {
- case INTERFACE_TRANSACTION: {
- reply.writeString(descriptor);
- return true;
- }
- case TRANSACTION_getString: {
- data.enforceInterface(descriptor);
- java.lang.String _result = this.getString();
- reply.writeNoException();
- reply.writeString(_result);
- return true;
- }
- case TRANSACTION_addStudent: {
- data.enforceInterface(descriptor);
- com.example.mysevicejava.Student _arg0;
- if ((0 != data.readInt())) {
- _arg0 = com.example.mysevicejava.Student.CREATOR.createFromParcel(data);
- } else {
- _arg0 = null;
- }
- this.addStudent(_arg0);
- reply.writeNoException();
- return true;
- }
- case TRANSACTION_getStudentList: {
- data.enforceInterface(descriptor);
- java.util.List<com.example.mysevicejava.Student> _result = this.getStudentList();
- reply.writeNoException();
- reply.writeTypedList(_result);
- return true;
- }
- default: {
- return super.onTransact(code, data, reply, flags);
- }
- }
- }
-
- private static class Proxy implements com.example.mysevicejava.IStudentService {
- private android.os.IBinder mRemote;
-
- Proxy(android.os.IBinder remote) {
- mRemote = remote;
- }
-
- @Override
- public android.os.IBinder asBinder() {
- return mRemote;
- }
-
- public java.lang.String getInterfaceDescriptor() {
- return DESCRIPTOR;
- }
-
- /**
- * Demonstrates some basic types that you can use as parameters
- * and return values in AIDL.
- *///定向tag
- @Override
- public java.lang.String getString() 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);
- boolean _status = mRemote.transact(Stub.TRANSACTION_getString, _data, _reply, 0);
- if (!_status && getDefaultImpl() != null) {
- return getDefaultImpl().getString();
- }
- _reply.readException();
- _result = _reply.readString();
- } finally {
- _reply.recycle();
- _data.recycle();
- }
- return _result;
- }
-
- @Override
- public void addStudent(com.example.mysevicejava.Student student) 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 ((student != null)) {
- _data.writeInt(1);
- student.writeToParcel(_data, 0);
- } else {
- _data.writeInt(0);
- }
- boolean _status = mRemote.transact(Stub.TRANSACTION_addStudent, _data, _reply, 0);
- if (!_status && getDefaultImpl() != null) {
- getDefaultImpl().addStudent(student);
- return;
- }
- _reply.readException();
- } finally {
- _reply.recycle();
- _data.recycle();
- }
- }
- //void test(in PathParceTest obb);
-
- @Override
- public java.util.List<com.example.mysevicejava.Student> getStudentList() throws android.os.RemoteException {
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- java.util.List<com.example.mysevicejava.Student> _result;
- try {
- _data.writeInterfaceToken(DESCRIPTOR);
- boolean _status = mRemote.transact(Stub.TRANSACTION_getStudentList, _data, _reply, 0);
- if (!_status && getDefaultImpl() != null) {
- return getDefaultImpl().getStudentList();
- }
- _reply.readException();
- _result = _reply.createTypedArrayList(com.example.mysevicejava.Student.CREATOR);
- } finally {
- _reply.recycle();
- _data.recycle();
- }
- return _result;
- }
-
- public static com.example.mysevicejava.IStudentService sDefaultImpl;
- }
-
- static final int TRANSACTION_getString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
- static final int TRANSACTION_addStudent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
- static final int TRANSACTION_getStudentList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
-
- public static boolean setDefaultImpl(com.example.mysevicejava.IStudentService impl) {
- if (Stub.Proxy.sDefaultImpl == null && impl != null) {
- Stub.Proxy.sDefaultImpl = impl;
- return true;
- }
- return false;
- }
-
- public static com.example.mysevicejava.IStudentService getDefaultImpl() {
- return Stub.Proxy.sDefaultImpl;
- }
- }
-
- /**
- * Demonstrates some basic types that you can use as parameters
- * and return values in AIDL.
- *///定向tag
- public java.lang.String getString() throws android.os.RemoteException;
-
- public void addStudent(com.example.mysevicejava.Student student) throws android.os.RemoteException;
- //void test(in PathParceTest obb);
-
- public java.util.List<com.example.mysevicejava.Student> getStudentList() throws android.os.RemoteException;
- }
根据类结构图, 其实我们只需要搞明白这2个核心实现方法
1. 静态抽象类 Stub;
2. Stub的静态内部类Proxy ;
Question: 写到这里,提个问题,就是google工程师为什么要把 Stub类设计为抽象类啊?
Answer: Stub类extends android.os.Binder 并且 implement 你自定义的AIDL文件中的方法, 它的最终实现是在你的service代码中, 人家google工程师他们只能帮你把模板搭建好, 具体的业务逻辑肯定是自己去实现了.
在服务端中继承IStudentService.Stub这个抽象类, 并在 onBind回调方法中返回IBinder对象
- class MyBinder extends IStudentService.Stub{
-
- @Override
- public String getString() throws RemoteException {
- return "我是从服务端返回的数据: 111";
- }
-
- @Override
- public void addStudent(Student student) throws RemoteException {
- mStudentList.add(student);
- }
-
- @Override
- public List<Student> getStudentList() throws RemoteException {
- return mStudentList;
- }
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- Log.e("test", "==服务端==onBind========");
- // TODO: Return the communication channel to the service.
- return new MyBinder();
- }
这个IBinder对象对应的就是客户端中 IBinder service对象.
public void onServiceConnected(ComponentName componentName, IBinder service)
我们逐个来解析:
public interface IStudentService extends android.os.IInterface
2.1 首先IStudentService.java类继承与 IInterface这个接口
- package android.os;
-
- /**
- * Base class for Binder interfaces. When defining a new interface,
- * you must derive it from IInterface.
- Binder接口的基类。当定义新接口时,你必须继承它。
- */
- public interface IInterface
- {
- /**
- * Retrieve the Binder object associated with this interface.
- * You must use this instead of a plain cast, so that proxy objects
- * can return the correct result.
- 检索与此接口关联的Binder对象。
- 必须使用此方法转换,这样代理对象才能返回正确的结果
- */
- public IBinder asBinder();
- }
同时它自己也是一个接口, 所有可以在Binder中传输的接口都需要继承IInterface接口, 那么如果要自定义手写AIDL的话, 我们当然必须继承IInterface接口, 好到这里提炼第一条规则出来.
2.2 Binder的唯一标识, 一般用当前Binder的类名表示.
为了一个Binder和一个特定服务接口绑定,以对外提供功能,需要给Binder定义一个DESCRIPTOR
描述,表示我这个Binder是提供特定功能链接的,不是随便可以用的。
通常,DESCRIPTOR
描述会直接使用包名 + 服务接口
。
private static final java.lang.String DESCRIPTOR = "com.example.mysevicejava.IStudentService";
2.3 asInterface(android.os.IBinder obj)
这个是方法是在静态抽象类 Stub中, 作用: 用于服务端的Binder对象转换成客户端所需的AIDL接口类型的对象, 此转换过程是区分进程的,如果Client 和 Service端在统一进程中, 那么此方法返回的就是服务端的Stub对象本身, 如果是跨进程的话, 则返回的是Stub.proxy对象.
- public static com.example.mysevicejava.IStudentService asInterface(android.os.IBinder obj) {
- if ((obj == null)) {
- return null;
- }
- // queryLocalInterface是Binder的方法,搜索本地是否有可用的对象
- // DESCRIPTOR = "com.example.mysevicejava.IStudentService";
- android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
-
- //如果有,则强制类型转换并返回
- if (((iin != null) && (iin instanceof com.example.mysevicejava.IStudentService))) {
- return ((com.example.mysevicejava.IStudentService) iin);
- }
- // //如果没有,则构造一个IStudentService.Stub.Proxy对象
- return new com.example.mysevicejava.IStudentService.Stub.Proxy(obj);
- }
2.4 Stub的静态内部类Proxy
通过上面的new com.example.mysevicejava.IStudentService.Stub.Proxy(obj)调用过来的
- private static class Proxy implements com.example.mysevicejava.IStudentService{
-
- private android.os.IBinder mRemote;
-
- //构造方法
- Proxy(android.os.IBinder remote){
- mRemote = remote;
- }
-
- @Override public android.os.IBinder asBinder(){
- return mRemote;
- }
-
- public java.lang.String getInterfaceDescriptor(){
- return DESCRIPTOR;
- }
- .......
- .......
- }
通过代码,我们知道
1. Proxy 实现了 com.example.mysevicejava.IStudentService 里面的3个方法
2. Proxy的asBinder()方法返回的mRemote, mRemote是在Proxy(android.os.IBinder remote) 这个构造方法中赋值的.
3. 网上有另外的一种结论:
asInterface方法的主要作用:如果是多进程操作,参数obj是BinderProxy对象,就new一个proxy接口;通过调用new com.example.mysevicejava.IStudentService.Stub.Proxy(obj) 就可以知道
把BinderProxy对象保存到mRemote变量,mRemote在aidl中是一个辅助变量.
mRemote 就是 BinderProxy对象.
----- 这条结论再后面的文章中验证.先记住就可以了,
首先从字面上来理解一下: proxy是代理 Stub是存根
AIDL: Android interface Definition Language
如果你觉的AIDL中的proxy / stub 比较难理解的话,先触类旁通一下, 换个思维理解
MIDL:微软接口定义语言Microsoft interface Definition Language, 它是定义COM接口的说明性语言。 关于COM (Component Object Model),中文译为,组件对象模型, 它也是一种进程间通信接口, 具体用法参考: 理解Com(Component Object model) 这篇文章,但不是我们关注的重点, 我们只是借助于它来理解我们的AIDL中的 proxy-stub 模式 , 拿COM的通信模式图看一下:
打个比方,你到自动取款机上去取款
你不会在乎钱具体放在那里,你只想看到足够或更多的钱从出口出来(这就是com的透明性)。你同银行之间的操作完全是取款机代理实现。你的取款请求通过取款机,传到另一头,银行的服务器,他也没有必要知道你在哪儿取钱,他所关心的是你的身份,和你取款多少。当他确认你的权限,就进行相应的操作,返回操作结果给取款机,取款机根据服务器返回结果,从保险柜里取出相应数量的钱给你。你取出卡后,操作完成。取款机不是直接同服务器连接的,他们之间还有一个“存根”,取款机与存根通信,存根又与服务器通信。从某种意义上说存根就是服务器的代理。(参考COM代理与存根)
概念理解:
客户端: 自己
proxy : 取款机 ,可以理解为银行金融系统取款业务的代理
服务端: 银行金融系统
Stub: 取款凭证(显示交易时间,交易金额,存钱/取钱), 它作为银行金融系统的实体存根
再回到AIDLFramework层的架构,如下图:
换而言之,Android就是在传统的C/S架构中加入了一层,实现IPC。图中表明,AIDL类似COM的Proxy/Stub架构。不过是现在android自己的序列化类Pacel。
客户端的代码中调用
- @Override
- public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
- Log.e("test", " componentName :" + componentName);
- mIStudentService = IStudentService.Stub.asInterface(iBinder);
- }
我们再回到2.3 asInterface(android.os.IBinder obj) 这个方法中来
从字面意思看,Stub是存根,Proxy是代理,而这个Stub是谁的存根呢?Proxy又是谁的代理呢?
我理解的是 :
Stub是 服务端Binder实体的存根.
Proxy则是Stub的代理.
Stub类: 服务实体,Binder的实现类,服务端一般会实例化一个Binder对象,在服务端onBind中绑定, 客户端asInterface获取到Stub。 这个类在编译aidl文件后自动生成,它继承自Binder,表示它是一个Binder本地对象; 它是一个抽象类,实现了IInterface接口,表明它的子类需要实现Server将要提供的具体能力(即aidl文件中声明的方 法)
我们先来看一下代码目录结构:
分为4个部分:客户端, 服务端 , 手写AIDL文件, javabean类
直接上代码:
1. 客户端ClientActivity.java
- /**
- * @ProjectName: WriteAIDLTest
- * @PackageName: com.example.writeaidltest
- * @Description: java类作用描述
- * @Author: 作者名
- * @CreateDate: 23-3-13 下午1:55
- * @Version: 1.0
- */
- public class ClientActivity extends Activity {
-
- private Intent intent;
-
- private IStudent mIStudent;
-
- //是否绑定成功
- boolean mBound = false;
-
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- intent = new Intent(this, MyServer.class);
-
- Button btn = (Button)findViewById(R.id.button);
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if(mBound) {
- try {
- Log.e("test", "mIStudent.getString() 当前线程 :" + Thread.currentThread().getName());
- String text = mIStudent.getString();
- Log.e("test", "mIStudent.getString() after ");
- Toast.makeText(ClientActivity.this, "内容: " + text, Toast.LENGTH_SHORT).show();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
- }
- });
-
-
- Button btn1 = (Button)findViewById(R.id.button1);
- btn1.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if(mBound) {
- try {
- mIStudent.addStudent(new Student(3, "王五"));
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
- }
- });
-
- Button btn2 = (Button)findViewById(R.id.button2);
- btn2.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if(mBound) {
- try {
- Log.e("test", "获取服务端所有学生的信息: "+mIStudent.getStudentList());
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
- }
- });
-
- }
-
-
-
- private ServiceConnection connection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName componentName, IBinder service) {
- Log.e("test", "===客户端===onServiceConnected=====service是一个什么对象: ="+service.getClass().getCanonicalName());
- mBound = true;
- mIStudent = Stub.asInterface(service);
- Log.e("test", "===客户端 mIStudent是一个什么对象:" + mIStudent.getClass().getCanonicalName());
- }
-
- @Override
- public void onServiceDisconnected(ComponentName componentName) {
- Log.e("test", "====onServiceDisconnected=====");
- mBound = false;
- }
- };
-
- //在onstart方法中 调用 bindservice 绑定服务
- @Override
- protected void onStart() {
- super.onStart();
- bindService(intent, connection, Context.BIND_AUTO_CREATE);
- }
-
- //在onstop方法中, 调用unbindservice 解绑服务
- @Override
- protected void onStop() {
- super.onStop();
- unbindService(connection);
- mBound = false;
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- }
- }
2. 服务端代码MyServer.java
- /**
- * @ProjectName: WriteAIDLTest
- * @PackageName: com.example.writeaidltest.service
- * @Description: java类作用描述
- * @Author: 作者名
- * @CreateDate: 23-3-13 下午3:12
- * @Version: 1.0
- */
- public class MyServer extends Service {
-
- private List<Student> mStudentList = new ArrayList<>();
-
- @Override
- public void onCreate() {
- super.onCreate();
- mStudentList.add(new Student(1, "张三"));
- mStudentList.add(new Student(2, "李四"));
- }
-
- @Nullable
- @Override
- public IBinder onBind(Intent intent) {
- Log.e("test", "==服务端==onBind===new MyBinder()是一个什么对象====="+new MyBinder().getClass().getCanonicalName());
- //return new MyBinder();
- Log.e("test", "==服务端==onBind==myBinder是一个什么对象====="+myBinder.toString());
- return myBinder;
- }
-
- IBinder myBinder = new Stub() {
- @Override
- public String getString() throws RemoteException {
- return "服务端数据 777";
- }
-
- @Override
- public void addStudent(Student student) throws RemoteException {
- mStudentList.add(student);
- }
-
- @Override
- public List<Student> getStudentList() throws RemoteException {
- return mStudentList;
- }
- };
-
- class MyBinder extends Stub{
- @Override
- public String getString() throws RemoteException {
- return "服务端数据 111";
- }
-
- @Override
- public void addStudent(Student student) throws RemoteException {
- mStudentList.add(student);
- }
-
- @Override
- public List<Student> getStudentList() throws RemoteException {
- return mStudentList;
- }
- }
-
- @Override
- public void onDestroy() {
- Log.e("test", "==服务端=onDestroy=====");
- super.onDestroy();
- }
-
-
-
- }
3. 序列化 Student.java
- public class Student implements Parcelable {
-
- private int id;
- private String name;
-
- public Student(int id, String name) {
- this.id = id;
- this.name = name;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(id);
- dest.writeString(name);
- }
-
- public void readFromParcel(Parcel parcel) {
- this.id = parcel.readInt();
- this.name = parcel.readString();
- }
-
- public static Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {
- @Override
- public Student createFromParcel(Parcel source) {
- return new Student(source);
- }
-
- @Override
- public Student[] newArray(int size) {
- return new Student[0];
- }
- };
-
- private Student(Parcel in) {
- this.id = in.readInt();
- this.name = in.readString();
- }
-
- @Override
- public String toString() {
- return "Student{" +
- "id=" + id +
- ", name='" + name + '\'' +
- '}';
- }
- }
4. 最重要,手动仿写AIDL文件 IStudent.java
相当于 IStudent.aidl 文件用安卓自带工具生成 IStudent.java
- /**
- * @ProjectName: WriteAIDLTest
- * @PackageName: com.example.writeaidltest.aidlfile
- * @Description: 手动仿写AIDL文件
- * @Author: 作者名
- * @CreateDate: 23-3-13 下午1:58
- * @Version: 1.0
- */
-
- public interface IStudent extends android.os.IInterface {
- //定义一个DESCRIPTOR
- //意图: 为了一个Binder和一个特定服务接口绑定,以对外提供功能,需要给Binder定义一个DESCRIPTOR描述,表示我这个Binder是提供特定功能链接的,不是随便可以用的
- public static final java.lang.String DESCRIPTOR = "com.example.writeaidltest.aidlfile.IStudentService";
-
-
- //定义操作数据的方法
- //1. 从服务端获取一个简单的字符串
- String getString() throws RemoteException;
-
- //2. 客户端往服务端 添加student对象
- void addStudent(Student student) throws RemoteException;
-
- //3. 客户端从服务段获取 所有Student的信息
- List<Student> getStudentList() throws RemoteException;
-
-
-
-
- //定义方法的id号
- static final int TRANSACTION_getString = IBinder.FIRST_CALL_TRANSACTION + 0;
- static final int TRANSACTION_addStudent = IBinder.FIRST_CALL_TRANSACTION + 1;
- static final int TRANSACTION_getStudentList = IBinder.FIRST_CALL_TRANSACTION + 2;
- }
手动仿写AIDL文件 Stub.java
抽象类 Stub
- public abstract class Stub extends android.os.Binder implements IStudent{
-
- //构造方法
- public Stub() {
- this.attachInterface(this, DESCRIPTOR);
- }
-
- public static IStudent asInterface(IBinder obj) {
-
- if (obj == null) {
- return null;
- }
-
- IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
- if (iin != null && (iin instanceof IStudent)) {
- return (IStudent)iin;
- }
-
- // 传入binder对象,返回一个服务代理对象
- return new Proxy(obj);
-
- }
-
- @SuppressLint("NewApi")
- @Override
- protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
- switch (code) {
- case INTERFACE_TRANSACTION:
- reply.writeString(DESCRIPTOR);
- return true;
-
- case TRANSACTION_getString:
- // 获取IBinder接口标志
- data.enforceInterface(DESCRIPTOR);
- //这个是服务端自己实现getString方法,获取返回值
- String stringResult = this.getString();
- Log.e("test", " stub onTransact 当前线程: "+Thread.currentThread().getName());
- reply.writeNoException();
- reply.writeString(stringResult);
- return true;
-
- case TRANSACTION_addStudent:
- // 获取IBinder接口标志
- data.enforceInterface(DESCRIPTOR);
- // 获取传入的Student对象
- Student arg0 = null;
- if (data.readInt() != 0) {
- arg0 = Student.CREATOR.createFromParcel(data);
- }
- this.addStudent(arg0);
- reply.writeNoException();
- return true;
-
- case TRANSACTION_getStudentList:
- data.enforceInterface(DESCRIPTOR);
- //
- List<Student> studentList = null;
- studentList = this.getStudentList();
- reply.writeNoException();
- reply.writeTypedList(studentList);
- return true;
- }
- return super.onTransact(code, data, reply, flags);
- }
-
- @Override
- public IBinder asBinder() {
- return this;
- }
- }
手动仿写 Proxy.java
- public class Proxy implements IStudent{
-
- private IBinder mRemote;
-
- public Proxy(IBinder remote) {
- mRemote = remote;
- Log.e("test", "===Proxy中 mRemote 是一个什么对象: " + mRemote.getClass().getCanonicalName());
- }
-
-
-
- @Override
- public String getString() throws RemoteException {
-
- Parcel data = Parcel.obtain(); // 跨进程传输数据对象
- Parcel reply = Parcel.obtain(); // 跨进程传输返回结果
- java.lang.String _result;
- try {
- data.writeInterfaceToken(DESCRIPTOR);
- // 调Stub的onTransact方法进行Stub.TRANSACTION_getString,远端返回
- Log.e("test", "mRemote transact 当前线程 :" + Thread.currentThread().getName());
- mRemote.transact(TRANSACTION_getString, data, reply, 0);
-
- reply.readException();
- _result = reply.readString();
-
- }finally {
- data.recycle();
- reply.recycle();
- }
- return _result;
- }
-
- @Override
- public void addStudent(Student student) throws RemoteException {
- Parcel data = Parcel.obtain(); // 跨进程传输数据对象
- Parcel reply = Parcel.obtain(); // 跨进程传输返回结果
- try{
- // 写入IBinder接口标志,一般为全类名,用户数据校验
- data.writeInterfaceToken(DESCRIPTOR);
- if (student != null){
- //写入数据
- data.writeInt(1);
- student.writeToParcel(data, 0);
- } else {
- data.writeInt(0);
- }
- // 调Stub的onTransact方法进行Stub.TRANSACTION_addBook处理,远端返回
- mRemote.transact(Stub.TRANSACTION_addStudent, data, reply, 0);
- reply.readException();
- } finally {
- data.recycle();
- reply.recycle();
- }
- }
-
- @Override
- public List<Student> getStudentList() throws RemoteException {
- Parcel data = Parcel.obtain(); // 跨进程传输数据对象
- Parcel reply = Parcel.obtain(); // 跨进程传输返回结果
-
- List<Student> result;
- try {
- // 写入IBinder接口标志,一般为全类名,用户数据校验
- data.writeInterfaceToken(DESCRIPTOR);
- // 调Stub的onTransact方法进行Stub.TRANSACTION_getStudentList,远端返回
- mRemote.transact(TRANSACTION_getStudentList, data, reply, 0);
- reply.readException();
- result = reply.createTypedArrayList(Student.CREATOR);
- } finally {
- reply.recycle();
- data.recycle();
- }
-
- return result;
- }
-
-
- // 返回Stub类传入的Binder对象
- @Override
- public IBinder asBinder() {
- return mRemote;
- }
-
- public java.lang.String getInterfaceDescriptor() {
- return DESCRIPTOR;
- }
- }
清单AndroidManifest.xml 文件
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.writeaidltest">
-
- <application
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:roundIcon="@mipmap/ic_launcher_round"
- android:supportsRtl="true"
- android:theme="@style/Theme.WriteAIDLTest">
- <activity android:name=".client.ClientActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
-
- <!-- service 运行在另外一个进程中 -->
- <service
- android:name=".service.MyServer"
- android:exported="true"
- android:enabled="true"
- android:process=":remote">
- <intent-filter>
- <action android:name="com.my.binder" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </service>
- </application>
-
上面的例子是模拟进程间通信的整个过程,可以通过log看出客户端发送数据给服务端,然后服务端处理之后再返回给客户端的整个流程。
大家可以通过这个Demo去学习AIDL的原理,供参考!
Demo 已上传: https://download.csdn.net/download/u012514113/87906468
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。