feat(arc): 添加虹软人脸识别插件基础功能
- 集成虹软 ArcSoft Face SDK,提供人脸检测、识别、活体检测功能 - 实现 Android 平台原生插件,包含 ArcPlugin 和 FaceEngineManager - 添加完整的人脸错误码枚举(586个错误码),覆盖 SDK 所有错误情况 - 创建人脸信息数据模型 FaceInfo,封装检测结果和特征数据 - 配置 Android 权限和依赖,包括相机、存储、网络等必要权限 - 添加方法通道实现,连接 Flutter 层与原生层通信 - 配置项目基础文件,包含 .gitignore、分析选项和元数据配置 - 实现单元测试框架,包含 Dart 和 Java 层的基本测试用例 - 添加示例应用配置,验证插件集成和基本功能使用 - 提供详细的开发指导文档 CLAUDE.md,说明架构和 API 使用方法
This commit is contained in:
9
android/.gitignore
vendored
Normal file
9
android/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.cxx
|
||||
59
android/build.gradle
Normal file
59
android/build.gradle
Normal file
@@ -0,0 +1,59 @@
|
||||
group = "com.xiarui.arc"
|
||||
version = "1.0"
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:8.9.1")
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: "com.android.library"
|
||||
|
||||
android {
|
||||
namespace = "com.xiarui.arc"
|
||||
|
||||
compileSdk = 36
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 24
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
jniLibs.srcDirs = ['src/main/jniLibs']
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
testImplementation("org.mockito:mockito-core:5.0.0")
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests.all {
|
||||
testLogging {
|
||||
events "passed", "skipped", "failed", "standardOut", "standardError"
|
||||
outputs.upToDateWhen {false}
|
||||
showStandardStreams = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
android/libs/arcsoft_face.jar
Normal file
BIN
android/libs/arcsoft_face.jar
Normal file
Binary file not shown.
BIN
android/libs/arcsoft_image_util.jar
Normal file
BIN
android/libs/arcsoft_image_util.jar
Normal file
Binary file not shown.
1
android/settings.gradle
Normal file
1
android/settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = 'arc'
|
||||
12
android/src/main/AndroidManifest.xml
Normal file
12
android/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.xiarui.arc">
|
||||
|
||||
<!-- 虹软 SDK 所需权限 -->
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.FLASHLIGHT"/>
|
||||
|
||||
</manifest>
|
||||
586
android/src/main/java/com/xiarui/arc/FaceErrorCode.java
Normal file
586
android/src/main/java/com/xiarui/arc/FaceErrorCode.java
Normal file
@@ -0,0 +1,586 @@
|
||||
package com.xiarui.arc;
|
||||
|
||||
/**
|
||||
* 虹软人脸识别 SDK 错误码枚举
|
||||
* 映射 SDK 返回的错误码到可读描述
|
||||
* 官方错误码文档:https://ai.arcsoft.com.cn
|
||||
*/
|
||||
public enum FaceErrorCode {
|
||||
// ==================== 通用错误码 ====================
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
MOK(0, "0x0", "成功"),
|
||||
|
||||
/**
|
||||
* 错误原因不明
|
||||
*/
|
||||
MERR_UNKNOWN(1, "0x1", "错误原因不明"),
|
||||
|
||||
/**
|
||||
* 无效的参数
|
||||
*/
|
||||
MERR_INVALID_PARAM(2, "0x2", "无效的参数"),
|
||||
|
||||
/**
|
||||
* 引擎不支持
|
||||
*/
|
||||
MERR_UNSUPPORTED(3, "0x3", "引擎不支持"),
|
||||
|
||||
/**
|
||||
* 内存不足
|
||||
*/
|
||||
MERR_NO_MEMORY(4, "0x4", "内存不足"),
|
||||
|
||||
/**
|
||||
* 状态错误
|
||||
*/
|
||||
MERR_BAD_STATE(5, "0x5", "状态错误"),
|
||||
|
||||
/**
|
||||
* 用户取消相关操作
|
||||
*/
|
||||
MERR_USER_CANCEL(6, "0x6", "用户取消相关操作"),
|
||||
|
||||
/**
|
||||
* 操作时间过期
|
||||
*/
|
||||
MERR_EXPIRED(7, "0x7", "操作时间过期"),
|
||||
|
||||
/**
|
||||
* 用户暂停操作
|
||||
*/
|
||||
MERR_USER_PAUSE(8, "0x8", "用户暂停操作"),
|
||||
|
||||
/**
|
||||
* 缓冲上溢
|
||||
*/
|
||||
MERR_BUFFER_OVERFLOW(9, "0x9", "缓冲上溢"),
|
||||
|
||||
/**
|
||||
* 缓冲下溢
|
||||
*/
|
||||
MERR_BUFFER_UNDERFLOW(10, "0xA", "缓冲下溢"),
|
||||
|
||||
/**
|
||||
* 存贮空间不足
|
||||
*/
|
||||
MERR_NO_DISKSPACE(11, "0xB", "存贮空间不足"),
|
||||
|
||||
/**
|
||||
* 组件不存在
|
||||
*/
|
||||
MERR_COMPONENT_NOT_EXIST(12, "0xC", "组件不存在"),
|
||||
|
||||
/**
|
||||
* 全局数据不存在
|
||||
*/
|
||||
MERR_GLOBAL_DATA_NOT_EXIST(13, "0xD", "全局数据不存在"),
|
||||
|
||||
// ==================== SDK 基础错误码 ====================
|
||||
/**
|
||||
* 无效的 APP_ID
|
||||
*/
|
||||
MERR_FSDK_INVALID_APP_ID(28673, "0x7001", "无效的 APP_ID"),
|
||||
|
||||
/**
|
||||
* 无效的 SDK_KEY
|
||||
*/
|
||||
MERR_FSDK_INVALID_SDK_ID(28674, "0x7002", "无效的 SDK_KEY"),
|
||||
|
||||
/**
|
||||
* APP_ID 和 SDK_KEY 不匹配
|
||||
*/
|
||||
MERR_FSDK_INVALID_ID_PAIR(28675, "0x7003", "APP_ID 和 SDK_KEY 不匹配"),
|
||||
|
||||
/**
|
||||
* SDK_KEY 和使用的 SDK 不匹配
|
||||
*/
|
||||
MERR_FSDK_MISMATCH_ID_AND_SDK(28676, "0x7004", "SDK_KEY 和使用的 SDK 不匹配"),
|
||||
|
||||
/**
|
||||
* 系统版本不被当前 SDK 所支持
|
||||
*/
|
||||
MERR_FSDK_SYSTEM_VERSION_UNSUPPORTED(28677, "0x7005", "系统版本不被当前 SDK 所支持"),
|
||||
|
||||
// ==================== 人脸识别基础错误码 ====================
|
||||
/**
|
||||
* 无效的输入内存
|
||||
*/
|
||||
MERR_FSDK_FR_INVALID_MEMORY_INFO(73729, "0x12001", "无效的输入内存"),
|
||||
|
||||
/**
|
||||
* 无效的输入图像参数
|
||||
*/
|
||||
MERR_FSDK_FR_INVALID_IMAGE_INFO(73730, "0x12002", "无效的输入图像参数"),
|
||||
|
||||
/**
|
||||
* 无效的脸部信息
|
||||
*/
|
||||
MERR_FSDK_FR_INVALID_FACE_INFO(73731, "0x12003", "无效的脸部信息"),
|
||||
|
||||
/**
|
||||
* 当前设备无 GPU 可用
|
||||
*/
|
||||
MERR_FSDK_FR_NO_GPU_AVAILABLE(73732, "0x12004", "当前设备无 GPU 可用"),
|
||||
|
||||
/**
|
||||
* 待比较的两个人脸特征的版本不一致
|
||||
*/
|
||||
MERR_FSDK_FR_MISMATCHED_FEATURE_LEVEL(73733, "0x12005", "待比较的两个人脸特征的版本不一致"),
|
||||
|
||||
// ==================== 人脸特征检测错误码 ====================
|
||||
/**
|
||||
* 人脸特征检测错误未知
|
||||
*/
|
||||
MERR_FSDK_FACEFEATURE_UNKNOWN(81921, "0x14001", "人脸特征检测错误未知"),
|
||||
|
||||
/**
|
||||
* 人脸特征检测内存错误
|
||||
*/
|
||||
MERR_FSDK_FACEFEATURE_MEMORY(81922, "0x14002", "人脸特征检测内存错误"),
|
||||
|
||||
/**
|
||||
* 人脸特征检测格式错误
|
||||
*/
|
||||
MERR_FSDK_FACEFEATURE_INVALID_FORMAT(81923, "0x14003", "人脸特征检测格式错误"),
|
||||
|
||||
/**
|
||||
* 人脸特征检测参数错误
|
||||
*/
|
||||
MERR_FSDK_FACEFEATURE_INVALID_PARAM(81924, "0x14004", "人脸特征检测参数错误"),
|
||||
|
||||
/**
|
||||
* 人脸特征检测结果置信度低
|
||||
*/
|
||||
MERR_FSDK_FACEFEATURE_LOW_CONFIDENCE_LEVEL(81925, "0x14005", "人脸特征检测结果置信度低"),
|
||||
|
||||
/**
|
||||
* 人脸特征检测结果操作过期
|
||||
*/
|
||||
MERR_FSDK_FACEFEATURE_EXPIRED(81926, "0x14006", "人脸特征检测结果操作过期"),
|
||||
|
||||
/**
|
||||
* 人脸特征检测人脸丢失
|
||||
*/
|
||||
MERR_FSDK_FACEFEATURE_MISSFACE(81927, "0x14007", "人脸特征检测人脸丢失"),
|
||||
|
||||
/**
|
||||
* 人脸特征检测没有人脸
|
||||
*/
|
||||
MERR_FSDK_FACEFEATURE_NO_FACE(81928, "0x14008", "人脸特征检测没有人脸"),
|
||||
|
||||
/**
|
||||
* 人脸特征检测人脸信息错误
|
||||
*/
|
||||
MERR_FSDK_FACEFEATURE_FACEDATA(81929, "0x14009", "人脸特征检测人脸信息错误"),
|
||||
|
||||
// ==================== ASF 扩展错误码 ====================
|
||||
/**
|
||||
* Engine 不支持的检测属性
|
||||
*/
|
||||
MERR_ASF_EX_FEATURE_UNSUPPORTED_ON_INIT(86017, "0x15001", "Engine 不支持的检测属性"),
|
||||
|
||||
/**
|
||||
* 需要检测的属性未初始化
|
||||
*/
|
||||
MERR_ASF_EX_FEATURE_UNINITED(86018, "0x15002", "需要检测的属性未初始化"),
|
||||
|
||||
/**
|
||||
* 待获取的属性未在 process 中处理过
|
||||
*/
|
||||
MERR_ASF_EX_FEATURE_UNPROCESSED(86019, "0x15003", "待获取的属性未在 process 中处理过"),
|
||||
|
||||
/**
|
||||
* PROCESS 不支持的检测属性
|
||||
*/
|
||||
MERR_ASF_EX_FEATURE_UNSUPPORTED_ON_PROCESS(86020, "0x15004", "PROCESS 不支持的检测属性"),
|
||||
|
||||
/**
|
||||
* 无效的输入图像
|
||||
*/
|
||||
MERR_ASF_EX_INVALID_IMAGE_INFO(86021, "0x15005", "无效的输入图像"),
|
||||
|
||||
/**
|
||||
* 无效的脸部信息
|
||||
*/
|
||||
MERR_ASF_EX_INVALID_FACE_INFO(86022, "0x15006", "无效的脸部信息"),
|
||||
|
||||
// ==================== 激活相关错误码 ====================
|
||||
/**
|
||||
* SDK 激活失败,请打开读写权限
|
||||
*/
|
||||
MERR_ASF_ACTIVATION_FAIL(90113, "0x16001", "SDK 激活失败,请打开读写权限"),
|
||||
|
||||
/**
|
||||
* SDK 已激活
|
||||
*/
|
||||
MERR_ASF_ALREADY_ACTIVATED(90114, "0x16002", "SDK 已激活"),
|
||||
|
||||
/**
|
||||
* SDK 未激活
|
||||
*/
|
||||
MERR_ASF_NOT_ACTIVATED(90115, "0x16003", "SDK 未激活"),
|
||||
|
||||
/**
|
||||
* detectFaceScaleVal 不支持
|
||||
*/
|
||||
MERR_ASF_SCALE_NOT_SUPPORT(90116, "0x16004", "detectFaceScaleVal 不支持"),
|
||||
|
||||
/**
|
||||
* 激活文件与 SDK 类型不匹配
|
||||
*/
|
||||
MERR_ASF_ACTIVEFILE_SDKTYPE_MISMATCH(90117, "0x16005", "激活文件与 SDK 类型不匹配"),
|
||||
|
||||
/**
|
||||
* 设备不匹配
|
||||
*/
|
||||
MERR_ASF_DEVICE_MISMATCH(90118, "0x16006", "设备不匹配"),
|
||||
|
||||
/**
|
||||
* 唯一标识不合法
|
||||
*/
|
||||
MERR_ASF_UNIQUE_IDENTIFIER_ILLEGAL(90119, "0x16007", "唯一标识不合法"),
|
||||
|
||||
/**
|
||||
* 参数为空
|
||||
*/
|
||||
MERR_ASF_PARAM_NULL(90120, "0x16008", "参数为空"),
|
||||
|
||||
/**
|
||||
* 版本不支持
|
||||
*/
|
||||
MERR_ASF_VERSION_NOT_SUPPORT(90122, "0x1600A", "版本不支持"),
|
||||
|
||||
/**
|
||||
* 签名错误
|
||||
*/
|
||||
MERR_ASF_SIGN_ERROR(90123, "0x1600B", "签名错误"),
|
||||
|
||||
/**
|
||||
* 激活信息保存异常
|
||||
*/
|
||||
MERR_ASF_DATABASE_ERROR(90124, "0x1600C", "激活信息保存异常"),
|
||||
|
||||
/**
|
||||
* 唯一标识符校验失败
|
||||
*/
|
||||
MERR_ASF_UNIQUE_CHECKOUT_FAIL(90125, "0x1600D", "唯一标识符校验失败"),
|
||||
|
||||
/**
|
||||
* 颜色空间不支持
|
||||
*/
|
||||
MERR_ASF_COLOR_SPACE_NOT_SUPPORT(90126, "0x1600E", "颜色空间不支持"),
|
||||
|
||||
/**
|
||||
* 图片宽高不支持,宽度需四字节对齐
|
||||
*/
|
||||
MERR_ASF_IMAGE_WIDTH_HEIGHT_NOT_SUPPORT(90127, "0x1600F", "图片宽高不支持,宽度需四字节对齐"),
|
||||
|
||||
/**
|
||||
* android.permission.READ_PHONE_STATE 权限被拒绝
|
||||
*/
|
||||
MERR_ASF_READ_PHONE_STATE_DENIED(90128, "0x16010", "android.permission.READ_PHONE_STATE 权限被拒绝"),
|
||||
|
||||
/**
|
||||
* 激活数据被破坏,请删除激活文件,重新进行激活
|
||||
*/
|
||||
MERR_ASF_ACTIVATION_DATA_DESTROYED(90129, "0x16011", "激活数据被破坏,请删除激活文件,重新进行激活"),
|
||||
|
||||
/**
|
||||
* 服务端未知错误
|
||||
*/
|
||||
MERR_ASF_SERVER_UNKNOWN_ERROR(90130, "0x16012", "服务端未知错误"),
|
||||
|
||||
/**
|
||||
* android.permission.INTERNET 权限被拒绝
|
||||
*/
|
||||
MERR_ASF_INTERNET_DENIED(90131, "0x16013", "android.permission.INTERNET 权限被拒绝"),
|
||||
|
||||
/**
|
||||
* 激活文件与 SDK 版本不匹配,请重新激活
|
||||
*/
|
||||
MERR_ASF_ACTIVEFILE_SDK_MISMATCH(90132, "0x16014", "激活文件与 SDK 版本不匹配,请重新激活"),
|
||||
|
||||
/**
|
||||
* 设备信息太少,不足以生成设备指纹
|
||||
*/
|
||||
MERR_ASF_DEVICEINFO_LESS(90133, "0x16015", "设备信息太少,不足以生成设备指纹"),
|
||||
|
||||
/**
|
||||
* 客户端时间与服务器时间前后相差在 30 分钟以上
|
||||
*/
|
||||
MERR_ASF_LOCAL_TIME_NOT_CALIBRATED(90134, "0x16016", "客户端时间与服务器时间前后相差在 30 分钟以上"),
|
||||
|
||||
/**
|
||||
* 数据校验异常
|
||||
*/
|
||||
MERR_ASF_APPID_DATA_DECRYPT(90135, "0x16017", "数据校验异常"),
|
||||
|
||||
/**
|
||||
* 传入的 APP_ID 和 AppKey 与使用的 SDK 版本不一致
|
||||
*/
|
||||
MERR_ASF_APPID_APPKEY_SDK_MISMATCH(90136, "0x16018", "传入的 APP_ID 和 AppKey 与使用的 SDK 版本不一致"),
|
||||
|
||||
/**
|
||||
* 短时间大量请求会被禁止请求,30 分钟之后解封
|
||||
*/
|
||||
MERR_ASF_NO_REQUEST(90137, "0x16019", "短时间大量请求会被禁止请求,30 分钟之后解封"),
|
||||
|
||||
/**
|
||||
* 激活文件不存在
|
||||
*/
|
||||
MERR_ASF_ACTIVE_FILE_NO_EXIST(90138, "0x1601A", "激活文件不存在"),
|
||||
|
||||
/**
|
||||
* 当前设备时间不正确,请调整设备时间
|
||||
*/
|
||||
MERR_ASF_CURRENT_DEVICE_TIME_INCORRECT(90139, "0x1601B", "当前设备时间不正确,请调整设备时间"),
|
||||
|
||||
/**
|
||||
* 检测模型不支持
|
||||
*/
|
||||
MERR_ASF_DETECT_MODEL_UNSUPPORTED(90140, "0x1601C", "检测模型不支持"),
|
||||
|
||||
// ==================== 网络相关错误码 ====================
|
||||
/**
|
||||
* 无法解析主机地址
|
||||
*/
|
||||
MERR_ASF_NETWORK_COULDNT_RESOLVE_HOST(94209, "0x17001", "无法解析主机地址"),
|
||||
|
||||
/**
|
||||
* 无法连接服务器
|
||||
*/
|
||||
MERR_ASF_NETWORK_COULDNT_CONNECT_SERVER(94210, "0x17002", "无法连接服务器"),
|
||||
|
||||
/**
|
||||
* 网络连接超时
|
||||
*/
|
||||
MERR_ASF_NETWORK_CONNECT_TIMEOUT(94211, "0x17003", "网络连接超时"),
|
||||
|
||||
/**
|
||||
* 网络未知错误
|
||||
*/
|
||||
MERR_ASF_NETWORK_UNKNOWN_ERROR(94212, "0x17004", "网络未知错误"),
|
||||
|
||||
// ==================== 激活密钥相关错误码 ====================
|
||||
/**
|
||||
* 无法连接激活服务器
|
||||
*/
|
||||
MERR_ASF_ACTIVEKEY_COULDNT_CONNECT_SERVER(98305, "0x18001", "无法连接激活服务器"),
|
||||
|
||||
/**
|
||||
* 服务器系统错误
|
||||
*/
|
||||
MERR_ASF_ACTIVEKEY_SERVER_SYSTEM_ERROR(98306, "0x18002", "服务器系统错误"),
|
||||
|
||||
/**
|
||||
* 请求参数错误
|
||||
*/
|
||||
MERR_ASF_ACTIVEKEY_POST_PARM_ERROR(98307, "0x18003", "请求参数错误"),
|
||||
|
||||
/**
|
||||
* ACTIVE_KEY 与 APP_ID、SDK_KEY 不匹配
|
||||
*/
|
||||
MERR_ASF_ACTIVEKEY_PARM_MISMATCH(98308, "0x18004", "ACTIVE_KEY 与 APP_ID、SDK_KEY 不匹配"),
|
||||
|
||||
/**
|
||||
* ACTIVE_KEY 已经被使用
|
||||
*/
|
||||
MERR_ASF_ACTIVEKEY_ACTIVEKEY_ACTIVATED(98309, "0x18005", "ACTIVE_KEY 已经被使用"),
|
||||
|
||||
/**
|
||||
* ACTIVE_KEY 信息异常
|
||||
*/
|
||||
MERR_ASF_ACTIVEKEY_ACTIVEKEY_FORMAT_ERROR(98310, "0x18006", "ACTIVE_KEY 信息异常"),
|
||||
|
||||
/**
|
||||
* ACTIVE_KEY 与 APP_ID 不匹配
|
||||
*/
|
||||
MERR_ASF_ACTIVEKEY_APPID_PARM_MISMATCH(98311, "0x18007", "ACTIVE_KEY 与 APP_ID 不匹配"),
|
||||
|
||||
/**
|
||||
* SDK 与激活文件版本不匹配
|
||||
*/
|
||||
MERR_ASF_ACTIVEKEY_SDK_FILE_MISMATCH(98312, "0x18008", "SDK 与激活文件版本不匹配"),
|
||||
|
||||
/**
|
||||
* ACTIVE_KEY 已过期
|
||||
*/
|
||||
MERR_ASF_ACTIVEKEY_EXPIRED(98313, "0x18009", "ACTIVE_KEY 已过期"),
|
||||
|
||||
// ==================== 离线授权相关错误码 ====================
|
||||
/**
|
||||
* 离线授权文件不存在或无读写权限
|
||||
*/
|
||||
MERR_ASF_LICENSE_FILE_NOT_EXIST(102401, "0x19001", "离线授权文件不存在或无读写权限"),
|
||||
|
||||
/**
|
||||
* 离线授权文件已损坏
|
||||
*/
|
||||
MERR_ASF_LICENSE_FILE_DATA_DESTROYED(102402, "0x19002", "离线授权文件已损坏"),
|
||||
|
||||
/**
|
||||
* 离线授权文件与 SDK 版本不匹配
|
||||
*/
|
||||
MERR_ASF_LICENSE_FILE_SDK_MISMATCH(102403, "0x19003", "离线授权文件与 SDK 版本不匹配"),
|
||||
|
||||
/**
|
||||
* 离线授权文件与 SDK 信息不匹配
|
||||
*/
|
||||
MERR_ASF_LICENSE_FILEINFO_SDKINFO_MISMATCH(102404, "0x19004", "离线授权文件与 SDK 信息不匹配"),
|
||||
|
||||
/**
|
||||
* 离线授权文件与设备指纹不匹配
|
||||
*/
|
||||
MERR_ASF_LICENSE_FILE_FINGERPRINT_MISMATCH(102405, "0x19005", "离线授权文件与设备指纹不匹配"),
|
||||
|
||||
/**
|
||||
* 离线授权文件已过期
|
||||
*/
|
||||
MERR_ASF_LICENSE_FILE_EXPIRED(102406, "0x19006", "离线授权文件已过期"),
|
||||
|
||||
/**
|
||||
* 离线授权文件不可用,本地原有激活文件可继续使用
|
||||
*/
|
||||
MERR_ASF_LOCAL_EXIST_USEFUL_ACTIVE_FILE(102407, "0x19007", "离线授权文件不可用,本地原有激活文件可继续使用"),
|
||||
|
||||
/**
|
||||
* 离线授权文件版本过低
|
||||
*/
|
||||
MERR_ASF_LICENSE_FILE_VERSION_TOO_LOW(102408, "0x19008", "离线授权文件版本过低"),
|
||||
|
||||
// ==================== 人脸搜索相关错误码 ====================
|
||||
/**
|
||||
* 人脸列表为空
|
||||
*/
|
||||
MERR_ASF_SEARCH_EMPTY(151553, "0x25001", "人脸列表为空"),
|
||||
|
||||
/**
|
||||
* 人脸不存在
|
||||
*/
|
||||
MERR_ASF_SEARCH_NO_EXIST(151554, "0x25002", "人脸不存在"),
|
||||
|
||||
/**
|
||||
* 特征值长度不匹配
|
||||
*/
|
||||
MERR_ASF_SEARCH_FEATURE_SIZE_MISMATCH(151555, "0x25003", "特征值长度不匹配"),
|
||||
|
||||
/**
|
||||
* 相似度异常
|
||||
*/
|
||||
MERR_ASF_SEARCH_LOW_CONFIDENCE(151556, "0x25004", "相似度异常"),
|
||||
|
||||
// ==================== 自定义扩展错误码 ====================
|
||||
/**
|
||||
* 引擎未初始化(自定义错误码)
|
||||
*/
|
||||
ENGINE_NOT_INITIALIZED(-1, "N/A", "引擎未初始化"),
|
||||
|
||||
/**
|
||||
* 未知错误
|
||||
*/
|
||||
UNKNOWN(-2, "N/A", "未知错误");
|
||||
|
||||
/**
|
||||
* 错误码(十进制)
|
||||
*/
|
||||
private final int code;
|
||||
|
||||
/**
|
||||
* 错误码(十六进制)
|
||||
*/
|
||||
private final String hexCode;
|
||||
|
||||
/**
|
||||
* 错误描述
|
||||
*/
|
||||
private final String message;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param code 错误码(十进制)
|
||||
* @param hexCode 错误码(十六进制)
|
||||
* @param message 错误描述
|
||||
*/
|
||||
FaceErrorCode(int code, String hexCode, String message) {
|
||||
this.code = code;
|
||||
this.hexCode = hexCode;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错误码(十进制)
|
||||
* @return 错误码整数值
|
||||
*/
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错误码(十六进制)
|
||||
* @return 错误码十六进制字符串
|
||||
*/
|
||||
public String getHexCode() {
|
||||
return hexCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错误描述
|
||||
* @return 错误描述信息
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据错误码整数值获取对应的枚举
|
||||
* @param code 错误码整数(十进制)
|
||||
* @return 对应的 FaceErrorCode 枚举
|
||||
*/
|
||||
public static FaceErrorCode fromCode(int code) {
|
||||
for (FaceErrorCode e : values()) {
|
||||
if (e.code == code) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据错误码获取错误描述
|
||||
* @param code 错误码整数
|
||||
* @return 错误描述信息
|
||||
*/
|
||||
public static String getMessageByCode(int code) {
|
||||
FaceErrorCode errorCode = fromCode(code);
|
||||
return errorCode.getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为成功状态
|
||||
* @param code 错误码整数
|
||||
* @return true 表示成功,false 表示失败
|
||||
*/
|
||||
public static boolean isSuccess(int code) {
|
||||
return code == MOK.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错误的详细信息(包含十进制、十六进制和描述)
|
||||
* @return 格式化的错误信息
|
||||
*/
|
||||
public String getDetailMessage() {
|
||||
return String.format("[%d / %s] %s", code, hexCode, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错误的详细信息(包含十进制、十六进制和描述)
|
||||
* @param code 错误码整数
|
||||
* @return 格式化的错误信息
|
||||
*/
|
||||
public static String getDetailMessageByCode(int code) {
|
||||
FaceErrorCode errorCode = fromCode(code);
|
||||
return errorCode.getDetailMessage();
|
||||
}
|
||||
}
|
||||
292
android/src/main/java/com/xiarui/arc/FaceInfo.java
Normal file
292
android/src/main/java/com/xiarui/arc/FaceInfo.java
Normal file
@@ -0,0 +1,292 @@
|
||||
package com.xiarui.arc;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 人脸信息类
|
||||
* 封装虹软 SDK 返回的单个人脸检测结果
|
||||
*/
|
||||
public class FaceInfo {
|
||||
/**
|
||||
* 人脸矩形框(左、上、右、下坐标)
|
||||
*/
|
||||
private Rect faceRect;
|
||||
|
||||
/**
|
||||
* 人脸角度(0/90/180/270)
|
||||
*/
|
||||
private int faceOrientation;
|
||||
|
||||
/**
|
||||
* 人脸 ID(VIDEO 模式下有效)
|
||||
*/
|
||||
private int faceId;
|
||||
|
||||
/**
|
||||
* 人脸相似度(识别功能返回)
|
||||
*/
|
||||
private float similarity;
|
||||
|
||||
/**
|
||||
* 活体检测结果(>0 表示活体)
|
||||
*/
|
||||
private float liveness;
|
||||
|
||||
/**
|
||||
* 年龄(年龄估计功能返回)
|
||||
*/
|
||||
private int age;
|
||||
|
||||
/**
|
||||
* 性别(性别识别功能返回,0=未知,1=男,2=女)
|
||||
*/
|
||||
private int gender;
|
||||
|
||||
/**
|
||||
* 口罩佩戴状态(口罩检测功能返回,-1=未知,0=未佩戴,1=已佩戴)
|
||||
*/
|
||||
private int maskStatus;
|
||||
|
||||
/**
|
||||
* 人脸特征数据(特征提取功能返回)
|
||||
*/
|
||||
private byte[] featureData;
|
||||
|
||||
/**
|
||||
* 默认构造函数
|
||||
*/
|
||||
public FaceInfo() {
|
||||
this.faceRect = new Rect();
|
||||
this.faceOrientation = 0;
|
||||
this.faceId = 0;
|
||||
this.similarity = 0.0f;
|
||||
this.liveness = 0.0f;
|
||||
this.age = 0;
|
||||
this.gender = 0;
|
||||
this.maskStatus = -1;
|
||||
this.featureData = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param faceRect 人脸矩形框
|
||||
*/
|
||||
public FaceInfo(Rect faceRect) {
|
||||
this.faceRect = faceRect;
|
||||
this.faceOrientation = 0;
|
||||
this.faceId = 0;
|
||||
this.similarity = 0.0f;
|
||||
this.liveness = 0.0f;
|
||||
this.age = 0;
|
||||
this.gender = 0;
|
||||
this.maskStatus = -1;
|
||||
this.featureData = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取人脸矩形框
|
||||
* @return 人脸矩形框 Rect 对象
|
||||
*/
|
||||
public Rect getFaceRect() {
|
||||
return faceRect;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置人脸矩形框
|
||||
* @param faceRect 人脸矩形框
|
||||
*/
|
||||
public void setFaceRect(Rect faceRect) {
|
||||
this.faceRect = faceRect;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置人脸矩形 left 坐标
|
||||
* @param left 左坐标
|
||||
*/
|
||||
public void setLeft(int left) {
|
||||
this.faceRect = new Rect(left, faceRect.top, faceRect.right, faceRect.bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置人脸矩形 top 坐标
|
||||
* @param top 上坐标
|
||||
*/
|
||||
public void setTop(int top) {
|
||||
this.faceRect = new Rect(faceRect.left, top, faceRect.right, faceRect.bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置人脸矩形 right 坐标
|
||||
* @param right 右坐标
|
||||
*/
|
||||
public void setRight(int right) {
|
||||
this.faceRect = new Rect(faceRect.left, faceRect.top, right, faceRect.bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置人脸矩形 bottom 坐标
|
||||
* @param bottom 下坐标
|
||||
*/
|
||||
public void setBottom(int bottom) {
|
||||
this.faceRect = new Rect(faceRect.left, faceRect.top, faceRect.right, bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置人脸角度
|
||||
* @param orient 人脸角度
|
||||
*/
|
||||
public void setOrient(int orient) {
|
||||
this.faceOrientation = orient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取人脸角度
|
||||
* @return 人脸角度(0/90/180/270)
|
||||
*/
|
||||
public int getFaceOrientation() {
|
||||
return faceOrientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置人脸角度
|
||||
* @param faceOrientation 人脸角度
|
||||
*/
|
||||
public void setFaceOrientation(int faceOrientation) {
|
||||
this.faceOrientation = faceOrientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取人脸 ID
|
||||
* @return 人脸 ID
|
||||
*/
|
||||
public int getFaceId() {
|
||||
return faceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置人脸 ID
|
||||
* @param faceId 人脸 ID
|
||||
*/
|
||||
public void setFaceId(int faceId) {
|
||||
this.faceId = faceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取人脸相似度
|
||||
* @return 人脸相似度(0.0-1.0)
|
||||
*/
|
||||
public float getSimilarity() {
|
||||
return similarity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置人脸相似度
|
||||
* @param similarity 人脸相似度
|
||||
*/
|
||||
public void setSimilarity(float similarity) {
|
||||
this.similarity = similarity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取活体检测结果
|
||||
* @return 活体值(>0 表示活体)
|
||||
*/
|
||||
public float getLiveness() {
|
||||
return liveness;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置活体检测结果
|
||||
* @param liveness 活体值
|
||||
*/
|
||||
public void setLiveness(float liveness) {
|
||||
this.liveness = liveness;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取年龄
|
||||
* @return 年龄值
|
||||
*/
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置年龄
|
||||
* @param age 年龄值
|
||||
*/
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取性别
|
||||
* @return 性别(0=未知,1=男,2=女)
|
||||
*/
|
||||
public int getGender() {
|
||||
return gender;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置性别
|
||||
* @param gender 性别值
|
||||
*/
|
||||
public void setGender(int gender) {
|
||||
this.gender = gender;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取口罩佩戴状态
|
||||
* @return 口罩状态(-1=未知,0=未佩戴,1=已佩戴)
|
||||
*/
|
||||
public int getMaskStatus() {
|
||||
return maskStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置口罩佩戴状态
|
||||
* @param maskStatus 口罩状态值
|
||||
*/
|
||||
public void setMaskStatus(int maskStatus) {
|
||||
this.maskStatus = maskStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取人脸特征数据
|
||||
* @return 人脸特征数据字节数组
|
||||
*/
|
||||
public byte[] getFeatureData() {
|
||||
return featureData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置人脸特征数据
|
||||
* @param featureData 人脸特征数据
|
||||
*/
|
||||
public void setFeatureData(byte[] featureData) {
|
||||
this.featureData = featureData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 FaceInfo 转换为 Map 对象,用于 Flutter 端调用
|
||||
* @return 包含人脸信息的 Map
|
||||
*/
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("left", faceRect.left);
|
||||
map.put("top", faceRect.top);
|
||||
map.put("right", faceRect.right);
|
||||
map.put("bottom", faceRect.bottom);
|
||||
map.put("orientation", faceOrientation);
|
||||
map.put("faceId", faceId);
|
||||
map.put("similarity", similarity);
|
||||
map.put("liveness", liveness);
|
||||
map.put("age", age);
|
||||
map.put("gender", gender);
|
||||
map.put("maskStatus", maskStatus);
|
||||
map.put("featureData", featureData != null ? featureData : new byte[0]);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
BIN
android/src/main/jniLibs/arm64-v8a/libarcsoft_face.so
Normal file
BIN
android/src/main/jniLibs/arm64-v8a/libarcsoft_face.so
Normal file
Binary file not shown.
BIN
android/src/main/jniLibs/arm64-v8a/libarcsoft_face_engine.so
Normal file
BIN
android/src/main/jniLibs/arm64-v8a/libarcsoft_face_engine.so
Normal file
Binary file not shown.
BIN
android/src/main/jniLibs/arm64-v8a/libarcsoft_image_util.so
Normal file
BIN
android/src/main/jniLibs/arm64-v8a/libarcsoft_image_util.so
Normal file
Binary file not shown.
BIN
android/src/main/jniLibs/armeabi-v7a/libarcsoft_face.so
Normal file
BIN
android/src/main/jniLibs/armeabi-v7a/libarcsoft_face.so
Normal file
Binary file not shown.
BIN
android/src/main/jniLibs/armeabi-v7a/libarcsoft_face_engine.so
Normal file
BIN
android/src/main/jniLibs/armeabi-v7a/libarcsoft_face_engine.so
Normal file
Binary file not shown.
BIN
android/src/main/jniLibs/armeabi-v7a/libarcsoft_image_util.so
Normal file
BIN
android/src/main/jniLibs/armeabi-v7a/libarcsoft_image_util.so
Normal file
Binary file not shown.
29
android/src/test/java/com/xiarui/arc/ArcPluginTest.java
Normal file
29
android/src/test/java/com/xiarui/arc/ArcPluginTest.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.xiarui.arc;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* This demonstrates a simple unit test of the Java portion of this plugin's implementation.
|
||||
*
|
||||
* Once you have built the plugin's example app, you can run these tests from the command
|
||||
* line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or
|
||||
* you can run them directly from IDEs that support JUnit such as Android Studio.
|
||||
*/
|
||||
|
||||
public class ArcPluginTest {
|
||||
@Test
|
||||
public void onMethodCall_getPlatformVersion_returnsExpectedValue() {
|
||||
ArcPlugin plugin = new ArcPlugin();
|
||||
|
||||
final MethodCall call = new MethodCall("getPlatformVersion", null);
|
||||
MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
|
||||
plugin.onMethodCall(call, mockResult);
|
||||
|
||||
verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user