http://bbs.51cto.com/thread-1086040-1.html
前言
为使应用程序之间能够彼此通信,Android提供了IPC (Inter Process Communication,进程间通信)的一种独特实现: AIDL (Android Interface Definition Language, Android接口定义语言)。
网上看了几篇关于AIDL的文章,写得都很不错,不过例子构造大多略微复杂: 建立两个Android项目,一个是client,一个是server(提供service)。
这篇文章将通过一个项目来介绍AIDL用法,包含了service和client。可能简单了些,不过轻省许多。


这篇博文包含以下两个部分:
1、AIDL介绍
2、定义
3、用例: HelloSumAIDL
    3.1、创建工程
    3.2、定义AIDL文件
    3.3、实现远程服务(Service)
    3.4、“暴露”服务
    3.5、相关代码


一、 AIDL介绍
在Android中,每个应用(Application)执行在它自己的进程中,无法直接调用到其他应用的资源,这也符合“沙箱”的理念。所谓沙箱原理,一般来说用在移动电话业务中,简单地说旨在部分地或全部地隔离应用程序。关于沙箱技术我们这里就不多做介绍了,可以参看51CTO的这篇文章。
因此,在Android中,当一个应用被执行时,一些操作是被限制的,比如访问内存,访问传感器,等等。这样做可以最大化地保护系统,免得应用程序“为所欲为”。
那我们有时需要在应用间交互,怎么办呢?于是,Android需要实现IPC协议。然而,这个协议还是有点复杂,主要因为需要实现数据管理系统(在进程或线程间传递数据)。为了暂时减缓这个“会呼吸的痛”,Android为我们实现了自己的IPC,也就是梁静茹,oh,sorry,是AIDL :] 




二、 定义
AIDL是IPC的一个轻量级实现,用了对于Java开发者来说很熟悉的语法。Android也提供了一个工具,可以自动创建Stub(类构架,类骨架)。当我们需要在应用间通信时,我们需要按以下几步走:
1. 定义一个AIDL接口
2. 为远程服务(Service)实现对应Stub
3. 将服务“暴露”给客户程序使用

三、 用例: HelloSumAIDL
AIDL的语法很类似Java的接口(Interface),只需要定义方法的签名。
AIDL支持的数据类型与Java接口支持的数据类型有些不同
1. 所有基础类型(int, char, 等)
2. String,List,Map,CharSequence等类
3. 其他AIDL接口类型
4. 所有Parcelable的类



为了更好地展示AIDL的用法,我们来看一个很简单的例子: 两数相加。



3.1
创建工程

事不宜迟,我们就创建一个Android项目。以下是项目的基本信息(不一定要一样):
- 项目名称: HelloSumAIDL
- 目标平台: 4.3
- 包名: com.android.hellosumaidl
- Activity名称: HelloSumAidlActivity




3.2 创建工程
com.android.hellosumaidl
这个包中,新建一个普通文件(New->File),取名为 IAdditionService.aidl。在这个文件中输入以下代码:





1
2
3
4
5
6
7
package com.android.hellosumaidl;
// Interface declaration
interface IAdditionService {
    // You can pass the value of in, out or inout
    // The primitive types (int, boolean, etc) are only passed by in
    int add(in int value1, in int value2);
}




一旦文件被保存,Android的AIDL工具会在 gen/com/android/hellosumaidl这个文件夹里自动生成对应的
IAdditionService.java这个文件。因为是自动生成的,所以无需改动。这个文件里就包含了 Stub,我们接下来要为我们的远程服务实现这个Stub。

3.3 实现远程服务
首先我们在
com.android.hellosumaidl
这个包中
新建一个类,取名叫 AdditionService.java。为了 实现我们 的服务,我们需要让 这个 类中的onBind方法返回一个IBinder类的对象。这个IBinder类的对象就代表了远程服务的实现。为了实现这个服务,我们要用到自动生成的子类IAdditionService.Stub。在其中,我们也必须实现我们之前在AIDL文件中定义的add() 数。下面是我们远程服务的代码:






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.android.hellosumaidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
/*
* This class exposes the service to client
*/
public class AdditionService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    @Override
    public IBinder onBind(Intent intent) {
        return new IAdditionService.Stub() {
            /*
             * Implement com.android.hellosumaidl.IAdditionService.add(int, int)
             */
            @Override
            public int add(int value1, int value2) throws RemoteException {
                return value1 + value2;
            }
        };
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}




3.4 “暴露”服务
一旦实现了服务中的onBind方法 ,我们就可以把客户程序(在这里是HelloSumAidlActivity.java)与服务连接起来了。为了建立这样的一个链接 ,我们需要实现ServiceConnection类。我们在 HelloSumAidlActivity.java 创建一个内部类AdditionServiceConnection,这个类继承ServiceConnection类,并且重写了它的两个方法:onServiceConnectedonServiceDisconnected。下面给出内部类的代码:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
* This inner class is used to connect to the service
*/
class AdditionServiceConnection implements ServiceConnection {
    public void onServiceConnected(ComponentName name, IBinder boundService) {
        service = IAdditionService.Stub.asInterface((IBinder)boundService);
        Toast.makeText(HelloSumAidlActivity.this, "Service connected", Toast.LENGTH_LONG).show();
    }
                                                                                                                                                                                                          
