1. Android Service总结06 AIDL

版本

版本说明

发布时间

发布人

V1.0

初始版本

2013-04-03

Skywang

       
  1.  

1 AIDL介绍

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

2 AIDL示例

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

2.1 创建.aidl文件

  1. (01)打开eclipse,新建工程”AIDLServiceImpl”,然后在工程的“com.text”包下创建“MyAIDLInterface.aidl”文件。
  1. 如下图:
  1.  
  1. (02)编辑“MyAIDLInterface.aidl”,提供doubleValue(int val)和halfValue(int value)服务。
  1. MyAIDLInterface.aidl”代码如下:
  1. package com.test;
  2.  
  3. interface MyAIDLInterface {
  4.  
  5. void doubleValue(int val);
  6.  
  7. void halfValue(int val);
  8. }
  1. (03)编译工程,在“gen”目录下会自动生成与“MyAIDLInterface.aidl”对应的“MyAIDLInterface.java”文件。
  1. 如下图:
  1. MyAIDLInterface.java”代码如下:
  1. /*
  2. * This file is auto-generated. DO NOT MODIFY.
  3. * Original file: F:\\workout\\android\\AIDLServiceImpl\\src\\com\\test\\MyAIDLInterface.aidl
  4. */
  5. package com.test;
  6. public interface MyAIDLInterface extends android.os.IInterface
  7. {
  8. /** Local-side IPC implementation stub class. */
  9. public static abstract class Stub extends android.os.Binder implements com.test.MyAIDLInterface
  10. {
  11. private static final java.lang.String DESCRIPTOR = "com.test.MyAIDLInterface";
  12. /** Construct the stub at attach it to the interface. */
  13. public Stub()
  14. {
  15. this.attachInterface(this, DESCRIPTOR);
  16. }
  17. /**
  18. * Cast an IBinder object into an com.test.MyAIDLInterface interface,
  19. * generating a proxy if needed.
  20. */
  21. public static com.test.MyAIDLInterface asInterface(android.os.IBinder obj)
  22. {
  23. if ((obj==null)) {
  24. return null;
  25. }
  26. android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
  27. if (((iin!=null)&&(iin instanceof com.test.MyAIDLInterface))) {
  28. return ((com.test.MyAIDLInterface)iin);
  29. }
  30. return new com.test.MyAIDLInterface.Stub.Proxy(obj);
  31. }
  32. public android.os.IBinder asBinder()
  33. {
  34. return this;
  35. }
  36. @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
  37. {
  38. switch (code)
  39. {
  40. case INTERFACE_TRANSACTION:
  41. {
  42. reply.writeString(DESCRIPTOR);
  43. return true;
  44. }
  45. case TRANSACTION_doubleValue:
  46. {
  47. data.enforceInterface(DESCRIPTOR);
  48. int _arg0;
  49. _arg0 = data.readInt();
  50. this.doubleValue(_arg0);
  51. reply.writeNoException();
  52. return true;
  53. }
  54. case TRANSACTION_halfValue:
  55. {
  56. data.enforceInterface(DESCRIPTOR);
  57. int _arg0;
  58. _arg0 = data.readInt();
  59. this.halfValue(_arg0);
  60. reply.writeNoException();
  61. return true;
  62. }
  63. }
  64. return super.onTransact(code, data, reply, flags);
  65. }
  66. private static class Proxy implements com.test.MyAIDLInterface
  67. {
  68. private android.os.IBinder mRemote;
  69. Proxy(android.os.IBinder remote)
  70. {
  71. mRemote = remote;
  72. }
  73. public android.os.IBinder asBinder()
  74. {
  75. return mRemote;
  76. }
  77. public java.lang.String getInterfaceDescriptor()
  78. {
  79. return DESCRIPTOR;
  80. }
  81. public void doubleValue(int val) throws android.os.RemoteException
  82. {
  83. android.os.Parcel _data = android.os.Parcel.obtain();
  84. android.os.Parcel _reply = android.os.Parcel.obtain();
  85. try {
  86. _data.writeInterfaceToken(DESCRIPTOR);
  87. _data.writeInt(val);
  88. mRemote.transact(Stub.TRANSACTION_doubleValue, _data, _reply, 0);
  89. _reply.readException();
  90. }
  91. finally {
  92. _reply.recycle();
  93. _data.recycle();
  94. }
  95. }
  96. public void halfValue(int val) throws android.os.RemoteException
  97. {
  98. android.os.Parcel _data = android.os.Parcel.obtain();
  99. android.os.Parcel _reply = android.os.Parcel.obtain();
  100. try {
  101. _data.writeInterfaceToken(DESCRIPTOR);
  102. _data.writeInt(val);
  103. mRemote.transact(Stub.TRANSACTION_halfValue, _data, _reply, 0);
  104. _reply.readException();
  105. }
  106. finally {
  107. _reply.recycle();
  108. _data.recycle();
  109. }
  110. }
  111. }
  112. static final int TRANSACTION_doubleValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
  113. static final int TRANSACTION_halfValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
  114. }
  115. public void doubleValue(int val) throws android.os.RemoteException;
  116. public void halfValue(int val) throws android.os.RemoteException;
  117. }
  1.  

