🔥 AIDL
AIDL 全稱 Android Interface Definition Language (Android 介面定義語言),允許你定義客戶端和服務都同意的編程介面,以便使用行程間通信 (IPC) 相互通信,在Android上,一個行程不能正常訪問另一個行程的記憶體,因此 Android 使用 AIDL 為你處理,
注意:僅當你允許來自不同應用程式的客戶端訪問你的 IPC 服務并希望在您的服務中處理多執行緒時,才需要使用 AIDL, 如果是多行程單執行緒那么使用 Messenger 就可以了,
🔥 名詞解釋
💥 方法
-
DESCRIPTOR:Binder的唯一標識,一般用當前的 Binder 的類名表示,
-
asInterface(IBinder obj):將服務端的 Binder物件生成客戶端所需的AIDL介面型別物件,這種轉換程序是區分行程的,如果位于同一行程,回傳的就是Stub 物件本身,否則回傳的是系統封裝后的Stub.proxy物件,
-
asBinder:用于回傳當前Binder物件,
-
onTransact:運行在服務端中的 Binder 執行緒池中,遠程請求會通過系統底層封裝后交由此方法來處理,
💥 tag
-
in:資料只能由客戶端流向服務端,服務端將會收到客戶端物件的完整資料,客戶端物件不會因為服務端對傳參的修改而發生變動,
-
out:資料只能由服務端流向客戶端,服務端將會收到客戶端物件,該物件不為空,但是它里面的欄位為空,但是在服務端對該物件作任何修改之后客戶端的傳參物件都會同步改動,
-
inout:服務端將會接收到客戶端傳來物件的完整資訊,并且客戶端將會同步服務端對該物件的任何變動,
🔥 定義 AIDL 介面
要使用 AIDL ,請執行以下步驟:
-
創建 .aidl 檔案
-
實作介面
-
向客戶端公開介面
💥 創建 .aidl 檔案
AIDL 使用一種簡單的語法,你可以使用一個或多個可以接受引數和回傳值的方法來宣告一個介面,引數和回傳值可以是任何型別,甚至是其他 AIDL 生成的介面,
必須使用 Java 編程語言構建 .aidl 檔案,每個 .aidl 檔案必須定義一個介面,并且只需要介面宣告和方法名,
AIDL 支持以下資料型別:
-
Java的所有原始型別(如 int )
-
所有原始陣列(如 int[])
-
String
-
CharSequence
-
List
-
Map
如下:

輸入名稱>finish

創建aidl

此時 在相同包名下創建.aidl 檔案,
IUserInterface.aidl
// IUserInterface.aidl
package com.scc.demo.ipc;
// Declare any non-default types here with import statements
interface IUserInterface {
/**
* 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);
}
只需將 .aidl 檔案保存在專案的 src/ 目錄中,當你構建應用程式時,SDK 工具會在專案的 gen/ 目錄中生成 IBinder 介面檔案, 生成的檔案名與 .aidl 檔案名匹配,但具有 .java 擴展名(例如,IUserInterface.aidl 結果為 IUserInterface.java),
如果你使用 Android Studio,增量構建幾憾訓立即生成系結器類,如下圖:

就問你6不6,
💥 Implement the interface
構建應用程式時,Android SDK 工具會生成一個以 .aidl 檔案命名的 .java 介面檔案, 生成的介面包括一個名為 Stub 的子類,它是其父介面(例如,IUserInterface.Stub)的抽象實作,并宣告了 .aidl 檔案中的所有方法 (如上圖),
注意:Stub 還定義了一些輔助方法,最顯著的是 asInterface(),它接受一個 IBinder(通常是傳遞給客戶端的 onServiceConnected() 回呼方法的那個)并回傳一個 stub 介面的實體,
因為咱使用的是 Android Studio ,構建的時候已經幫咱生成好了,
package com.scc.demo.ipc;
public interface IUserInterface extends android.os.IInterface
{
public static class Default implements com.scc.demo.ipc.IUserInterface
{
@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
{
}
@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.scc.demo.ipc.IUserInterface
{
private static final java.lang.String DESCRIPTOR = "com.scc.demo.ipc.IUserInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
public static com.scc.demo.ipc.IUserInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.scc.demo.ipc.IUserInterface))) {
return ((com.scc.demo.ipc.IUserInterface)iin);
}
return new com.scc.demo.ipc.IUserInterface.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
{
...
}
private static class Proxy implements com.scc.demo.ipc.IUserInterface
{
...
}
static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
public static boolean setDefaultImpl(com.scc.demo.ipc.IUserInterface impl) {
...
}
public static com.scc.demo.ipc.IUserInterface getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
/**
* 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;
}
💥 向客戶端公開介面
既然你服務端的介面已經定義好了,那就公開給客戶端,要不客戶端怎么呼叫,
public class AIDLService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
//回傳你的介面
return stub;
}
private IUserInterface.Stub stub = new IUserInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
//你的邏輯
}
};
}
好了,解釋完了,上手搞,
🔥 實體
💥 User.java
創建一個實體并進行序列化,具體程序就不描述了,
public class User implements Parcelable {
String name;
int age;
...
}
💥 IUserInterface.aidl
// IUserInterface.aidl
package com.scc.demo.ipc;
// Declare any non-default types here with import statements
parcelable User;
interface IUserInterface {
/**
* 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);
void setUser(in User user);
User getUser();
}
💥 AIDLService.java
public class AIDLService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
//回傳你的介面
return stub;
}
private IUserInterface.Stub stub = new IUserInterface.Stub() {
User user = null;
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void setUser(User user) throws RemoteException {
this.user = user;
MLog.e("AIDLService:"+user.toString());
}
@Override
public User getUser() throws RemoteException {
return user;
}
};
}
別忘記在AndroidMainfest.xml中宣告一下,
💥 MainActivity
public class MainActivity extends ActivityBase implements View.OnClickListener {
IUserInterface iUserInterface ;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
}
ServiceConnection connectionAidl = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iUserInterface = IUserInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
bound = false;
}
};
@Override
protected void onStop() {
super.onStop();
if (bound) {
unbindService(connectionAidl);
bound = false;
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_bind_service:
bindService(new Intent(MainActivity.this, AIDLService.class),connectionAidl, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_setuser:
try {
iUserInterface.setUser(new User("Scc",15));
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case R.id.btn_getuser:
try {
User userG = iUserInterface.getUser();
MLog.e("MainActivity:"+userG.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
}
💥 運行效果

行程也跨了,資料也拿到了,洗洗睡吧,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/341926.html
標籤:其他
