Android IPC機制(三)使用AIDL實現跨進程方法調用
上一篇文章中我們介紹了使用Messenger來進行進程間通信的方法,但是我們能發現Messenger是以串行的方式來處理客戶端發來的信息,如果有大量的消息發到服務端,服務端仍然一個一個的處理再響應客戶端顯然是不合適的。另外,Messenger用來進程間進行數據傳遞但是卻不能滿足跨進程的方法調用,接下來我們來使用AIDL來實現跨進程方法調用
1. 創建AIDL文件
我們將項目的目錄結構調為Android模式,在java同級目錄創建aidl文件夾,在文件夾中創建一個包名和應用包名一致的包
我們先創建一個IGameManager.aidl的文件,這里面有兩個方法分別是addGame和getGameList。(IGameManager.aidl)
package com.example.liuwangshu.moonaidl;
import com.example.liuwangshu.moonaidl.Game;
interface IGameManager {
List<Game>getGameList();
void addGame(in Game game);
}
在AIDL文件中支持的數據類型包括:
- 基本數據類型
- String和CharSequence
- List:只支持ArrayList,里面的元素都必須被AIDL支持
- Map:只支持HashMap,里面的元素必須被AIDL 支持
- 實現Parcelable接口的對象
- 所有AIDL接口
在IGameManager.aidl中我們用到了Game這個類,這個類實現了Parcelable,在AIDL 文件中我們要import 進來,來看看Game類。(Game.java)
package com.example.liuwangshu.moonaidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Game implements Parcelable {
public String gameName;
public String gameDescribe;
public Game(String gameName,String gameDescribe){
this.gameName=gameName;
this.gameDescribe=gameDescribe;
}
protected Game(Parcel in) {
gameName=in.readString();
gameDescribe=in.readString();
}
public static final Creator<Game> CREATOR = new Creator<Game>() {
@Override
public Game createFromParcel(Parcel in) {
return new Game(in);
}
@Override
public Game[] newArray(int size) {
return new Game[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(gameName);
dest.writeString(gameDescribe);
}
}
在這里不去講怎么去實現Parcelable 接口,在上面的IGameManager.aidl文件中我們用到了Game這個類,所以我們也要創建Game.aidl,來申明Game實現了parcelable 接口。(Game.aidl)
package com.example.liuwangshu.moonaidl; parcelable Game;
這個時候我們重新編譯程序,工程就會自動生成IGameManager.aidl對應的接口文件,這個文件生成的位置和Eclipse的位置不同,我們將項目的目錄結構調整為project模式,在app–>build–>generated–>soure–>aidl–>debug目錄下我們找到自己的包名文件,在文件中有一個接口文件IGameManager。
IGameManager接口文件的代碼這里就不說了,有興趣的可以下載本項目的源碼去了解下。
2. 創建服務端
服務端我們在onCreate方法中創建了兩個游戲的信息并創建Binder對象實現了AIDL的接口文件中的方法,并在onBind方法中將Binder對象返回。(AIDLService.java)
package com.example.liuwangshu.moonaidl;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class AIDLService extends Service{
private CopyOnWriteArrayList<Game> mGameList=new CopyOnWriteArrayList<Game>();
private Binder mBinder= new IGameManager.Stub() {
@Override
public List<Game> getGameList() throws RemoteException {
return mGameList;
}
@Override
public void addGame(Game game) throws RemoteException {
mGameList.add(game);
}
};
@Override
public void onCreate() {
super.onCreate();
mGameList.add(new Game("九陰真經ol", "最好玩的武俠網游"));
mGameList.add(new Game("大航海時代ol","最好玩的航海網游"));
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
當然我們不要忘了這個服務端應該運行在另一個進程,在AndroidManifest.xml文件中配置service:
<service android:name=".AIDLService" android:process=":remote"></service>
3. 客戶端調用
最后我們在客戶端onCreate方法中調用bindService方法綁定遠程服務端,綁定成功后將返回的Binder對象轉換為AIDL接口,這樣我們就可以通過這個接口來調用遠程服務端的方法了。(AIDLActivity.java)
package com.example.liuwangshu.moonaidl;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.List;
public class AIDLActivity extends AppCompatActivity {
private final static String TAG="AIDLActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl);
Intent mIntent=new Intent(AIDLActivity.this,AIDLService.class);
bindService(mIntent,mServiceConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mServiceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IGameManager iGameManager=IGameManager.Stub.asInterface(service);
Game game=new Game("月影傳說","最好玩的武俠單機游戲");
try {
iGameManager.addGame(game);
List<Game> mList=iGameManager.getGameList();
for(int i=0;i<mList.size();i++){
Game mGame=mList.get(i);
Log.i(TAG,mGame.gameName+"---"+mGame.gameDescribe);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
}
}
綁定成功后我們創建了一個新的Game然后調用遠程服務端的addGame方法將新游戲添加進去,然后調用循環將遠端服務中的所有的游戲在打印出來,我們運行程序
打印出了遠程服務端的所有的游戲,這樣我們就成功的在客戶端通過AIDL來調用遠程服務端的方法了。
https://github.com/henrymorgen/MoonAIDL2
浙公網安備 33010602011771號