【小資說庫】第13期 應用程序開發人員、DBA和DBMS開發人員的分工是怎樣的?
931
2025-04-05
文章目錄
AIDL 跨進程通信完整流程梳理
1、AIDL 文件編譯
2、注冊服務
3、IMyAidlInterface.Stub.asInterface 方法獲取遠程服務
4、IMyAidlInterface.Stub.Proxy 代理類
5、IMyAidlInterface.Stub.Proxy 代理類方法執行
6、Binder.transact 方法執行
7、IMyAidlInterface.Stub.onTransact 方法執行
8、調用 Service 中實現的 IMyAidlInterface.Stub 抽象方法
AIDL 跨進程通信完整流程梳理
1、AIDL 文件編譯
AIDL 文件 IMyAidlInterface.aidl 在客戶端和服務端都有 , 編譯時 , 都會在 " build\generated\aidl_source_output_dir\debug\out\kim\hsl\aidl_demo " 目錄生成 IMyAidlInterface.java 源文件 ;
這樣在客戶端與服務器端都可以調用 IMyAidlInterface.Stub 類的相關方法 , 主要是 asInterface 方法 , 用于獲取遠程服務或代理 ;
2、注冊服務
在應用中 , 通過綁定 Service 注冊服務 ;
// 通過 Action 和 包名 , 綁定遠程服務 Intent intent = new Intent("android.intent.action.MyService"); intent.setPackage("kim.hsl.aidl_demo"); bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
1
2
3
4
3、IMyAidlInterface.Stub.asInterface 方法獲取遠程服務
開啟一個 ServiceConnection , 在 ServiceConnection 的 onServiceConnected 方法中 ,
調用 IMyAidlInterface.Stub.asInterface 方法 ,
在 IMyAidlInterface.Stub.asInterface 方法中 , 傳入我們需要的 Service 遠程服務 ; 這里涉及到跨進程調用 , 拿到的是一個代理 ;
Stub 中定義了 asInterface 方法 , 該方法的作用是將 android.os.IBinder 對象轉為 AIDL 接口對象 ; 傳入的 DESCRIPTOR 描述符 , 用于描述用戶想要哪個 Binder , android.os.IBinder 對象調用 queryLocalInterface 方法 , 檢查本地服務是否存在 ;
如果可以找到本地服務對應的接口 , 可以直接返回本地服務 ;
如果沒有找到本地服務 , 就會返回一個 Stub 代理 ;
詳細的過程參考下面的代碼 :
/** * 將IBinder對象強制轉換為kim.hsl.aidl_demo.IMyAidlInterface接口,必要時生成代理。 */ public static kim.hsl.aidl_demo.IMyAidlInterface asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } // 傳入 DESCRIPTOR 描述符 , 用于描述用戶想要哪個 Binder // android.os.IBinder 對象調用 queryLocalInterface 方法 , 檢查本地服務 android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); // 如果可以找到本地服務對應的接口 , 可以直接返回本地服務 if (((iin!=null)&&(iin instanceof kim.hsl.aidl_demo.IMyAidlInterface))) { return ((kim.hsl.aidl_demo.IMyAidlInterface)iin); } // 如果沒有找到本地服務 , 就會返回一個 Stub 代理 return new kim.hsl.aidl_demo.IMyAidlInterface.Stub.Proxy(obj); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
4、IMyAidlInterface.Stub.Proxy 代理類
上述 IMyAidlInterface.Stub.asInterface 方法 , 最終返回一個代理 , 代理如下 :
在 IMyAidlInterface.java 中的代理中 , 實現了 3 3 3 個 AIDL 接口方法 ;
private static class Proxy implements kim.hsl.aidl_demo.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 { } /** * in 寫入, out 輸出, inout 寫入和輸出 */ @Override public void addStudent(kim.hsl.aidl_demo.Student student) throws android.os.RemoteException { } /** * 獲取 Student 集合 */ @Override public java.util.List
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
5、IMyAidlInterface.Stub.Proxy 代理類方法執行
在主應用中 , 調用 IMyAidlInterface aidl 也就是 IMyAidlInterface.Stub.asInterface 方法返回的代理對象的 addStudent 方法 , 分析代理中的該方法 , 首先生成輸入和輸出數據 , 傳參和反參都會傳入 mRemote.transact 方法中 , 這是 Binder 的方法 ;
/** * in 寫入, out 輸出, inout 寫入和輸出 */ @Override public void addStudent(kim.hsl.aidl_demo.Student student) throws android.os.RemoteException { // 通過 Parcel 池獲得兩個對象 , 分別用于輸入和輸出 // 輸入對象 android.os.Parcel _data = android.os.Parcel.obtain(); // 輸出對象 android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); if ((student!=null)) { _data.writeInt(1); student.writeToParcel(_data, 0); } else { _data.writeInt(0); } // 調用 Binder 的 transact 方法 boolean _status = mRemote.transact(Stub.TRANSACTION_addStudent, _data, _reply, 0); if (!_status && getDefaultImpl() != null) { getDefaultImpl().addStudent(student); return; } _reply.readException(); if ((0!=_reply.readInt())) { student.readFromParcel(_reply); } } finally { _reply.recycle(); _data.recycle(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
6、Binder.transact 方法執行
Binder 中的 transact 方法執行后 , 會回調 IMyAidlInterface.java 中的 Stub 內部類的 onTransact 方法 ,
Binder 的 transact 方法 ; 進入該方法后 , 會將原來的線程掛起 , 直到返回 , 原來的線程才會繼續執行 , 這里非常容易出現 ANR ;
/** * 遠程對象的基類,由{@link IBinder}定義的輕量級遠程過程調用機制的核心部分。 * 此類是IBinder的一個實現,它提供了此類對象的標準本地實現。 * *
大多數開發人員不會直接實現這個類, * 而是使用aidl工具來描述所需的接口, * 讓它生成適當的Binder子類。 * 然而,您可以直接從Binder派生來實現您自己的定制RPC協議, * 或者直接實例化一個原始Binder對象,將其用作可以跨進程共享的令牌。 * *
這個類只是一個基本的IPC原語; * 它對應用程序的生命周期沒有影響,并且只有創建它的進程繼續運行時才有效。 * 要正確使用此功能,您必須在頂級應用程序組件(a{@link android.app.Service}、 * {@link android.app.Activity}或{@link android.content.ContentProvider}) * 的上下文中執行此操作,該組件應保持運行。
* *您必須記住流程可能會消失的情況,因此需要稍后重新創建新的活頁夾, * 并在流程再次啟動時重新附加它。 * 例如,如果您在{@link android.app.Activity}中使用此函數, * 則您的活動的進程可能會在活動未啟動時被終止; * 如果以后重新創建活動,則需要創建新的活頁夾, * 并再次將其交回正確的位置; * 您需要注意的是,您的流程可能由于其他原因(例如接收廣播)而啟動, * 這將不涉及重新創建活動,因此運行其代碼以創建新的綁定。
* * @see IBinder */ public class Binder implements IBinder { /** * 默認實現回放地塊并調用onTransact。在遠程端,transact調用綁定器來執行IPC。 */ 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; } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
7、IMyAidlInterface.Stub.onTransact 方法執行
在 IMyAidlInterface.Stub.onTransact 方法中 , 通過方法對應的 ID 常量值匹配方法 , 在該方法中就會調用 IMyAidlInterface.Stub 中沒有實現的抽象方法 ;
@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_basicTypes: { return true; } case TRANSACTION_addStudent: { return true; } case TRANSACTION_getStudents: { return true; } default: { return super.onTransact(code, data, reply, flags); } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
8、調用 Service 中實現的 IMyAidlInterface.Stub 抽象方法
IMyAidlInterface.Stub 中的抽象方法 , 在 Service 中實現 ;
/** * 創建 IMyAidlInterface.Stub 抽象類子類對象 , 實現其中的 3 個抽象方法 * Binder 調用 transact 方法時 , 會調用 IMyAidlInterface.Stub 的 onTransact 方法 * 在 IMyAidlInterface.Stub.onTransact 方法中會調用下面實現的抽象方法 */ private IMyAidlInterface.Stub stub = new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { Log.i(TAG, "anInt=" + anInt + " , aLong=" + aLong + " , aBoolean=" + aBoolean + " , aFloat=" + aFloat + " , aDouble=" + aDouble + " , aString=" + aString); } @Override public void addStudent(Student student) throws RemoteException { if (students != null) { students.add(student); } } @Override public List
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
任務調度
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。