Android Binder通信(3) - c client端和 c service端  java client端和c service端

 

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

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值