Android在设计理念上强调组件化,组件之间的依赖性很小。我们往往发一个Intent请求就可以启动另一个应用的Activity,或者一个你不知道在哪个进程的Service,或者可以注册一个广播,只要有这个事件发生你都可以收到,又或者你可以查询一个ContentProvider获得你想要的数据,这其实都需要跨进程通信的支持。只是Android将其封装的如此简单,应用开发者甚至完全不用关注它是不是和我在一个进程里。

我们有没有想过安全性问题,如此简单就可以跨进程的访问,安全性问题怎么保证。本来每个进程都是一个孤岛,而通过ipc,这个孤岛却可以和世界通信了。这里简单介绍下android中的安全机制。

android是如何实现ipc的呢?答案是binder。Binder并不是android最早开始使用,它发源于Be和Palm之前的OpenBinder,由Dianne Hackborn领导开发。Hackborn现在就在google,是android framework的工程师,我们可以从https://lkml.org/lkml/2009/6/25/3看一下,Hackborn如何描述binder。一句话总结:

In the Android platform, the binder is used for nearly everything that
happens across processes in the core platform. 

android将binder几乎封装的不可见,我们看下层次结构是怎么样的。

最底层的是android的ashmen(Anonymous shared memoryy)机制,它负责辅助实现内存的分配,以及跨进程所需要的内存共享。

AIDL(android interface definition language)对Binder的使用进行了封装,可以让开发者方便的进行方法的远程调用,后面会详细介绍。

Intent是最高一层的抽象,方便开发者进行常用的跨进程调用。我们在使用Anroid的的四大组件的时候都会用的Intent。

AIDL是android为了方便开发者进行远程方法调用,定义的一种语言。使用aidl完成一个远程方法调用只需要三个步骤:

1.用aidl定义需要被调用方法接口。

2.实现这些方法。

3.调用这些方法。

下面我们以Service为例子来说明如何使用aidl。

Service是Android中的服务组件, 经常用来执行一些运行在后台的耗时操作. 使用一个Service需要继承Service类, 并根据需要重写生命周期方法. Service的生命周期如下:

从图中可以看出, Service可以有两种启动方式:

1. 以startService(Intent intent)的方式启动. 此时启动的Service与调用者之间没有关联, 即使调用者已经退出, Service仍然可以继续运行, 而且调用者和Service之间无法进行数据交换和通信. 如果需要停止Service的运行, 只能调用Context类的stopService(intent)方法, 或者由Service本身调用其stopSelf()等方法.

2. 以bindService(Intent service, ServiceConnection conn, int flags)的方式启动.

此时调用者与Service绑定在一起, 如果调用者退出, 则Service也随之退出, 而且调用者和Service之间可以进行数据交换或通信.

根据调用者和Service是否在一个应用程序内, 可以将调用者和Service之间的通信分为进程内通信和进程间通信.

a. 进程内通信. bindService(Intent service, ServiceConnection conn, int flags)方法的第二个参数为ServiceConnection对象, 最后一个参数通常可以是Service.BIND_AUTO_CREATE. ServiceConnection是一个接口, 该接口包含2个方法:

|-- onServiceConnected(ComponentName name, IBinder service): 该方法在调用者和Service成功绑定之后由系统回调.

方法中的第一个参数ComponentName是所绑定的Service的组件名称, 而IBinder对象就是Service中onBinder()方法的返回值. 要实现调用者和Service之间的通信, 只需要调用IBinder对象中定义的方法即可.

下面我给出一个示例,工程结构如下:

在eclipse中定义一个aidl结尾的文件,我们一般将这个放在一个单独的包中。

package com.aidl;
interface TestAIDL {
String registerTestCall();
void invokCallBack();
}

eclipse自动会生成一个,一个java文件,这个文件中可以看到Stud实现了上面的接口,并继承了Binder,如下:

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

编写实现类,只需要继承TestAIDL.Stub

package com.aidl;

import android.util.Log;

public class TestBinder extends TestAIDL.Stub {

    public String registerTestCall() {

        Log.i("1", "注册");
return "您好";
} public void invokCallBack() {
Log.i("2", "回调");
} }

编写服务类,在服务类中需要创建TestBinder的对象。

package com.aidl;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder; public class TestService extends Service{ private TestBinder mBiner= new TestBinder();
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return mBiner;
} @Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
} @Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
} @Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
} @Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return super.onUnbind(intent);
} }

客户端实现

在ServiceConnection中获取上面创建的binder对象,然后在客户端使用binder中的方法。

package com.example.aidlclient;

