詳解Android中AIDL的使用
AIDL,即Android Interface Definition Language,Android接口定義語(yǔ)言。這門(mén)語(yǔ)言是為了實(shí)現(xiàn)進(jìn)程間通信。每一個(gè)進(jìn)程都有自己的一塊獨(dú)立的內(nèi)存,都在自己的內(nèi)存上存儲(chǔ)自己的數(shù)據(jù),執(zhí)行自己的操作,每個(gè)進(jìn)程之間你不知我,我不知你,而AIDL,就是兩個(gè)進(jìn)程之間溝通的橋梁。
AIDL用來(lái)做什么
AIDL是Android中IPC(Inter-Process Communication)方式中的一種,AIDL是Android Interface definition language的縮寫(xiě),對(duì)于小白來(lái)說(shuō),AIDL的作用是讓你可以在自己的APP里綁定一個(gè)其他APP的service,這樣你的APP可以和其他APP交互。
aidl文件支持的數(shù)據(jù)類(lèi)型包括:
- 八種基本數(shù)據(jù)類(lèi)型:byte、char、short、int、long、float、double、boolean
- String、CharSequence
- 實(shí)現(xiàn)了Parcelable接口的數(shù)據(jù)類(lèi)型
- List類(lèi)型。List承載的數(shù)據(jù)必須是AIDL支持的類(lèi)型,或者是其他聲明的AIDL對(duì)象
- Map類(lèi)型。Map承載的數(shù)據(jù)必須是AIDL支持的類(lèi)型,或者是其他聲明的AIDL對(duì)象
在使用其他聲明的AIDL對(duì)象的時(shí)候必須要導(dǎo)包,即使要使用的AIDL對(duì)象文件和當(dāng)前正在編輯的aidl文件在同一個(gè)文件夾下。
aidl文件可以分為兩類(lèi),一類(lèi)用來(lái)聲明實(shí)現(xiàn)了Parcelable接口的數(shù)據(jù)類(lèi)型,以供其他AIDL文件使用那些非默認(rèn)支持的數(shù)據(jù)類(lèi)型。還有一類(lèi)是用來(lái)定義接口方法,聲明要暴露哪些接口給客戶(hù)端調(diào)用。
AIDL的具體使用步驟是:
一、創(chuàng)建一個(gè)服務(wù)端工程
1、如果aidl文件中涉及到實(shí)現(xiàn)了Parcelable接口的數(shù)據(jù)類(lèi)型,則先將該aidl文件定義出來(lái)。在src文件夾下右鍵,選擇新建aidl文件,這里新建了一個(gè)Book.aidl文件。

新建完以后,會(huì)在main文件下生成一個(gè)aidl的文件夾,aidl文件夾下的目錄結(jié)構(gòu)和java文件夾下的目錄結(jié)構(gòu)一樣。

Book.aidl文件中會(huì)有一個(gè)默認(rèn)方法。

我們刪除掉這個(gè)默認(rèn)方法,只聲明一個(gè)parcelable數(shù)據(jù)類(lèi)型,這個(gè)文件就成為聲明Parcelable數(shù)據(jù)類(lèi)型的AIDL文件。注意這里的parcelable中的p是小寫(xiě)的。

