Android Service总结06 之AIDL

版本

版本说明

发布时间

发布人

V1.0

初始版本

2013-04-03

Skywang



1 AIDL介绍

 AIDL,即Android InterfaceDefinition Language
    Android使用AIDL来完成进程间通信(IPC),并且一般在服务需要接受不同应用多线程的请求时才需要使用AIDL;如果是同一个应用内的请求使用Binder实现即可;如果只是应用间通信而不是多线程处理的话使用Messenger,当然这两种情况也可以使用AIDL。本地进程和远程进程使用AIDL有所不同,本地进程内调用时会都在调用的线程内执行,远程进程使用是通过Service进程内一个由系统维护的线程池发出调用,所以可能是未知线程同时调用,需要注意线程安全问题。


2 AIDL示例

 创建AIDL服务的步骤:(01)创建.aidl文件。 .aidl是接口文件,它定义了服务所能提供的功能。 (02)实现.aidl所定义的接口。 (03)将接口开放给其它应用程序。 

2.1 创建.aidl文件

 (01)打开eclipse,新建工程”AIDLServiceImpl”,然后在工程的“com.text”包下创建“MyAIDLInterface.aidl”文件。
    如下图:
Android Service总结06 之AIDL
    (02)编辑“MyAIDLInterface.aidl”,提供doubleValue(int val)和halfValue(int value)服务。
    “MyAIDLInterface.aidl”代码如下:
package com.test;interface MyAIDLInterface {    void doubleValue(int val);    void halfValue(int val);}
 (03)编译工程,在“gen”目录下会自动生成与“MyAIDLInterface.aidl”对应的“MyAIDLInterface.java”文件。
    如下图:
Android Service总结06 之AIDL
 “MyAIDLInterface.java”代码如下:
/* * This file is auto-generated.  DO NOT MODIFY. * Original file: F:\\workout\\android\\AIDLServiceImpl\\src\\com\\test\\MyAIDLInterface.aidl */package com.test;public interface MyAIDLInterface extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.test.MyAIDLInterface{private static final java.lang.String DESCRIPTOR = "com.test.MyAIDLInterface";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.test.MyAIDLInterface interface, * generating a proxy if needed. */public static com.test.MyAIDLInterface asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.test.MyAIDLInterface))) {return ((com.test.MyAIDLInterface)iin);}return new com.test.MyAIDLInterface.Stub.Proxy(obj);}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_doubleValue:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();this.doubleValue(_arg0);reply.writeNoException();return true;}case TRANSACTION_halfValue:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();this.halfValue(_arg0);reply.writeNoException();return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.test.MyAIDLInterface{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 void doubleValue(int val) 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.writeInt(val);mRemote.transact(Stub.TRANSACTION_doubleValue, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}public void halfValue(int val) 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.writeInt(val);mRemote.transact(Stub.TRANSACTION_halfValue, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}}static final int TRANSACTION_doubleValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_halfValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);}public void doubleValue(int val) throws android.os.RemoteException;public void halfValue(int val) throws android.os.RemoteException;}

2.2 实现.aidl所定义的接口

 (04)在“com.test”包下新建文件MyAIDLService.java,并实现doubleValue(int val)和halfValue(int value)接口。
    如下图:
Android Service总结06 之AIDL MyAIDLService.java的代码如下:

package com.test;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class MyAIDLService extends Service{    private static final String TAG = "skywang-->MyAIDLService";    private MyAIDLInterface.Stub myBinder =             new MyAIDLInterface.Stub() {                                @Override                public void halfValue(int val) throws RemoteException {                    Log.d(TAG, "halfValue val="+val/2);                                     }                                 @Override                public void doubleValue(int val) throws RemoteException {                    Log.d(TAG, "doubleValue val="+val*2);                                    }            };    @Override    public void onCreate() {                super.onCreate();    }        @Override    public void onDestroy(){        super.onDestroy();    }        @Override    public IBinder onBind(Intent intent) {        return myBinder;    }}

(05) 定义aidl对应的manifest
manifest内容如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.test"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="9"        android:targetSdkVersion="17" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >                <service android:name=".MyAIDLService" android:process=":remote">             <intent-filter>                 <action android:name="com.test.MY_AIDL_SERVICE" />             </intent-filter>         </service>    </application></manifest>
 至此,我们已经完成了.aidl服务的定义和实现。

2.3 将接口开放给其它应用程序

 (06)新建一个工程“AIDLServiceTest”,然后在工程的“com.skywang”包下创建AIDLServiceTest.java;
(07)然后,将MyAIDLInterface.aidl文件拷贝到AIDLServiceTest工程的“com.test”包下。
    如下图:
