Android 深入淺出AIDL(一)

前言

本文主要講述AIDL作用以及如何快速上手AIDL項(xiàng)目

簡(jiǎn)介

A [android]
I [Interface]
D [Definition]
L [Language]
Android接口定義語言。
作用:方便系統(tǒng)為我們生成代碼從而實(shí)現(xiàn)跨進(jìn)程通訊,僅此而已。(玉剛老師如是說也),也就是說這個(gè)AIDL就只是一個(gè)快速跨進(jìn)程通訊的工具。

快速上手

本篇文章意在快速實(shí)現(xiàn)AIDL項(xiàng)目,更多詳細(xì)內(nèi)容下篇繼續(xù)闡述。

在服務(wù)端創(chuàng)建AIDL文件,用來聲明java Bean以及傳輸調(diào)用的接口?!韭暶魑募?br> 在服務(wù)端創(chuàng)建Service并且實(shí)現(xiàn)上面的接口?!緞?chuàng)建服務(wù)】
客戶端綁定Service?!窘壎ǚ?wù)】
客戶端調(diào)用服務(wù)端接口?!究邕M(jìn)程調(diào)用】

服務(wù)端

創(chuàng)建服務(wù)端項(xiàng)目
首先我們?cè)赼pp/src/main 目錄下創(chuàng)建AIDL文件夾。


image.png

創(chuàng)建載體MessageBean

首先我們?cè)谶@個(gè)AIDL文件夾里創(chuàng)建用來傳輸?shù)膉ava Bean對(duì)象(包名并不重要),并且實(shí)現(xiàn)Parcelable接口(建議使用Parcelable插件),因?yàn)檫M(jìn)程間通訊需要將該對(duì)象轉(zhuǎn)化為字節(jié)序列,用于傳輸或者存儲(chǔ)。(傳遞的載體)

public class MessageBean implements Parcelable {
private String content;//需求內(nèi)容
private int level;//重要等級(jí)

``````
get set方法
``````

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.content);
    dest.writeInt(this.level);
}

//如果需要支持定向tag為out,inout,就要重寫該方法
public void readFromParcel(Parcel dest) {
    //注意,此處的讀值順序應(yīng)當(dāng)是和writeToParcel()方法中一致的
    this.content = dest.readString();
    this.level = dest.readInt();
}
protected MessageBean(Parcel in) {
    this.content = in.readString();
    this.level = in.readInt();
}
public MessageBean() {

public static final Creator<MessageBean> CREATOR = new Creator<MessageBean>() {
    @Override
    public MessageBean createFromParcel(Parcel source) {
        return new MessageBean(source);
    }

    @Override
    public MessageBean[] newArray(int size) {
        return new MessageBean[size];
    }
};
}

創(chuàng)建AIDL文件MessageBean.AIDL

因?yàn)锳IDL這個(gè)語言的規(guī)范就是aidl文件,所以我們必須將MessageBean轉(zhuǎn)為aidl文件,供其它aidl的調(diào)用與交互。就這么簡(jiǎn)單,一個(gè)文件里面兩行代碼。(這個(gè)文件要與java Bean放置同一包下)

package qdx.aidlserver;//手動(dòng)導(dǎo)包
parcelable MessageBean;//parcelable是小寫

AIDL文件與java文件的區(qū)別

文件類型:用AIDL書寫的文件的后綴是 .aidl,而不是 .java。
數(shù)據(jù)類型:AIDL默認(rèn)支持一些數(shù)據(jù)類型,在使用這些數(shù)據(jù)類型的時(shí)候是不需要導(dǎo)包的,但是除了這些類型之外的數(shù)據(jù)類型,在使用之前必須導(dǎo)包,就算目標(biāo)文件與當(dāng)前正在編寫的 .aidl 文件在同一個(gè)包下——在 Java 中,這種情況是不需要導(dǎo)包的。比如,現(xiàn)在我們編寫了兩個(gè)文件,一個(gè)叫做 IDemandManager.java ,另一個(gè)叫做 IDemandManager.aidl,它們都在 qdx.aidlserver 包下 ,現(xiàn)在我們需要在 .aidl 文件里使用 MessageBean 對(duì)象,那么我們就必須在 .aidl 文件里面寫上 import qdx.aidlserver.MessageBean; 哪怕 .java 文件和 .aidl 文件就在一個(gè)包下。

默認(rèn)支持的數(shù)據(jù)類型
Java中的八種基本數(shù)據(jù)類型( byte,short(不支持short,編譯不通過),int,long,float,double,boolean,char)
String 和 CharSequence類型
List : List中的所有元素必須是AIDL支持的類型之一,里面的每個(gè)元素都必須能夠被AIDL支持
Map : Map中的所有元素必須是AIDL支持的類型之一,包括key和value
Parcelabel : 所有實(shí)現(xiàn)了Parcelabel 接口的對(duì)象
AILD : 所有的AIDL接口本身也可以在AIDL文件中使用

創(chuàng)建AIDL文件IDemandManager.AIDL

