在 service和activity通信這篇文章的基礎上,我們再來學習aidl。
aidl是android跨程序通信的常用方法
AIDL對Java類型的支援如下:
1.AIDL支援Java原始資料類型。
2.AIDL支援String和CharSequence。
3.AIDL支援傳遞其他AIDL接口,但你引用的每個AIDL接口都需要一個import語句,即使位于同一個包中。
4.AIDL支援傳遞實作了android.os.Parcelable接口的複雜類型,同樣在引用這些類型時也需要import語句。(Parcelable接口告訴Android運作時在封送(marshalling)和解封送(unmarshalling)過程中實作如何序列化和反序列化對象,你可以很容易聯想到java.io.Serializable接口。有些朋友可能會有疑問,兩種接口功能确實類似,但為什麼Android不用内置的Java序列化機制,而偏偏要搞一套新東西呢?這是因為Android團隊認為Java中的序列化太慢,難以滿足Android的程序間通信需求,是以他們建構了Parcelable解決方案。Parcelable要求顯示序列化類的成員,但最終序列化對象的速度将快很多。另外要注意的是,Android提供了兩種機制來将資料傳遞給另一個程序,第一種是使用Intent将資料束(Bundle)傳遞給活動,第二種也就是Parcelable傳遞給服務。這兩種機制不可互換,不要混淆。也就是說,Parcelable無法傳遞給活動,隻能用作AIDL定義的一部分)。
5.AIDL支援java.util.List和java.util.Map,但是有一些限制。集合中項的允許資料類型包括Java原始類型、String、CharSequence或是android.os.Parcelable。無需為List和Map提供import語句,但需要為Parcelable提供import語句。
6.非原始類型中,除了String和CharSequence以外,其餘均需要一個方向訓示符。方向訓示符包括in、out、和inout。in表示由用戶端設定,out表示由服務端設定,inout表示用戶端和服務端都設定了該值。預設類型其實隐含了一個預設訓示符in
參考自http://blog.csdn.net/liuhe688/article/details/6409708
注意事項
1、oneway關鍵字在跨程序調用的時候使得調用不阻塞,直接傳回。在同一個程序内,oneway沒有任何意義。
2、aidl檔案可以引用aidl檔案,但不能引用java檔案。是以有時候我們想要在程序間傳輸某個對象,比如BaseData,首先要BaseData實作parceble,寫一個java檔案,然後在同樣的目錄下寫個同名aidl檔案,并注明parceble BaseData作為定義,然後其他aidl檔案才能引用BaseData,可參考http://blog.csdn.net/dangnianmingyue_gg/article/details/48197293 内的PayClass。
例子
activity擷取service資料關鍵連接配接點是onServiceConnected
首先寫服務端的app: AidlServer
這裡我們建立一個Service類MyService,在MyService中放1個計時器
public void onCreate() {
super.onCreate();
String TAG="";
LogFish.d("onCreate process name " + SystemUtil.getCurProcessName(MyService.this));
Log.i(TAG, "Service is Created");
thread = new Thread(new Runnable() {
@Override
public void run() {
// 每間隔0.1秒count加1 ,直到quit為true
while (!quit) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
});
thread.start();
}
編寫aidl接口,getCount用來擷取service的資料,complexCal用來做複雜計算,注意這裡是跨程序的
interface IMyAidlInterface {
int getCount();
double complexCal(String str,int t);
}
service中的binder重寫aidl接口方法
IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
@Override
public int getCount() throws RemoteException {
return count;
}
@Override
public double complexCal(String str, int t) throws RemoteException {
int ret=str.hashCode()+t;
return ret*0.3;
}
};
manifest中的MyService配置如下
<service
android:name=".MyService"
android:process="com.myservice">
<intent-filter>
<action android:name="com.example.servicetest.MyAIDLService" />
</intent-filter>
</service>
檔案目錄如下:
再編寫用戶端app:AidlClient
首先在同樣目錄下,放一模一樣的aidl檔案
再編寫activity檔案,代碼如下
public class MainActivity extends Activity implements View.OnClickListener {
private Button bindService;
private Button unbindService;
private IMyAidlInterface myAIDLInterface;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LogFish.d("process name"+ SystemUtil.getCurProcessName(MainActivity.this));
myAIDLInterface = IMyAidlInterface.Stub.asInterface(service);
try {
int cnt = myAIDLInterface.getCount();
double db = myAIDLInterface.complexCal("hello world",6);
LogFish.d("result is " + cnt);
LogFish.d( "complexCal value " + db);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService = (Button) findViewById(R.id.bind_service);
unbindService = (Button) findViewById(R.id.unbind_service);
Button bv = (Button) findViewById(R.id.get_num);
bv.setOnClickListener(this);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
Intent intent = new Intent("com.example.servicetest.MyAIDLService");
startService(intent);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bind_service:
Intent intent = new Intent("com.example.servicetest.MyAIDLService");
boolean b= bindService(intent, connection, Service.BIND_AUTO_CREATE);
LogFish.d("bind result "+b);
break;
case R.id.unbind_service:
// Intent unbindIntent = new Intent(this, com.aidl.server.MyService.class);
unbindService(connection);
LogFish.d("unbind ");
break;
default:
break;
}
}
}
Ok,代碼編寫完畢,先安裝AidlServer,再運作AidlClient
結果如下:
05-13 19:35:07.246 1734-1734/com.aidl.client D/LogFish﹕ result is 41
05-13 19:35:07.246 1734-1734/com.aidl.client D/LogFish﹕ complexCal value is 5.382318174E8
result是指service啟動到bind之間的時間,complexCal value是AidlServer計算出來的結果,AidlClient提供參數
用到module:AidlServer和AidlClient