2.2 实现.aidl所定义的接口

  1. (04)在“com.test”包下新建文件MyAIDLService.java,并实现doubleValue(int val)和halfValue(int value)接口。
  1. 如下图:

  1. MyAIDLService.java的代码如下:
  1. package com.test;
  2.  
  3. import android.app.Service;
  4. import android.content.Intent;
  5. import android.os.IBinder;
  6. import android.os.RemoteException;
  7. import android.util.Log;
  8.  
  9. public class MyAIDLService extends Service{
  10. private static final String TAG = "skywang-->MyAIDLService";
  11.  
  12. private MyAIDLInterface.Stub myBinder =
  13. new MyAIDLInterface.Stub() {
  14.  
  15. @Override
  16. public void halfValue(int val) throws RemoteException {
  17. Log.d(TAG, "halfValue val="+val/2);
  18.  
  19. }
  20.  
  21. @Override
  22. public void doubleValue(int val) throws RemoteException {
  23. Log.d(TAG, "doubleValue val="+val*2);
  24. }
  25. };
  26. @Override
  27. public void onCreate() {
  28. super.onCreate();
  29. }
  30.  
  31. @Override
  32. public void onDestroy(){
  33. super.onDestroy();
  34. }
  35.  
  36. @Override
  37. public IBinder onBind(Intent intent) {
  38. return myBinder;
  39. }
  40. }
  1. (05) 定义aidl对应的manifest
    manifest内容如下:
  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2. package="com.test"
  3. android:versionCode="1"
  4. android:versionName="1.0" >
  5.  
  6. <uses-sdk
  7. android:minSdkVersion="9"
  8. android:targetSdkVersion="17" />
  9.  
  10. <application
  11. android:allowBackup="true"
  12. android:icon="@drawable/ic_launcher"
  13. android:label="@string/app_name"
  14. android:theme="@style/AppTheme" >
  15.  
  16. <service android:name=".MyAIDLService" android:process=":remote">
  17. <intent-filter>
  18. <action android:name="com.test.MY_AIDL_SERVICE" />
  19. </intent-filter>
  20. </service>
  21.  
  22. </application>
  23.  
  24. </manifest>
  1. 至此,我们已经完成了.aidl服务的定义和实现。
  1.  

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

  1. (06)新建一个工程“AIDLServiceTest”,然后在工程的“com.skywang”包下创建AIDLServiceTest.java
    (07)然后,将MyAIDLInterface.aidl文件拷贝到AIDLServiceTest工程的“com.test”包下。
  1. 如下图:
  1. 注意:.aidl所在的包名,必须和定义它的包名一样!(即MyAIDLInterface.aidl所在的定义它的工程的包为com.test;那么,调用MyAIDLInterface.aidl的程序,也必须把MyAIDLInterface.aidl放在com.test包下面)
  2.  
  3. (08)AIDLServiceTest.java首先必须实现ServiceConnection接口。
  1. 实现ServiceConnection接口的原因是:我们在后面调用.aidl服务的时候,必须通过bindService()去绑定服务;而bindService()需要用到ServiceConnection对象。
  2. 实现ServiceConnection很简单,只需要实现两个接口:
  3. onServiceConnected    —— 连上服务的回调函数。一般在此函数中,获取服务对象。  
  4. onServiceDisconnected —— 断开服务的回调函数。可以直接返回null
  1. ServiceConnection的实现代码如下:
  1. private MyAIDLInterface mBinder = null;
  2. private ServiceConnection mConnection = new ServiceConnection() {
  3.  
  4. @Override
  5. public void onServiceDisconnected(ComponentName name) {
  6. mBinder = null;
  7. }
  8.  
  9. @Override
  10. public void onServiceConnected(ComponentName name, IBinder service) {
  11. Log.d(TAG, "Service connected!");
  12. mBinder = MyAIDLInterface.Stub.asInterface(service);
  13. }
  14. };
  1. (09)开始访问服务之前,我们要先通过bindService()绑定服务;使用完毕之后,通过unbindService()断开服务。
    AIDLServiceTest.java代码如下:
  1. package com.skywang;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.os.IBinder;
  6. import android.os.RemoteException;
  7. import android.util.Log;
  8. import android.view.View;
  9. import android.view.View.OnClickListener;
  10. import android.widget.Button;
  11. import android.content.ComponentName;
  12. import android.content.Intent;
  13. import android.content.Context;
  14. import android.content.ServiceConnection;
  15. import com.test.MyAIDLInterface;
  16.  
  17. public class AIDLServiceTest extends Activity {
  18. private static final String TAG = "skywang-->AIDLServiceTest";
  19.  
  20. private Button mStart = null;
  21. private Button mHalf = null;
  22. private Button mDouble = null;
  23. private Button mEnd = null;
  24.  
  25. private MyAIDLInterface mBinder = null;
  26. private ServiceConnection mConnection = new ServiceConnection() {
  27.  
  28. @Override
  29. public void onServiceDisconnected(ComponentName name) {
  30. mBinder = null;
  31. }
  32.  
  33. @Override
  34. public void onServiceConnected(ComponentName name, IBinder service) {
  35. Log.d(TAG, "Service connected!");
  36. mBinder = MyAIDLInterface.Stub.asInterface(service);
  37. }
  38. };
  39.  
  40. @Override
  41. public void onCreate(Bundle savedInstanceState) {
  42. super.onCreate(savedInstanceState);
  43. setContentView(R.layout.aidlservice_test);
  44.  
  45. mStart = (Button) findViewById(R.id.btStart);
  46. mStart.setOnClickListener(new View.OnClickListener() {
  47.  
  48. @Override
  49. public void onClick(View arg0) {
  50. Log.d(TAG, "click start button");
  51.  
  52. Intent intent = new Intent("com.test.MY_AIDL_SERVICE");
  53. boolean result = bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
  54. if (!result) {
  55. mBinder = null;
  56. }
  57. }
  58. });
  59.  
  60. mHalf = (Button) findViewById(R.id.btHalf);
  61. mHalf.setOnClickListener(new View.OnClickListener() {
  62.  
  63. @Override
  64. public void onClick(View arg0) {
  65. Log.d(TAG, "click half button");
  66.  
  67. try {
  68. if (mBinder != null) {
  69. mBinder.halfValue(10);
  70. }
  71. } catch (RemoteException e) {
  72. e.printStackTrace();
  73. }
  74. }
  75. });
  76.  
  77. mDouble = (Button) findViewById(R.id.btDouble);
  78. mDouble.setOnClickListener(new View.OnClickListener() {
  79.  
  80. @Override
  81. public void onClick(View arg0) {
  82. Log.d(TAG, "click double button");
  83.  
  84. try {
  85. if (mBinder != null) {
  86. mBinder.doubleValue(10);
  87. }
  88. } catch (RemoteException e) {
  89. e.printStackTrace();
  90. }
  91. }
  92. });
  93.  
  94. mEnd = (Button) findViewById(R.id.btEnd);
  95. mEnd.setOnClickListener(new View.OnClickListener() {
  96.  
  97. @Override
  98. public void onClick(View arg0) {
  99. Log.d(TAG, "click end button");
  100.  
  101. if (mBinder != null) {
  102. unbindService(mConnection);
  103. mBinder = null;
  104. }
  105. }
  106. });
  107. }
  108.  
  109. }
  1.  

