Android中實(shí)現(xiàn)跨進(jìn)程通信(IPC)的幾種方式(二)
????在上一篇文章中介紹了什么是多進(jìn)程,為什么需要多進(jìn)程,多進(jìn)程的優(yōu)缺點(diǎn)等。這篇我們將會(huì)使用AIDL來(lái)實(shí)現(xiàn)跨進(jìn)程通信。
1.什么是AIDL
????AIDL全稱(chēng)是Android接口定義語(yǔ)言 您可以利用它定義客戶(hù)端與服務(wù)使用進(jìn)程間通信 (IPC) 進(jìn)行相互通信時(shí)都認(rèn)可的編程接口。 在 Android 上,一個(gè)進(jìn)程通常無(wú)法訪(fǎng)問(wèn)另一個(gè)進(jìn)程的內(nèi)存。 盡管如此,進(jìn)程需要將其對(duì)象分解成操作系統(tǒng)能夠識(shí)別的原語(yǔ),并將對(duì)象編組成跨越邊界的對(duì)象。 編寫(xiě)執(zhí)行這一編組操作的代碼是一項(xiàng)繁瑣的工作,因此 Android 會(huì)使用 AIDL 來(lái)處理。
2. 創(chuàng)建.aidl文件
????AIDL 使用簡(jiǎn)單語(yǔ)法,使您能通過(guò)可帶參數(shù)和返回值的一個(gè)或多個(gè)方法來(lái)聲明接口。 參數(shù)和返回值可以是任意類(lèi)型,甚至可以是其他 AIDL 生成的接口。
3. 創(chuàng)建客戶(hù)端服務(wù)端進(jìn)行通信的實(shí)體類(lèi),并實(shí)現(xiàn)Parcelable接口。
4. 創(chuàng)建aidl文件

5. 創(chuàng)建于實(shí)體類(lèi)對(duì)應(yīng)的aidl文件

6. 創(chuàng)建通信接口aidl文件

7默認(rèn)情況下,AIDL 支持下列數(shù)據(jù)類(lèi)型:
默認(rèn)情況下,AIDL 支持下列數(shù)據(jù)類(lèi)型:
Java 編程語(yǔ)言中的所有原語(yǔ)類(lèi)型(如 int、long、char、boolean 等等)
String
CharSequence
List
????List 中的所有元素都必須是以上列表中支持的數(shù)據(jù)類(lèi)型、其他 AIDL 生成的接口或您聲明的可打包類(lèi)型。 可選擇將 List 用作“通用”類(lèi)(例如,List<String>)。另一端實(shí)際接收的具體類(lèi)始終是 ArrayList,但生成的方法使用的是 List 接口。
Map
????Map 中的所有元素都必須是以上列表中支持的數(shù)據(jù)類(lèi)型、其他 AIDL 生成的接口或您聲明的可打包類(lèi)型。 不支持通用Map 另一端實(shí)際接收的具體類(lèi)始終是 HashMap,但生成的方法使用的是 Map 接口。
????您必須為以上未列出的每個(gè)附加類(lèi)型加入一個(gè) import 語(yǔ)句,即使這些類(lèi)型是在與您的接口相同的軟件包中定義。
8. 注意事項(xiàng)
???? 非基本的數(shù)據(jù)類(lèi)型都需要導(dǎo)入包,即使他們?cè)谕粋€(gè)包里面。
????在方法參數(shù)中,除了基本數(shù)據(jù)類(lèi)型,其他的數(shù)據(jù)類(lèi)型都需要標(biāo)上 in(輸入) out(輸出) inout(輸入輸出)
-
build project,然后找到build/generated/source/aidl目錄下面生成的Java文件
屏幕快照 2018-05-26 18.11.47.png
9實(shí)現(xiàn)服務(wù)端代碼
package com.example.huangjie.ipc;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* Created by huangjie on 2018/5/22.
*/
public class AidlService extends Service {
private ArrayList<Book> bookList;
private IBinder mBinder = new BookManager.Stub() {
@Override
public void addBook(Book book) throws RemoteException {
bookList.add(book);
}
@Override
public List<Book> getBookList() throws RemoteException {
return bookList;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onCreate() {
super.onCreate();
bookList = new ArrayList<>();
bookList.add(new Book("ID123", "Android開(kāi)發(fā)藝術(shù)探索"));
bookList.add(new Book("ID124", "劍指offer Java版"));
}
}
聲明服務(wù)端Servce
<service
android:name=".AidlService"
android:process=":test">
</service>
10編寫(xiě)客戶(hù)端綁定service代碼
package com.example.huangjie.ipc;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
BookManager bookManager = BookManager.Stub.asInterface(service);
try {
List<Book> bookList = bookManager.getBookList();
Toast.makeText(getApplicationContext(), "來(lái)自服務(wù)端的數(shù)據(jù)" + bookList.toString(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Intent intent = new Intent(this, AidlService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
}
總結(jié):實(shí)現(xiàn)AIDL跨進(jìn)程通信步驟:
- 實(shí)現(xiàn)服務(wù)端于客戶(hù)端通信實(shí)體類(lèi)并實(shí)現(xiàn)Parcelable接口
- 在項(xiàng)目 src/ 目錄中加入 .aidl 文件。
- 聲明一個(gè) IBinder 接口實(shí)例(基于 AIDL 生成)。
- 實(shí)現(xiàn) ServiceConnection。
- 調(diào)用 Context.bindService(),以傳入您的 ServiceConnection 實(shí)現(xiàn)。
- 在您的 onServiceConnected() 實(shí)現(xiàn)中,您將收到一個(gè) IBinder 實(shí)例(名為 service)。調(diào)用BookManager bookManager = BookManager.Stub.asInterface(service) ,以將返回的參數(shù)轉(zhuǎn)換為BookManager 類(lèi)型。
- 調(diào)用您在接口上定義的方法。您應(yīng)該始終捕獲 DeadObjectException 異常,它們是在連接中斷時(shí)引發(fā)的;這將是遠(yuǎn)程方法引發(fā)的唯一異常。
- 如需斷開(kāi)連接,請(qǐng)使用您的接口實(shí)例調(diào)用 Context.unbindService()。
