Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android AIDL淺談

Android AIDL淺談

編輯:關於Android編程

接觸Android久的朋友,就會在面試或者實際開發中遇到AIDL,那麼今天我們就來看看AIDL。

一、官方描述

1.1 文檔說明

AIDL-Android Interface Definition Language,android接口定義語言,它與你可能已經使用過的其他接口定義語言很類似,它允許你定義接口規則,在客戶端和服務器約定為了相互之間能使用IPC(進程間通信)通信。在Android中,正常情況下,一個進程無法訪問另外一個進程的內存。所以,它們需要將對象分解成操作系統可以識別的原始的類型,這些有序的對象可以穿過邊界為你。代碼做編組,是比較繁瑣的,但是如果你使用AIDL,那麼Android將會自己處理。

PS:1. 使用AIDL的條件是,允許不同的客戶端應用訪問你的服務,並且在服務端還需要處理多進程。(多客戶端、多線程、IPC)

2. 如果你不需要並發處理不同應用的IPC,你應當創建一個接口實現Binder。

3. 如果你只執行IPC,不需要處理對線程,那麼使用Messenger實現一個接口。

補:在實現AIDL時,要先綁定一個服務。

1.2 數據類型。

AIDL支持的數據類型有以下幾種,

1.支持Java原始數據類型。支持基本數據類型有byte,int,long,float,double,boolean,char,注意沒有‘short’。
2.支持String和CharSequence。
3.支持java.util.List和java.util.Map。集合中項的允許數據類型包括Java原始類型、String、CharSequence或是android.os.Parcelable。無需為List和Map提供import語句,但需 要為Parcelable提供import語句。
4.支持傳遞實現了Android.os.Parcelable接口的復雜類型,同樣在引用這些類型時也需要import語句。Parcelable 是Android提供的實現序列化方式。

二、創建AIDL。

為了模擬使用AIDL,需要創建兩個應用,一個是服務端,一個客戶端。打算實現一個簡單的加法計算功能。首先看看服務端的具體實現,

2.1 服務端的具體實現。

1. 打開Android Studio,創建一個Moudle,命名為AidlServer,然後創建一個CalculateAidl的AIDL文件,具體代碼如下;

 

package xinxing.aidltest;


interface CalculateAidl {
  int add(int num1,int num2);
}
代碼比較簡單,就是定義了一個接口,裡面有一個方法。

 

2. 需要創建一個繼承Service的服務,這個服務是用來實現AIDL接口以及提供遠程調用,具體看實現,

 

package xinxing.aidltest;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class CalculateService extends Service {
    public CalculateService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    private IBinder binder= new CalculateAidl.Stub(){
        @Override
        public int add(int num1, int num2) throws RemoteException {
            int result=num1+num2;
            return result;
        }
    };
}
代碼比較少、也簡單,了解Service的應該很容易看懂。還是再次解釋下,在該Service中通過stub(存根) 返回了IBinder對象,並且在該過程中實現了AIDL接口的方法。

 

至此,服務端的開發就結束了!就是這麼簡約!吐舌頭

2.2 客戶端實現。

1. 打開Android Studio,創建一個Moudle,命名為AidlClient,接著把服務端的AIDL文件直接復制拷貝到該項目中(客戶端和服務費的AIDL文件的包一定要一樣)。

2. 實現布局編碼。此處就不羅列了!

3. 主要功能。在調用AIDL接口時,我們首先需要綁定一個遠程服務,

 

   /**
     * 綁定服務
     */
    private void bindService() {
        //先檢查服務端應用是否安裝
        if (AppUtils.checkPackage(MainActivity.this, "xinxing.aidltest")) {
            Intent intent = new Intent();
            intent.setComponent(new ComponentName("xinxing.aidltest", "xinxing.aidltest.CalculateService"));
            bindService(intent, conn, Context.BIND_AUTO_CREATE);

        } else {
            isBindSuccess=false;
            Toast.makeText(MainActivity.this, "第三方應用可能未安裝成功,請檢查後,再試!", Toast.LENGTH_LONG).show();
        }
    }
綁定遠程服務,首先判斷服務應用是否安裝,安裝了,才去綁定服務,沒有安裝,提示‘未安裝’。

 

 

 //遠程連接
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            calculateAidl = CalculateAidl.Stub.asInterface(service);
            isBindSuccess=true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            calculateAidl = null;
            isBindSuccess=false;
        }
    };
