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。