前语

上一篇咱们叙述了Service的进阶用法,特别是在运用跨进程Service的时分,咱们运用了AIDL技能,本篇咱们详细来理一理所谓的AIDL技能,它究竟帮咱们做了什么事情。

一、AIDL生成了什么文件

1.1 新建模块代码

咱们新建一个MainActivity和MainService,详细代码如下所示:

<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.RethinkingService">
    <activity
        android:name="com.afs.rethinkingservice.MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service
        android:name="com.afs.rethinkingservice.MainService"
        android:exported="true"
        android:process=":remote">
        <intent-filter>
            <action android:name="com.afs.rethinkingservice.maidl.MainAIDLService" />
        </intent-filter>
    </service>
</application>
“` “`
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:orientation="vertical"
    tools:context=".MainActivity">
    <Button android:id="@+id/btn_start_service" android:layout_width="match_parent"
        android:layout_height="wrap_content" android:text="开启服务" />
    <Button android:id="@+id/btn_bind_service" android:layout_width="match_parent"
        android:layout_height="wrap_content" android:text="绑定服务" />
    <Button android:id="@+id/btn_test_aidl_method" android:layout_width="match_parent"
        android:layout_height="wrap_content" android:text="测验AIDL中的办法" />
    <Button android:id="@+id/btn_stop_service" android:layout_width="match_parent"
        android:layout_height="wrap_content" android:text="停止服务" />
</LinearLayout>
public class MainActivity extends AppCompatActivity {
    public static final String TAG = "MainActivity=========";
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected() executed");
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected() executed");
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate() executed");
        Log.d(TAG, "onCreate() executed Thread id is " + Thread.currentThread().getId());
        Log.d(TAG, "onCreate() executed process id is " + Process.myPid());
        findViewById(R.id.btn_start_service).setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, MainService.class);
            startService(intent);
        });
        findViewById(R.id.btn_bind_service).setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, MainService.class);
            bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
        });
        findViewById(R.id.btn_stop_service).setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, MainService.class);
            stopService(intent);
        });
        findViewById(R.id.btn_test_aidl_method).setOnClickListener(v -> {
        });
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy() executed");
    }
}
package com.afs.rethinkingservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Process;
import android.util.Log;
import androidx.annotation.Nullable;
public class MainService extends Service {
    public static final String TAG = "MainService=========";
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate() executed");
        Log.d(TAG, "onCreate() executed Thread id is " + Thread.currentThread().getId());
        Log.d(TAG, "onCreate() executed process id is " + Process.myPid());
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand() executed");
        return super.onStartCommand(intent, flags, startId);
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind() executed");
        return null;
    }
    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy() executed");
        super.onDestroy();
    }
}

1.2 新建aidl文件

右键新建一个名为MainAIDLService.aidl的文件

package com.afs.rethinkingservice.maidl;
// Declare any non-default types here with import statements
interface MainAIDLService {
    int plus(int a, int b);
    String toUpperCase(String str);
}

然后编译该文件,会在build/generated/aidl_source_output_dir目录下生成一个同名的MainAIDLService.java文件。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 */
package com.afs.rethinkingservice.maidl;
// Declare any non-default types here with import statements
public interface MainAIDLService extends android.os.IInterface {
    /** Default implementation for MainAIDLService. */
    public static class Default implements com.afs.rethinkingservice.maidl.MainAIDLService {
        @Override
        public int plus(int a, int b) throws android.os.RemoteException {
            return 0;
        }
        @Override
        public java.lang.String toUpperCase(java.lang.String str) 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 com.afs.rethinkingservice.maidl.MainAIDLService {
        private static final java.lang.String DESCRIPTOR = "com.afs.rethinkingservice.maidl.MainAIDLService";
        /** Construct the stub at attach it to the interface. */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an com.afs.rethinkingservice.maidl.MainAIDLService interface,
         * generating a proxy if needed.
         */
        public static com.afs.rethinkingservice.maidl.MainAIDLService asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.afs.rethinkingservice.maidl.MainAIDLService))) {
                return ((com.afs.rethinkingservice.maidl.MainAIDLService) iin);
            }
            return new com.afs.rethinkingservice.maidl.MainAIDLService.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_plus: {
                    data.enforceInterface(descriptor);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.plus(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
                case TRANSACTION_toUpperCase: {
                    data.enforceInterface(descriptor);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    java.lang.String _result = this.toUpperCase(_arg0);
                    reply.writeNoException();
                    reply.writeString(_result);
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }
        private static class Proxy implements com.afs.rethinkingservice.maidl.MainAIDLService {
            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 plus(int a, int b) 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);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    boolean _status = mRemote.transact(Stub.TRANSACTION_plus, _data, _reply, 0);
                    if (!_status && getDefaultImpl() != null) {
                        return getDefaultImpl().plus(a, b);
                    }
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
            @Override
            public java.lang.String toUpperCase(java.lang.String str) 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);
                    _data.writeString(str);
                    boolean _status = mRemote.transact(Stub.TRANSACTION_toUpperCase, _data, _reply, 0);
                    if (!_status && getDefaultImpl() != null) {
                        return getDefaultImpl().toUpperCase(str);
                    }
                    _reply.readException();
                    _result = _reply.readString();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
            public static com.afs.rethinkingservice.maidl.MainAIDLService sDefaultImpl;
        }
        static final int TRANSACTION_plus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_toUpperCase = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        public static boolean setDefaultImpl(com.afs.rethinkingservice.maidl.MainAIDLService impl) {
            // Only one user of this interface can use this function
            // at a time. This is a heuristic to detect if two different
            // users in the same process use this function.
            if (Stub.Proxy.sDefaultImpl != null) {
                throw new IllegalStateException("setDefaultImpl() called twice");
            }
            if (impl != null) {
                Stub.Proxy.sDefaultImpl = impl;
                return true;
            }
            return false;
        }
        public static com.afs.rethinkingservice.maidl.MainAIDLService getDefaultImpl() {
            return Stub.Proxy.sDefaultImpl;
        }
    }
    public int plus(int a, int b) throws android.os.RemoteException;
    public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException;
}

