在Android 應用開發過程中涉及到進程間通信的場景不多,但是隨着進程化開發的實現,單APP多進程的情況也越來越多。這就涉及到IPC進程間通信,而Binder 就是其中的一種,Android中很多情況 IPC 通信都是通過 Binder 實現的,其底層相對複雜,在應用層,我們可以理解Binder 就是一個Java 類,在進程間通信的 client -> service 結構中數據的傳遞是通過Binder 來實現的。而Android 爲了方便我們實現這一功能 提供了AIDL 文件 Android Interface Definition Language(安卓接口定義語言)
要實現進程間通信我們需要創建 service 端和 client 端
1.創建AIDL 文件
// IServiceInterface.aidl
package com.fyh.aidl;
// Declare any non-default types here with import statements
interface IServiceInterface {
/**
* 這邊默認生成的一個方法 可以不用管,這裏寫個getData() 方法獲取數據
*/
String getData();
}
當創建好AIDL文件 編譯後,會自動生成一個 對應名稱的Java 接口類
public interface IServiceInterface extends android.os.IInterface
2.創建 service
public class AIDLService extends Service {
public AIDLService() {
}
@Override
public IBinder onBind(Intent intent) {
return stub;
}
//這裏 Stub 是一個繼承 IBinder 的抽象類,所以 IServiceInterface.Stub 是我們對 IBinder
//的具體實現,而我們實現的方法就是服務端提供一個方法傳遞數據"{'data':'AIDLServiceTest'}
IServiceInterface.Stub stub = new IServiceInterface.Stub() {
@Override
public String getData() throws RemoteException {
String s = "{'data':'AIDLServiceTest'}";
return s;
}
};
}
3.創建 client 端
//創建service 鏈接
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iServiceInterface = IServiceInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iServiceInterface = null;
}
};
//綁定
public void bindService(Context context) {
Intent intent = new Intent();
intent.setAction("com.fyh.aidl");
intent.setPackage("com.fyh.aidl.service");
context.bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
//解綁
public void unbindService(Context context) {
if (null == iServiceInterface) {
return;
}
context.unbindService(connection);
iServiceInterface = null;
}
//請求服務端數據
public String requestData() {
if (null == iServiceInterface) {
return null;
}
try {
String data = iServiceInterface.getData();
return data;
} catch (RemoteException e) {
e.printStackTrace();
}
return null;
}
輸出的結果
通過使用 AIDL 我們會非常方便的實現進程間的通訊 同時我們可以看看自動生成的 IServiceInterface.java 文件是什麼樣的結構。
package com.fyh.aidl;
public interface IServiceInterface extends android.os.IInterface{
public static class Default implements com.fyh.aidl.IServiceInterface{
@Override
public java.lang.String getData() throws android.os.RemoteException{
return null;
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
public static abstract class Stub extends android.os.Binder implements com.fyh.aidl.IServiceInterface{
private static final java.lang.String DESCRIPTOR = "com.fyh.aidl.IServiceInterface";
public Stub(){
this.attachInterface(this, DESCRIPTOR);
}
public static com.fyh.aidl.IServiceInterface asInterface(android.os.IBinder obj){
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.fyh.aidl.IServiceInterface))) {
return ((com.fyh.aidl.IServiceInterface)iin);
}
return new com.fyh.aidl.IServiceInterface.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder(){
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_getData:
{
data.enforceInterface(descriptor);
java.lang.String _result = this.getData();
reply.writeNoException();
reply.writeString(_result);
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.fyh.aidl.IServiceInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override
public java.lang.String getData() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getData, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().getData();
}
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static com.fyh.aidl.IServiceInterface sDefaultImpl;
}
static final int TRANSACTION_getData = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
public static boolean setDefaultImpl(com.fyh.aidl.IServiceInterface impl) {
if (Stub.Proxy.sDefaultImpl == null && impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static com.fyh.aidl.IServiceInterface getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public java.lang.String getData() throws android.os.RemoteException;
}
在這個類中 實現了 com.fyh.aidl.IServiceInterface 接口的 情況有三種 Default Stub Proxy 。當default 的時候 返回的是null。
我們在 service 中實現的 是IServiceInterface.Stub stub = new IServiceInterface.Stub() 。從代碼中我們可以看出 Stub 是一個繼承了IBinder 實現了IServiceInterface 的抽象靜態內部類,而具體的實現實在 AIDLService 中進行的。而這個 具體 的IBinder 時間對象 stub 會在客戶端綁定的時候返回給客戶端 。客戶端會調用Stub中的靜態方法asInterface,stub作爲參數,最後拿到IServiceInterface接口對象 iServiceInterface 。
然後 if (((iin!=null)&&(iin instanceof com.fyh.aidl.IServiceInterface))) 判斷客戶端和服務端是否在同一個進程下,如果在同一進程那麼asInterface()將返回Stub對象本身,因爲此時根本不需要跨進稱通信,那麼直接調用Stub對象的接口就可以了。否則返回Stub.Proxy代理對象。該對象持有着遠程的Binder引用,因爲現在需要跨進程通信。
好了介紹的比較簡單,文章主要是AIDL 的簡單實現,順便看看Android 爲我們自動生成的類裏面是什麼樣子的。如果要深入瞭解,還需要等深入的學習。
demo 地址 : https://github.com/fyhsgsgssg/AIDLTest