通过代码例子详解aidl跨进程通信的调用流程

Python实战社群

Java实战社群

长按识别下方..,按需求添加

扫码关注添加客服

进Python社群▲

扫码关注添加客服

进Java社群


作者丨张潮州 

来源丨Android技术堆栈

使用aidl进行跨进程通信

1、首先创建aidl文件,并声明接口:
// IRemoteService.aidl
package source.analysis.android29.aidl;
// Declare any non-default types here with import statements
parcelable User;

interface IRemoteService {
    int getValue();
    User getUser(in String username);
}

2、创建接口需要的Parcelable实体类:
public class User implements Parcelable {
    private int age;
    private String nickname;
    private int gender;

    public int getAge() {
        return age;
    }

    public User setAge(int age) {
        this.age = age;
        return this;
    }

    public String getNickname() {
        return nickname;
    }

    public User setNickname(String nickname) {
        this.nickname = nickname;
        return this;
    }

    public int getGender() {
        return gender;
    }
    
    public User setGender(int gender) {
        this.gender = gender;
        return this;
    }

    public User() {
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.age);
        dest.writeString(this.nickname);
        dest.writeInt(this.gender);
    }

    protected User(Parcel in) {
        this.age = in.readInt();
        this.nickname = in.readString();
        this.gender = in.readInt();
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel source) {
            return new User(source);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };
}

3、编译后自动生成接口和空的实体类:

IRemoteService

/*
 * This file is auto-generated.  DO NOT MODIFY.
 */

package source.analysis.android29.aidl;
// Declare any non-default types here with import statements

public interface IRemoteService extends android.os.IInterface {
    /**
     * Default implementation for IRemoteService.
     */

    public static class Default implements source.analysis.android29.aidl.IRemoteService {
        @Override
        public int getValue() throws android.os.RemoteException {
            return 0;
        }

        @Override
        public source.analysis.android29.aidl.User getUser(java.lang.String username) throws android.os.RemoteException {
            return null;
        }

        @Override
        public android.os.IBinder asBinder() {
            return null;
        }
    }

    /**
     * Local-side IPC implementation stub class.
     */

    public static abstract class Stub extends android.os.Binder implements source.analysis.android29.aidl.IRemoteService {
        private static final java.lang.String DESCRIPTOR = "source.analysis.android29.aidl.IRemoteService";

        /**
         * Construct the stub at attach it to the interface.
         */

        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an source.analysis.android29.aidl.IRemoteService interface,
         * generating a proxy if needed.
         */

        public static source.analysis.android29.aidl.IRemoteService asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof source.analysis.android29.aidl.IRemoteService))) {
                return ((source.analysis.android29.aidl.IRemoteService) iin);
            }
            return new source.analysis.android29.aidl.IRemoteService.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_getValue: {
                    data.enforceInterface(descriptor);
                    int _result = this.getValue();
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
                case TRANSACTION_getUser: {
                    data.enforceInterface(descriptor);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    source.analysis.android29.aidl.User _result = this.getUser(_arg0);
                    reply.writeNoException();
                    if ((_result != null)) {
                        reply.writeInt(1);
                        _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    } else {
                        reply.writeInt(0);
                    }
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }

        private static class Proxy implements source.analysis.android29.aidl.IRemoteService {
            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;
            }

            @Override
            public int getValue() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    boolean _status = mRemote.transact(Stub.TRANSACTION_getValue, _data, _reply, 0);
                    if (!_status && getDefaultImpl() != null) {
                        return getDefaultImpl().getValue();
                    }
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public source.analysis.android29.aidl.User getUser(java.lang.String username) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                source.analysis.android29.aidl.User _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(username);
                    boolean _status = mRemote.transact(Stub.TRANSACTION_getUser, _data, _reply, 0);
                    if (!_status && getDefaultImpl() != null) {
                        return getDefaultImpl().getUser(username);
                    }
                    _reply.readException();
                    if ((0 != _reply.readInt())) {
                        _result = source.analysis.android29.aidl.User.CREATOR.createFromParcel(_reply);
                    } else {
                        _result = null;
                    }
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            public static source.analysis.android29.aidl.IRemoteService sDefaultImpl;
        }

        static final int TRANSACTION_getValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

        public static boolean setDefaultImpl(source.analysis.android29.aidl.IRemoteService impl) {
            if (Stub.Proxy.sDefaultImpl == null && impl != null) {
                Stub.Proxy.sDefaultImpl = impl;
                return true;
            }
            return false;
        }

        public static source.analysis.android29.aidl.IRemoteService getDefaultImpl() {
            return Stub.Proxy.sDefaultImpl;
        }
    }

    public int getValue() throws android.os.RemoteException;

    public source.analysis.android29.aidl.User getUser(java.lang.String username) throws android.os.RemoteException;
}

User.java

// This file is intentionally left blank as placeholder for parcel declaration.

4、实现接口方法

RemoteServiceImpl

public class RemoteServiceImpl extends IRemoteService.Stub {
    @Override
    public int getValue() throws RemoteException {
        return 100;
    }

    @Override
    public User getUser(String username) throws RemoteException {
        User user = new User();
        user.setAge(18);
        user.setGender(0);
        user.setNickname("昵称");
        return user;
    }
}

