日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Android跨進程IPC通信AIDL

瀏覽:82日期:2022-09-27 10:00:19
簡介

AIDL:Android Interface Definition Language,即Android接口定義語言,用于生成Android不同進程間進行進程通信(IPC)的代碼,一般情況下一個進程是無法訪問另一個進程的內存的。如果某些情況下仍然需要跨進程訪問內存數據,這時候Android系統就要將其對象分解成能夠識別的原數據,編寫這一組操作的代碼是一項繁瑣的工作,但是AIDL對底層進行了抽象的封裝,簡化了跨進程操作。

在Android中跨進程操作的方式不止一種,四大組件中ContentProvider天生就是為跨進程操作而存在的,但是ContentProvider所謂的跨進程操作數據,這些數據不一定是存放在內存中的,如通訊錄數據時存放在Sqlite數據庫中的。AIDL支持的跨進程操作的數據是要存放在內存中的,AIDL底層實際上也是使用的Binder進行的跨進程操作,后續另起一篇博文繼續介紹Binder的跨進程機制。

使用場景

只有不同應用之間需要進行IPC,并且想要在Service中處理多線程時,這種場景才有必要使用AIDL。如果僅僅需要跨進程但是不是跨應用,這時候應該通過Binder進行數據交互;另外如果僅僅是需要跨進程IPC,但是不需要處理多線程,這時候應該通過Messenger類進行數據交互。

定義AIDL接口

在Android Studio中使用AIDL的項目的目錄結構跟eclipse中有很大差異,下圖是使用AIDL的項目的目錄結構。

Android跨進程IPC通信AIDL

在Android Studio中只需要在某個Module中使用右鍵菜單中new就會顯示創建AIDL文件的菜單,當新建成功后AIDL文件位于工程的同java同一級的aidl目錄文件夾下面。在 .aidl 文件中存放的就是AIDL接口。

定義.aidl文件

.aidl文件名稱必須同接口名稱保持一致,必須使用Java語言的語法定義AIDL文件。AIDL使用簡單語法,通過可帶參數和返回值的一個或多個方法來聲明接口。參數和返回值可以是任意類型,甚至可以是其他 AIDL 生成的接口。每個.aidl文件都必須定義單個接口,并且只需包含接口聲明和方法簽名,也意味著在.aidl文件中接口名稱和方法名稱都不可以使用權限修飾符。

默認情況下,AIDL 支持下列數據類型:

Java語言中所有的基本數據類型,字符類型char,布爾類型boolean以及數值類型byte、short、int、long、float、double; String和CharSequence類型; 集合List類型,List中的所有元素都必須是以上列表中支持的數據類型、其他 AIDL 生成的接口或您聲明的可打包類型。可選擇將 List用作泛型類型(例如,List )。另一端實際接收的具體類始終是 ArrayList,但生成的方法使用的是List接口, 在AIDL中不可以使用ArrayList類型進行定義,只能使用List接口定義 ,否則會報unknown type編譯錯誤。 集合Map類型,中的所有元素都必須是以上列表中支持的數據類型、其他 AIDL 生成的接口或您聲明的可打包類型。不同于集合List接口, 在AIDL中不支持泛型Map(如 Map 形式的 Map)。 另一端實際接收的具體類始終是 HashMap,但生成的方法使用的是 Map 接口。類似List接口, 在.aidl文件中不能使用HashMap,只能使用Map接口 。 自定義類型必須實現Parcelable接口,并且在aidl文件夾下有對應類型的aidl文件; 非JDK中定義的類型,類似于Java語法,必須使用import進行引入。

定義AIDL接口時需要注意如下:

方法可帶零個或多個參數,返回值或空值,但是方法名稱不能相同; 所有非基本數據類型參數都需要指示數據走向的方向標記。可以是 in、out 或 inout。基本數據類型默認為 in,不能是其他方向; .aidl 文件中包括的所有代碼注釋都包含在生成的 IBinder 接口中(import 和 package 語句之前的注釋除外); 只支持方法,不應在AIDL中定義靜態字段。

如下是定義是IRemoteService.aidl:

