Android AIDL使用介绍(1)基本使用
1.什么是AIDL
AIDL全稱是Android Interface Definition Language,中文譯為Android接口定義語言,AIDL的提出是為了解決進程間通訊,我們知道,在Android系統(tǒng)中,每個進程在內(nèi)存中是相互獨立的,類似一個個獨立王國,一個進程通常情況下無法訪問其他進程的內(nèi)存,但進程之間不是老死不相往來的狀態(tài),他們之間有許多數(shù)據(jù)交互的需求,為此提出了AIDL,通過AIDL,定義雙方認可的數(shù)據(jù)交互接口,再由AIDL翻譯成操作系統(tǒng)理解的底層語言,進而實現(xiàn)進程間通訊。
2.AIDL的使用
進程間通訊轉(zhuǎn)換成具體業(yè)務邏輯則是一個服務端和客戶端的會話。服務端和客戶端約定好AIDL接口,服務端實現(xiàn)接口的具體邏輯并暴露給客戶端,客戶端再調(diào)用接口。既然涉及到兩方,則在工程中也創(chuàng)建服務端和客戶端兩個項目,見圖2,我的是服務端和客戶端放在一個工程下,分開放在兩個工程目錄下也是可行的。
具體的開發(fā)步驟如下:
1.服務端創(chuàng)建.aidl文件
AIDL接口和日常生活的合同比較相似,服務端和客戶端約定AIDL接口相當于雙方草擬業(yè)務合作合同,開發(fā)過程中一般都在服務端這邊準備合同,也即在服務端創(chuàng)建.aidl文件,方法為:
a.在service模塊下的main目錄下,新建aidl文件,在其之下新建一個包(package),包名自定義,然后右鍵新建.aidl文件,如圖所示,aidl文件名字自定義,確定之后,AS幫我們新建一個.aidl文件。
b.點開新建的aidl文件會發(fā)現(xiàn)不是空白,而是有了內(nèi)容,這是AS自動生成幫忙填寫的內(nèi)容,其中basicTypes接口是演示AIDL可直接使用的基本數(shù)據(jù)類型,如果想用自己定義的數(shù)據(jù)類型,還需要做一些操作,這將在另一篇博客說明。刪掉basicType后,填上要實現(xiàn)的接口,這里填寫ServiceGreet,表示服務端跟客戶端打個招呼,代碼內(nèi)容如下,添加之后記得同步一下工程,否則在調(diào)用還是默認的basicType函數(shù),這樣aidl文件創(chuàng)建好了。
package com.pm.service;interface ServiceAidlInterface {String ServiceGreet(); }2.服務端實現(xiàn)接口
aidl文件創(chuàng)建成功后,也就是草擬好了合同,接下來就是履行合同的過程,即服務端這邊根據(jù)aidl文件實現(xiàn)接口。
我們注意到,aidl文件有別于java格式文件,aidl文件那怎么和java聯(lián)系起來呢,畢竟開發(fā)語言是java。實際上在創(chuàng)建aidl文件時,Android SDK工具自動生成一個同名的java接口,例如ServiceAidlInterface.aidl生成的文件名是ServiceAidlInterface.java,服務端調(diào)用接口實際是和該java文件打交道,這也是為什么創(chuàng)建或者更改aidl文件要及時同步的原因,如果同步不及時,SDK工具可能不及時自動生成的更新java接口。
AS根據(jù)aidl文件自動生成的java接口里有一個名為 Stub 的內(nèi)部抽象類,Stub意思是存根,根據(jù)百度百科,存根意思是票據(jù)、證件等開出后所留的底子,這個抽象類的確有這個意思,具體需要另外展開文章來說明了,這里可先簡單理解一下,我們把aidl進程間通訊理解成銀行匯款過程,服務端通過該銀行匯款(數(shù)據(jù)交互)給客戶端,在aidl里聲明的各種接口相當于匯款單,實現(xiàn)接口相當于打入錢的過程,從這個角度可勉強理解存根的意義,現(xiàn)實中拿到存根已經(jīng)匯完錢了,而這里是拿到存根再匯錢(即實現(xiàn)接口),實際上,實現(xiàn) .aidl 生成的接口是擴展生成的YourInterface.Stub接口的過程,實現(xiàn)接口的代碼如下:
package com.pm.service;import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException;public class MyService extends Service {private ServiceAidlInterface.Stub serviceAidlInterface= new ServiceAidlInterface.Stub() {@Overridepublic String ServiceGreet() throws RemoteException {return "Hello Client!";}};@Overridepublic IBinder onBind(Intent intent) {return serviceAidlInterface.asBinder();} }最后別忘了在AndroidManifest.xml注冊服務,內(nèi)容如下
<serviceandroid:name=".MyService"android:exported="true"><intent-filter><action android:name="com.pm.service.MyService" /><category android:name="android.intent.category.DEFAULT" /></intent-filter>這樣服務端工作就完成了。
3.客戶端調(diào)用接口
現(xiàn)實中合同都是一式兩份的,這里也不例外,客戶端也要拿到aidl文件,而且要求aidl所在的包名必須和服務端aidl所在的包名一致,最穩(wěn)妥的辦法是直接整個拷貝服務端的aidl目錄,同樣的,拷貝完aidl文件之后,也要及時同步一下項目,AS才能及時自動生成對應的java接口。
3.1 首先,建立一個服務連接,在連接上時,初始化接口,代碼如下,我們注意到,這里還是用的Stub,這樣和服務端的存根對得上
private ServiceConnection connection=new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {serviceAidlInterface = ServiceAidlInterface.Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName name) {}};3.2 傳入第一步創(chuàng)建的連接,綁定服務,這樣客戶端和服務端同呼吸共命運了
private void bindService() {Intent intent = new Intent();intent.setAction("com.pm.service.MyService");intent.setPackage("com.pm.service");this.bindService(intent, connection, BIND_AUTO_CREATE);}3.3 最后一步是調(diào)用接口了,這一步比較簡單,調(diào)用服務器打招呼接口
String greet= serviceAidlInterface.ServiceGreet();tvInfo.setText(greet);3.總結
把aidl當成一個合同文件來理解,有助于理解aidl的作用,其中因為存根概念,又從銀行匯款來理解。aidl創(chuàng)建后,Android SDK工具,這里是Android Studio自動幫忙生成對應的java接口,前提是要及時同步工程,工程不及時同步的話,aidl文件更新了,對應的java接口還是舊數(shù)據(jù)。aidl創(chuàng)建之后,服務器實現(xiàn)Stub存根里的方法,之后aidl拷貝給客戶端,客戶端創(chuàng)建連接,在連接里實例化存根,這樣便取出了存根里的方法,最后綁定服務后調(diào)用即可。
最后附上完整客戶端代碼和布局
package com.pm.myaidldemo;import androidx.appcompat.app.AppCompatActivity;import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView;import com.pm.service.ServiceAidlInterface;public class MainActivity extends AppCompatActivity {private Button bServiceGreet;private TextView tvInfo;private ServiceAidlInterface serviceAidlInterface;private ServiceConnection connection=new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {serviceAidlInterface = ServiceAidlInterface.Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName name) {}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bindService();bServiceGreet=findViewById(R.id.btnServiceGreet);tvInfo=findViewById(R.id.tvInfo);bServiceGreet.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {String greet= serviceAidlInterface.ServiceGreet();tvInfo.setText(greet);} catch (RemoteException e) {e.printStackTrace();}}});}private void bindService() {Intent intent = new Intent();intent.setAction("com.pm.service.MyService");intent.setPackage("com.pm.service");this.bindService(intent, connection, BIND_AUTO_CREATE);} }客戶端布局文件
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tvInfo"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/btnServiceGreet"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Button"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>總結
以上是生活随笔為你收集整理的Android AIDL使用介绍(1)基本使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android Service介绍
- 下一篇: Android AIDL使用介绍(2)自