2、這個(gè)時(shí)候我們來(lái)定義Book類(lèi)并實(shí)現(xiàn)Parcelable接口,注意Book類(lèi)在java文件夾下的目錄與Book.aidl文件在aidl文件夾下的目錄保持一致。
public class Book implements Parcelable {
private String name;
public Book(String name) {
this.name=name;
}
protected Book(Parcel in) {
this.name = in.readString();
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
/**
* 這個(gè)方法是自己寫(xiě)上去的,并不是根據(jù)錯(cuò)誤提示自動(dòng)生成的代碼
* 默認(rèn)生成的模板類(lèi)的對(duì)象只支持為in的定向tag。因?yàn)槟J(rèn)生成的類(lèi)里面只有 writeToParcel() 方法。
* 而如果要支持為out或者inout的定向tag的話,還需要實(shí)現(xiàn)readFromParcel()方法。
* 而這個(gè)方法其實(shí)并沒(méi)有在 Parcelable 接口里面,所以需要我們從頭寫(xiě)。
*/
public void readFromParcel(Parcel dest){
name=dest.readString();
}
}
這里需要注意的一點(diǎn)是如果要支持為out或inout的定向tag的話,需要我們手寫(xiě)readFromParcel()方法。
3、然后我們開(kāi)始寫(xiě)B(tài)ookController.aidl文件來(lái)定義能被客戶(hù)端調(diào)用的接口。
package com.example.service;
import com.example.service.Book;
// Declare any non-default types here with import statements
interface BookController {
int getInt();//int類(lèi)型
String getString();//String類(lèi)型
List<Book> getBookList();//aidl對(duì)象
void addBook(inout Book book);//aidl對(duì)象
}
這里需要注意的是,雖然Book.aidl文件和BookController.aidl文件在同一個(gè)包下,還是需要手動(dòng)導(dǎo)入一下。
4、至此,我們的aidl文件寫(xiě)完了,然后我們Rebuild project,系統(tǒng)會(huì)幫我們生成一個(gè)與AIDL文件同名的java文件,這個(gè)java文件才是與我們跨進(jìn)程通信密切相關(guān)的東西。
5、定義一個(gè)Service,通過(guò)這個(gè)Service將接口暴露給外部。
public class AIDLService extends Service {
private List<Book> bookList;
public AIDLService() {
}
@Override
public void onCreate() {
super.onCreate();
bookList = new ArrayList<>();
initData();
}
private void initData() {
Book book1 = new Book("花千骨");
Book book2 = new Book("公主小妹");
Book book3 = new Book("仙劍奇?zhèn)b傳");
Book book4 = new Book("飄");
Book book5 = new Book("茶花女");
Book book6 = new Book("解憂雜貨鋪");
Book book7 = new Book("活著");
Book book8 = new Book("三生三世十里桃花");
bookList.add(book1);
bookList.add(book2);
bookList.add(book3);
bookList.add(book4);
bookList.add(book5);
bookList.add(book6);
bookList.add(book7);
bookList.add(book8);
}
private final BookController.Stub stub = new BookController.Stub() {
@Override
public int getInt() throws RemoteException {
return bookList == null ? 0 : bookList.size();
}
@Override
public String getString() throws RemoteException {
return bookList == null ? "" : bookList.get(0).getName();
}
@Override
public List<Book> getBookList() throws RemoteException {
return bookList;
}
@Override
public void addBook(Book book) throws RemoteException {
if (book != null) {
bookList.add(book);
} else {
Log.i("ruxing", "接收到了一個(gè)空對(duì)象 Inout");
}
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return stub;
}
}
6、在清單文件中注冊(cè)服務(wù)。
<service android:name=".AIDLService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.service.action"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
至此,服務(wù)端開(kāi)發(fā)完成了。
二、創(chuàng)建一個(gè)custom工程
1、新建一個(gè)custom工程,把服務(wù)端的aidl文件夾下的內(nèi)容全部拷貝到新項(xiàng)目中,如果aidl中有用到bean實(shí)體類(lèi),把實(shí)體類(lèi)也拷貝過(guò)來(lái),然后Rebuild Project。

2、在客戶(hù)端的activity中連接遠(yuǎn)程服務(wù),實(shí)現(xiàn)aidl通信。
public class MainActivity extends AppCompatActivity {
private BookController bookController;
private boolean connected;
private List<Book> bookList;
private Button mBtnGetBookList;
private Button mBtnAddBook;
private Button mBtnGetBookSize;
private Button mBtnGetFirstBookName;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
bookController = BookController.Stub.asInterface(service);
connected = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
bookController = null;
connected = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnGetBookList = findViewById(R.id.btn_get_book_list);
mBtnAddBook = findViewById(R.id.btn_add);
mBtnGetBookSize = findViewById(R.id.btn_get_book_size);
mBtnGetFirstBookName = findViewById(R.id.btn_first_book_name);
mBtnGetBookList.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (connected) {
try {
bookList = bookController.getBookList();
for (int i = 0; i < bookList.size(); i++) {
Log.i("ruxing", "name=" + bookList.get(i).getName());
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
mBtnAddBook.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (connected) {
Book book = new Book("新書(shū)");
try {
bookController.addBook(book);
Log.i("ruxing", "向服務(wù)器添加了一本新書(shū)==="+book.getName());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
mBtnGetBookSize.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (connected) {
try {
int size = 0;
size = bookController.getInt();
Log.i("ruxing", "共有" + size + "本書(shū)");
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
mBtnGetFirstBookName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (connected) {
try {
String name = bookController.getString();
Log.i("ruxing", "第一本書(shū)的書(shū)名是:" + name);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
Intent intent = new Intent();
intent.setPackage("com.example.service");
intent.setAction("com.example.service.action");
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (connected) {
unbindService(serviceConnection);
}
}
}
完整的代碼地址:
https://github.com/ruxing1102/AIDL.git
到此這篇關(guān)于Android中AIDL的使用的文章就介紹到這了,更多相關(guān)Android AIDL使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)下載進(jìn)度條效果
vivo商店在下載應(yīng)用的時(shí)候,底部有一個(gè)圓角矩形的下載進(jìn)度條,中間有一個(gè)進(jìn)度文字,而且進(jìn)度和文字交匯的時(shí)候,交匯部分的文字會(huì)從藍(lán)色邊為白色,會(huì)有一種一半白色字,一半藍(lán)色字的效果。本文將仿照該樣式實(shí)現(xiàn)一個(gè)2021-06-06
Android類(lèi)加載ClassLoader雙親委托機(jī)制詳解
這篇文章主要為大家介紹了Android類(lèi)加載ClassLoader雙親委托機(jī)制詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
Android 系統(tǒng)服務(wù)TelecomService啟動(dòng)過(guò)程原理分析
這篇文章主要介紹了Android 系統(tǒng)服務(wù)TelecomService啟動(dòng)過(guò)程原理分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
Android RecyclerView滾動(dòng)定位
這篇文章主要為大家詳細(xì)介紹了Android RecyclerView滾動(dòng)定位的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
利用HorizontalScrollView實(shí)現(xiàn)滑動(dòng)頁(yè)面時(shí)的縮放效果
這篇文章主要為大家詳細(xì)介紹了利用HorizontalScrollView實(shí)現(xiàn)滑動(dòng)頁(yè)面時(shí)的縮放效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
Android自定義ViewGroup之第一次接觸ViewGroup
這篇文章主要為大家詳細(xì)介紹了Android自定義ViewGroup之第一次接觸ViewGroup,感興趣的小伙伴們可以參考一下2016-06-06
Android TextView的TextWatcher使用案例詳解
這篇文章主要介紹了Android TextView的TextWatcher使用案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08

