活体检测
根据提示做出相应的活体动作,SDK 实时采集动态信息,判断用户是否为活体、真人。在黑灰产对抗激烈,“AI换脸”频发的场景下,活体检测SDK同时也集成了 风控设备环境检测能力,能够有效拦截摄像头被外部流注入的情况,同时独有的人脸鉴伪技术也能很好的识别合成脸攻击
⚠️ 接入活体SDK注意事项:
- 本地手动依赖,默认提供了活体检测、风控设备环境检测能力(推荐)
- 远程仓库依赖,仅集成了基础活体检测,不具备环境风险感知能力,如果您对SDK体积比较敏感,可以这种方式
- 如果您的产品服务的用户主要在海外,请联系技术支持提供海外专属技术方案,耗时更低
兼容性
| 条目 | 说明 |
|---|---|
| 适配版本 | minSdkVersion 21 及以上版本 |
| cpu 架构 | 内部提供了 armeabi-v7a 和 arm64-v8a 两种 so ,对于不兼容 arm 的 x86 机型不适配 |
资源引入
本地手动依赖(推荐)
获取 SDK
从易盾后台下载活体检测相关 sdk 的 aar 包
SDK模块介绍
| 模块名称 | 功能说明 | 支持裁剪 | SDK包体积 | 编译后体积增量 |
|---|---|---|---|---|
| livedetect-xxx.aar | 活体人脸检测 | 不可裁剪 | 3.7MB | 3.8MB |
| crashreport-xxx.aar | 活体人脸检测异常上报 | 不可裁剪 | 172KB | 173KB |
| base-core.aar | 活体人脸检测基本库 | 不可裁剪 | 34KB | 35KB |
| HTProtectLib-xxx.aar | 风控设备环境检测 | 可裁剪 | 6.1MB | 6.4MB |
添加 aar 包依赖
将获取到的 aar 文件拷贝到对应 module 的 libs 文件夹下(如没有该目录需新建),然后在 build.gradle 文件中增加如下代码
android{
repositories {
flatDir {
dirs 'libs'
}
}
}
dependencies {
implementation(name:'livedetect-xxx', ext: 'aar')
implementation(name: 'crashreport-xxx', ext: 'aar')
implementation(name: 'base-core-xxx', ext: 'aar')
implementation(name: 'HTProtectLib-xxx', ext: 'aar')
implementation 'com.squareup.okhttp3:okhttp:4.9.1' //若项目中原本存在无需添加
implementation 'com.google.code.gson:gson:2.8.6' //若项目中原本存在无需添加
}
SDK包裁剪说明
如果您对 SDK 体积比较敏感,可以不集成 HTProtectLib-xxx.aar 包,但是这意味着您放弃了风控设备环境检测能力
远程仓库依赖
获取 SDK
确认 Project 根目录的 build.gradle 中配置了 mavenCentral 支持
buildscript {
repositories {
mavenCentral()
}
...
}
allprojects {
repositories {
mavenCentral()
}
}
在对应 module 的 build.gradle 中添加依赖
implementation 'io.github.yidun:livedetect:3.3.8'
集成风控能力
如果需要在活体检测过程中检测设备环境,那需要额外接入风控 SDK,风控 SDK 仅提供本地依赖的方式
将易盾后台获取到的 aar 文件拷贝到对应 module 的 libs 文件夹下(如没有该目录需新建),然后在 build.gradle 文件中增加如下代码
android{
repositories {
flatDir {
dirs 'libs'
}
}
}
dependencies {
implementation(name: 'HTProtectLib-xxx', ext: 'aar')
}
注意点
- 在 app 的 build.gradle android 域下添加如下配置
packagingOptions {
doNotStrip "/arm64-v8a/libalive_detected.so"
doNotStrip "/armeabi-v7a/libalive_detected.so"
}
- 如果同时使用易盾的活体检测和身份证 ocr sdk,请务必先引用 ocr sdk; 遇到 so 冲突,请用以下方式解决
packagingOptions {
pickFirst 'lib/arm64-v8a/libc++_shared.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
}
各种配置
权限配置
SDK 依赖如下权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
其中,所有活体检测模式均需要相机权限;RGB 活体模式还需要存储权限和设备状态权限。以上权限均属于隐私权限,Android 6.0 及以上版本需要在使用前动态申请。
ActivityCompat.requestPermissions(
this,
new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE
},
0
);
申明与其他应用交互的意图范畴
在 Manifest 配置文件的权限配置下方添加如下配置
<queries>
<intent>
<action android:name="android.intent.action.MAIN"/>
</intent>
</queries>
混淆配置
在 proguard-rules.pro 文件中添加如下混淆规则
-keeppackagenames com.netease.nis.alivedetected
-keep class com.netease.nis.alivedetected.**{*;}
-dontwarn com.netease.nis.alivedetected.**
-keep class com.netease.cloud.nos.yidun.**{*;}
-dontwarn com.netease.cloud.nos.yidun.**
-keep class com.netease.htprotect.**{*;}
-keep class com.netease.mobsec.**{*;}
快速调用示例
在 layout 布局文件中使用活体检测相机预览 View
注意点
- 为了避免在某些中低端机型上检测卡顿,建议预览控件的宽与高不要设置为全屏,过大的预览控件会导致处理的数据过大,降低检测流畅度
- 预览宽高不要随意设置,请遵守大部分相机支持的预览宽高比,3:4 或 9:16
- 最好限制竖屏,横屏会影响效果
示例
<com.netease.nis.alivedetected.NISCameraPreview
android:id="@+id/surface_view"
android:layout_width="360dp"
android:layout_height="480dp" />
在代码中调用相对应 api 开启活体检测
public class DemoActivity extends AppCompatActivity {
private AliveDetector aliveDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
NISCameraPreview cameraPreview = findViewById(R.id.surface_view);
aliveDetector = AliveDetector.getInstance();
aliveDetector.init(this, cameraPreview, "申请的业务id");
aliveDetector.setDetectedListener(new DetectedListener() {
@Override
public void onReady(boolean isInitSuccess) {
}
@Override
public void onActionCommands(ActionType[] actionTypes) {
}
@Override
public void onStateTipChanged(ActionType actionType, String stateTip, int code) {
//单步动作 actionType.getActionID()为 0:正视前方 1:向右转头 2:向左转头 3:张嘴动作 4:眨眼动作 5:动作错误
6:动作通过
}
@Override
public void onPassed(boolean isPassed, String token) {
}
@Override
public void onCheck() {
}
@Override
public void onError(int code, String msg, String token) {
}
@Override
public void onOverTime() {
}
@Override
public void onBackgroundColor(int color) {
// RGB 活体模式下,根据 SDK 返回的颜色值更新检测页面背景颜色
}
});
aliveDetector.startDetect();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (isFinishing()) {
if (aliveDetector != null) {
aliveDetector.stopDetect();
aliveDetector.destroy();
}
}
}
}
更多使用场景请参考 demo
SDK 方法说明
1. 获取 AliveDetector 单例对象
代码说明
AliveDetector aliveDetector = AliveDetector.getInstance();
2. 初始化
代码说明
aliveDetector.init(Context context, NISCameraPreview cameraPreview, String businessId)
参数说明
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|---|---|---|---|---|
| context | Context | 是 | 无 | 上下文 |
| cameraPreview | NISCameraPreview | 是 | 无 | 相机预览 View |
| businessId | String | 是 | 无 | 活体检测业务 id |
3. 设置回调监听
代码说明
代码添加在 init 之后 startDetect 之前调用
aliveDetector.setDetectedListener(DetectedListener detectedListener)
参数说明
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|---|---|---|---|---|
| detectedListener | DetectedListener | 是 | 无 | 监听接口 |
DetectedListener 接口说明
public interface DetectedListener {
/**
* 活体检测引擎初始化时回调
*
* @param isInitSuccess 活体检测引擎是否初始化成功:
* 1)true,初始化完成可以开始检测
* 2)false,初始化失败,可尝试重新启动活体检测流程 {@link AliveDetector#startDetect()}
*/
void onReady(boolean isInitSuccess);
/**
* 此次活体检测下发的待检测动作指令序列,{@link ActionType}
*
* @param actionTypes
*/
void onActionCommands(ActionType[] actionTypes);
/**
* 活体检测状态是否改变,当引擎检测到状态改变时会回调该接口
*
* @param actionType 当前动作类型,枚举值,总共6种类型:
* ACTION_STRAIGHT_AHEAD("0", "正视前方"),
* ACTION_TURN_HEAD_TO_RIGHT("1", "向右转头"),
* ACTION_TURN_HEAD_TO_LEFT("2", "向左转头"),
* ACTION_OPEN_MOUTH("3", "张嘴动作"),
* ACTION_BLINK_EYES("4", "眨眼动作"),
* ACTION_ERROR("5", "动作错误"),
* ACTION_PASSED("6", "动作通过")
*
* @param stateTip 引擎检测到的实时状态
* @param code 错误码,在ACTION_ERROR时用于国际化使用(0:手机抖动,请保持稳定、1:请移动人脸到摄像头视野中间、2:环境光线暗、3:环境光线过亮、4:图像质量模糊、5:多人脸、6:距离太远、7:距离太近)
*/
void onStateTipChanged(ActionType actionType, String stateTip, int code);
/**
* 活体检测是否通过回调
*
* @param isPassed 活体检测是否通过,true:通过,false:不通过
* @param token 此次活体检测返回的易盾token
*/
void onPassed(boolean isPassed, String token);
/**
* 活体检测本地检测通过
* 启动远程检测
*/
void onCheck();
/**
* 活体检测过程中出现错误时回调
*
* @param code 错误码
* 1:sdk内部异常 2:服务端返回数据异常 3:上传图片异常
* @param msg 出错原因
*/
void onError(int code, String msg, String token);
/**
* 活体检测过程超时回调
*/
void onOverTime();
/**
* RGB 活体检测背景颜色变化回调
*
* @param color SDK 返回的背景颜色值
*/
void onBackgroundColor(int color);
}
onBackgroundColor 回调说明
RGB 活体模式会通过该回调返回检测页面需要展示的背景颜色。业务方收到回调后,应根据 color 更新活体检测页面的背景颜色。无 RGB 需求无需额外处理该回调。
4. 开始活体检测
代码添加在 init 之后调用
代码说明
aliveDetector.startDetect()
5. 停止活体检测
代码说明
可在onStop、onDestroy中调用
aliveDetector.stopDetect()
6. 释放资源(建议放在 onDestroy)
代码说明
aliveDetector.destroy()
7. 是否开启调试模式(非必须)
代码说明
aliveDetector.setDebugMode(boolean isDebug)
参数说明
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|---|---|---|---|---|
| isDebug | boolean | 是 | false | 是否打印日志 |
8. 设置检测动作灵敏度(非必须)
代码说明
aliveDetector.setSensitivity(int sensitivity)
参数说明
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|---|---|---|---|---|
| sensitivity | int | 是 | AliveDetector.SENSITIVITY_NORMAL | 可取值 AliveDetector.SENSITIVITY_EASY = 0、AliveDetector.SENSITIVITY_NORMAL = 1、AliveDetector.SENSITIVITY_HARD = 2 分别对应容易、普通、难 |
9. 设置超时时间(非必须)
代码添加在 startDetect 之前调用
代码说明
aliveDetector.setTimeOut(long timeout)
参数说明
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|---|---|---|---|---|
| timeout | long | 是 | 30000 | 单位毫秒 |
10. 设置域名(非必须)
用于海外域名失效的场景,可以设置私有化的域名列表,内部会自动切换
代码说明
aliveDetector.setHosts(String[] hosts)
参数说明
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|---|---|---|---|---|
| hosts | String[] | 是 | 无 | 多域名 |
11. 是否允许多人脸(非必须)
代码说明
aliveDetector.setAllowMultipleFace(boolean allowMultipleFace)
参数说明
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|---|---|---|---|---|
| allowMultipleFace | boolean | 是 | false | 是否允许多人脸 |
12. 设置设备抖动检测阈值(非必须)
值越小越灵敏
代码说明
aliveDetector.setShakeThreshold(int shakeThreshold)
参数说明
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|---|---|---|---|---|
| shakeThreshold | int | 是 | 35 | 抖动检测阈值 |
13. 设置人脸占比阈值(非必须)
代码说明
aliveDetector.setFaceThreshold(int faceThreshold)
参数说明
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|---|---|---|---|---|
| faceThreshold | int | 是 | 7 | 人脸占比阈值,范围7-50 |