    public void onServiceDisconnected(ComponentName name) {
        service = null;
        Toast.makeText(HelloSumAidlActivity.this, "Service disconnected", Toast.LENGTH_LONG).show();
    }
}



这个方法接收一个远程服务的实现作为参数。这个实现随后被转换(cast)
为我们自己的AIDL的实现。我们使用  IAdditionService.Stub.asInterface((IBinder)boundService)


3.5 相关代码
为了完成我们的测试项目,我们需要首先改写
main.xml
(主界面的格局文件)和string.xml (字符串定义文件):



main.xml





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="utf-8"?>
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
            android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello"
        android:textSize="22sp" />
                                                                                                                                                      
            android:id="@+id/value1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="@string/hint1" >
   
                                                                                                                                                      
            android:id="@+id/TextView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/plus"
        android:textSize="36sp" />
                                                                                                                                                      
            android:id="@+id/value2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="@string/hint2" >
   
                                                                                                                                                      
            android:id="@+id/buttonCalc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="@string/equal" >
   
                                                                                                                                                      
            android:id="@+id/result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/result"
        android:textSize="36sp" />
                                                                                                                                                      





string.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>

    HelloSumAIDL
    Hello Sum AIDL
    Result
                                                                                                                                               
    +
    =
                                                                                                                                               
    Value 1
    Value 2
                                                                                                                                               





最后,我们的 HelloSumAidlActivity.java如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package com.android.hellosumaidl;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
public class HelloSumAidlActivity extends Activity {
    IAdditionService service;
    AdditionServiceConnection connection;
                                                                                                                             
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
                                                                                                                                 
        initService();
                                                                                                                                 
        Button buttonCalc = (Button)findViewById(R.id.buttonCalc);
                                                                                                                                 
        buttonCalc.setOnClickListener(new OnClickListener() {
            TextView result = (TextView)findViewById(R.id.result);
            EditText value1 = (EditText)findViewById(R.id.value1);
            EditText value2 = (EditText)findViewById(R.id.value2);
                                                                                                                                     
            @Override
            public void onClick(View v) {
                int v1, v2, res = -1;
                v1 = Integer.parseInt(value1.getText().toString());
                v2 = Integer.parseInt(value2.getText().toString());
                                                                                                                                         
                try {
                    res = service.add(v1, v2);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                                                                                                                                         
                result.setText(Integer.valueOf(res).toString());
            }
        });
    }
                                                                                                                             
    @Override
    protected void onDestroy() {
        super.onDestroy();
        releaseService();
    }
                                                                                                                             
    /*
     * This inner class is used to connect to the service
     */
    class AdditionServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName name, IBinder boundService) {
            service = IAdditionService.Stub.asInterface((IBinder)boundService);
            Toast.makeText(HelloSumAidlActivity.this, "Service connected", Toast.LENGTH_LONG).show();
        }
                                                                                                                                 
        public void onServiceDisconnected(ComponentName name) {
            service = null;
            Toast.makeText(HelloSumAidlActivity.this, "Service disconnected", Toast.LENGTH_LONG).show();
        }
    }
                                                                                                                             
    /*
     * This function connects the Activity to the service
     */
    private void initService() {
        connection = new AdditionServiceConnection();
        Intent i = new Intent();
        i.setClassName("com.android.hellosumaidl", com.android.hellosumaidl.AdditionService.class.getName());
        boolean ret = bindService(i, connection, Context.BIND_AUTO_CREATE);
    }
                                                                                                                             
    /*
     * This function disconnects the Activity from the service
     */
    private void releaseService() {
        unbindService(connection);
        connection = null;
    }
}




将此项目运行起来,得到的两个截图如下:


Fig 1 : 填写数字前





Fig 2 : 按下计算按钮后




后记


附上测试项目的Android代码包

  HelloSumAidl.zip  (1.41 MB)

2013-12-4 17:25, 下载次数: 3463

本帖最近评分记录 rongwei84n 无忧币 +10  多谢分享 2013-12-4 18:03

更多相关文章

  1. android 开发环境配置
  2. Android中PopupWindow自定义坐标实现
  3. android实现简单的画画板
  4. Android中TabLayout添加小红点
  5. Android官方命令深入分析之Hierarchy Viewer
  6. Android与JavaScrpit相互调用
  7. 浅谈Java中Collections.sort对List排序的两种方法
  8. NPM 和webpack 的基础使用
  9. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程

随机推荐

  1. Android(安卓)jetpack的Paging和Room结合
  2. Android之Activity全方位解析
  3. NDK进阶实例
  4. APP开发实战61-Activity消息路由
  5. Android补间动画
  6. 【Arduino】开发入门【十】Arduino蓝牙模
  7. Android(安卓)OpenGL详解一
  8. Android(安卓)NDK 下的宽字符编码转换及i
  9. Android应用程序安装过程解析(源码角度)
  10. Android自带的下载功能,不需要断点续传、