Android AIDL-跨进程
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的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(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对象中定义的方法即可.
下面我给出一个示例,工程结构如下:
在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 9(P)应用进程创建流程大揭秘
- Google 菜市场(Android Market)上不去的解决方法
- Android高手进阶教程(二十一)之---Android中创建与几种解析xml的
- Android中的多进程开发以及多进程的使用场景
- Android中实现跨进程通信(IPC)的方式(三)之观察者模式
- Android 蓝牙通信开发(一) 搜索蓝牙设备