3 示例演示

  1. 程序运行效果图:
  1. 点击Start按钮,Logcat如下:
  2. DEBUG/skywang-->AIDLServiceTest(276):click half button
  3. DEBUG/skywang-->AIDLServiceTest(276):Service connected!
  4.  
  5. 点击Half按钮,Logcat如下:
  6. DEBUG/skywang-->AIDLServiceTest(276):click half button
  7. DEBUG/skywang-->MyAIDLService(285):halfValue val=5
  8.  
  9. 点击Double按钮,Logcat如下:
  10. DEBUG/skywang-->AIDLServiceTest(276):click double button
  11. DEBUG/skywang-->MyAIDLService(285):doubleValue val=20
  12.  
  13. 点击End按钮,Logcat如下:
  14. DEBUG/skywang-->AIDLServiceTest(276):click end button

4 参考文献

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

  1. 更多service内容:

Android Service总结01 目录

Android Service总结02 service介绍

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

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

Android Service总结05 之IntentService

Android Service总结06 之AIDL


  1.  

Android Service总结06 之AIDL的更多相关文章

  1. Android Service和Binder、AIDL

    1.首先理解service的作用和生命周期 由于activity如果切换,那么他就不再运行,那么我们想在玩游戏的时候听播放器中的音乐,activity就应运而生了,这是最常见的一种场景,同时servi ...

  2. Android Service总结05 之IntentService

    Android Service总结05 之IntentService   版本 版本说明 发布时间 发布人 V1.0 添加了IntentService的介绍和示例 2013-03-17 Skywang ...

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

    Android Service总结04 之被绑定的服务 -- Bound Service 版本 版本说明 发布时间 发布人 V1.0 添加了Service的介绍和示例 2013-03-17 Skywa ...

  4. Android Service总结01 目录

    Android Service总结01 目录 1 Android Service总结01 目录 2 Android Service总结02 service介绍 介绍了“4种service 以及 它们的 ...

  5. Android Service总结02 service介绍

    Android Service总结02 service介绍 版本 版本说明 发布时间 发布人 V1.0 介绍了Service的种类,常用API,生命周期等内容. 2013-03-16 Skywang ...

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

    Android Service总结03 之被启动的服务 -- Started Service 版本 版本说明 发布时间 发布人 V1.0 添加了Service的介绍和示例 2013-03-17 Sky ...

  7. android service 的各种用法(IPC、AIDL)

    http://my.oschina.net/mopidick/blog/132325 最近在学android service,感觉终于把service的各种使用场景和用到的技术整理得比较明白了,受益颇 ...

  8. Android service binder aidl 关系

    /********************************************************************************** * Android servic ...

  9. Android Service AIDL 远程调用服务 【简单音乐播放实例】

    Android Service是分为两种: 本地服务(Local Service): 同一个apk内被调用 远程服务(Remote Service):被另一个apk调用 远程服务需要借助AIDL来完成 ...

随机推荐

  1. Docker 下 mysql 简单的 主从复制实现

    1. 拉取镜像 docker pull mysql: 2. 运行这个镜像 docker run -d --name maser mysql: 3. 安装一些必要的软件 docker exec -it ...

  2. TP3.2加载外部PHPexcel类,实现导入和导出

    TP3.2加载外部PHPexcel类,实现导入和导出 导入: 1.将下载好的PHPexcel文件放到libray/Org/Uti/文件夹下,将PHPEXCEL.PHP改为PHPEXCEL.class. ...

  3. delphi 控件的名称怎么不显示了

    选择菜单 Tools--Environment在打开的对话框中选择 Designer 页,选 其中的 Options 选项勾选 Show component captions ,点击 OK即可

  4. JS频率控制函数

    /** * 频率控制 返回函数连续调用时,fn 执行频率限定为每多少时间执行一次 * @param {Function} fn 需要调用的函数 * @param {Number} delay 延迟时间 ...

  5. letsencrypt续期 最简单的续期方法更新证书

    Let's Encrypt申请的证书会有三个月的有效期,如何更方便的续期呢? 关于证书续期: 所谓letsencrypt续期,续期相当于重新申请一次证书,然后在服务器端将过期的证书替换掉即可.由于这个 ...

  6. 普通的jdbc事务在插入数据后 下面的代码报错时 数据不会回滚 但是 spring的事务会回滚

    普通的jdbc事务在插入数据后 下面的代码报错时 数据不会回滚 但是 spring的事务会回滚

  7. 想转C++了

    暑假想学一学C++ 早退役了高考后才转C++的oier——我真是太蒻了

  8. Mobile Phone Network CodeForces - 1023F(并查集lca+修改环)

    题意: 就是有几个点,你掌控了几条路,你的商业对手也掌控了几条路,然后你想让游客都把你的所有路都走完,那么你就有钱了,但你又想挣的钱最多,真是的过分..哈哈 游客肯定要对比一下你的对手的路 看看那个便 ...

  9. 【转】#pragma的用法

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

  10. 缓存面板获取之前页面选中的数据Objuid的方法

    String partUid = request.getParameter("contextInstanceUid"); contextInstanceUid是存在总线总的键名,存 ...