Android Binder (可以直接写在项目中的写法)
Posted we1less
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Binder (可以直接写在项目中的写法)相关的知识,希望对你有一定的参考价值。
此篇为大家展示一个写在项目中的写法,native层的service注册和获取服务,加上回调。
首先展示一下项目目录
binder通信是基于aidl接口实现的,使用aidl接口可以省略许多不必要的代码。
工程的基础mk
android.mk
include $(call all-subdir-makefiles)
Android.bp
subdirs = ["cmd","lib","service"]
cmd文件夹代表服务从这个文件夹启动,当然如果特别完整的需要把 .rc文件和SELINUX权限放开
Android.bp
cc_binary {
srcs: ["main_godaservice.cpp"],
shared_libs: [
"libgodaservice", //需要启动的动态库
"liblog",
"libutils",
"libbinder",
],
name: "godaservice",
compile_multilib: "32",
vendor: true, //代表生成在vendor/bin/下
//vendor_available: true,
//LOCAL_INIT_RC := cameraserver.rc
}
main_godaservice.cpp 主要的启动类
//参考 frameworks/av/media/mediaserver/main_mediaserver.cpp
#define LOG_TAG "GodaService"
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include "GodaService.h"
#include <utils/Log.h>
using namespace android;
int main(void)
{
// 实际这个函数的目的就是防止程序收到SIGPIPE后自动退出
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self());
//获得BpServiceManager
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
android::hardware::GodaService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
service文件夹存放着binder服务端 同时这里也存在者aidl文件
Android.bp
cc_library_shared {
name: "libgodaservice",
srcs: [
"aidl/android/hardware/IGodaService.aidl",
"aidl/android/hardware/IGodaServiceListener.aidl",
"GodaService.cpp",
],
aidl: {
export_aidl_headers: true, //这个代表可以被外部引用
local_include_dirs: ["aidl"],
},
export_include_dirs: ["./"], //在当前文件夹下导入头文件
shared_libs: [
"libcutils",
"libutils",
"liblog",
"libbase",
"libbinder",
],
vendor: true,
//vendor_available: true,
}
IGodaService.aidl 基础接口类
对于aidl接口来讲编译后的接口文件路径
out/target/product/generic_x86_64/obj/SHARED_LIBRARIES/libgodaservice_intermediates
本来应该是这个路径但是其中包含了export_includes
所以最终的路径指向
out/soong/.intermediates/frameworks/av/goda/service/libgodaservice/android_x86_64_shared_core/gen/aidl/android/hardware/
out/soong/.intermediates/frameworks/av/goda/service/libgodaservice/android_x86_64_shared_core/gen/aidl/frameworks/av/goda/service/aidl/android/hardware/
这里面包含编译后的bnbp和 Ixxx 接口文件
如果想了解其中的代码可参考
Android Binder(C++版本例子)_we1less的博客-CSDN博客
package android.hardware;
import android.hardware.IGodaServiceListener;
interface IGodaService
{
const int ERROR_PERMISSION_DENIED = 9001;
const int ERROR_DISCONNECTED = 9002;
const int ERROR_TIMED_OUT = 9003;
int getNumberOfGoda(int type);
void registerListener(IGodaServiceListener listener);
void removeListener(IGodaServiceListener listener);
//oneway 客户端调用后立即返回
//in 是对于服务端来讲的 站在服务端的角度上
//in 代表数据流向服务端 并代表服务端无法修改传递进来的参数
//out
oneway void notifyMessage(int type, in String msg);
}
IGodaServiceListener.aidl 回调类
package android.hardware;
interface IGodaServiceListener
{
const int STATUS_NOT_PRESENT = 0;
const int STATUS_PRESENT = 1;
const int STATUS_UNKNOWN = -1;
oneway void onStatusChanged(int status, String msg);
}
GodaService.h
#ifndef ANDROID_GODASERVICE_H
#define ANDROID_GODASERVICE_H
#include <android/hardware/BnGodaService.h>
#include <android/hardware/IGodaService.h>
#include <android/hardware/IGodaServiceListener.h>
#include <binder/BinderService.h>
#include <utils/String16.h>
#include <android/log.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
namespace android {
namespace hardware {
class GodaService :
public ::android::BinderService<GodaService>,
public BnGodaService
{
friend class BinderService<GodaService>;
public:
GodaService();
~GodaService();
static const char* getServiceName() { return "goda"; }
//_aidl_return 这里我理解就是aidl中的返回
::android::binder::Status getNumberOfGoda(int32_t type, int32_t* _aidl_return) override;
::android::binder::Status registerListener(const sp<IGodaServiceListener>& listener) override;
::android::binder::Status removeListener(const sp<IGodaServiceListener>& listener) override;
::android::binder::Status notifyMessage(int32_t type, const String16& msg) override;
// RefBase
virtual void onFirstRef();
public:
sp<IGodaServiceListener> igsl;
};
}
}
#endif //ANDROID_GODASERVICE_H
GodaService.cpp
#define LOG_TAG "GodaService"
#include "GodaService.h"
using namespace android;
#define STATUS_ERROR(errorCode, errorString) \\
binder::Status::fromServiceSpecificError(errorCode, \\
String8::format("%s:%d: %s", __FUNCTION__, __LINE__, errorString))
#define STATUS_ERROR_FMT(errorCode, errorString, ...) \\
binder::Status::fromServiceSpecificError(errorCode, \\
String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, \\
__VA_ARGS__))
//errorCode
/*
const int ERROR_PERMISSION_DENIED = 9001;
const int ERROR_DISCONNECTED = 9002;
const int ERROR_TIMED_OUT = 9003;
*/
namespace android {
namespace hardware {
void GodaService::onFirstRef()
{
LOGD("onFirstRef");
}
GodaService::GodaService()
{
LOGD("GodaService");
}
GodaService::~GodaService()
{
LOGD("~GodaService");
}
binder::Status GodaService::getNumberOfGoda(int32_t type, int32_t* _aidl_return)
{
//
LOGD("service::getNumberOfGoda type == %d", type);
if(type == ERROR_PERMISSION_DENIED) {
* _aidl_return = ERROR_PERMISSION_DENIED;
} else if(type == ERROR_DISCONNECTED) {
* _aidl_return = ERROR_DISCONNECTED;
} else {
return STATUS_ERROR(ERROR_TIMED_OUT, "godv666");
}
return binder::Status::ok();
}
binder::Status GodaService::registerListener(const sp<IGodaServiceListener>& listener)
{
LOGD("service::registerListener");
if(listener == NULL){
LOGD("registerListener == null");
return STATUS_ERROR(ERROR_DISCONNECTED, "registerListener == null");
}
igsl = listener;
return binder::Status::ok();
}
binder::Status GodaService::removeListener(const sp<IGodaServiceListener>& listener)
{
if(igsl == NULL){
LOGD("igsl already is null");
return STATUS_ERROR(ERROR_TIMED_OUT, "igsl already is null");
}
if(listener == NULL){
LOGD("removeListener == null");
return STATUS_ERROR(ERROR_PERMISSION_DENIED, "removeListener == null");
}
igsl = NULL;
return binder::Status::ok();
}
binder::Status GodaService::notifyMessage(int32_t type, const String16& msg)
{
String8 msg8 = String8(msg);
const char *c_msg = msg8.string();
LOGD("service::notifyMessage msg = %s", c_msg);
if(igsl == NULL){
LOGD("igsl == null");
return STATUS_ERROR(ERROR_PERMISSION_DENIED, "igsl == null");
}
if(type == IGodaServiceListener::STATUS_NOT_PRESENT){
LOGD("service::STATUS_NOT_PRESENT");
igsl->onStatusChanged(666, msg);
LOGD("service::onStatusChanged end");
} else {
LOGD("service::else");
igsl->onStatusChanged(777777, msg);
}
return binder::Status::ok();
}
}
}
lib目录准备是用来让java层调用和示范在native层如何使用binder通信
Android.bp
cc_binary {
name: "libgodaclient",
srcs: [
"GodaClients.cpp",
],
shared_libs: [
"libcutils",
"libutils",
"liblog",
"libbinder",
"libgodaservice",
],
include_dirs: [
"./", //用户值定的头文件查找路径
],
vendor: true,
export_shared_lib_headers: ["libgodaservice"],
//vendor_available: true,
}
GodaClients.cpp native层客户端的示例代码
#define LOG_TAG "GodaService"
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <android/hardware/IGodaService.h>
#include <android/hardware/BnGodaServiceListener.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
using namespace android;
namespace android {
namespace hardware {
class GodaServiceListener :public BnGodaServiceListener {
public :
bool hasMsg;
virtual ::android::binder::Status onStatusChanged(int32_t status,
const ::android::String16& msg) {
String8 msg8 = String8(msg);
const char *c_msg = msg8.string();
ALOGI("GodaServiceListener onStatusChanged status == %d , msg = %s\\n",status,c_msg);
hasMsg = true;
return binder::Status::ok();
}
};
}
}
int main(int argc,char **argv)
{
ALOGI("Usage:\\n");
if(argc < 2){
ALOGI("Usage:\\n");
ALOGI("%s hello\\n",argv[0]);
}
//getService
//打开驱动 mmap
sp<ProcessState> proc(ProcessState::self());
//获得BpServiceManager
sp<IServiceManager> sm(defaultServiceManager());
sp<IBinder> binder =
sm->getService(String16("goda"));
if(binder == 0)
{
ALOGI("can not get goda service\\n");
return -1;
}
sp<android::hardware::IGodaService> service =
interface_cast<android::hardware::IGodaService>(binder);
sp<android::hardware::GodaServiceListener> gsl(new android::hardware::GodaServiceListener());
if(argc == 2){
int res;
ALOGI("client call getNumberOfGoda\\n");
service->getNumberOfGoda(android::hardware::IGodaService::ERROR_PERMISSION_DENIED, &res);
ALOGI("client call getNumberOfGoda == %d\\n", res);
} else if(argc == 3){
//void registerListener(IGodaServiceListener listener);
//oneway void notifyMessage(int type, in String msg);
ALOGI("client call registerListener\\n");
service->registerListener(gsl);
ALOGI("client call notifyMessage\\n");
String16 msg = String16("goda666");
service->notifyMessage(android::hardware::IGodaServiceListener::STATUS_NOT_PRESENT, msg);
}
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
ALOGI("client exit\\n");
return 0;
};
build/target/product/core_base.mk 还要在对应的包文件中加入这几个库
# godv modules
PRODUCT_PACKAGES += \\
libgodaservice \\
libgodaclient \\
godaservice
最后附上执行效果
以上是关于Android Binder (可以直接写在项目中的写法)的主要内容,如果未能解决你的问题,请参考以下文章