日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Android IPC系列(一):AIDL使用详解

發(fā)布時(shí)間:2023/12/2 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android IPC系列(一):AIDL使用详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

概述

AIDL可以實(shí)現(xiàn)進(jìn)程間的通信,由于每個(gè)進(jìn)程都是運(yùn)行在獨(dú)立的空間,不同的進(jìn)程想要交互需要借助一些特殊的方式,AIDL就是其中的一種,AIDL是一種模板,因?yàn)閷?shí)際交互過(guò)程中,并不是AIDL起的作用,具體會(huì)在之后源碼分析解釋,AIDL的作用是為了避免重復(fù)編寫代碼而出現(xiàn)的一個(gè)模板

語(yǔ)法

AIDL的語(yǔ)法十分簡(jiǎn)單,與Java語(yǔ)言基本保持一致,需要記住的規(guī)則有以下幾點(diǎn):

  • AIDL文件以 .aidl 為后綴名 AIDL支持的數(shù)據(jù)類型分為如下幾種:

    • 八種基本數(shù)據(jù)類型:byte、char、int、long、float、double、boolean String,CharSequence,其中不支持short類型
    • 實(shí)現(xiàn)了Parcelable接口的數(shù)據(jù)類型
    • List 類型。List承載的數(shù)據(jù)必須是AIDL支持的類型,或者是其它聲明的AIDL對(duì)象
    • Map類型。Map承載的數(shù)據(jù)必須是AIDL支持的類型,或者是其它聲明的AIDL對(duì)象
  • 定向Tag。定向Tag表示在跨進(jìn)程通信中數(shù)據(jù)的流向,用于標(biāo)注方法的參數(shù)值,分為 in、out、inout 三種。其中

    • in 表示數(shù)據(jù)只能由客戶端流向服務(wù)端
    • out 表示數(shù)據(jù)只能由服務(wù)端流向客戶端
    • inout 則表示數(shù)據(jù)可在服務(wù)端與客戶端之間雙向流通
    • 此外,如果AIDL方法接口的參數(shù)值類型是:基本數(shù)據(jù)類型、String、CharSequence或者其他AIDL文件定義的方法接口,那么這些參數(shù)值的定向 Tag 默認(rèn)是且只能是 in,所以除了這些類型外,其他參數(shù)值都需要明確標(biāo)注使用哪種定向Tag。定向Tag具體的使用差別后邊會(huì)有介紹
  • 明確導(dǎo)包。在AIDL文件中需要明確標(biāo)明引用到的數(shù)據(jù)類型所在的包名,即使兩個(gè)文件處在同個(gè)包名下

服務(wù)端

  • 先建立一個(gè)項(xiàng)目
  • 由于要傳輸自定義User對(duì)象,所以定義一個(gè)User的aidl文件,直接生成 創(chuàng)建完成后,系統(tǒng)就會(huì)默認(rèn)創(chuàng)建一個(gè) aidl 文件夾,文件夾下的目錄結(jié)構(gòu)即是工程的包名,Book.aidi 文件就在其中 然后更改User.aidl文件內(nèi)容
package com.baidu.bpit.aibaidu.aidl;parcelable User; 復(fù)制代碼
  • 然后生成一個(gè)User的類,實(shí)現(xiàn)Parcelable
public class User implements Parcelable {public String name;public User(String name){this.name=name;}protected User(Parcel in) {name = in.readString();}public static final Creator<User> CREATOR = new Creator<User>() {@Overridepublic User createFromParcel(Parcel in) {return new User(in);}@Overridepublic User[] newArray(int size) {return new User[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(name);} } 復(fù)制代碼
  • 然后在定義一個(gè)BookName的aidl文件,向客戶端暴露可調(diào)用的接口,需要手動(dòng)導(dǎo)入U(xiǎn)ser,import com.baidu.bpit.aibaidu.aidl.User;
package com.baidu.bpit.aibaidu.aidl; import com.baidu.bpit.aibaidu.aidl.User; interface BookName {String getName();List<User> getList();} 復(fù)制代碼
  • 這時(shí)候重新build一下工程
  • 現(xiàn)在需要來(lái)創(chuàng)建一個(gè) Service 供客戶端遠(yuǎn)程綁定了,返回你的自定義的Binder
public class ServiceService extends Service {public ServiceService() {}@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}class MyBinder extends BookName.Stub {@Overridepublic String getName() throws RemoteException {return "西游記";}@Overridepublic List<User> getList() throws RemoteException {User user = new User("111");User user1 = new User("222");List<User> users = new ArrayList<>();users.add(user1);users.add(user);return users;}} } 復(fù)制代碼
  • AndroidManifest.xml文件定義
<serviceandroid:name=".ServiceService"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.aaa.aaa" /></intent-filter></service> 復(fù)制代碼

客戶端

