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 thathappens across processes in the core platform.

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

Android AIDL-跨进程

最底层的是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的生命周期如下:

Android AIDL-跨进程

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

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

2. 以bindService(Intentservice,ServiceConnectionconn, 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对象中定义的方法即可.

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

Android AIDL-跨进程

在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 9(P)应用进程创建流程大揭秘
  2. Google 菜市场(Android Market)上不去的解决方法
  3. Android高手进阶教程(二十一)之---Android中创建与几种解析xml的
  4. Android中的多进程开发以及多进程的使用场景
  5. Android中实现跨进程通信(IPC)的方式(三)之观察者模式
  6. Android 蓝牙通信开发(一) 搜索蓝牙设备

随机推荐

  1. Android快速开发系列 10个常用工具类
  2. android 编译SDK
  3. android开机启动流程简单分析
  4. 【Android】- MediaPlayer错误之MediaPla
  5. Android之Fragment
  6. Java入侵检测(三)
  7. Android输入框实时模糊搜索效果的示例代
  8. android提供的TextUtils类
  9. Android实现图片左右滑动效果
  10. Android软件中嵌入地图之三:Google地图