在Android中实现一个Java服务非常简单,编写AIDL文件定义接口,然后定义一个类继承自Service并定义一个类实现AIDL中定义的接口即可,在C++中有办法用AIDL定义接口并实现一个服务供Java端和C++端访问吗?
在api-29之后是可以实现的,步骤如下:
1.添加AIDL文件:IFoundationService.aidl
目录相对路径为:aidl/com/free/device
package com.free.device;
interface IFoundationService
{
int Function1();
int Function2();
int Function3();
}
2.实现FoundationService.h
#ifndef COM_FREE_DEVICE_FOUNDATION_SERVICE_H_
#define COM_FREE_DEVICE_FOUNDATION_SERVICE_H_
#include <stdlib.h>
#include <utils/RefBase.h>
#include <binder/TextOutput.h>
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <thread>
#include "com/free/device/IFoundationService.h"
#include "com/free/device/BnFoundationService.h"
using namespace android;
class IFoundationServer : public com::free::device::BnFoundationService
{
public:
IFoundationServer();
virtual ~IFoundationServer();
binder::Status function1(int32_t* _aidl_return);
binder::Status function2(int32_t* _aidl_return);
binder::Status function3(int32_t* _aidl_return);
private:
//其他私有变量
private:
std::string getCurrentDateTime();
//其他私有函数
};
#endif // COM_FREE_DEVICE_FOUNDATION_SERVICE_H_
3.实现FoundationService.cpp
#define LOG_TAG "FoundationServiced"
#include "FoundationService.h"
#include <utils/Log.h>
#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <array>
#include <chrono>
#include <ctime>
#include <stdio.h>
#include <unistd.h>
#include <thread>
#include <atomic>
#include <signal.h>
using namespace android;
// 构造函数
IFoundationServer::IFoundationServer() {}
// 析构函数
IFoundationServer::~IFoundationServer() {
}
//接口实现
binder::Status IFoundationServer::function1(int32_t* _aidl_return) {
return binder::Status::ok();
}
// 停止Logcat日志记录
binder::Status IFoundationServer::function2(int32_t* _aidl_return) {
return binder::Status::ok();
}
// 启用内核日志记录
binder::Status IFoundationServer::function3( int32_t* _aidl_return) {
return binder::Status::ok();
}
// 获取当前日期和时间
std::string IFoundationServer::getCurrentDateTime() {
auto now = std::chrono::system_clock::now();
auto now_c = std::chrono::system_clock::to_time_t(now);
std::array<char, 64> buf;
std::strftime(buf.data(), buf.size(), "%Y%m%d%H%M%S", std::localtime(&now_c));
return std::string(buf.data());
}
4.实现FoundationServiced.cpp,服务Damon进程的入库函数
#define LOG_TAG "FoundationServiced"
#include <stdlib.h>
#include <utils/RefBase.h>
#include <utils/Log.h>
#include <binder/TextOutput.h>
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "FoundationService.h"
using namespace android;
int main(int /*argc*/, char const ** /*argv*/)
{
defaultServiceManager()->addService(String16("IFoundation"), new IFoundationServer());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
5.foundationservice.rc
service foundationservice /system/bin/foundationserviced
class core
user root
group root
6.编写Android.bp
cc_library_shared {
name: "libfoundationservice",
srcs: [
"aidl/com/free/device/IFoundationService.aidl",
"FoundationService.cpp"
],
aidl: {
export_aidl_headers: true,
},
export_include_dirs: ["aidl"],
include_dirs: ["frameworks/native"],
shared_libs: [
"libbinder",
"libutils",
"liblog",
],
cflags: [
"-Wall",
"-Werror",
"-Wunused",
"-Wunreachable-code",
],
}
cc_binary {
name: "foundationserviced",
srcs: [
"FoundationServiced.cpp",
],
include_dirs: ["frameworks/native"],
shared_libs: [
"libfoundationservice",
"libbinder",
"libutils",
"liblog",
],
cflags: [
"-Wall",
"-Werror",
"-Wunused",
"-Wunreachable-code",
"-Wunused-parameter",
],
init_rc: ["foundationservice.rc"],
}
7.Selinux相关修改
修改private/service_contexts
foundationserviced u:object_r:foundationserviced_service:s0
新增foundationserviced.te
# foundationserviced service
type foundationserviced, domain, coredomain;
type foundationserviced_exec, exec_type, file_type;
#binder_use(foundationserviced);
init_daemon_domain(foundationserviced);
allow foundationserviced foundationserviced_service:service_manager { add };
allow foundationserviced binder_device:chr_file { ioctl open read write };
allow foundationserviced servicemanager:binder call;
修改file_contexts
/system/bin/foundationserviced u:object_r:foundationserviced_exec:s0
修改service.te
type foundationserviced_service, service_manager_type;
8.device.mk修改
PRODUCT_PACKAGES += \
libfoundationservice \
foundationserviced
9.client实现
Java客户端
private static final String SERVICE_MANAGER = "android.os.ServiceManager";
private static final String GET_SERVICE = "getService";
private static final String SERVICE_NAME = "IFoundation";
private void init() {
IBinder binder = null;
try {
// 加载android.os.ServiceManager类,这是Android的一个系统服务管理类
Class<?> serviceManager = Class.forName(SERVICE_MANAGER);
// 从ServiceManager类中获取名为"getService"的方法,该方法用于获取服务的IBinder对象
Method getServiceMethod = serviceManager.getDeclaredMethod(GET_SERVICE, String.class);
// 调用getService方法,获取名为SERVICE_NAME 的服务的IBinder对象
binder = (IBinder) getServiceMethod.invoke(null, SERVICE_NAME);
// 检查获取的IBinder对象是否为空,如果为空则表示服务获取失败
if (binder == null) {
Log.d(TAG, "getService failed for " + SERVICE_NAME);
return;
}
mFoundation = IFoundationService.Stub.asInterface(binder);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "meet exception: " + e.getMessage());
}
}