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. html css布局

    这几天有点急于求成了,原来每一门技术都像大海,只有深入其中才发现它比看到的更要深广的多. 虽然忙里偷闲的看了HTML5,NODE.JS,JAVASCRIPT核心等许多东西,但是真正掌握的不足十分之一, ...

  2. 获得当前时间的PRO

    1.没有参数的存储过程 create or replace procedure get_timeas    cur_time varchar2(10);begin  select to_char(sy ...

  3. Struts 2简单配置分析

    要配置Struts 2,首先先要有Struts 2的Jar包,可以去Struts的官网下载(http://struts.apache.org/),这里有3个GA版本可以选择下载,我选择的是最新的2.2 ...

  4. 执行umount 命令的时候出现 device is busy

    执行umount 命令的时候出现 device is busy ,有人在使用这块磁盘 umount /dev/sde1 umount: /u01/app/oracle: device is busy ...

  5. iOS 进阶 第六天(0402)

    0402 通知和代理的区别 代理是一对一的,只能是调用实现了协议里的方法,对象作为实现了该方法才能执行方法 通知是多对多,它是通过通知中心分发 通知要及时移除,如果不及时移除可能会收到多次通知,就好像 ...

  6. RUP(Rational Unified Process)

    RUP Rational Unified Process 目前阶段在学习UML,怎么会写RUP呢?学习UML是为了更好的把系统搭建好,RUP也是一样,为系统服务! 软件危机 美国国家总审计局,在198 ...

  7. std::function赋值的几种方法

    定义: #include <functional> std::function<void(const QString&)> myPrintFunction; 函数指针 ...

  8. win7 telnet命令无法使用

    很多做网络测试的同学发现安装win7后,无法使用telnet命令了,提示“telnet不是内部或外部命令,也不是可运行的程序”,但是很需要在win7中使用telnet工具,怎么办? 首先你要要确认你的 ...

  9. WPF 多线程处理(5)

    WPF 多线程处理(1) WPF 多线程处理(2) WPF 多线程处理(3) WPF 多线程处理(4) WPF 多线程处理(5) WPF 多线程处理(6) 项目的目录: 以下是FileStroage的 ...

  10. html+css学习笔记 [基础1]

    ---------------------------------------------------------------------------------------------------- ...