遠程連接成功,通過IBinder對象獲取到AIDL實例,下面就是如何調用接口了,

 

 

  if (!isBindSuccess) {
            Toast.makeText(MainActivity.this, "第三方應用可能未安裝成功,請檢查後,再試!", Toast.LENGTH_LONG).show();
            return;
        }
        if (TextUtils.isEmpty(etNum1.getText().toString())) {
            Toast.makeText(MainActivity.this, "請輸入第一個數字", Toast.LENGTH_LONG).show();
            return;
        }
        int num1 = Integer.parseInt(etNum1.getText().toString());
        if (TextUtils.isEmpty(etNum2.getText().toString())) {
            Toast.makeText(MainActivity.this, "請輸入第二個數字", Toast.LENGTH_LONG).show();
            return;
        }
        int num2 = Integer.parseInt(etNum2.getText().toString());
        try {
            String result = String.valueOf(calculateAidl.add(num1, num2));
            tvResult.setText(result);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
代碼比較簡單,就不多說了!至此,客戶端的代碼也ok 了!

 

這是當服務端應用沒有安裝時,點擊計算按鈕的效果截圖,

\

這是當服務端應用已經安裝,點擊計算按鈕的效果截圖,

\

下面展示MainActivity的全部代碼,

 

package xinxing.aidlclient;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import xinxing.aidltest.CalculateAidl;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText etNum1;
    private EditText etNum2;
    private TextView tvResult;
    private Button btn;
    private CalculateAidl calculateAidl;//aidl對象
    private boolean  isBindSuccess=false;//是否綁定成功
    //遠程連接
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            calculateAidl = CalculateAidl.Stub.asInterface(service);
            isBindSuccess=true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            calculateAidl = null;
            isBindSuccess=false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        etNum1 = (EditText) findViewById(R.id.et_num1);
        etNum2 = (EditText) findViewById(R.id.et_num2);
        tvResult = (TextView) findViewById(R.id.tv_result);
        btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(this);
        bindService();
    }


    @Override
    public void onClick(View v) {
        if (!isBindSuccess) {
            Toast.makeText(MainActivity.this, "第三方應用可能未安裝成功,請檢查後,再試!", Toast.LENGTH_LONG).show();
            return;
        }
        if (TextUtils.isEmpty(etNum1.getText().toString())) {
            Toast.makeText(MainActivity.this, "請輸入第一個數字", Toast.LENGTH_LONG).show();
            return;
        }
        int num1 = Integer.parseInt(etNum1.getText().toString());
        if (TextUtils.isEmpty(etNum2.getText().toString())) {
            Toast.makeText(MainActivity.this, "請輸入第二個數字", Toast.LENGTH_LONG).show();
            return;
        }
        int num2 = Integer.parseInt(etNum2.getText().toString());
        try {
            String result = String.valueOf(calculateAidl.add(num1, num2));
            tvResult.setText(result);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
     * 綁定服務
     */
    private void bindService() {
        //先檢查服務端應用是否安裝
        if (AppUtils.checkPackage(MainActivity.this, "xinxing.aidltest")) {
            Intent intent = new Intent();
            intent.setComponent(new ComponentName("xinxing.aidltest", "xinxing.aidltest.CalculateService"));
            bindService(intent, conn, Context.BIND_AUTO_CREATE);

        } else {
            isBindSuccess=false;
            Toast.makeText(MainActivity.this, "第三方應用可能未安裝成功,請檢查後,再試!", Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (isBindSuccess) {
            unbindService(conn);
        }
    }
}
記得在Activity銷毀的時候,解除綁定。

 

三、總結。

使用AIDL,首先需要定義接口以及接口使用到的數據類型,如果是比較復雜的數據類型,需要自己通過Parcelable去實現序列化。繼承一個Service實現AIDL接口定義的方法。調用該AIDL方法是,最好能加入判斷(被調用的應用是否安裝的判斷)。

1. 使用AIDL的情況是多線程、 多應用 、IPC。

2. 使用AIDL時,客戶端和服務端的AIDL文件以及包名都要一樣。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved