【Android】圖文解密Android AIDL

1、簡介

AIDL是一種接口描述語言,用於進程間通信,有如下幾個特點。
1)AIDL用於多個客戶端跨進程訪問服務端,且服務端需要處理多線程的場合。否則,同一進程內的通信可以使用Binder,跨進程的通信可以使用Messager。
2)AIDL調用如果來自本地進程,即客戶端和服務端在同一進程,則服務端的執行過程與發起調用的客戶端在一個線程,此時完全沒必要使用AIDL,而是使用上面提到的Binder即可。
3)AIDL調用如果來自遠程進程,即客戶端和服務端在不同進程,則服務端必須考慮併發AIDL調用,保證線程安全,因爲每次遠程調用可能在服務端的不同線程中執行。
4)oneway關鍵字。本地調用爲同步調用,不受oneway影響。oneway用於遠程調用時,不會阻塞。
5)in、out、inout關鍵字。這三個關鍵字表示數據流向,in表示客戶端的數據可以流向服務端,out表示服務端的數據可以流向客戶端,inout表示客戶端和服務的數據流是雙向的。基本數據類型默認爲in,不可以爲別的;非基本數據類型需要指定一個實際需要的關鍵字,因爲這個關鍵字會影響數據的打包規則,從而影響性能。

2、用法

如何使用AIDL,包括以下幾個步驟。

1)創建.aidl文件。

aidl語法類似於Java,數據類型支持boolean、char、byte、short、int、long、float、double八個基本類型,以及String、CharSequence、List和Map,也支持自定義類型,如AIDL生成的接口、parcelable類,但即使是同一package的自定義類型也必須使用import。下面是一個簡單的例子,形式爲遠程調用,使用了AndroidStudio,App名字爲AIDLTest,package名字爲com.example.aidltest。

// IRemoteService.aidl
package com.example.aidltest;

import com.example.aidltest.IRemoteServiceCallback;
import com.example.aidltest.User;

interface IRemoteService {
    int add(int a, int b);
    void print(String string);

    void printUser(in User user);
    void printUser2(out User user);
    void printUser3(inout User user);

    void registerCallback(IRemoteServiceCallback callback);
}

然後,AndroidStudio編譯時會自動生成一個文件IRemoteService.java,其中定義了一個非常重要的抽象類Stub,本質上是一個IBinder。Debug編譯時這個文件的位置爲AIDLTest/app/build/generated/aidl_source_output_dir/debug/compileDebugAidl/out/com/example/myserver,稍後再解釋這個文件中代碼。
另外,還定義了兩個aidl文件,User.aidl和// IRemoteServiceCallback.aidl,代碼如下,稍後會解釋它們的作用。

// User.aidl
package com.example.aidltest;

parcelable User;

// IRemoteServiceCallback.aidl
package com.example.aidltest;

// Declare any non-default types here with import statements

interface IRemoteServiceCallback {
    void hello(int flag);
}

2)實現接口

實現接口,即我們在.aidl文件中聲明的接口,這些接口出現在了Stub中。代碼如下所示。

private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
        @Override
        public int add(int a, int b) {
            int ret = a + b;
            Log.d("RemoteService", "add ret:" + ret);
            return ret;
        }

        @Override
        public void print(String string) {
            Log.d("RemoteService", "print string:" + string);
        }

        @Override
        public void printUser(User user) {
            Log.d("RemoteService", "printUser user:" + user);
            try {
                if (null != mCallback) {
                    mCallback.hello(111);
                }
            } catch (Exception e) {
                Log.d("RemoteService", "callback Exception:" + e);
            }
        }

        @Override
        public void printUser2(User user) {
            Log.d("RemoteService", "printUser2 user:" + user);
            try {
                if (null != mCallback) {
                    mCallback.hello(222);
                }
            } catch (Exception e) {
                Log.d("RemoteService", "callback Exception:" + e);
            }
        }

        @Override
        public void printUser3(User user) {
            Log.d("RemoteService", "printUser3 user:" + user);
            try {
                if (null != mCallback) {
                    mCallback.hello(333);
                }
            } catch (Exception e) {
                Log.d("RemoteService", "callback Exception:" + e);
            }
        }

        @Override
        public void registerCallback(IRemoteServiceCallback callback) {
            Log.d("RemoteService", "registerCallback callback:" + callback);
            mCallback = callback;
        }
    }; 