  • 首先把服務(wù)端的aidl文件夾,整體復(fù)制到客戶端
  • 之后,需要?jiǎng)?chuàng)建和服務(wù)端User類所在的相同包名來(lái)存放 User類
  • 在MainActivity綁定服務(wù)端的service,點(diǎn)擊按鈕獲取書名
public class MainActivity extends AppCompatActivity {private BookName bookName;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bindServer();initView();}private void initView() {findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {Log.d("mmmgetName", bookName.getName());List<User> list = bookName.getList();for (User user : list) {Log.d("mmmgetList", user.name);}} catch (RemoteException e) {e.printStackTrace();}}});}private void bindServer() {Intent mIntent = new Intent();//你定義的service的actionmIntent.setAction("com.aaa.aaa");//這里你需要設(shè)置你應(yīng)用的包名mIntent.setPackage("com.baidu.bpit.aibaidu.aidl");bindService(mIntent, new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {bookName = BookName.Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName name) {}}, BIND_AUTO_CREATE);} }復(fù)制代碼
  • 點(diǎn)擊按鈕打印
01-18 22:11:17.642 4542-4542/com.baidu.bpit.aibaidu.client D/mmmgetName: 西游記 01-18 22:11:17.643 4542-4542/com.baidu.bpit.aibaidu.client D/mmmgetList: 222111 復(fù)制代碼

正確獲取數(shù)據(jù)

定向TAG

有三種定向TAG

  • inout:服務(wù)端修改數(shù)據(jù),會(huì)同步到客戶端,因此可以說(shuō)數(shù)據(jù)是雙向流動(dòng)的
  • in:數(shù)據(jù)只從客戶端流向服務(wù)端,服務(wù)端修改數(shù)據(jù)不會(huì)影響客戶端
  • out:數(shù)據(jù)只能由服務(wù)端傳向客戶端,及時(shí)客戶端傳入一個(gè)對(duì)象,這個(gè)對(duì)象也是空的,即沒(méi)有數(shù)據(jù),服務(wù)端獲取該對(duì)象后,對(duì)該對(duì)象任何操作都會(huì)同步到客戶端這里

修改aidl

interface BookName {String getName();List<User> getList();void addInout(inout User user);void addIn(in User user);void addout(out User user);} 復(fù)制代碼

這次增加了三個(gè)方法addInout,addIn,addout,之后分別測(cè)試這三個(gè)方法

修改User類 User類需要添加倆個(gè)方法,一個(gè)無(wú)參構(gòu)造,一個(gè)readFromParcel

public class User implements Parcelable {public String name;public User(){}public User(String name){this.name=name;}protected User(Parcel in) {name = in.readString();}public static final Creator<User> CREATOR = new Creator<User>() {@Overridepublic User createFromParcel(Parcel in) {return new User(in);}@Overridepublic User[] newArray(int size) {return new User[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(name);}public void readFromParcel(Parcel dest) {name = dest.readString();} } 復(fù)制代碼

先測(cè)試一下inout

服務(wù)端

public class ServiceService extends Service {public ServiceService() {}@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}class MyBinder extends BookName.Stub {@Overridepublic String getName() throws RemoteException {return "西游記";}@Overridepublic List<User> getList() throws RemoteException {User user = new User("111");User user1 = new User("222");List<User> users = new ArrayList<>();users.add(user1);users.add(user);return users;}@Overridepublic void addInout(User user) throws RemoteException {Log.d("mmmserver","服務(wù)端獲取到:"+user.name);user.name="服務(wù)端更改";Log.d("mmmserver","服務(wù)端修改書名:"+user.name);}@Overridepublic void addIn(User user) throws RemoteException {}@Overridepublic void addout(User user) throws RemoteException {}} } 復(fù)制代碼

主要看inout方法,服務(wù)端接受到客戶端傳來(lái)的信息后,修改信息內(nèi)容

客戶端

private void initView() {findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {User user = new User("客戶端傳入");Log.d("mmmclient", "客戶端向服務(wù)端傳入一本書,書名:" + user.name);bookName.addInout(user);Log.d("mmmclient", "服務(wù)端修改書名后,書名:" + user.name);} catch (RemoteException e) {e.printStackTrace();}}});} 復(fù)制代碼

點(diǎn)擊按鈕后,向服務(wù)端傳入數(shù)據(jù),服務(wù)端收到數(shù)據(jù),會(huì)對(duì)數(shù)據(jù)更改,客戶端再次查看此數(shù)據(jù),看是否同步

