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. CentOS 6.4 安装搭建 Scrapy 0.22 环境

    一.安装Python2.7.6 更新CentOS lib库文件 yum -y update 安装开发工具包 yum groupinstall -y development 安装扩展包 yum inst ...

  2. jvm 数据区划分学习

    Java virtual machine 运行时数据存储区域划分 2015年1月25日 19:15 Pc  寄存器 Each Java Virtual Machine thread has its o ...

  3. 将Unity3D游戏移植到Android平台上

    将Unity3D游戏移植到Android平台是一件很容易的事情,只需要在File->Build Settings中选择Android平台,然后点击Switch Platform并Build出ap ...

  4. PAT IO-04 混合类型数据格式化输入(5)

    /* *PAT IO-04 混合类型数据格式化输入(5) *2015-08-01 作者:flx413 */ #include<stdio.h> int main() { int a; fl ...

  5. PHP正则表达式的逆向引用与子模式 php preg_replace应用

    mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit]) 功能 在 subject 中搜索 ...

  6. cocos2dx中加载图片资源的方法,和从内存中获取已经加载的图片资源的方法

    游戏中通常需要将常用的资源如:声音,图片,plist文件,提前加载进内存,以加快游戏的流畅度 1.预加载声音: SimpleAudioEngine::getInstance()->preload ...

  7. LintCode-Word Segmentation

    Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separa ...

  8. NAND的一些相关概念

    chipsize:整个NAND FLASH 的大小,单位为MB pagesize:一页的大小,单位为字节Byte erasesize:最小擦除大小,单位为字节Byte   NAND写操作基本单位是页, ...

  9. Eclipse启动的时候窗口一闪就关的解决办法(转)

    有时候会碰到如题这种问题,从网上查知解决办法,非常管用 为eclipse.exe创建一个快捷方式,然后快捷方式上右键-属性,在目标栏填入 E:\eclipse\eclipse.exe -vm &quo ...

  10. Error:No marked region found along edge. - Found along top edge.

    android开发的时候,初次使用.9图片出现以下: Error:No marked region found along edge. - Found along top edge. 原因: 如图:上 ...