摘要:本节主要来讲解Android10.0 Binder在Framework中的示例
阅读本文大约需要花费15分钟。
文章首发微信公众号:IngresGe
专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析
[Android取经之路] 系列文章:
《系统启动篇》
《日志系统篇》
《Binder通信原理》:
Server进程目录结构:
Server
├─src
│ └─com
│ └─android
│ └─server
│ ├─Server.java
│ ├─MyService.java
│ └─IMyService.java
├─Android.mk
└─serverTest
Client进程目录结构:
Client
├─src
│ └─com
│ └─android
│ └─client
│ ├─Client.java
│ ├─MyServiceProxy.java
│ └─IMyService.java
├─Android.mk
└─clientTest
文件说明:
文件 |
说明 |
Server.java |
Server入口 |
MyService.java |
服务实体 |
IMyService.java |
服务接口 |
Android.mk | 编译文件 |
serverTest |
可执行程序,保存在/system/bin中, 用来运行JAVA进程 |
[Server.java] 服务入口
package com.android.server;
import android.os.Looper;
import android.os.ServiceManager;
public class Server {
public static void main(String args[]){
System.out.println("Server service Start");
Looper.prepareMainLooper(); //开启循环执行
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
/*注册服务*/
ServiceManager.addService("MyTestService", new MyService());
Looper.loop();
}
}
[MyService.java] 服务实体
package com.android.server;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.IInterface;
import android.os.RemoteException;
public class MyService extends Binder implements IMyService{
private String value;
public MyService() {
attachInterface(this, IMyService.descriptor);
}
@Override
public IBinder asBinder() {
return this;
}
public static IMyService asInterface(IBinder obj) {
if ((obj == null)) {
return null;
}
IMyService in = (IMyService)obj.queryLocalInterface(IMyService.descriptor);
if (in != null) {
return in;
}
return null;
}
/*接收远程消息,进行处理*/
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case SET_VALUE_TRANSACTION: {
data.enforceInterface(IMyService.descriptor);
String str = data.readString(); //收到Client的数据
setValue(str);
reply.writeNoException();
return true;
}
case GET_VALUE_TRANSACTION: {
data.enforceInterface(IMyService.descriptor);
String str = getValue();
reply.writeNoException();
reply.writeString(str); //把返回的数据写入Parcel,Client会进行接收
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
/*服务的实现方法*/
@Override
public void setValue(String str) throws RemoteException {
System.out.println("Client calling : setValue is " + str);
this.value = str;
}
@Override
public String getValue() throws RemoteException {
System.out.println("Client calling : getValue is " + value);
return value;
}
}
[IMyService.java] 接口
package com.android.server;
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
public interface IMyService extends IInterface {
static final String descriptor = "com.android.server";
public void setValue(String str) throws RemoteException;
public String getValue() throws RemoteException;
static final int SET_VALUE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
static final int GET_VALUE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;
}
[Android.mk] 编译文件
LOCAL_PATH:= $(call my-dir)
#1.编译成serverTest.jar,编译到/system/framework中
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := serverTest
include $(BUILD_JAVA_LIBRARY)
#2.编译成serverTest进程,最终放入到/system/bin中,源文件是当前目录下的serverTest
include $(CLEAR_VARS)
LOCAL_MODULE := serverTest
LOCAL_SRC_FILES := serverTest
LOCAL_MODULE_PATH := $(TARGET_OUT)/bin
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_TAGS := optional
include $(BUILD_PREBUILT)
[serverTest] 可执行文件,最终会拷贝到/system/bin中
#!/system/bin/sh
# Script to start "serverTest" on the device
#
base=/system
export CLASSPATH=$base/framework/serverTest.jar
exec app_process $base/bin com.android.server.Server "$@"
文件说明:
文件 |
说明 |
Client.java |
Client入口 |
MyServiceProxy.java |
服务代理 |
IMyService.java |
服务接口 |
Android.mk |
编译命令 |
clientTest |
可执行程序,保存在/system/bin中, 用来运行JAVA进程 |
[Client.java] Client 入口
package com.android.client;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
public class Client {
public static void main(String[] args) throws RemoteException {
System.out.println("Client start");
//获取服务
IBinder binder = ServiceManager.getService("MyTestService");
//创建MyServiceProxy对象
IMyService myService = new MyServiceProxy(binder);
//通过MyServiceProxy对象调用接口的方法
myService.setValue("Hello binder!");
String str = myService.getValue();
System.out.println("The value from server binder is " + str);
System.out.println("Client end");
}
}
[MyServiceProxy.java] 服务代理
package com.android.client;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
public class MyServiceProxy implements IMyService {
private IBinder mRemote;
public MyServiceProxy(IBinder remote) {
mRemote = remote;
}
public String getInterfaceDescriptor() {
return IMyService.descriptor;
}
/*接口方法实现*/
@Override
public void setValue(String str) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IMyService.descriptor);
data.writeString(str); //把str数据写入Parcel,服务端会进行解析
mRemote.transact(SET_VALUE_TRANSACTION, data, reply, 0); //发送的code:SET_VALUE_TRANSACTION
reply.readException();
} finally {
reply.recycle();
data.recycle();
}
}
@Override
public String getValue() throws RemoteException {
String str;
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IMyService.descriptor);
mRemote.transact(GET_VALUE_TRANSACTION, data, reply, 0); //发送的code:GET_VALUE_TRANSACTION
reply.readException();
str = reply.readString(); //读取服务端发来的内容
} finally {
reply.recycle();
data.recycle();
}
return str;
}
@Override
public IBinder asBinder() {
return mRemote;
}
}
[Android.mk] 编译文件
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := clientTest
include $(BUILD_JAVA_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := clientTest
LOCAL_SRC_FILES := clientTest
LOCAL_MODULE_PATH := $(TARGET_OUT)/bin
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_TAGS := optional
include $(BUILD_PREBUILT)
[clientTest] 可执行程序
#!/system/bin/sh
# Script to start "clientTest" on the device
#
base=/system
export CLASSPATH=$base/framework/clientTest.jar
exec app_process $base/bin com.android.client.Client "$@"
7.Client端执行:/system.bin/clientTest
运行结果:
Client:
Server:
我的微信公众号:IngresGe