package com.sunny.server;import com.sunny.server.bean.User; interface IRemoteService { void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); String getName(); void setListData(in List<String> inList,out List<String> outList); void setMapData(in Map map); void setUser(in User user); }

下面是自定義的JavaBean類型User.aidl

package com.sunny.server.bean; parcelable User;

User類在使用的時候必須實現Parcelable接口,代碼這里就不再貼出來了。

Service實現AIDL接口

在定義的AIDL接口編譯后實際上會生成一個跟.aidl同名的Java類文件,里面包含了所有的AIDL文件中聲明的方法,并且包含了一個默認的實現類Stub,該類是抽象類,繼承了Binder類實現了AIDL接口。在Stub類中有兩個方法一個是asInterface()方法,該方法返回的是AIDL文件生成的接口,另外一個方法是asBinder(),該方法返回的是一個IBinder類型的實例。

asInterface()和asBinder()方法非常有用,asInterface()方法可以用于客戶端的IPC方法調用,另外一個方法可以用于在服務端返回Binder實例,并在服務端實現響應的接口方法。

上面介紹過在定義非基本數據類型的時候必須定義數據走向,聲明in或out或者inout,在AIDL生成的Java文件中就可以看出來究竟了,這里可以參看setListData()方法的生成實現。

@Overridepublic void setListData(java.util.List<java.lang.String> inList, java.util.List<java.lang.String> outList) 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.writeStringList(inList); mRemote.transact(Stub.TRANSACTION_setListData, _data, _reply, 0); _reply.readException(); _reply.readStringList(outList); } finally { _reply.recycle(); _data.recycle(); }}

如果聲明數據時是in,在生成相對應的方法的時候調用的實際上是Parcel的writeXXX方法,如果聲明的是out,在實現上面采用的是readXXX,所以在定義的時候一定要明確調用邏輯。

接下來看一下服務端中MyService類的實現。

p

ublic class MyService extends Service { private static final String TAG = 'AIDL_Server'; @Nullable @Override public IBinder onBind(Intent intent) {return mBinder; } private IRemoteService.Stub mBinder = new IRemoteService.Stub() { @Overridepublic void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { Log.d(TAG, 'anInt:' + anInt + ' aLong:' + aLong + ' aBoolean:' + aBoolean + ' aFloat:' + aFloat + ' aDouble:' + aDouble + ' aString:' + aString);} @Overridepublic String getName() throws RemoteException { return 'admin';} @Overridepublic void setListData(List<String> inList, List<String> outList) throws RemoteException { Log.d(TAG, 'inList:' + inList.toString()); setOutList(outList);} @Overridepublic void setMapData(Map map) throws RemoteException { Log.d(TAG, 'map:' + map.toString());} @Overridepublic void setUser(User user) throws RemoteException { Log.d(TAG, 'user:' + user.toString());} }; private void setOutList(List<String> list) {list.add('out_01');list.add('out_02');list.add('out_03'); }}

在MyService類中,除了getName是一個有返回值的方法,其余的方法都是void類型的,另外在數據走向方面,除了setListData方法的第二個參數outList是輸出類型的參數,其余的參數都是輸入類型參數,所以這里將其它參數直接打印出來了。

調用IPC方法

在客戶端想要調用Android的AIDL中定義的IPC方法,可以通過如下步驟實現:

首先需要定義一個相同包名相同目錄的AIDL文件夾; 聲明一個AIDL文件生成的接口實例; 實現ServiceConnection接口; 調用bindService綁定服務,傳入生成的ServiceConnection實例; 在onServiceConnected()實現中,將收到的IBinder實例(名為 service)。調用 XXX.Stub.asInterface((IBinder)service),以將返回的參數轉換為 AIDL生成的接口類型。 通過調用生成的AIDL接口實例中對應的方法就可以實現IPC調用了; 在不使用的時候解除服務的綁定Context.unbindService()。

如下是客戶端Activity中代碼的實現:

public class MainActivity extends AppCompatActivity { private static final String TAG = 'AIDL_Client'; private MyConnection conn; private IRemoteService service; private List<String> outList=new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main); } public void startBind(View v) {Intent intent = new Intent();conn=new MyConnection();intent.setAction('com.sunny.server.service.MyService');bindService(intent, conn, Context.BIND_AUTO_CREATE); } public void startExecute(View v) {try { service.basicTypes(1, 10000L, true, 1.5f, 300.3, 'Hello World'); Log.d(TAG, 'getName:' + service.getName()); List<String> inList = new ArrayList<String>(); inList.add('inList01'); inList.add('inList02'); service.setListData(inList, outList); Log.d(TAG, 'outList:' + outList.toString()); Map<String, String> map = new HashMap<String, String>(); map.put('key01', 'value01'); map.put('key02', 'value02'); service.setMapData(map); User user = new User(); user.setId(1001); user.setName('admin'); service.setUser(user);} catch (RemoteException e) { e.printStackTrace();} } private class MyConnection implements ServiceConnection { public void onServiceConnected(ComponentName name, IBinder binder) { service = IRemoteService.Stub.asInterface(binder);} public void onServiceDisconnected(ComponentName name) {} } @Override protected void onDestroy() {super.onDestroy();unbindService(conn); }} 其它

上述示例只是為了介紹AIDL如何跨進程通信的,所以在客戶端接收到的數據直接就在主線程中處理了。但是實際上客戶端調用服務端的遠程方法,被調用的方法運行在服務端的Binder線程池中的,同時客戶端線程會被掛起,這時候如果服務端方法執行比較耗時,就會導致客戶端長時間阻塞在這里,如果客戶端方法位于UI線程中,可能會引起ANR。在實際開發的時候注意,客戶端進行IPC通信的時候盡量放在子線程中。由于服務端的方法本身就是運行在服務端的Binder線程池中,所以即使服務端需要執行大量耗時的工作也不需要開啟新的線程去執行。

另外一定要注意的就是安全性,默認情況下遠程服務任何人都可以連接,這應該不是我們所需要的,所以還需要考慮一下權限驗證。一般情況下有兩種處理方法,第一種是通過自定義權限的方法,我們在服務端Service方法的onBinder()方法中添加權限驗證,如果權限驗證不通過直接返回null。另外一種就是在服務端的onTransact()方法中做驗證,也是做權限驗證,如果不通過直接返回false。除了上面講的權限驗證之外,可以通過getCallingPid()和getCallingUid()拿到客戶端應用的Pid和Uid進行校驗。

有關AIDL的介紹就先到這里了,后續繼續介紹一下Binder有關內容。

