1.Java端 binder client端
ServiceManager.getService获取binder,然后调用binder.transact来通信
@MainActivity
public static final String SERVICE_NAME = "binder.cservice";
//建议使用FIRST_CALL_TRANSACTION来表示感觉比较规范,只要和binder对端一致就可以
public static final int NOTIFY_MESSAGE = IBinder.FIRST_CALL_TRANSACTION;
public static final int DELETE_FILE = IBinder.FIRST_CALL_TRANSACTION + 1;
public static final int ADD_FILE = IBinder.FIRST_CALL_TRANSACTION + 2;
public static final int RELEASE_FILE = IBinder.FIRST_CALL_TRANSACTION + 3;
private void initView() {
Button btn = findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG,"initView onClick: ");
notityCService();
}
});
}
private void notityCService() {
IBinder binder = null ;
binder = ServiceManager.getService(SERVICE_NAME);
if(binder == null) {
Log.e(TAG,"notityCService binder is null: ");
return;
}
Parcel data = Parcel.obtain();
data.writeString("Hello world");
Parcel reply = Parcel.obtain();
int replyResult = -1;
try {
binder.transact(DELETE_FILE, data, reply,0);
replyResult = reply.readInt();
Log.d(TAG, "result1: " + replyResult);
replyResult = reply.readInt();
Log.d(TAG, "result2: " + replyResult);
} catch (RemoteException e) {
Log.e(TAG,"RemoteException: " + e);
}
data.recycle();
reply.recycle();
}
2.C binder service端
binder server端通过onTransact,来获取binder端来的data,并且把回复写到reply里
@MyPrint.cpp
#include "MyPrint.h"
#include <log/log.h>
#include <binder/Parcel.h>
#include <utils/Log.h>
#define SERVICE_NAME "binder.cservice"
#define LOG_TAG "MyPrint"
namespace android {
MyPrint::MyPrint() {
}
MyPrint::~MyPrint() {
}
int MyPrint::instantiate(){
int ret = defaultServiceManager()->addService(String16(SERVICE_NAME), new MyPrint());
return ret;
}
status_t MyPrint::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
switch (code) {
case NOTIFY_MESSAGE: {
char const* message = data.readCString();
ALOGI("onTransact NOTIFY_MESSAGE message = %s", message);
reply->writeInt32(5);
ALOGI("onTransact NOTIFY_MESSAGE reply 5");
break;
}
case DELETE_FILE: {
String16 message = data.readString16();
ALOGI("onTransact DELETE_FILE message = %s", String8(message).string().c_str()));
reply->writeInt32(6);
reply->writeInt32(7);
ALOGI("onTransact DELETE_FILE reply 6 7");
break;
}
default:
ALOGI("Unsupported command code: (%d)", code);
return BBinder::onTransact(code, data, reply, flags);
}
return 0;
}
}//namespace
#MyPrint.h
#ifndef _MYPRINT_HEADER_
#define _MYPRINT_HEADER_
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IServiceManager.h>
#include <utils/threads.h>
#include <stdio.h>
namespace android{
class MyPrint: public BBinder{ //BBinder
public:
enum {
NOTIFY_MESSAGE = IBinder::FIRST_CALL_TRANSACTION, //注意这里是, 和 ::
DELETE_FILE = IBinder::FIRST_CALL_TRANSACTION + 1,
ADD_FILE = IBinder::FIRST_CALL_TRANSACTION + 2,
RELEASE_FILE = IBinder::FIRST_CALL_TRANSACTION + 3,
};
static int instantiate();
MyPrint();
virtual ~MyPrint();
virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);
};
}//namespace
#endif
rc唤醒 /system/bin/binderCService时,执行main.cpp,然后addservice并且执行MyPrint::MyPrint()来初始化
@main.cpp
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <cutils/log.h>
#include "MyPrint.h"
#include <utils/Log.h>
using namespace android;
int main(int argc, char *argv[]) {
ALOGI("MyPrint cservice is starting up...");
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
MyPrint::instantiate(); //add service 并且初始化MyPrint
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
ALOGI("MyPrint cservice exits thread loop");
return 0;
}
@Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH) \
$(TARGET_OUT_HEADERS)/common/inc
LOCAL_SHARED_LIBRARIES := \
libc \
libcutils \
libutils \
liblog \
libdl \
libbinder
LOCAL_MODULE := binderCService
LOCAL_SRC_FILES := main.cpp MyPrint.cpp
LOCAL_MODULE_TAGS := optional
#LOCAL_CFLAGS := $(QSEECOM_CFLAGS)
LOCAL_INIT_RC := binderCService.rc
include $(BUILD_EXECUTABLE)
include $(call all-makefiles-under,$(LOCAL_PATH))
//默认是会有selinux问题,不会启动成功,需要手动 binderCService &来启动
@binderCService.rc
service binderCService /system/bin/binderCService
class late_start
user root
group root
//手动启动后,执行如下命令,可以看到服务起来,并且打印main.cpp中的log
msm8996_gvmq:/ # service list| grep bind
0 binder.cservice: []
3.c client端 binder到service端
c client端通过ibinder->transact,写2019到binder server端
@binder_test.cpp
#include <binder/IServiceManager.h>
#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <cutils/log.h>
#include <utils/Log.h>
using namespace android;
#define SERVICE_NAME "binder.cservice"
int main() {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> ibinder = sm->getService(String16(SERVICE_NAME));
if (ibinder == NULL) {
ALOGI("binder_test binder is null" );
return -1;
}
Parcel data, reply;
int cmd = IBinder::FIRST_CALL_TRANSACTION;
int ret;
ALOGI("binder_test transact FIRST_CALL_TRANSACTION" );
data.writeInt32(2019);
ret = ibinder->transact(cmd, data, &reply, 0);
ALOGI("binder_test transact : %d" ,reply.readInt32());
data.freeData();
return 0;
}
//c的客户端也是system/bin/binder_test,通过binder_test来启动
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
libc \
libcutils \
libutils \
liblog \
libdl \
libbinder
LOCAL_MODULE := binder_test
LOCAL_SRC_FILES := binder_test.cpp
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
binder server端,修改了下,必须读client的data才能走下去,这里用data.readInt32()
case NOTIFY_MESSAGE: {
ALOGI("onTransact NOTIFY_MESSAGE message");
int message = data.readInt32();
reply->writeInt32(5);
ALOGI("onTransact NOTIFY_MESSAGE reply 5");
break;
}
调试时限制性 binderCService & 启动service,然后binder_test在启动client端就可以了
结果如下:
I : MyPrint cservice is starting up...
I : binder_test transact FIRST_CALL_TRANSACTION
I MyPrint : onTransact NOTIFY_MESSAGE message
I MyPrint : onTransact NOTIFY_MESSAGE reply 5
I : binder_test transact : 5
4.parcel介绍和使用
//String16 String8 Const char*关系
String16 name16 = String16("HellOThEWrolD"); //定义初始化String16
String8 name8 = String8(name16); //String16转为String8
const char *C_name8 = name8.string(); //String8转为const char *
const char*到char*的转换:
char *buf = new char[strlen(C_name8)+1];
strcpy(buf, C_name8);
java端Parcel类使用如下
Parcel data = Parcel.obtain(); //获取Parcel
data.writeString("Hello world"); //writeString写入数据
Parcel reply = Parcel.obtain();
binder.transact(DELETE_FILE, data, reply,0); //binder transact
data.recycle(); //释放parcel
reply.recycle();
C Server端
status_t MyPrint::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
switch (code) {
case DELETE_FILE: {
String16 message = data.readString16(); //readString16
ALOGI("onTransact DELETE_FILE message = %s", String8(message).string()); //先转为Sring8,在使用.string()转为Const char*才可以打印
reply->writeInt32(6); //写Int
reply->writeInt32(7);
ALOGI("onTransact DELETE_FILE reply 6 7");
break;
}
...
}
C Client端
Parcel data, reply; //初始化
int cmd = IBinder::FIRST_CALL_TRANSACTION;
String8 src1("HelloDayi ");
data.writeString8(src1); //write
ret = ibinder->transact(cmd, data, &reply, 0);
data.freeData(); //释放
5.service端 selinux
测试使用adb shell setenforce 0关闭selinux检测,然后binderCService &来启动service