爲使應用程序之間可以彼此通訊,Android提供了IPC (Inter Process Communication,進程間通訊)的一種獨特實現: AIDL (Android Interface Definition Language, Android接口定義語言)。java
簡單來講,AIDL 就是定義一個接口,客戶端(調用端)經過 bindService 來與遠程服務端創建一個鏈接,在該鏈接創建時會將返回一個 IBinder 對象,該對象是服務端 Binder 的 BinderProxy。在創建鏈接時,客戶端經過 asInterface 函數將該 BinderProxy 對象包裝成本地的 Proxy,並賦值給Proxy類的mRemote 字段,本地經過 mRemote 便可調用遠程方法。android
首先打開 Android Studio,new 一個 AIDL file。具體代碼以下 :app
interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); }
basicTypes 方法事接口自帶的,不過能夠知道,在 aidl 中只能使用這些基本類型參數:int, long, boolean, float,double , String ;ide
除了 basicTypes 方法以外,咱們也能夠添加本身的方法。所以,能夠刪除 basicTypes 方法,添加本身的方法。函數
添加完方法以後,選中 .aidl 文件,在彈出的菜單中選擇 Synchronize LocalAIDLS... Service.java,就會會自動幫你生成對應的 java 代碼。ui
格式化代碼以後,以下所示:this
/* * This file is auto-generated. DO NOT MODIFY. * Original file: /Users/shenjiaqi/Documents/sjq/booksource/chapter6/DatabaseTest/app/src/main/aidl/com/example/databasetest/IMyAidlInterface.aidl */ package com.example.databasetest; public interface IMyAidlInterface extends android.os.IInterface { /** * Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.example.databasetest.IMyAidlInterface { private static final java.lang.String DESCRIPTOR = "com.example.databasetest.IMyAidlInterface"; /** * Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.example.databasetest.IMyAidlInterface interface, * generating a proxy if needed. */ public static com.example.databasetest.IMyAidlInterface asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.example.databasetest.IMyAidlInterface))) { return ((com.example.databasetest.IMyAidlInterface) iin); } return new com.example.databasetest.IMyAidlInterface.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 { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_basicTypes: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); long _arg1; _arg1 = data.readLong(); boolean _arg2; _arg2 = (0 != data.readInt()); float _arg3; _arg3 = data.readFloat(); double _arg4; _arg4 = data.readDouble(); java.lang.String _arg5; _arg5 = data.readString(); this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.example.databasetest.IMyAidlInterface { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) 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(anInt); _data.writeLong(aLong); _data.writeInt(((aBoolean) ? (1) : (0))); _data.writeFloat(aFloat); _data.writeDouble(aDouble); _data.writeString(aString); mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException; }
若是,你須要修改 .aidl 文件,那麼修改以後,選擇 build -> make project 便可,會從新生成對應的java文件。spa
其中的 proxy 是一個靜態類,實現了這個 IMyAidlInterface 接口。Stub 繼承了 Binder 同時實現了 IMyAidlInterface 接口。.net
若是,須要傳遞複雜數據,那麼就須要實現 Parcelable 接口,可序列化:代理
public class Info implements Parcelable { private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Info() { } public Info(Parcel in) { content = in.readString(); } public static final Creator<Info> CREATOR = new Creator<Info>() { @Override public Info createFromParcel(Parcel in) { return new Info(in); } @Override public Info[] newArray(int size) { return new Info[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(content); } /** * 參數是一個Parcel,用它來存儲與傳輸數據 * * @param dest */ public void readFromParcel(Parcel dest) { //注意,此處的讀值順序應當是和writeToParcel()方法中一致的 content = dest.readString(); } //方便打印數據 @Override public String toString() { return "content : " + content; } }
與此同時,也要建一個 info.aidl 文件,代表數據也是能夠傳遞的。
package com.viii.aidlclient; //注意:Info.Info.java的包名應當是同樣的 //這個文件的做用是引入了一個序列化對象 Info 供其餘的AIDL文件使用 //注意parcelable是小寫 parcelable Info;
這樣就可使用 info 對象了。 不用在受前面的基本類型變量所控制。
接下去,新建一個Service負責接收消息,並在AndroidManifest.xml裏面註冊 Service:
public class MyService extends Service { private static final String TAG = "MyService"; // private MyBinder mMyBinder = new MyBinder(); @Nullable @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind: ");
// 應該返回 mBinder return null; } @Override public void onCreate() { Log.d(TAG, "onCreate: "); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand: "); return super.onStartCommand(intent, flags, startId); } // 這裏就是服務端的實現 private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { // 具體實現過程 } }; }
這時候,能夠 basicTypes 方法添加具體函數代碼,實現你想要的功能。
當咱們在本地獲取到代理後以後,調用 basicTypes 就會觸發服務端的調用。
接下去在mainactivity中進行綁定。
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private IMyAidlInterface mService; private boolean mIsBound; private AdditionServiceConnection mServiceConnection; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); doBindService() ; }/** * bind service */ private void doBindService() { mServiceConnection = new AdditionServiceConnection(); Intent intent = new Intent(this, MyService.class); bindService(intent, mServiceConnection, BIND_AUTO_CREATE); } /** * unbind service */ private void doUnbindService() { if (mIsBound) { unbindService(mServiceConnection); mServiceConnection = null; mIsBound = false; } } /** * ServiceConection */ class AdditionServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) {
// 鏈接的時候獲取本地代理,這樣咱們就能夠調用 service 中的方法了。 mService = IMyAidlInterface.Stub.asInterface((IBinder) service); mIsBound = true; try { //設置死亡代理 service.linkToDeath(mDeathRecipient, 0); } catch (RemoteException e) { e.printStackTrace(); } Log.d(TAG, "onServiceConnected: "); } @Override public void onServiceDisconnected(ComponentName name) { mService = null; mIsBound = false; Log.d(TAG, "onServiceDisconnected: "); } } /** * 監聽Binder是否死亡 */ private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { if (mService == null) { return; } mService.asBinder().unlinkToDeath(mDeathRecipient, 0); mService = null; //從新綁定 doBindService(); } }; @Override protected void onStop() { super.onStop(); doUnbindService(); } }
將遠程服務的 binder 拿到以後,咱們就能夠調用相關方法實現本身的功能呢。
到這裏,一個 AIDL 就被咱們實現了。
具體實例代碼見 :https://download.csdn.net/download/szengjiaqi/10613236