Android學習之跨進程通信安卓接口定義語言AIDL(一)

今天來寫下安卓接口定義語言,也就是大家聽了都頭疼的AIDL,今天有幸看到慕課網的AIDL視頻學習了一下,在此感謝慕課網,是個很不錯的網站。

進入正題,Android中跨進程是如何傳遞數據的?如果是Service方面的當然是AIDL。

Android中2個進程無法直接通信,必須通過Android系統底層間接通信,而跨進程通信有4種方式,分別對應4大組件,其中Service對應的就叫AIDL,即Android Interface Defined Language安卓接口定義語言

基本語法:

語法和Java接口類似

只支持方法,不能定義靜態成員

運行方法有任何類型的參數和返回值

除默認類型外,均需要導包

AIDL使用情況:
IPC:Inter-Process Communication進程間通信
什麼時候用AIDL?有IPC,多線程,多個應用程序
什麼時候用Binder?只有IPC,無多線程,多個應用程序
什麼時候用Messenger?只有IPC,無多線程
AIDL使用過程:
1.創建.aidl文件
sdk中的build-tools目錄下提供了aidl工具,用來將aidl文件轉換成java可編譯文件
Eclipse:新建包,新建file,後綴爲.aidl,按格式敲上代碼,java文件在gen/相同包名之下自動會創建
Android Studio:右鍵new AIDL即可,java文件在build/generated/source/aidl/debug/相同包名之下自動會創建
2.實現接口
創建一個Service,重寫onBind(),然後實例化IBinder iBinder = new IDemoAidlInterface.Stub() {}並實現其中的方法
3.向客戶端暴露接口
繼承Service並且重寫onBind(),返回IBinder

4.客戶端綁定服務,拿到遠程的服務

下面講下Demo:

先在app中新建AIDL,這個app作爲服務端,右鍵工程new AIDL即可,java文件在build/generated/source/aidl/debug/相同包名之下自動會創建

package yuzhentao.aidldemo;

//interface:關鍵字,IDemoAidlInterface:接口名
interface IDemoAidlInterface {

    //add():方法
    int add(int num1, int num2);

}

創建一個Service,實例化IBinder iBinder = new IDemoAidlInterface.Stub() {}並實現其中的方法也就是add(),還要重寫onBInd(),返回值就是iBinder

/**
 * Aidl服務
 *
 * @author yuzhentao
 */
public class IDemoAidlService extends Service {

    /**
     * 當客服端綁定到服務端時會執行
     *
     * @param intent:Intent
     * @return IBinder
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }

    private IBinder iBinder = new IDemoAidlInterface.Stub() {
        @Override
        public int add(int num1, int num2) throws RemoteException {
            Log.e("yzt", "收到遠程請求,輸入的參數是:" + num1 + "和" + num2);
            return num1 + num2;
        }
    };

}

不要忘記在AndroidManifest.xml中註冊這個Service,android:enabled和android:exported必須爲true,android:exported用於指示該服務是否能夠被其他應用程序組件調用或跟它交互。如果設置爲true,則能夠被調用或交互,否則不能。也就是能被跨進程使用。

<service
    android:name=".IDemoAidlService"
    android:enabled="true"
    android:exported="true" />

接下來使用Android Studio的File來new一個module,這個module作爲客戶端,很重要的一步就是複製.aidl文件,.aidl必須和服務端的一樣,包括包名,否則編譯不通過,然後寫客戶端的佈局,這裏要實現一個加法的功能

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <EditText
        android:id="@+id/edittext_num1_activity_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="+"
        android:textSize="20dp" />

    <EditText
        android:id="@+id/edittext_num2_activity_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="="
        android:textSize="20dp" />

    <EditText
        android:id="@+id/edittext_result_activity_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:editable="false" />

    <Button
        android:id="@+id/button_activity_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="發送遠程請求"
        android:textSize="16dp" />

</LinearLayout>
然後客戶端主界面中來獲取客戶端,先要綁定服務,Intent必須是顯式的,參數爲包名和類名的全稱,然後實現ServiceConnection接口,onServiceConnected()中通過
IDemoAidlInterface.Stub.asInterface(service)

返回IDemoAidlInterface,拿到遠程的服務,這個IDemoAidlInterface就是AIDL的java文件,最後是單擊事件中通過IDemoAidlInterface來調用add()方法把數據傳遞到服務端,計算就是在服務端中進行的,以下是完整代碼:

/**
 * 客戶端
 * 獲取服務端
 * .aidl必須和服務端的一樣,包括包名,負責編譯不通過
 *
 * @author yuzhentao
 */
public class MainActivity extends Activity {

    private IDemoAidlInterface iDemoAidlInterface;
    /**
     * 服務連接接口
     */
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {//連接服務時執行,ComponentName是bindService()指定的,IBinder是服務端的onBind()返回的
            iDemoAidlInterface = IDemoAidlInterface.Stub.asInterface(service);//返回IDemoAidlInterface,拿到了遠程的服務的代理
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {//斷開服務時執行
            iDemoAidlInterface = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        bindService();//綁定服務
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);//解綁服務
    }

    private void initView() {
        final EditText etNum1 = (EditText) findViewById(R.id.edittext_num1_activity_main);
        final EditText etNum2 = (EditText) findViewById(R.id.edittext_num2_activity_main);
        final EditText etResult = (EditText) findViewById(R.id.edittext_result_activity_main);
        findViewById(R.id.button_activity_main).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int num1 = Integer.parseInt(etNum1.getText().toString());
                int num2 = Integer.parseInt(etNum2.getText().toString());
                String result;
                try {
                    result = iDemoAidlInterface.add(num1, num2) + "";//調用遠程的服務
                    etResult.setText(result);
                } catch (RemoteException e) {
                    e.printStackTrace();
                    etResult.setText("發生錯誤");
                }
            }
        });
    }

    /**
     * 綁定服務
     * alt+command+m:提取方法
     */
    private void bindService() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("yuzhentao.aidldemo", "yuzhentao.aidldemo.IDemoAidlService"));//顯式Intent
        bindService(intent, conn, Context.BIND_AUTO_CREATE);//綁定服務
    }

}
最後是效果圖,左邊是服務端,右邊客戶端輸入2個值,點擊發送遠程請求,服務端就會返回值到客戶端,這是在2個進程間實現的,希望對大家有點幫助:


發佈了36 篇原創文章 · 獲贊 11 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章