3)公開接口

公開接口,即提供Service,在onBind函數中返回我們實現的Stub類對象。代碼如下所示,重點就一個地方,Override onBind,返回上一步實現的接口。

// RemoteService.java
package com.example.aidltest;

import android.app.Service;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.IBinder;
import android.util.Log;

public class RemoteService extends Service {
    private IRemoteServiceCallback mCallback;

    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
        @Override
        public int add(int a, int b) {
            int ret = a + b;
            Log.d("RemoteService", "add ret:" + ret);
            return ret;
        }

        @Override
        public void print(String string) {
            Log.d("RemoteService", "print string:" + string);
        }

        @Override
        public void printUser(User user) {
            Log.d("RemoteService", "printUser user:" + user);
            try {
                if (null != mCallback) {
                    mCallback.hello(111);
                }
            } catch (Exception e) {
                Log.d("RemoteService", "callback Exception:" + e);
            }
        }

        @Override
        public void printUser2(User user) {
            Log.d("RemoteService", "printUser2 user:" + user);
            try {
                if (null != mCallback) {
                    mCallback.hello(222);
                }
            } catch (Exception e) {
                Log.d("RemoteService", "callback Exception:" + e);
            }
        }

        @Override
        public void printUser3(User user) {
            Log.d("RemoteService", "printUser3 user:" + user);
            try {
                if (null != mCallback) {
                    mCallback.hello(333);
                }
            } catch (Exception e) {
                Log.d("RemoteService", "callback Exception:" + e);
            }
        }

        @Override
        public void registerCallback(IRemoteServiceCallback callback) {
            Log.d("RemoteService", "registerCallback callback:" + callback);
            mCallback = callback;
        }
    };

    public RemoteService() {
        Log.d("RemoteService", "RemoteService");
    }

    @Override
    public void onCreate() {
        Log.d("RemoteService", "onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int ret = super.onStartCommand(intent, flags, startId);
        Log.d("RemoteService", "onStartCommand intent:" + intent);
        Log.d("RemoteService", "onStartCommand flags:" + flags);
        Log.d("RemoteService", "onStartCommand startId:" + startId);
        Log.d("RemoteService", "onStartCommand ret:" + ret);
        return ret;
    }

    @Override
    public void onDestroy() {
        Log.d("RemoteService", "onDestroy");
        mCallback = null;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        Log.d("RemoteService", "onConfigurationChanged newConfig:" + newConfig);

    }

    @Override
    public void onLowMemory() {
        Log.d("RemoteService", "onLowMemory");

    }

    @Override
    public void onTrimMemory(int level) {
        Log.d("RemoteService", "onTrimMemory level:" + level);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d("RemoteService", "onBind intent:" + intent);
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("RemoteService", "onUnbind intent:" + intent);
        mCallback = null;
        return false;
    }

    @Override
    public void onRebind(Intent intent) {
        Log.d("RemoteService", "onRebind intent:" + intent);
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Log.d("RemoteService", "onTaskRemoved intent:" + rootIntent);
    }
}

在早期的Android版本中,開啓關聯啓動後,一個App可以綁定另一個App的Service,這就是一種遠程調用,不過現在的Android禁止了這種做法。在同一個app內,Service默認在app所屬的進程,在AndroidManifest.xml中給Service配置android:process某個屬性後,Service就會是一個獨立的進程,這時候在同一個app內綁定Service,也是遠程調用。

4)實現客戶端

客戶端使用bindService通過顯式Intent綁定Service,這時需要一個ServiceConnection對象,當綁定成功、Service連接後會收到onServiceConnected通知,其中的參數IBinder就是與服務端通信的橋樑,然後使用IRemoteService.Stub.asInterface把這個IBinder轉換爲IRemoteService,接着就可以調用aidl中聲明的接口了,代碼如下所示。

// MainActivity.java
package com.example.aidltest;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {
    private static final int HELLO = 0;

    private IRemoteService mRemoteService;

    private final ServiceConnection mRemoteConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            Log.d("MainActivity", "onServiceConnected className:" + className);
            Log.d("MainActivity", "onServiceConnected service:" + service);
            mRemoteService = IRemoteService.Stub.asInterface(service);
            if (null != mRemoteService) {
                try {
                    mRemoteService.registerCallback(mRemoteServiceCallback);
                    Log.d("MainActivity", "add:" + mRemoteService.add(100, 200));
                    mRemoteService.print("Called from client");
                    User user = new User("AAA", 111);
                    mRemoteService.printUser(user);
                    mRemoteService.printUser2(user);
                    mRemoteService.printUser3(user);
                    Log.d("MainActivity", "User:" + user);
                } catch (Exception e) {
                    Log.d("MainActivity", "Remote Exception:" + e);
                }
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            Log.d("MainActivity", "onServiceDisconnected className:" + className);
            mRemoteService = null;
        }

        @Override
        public void onBindingDied(ComponentName name) {
            Log.d("MainActivity", "onBindingDied className:" + name);
        }

        @Override
        public void onNullBinding(ComponentName name) {
            Log.d("MainActivity", "onNullBinding className:" + name);
        }
    };

    private IRemoteServiceCallback mRemoteServiceCallback = new IRemoteServiceCallback.Stub() {
        @Override
        public void hello(int flag) {
            Log.d("MainActivity", "hello flag:" + flag);
            mRemoteServiceHandler.sendMessage(mRemoteServiceHandler.obtainMessage(HELLO, flag));
        }
    };

    private Handler mRemoteServiceHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case HELLO:
                    Log.d("MainActivity", "handleMessage hello flag:" + msg.arg1);
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("MainActivity", "onCreate");
        setContentView(R.layout.activity_main);
        try {
            boolean ret = bindService(new Intent(this, RemoteService.class), mRemoteConnection, Context.BIND_AUTO_CREATE);
            Log.d("MainActivity", "bindService ret:" + ret);
        } catch (Exception e) {
            Log.d("MainActivity", "bindService Exception:" + e);
        }
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d("MainActivity", "onRestart");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d("MainActivity", "onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("MainActivity", "onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d("MainActivity", "onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d("MainActivity", "onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d("MainActivity", "onDestroy");
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onDestroy();
        Log.d("MainActivity", "onConfigurationChanged newConfig:" + newConfig);
    }
} 

5)支持自定義類型

aidl中支持自定義類型,分三步。
第一步,比如說定義一個User類,需要實現接口Parcelable,包括兩個函數,describeContents和writeToParcel,然後定義一個變量public static final Parcelable.Creator<User> CREATOR。代碼如下所示,需要注意writeToParcel和readFromParcel的變量順序一致。

// User.java
package com.example.aidltest;

import android.os.Parcel;
import android.os.Parcelable;

public class User implements Parcelable {
    private String mName;
    private int mAge;

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

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

    public User() {
        this("default", 0);
    }

    public User(String name, int age) {
        mName = name;
        mAge = age;
    }

    public User(Parcel in) {
        readFromParcel(in);
    }

    public void readFromParcel(Parcel in) {
        mName = in.readString();
        mAge = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeString(mName + "?");
        out.writeInt(mAge * 100);
    }

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

    @Override
    public String toString() {
        return super.toString() + "/mName:" + mName + "/mAge:" + mAge;
    }
}

Parcelable對象可以打包爲Parcel,有了Parcel就可以通過IBinder進行進程間通信了,Parcel的主要目的就是IPC。
第二步,定義同名aidl文件,使用parceable標記自定義類型User。
第三步,在aidl文件中使用自定義類型User,需要注意參數流向。