01-18 23:15:18.529 5606-5606/com.baidu.bpit.aibaidu.client D/mmmclient: 客戶端向服務(wù)端傳入一本書,書名:客戶端傳入 01-18 23:15:18.529 5527-5554/com.baidu.bpit.aibaidu.aidl D/mmmserver: 服務(wù)端獲取到:客戶端傳入 01-18 23:15:18.530 5527-5554/com.baidu.bpit.aibaidu.aidl D/mmmserver: 服務(wù)端修改書名:服務(wù)端更改 01-18 23:15:18.530 5606-5606/com.baidu.bpit.aibaidu.client D/mmmclient: 服務(wù)端修改書名后,書名:服務(wù)端更改 復(fù)制代碼

看到服務(wù)端修改可以及時(shí)同步到客戶端,這就是inout 數(shù)據(jù)雙向流動(dòng)

測(cè)試in

服務(wù)端

@Overridepublic void addIn(User user) throws RemoteException {Log.d("mmmserverIn", "服務(wù)端獲取到:" + user.name);user.name = "服務(wù)端更改";Log.d("mmmserverIn", "服務(wù)端修改書名:" + user.name);} 復(fù)制代碼

客戶端

private void initView() {findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {User user = new User("客戶端傳入");Log.d("mmmclient", "客戶端向服務(wù)端傳入一本書,書名:" + user.name);bookName.addIn(user);Log.d("mmmclient", "服務(wù)端修改書名后,書名:" + user.name);} catch (RemoteException e) {e.printStackTrace();}}});} 復(fù)制代碼

當(dāng)點(diǎn)擊按鈕,會(huì)發(fā)送數(shù)據(jù)到服務(wù)端,服務(wù)端會(huì)更改數(shù)據(jù)內(nèi)容,客戶端再次查看數(shù)據(jù),看是否被改變

01-18 23:26:23.079 5815-5815/com.baidu.bpit.aibaidu.client D/mmmclient: 客戶端向服務(wù)端傳入一本書,書名:客戶端傳入 01-18 23:26:23.080 5736-5763/com.baidu.bpit.aibaidu.aidl D/mmmserverIn: 服務(wù)端獲取到:客戶端傳入 01-18 23:26:23.081 5736-5763/com.baidu.bpit.aibaidu.aidl D/mmmserverIn: 服務(wù)端修改書名:服務(wù)端更改 01-18 23:26:23.081 5815-5815/com.baidu.bpit.aibaidu.client D/mmmclient: 服務(wù)端修改書名后,書名:客戶端傳入 復(fù)制代碼

看以看出服務(wù)端修改數(shù)據(jù),并不會(huì)影響客戶端

測(cè)試OUT

服務(wù)端

@Overridepublic void addout(User user) throws RemoteException {Log.d("mmmserverout", "服務(wù)端獲取到:" + user.name);user.name = "服務(wù)端更改";Log.d("mmmserverout", "服務(wù)端修改書名:" + user.name);} 復(fù)制代碼

客戶端

private void initView() {findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {User user = new User("客戶端傳入");Log.d("mmmclient", "客戶端向服務(wù)端傳入一本書,書名:" + user.name);bookName.addout(user);Log.d("mmmclient", "服務(wù)端修改書名后,書名:" + user.name);} catch (RemoteException e) {e.printStackTrace();}}});} 復(fù)制代碼

客戶端向服務(wù)端傳入數(shù)據(jù),服務(wù)端收到后,更改數(shù)據(jù),客戶端再次查看數(shù)據(jù)

01-18 23:36:21.997 6100-6100/com.baidu.bpit.aibaidu.client D/mmmclient: 客戶端向服務(wù)端傳入一本書,書名:客戶端傳入 01-18 23:36:21.998 6023-6037/com.baidu.bpit.aibaidu.aidl D/mmmserverout: 服務(wù)端獲取到:null服務(wù)端修改書名:服務(wù)端更改 01-18 23:36:21.998 6100-6100/com.baidu.bpit.aibaidu.client D/mmmclient: 服務(wù)端修改書名后,書名:服務(wù)端更改 復(fù)制代碼

可以看到服務(wù)端收到的是空對(duì)象,服務(wù)端更改影響客戶端

GitHub: 參考:www.jianshu.com/p/29999c1a9…

轉(zhuǎn)載于:https://juejin.im/post/5d4d12e7518825237b5bdb4d

總結(jié)

以上是生活随笔為你收集整理的Android IPC系列(一):AIDL使用详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。