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被卸載,調用端使用此服務時會出錯

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容