import com.aidl.TestAIDL;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText; public class ActivityClient extends Activity { Button btnBind ;
Button btnExcut ;
Button btnUnbind ;
private TestAIDL mBinder;
EditText editText;
final String Tag="com.aidl.TestAIDL"; ServiceConnection conn= new ServiceConnection()
{ @Override
public void onServiceConnected(ComponentName arg0, IBinder binder) {
// TODO Auto-generated method stub
mBinder=TestAIDL.Stub.asInterface(binder);
} @Override
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub } }; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
btnBind=(Button)findViewById(R.id.button2);
btnExcut=(Button)findViewById(R.id.button3);
btnUnbind=(Button)findViewById(R.id.button1); editText=(EditText)findViewById(R.id.editText1);
btnExcut.setOnClickListener(new OnClickListener() { @Override
public void onClick(View arg0) { Log.d("","执行前");
// TODO Auto-generated method stub
if(mBinder!=null)
{
try {
String s= mBinder.registerTestCall();
editText.setText(s);
Log.d("","执行后");
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}); btnUnbind.setOnClickListener(new OnClickListener() { @Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
unbindService(conn);
}
}); btnBind.setOnClickListener(new OnClickListener() { @Override
public void onClick(View arg0) {
// TODO Auto-generated method stub Intent intentService = new Intent();
intentService.setAction(Tag); bindService(intentService, conn, Context.BIND_AUTO_CREATE);
}
});
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_client, menu);
return true;
} }

Android AIDL-跨进程的更多相关文章

  1. 图文详解 Android Binder跨进程通信机制 原理

    图文详解 Android Binder跨进程通信机制 原理 目录 目录 1. Binder到底是什么? 中文即 粘合剂,意思为粘合了两个不同的进程 网上有很多对Binder的定义,但都说不清楚:Bin ...

  2. Android使用AIDL跨进程通信

    一.基本类型 1.AIDL是什么 AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definiti ...

  3. Android AIDL 进行进程间通讯(IPC)

    编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...

  4. AIDL跨进程通信

    Android跨进程通信会用到AIDL,当然跨进程通信不一定要用AIDL,像广播也是可以的,当然这里用到AIDL相对比较安全一些: AIDL允许传递基本数据类型(Java 的原生类型如int/long ...

  5. AIDL/IPC Android AIDL/IPC 进程通信机制——超具体解说及使用方法案例剖析(播放器)

    首先引申下AIDL.什么是AIDL呢?IPC? ------ Designing a Remote Interface Using AIDL 通常情况下,我们在同一进程内会使用Binder.Broad ...

  6. android 25 跨进程启动activity

    跨进程启动activity,启动系统预定义的activity就是跨进程的. client项目启动server项目的activity. clientActivity.java package com.s ...

  7. Aidl跨进程通信机制-android学习之旅(87)

    Aidl简介 AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信的代码. 如果在 ...

  8. 【整理】使用AIDL跨进程传递复杂对象的实践例子

    首先定义对象类,并实现Parcelable接口,实现接口内的几个方法,看代码,Person.java package com.example.u3.aidltest; import android.o ...

  9. AIDL跨进程通信报Intent must be explicit

    在Android5.0机子上采用隐式启动来调试AIDL时,会出现Intent must be explicit的错误,原因是5.0的机子不允许使用隐式启动方式,解决的方法是:在启动intent时添加i ...

  10. 【朝花夕拾】Android性能篇之(七)Android跨进程通信篇

    前言 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一.Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Andro ...

随机推荐

  1. mac升级yosemite后安装gd的freetype扩展

    Mac升级系统到 Yosemite 10.10,对于各位Coder来说,还是需要一些时间来折腾的! @星空之下 同学反映 PHPCMS 的验证码图片不能正常显示,反馈该验证码需要GD库支持FreeTy ...

  2. UpdateData(false) and UpdateData(true)

    数据更新函数: UpdateData(false); 控件的关联变量的值传给控件并改变控件状态(程序--->EXE) UpdateData(true); 控件的状态传给其关联的变量(EXE--- ...

  3. rJava配置

    1. 下载安装R-3.1.1-win.exe: 2. 在R中安装rJava > install.packages("rJava") 3. 设置环境变量: PATH:D:\So ...

  4. Careercup - Facebook面试题 - 5998719358992384

    2014-05-02 00:22 题目链接 原题: Given a matrix consisting of 's. 题目:给定一个01矩阵,找出由1构成的连通分量中最大的一个. 解法:四邻接还是八邻 ...

  5. adb shell 出现 error :

    首先,确保 adb 服务有起来    adb kill-server adb start-server其次,确保 adb devices 可以找到设备

  6. 2064: 分裂 - BZOJ

    Description 背景: 和久必分,分久必和... 题目描述: 中国历史上上分分和和次数非常多..通读中国历史的WJMZBMR表示毫无压力. 同时经常搞OI的他把这个变成了一个数学模型. 假设中 ...

  7. Ext学习-基础组件介绍

    1.目标    学习对象获取,组件基础,事件模型以及学习ExtJS中的基础组件的应用. 2.内容   1.对象获取   2.组件原理以及基础   3.事件模型   4.常用组件的介绍 3.学习步骤 1 ...

  8. 【BZOJ】【3404】【USACO2009 Open】Cow Digit Game又见数字游戏

    博弈论 Orz ZYF 从前往后递推……反正最大才10^6,完全可以暴力预处理每个数的状态是必胜还是必败(反正才两个后继状态),然后O(1)查询……我是SB /******************** ...

  9. 使用NodeJs,实现数据抓取

    学习笔记 前言 近期做一个数据抓爬工具,最开始使用的是C#控制台应用,同时正则表达式去过滤数据,看着还行,可每次运行都依附于.net framework很是不爽,于是想整点其他的方法.本人还是比较喜欢 ...

  10. NData BUG 记录

    一.collection 如果设计如下页面 页面模型如下 using UnityEngine; using System.Collections; using System.Collections.G ...