Android Service总结06 之AIDL
注意:.aidl所在的包名,必须和定义它的包名一样!(即MyAIDLInterface.aidl所在的定义它的工程的包为com.test;那么,调用MyAIDLInterface.aidl的程序,也必须把MyAIDLInterface.aidl放在com.test包下面)  (08)AIDLServiceTest.java首先必须实现ServiceConnection接口。
    实现ServiceConnection接口的原因是:我们在后面调用.aidl服务的时候,必须通过bindService()去绑定服务;而bindService()需要用到ServiceConnection对象。 实现ServiceConnection很简单,只需要实现两个接口: onServiceConnected —— 连上服务的回调函数。一般在此函数中,获取服务对象。  onServiceDisconnected —— 断开服务的回调函数。可以直接返回null。
 ServiceConnection的实现代码如下:
  private MyAIDLInterface mBinder = null;  private ServiceConnection mConnection = new ServiceConnection() {          @Override       public void onServiceDisconnected(ComponentName name) {          mBinder = null;          }          @Override      public void onServiceConnected(ComponentName name, IBinder service) {          Log.d(TAG, "Service connected!");          mBinder = MyAIDLInterface.Stub.asInterface(service);      }  };

(09)开始访问服务之前,我们要先通过bindService()绑定服务;使用完毕之后,通过unbindService()断开服务。
AIDLServiceTest.java代码如下:
package com.skywang;import android.app.Activity;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.content.ComponentName;import android.content.Intent;import android.content.Context;import android.content.ServiceConnection;import com.test.MyAIDLInterface;public class AIDLServiceTest extends Activity {    private static final String TAG = "skywang-->AIDLServiceTest";    private Button mStart = null;    private Button mHalf = null;    private Button mDouble = null;    private Button mEnd = null;        private MyAIDLInterface mBinder = null;    private ServiceConnection mConnection = new ServiceConnection() {                @Override         public void onServiceDisconnected(ComponentName name) {            mBinder = null;            }            @Override        public void onServiceConnected(ComponentName name, IBinder service) {            Log.d(TAG, "Service connected!");            mBinder = MyAIDLInterface.Stub.asInterface(service);        }    };        @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.aidlservice_test);                mStart = (Button) findViewById(R.id.btStart);        mStart.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View arg0) {                Log.d(TAG, "click start button");                            Intent intent = new Intent("com.test.MY_AIDL_SERVICE");                boolean result = bindService(intent, mConnection, Context.BIND_AUTO_CREATE);                if (!result) {                    mBinder = null;                }            }        });        mHalf = (Button) findViewById(R.id.btHalf);        mHalf.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View arg0) {                Log.d(TAG, "click half button");                try {                    if (mBinder != null) {                        mBinder.halfValue(10);                    }                } catch (RemoteException e) {                    e.printStackTrace();                }            }        });        mDouble = (Button) findViewById(R.id.btDouble);        mDouble.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View arg0) {                Log.d(TAG, "click double button");                                try {                    if (mBinder != null) {                        mBinder.doubleValue(10);                    }                } catch (RemoteException e) {                    e.printStackTrace();                }            }        });                mEnd = (Button) findViewById(R.id.btEnd);        mEnd.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View arg0) {                Log.d(TAG, "click end button");                                if (mBinder != null) {                    unbindService(mConnection);                    mBinder = null;                }            }        });    }    }

3 示例演示

    程序运行效果图:
Android Service总结06 之AIDL
    点击“Start”按钮,Logcat如下:DEBUG/skywang-->AIDLServiceTest(276):click half button DEBUG/skywang-->AIDLServiceTest(276):Service connected!    点击“Half”按钮,Logcat如下:DEBUG/skywang-->AIDLServiceTest(276):click half button DEBUG/skywang-->MyAIDLService(285):halfValue val=5    点击“Double”按钮,Logcat如下:DEBUG/skywang-->AIDLServiceTest(276):click double button DEBUG/skywang-->MyAIDLService(285):doubleValue val=20    点击“End”按钮,Logcat如下:DEBUG/skywang-->AIDLServiceTest(276):click end button

4 参考文献

1. Android API文档:http://developer.android.com/guide/components/aidl.html
2. Android AIDL使用详解:http://blog.csdn.net/stonecao/article/details/6425019
点击下载:源代码

更多service内容:

1Android Service总结01 目录

2Android Service总结02 service介绍

3Android Service总结03 之被启动的服务 -- Started Service

4Android Service总结04 之被绑定的服务 -- Bound Service

5Android Service总结05 之IntentService

6Android Service总结06 之AIDL




更多相关文章

  1. Mac与Android文件传输工具 Android File Transfer
  2. android 打开各种文件(setDataAndType)
  3. Android清单文件属性大全
  4. 自定义TabActivity,TabActivity的美化
  5. Android 文件夹命名规范 国际化资源
  6. android4.0自定义标题报错 -----断点记录

随机推荐

  1. Python办公自动化|从Word到Excel
  2. 手把手教你使用Matplotlib绘图|实战
  3. PythonGUI编程|使用Tkinter制作快递查询软
  4. 重庆火锅哪家强,Python帮你探探店
  5. NumPy进阶修炼|基础
  6. Python办公自动化|批量合并PDF,拿来就用
  7. 手把手教你使用Matplotlib|实战
  8. 动画:用动画给面试官解释 TCP 三次握手过
  9. 开始你的第一个机器学习项目|文末送书
  10. 玩转数据处理120题重制说明与下载