5、创建独立进程服务

RemoteService

public class RemoteService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new RemoteServiceImpl();
    }
}

在AndroidManifest.xml中..独立进程服务:

<service android:name=".aidl.RemoteService" android:process=":remote"/>

6、绑定独立进程服务

绑定独立进程服务

Intent intent = new Intent(this, RemoteService.class);
bindService(intent, this, Context.BIND_AUTO_CREATE);

7、获取独立进程服务代理
public class AidlActivity extends AppCompatActivity implements ServiceConnection {

/**
 * Called when the connection with the service is established
 */

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
    // Following the example above for an AIDL interface,
    // this gets an instance of the IRemoteInterface, which we can use to call on the service
    iRemoteService = IRemoteService.Stub.asInterface(service);
}

/**
 * Called when the connection with the service disconnects unexpectedly
 */

@Override
public void onServiceDisconnected(ComponentName name) {
    Log.e(TAG, "Service has unexpectedly disconnected");
    iRemoteService = null;
}

8、通过独立进程服务代理进行通信
iRemoteService.getValue()
iRemoteService.getUser("android")

aidl跨进程通信调用流程

1、绑定服务

1.1、Activity中通过bindService()方法绑定远程服务RemoteService,具体实现方法是ContextImpl的bindService()方法。

1.2、远程服务RemoteService绑定成功后会回调onBind()方法,返回远程服务RemoteService的具体实现RemoteServiceImpl()。

1.3、远程服务绑定成功后,会回调onServiceConnected()方法,通知当前进程也就是AidlActivity,远程服务RemoteService已经连接成功,可以获取远程服务的代理进行进程间的通信了。

2、获取服务代理并通过服务代理进行通信

2.1、获取IRemoteService.Stub获取远程服务的代理,也就是IRemoteService.Stub.Proxy。

2.2、通过代理IRemoteService.Stub.Proxy调用远程服务的方法,代理IRemoteService.Stub.Proxy通过asBinder()方法获取BinderProxy调用transact()方法通知远程服务,而transact()方法使用JNI技术调用了native方法transactNative()方法。

2.3、transactNative()方法最后会调用远程服务IRemoteService.Stub的onTransact()方法,onTransact()方法会通过asBinder()方法获取RemoteServiceImpl,并调用RemoteServiceImpl的实际实现方法。

程序员专栏
 扫码关注填加客服 
长按识别下方..进群

近期精彩内容推荐:  

 字节跳动半夜给员工发钱,全员沸腾了

 为何程序员上班时间总戴个耳机?

 为什么建议大家使用 Linux 开发?

 盘点提高国内访问GitHub速度的9种方案





在看点这里好文分享给更多人↓↓

标签:
AndroidPush
Android编程精选 微信号:AndroidPush 扫描二维码关注公众号
优质自媒体

小编推荐

  1. 1 繁星点点伴你入眠什么意思(繁星点点什么歌的歌词)

    大家好,小娟今天来为大家解答繁星点点伴你入眠什么意思以下问题,繁星点点什么歌的歌词很多人还不知道,现在让我们一起来看看吧!1、意思是

  2. 2 等边三角形面积(等边三角形面积公式已知边长)

    大家好,小娟今天来为大家解答等边三角形面积以下问题,等边三角形面积公式已知边长很多人还不知道,现在让我们一起来看看吧!1、等边三角形

  3. 3 湖南最好的大学(湖北最好的大学)

    大家好,小乐今天来为大家解答湖南最好的大学以下问题,湖北最好的大学很多人还不知道,现在让我们一起来看看吧!1、湖南最好10所大学,相关

  4. 4 荔枝英文(荔枝英文名)

    大家好,小乐今天来为大家解答荔枝英文以下问题,荔枝英文名很多人还不知道,现在让我们一起来看看吧!1、litchi 英 [ˈli:ˌtʃi:] 美 [ˈlitʃi]n. 荔枝

  5. 5 百合cp本(百合cp本)

    大家好,小豪今天来为大家解答百合cp本以下问题,百合cp本很多人还不知道,现在让我们一起来看看吧!1、某科学的超电磁炮(搞笑) 恋姬无双系

  6. 6 张胜兵坐诊上海(5月12号)、广州(5月13号)限号20人,请联系助理速约!谢绝空降!

    为轻易恢弘患者就诊,现将武汉知名中医张胜兵2024年5月出诊放置公示如下,请人人凭据需要自行选择就诊时间。如因特别情形或者更改出诊时间,请

  7. 7 这次,被肥西“硬控”了!

    提到肥西特色农产物你最先想到?米线、米饺、照样肥西老母鸡?若是你只知道这些那这个蒲月你必然要来一趟肥西这里的“肥西月月农”运动邀你

  8. 8 绿瘦减肥药三亚药店有售吗(绿瘦减肥产品市场评论)

    大家好,小伟今天来为大家解答绿瘦减肥药三亚药店有售吗以下问题,绿瘦减肥产品市场评论很多人还不知道,现在让我们一起来看看吧!1、三亚机

Copyright 2024 优质自媒体,让大家了解更多图文资讯!