binder-JAVA层代码编写

本篇主要分析如何编写JAVA层的binder代码

代码的编写包括几部分

  • client
  • server
  • 注册服务
  • 获取服务
  • 使用服务

首先,关于cpp中那么多的什么Bnxxx,Bpxxx这些在JAVA层不需要再写了,AIDL已经帮我们封装好了数据,我们只需新建.aidl文件,就会生成相关类

创建 aidl 文件,IHelloService.aidl

1
2
3
4
5
6
/** {@hide} */
interface IHelloService
{
void sayhello();
int sayhello_to(String name);
}

我们编写一个 hello,两个方法

编译后生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
public interface IHelloService extends android.os.IInterface
{
//这个类中没有实现接口中的方法,并且他是一个抽象类,因此我们编写server的时候,需要自己来编写它们的实现
public static abstract class Stub extends android.os.Binder implements IHelloService
{
private static final java.lang.String DESCRIPTOR = "IHelloService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
// 根据 IBinder 构建一个 IHelloService 在android的源码中,这种使用方法非常常见
public static IHelloService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof IHelloService))) {
return ((IHelloService)iin);
}
return new IHelloService.Stub.Proxy(obj);
}

@Override public android.os.IBinder asBinder()
{
return this;
}
// onTransact 相信读者很熟悉了,就是根据code来调用不同的函数,它属于服务端
@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_sayhello:
{
data.enforceInterface(DESCRIPTOR);
this.sayhello();
reply.writeNoException();
return true;
}
case TRANSACTION_sayhello_to:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
int _result = this.sayhello_to(_arg0);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

//客户端的代理 是一个RPC过程,远程调用服务端的方法
private static class Proxy implements IHelloService
{
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 sayhello() 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_sayhello, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public int sayhello_to(java.lang.String name) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(name);
mRemote.transact(Stub.TRANSACTION_sayhello_to, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}

static final int TRANSACTION_sayhello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_sayhello_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

}

//这两个方法 需要我们的server自己去实现
public void sayhello() throws android.os.RemoteException;
public int sayhello_to(java.lang.String name) throws android.os.RemoteException;
}

既然需要自己实现,那么我们就先实现两个函数

HelloService.java 实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import android.util.Slog;
/* 实现Hello服务的函数 */
public class HelloService extends IHelloService.Stub {
private static final String TAG = "HelloService";
private int cnt1 = 0;
private int cnt2 = 0;

public void sayhello() throws android.os.RemoteException {
cnt1++;
Slog.i(TAG, "sayhello : cnt = "+cnt1);
}

public int sayhello_to(java.lang.String name) throws android.os.RemoteException {
cnt2++;
Slog.i(TAG, "sayhello_to "+name+" : cnt = "+cnt2);
return cnt2;
}
}

接下来,我们就要走流程了

  • client
  • server
  • 注册服务
  • 获取服务
  • 使用服务

首先,注册服务,也就是server端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import android.util.Slog;
import android.os.ServiceManager;

public class TestServer {
private static final String TAG = "TestServer";

public static void main(String args[])
{
ServiceManager.addService("hello", new HelloService());

while (true)
{

}
}
}

很简单,ServiceManager 是android提供的类,直接调用即可,我们服务中,应该会有循环然后处理数据解析数据等等操作的,它把这部分代码写哪了? 下篇文章分析

然后是编写client端,它需要获取服务,然后使用服务来调用函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import android.os.ServiceManager;
import android.os.IBinder;

public class TestClient {
private static final String TAG = "TestClient";

public static void main(String args[])
{
// 为什么这么写 你去源码里搜下servicemanager就知道了 源码里都这么写
IBinder binder = ServiceManager.getService("hello");
IHelloService svr = IHelloService.Stub.asInterface(binder);

if (args.length == 1){
svr.sayhello();
}else{
int cnt = svr.sayhello_to(args[1]);
}
}
}

可以发现代码很简单,功能都是被封装在了 ServiceManager中

到此为止,我们的代码就编写完成了,下一篇分析JAVA层的机制