`
isiqi
  • 浏览: 16484250 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

深刻解析 Android 的 AIDL 介面

阅读更多

深刻解析 Android 的 AIDL 介面
在Android應用框架裡,應用層級的軟體大多是Java類別,而系統層級的軟體大多是C或 C++類別。Android使用JNI介面來達成這個目標。例如,在Android裡有個MediaPlayer.cpp類別,當它搭配上JNI介面之後,在VM上執行的MediaPlayer.java就可以透過JNI介面與MediaPlayer.cpp類別溝通了。
clip_image001

圖1-1

基於這樣的架構,我門就可以盡量將MediaPlayer.java裡的程式邏輯移入MediaPlayer.cpp類別裡,以便加快程式的執行速度。此外,以JNI介面包裝MediaPlayer.cpp類別,並且銜接相互輝映的MediaPlayer.java類別,可以讓眾多的Java應用程式透過MediaPlayer.java來使用MediaPlayer.cpp類別的服務。這是一種非常有用的包裝技巧,藉由包裝來創造更多的應用機會。

為了進一步創造更多的應用機會,可以替MediaPlayer.java類別加上AIDL介面,讓更多的Java應用程式能與MediaPlayer.java類別進行遠距的IPC溝通。如下圖所示:
clip_image002
圖1-2

上圖表示出JNI在Android裡扮演的角色,以及Android框架裡Java與C/C++類別融合的基本架構。上面的图1-2是一個較為抽象的圖,凸显JNI与AIDL的相互呼應之角色。
於此,以高煥堂所寫的第2本Android書:<> 一书里的范例:HalfAdder組件為例,展示其幕后的细节架构。首先看看其JNI介面之上的細節架構,如下UML圖:
clip_image004

圖1-3

上圖1-2幕後的細節架構之一

上圖凸顯了AIDL介面的細節架構。下圖1-4將換個角度,從*.so開發者來看,當我們開發系統層級的C/C++類別時,也能善用JNI,創造C/C++類別的廣大商機。其細節架構如下UML圖:
clip_image006
圖1-4

上圖1-2幕後的細節架構之二

1.3
說明C/C++組件開發
從上圖1-4可看到此范例的C/C++組件部份。其詳細的程式碼,請閱讀高煥堂所寫的第2本Android書:<> 一書之第5~6章。
1.4
說明AIDL介面類別之開發

基於剛才所撰寫的相對應Java類別:Calculator.java,就能順利配上AIDL介面了。
1.4.1
細說AIDL介面與IBinder介面

其實,AIDL介面幕後是仰賴著IBinder介面的。所以,我們的應用程式可以選擇使用IBinder介面,也可以使用AIDL介面。如果採取IBinder介面,就不必使用aidl.exe工具去产生calInterface.java介面定义档了,其介面類別較單純一些,如下圖所示:
clip_image008圖1-5

僅使用較單純的IBinder介面

由於IBinder介面只提供單一函數(即transact()函數)來進行远距沟通,呼叫起來比較不方便。例如,當Calculator類別有多個函數時,myActivity要如何呼叫它們呢?

可以呼叫IBinder介面的transact()函數,再转而呼叫Calculator的各個函數。由於它並不太方便,所以Android提供Proxy/Stub結構的AIDL介面來化解這個問題,其架構圖如下:

clip_image010圖1-6

更方便的AIDL介面(其介面類別結構較複雜一些)在本範例裡,將採取AIDL介面,同時也介紹其幕後的IBinder介面,以及其兩這之間的密切關係。

1.4.2細說Stub類別的程式碼

這個Stub類別就是由aidl.exe所产出的;也就是在calInterface.java裡面。并再重复列出calInterface.java程式碼如下:

/*---- calInterface.java ----*/

/*

* This file is auto-generated.

DO NOT MODIFY.

* Original file: calInterface.aidl

*/

package com.misoo.gx06;

import java.lang.String;

import android.os.RemoteException;

import android.os.IBinder;

import android.os.IInterface;

import android.os.Binder;

import android.os.Parcel;

public interface calInterface extends android.os.IInterface

{

/** Local-side IPC implementation stub class. */

public static abstract class Stub extends android.os.Binder implements com.misoo.gx06.calInterface

{

private static final java.lang.String DESCRIPTOR = "com.misoo.gx06.calInterface";

/** Construct the stub at attach it to the interface. */

public Stub()

{

this.attachInterface(this, DESCRIPTOR);

}

/**

* Cast an IBinder object into an calInterface interface,

* generating a proxy if needed.

*/

public static com.misoo.gx06.calInterface asInterface(android.os.IBinder obj)

{

if ((obj==null)) {

return null;

}

com.misoo.gx06.calInterface in = (com.misoo.gx06.calInterface)obj.queryLocalInterface(DESCRIPTOR);

if ((in!=null)) {

return in;

}

return new com.misoo.gx06.calInterface.Stub.Proxy(obj);

}

public android.os.IBinder asBinder()

{

return this;

}

public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException

{

switch (code)

{

case INTERFACE_TRANSACTION:

{

reply.writeString(DESCRIPTOR);

return true;

}

case TRANSACTION_EvDigitPress:

{

data.enforceInterface(DESCRIPTOR);

int _arg0;

_arg0 = data.readInt();

java.lang.String _result = this.EvDigitPress(_arg0);

reply.writeNoException();

reply.writeString(_result);

return true;

}

case TRANSACTION_EvCPress:

{

data.enforceInterface(DESCRIPTOR);

java.lang.String _result = this.EvCPress();

reply.writeNoException();

reply.writeString(_result);

return true;

}

case TRANSACTION_EvPlusPress:

{

data.enforceInterface(DESCRIPTOR);

java.lang.String _result = this.EvPlusPress();

reply.writeNoException();

reply.writeString(_result);

return true;

}

case TRANSACTION_EvAssignPress:

{

data.enforceInterface(DESCRIPTOR);

java.lang.String _result = this.EvAssignPress();

reply.writeNoException();

reply.writeString(_result);

return true;

}

}

return super.onTransact(code, data, reply, flags);

}

private static class Proxy implements com.misoo.gx06.calInterface

{

private android.os.IBinder mRemote;

Proxy(android.os.IBinder remote)

{

mRemote = remote;

}

public android.os.IBinder asBinder()

{

return mRemote;

}

public java.lang.String getInterfaceDescriptor()

{

return DESCRIPTOR;

}

public java.lang.String EvDigitPress(int d) throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

java.lang.String _result;

try {

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeInt(d);

mRemote.transact(Stub.TRANSACTION_EvDigitPress, _data, _reply, 0);

_reply.readException();

_result = _reply.readString();

}

finally {

_reply.recycle();

_data.recycle();

}

return _result;

}

public java.lang.String EvCPress() throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

java.lang.String _result;

try {

_data.writeInterfaceToken(DESCRIPTOR);

mRemote.transact(Stub.TRANSACTION_EvCPress, _data, _reply, 0);

_reply.readException();

_result = _reply.readString();

}

finally {

_reply.recycle();

_data.recycle();

}

return _result;

}

public java.lang.String EvPlusPress() throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

java.lang.String _result;

try {

_data.writeInterfaceToken(DESCRIPTOR);

mRemote.transact(Stub.TRANSACTION_EvPlusPress, _data, _reply, 0);

_reply.readException();

_result = _reply.readString();

}

finally {

_reply.recycle();

_data.recycle();

}

return _result;

}

public java.lang.String EvAssignPress() throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

java.lang.String _result;

try {

_data.writeInterfaceToken(DESCRIPTOR);

mRemote.transact(Stub.TRANSACTION_EvAssignPress, _data, _reply, 0);

_reply.readException();

_result = _reply.readString();

}

finally {

_reply.recycle();

_data.recycle();

}

return _result;

}

}

static final int TRANSACTION_EvDigitPress = (IBinder.FIRST_CALL_TRANSACTION + 0);

static final int TRANSACTION_EvCPress = (IBinder.FIRST_CALL_TRANSACTION + 1);

static final int TRANSACTION_EvPlusPress = (IBinder.FIRST_CALL_TRANSACTION + 2);

static final int TRANSACTION_EvAssignPress = (IBinder.FIRST_CALL_TRANSACTION + 3);

}

public java.lang.String EvDigitPress(int d) throws android.os.RemoteException;

public java.lang.String EvCPress() throws android.os.RemoteException;

public java.lang.String EvPlusPress() throws android.os.RemoteException;

public java.lang.String EvAssignPress() throws android.os.RemoteException;

}

這個calInterface.java檔案是由aidl.exe工具程式所产出的。

首先,calInterface界面继承了Android提供的Iinterface界面,如下述程式碼:

public interface calInterface extends android.os.IInterface

{

………

}這個類別定義又內含有一個Stub類別,其繼承Android提供的Binder父類別,而且實作calInterface介面,如下述程式碼:

public interface calInterface extends android.os.IInterface

{

……….

public static abstract class Stub extends android.os.Binder implements
com.misoo.gx06.calInterface

{

……….

private static class Proxy implements com.misoo.gx06.calInterface

{

………

}

………..

}

由於Stub類別继承了Binder父類別,而Binder又實作了IBinder介面,所以Stub類別支持兩個介面:IBinder和calInterface。其內含的Proxy类別也支持calInterface。

clip_image011

圖1-7
IBinder與calInterface介面之關係

1.4.4細說CalBinder類別的程式碼

基於這個結構,就可以從Stub類別衍生(Derive)出子類別:calBinder,其程式碼為:

/*---- CalBinder.java ----*/

package com.misoo.gx06;

import android.os.RemoteException;

public class CalBinder extends calInterface.Stub{

private Calculator mCal = null;

public CalBinder(){

mCal = new Calculator();

}

@Override

public String EvAssignPress() throws RemoteException {

mCal.EvAssignPress();

return mCal.retStr;

}

@Override

public String EvCPress() throws RemoteException {

mCal.EvCPress();

return mCal.retStr;

}

@Override

public String EvDigitPress(int d) throws RemoteException {

mCal.EvDigitPress(d);

return mCal.retStr;

}

@Override

public String EvPlusPress() throws RemoteException {

mCal.EvPlusPress();

return mCal.retStr;

}

}

其中,指令:

public CalBinder(){

mCal = new Calculator();

}

誕生了一個Calculator物件,如此與Calculator類別銜接起來了。

1.4.5函數呼叫的情境

此範例程式需要用到各AIDL類別的詳細函數如下圖所示:

clip_image013

圖1-8AIDL各類別裡的函數及其關係

只要對物件觀念和技術較為熟悉的話,就可看出來其並不太複雜,只是基本物件觀念之應用而已。更詳細之說明,請看高煥堂所寫的第2本Android書:<> 一書。

分享到:
评论

相关推荐

    深刻解析Android的AIDL界面

    Android的AIDL(Android Interface Definition Language)是一种用于实现Android应用程序间进程间通信(IPC, Inter-Process Communication)的机制。AIDL允许你在不同进程中的组件之间定义接口,使得它们能够相互...

    wps for android AIDL调用

    而AIDL(Android Interface Definition Language)是Android系统提供的一种接口定义语言,用于处理进程间通信(IPC, Inter-Process Communication)。当需要在第三方应用中与WPS Office进行交互时,AIDL就成为了一个...

    AndroidAIDL

    **Android AIDL(Android Interface Definition Language)详解** 在Android系统中,进程间的通信(IPC, Inter-Process Communication)是至关重要的,特别是在开发大型、复杂的应用时。AIDL(Android Interface ...

    android aidl 不同进程间通信

    Android Aidl(Android Interface Definition Language)是Android提供的一种强大的IPC机制,它允许两个不同进程之间的服务进行接口调用,实现了类似远程方法调用(RPC,Remote Procedure Call)的效果。下面将详细...

    Android aidl Binder框架浅析

    **Android aidl Binder框架浅析** 在Android系统中,服务间的通信是通过Binder机制实现的,它是Android系统中进程间通信(IPC)的核心组件。Binder框架允许不同进程间的对象互相调用方法,使得数据和操作可以在不同...

    android AidlDemo(简单aidl的例子)

    在Android开发中,AIDL(Android Interface Definition Language)是一种用于进程间通信(Inter-Process Communication, IPC)的工具,使得不同应用之间的服务可以共享数据和功能。本示例"android AidlDemo(简单aidl...

    android aidl 复杂数据类型 传图片

    在Android应用开发中,AIDL(Android Interface Definition Language)是一种强大的工具,用于实现跨进程通信(IPC,Inter-Process Communication)。当我们需要在一个Activity中调用另一个进程中服务的方法时,AIDL...

    android aidl文件不一致引起的调用出错问题.doc

    Android AIDL 文件不一致引起的调用出错问题 Android AIDL(Android Interface Definition Language)是一种基于接口定义语言,用于定义 Android 应用程序之间的接口。AIDL 文件是用于定义服务端和客户端之间的接口...

    android AIDL 完整DEMO

    Android AIDL(Android Interface Definition Language)是Android系统中用于实现进程间通信(IPC,Inter-Process Communication)的一种机制。在Android应用开发中,当需要在不同进程之间共享数据或调用服务时,...

    Android AIDL demo (Android Studio)

    在Android开发中,AIDL(Android Interface Definition Language)是一种用于实现进程间通信(IPC, Inter-Process Communication)的工具。本教程将详细讲解如何在Android Studio中创建并使用AIDL,以便不同进程间的...

    Android Aidl

    在Android系统中,AIDL(Android Interface Definition Language)是一种接口定义语言,用于实现不同进程间的通信,即远程进程通讯。AIDL使得服务(Service)和活动(Activity)这两个独立的APK之间能够相互通信,...

    android aidl dome下载

    Android AIDL(Android Interface Definition Language)是Android系统提供的一种接口定义语言,用于实现不同应用程序进程间的通信(IPC,Inter-Process Communication)。AIDL允许我们定义服务和服务客户端之间交互...

    Android AIDL使用例子

    在Android系统中,AIDL(Android Interface Definition Language)是一种用于实现进程间通信(Inter-Process Communication, IPC)的工具。AIDL使得不同进程间的组件能够相互通信,即便它们运行在不同的应用程序或...

    android AIDL demo讲解

    Android AIDL(Android Interface Definition Language)是Android系统提供的一种接口定义语言,用于处理进程间通信(IPC, Inter-Process Communication)。在Android应用开发中,当需要在不同进程间共享数据或者...

    Android Aidl 测试Demo

    在Android开发中,AIDL(Android Interface Definition Language)是一种强大的工具,用于实现进程间通信(IPC,Inter-Process Communication)。AIDL使得一个应用能够暴露其服务到其他应用,即使它们运行在不同的...

    Android aidl实现传递对象

    而Android Interface Definition Language(AIDL)是Google提供的一种用于处理进程间通信的语言,它允许应用程序之间透明地交换数据。当我们需要在不同的应用之间传递复杂的对象时,AIDL就显得尤为重要。本文将深入...

    Android AIDL示例代码.zip

    AIDL(Android Interface Definition Language)就是Android系统提供的一种强大的工具,用于处理跨进程通信。这个“Android AIDL示例代码.zip”压缩包中包含了丰富的示例和解释,旨在帮助开发者更好地理解和运用AIDL...

    Android AIDL 一个完整的Demo(包括服务端客户端2个工程)

    在Android开发中,AIDL(Android Interface Definition Language)是一种用于实现跨进程通信(IPC, Inter-Process Communication)的重要工具。本教程将通过一个完整的AIDL Demo来深入理解其工作原理和应用,涉及到...

    Android AIDL 简易demo

    在Android系统中,AIDL(Android Interface Definition Language)是一种用于实现跨进程通信(IPC, Inter-Process Communication)的重要工具。本教程将通过一个简单的AIDL示例,详细讲解如何使用AIDL来实现在不同...

Global site tag (gtag.js) - Google Analytics