標籤:
在上一篇文章Android IPC機制(二)用Messenger進行處理序間通訊中我們介紹了使用Messenger來進行處理序間通訊的方法,但是我們能發現Messenger是以串列的方式來處理用戶端發來的資訊,如果有大量的訊息發到服務端,服務端仍然一個一個的處理再響應用戶端顯然是不合適的。另外,Messenger用來進程間進行資料傳遞但是卻不能滿足跨進程的方法調用,接下來我們來使用AIDL來實現跨進程方法調用,此前我們都是用Eclipse來實現的,這次我們看看在Android Studio中使用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檔案中支援的資料類型包括:
- 基礎資料型別 (Elementary Data Type)
- 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來調用遠程服務端的方法了。
github源碼下載
Android IPC機制(三)在Android Studio中使用AIDL實現跨進程方法調用