6)服務端通知客戶端

服務端通知客戶端有兩種方式,一種是aidl中接口的參數標記爲out或inout,另一種是使用aidl,即上文代碼中的IRemoteServiceCallback.aidl,客戶端實現IRemoteServiceCallback.Stub,然後通過IRemoteService中提供的接口registerCallback向服務端註冊callback,服務端可通過這個callback向客戶端發送通知,客戶端收到這個通知時可能不在主線程,有時候還會根據需要使用Handler進行轉線程,可參考上面MainActivity中的代碼。

3、aidl自動生成的java代碼

上面定義瞭如下三個aidl文件。

├── IRemoteService.aidl
├── IRemoteServiceCallback.aidl
└── User.aidl

其中User.aidl對應的Java代碼是我們手動寫的,其它兩個對應的Java代碼是自動生成的。首先來看一下IRemoteServiceCallback.java,本質上就是個Binder實現,代碼如下。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: /evo/AIDLTest/app/src/main/aidl/com/example/aidltest/IRemoteServiceCallback.aidl
 */
package com.example.aidltest;
// Declare any non-default types here with import statements

public interface IRemoteServiceCallback extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.example.aidltest.IRemoteServiceCallback
    {
        private static final java.lang.String DESCRIPTOR = "com.example.aidltest.IRemoteServiceCallback";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an com.example.aidltest.IRemoteServiceCallback interface,
         * generating a proxy if needed.
         */
        public static com.example.aidltest.IRemoteServiceCallback asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.aidltest.IRemoteServiceCallback))) {
                return ((com.example.aidltest.IRemoteServiceCallback)iin);
            }
            return new com.example.aidltest.IRemoteServiceCallback.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_hello:
                {
                    data.enforceInterface(descriptor);
                    int _arg0;
                    _arg0 = data.readInt();
                    this.hello(_arg0);
                    reply.writeNoException();
                    return true;
                }
                default:
                {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }
        private static class Proxy implements com.example.aidltest.IRemoteServiceCallback
        {
            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 void hello(int flag) throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(flag);
                    mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
                    _reply.readException();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }
        static final int TRANSACTION_hello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }
    public void hello(int flag) throws android.os.RemoteException;
}

下面是IRemoteServiceCallback相關的類圖。
在這裏插入圖片描述
aidl中沒有使用oneway,oneway的意思就是不阻塞,那麼在自動生成的Java代碼中,有兩個區別,一個是Stub類的onTransact函數不作reply處理,另一個是Proxy類的函數如上文的hello不作reply處理。另外,如果函數有返回值,或者使用了不同的in、out、input關鍵字,生成的代碼也是不同的。IRemoteService.java代碼如下所示,可以看到對自定義數據類型User使用了in、out、input後的區別。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: /evo/AIDLTest/app/src/main/aidl/com/example/aidltest/IRemoteService.aidl
 */
