1簡介
AIDL:Android Interface Definition Language,即Android介面定義語言, 是IPC(interprocess communication)程式間通訊方式的一種。
2使用
本篇目的是本地通過aidl呼叫遠端service服務,計算傳入的兩個數值的和並返回的例子,初步掌握AIDL的使用。 閒話少說,先上效果圖
2.1 AIDL介面的建立
在java目錄下建立aidl資料夾
在aidl資料夾下建立aidl檔案 AIDL檔案程式碼實現// ILiujianAidl.aidl
package com.liujian.aidl;
interface ILiujianAidl {
//計算兩個數的和
int add(int num1 ,int num2);
}
複製程式碼
完成程式碼後一定要同步一下,Android Studio會自動為我們生成我們最終使用的ILiujianAidl檔案。
2.2 遠端服務的實現
本例通過設定service的清單檔案process屬性,使它和客戶端的Activity不在同一個程式中,構成多程式通訊的場景。
<service
android:name=".IRemoteService"
android:process=":remote"/>
複製程式碼
服務端程式碼實現
public class IRemoteService extends Service {
private final String TAG = "IRemoteService";
/**
* 當客戶端繫結該服務時會執行
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
private IBinder iBinder = new ILiujianAidl.Stub() {
@Override
public int add(int num1, int num2) throws RemoteException {
Log.i(TAG,"收到了遠端的請求,輸入的引數是"+num1+"和"+num2);
return num1 + num2;
}
};
}
複製程式碼
2.3客戶端的實現
首先要進行繫結服務
/**
* 繫結服務
*/
private void bindService(){
//獲取到服務端
Intent intent = new Intent();
//新版本必須顯式Intent繫結服務
intent.setComponent(new ComponentName("com.liujian.aidl","com.liujian.aidl.IRemoteService"));
bindService(intent,conn, Context.BIND_AUTO_CREATE);
}
複製程式碼
然後獲取輸入資料
最後呼叫服務並顯示結果
/**
* 呼叫服務計算結果並顯示
*/
private void calculateToShow(int num1,int num2){
try {
//呼叫遠端服務
int res = iLiujianAidl.add(num1,num2);
etRes.setText(res+"");
} catch (RemoteException e) {
e.printStackTrace();
etRes.setText("出錯了");
}
}
複製程式碼
客戶端完整程式碼
package com.liujian.aidl;
import android.app.Activity;
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.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity implements View.OnClickListener{
private EditText etNum1,etNum2,etRes;
private Button btCalculate;
ILiujianAidl iLiujianAidl;
ServiceConnection conn = new ServiceConnection() {
//繫結上服務的時候執行
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//拿到了遠端的服務
iLiujianAidl = ILiujianAidl.Stub.asInterface(service);
}
//當服務斷開時執行
@Override
public void onServiceDisconnected(ComponentName name) {
//回收
iLiujianAidl = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
bindService();
}
private void initView() {
etNum1 = findViewById(R.id.etNum1);
etNum2 = findViewById(R.id.etNum2);
etRes = findViewById(R.id.etRes);
btCalculate = findViewById(R.id.btCalculate);
btCalculate.setOnClickListener(this);
}
@Override
public void onClick(View v) {
int num1 = Integer.valueOf(etNum1.getText().toString());
int num2= Integer.valueOf(etNum2.getText().toString());
calculateToShow(num1,num2);
}
/**
* 呼叫服務計算結果並顯示
*/
private void calculateToShow(int num1,int num2){
try {
//呼叫遠端服務
int res = iLiujianAidl.add(num1,num2);
etRes.setText(res+"");
} catch (RemoteException e) {
e.printStackTrace();
etRes.setText("出錯了");
}
}
/**
* 繫結服務
*/
private void bindService(){
//獲取到服務端
Intent intent = new Intent();
//新版本必須顯式Intent繫結服務
intent.setComponent(new ComponentName("com.liujian.aidl","com.liujian.aidl.IRemoteService"));
bindService(intent,conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
複製程式碼
3其他
3.1AIDL支援的資料型別
-
基本資料型別(int、long、char、boolean、double等)
-
String和CharSequence
-
List:只支援ArrayList,裡面每個元素都必須能夠被AIDL支援
-
Map:只支援HashMap,裡面的每個元素都必須被AIDL支援,包括key和value
-
Parcelable:所有實現了Parcelable介面的物件
-
AIDL:所有的AIDL介面本身也可以在AIDL檔案中使用
3.2 注意事項
- Parcelable物件和AIDL介面物件必須要顯示import進來不管他們是否和當前的AIDL檔案處於同一個包內
- 如果AIDL檔案中用到了自定義的Parcelable物件,那麼必須新建一個和他同名的AIDL檔案,並在其中宣告它為Parcelable型別
- AIDL中除了基本資料型別,其他型別的引數都必須標上方向:in(輸入型引數)、out(輸出型引數)、inout(輸入輸出型引數)
- AIDL介面中只支援方法,不支援宣告靜態常量