來自:http://www.sunnyang.com/748.html

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲成人不卡| 亚洲女人av| 亚洲欧洲日韩| 蜜桃视频欧美| 99久久夜色精品国产亚洲狼| 日本国产精品| 午夜国产一区二区| 亚洲欧洲另类| 免费一区二区视频| 综合一区在线| 国产欧美一区二区三区国产幕精品| 亚洲日本免费电影| 日韩高清电影一区| 国产精品久久777777毛茸茸| 国产欧美一区二区三区米奇| 国产精品草草| 国产盗摄——sm在线视频| 色天使综合视频| 欧美日韩国产高清电影| 黄色在线一区| 欧美一区=区| 日韩三级一区| 国产精品美女午夜爽爽| 国产精久久一区二区| 成人在线免费观看91| 欧美aa在线观看| 国产精品美女| 日本午夜精品久久久| 国产精品欧美三级在线观看 | 亚洲精品888| 蜜桃视频免费观看一区| 日韩在线电影| 麻豆91精品91久久久的内涵| 欧美精品日日操| 亚洲一区二区网站| 日本天堂一区| 韩国久久久久久| 欧美网站在线| 日韩欧美中文字幕电影| 国产不卡精品| 香蕉视频成人在线观看| 国产精品自拍区| 精品免费av在线| 亚洲三区欧美一区国产二区| 免费在线成人| 91久久中文| 国产精品啊啊啊| 日韩欧美1区| 最新国产精品久久久| 国产在线不卡一区二区三区| 黄色亚洲精品| 国产视频网站一区二区三区| 国产 日韩 欧美一区| 国产精品日韩久久久| 国产精品一在线观看| 久久国产中文字幕| 日韩av资源网| 久久精品亚洲欧美日韩精品中文字幕| 视频一区中文字幕国产| 捆绑调教美女网站视频一区| 亚洲激情av| 麻豆精品在线观看| 欧美成人精品| 国产精品sm| 国产毛片一区| 国产精品大片免费观看| 婷婷亚洲五月色综合| 国产精品羞羞答答在线观看| 欧美日韩四区| 麻豆国产一区| 亚洲有吗中文字幕| 日韩国产一区二区三区| 四虎在线精品| 欧美精选一区二区三区| 国产在线日韩精品| 91成人精品观看| 最新日韩欧美| 欧美经典一区| 无码日韩精品一区二区免费| 亚洲电影在线| 成人国产精品一区二区网站| 日韩激情视频网站| 日韩一级不卡| 高清一区二区三区av| 欧美日韩激情| 岛国av在线播放| 国产精品一区二区免费福利视频| 99视频一区| 人人精品亚洲| 麻豆精品少妇| 日本va欧美va精品| 久久xxxx| 日韩另类视频| 久久精品国产久精国产爱| 亚州av一区| 亚洲欧美高清| 久久蜜桃精品| 成人午夜网址| 欧美激情精品| 欧美一区自拍| 日韩成人精品一区二区三区| 国产综合精品一区| 日韩综合在线| 国产精品片aa在线观看| 日韩高清二区| 亚洲精品第一| 一区二区三区四区日韩| 999久久久国产精品| 欧美男人天堂| 激情久久99| 久久免费福利| 一区在线视频观看| 国产99亚洲| 久久久久国产一区二区| 日产精品一区| 成人看片网站| 亚洲涩涩在线| zzzwww在线看片免费| 成人国产精品| 福利欧美精品在线| 日韩电影免费网址| 日韩在线不卡| 国产精品99一区二区三| 久久精品国产久精国产| 精品视频97| 91一区二区三区四区| 91亚洲人成网污www| 中文另类视频| 亚洲欧洲一区| 亚洲深夜福利在线观看| 日本成人手机在线| 国产精品一区2区3区| 欧美成a人片免费观看久久五月天| 国产精品sss在线观看av| 久久精品国产一区二区| 精品国产乱码久久久| 久草免费在线视频| 精品国产三区在线| 高清在线一区| 成人久久久久| 尤物在线精品| 日韩在线黄色| 国产欧美自拍一区| 精品五月天堂| 麻豆久久久久久久| 日韩欧美午夜| 欧美另类专区| 婷婷综合成人| 免费一区二区三区在线视频| 日韩免费小视频| 国产一区91| 热久久久久久| 成人污污视频| 亚洲视频综合| 亚洲一区二区三区久久久| 久久国产乱子精品免费女| 麻豆国产一区| 久久三级福利| 亚洲专区一区| 国产精品午夜av| 日韩一区二区在线免费| 久久福利毛片| 国产精品资源| 久久精品在线| 亚洲一区二区小说| 国产极品嫩模在线观看91精品| 国产96在线亚洲| 亚洲高清不卡| 日韩伦理在线一区| 国产精品女主播一区二区三区| 欧美在线看片| 欧美成人a交片免费看| 免费视频久久| 国产一区二区三区四区大秀| 黑丝美女一区二区| 国产精品久久久一区二区| 亚洲二区视频| 国产精品亚洲综合久久| 女人av一区| 国产精品丝袜在线播放| 婷婷中文字幕一区| 国产精品久久免费视频| 综合日韩av| 亚洲三级观看| 精品视频网站| 亚洲久草在线| 精品丝袜在线| 欧美日韩午夜| 亚洲女同一区| 久久精品国产亚洲aⅴ| 中文精品在线| 91亚洲国产| 日韩高清电影一区| 不卡av一区二区| 麻豆成人综合网| 亚洲精品亚洲人成在线观看| 亚洲v在线看| 国产精品久久久免费| 在线亚洲自拍| 国产精品专区免费|