1.3 整理aidl生成的文件内容

对着MainAIDLService.java文件,乍一看咱们可能会觉得一脸懵逼,该文件如同非常混乱,可是假如细心整理一下,其实会发现里边的结构是这样的

重新认识Service(三)AIDL的使用和理解

主要是主动生成了四个类,MainAIDLService、Default、Stub、Proxy,假如咱们把代码精简一下,大概是下面这样的:

public interface MainAidlService extends android.os.IInterface {
    /**
     * MainAidlService接口的默许完结类(高版别SDK才会生成)
     */
    public static class Default implements com.afs.rethinkingservice.maidl.MainAidlService {
    }
    /**
     * 本地IPC通讯的完结类父类
     */
    public static abstract class Stub extends android.os.Binder implements com.afs.rethinkingservice.maidl.MainAidlService {
        /**
         * 长途IPC通讯的完结类
         */
        private static class Proxy implements com.afs.rethinkingservice.maidl.MainAidlService {
        }
    }
}

由此可见,aidl主要是帮咱们生成了以下四个东西

  • 【MainAidlService】接口,承继了android.os.IInterface的接口
  • 【Default】类,完结了MainAidlService接口的类(高版别SDK才会生成MainAidlService接口的默许完结类)
  • 【Stub】抽象类,承继自android.os.Binder并完结了MainAidlService接口(本地IPC通讯的完结类父类)
  • 【Proxy】类,完结了MainAidlService接口(长途IPC通讯的完结类)

二、去除AIDL文件,创立Java类完结Binder通讯

2.1 复制aidl生成的类

在理清了这四个类之后,接下来咱们能够把上面说到的四个类全部复制出来,放到咱们的java包中,

重新认识Service(三)AIDL的使用和理解

删去本来右键新建的MainAIDLService.aidl文件,以及在build文件夹中生成的文件。
之后修复代码(主要是拜访权限的修正),去除错误提示之后,各个类的代码如下所示:

