因为上一节service manager中,对于binder通信的客户端(BpServiceManager)和服务端(service manager进程)已经有比较详细的解释,所以,不再对于Binder通信的client端和server端做分析,有兴趣的同学可以看看MediaPlayerService和MediaPlayer,网上很多资料有讲解。
当目前为止,所有的代码都是以C/C++语言的,但是,App开发者通常使用Java语言,那么Java是如何使用Binder通信的呢?
AIDL
很多时候,我们是通过aidl(Android Interface Define Language)间接的使用Binder机制的。例如,我们准备了下面这样一个aidl文件:
package com.ray.example;
interface RInterface {
void hello(String message);
}
经过IDE的编译,我们会得到下面这样的Java文件:
/*___Generated_by_IDEA___*/
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: /home/ray/Learning&Study/BinderProProject/SearchApp/src/main/java/com/ray/example/RInterface.aidl
*/
package com.ray.example;
public interface RInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.ray.example.RInterface
{
private static final java.lang.String DESCRIPTOR = "com.ray.example.RInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.ray.example.RInterface interface,
* generating a proxy if needed.
*/
public static com.ray.example.RInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.ray.example.RInterface))) {
return ((com.ray.example.RInterface)iin);
}
return new com.ray.example.RInterface.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_hello:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
this.hello(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.ray.example.RInterface
{
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 void hello(java.lang.String message) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(message);
mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_hello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void hello(java.lang.String message) throws android.os.RemoteException;
}
编译产生的java文件提供了三个对象:
RInterface接口:继承自IInterface接口,并且有一个hello的成员函数。作为server和client之间的约定,双方都会使用。
RInterface.Stub抽象类:继承自Binder类,并且提供了onTransact函数的实现,以及静态函数asInterface。
RInterface.Stub.Proxy类:实现了RInterface接口,实现了hello函数。
XXXX.Stub
主要由Server端实现,Server端通过继承本类,来提供具体的处理逻辑。通常,在Server端,我们会有如下代码:
package com.ray.example;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
/**
* Created by ray on 2/7/14.
*/
public class RServer extends RInterface.Stub {
public final String TAG_RAY = "ray";
@Override
public void hello(String message) throws RemoteException {
Log.i(TAG_RAY,"Hello~ " + message);
}
}
这里通过重载来hello函数来提供具体的处理逻辑。而hello函数是如何被调用的呢?这就需要回顾RInterface.Stub类对于onTransact函数的重载:
@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_hello:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
this.hello(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
当onTransact函数被以特定的参数调用时,hello函数会被调用:
static final int TRANSACTION_hello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
Android系统约定,code必须大于等于
int FIRST_CALL_TRANSACTION = 0x00000001;
并且,小于等于