一、前言

Android中的RPC参考了JAVA中的RMI(remote methord invocation)方案;Android中的RPC机制是为了实现进程间通信,即一个进程使用另一个进程中的远程对象,Android用AIDL(android interface defined language,Android接口定义语言)来实现,使用户可以很方便的定义一套接口,然后通过远程Service为代理,客户端在绑定该远程Service时,获得远程对象,然后就可以使用该对象。

二、流程

1. 定义一个.aidl接口文件,ADT则会在gen目录下,自动生成一个对应的.java文件(此文件为自动生成,不可修改);
2. 自动生成的.java中,有一个抽象的Stub类,因此,创建一个基于Stub的子类,并实现在.aidl中定义的接口;
3. 创建一个Service子类,在onCreate中,创建步骤2中的实例对象,在onBind中,返回该实例对象;
4. 在Activity中,发送一个bindService(it, conn, BIND_AUTO_CREATE),请求绑定远程Service;
5. 若成功,则在ServiceConnection.onServiceConnected中获得步骤3中的实例对象;
6. 在AndroidManifest.xml中,注册远程Service;

三、例子

按照流程中的步骤,实现该例子:

3.1 定义.aidl文件

package com.chris.rpc.aidl;interface ITest {void setCustomerName(String name);String getCustomerName();}

很简单,定义了两个接口,然后,ADT就会自动在gen目录下生成ITest.java文件,我们来看看:

/* * This file is auto-generated.  DO NOT MODIFY. * Original file: E:\\chris\\Android_Dev\\eclipse\\workspace\\RpcAidl\\src\\com\\chris\\rpc\\aidl\\ITest.aidl */package com.chris.rpc.aidl;public interface ITest extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.chris.rpc.aidl.ITest{private static final java.lang.String DESCRIPTOR = "com.chris.rpc.aidl.ITest";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.chris.rpc.aidl.ITest interface, * generating a proxy if needed. */public static com.chris.rpc.aidl.ITest asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.chris.rpc.aidl.ITest))) {return ((com.chris.rpc.aidl.ITest)iin);}return new com.chris.rpc.aidl.ITest.Stub.Proxy(obj);}@Override public android.os.IBinder asBinder(){return this;}@Override 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_setCustomerName:{data.enforceInterface(DESCRIPTOR);java.lang.String _arg0;_arg0 = data.readString();this.setCustomerName(_arg0);reply.writeNoException();return true;}case TRANSACTION_getCustomerName:{data.enforceInterface(DESCRIPTOR);java.lang.String _result = this.getCustomerName();reply.writeNoException();reply.writeString(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.chris.rpc.aidl.ITest{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}@Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}@Override public void setCustomerName(java.lang.String name) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeString(name);mRemote.transact(Stub.TRANSACTION_setCustomerName, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}@Override public java.lang.String getCustomerName() 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_getCustomerName, _data, _reply, 0);_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_setCustomerName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_getCustomerName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);}public void setCustomerName(java.lang.String name) throws android.os.RemoteException;public java.lang.String getCustomerName() throws android.os.RemoteException;}

3.2 创建Stub子类,并实现接口:

package com.chris.rpc.aidl;import android.os.RemoteException;import android.util.Log;import com.chris.rpc.aidl.ITest.Stub;public class MyTest extends Stub {private final static String TAG = "ChrisRpcAidl";private String strName = "";@Overridepublic void setCustomerName(String name) throws RemoteException {Log.d(TAG, "[MyTest] setCustomerName name = " + name);strName = name;}@Overridepublic String getCustomerName() throws RemoteException {Log.d(TAG, "[MyTest] getCustomerName name = " + strName);return strName;}}

3.3 创建远程Service类:

package com.chris.rpc.aidl;import com.chris.rpc.aidl.ITest.Stub;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.util.Log;public class MyService extends Service {private final static String TAG = "ChrisRpcAidl";private Stub mTest = null;@Overridepublic IBinder onBind(Intent arg0) {Log.d(TAG, "onBind ...");return mTest;}@Overridepublic void onCreate() {Log.d(TAG, "onCreate ...");mTest = new MyTest();super.onCreate();}}

3.4 在Activity中请求绑定该远程Service,并获取实例:

package com.chris.rpc.aidl;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;public class MainActivity extends Activity {private final static String TAG = "ChrisRpcAidl";private final static String SERVICE_ACTION = "com.chris.rpc.aidl.action.MYSERVICE";private ITest mTest = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent it = new Intent();it.setAction(SERVICE_ACTION);// 发送绑定Service请求,如果成功,则会调用ServiceConnectionbindService(it, conn, BIND_AUTO_CREATE);}private ServiceConnection conn = new ServiceConnection(){// 绑定成功,返回的对象是IBinder接口,通过asInterface转换为定义的ITest接口@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.d(TAG, "onServiceConnected ...");mTest = ITest.Stub.asInterface(service);if(mTest != null){try {mTest.setCustomerName("chris");Log.d(TAG, "-------------------");Log.d(TAG, "get name = " + mTest.getCustomerName());} catch (RemoteException e) {e.printStackTrace();}}}@Overridepublic void onServiceDisconnected(ComponentName name) {}};}

3.5 在AndroidManifest.xml中,注册远程Service:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.chris.rpc.aidl"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="10"        android:targetSdkVersion="10" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name="com.chris.rpc.aidl.MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <service android:name="com.chris.rpc.aidl.MyService">            <intent-filter>                <action android:name="com.chris.rpc.aidl.action.MYSERVICE" />            </intent-filter>        </service>    </application></manifest>

3.6 运行截图:

四、小结

本篇文章是让大家了解AIDL的过程,特别是大家需要理解一个自动生成的接口类的中Stub, asInterface, onTransact方法,这些方法在Android Java Framework中有对应的实现,并最终通过native来完成。然后就是大家要了解这个远程Service的用法就可以了。AIDL通常用在如手机播放器这类应用中,各个activity与service绑定后,可以控制播放器的各个状态。
(之后要是有空,我会继续写androd java framework中关于binder的理解)

更多相关文章

  1. Android中一个Activity调用另一个Activity — Intent对象的使用
  2. AIDL(android 接口描述语言)
  3. Android中自定义Tab的实现
  4. Android利用drawable文件夹自定义控件背景、样式
  5. Android(安卓)Makefile中是 如何识别 TARGET_PRODUCT 的
  6. Android简单自定义圆形和水平ProgressBar
  7. 【Android(安卓)Training UI】创建自定义Views(Lesson 0 - 章节
  8. Android(安卓)ApiDemos示例解析(132):Views->Layout Animation->
  9. 2.高焕堂讲解 ContentProvider范例

随机推荐

  1. android点滴(11) -- Android常用命令
  2. android 权限介绍(一)
  3. android NDK/JNI-实例开发流程
  4. android Toolbar的使用结合状态栏与返回
  5. 【Android Audio】Android Audio System
  6. Android SDK目录结构和工具介绍
  7. Android recyclerview更新item位置移动
  8. 【荐货】Android主流技术知多少?
  9. Android音频系统之四AudioPolicy
  10. Android SQLite Shell