public interface MainAidlService extends android.os.IInterface {
    public int plus(int a, int b) throws android.os.RemoteException;
    public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException;
}
public class Default implements com.afs.rethinkingservice.maidl.MainAidlService {
    @Override
    public int plus(int a, int b) throws android.os.RemoteException {
        return 0;
    }
    @Override
    public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException {
        return null;
    }
    @Override
    public android.os.IBinder asBinder() {
        return null;
    }
}
public class Proxy implements com.afs.rethinkingservice.maidl.MainAidlService {
    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 plus(int a, int b) 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);
            _data.writeInt(a);
            _data.writeInt(b);
            boolean _status = mRemote.transact(Stub.TRANSACTION_plus, _data, _reply, 0);
            if (!_status && getDefaultImpl() != null) {
                return getDefaultImpl().plus(a, b);
            }
            _reply.readException();
            _result = _reply.readInt();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
        return _result;
    }
    @Override
    public java.lang.String toUpperCase(java.lang.String str) 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);
            _data.writeString(str);
            boolean _status = mRemote.transact(Stub.TRANSACTION_toUpperCase, _data, _reply, 0);
            if (!_status && getDefaultImpl() != null) {
                return getDefaultImpl().toUpperCase(str);
            }
            _reply.readException();
            _result = _reply.readString();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
        return _result;
    }
    public static MainAidlService sDefaultImpl;
}
public abstract class Stub extends android.os.Binder implements com.afs.rethinkingservice.maidl.MainAidlService {
    public static final java.lang.String DESCRIPTOR = "com.afs.rethinkingservice.maidl.MainAidlService";
    /**
     * Construct the stub at attach it to the interface.
     */
    public Stub() {
        this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an com.afs.rethinkingservice.maidl.MainAidlService interface,
     * generating a proxy if needed.
     */
    public static com.afs.rethinkingservice.maidl.MainAidlService asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (((iin != null) && (iin instanceof com.afs.rethinkingservice.maidl.MainAidlService))) {
            return ((com.afs.rethinkingservice.maidl.MainAidlService) iin);
        }
        return new 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_plus: {
                data.enforceInterface(descriptor);
                int _arg0;
                _arg0 = data.readInt();
                int _arg1;
                _arg1 = data.readInt();
                int _result = this.plus(_arg0, _arg1);
                reply.writeNoException();
                reply.writeInt(_result);
                return true;
            }
            case TRANSACTION_toUpperCase: {
                data.enforceInterface(descriptor);
                java.lang.String _arg0;
                _arg0 = data.readString();
                java.lang.String _result = this.toUpperCase(_arg0);
                reply.writeNoException();
                reply.writeString(_result);
                return true;
            }
            default: {
                return super.onTransact(code, data, reply, flags);
            }
        }
    }
    static final int TRANSACTION_plus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_toUpperCase = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    public static boolean setDefaultImpl(com.afs.rethinkingservice.maidl.MainAidlService impl) {
        // Only one user of this interface can use this function
        // at a time. This is a heuristic to detect if two different
        // users in the same process use this function.
        if (Proxy.sDefaultImpl != null) {
            throw new IllegalStateException("setDefaultImpl() called twice");
        }
        if (impl != null) {
            Proxy.sDefaultImpl = impl;
            return true;
        }
        return false;
    }
    public static MainAidlService getDefaultImpl() {
        return Proxy.sDefaultImpl;
    }
}

2.2 运用咱们复制的类来完结Binder通讯

依照咱们之前生成binder目标实例的办法,重新修正咱们的MainActivity和MainService的代码,代码如下所示:

public class MainActivity extends AppCompatActivity {
    private MainAidlService mBinder;
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected() executed");
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected() executed");
            mBinder = Stub.asInterface(service);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_test_aidl_method).setOnClickListener(v -> {
            try {
                int total = mBinder.plus(1, 1);
                Log.d(TAG, "total === " + total);
                String newString = mBinder.toUpperCase("aaabbbcccddd");
                Log.d(TAG, "newString === " + newString);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        });
    }
}
public class MainService extends Service {
    public class MainBinder extends Stub {
        @Override
        public int plus(int a, int b) throws RemoteException {
            return a + b;
        }
        @Override
        public String toUpperCase(String str) throws RemoteException {
            return str.toUpperCase();
        }
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind() executed");
        return new MainBinder();
    }
}

2.3 验证成果通讯成果

咱们发动app,然后别离点击绑定服务,测验AIDL中的办法按钮,日志信息如下:

2022-03-31 15:46:16.793 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: onCreate() executed
2022-03-31 15:46:16.794 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: onCreate() executed Thread id is 2
2022-03-31 15:46:16.794 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: onCreate() executed process id is 32638
2022-03-31 15:46:29.837 739-739/com.afs.rethinkingservice03 D/MainService=========: onCreate() executed
2022-03-31 15:46:29.838 739-739/com.afs.rethinkingservice03 D/MainService=========: onCreate() executed Thread id is 2
2022-03-31 15:46:29.838 739-739/com.afs.rethinkingservice03 D/MainService=========: onCreate() executed process id is 739
2022-03-31 15:46:29.838 739-739/com.afs.rethinkingservice03 D/MainService=========: onBind() executed
2022-03-31 15:46:29.843 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: onServiceConnected() executed
2022-03-31 15:46:44.757 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: total === 2
2022-03-31 15:46:44.758 32638-32638/com.afs.rethinkingservice03 D/MainActivity=========: newString === AAABBBCCCDDD

依据日志信息可知,咱们成功完结了Binder通讯。
这就阐明,AIDL技能只是依照某种规范,主动帮咱们生成了一些类来帮咱们完结Binder通讯,
那么假如咱们不用AIDL技能,能否手动创立相关的类来帮咱们完结Binder通讯呢? 答案当然是能够的,咱们完全能够手动创立相关的类来完结Binder通讯,只不过相比较而言,aidl主动生成这种办法更简单高效。

