天天看點

Android - AIDL 使用

AIDL(Android Interface Definition Language)

程式員可以利用AIDL自定義程式設計接口,在用戶端和服務端之間實作程序間通信(IPC)。在Android平台上,一個程序通常不能通路另外一個程序的記憶體空間,是以,Android平台将這些跨程序通路的對象分解成作業系統能夠識别的簡單對象。并為跨應用通路而特殊編排和整理這些對象。用于編排和整理這些對象的代碼編寫起來十分冗長,是以Android的AIDL提供了相關工具來自動生成這些代碼。

例子:建立兩個apk,一個作為服務提供方,一個作為AIDL服務調用方。

android studio

AIDL服務方代碼

一共4步

1.先進入服務方的工程,在

com.rust.aidl

包内建立

IMyService.aidl

檔案

// IMyService.aidl
package com.rust.aidl;

// Declare any non-default types here with import statements

interface IMyService {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    String helloAndroidAIDL(String name);// 此次使用的方法
}
           

2.在

com.rust.service

MyService.java

檔案;有一個内部類

MyServiceImpl

實作接口的功能

package com.rust.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;

import com.rust.aidl.IMyService;

public class MyService extends Service {

    public class MyServiceImpl extends IMyService.Stub {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
                               double aDouble, String aString) throws RemoteException {

        }

        public String helloAndroidAIDL(String name) throws RemoteException {
            Log.d("aidl", "helloAndroidAIDL heard from : " + name);
            return "Rust: Service01 return value successfully!";
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new MyServiceImpl();// 傳回内部類執行個體
    }
}           

3.實作了MyService類後,對此AIDL服務進行配置;在

AndroidManifest.xml

檔案中配置

<service android:name="com.rust.service.MyService">
            <intent-filter>
                <action android:name="com.rust.aidl.IMyService" />
            </intent-filter>
        </service>           

service寫實作類

MyService

;action裡面寫上AIDL檔案

4.釋出運作此apk

AIDL調用方代碼

建立(或進入)AIDL調用方的工程,這裡是MyAIDLTest工程。有如下3個步驟:

1.将AIDL服務端生成的Java檔案複制到調用方工程裡,盡量保持這個Java檔案的路徑與服務端的一緻,便于識别

2.寫代碼綁定服務,擷取AIDL服務對象

3.通過AIDL服務對象完成AIDL接口調用

本例中,生成的Java檔案路徑為:

服務端/app/build/generated/source/aidl/debug/com/rust/aidl/IMyService.java

将其複制到調用方工程下:

MyAIDLTest/app/src/main/java/com/rust/aidl/IMyService.java

編寫調用方

MainActivity.java

代碼

package rust.myaidltest;

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.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.rust.aidl.IMyService;

public class MainActivity extends AppCompatActivity {

    Button aidlBtn;
    IMyService myService;// 服務
    String appName = "unknown";

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myService = IMyService.Stub.asInterface(service);// 擷取服務對象
            aidlBtn.setEnabled(true);
        }// 連接配接服務

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        aidlBtn = (Button) findViewById(R.id.aidl_1_btn);
        appName = getPackageName();
        
        // 我們沒辦法在構造Intent的時候就顯式聲明.
        Intent intent = new Intent("com.rust.aidl.IMyService");
        // 既然沒有辦法建構有效的component,那麼給它設定一個包名也可以生效的
        intent.setPackage("com.rust.aboutview");// the service package
        // 綁定服務,可設定或觸發一些特定的事件
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

        aidlBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    // AIDL服務調用代碼如下:
                    String msg = myService.helloAndroidAIDL(appName);
                    Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}           
效果

點選調用端的按鈕,彈出Toast:

Rust: Service01 return value successfully!

服務端apk列印log:

helloAndroidAIDL heard from : rust.myaidltest

其中,

rust.myaidltest

就是調用端傳入的自身的包名

服務端更新後,如果aidl檔案沒改動,不需要更新生成的Java檔案

如果服務端apk被解除安裝,調用端使用此服務時會出錯

繼續閱讀