AIDL的基本使用

LiuJian-Android發表於2018-02-27

1簡介

AIDL:Android Interface Definition Language,即Android介面定義語言, 是IPC(interprocess communication)程式間通訊方式的一種。

2使用

本篇目的是本地通過aidl呼叫遠端service服務,計算傳入的兩個數值的和並返回的例子,初步掌握AIDL的使用。 閒話少說,先上效果圖

AIDL的基本使用

2.1 AIDL介面的建立

在java目錄下建立aidl資料夾

AIDL的基本使用
在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介面中只支援方法,不支援宣告靜態常量

3.3選擇合適的IPC方式

AIDL的基本使用

相關文章