三、AIDL生成的几个类的效果是什么?

咱们已经完结了Binder通讯,接下来咱们继续来看看这四个类的效果别离是什么。

MainActivity中的代码告知咱们,咱们在和MainService进行通讯的时分,主要是调用了mBinder办法来完结的:

         mBinder.plus(1, 1);
         mBinder.toUpperCase("aaabbbcccddd");

而Bindder主要是经过Stub.asInterface(service)来赋值的:

    private MainAidlService mBinder;
    private ServiceConnection mServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceDisconnected(ComponentName name) {
                Log.d(TAG, "onServiceDisconnected() executed");
            }
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(TAG, "onServiceConnected() executed");
                mBinder = Stub.asInterface(service);
            }
            };

那么咱们就来看看Stub.asInterface究竟做了什么事情:


public abstract class Stub extends android.os.Binder implements com.afs.rethinkingservice.maidl.MainAidlService {
    public static final java.lang.String DESCRIPTOR = "com.afs.rethinkingservice.maidl.MainAidlService";//**要害点2**
    /**
     * Construct the stub at attach it to the interface.
     */
    public Stub() {
        this.attachInterface(this, DESCRIPTOR);//**要害点4**
    }
    /**
     * Cast an IBinder object into an com.afs.rethinkingservice.maidl.MainAidlService interface,
     * generating a proxy if needed.
     */
    public static com.afs.rethinkingservice.maidl.MainAidlService asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);//**要害点1**
        if (((iin != null) && (iin instanceof com.afs.rethinkingservice.maidl.MainAidlService))) {//**要害点5**
            return ((com.afs.rethinkingservice.maidl.MainAidlService) iin);
        }
        return new Proxy(obj);//**要害点6**
    }
    @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_plus: {
                data.enforceInterface(descriptor);
                int _arg0;
                _arg0 = data.readInt();
                int _arg1;
                _arg1 = data.readInt();
                int _result = this.plus(_arg0, _arg1);//要害点10
                reply.writeNoException();
                reply.writeInt(_result);
                return true;
            }
            case TRANSACTION_toUpperCase: {
                data.enforceInterface(descriptor);
                java.lang.String _arg0;
                _arg0 = data.readString();
                java.lang.String _result = this.toUpperCase(_arg0);//要害点10
                reply.writeNoException();
                reply.writeString(_result);
                return true;
            }
            default: {
                return super.onTransact(code, data, reply, flags);
            }
        }
    }
}
public class Binder implements IBinder {
    //**要害点4**
    public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }
    //**要害点3**
    public @Nullable
    IInterface queryLocalInterface(@NonNull String descriptor) {
        if (mDescriptor != null && mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }
    //**要害点9**
    public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
                                  int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);
        if (data != null) {
            data.setDataPosition(0);
        }
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }
}
public class Proxy implements com.afs.rethinkingservice.maidl.MainAidlService {
    private android.os.IBinder mRemote;
    Proxy(android.os.IBinder remote) {//**要害点7**
        mRemote = remote;
    }
    @Override
    public int plus(int a, int b) 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);
            _data.writeInt(a);
            _data.writeInt(b);
            boolean _status = mRemote.transact(Stub.TRANSACTION_plus, _data, _reply, 0);//**要害点8**
            _reply.readException();
            _result = _reply.readInt();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
        return _result;//要害点11
    }
    @Override
    public java.lang.String toUpperCase(java.lang.String str) 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);
            _data.writeString(str);
            boolean _status = mRemote.transact(Stub.TRANSACTION_toUpperCase, _data, _reply, 0);//**要害点8**
            _reply.readException();
            _result = _reply.readString();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
        return _result;//要害点11
    }
}
  • 1.在Stub.asInterface办法中,当object为null的时分,直接回来null
  • 2.调用android.os.IBinder实例目标obj的queryLocalInterface()办法,其中DESCRIPTOR字段其实便是【MainAidlService的包名途径】
  • 3.IBinder的queryLocalInterface会判别本身的mDescriptor字段是否等于【MainAidlService的包名途径】,假如等于就回来mOwner,而mOwner其实是在Stub目标的结构办法中,调用attachInterface()进行赋值的,mOwner=本身,mDescriptor=【MainAidlService的包名途径】,而咱们在MainService中创立的MainBinder就承继了Stub,Stub又完结了MainAidlService接口,MainAidlService接口又承继了android.os.IInterface接口。这样android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR),其实获取的便是MainBinder实例目标;
  • 4.在要害点5处进行了判别,假如不为空,且完结了MainAidlService接口,就直接回来MainBinder实例目标;这儿之所以做这个判别是因为,当MainService和MainActivity两者处于同一个进程的时分,MainBinder实例目标是能够成功回来的,可是当两者不在同一个进程则会回来失败**
  • 5.在要害点6处,当回来MainBinder失败的时分,阐明MainService和MainActivity不在同一个进程,就开端创立Proxy目标,
  • 6.而Proxy其实是个署理类,它也完结了MainAidlService接口;别的Proxy的结构办法传入的便是Binder实例目标,然后当咱们调用plus(int a, int b)和toUpperCase(java.lang.String str)办法的时分,在要害点8处,Proxy都会经过调用Binder的transact办法。
  • 7.在要害点9,在Binder的transact办法中又会调用onTransact()办法,在要害点10处,咱们复制的Stub类就完结了onTransact(),该办法会匹配相应的办法名,然后调用详细的办法,也便是MainBinder中的办法终究同步走完这段代码,来到要害点11处,成功回来函数调用成果