package com.example.aidltest;
public interface IRemoteService extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.example.aidltest.IRemoteService
    {
        private static final java.lang.String DESCRIPTOR = "com.example.aidltest.IRemoteService";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an com.example.aidltest.IRemoteService interface,
         * generating a proxy if needed.
         */
        public static com.example.aidltest.IRemoteService asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.aidltest.IRemoteService))) {
                return ((com.example.aidltest.IRemoteService)iin);
            }
            return new com.example.aidltest.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_add:
                {
                    data.enforceInterface(descriptor);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.add(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
                case TRANSACTION_print:
                {
                    data.enforceInterface(descriptor);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    this.print(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_printUser:
                {
                    data.enforceInterface(descriptor);
                    com.example.aidltest.User _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.example.aidltest.User.CREATOR.createFromParcel(data);
                    }
                    else {
                        _arg0 = null;
                    }
                    this.printUser(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_printUser2:
                {
                    data.enforceInterface(descriptor);
                    com.example.aidltest.User _arg0;
                    _arg0 = new com.example.aidltest.User();
                    this.printUser2(_arg0);
                    reply.writeNoException();
                    if ((_arg0 != null)) {
                        reply.writeInt(1);
                        _arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    }
                    else {
                        reply.writeInt(0);
                    }
                    return true;
                }
                case TRANSACTION_printUser3:
                {
                    data.enforceInterface(descriptor);
                    com.example.aidltest.User _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.example.aidltest.User.CREATOR.createFromParcel(data);
                    }
                    else {
                        _arg0 = null;
                    }
                    this.printUser3(_arg0);
                    reply.writeNoException();
                    if ((_arg0 != null)) {
                        reply.writeInt(1);
                        _arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    }
                    else {
                        reply.writeInt(0);
                    }
                    return true;
                }
                case TRANSACTION_registerCallback:
                {
                    data.enforceInterface(descriptor);
                    com.example.aidltest.IRemoteServiceCallback _arg0;
                    _arg0 = com.example.aidltest.IRemoteServiceCallback.Stub.asInterface(data.readStrongBinder());
                    this.registerCallback(_arg0);
                    reply.writeNoException();
                    return true;
                }
                default:
                {
                    return super.onTransact(code, data, reply, flags);
                }
        }
    }
        private static class Proxy implements com.example.aidltest.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 add(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);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
            @Override
            public void print(java.lang.String string) throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(string);
                    mRemote.transact(Stub.TRANSACTION_print, _data, _reply, 0);
                    _reply.readException();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
            @Override
            public void printUser(com.example.aidltest.User user) 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 ((user != null)) {
                        _data.writeInt(1);
                        user.writeToParcel(_data, 0);
                    }
                    else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_printUser, _data, _reply, 0);
                    _reply.readException();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
            @Override public void printUser2(com.example.aidltest.User user) throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_printUser2, _data, _reply, 0);
                    _reply.readException();
                    if ((0!=_reply.readInt())) {
                        user.readFromParcel(_reply);
                    }
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
            @Override
            public void printUser3(com.example.aidltest.User user) 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 ((user != null)) {
                        _data.writeInt(1);
                        user.writeToParcel(_data, 0);
                    }
                    else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_printUser3, _data, _reply, 0);
                    _reply.readException();
                    if ((0 !=_reply.readInt())) {
                        user.readFromParcel(_reply);
                    }
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
            @Override public void registerCallback(com.example.aidltest.IRemoteServiceCallback callback) throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeStrongBinder((((callback != null)) ? (callback.asBinder()) : (null)));
                    mRemote.transact(Stub.TRANSACTION_registerCallback, _data, _reply, 0);
                    _reply.readException();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }
        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_print = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_printUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
        static final int TRANSACTION_printUser2 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
        static final int TRANSACTION_printUser3 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
        static final int TRANSACTION_registerCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
    }
    public int add(int a, int b) throws android.os.RemoteException;
    public void print(java.lang.String string) throws android.os.RemoteException;
    public void printUser(com.example.aidltest.User user) throws android.os.RemoteException;
    public void printUser2(com.example.aidltest.User user) throws android.os.RemoteException;
    public void printUser3(com.example.aidltest.User user) throws android.os.RemoteException;
    public void registerCallback(com.example.aidltest.IRemoteServiceCallback callback) throws android.os.RemoteException;
}

最後,總結一下aidl中幾個特殊關鍵字的用法。oneway表示數據流單方向流通,那麼oneway標識的接口不能有返回值,參數類型不能是out和inout。對於8個基本數據類型來說,包括String類型,以及aidl接口,充當接口參數類型時默認爲in,不能是out和inout。

4、aidl流程

aidl流程其實就是Binder進程間通信的流程,在Java客戶端通過Proxy發起遠程調用請求,然後經JNI、Native到Kernel後,再經Native、JNI到Java服務端的Stub.onTransact。如果需要數據迴流或反向通知,數據再從服務端的Stub流向客戶端的Proxy。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章