Android开发之IPC进程间通信-AIDL介绍及实例解析
一、IPC进程间通信
IPC是进程间通信方法的统称,Linux IPC包括以下方法,Android的进程间通信主要采用是哪些方法呢?
1. 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
2. 信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);
3. 报文(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
4. 共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
5. 信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
6. 套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
二、AIDL(Android Interface Definition Language)
AIDL - Android Interface Definition Language - Android 接口定义语言。因为在Android中,应用程序运行在各自独立的进程里。应用程序之间是不能访问对方的内存空间的。有时为了实现进程间的通信,要用到PCI机制。Android支持PCI机制,但是需要Android能读懂的序列化数据(marshaling/un marshaling of data). AIDL就是为了描述这样的数据产生的,它是一种接口定义语言。语法类似JAVA,.aidl文件里面写的是公布给客户端接口声明。
本文中,为了吸取客户端,服务器端两个android 项目的经验,将两段整合到一个android项目里,这样可能会比较清晰。下面就看看实例解析吧。
三、AIDL介绍及解析
1.AIDL介绍
在Android中,每个应用(Application)执行在它自己的进程中,无法直接调用到其他应用的资源,这也符合“沙箱”的理念。所谓沙箱原理,一般来说用在移动电话业务中,简单地说旨在部分地或全部地隔离应用程序。关于沙箱技术我们这里就不多做介绍了。因此,在Android中,当一个应用被执行时,一些操作是被限制的,比如访问内存,访问传感器,等等。这样做可以最大化地保护系统,免得应用程序“为所欲为”。那我们有时需要在应用间交互,怎么办呢?于是,Android需要实现IPC协议。然而,这个协议还是有点复杂,主要因为需要实现数据管理系统(在进程或线程间传递数据)。Android为我们实现了自己的IPC,也就是AIDL。
2.定义AIDL接口
AIDL是IPC的一个轻量级实现,用了对于Java开发者来说很熟悉的语法。Android也提供了一个工具,可以自动创建Stub(类构架,类骨架)。当我们需要在应用间通信时,我们需要按以下几步走:
a. 定义一个AIDL接口
b. 为远程服务(Service)实现对应Stub
c. 将服务“暴露”给客户程序使用
3.实例解析
AIDL的语法很类似Java的接口(Interface),只需要定义方法的签名。
AIDL支持的数据类型与Java接口支持的数据类型有些不同
a. 所有基础类型(int, char, 等)
b. String,List,Map,CharSequence等类
c. 其他AIDL接口类型
d. 所有Parcelable的类
下面以一个加法器为例来做解析。
(1)创建工程,创建AIDL接口:新建一个文件,命名为IAdditionService.aidl 即可
package com.czm.hellosumaidl; interface IAdditionService{
int add(int value1,int value2);
}
一旦文件被保存,Android的AIDL工具会在 gen/com/android/hellosumaidl 这个文件夹里自动生成对应的 IAdditionService.java 这个文件。因为是自动生成的,所以无需改动。这个文件里就包含了 Stub ,我们接下来要为我们的远程服务实现这个Stub。
(2)实现远程服务
首先我们新建一个类,取名叫AdditionService.java 。为了 实现我们 的服务,我们需要让 这个 类中的 onBind方法返回一个 IBinder 类的对象。这个 IBinder 类的对象就代表了远程服务的实现。为了实现这个服务,我们要用到自动生成的子类 IAdditionService.Stub 。在其中,我们也必须实现我们之前在AIDL文件中定义的 add() 函 数。下面是我们远程服务的代码:
public class AdditionService extends Service{ @Override
public void onCreate() {
super.onCreate();
} @Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return new IAdditionService.Stub() { @Override
public int add(int value1, int value2) throws RemoteException {
// TODO Auto-generated method stub
return value1 + value2;
}
};
} @Override
public void onDestroy() {
super.onDestroy();
} }
(3)提供服务(“暴露”服务给使用者)
一旦实现了服务中的onBind方法 ,我们就可以把客户程序(在这里是MainActivity.java )与服务连接起来了。为了建立这样的一个链接 ,我们需要实现 ServiceConnection 类。我们在 MainActivity.java 创建一个内部类 AdditionServiceConnection ,这个类继承 ServiceConnection 类,并且重写了它的两个方法: onServiceConnected 和 onServiceDisconnected。下面给出 内部类的代码:
class AdditionServiceConnection implements ServiceConnection { @Override
public void onServiceConnected(ComponentName name, IBinder boundService) {
// TODO Auto-generated method stub
service = IAdditionService.Stub.asInterface((IBinder) boundService);
Toast.makeText(MainActivity.this, "Service connected",
Toast.LENGTH_SHORT).show();
} @Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
service = null;
Toast.makeText(MainActivity.this, "Service disconnected",
Toast.LENGTH_SHORT).show();
} }
(4)相关代码及效果截图
MainActivity.java的全部代码如下:
package com.czm.hellosumaidl; import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
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; public class MainActivity extends Activity { IAdditionService service;
AdditionServiceConnection connection;
EditText value1;
EditText value2;
TextView result;
Button buttonCalc;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initService(); buttonCalc = (Button) findViewById(R.id.buttonCalc); value1 = (EditText) findViewById(R.id.value1);
value1.setText("23");
value2 = (EditText) findViewById(R.id.value2);
value2.setText("24");
result = (TextView) findViewById(R.id.result);
buttonCalc.setOnClickListener(new OnClickListener() { @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 function connects the Activity to the service
*/
private void initService() {
connection = new AdditionServiceConnection(); Intent i = new Intent();
i.setClassName("com.czm.hellosumaidl",com.czm.hellosumaidl.AdditionService.class.getName());
boolean ret = this.bindService(i, connection, Context.BIND_AUTO_CREATE);
} /*
* This function disconnects the Activity from the service
*/
private void releaseService() {
unbindService(connection);
connection = null;
} class AdditionServiceConnection implements ServiceConnection { @Override
public void onServiceConnected(ComponentName name, IBinder boundService) {
// TODO Auto-generated method stub
service = IAdditionService.Stub.asInterface((IBinder) boundService);
Toast.makeText(MainActivity.this, "Service connected",
Toast.LENGTH_SHORT).show();
} @Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
service = null;
Toast.makeText(MainActivity.this, "Service disconnected",
Toast.LENGTH_SHORT).show();
} } }
效果截图如下:
执行AIDL接口之前 执行AIDL接口之后
Android开发之IPC进程间通信-AIDL介绍及实例解析的更多相关文章
- Android开发之UI更新交互机制与实例解析
android开发过程中,经常需要更新UI的状态和文案等.这是就需要对UI进行 更新.在android中更新UI一般有三种方法,handler机制.RunOnUiThread方法以及AsyncTask ...
- Android开发之InstanceState详解
Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...
- 【Android UI】Android开发之View的几种布局方式及实践
引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...
- Android开发之旅: Intents和Intent Filters(理论部分)
引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...
- Android开发之Java必备基础
Android开发之Java必备基础 Java类型系统 Java语言基础数据类型有两种:对象和基本类型(Primitives).Java通过强制使用静态类型来确保类型安全,要求每个变量在使用之前必须先 ...
- [置顶] Android开发之MediaPlayerService服务详解(一)
前面一节我们分析了Binder通信相关的两个重要类:ProcessState 和 IPCThreadState.ProcessState负责打开Binder 驱动,每个进程只有一个.而 IPCThre ...
- Android 开发之旅:深入分析布局文件&又是“Hello World!”
http://www.cnblogs.com/skynet/archive/2010/05/20/1740277.html 引言 上篇可以说是一个分水岭,它标志着我们从Android应用程序理论进入实 ...
- [置顶] Android开发之serviceManager分析
Android 开发之serviceManager分析 在Android系统中用到最多的通信机制就是Binder,Binder主要由Client.Server.ServiceManager和Binde ...
- Android开发之TextView高级应用
Android开发之TextView高级应用 我们平时使用TextView往往让它作为一个显示文字的容器,但TextView的功能并不局限于此.以下就和大家分享一下TextView的一些使用技巧. A ...
随机推荐
- Codeigniter夸应用调用model
Thinkphp里面的model都是可以跨应用调用,ci本身没有实现这个方法.可是稍微修改下,比Thinkphp用起来更容易调用.找到Loader.php文件的地址/system/core/Loade ...
- apache开源项目--Cassandra
Apache Cassandra是一套开源分布式Key-Value存储系统.它最初由Facebook开发,用于储存特别大的数据.Facebook目前在使用此系统. 主要特性: 分布式 基于column ...
- c语言诊断_断言库函数#include<assert.h>
诊断<assert.h> assert #include <assert.h> void assert(int exp); assert宏用于为程序增加诊断功能.当asser ...
- WCF中修改接口或步骤名称而不影响客户端程序
WCF中修改接口或方法名称而不影响客户端程序 本篇接着"从Web Service和Remoting Service引出WCF服务"中有关WCF的部分. 运行宿主应用程序. 运行We ...
- C# 操作 Word 修改word的高级属性中的自定义属性2
word的类库使用的是word2007版本的类库,类库信息见下面图片,折腾了半天,终于找到入口,网上 很多说的添加或者修改word的高级属性中的自定义属性都是错误的,感觉都是在copy网上的代码,自己 ...
- poj2686 Traveling by Stagecoach
http://poj.org/problem?id=2686 Trav ...
- oracle sys sysman system 介绍
Oracle数据库中SYS.SYSTEM.DBSNMP.SYSMAN四用户的区别 SYS用户: SYS,默认密码为CHANGE_ON_INSTALL,当创建一个数据库时,SYS用户将被默认创建并授予D ...
- NOIP2015 子串 (DP+优化)
子串 (substring.cpp/c/pas) [问题描述] 有两个仅包含小写英文字母的字符串 A 和 B.现在要从字符串 A 中取出 k 个 互不重 叠 的非空子串,然后把这 k 个子串按照其在字 ...
- git引用^和~的区别
这篇git文章必转:解答我一直的疑惑 http://www.cnblogs.com/hutaoer/archive/2013/05/14/3078191.html 一. 引子 在git操作中,我们可以 ...
- 《Genesis-3D开源游戏引擎--横版格斗游戏制作教程07:UI》
概述: UI即User Interface(用户界面)的简称.UI设计是指对软件的燃机交互.操作逻辑.界面美观的整体设计.好的UI设计不仅可以让游戏变得更有品位,更吸引玩家,还能充分体现开发者对游戏整 ...