以上内容总结一句话便是, mBinder = Stub.asInterface(service)这个办法,当MainService和MainActivity两者处于同一个进程的时分,直接回来MainBinder实例目标。 当两者不在同一个进程的时分,会主动创立一个内部持有Binder实例的Proxy署理目标,内部经过Binder来完结进程间办法调用通讯功用

最后咱们再总结一下四个类各自的效果:

  • 【MainAidlService】接口类,能够理解为通讯的协议标准,其他三个类都完结了这个接口
  • 【Default】类,在低版别SDK编译器,AIDL不会生成这个类,而在高版别SDK编译器中,Aidl会生成这个类,MainAidlService接口的默许完结类。
  • 【Stub】抽象类,承继自android.os.Binder并完结了MainAidlService接口,咱们的MainBinder便是承继了它,asInterface()和onTransact() 办法是他的核心。
  • 【Proxy】类,完结了MainAidlService接口,长途IPC通讯的详细完结类,内部持有Binder实例目标,调用Binder的transact()办法完结跨进程通讯

四、验证咱们的定论

别离在MainActivity中和Stub中增加日志打印代码:

public class MainActivity extends AppCompatActivity {
    public static final String TAG = "MainActivity=========";
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected() executed");
            mBinder = Stub.asInterface(service);
            Log.d(TAG, "mBinder的类型==================" + mBinder.getClass());
        }
    };
}
public abstract class Stub extends android.os.Binder implements com.afs.rethinkingservice.maidl.MainAidlService {
    public static final String TAG = "Stub=========";
    public static com.afs.rethinkingservice.maidl.MainAidlService asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (iin == null) {
            Log.d(TAG, "iin的类型==================null");
        } else {
            Log.d(TAG, "iin的类型==================" + iin.getClass());
        }
        if (((iin != null) && (iin instanceof com.afs.rethinkingservice.maidl.MainAidlService))) {
            return ((com.afs.rethinkingservice.maidl.MainAidlService) iin);
        }
        return new Proxy(obj);
    }
}

4.1 当MainActivity和MainService不在同一个进程的时分:

2022-03-31 17:16:58.440 6389-6389/com.afs.rethinkingservice03 D/MainActivity=========: onServiceConnected() executed
2022-03-31 17:16:58.440 6389-6389/com.afs.rethinkingservice03 D/Stub=========: iin的类型==================null
2022-03-31 17:16:58.440 6389-6389/com.afs.rethinkingservice03 D/MainActivity=========: mBinder的类型==================class com.afs.rethinkingservice.maidl.Proxy

4.2 去掉AndroidManifest中MainService的Process字段,当MainActivity和MainService在同一个进程的时分:

2022-03-31 17:20:26.020 6722-6722/com.afs.rethinkingservice03 D/MainActivity=========: onServiceConnected() executed
2022-03-31 17:20:26.020 6722-6722/com.afs.rethinkingservice03 D/Stub=========: iin的类型==================class com.afs.rethinkingservice.MainService$MainBinder
2022-03-31 17:20:26.021 6722-6722/com.afs.rethinkingservice03 D/MainActivity=========: mBinder的类型==================class com.afs.rethinkingservice.MainService$MainBinder

经过上面的两端日志信息,能够进一步证明咱们的定论: Stub.asInterface(service)这个办法,当MainService和MainActivity两者处于同一个进程的时分,直接回来MainBinder实例目标。 当两者不在同一个进程的时分,会主动创立一个内部持有Binder实例的Proxy署理目标,内部经过Binder来完结进程间办法调用通讯功用