我們創(chuàng)建IDemandManager接口用來實(shí)現(xiàn)傳遞方法。
另外方法內(nèi)如果有傳輸載體,就必須指明定向tag(in,out,inout)

  • in : 客戶端數(shù)據(jù)對(duì)象流向服務(wù)端,并且服務(wù)端對(duì)該數(shù)據(jù)對(duì)象的修改不會(huì)影響到客戶端。

  • out : 數(shù)據(jù)對(duì)象由服務(wù)端流向客戶端,(客戶端傳遞的數(shù)據(jù)對(duì)象此時(shí)服務(wù)端收到的對(duì)象內(nèi)容為空,服務(wù)端可以對(duì)該數(shù)據(jù)對(duì)象修改,并傳給客戶端)

  • inout : 以上兩種數(shù)據(jù)流向的結(jié)合體。(但是不建議用此tag,會(huì)增加開銷)

    package qdx.aidlserver;
    
    import qdx.aidlserver.MessageBean;
     import qdx.aidlserver.IDemandListener;
    
    interface IDemandManager {
    MessageBean getDemand();
    
     void setDemandIn(in MessageBean msg);//客戶端->服務(wù)端
    
     //out和inout都需要重寫MessageBean的readFromParcel方法
     void setDemandOut(out MessageBean msg);//服務(wù)端->客戶端
    
    void setDemandInOut(inout MessageBean msg);//客戶端<->服務(wù)端
    }
    

埋坑與完善

該篇文章內(nèi)容不多,但是處處皆是精華,尤其是以下3條建議,以防引起慘案。

  1. xxx.aidl 中不能存在同方法名不同參數(shù)的方法。

  2. xxx.aidl 中實(shí)體類必須要有指定的tag。

  3. 在Android Studio里寫完aidl文件還需要在build.gradle文件中android{}方法內(nèi)添加aidl路徑。

    sourceSets {
     main {
      java.srcDirs = ['src/main/java', 'src/main/aidl']
      }
     }
    

創(chuàng)建Service

最后我們還需要?jiǎng)?chuàng)建一個(gè)服務(wù),用來處理客戶端發(fā)來的請(qǐng)求,或者是定時(shí)推信息到客戶端。

public class AIDLService extends Service {

@Override
public IBinder onBind(Intent intent) {
    return demandManager;
}

//Stub內(nèi)部繼承Binder,具有跨進(jìn)程傳輸能力
IDemandManager.Stub demandManager = new IDemandManager.Stub() {
    @Override
    public MessageBean getDemand() throws RemoteException {
        MessageBean demand = new MessageBean("首先,看到我要敬禮", 1);
        return demand;
    }

    @Override
    public void setDemandIn(MessageBean msg) throws RemoteException {//客戶端數(shù)據(jù)流向服務(wù)端
        Log.i(TAG, "程序員:" + msg.toString());
    }

    @Override
    public void setDemandOut(MessageBean msg) throws RemoteException {//服務(wù)端數(shù)據(jù)流向客戶端
        Log.i(TAG, "程序員:" + msg.toString());//msg內(nèi)容一定為空

        msg.setContent("我不想聽解釋,下班前把所有工作都搞好!");
        msg.setLevel(5);
    }

    @Override
    public void setDemandInOut(MessageBean msg) throws RemoteException {//數(shù)據(jù)互通
        Log.i(TAG, "程序員:" + msg.toString());

        msg.setContent("把用戶交互顏色都改成粉色");
        msg.setLevel(3);
    }
};

}
最后我們?cè)谇鍐挝募凶?cè)服務(wù)
action 為服務(wù)名稱,客戶端可以通過此(com.tengxun.aidl)隱式啟動(dòng)該服務(wù)。
在魅族的手機(jī)上,系統(tǒng)禁止了隱式方法啟動(dòng)服務(wù)的權(quán)限,所以務(wù)必在手機(jī)管家/權(quán)限管理/ 中,開啟該項(xiàng)目的自啟權(quán)限。
<service
android:name=".AIDLService"
android:exported="true">
<intent-filter>
<action android:name="com.tengxun.aidl" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評(píng)論 19 139
  • 前言 在決定用這個(gè)標(biāo)題之前甚是忐忑,主要是擔(dān)心自己對(duì)AIDL的理解不夠深入,到時(shí)候大家看了之后說——你這是什么玩意...
    lypeer閱讀 38,470評(píng)論 22 289
  • Android跨進(jìn)程通信IPC整體內(nèi)容如下 1、Android跨進(jìn)程通信IPC之1——Linux基礎(chǔ)2、Andro...
    隔壁老李頭閱讀 10,969評(píng)論 13 43
  • @Transactional: ?可設(shè)置的屬性: ?value|transactionManager:指定事務(wù)管理...
    換個(gè)名字_b5dd閱讀 565評(píng)論 2 0
  • 因?yàn)榭偸堑貌坏剑詽u漸就不想要了。我明白我們?cè)谝黄鹬皇莻€(gè)錯(cuò)誤,但開頭是美好的。在一起后除了剛開始的甜,之后就會(huì)越...
    清溪淺淺流閱讀 228評(píng)論 0 0

友情鏈接更多精彩內(nèi)容