Android接入Advance.Ai活体检测 Api (安卓活体检测)
通过摄像头实时采集动态影像、识别人物面部表情,以此检测、验证用户的真实性与可靠性。
advance.ai 系统已针对印度尼西亚、印度、菲律宾、越南、泰国这五个国家市场的本地使用环境,定制开发了性能优化方案
活体检测前提:安卓系统相机授权可点击此链接学习
advance活体检测时序图UML 操作步骤梳理:
Request Url
https://api.advance.ai/openapi/liveness/v1/auth-license
POST (application/json)
Notes:
ADVANCE service is deployed overseas. If your test/official environment is in China, please request the service via VPN to avoid packet loss, service timeout and other problems
example
curl -X POST //请求方式
-H “X-ADVAI-KEY: {Your Access Key}” // 请求头header 加入 该参数 Advance Access Key
-H “Content-Type: application/json” //请求头header内容类型application/json
-d ‘{“licenseEffectiveSeconds”: 600}’ //applicationId如果加入会进行包名校验,默认不传
“https://api.advance.ai/openapi/liveness/v1/auth-license” // url
//该方法以及参数等后面有详细说明
GuardianLivenessDetectionSDK.init(getApplication(), Market.Indonesia); //印尼市场
//license参数通过步骤1获取
String checkResult = GuardianLivenessDetectionSDK.setLicenseAndCheck(license);//步骤一获取license参数
if ("SUCCESS".equals(checkResult)) {
// license 有效
checkPermissions(); //该方法是检测相机权限以及调用活体检测在下面8有
} else {// license 不可用,过期或者格式错误
Toast.makeText(MainActivity.this, checkResult, Toast.LENGTH_SHORT).show();
}
LivenessResult.isSuccess(); //是否成功
LivenessResult.getLivenessId(); //可以api加入参数来查看分数
LivenessResult.getLivenessBitmap(); //获取活体检测图像
Request URL
https://api.advance.ai/openapi/liveness/v3/detection-result
POST (application/json)
Request Parameters:
livenessId
resultType
(详细说明如下:)
//动作顺序 张嘴 眨眼 摇头...
// 第一个布尔值代表是否打乱传入的动作顺序,true 代表打乱顺序。 默认的动作顺序是 [眨眼]->[摇头]
GuardianLivenessDetectionSDK.setActionSequence(true,Detector.DetectionType.POS_YAW, Detector.DetectionType.MOUTH, Detector.DetectionType.BLINK);
https://www.advanceai.com.cn/cn/index/pageview/catid/122.html
https://in.advance.ai/
[ click (API Doc-> Liveness detection)
点击 (API文档->活体检测) ]
https://www.advance.ai/liveness-detection
Android接入AdvanceAI活体检测,通过摄像头实时采集检测详细说明如下:
3.0 Advance活性检测服务有三个步骤:
`
*步骤1:请求活动检测许可证授权以获得“许可证”
*步骤2:转到下载,下载Android或IOS SDK,将其集成到您的移动应用程序中,以进行活跃度检测,并将步骤1中获取的“许可证”作为请求参数
*步骤3:请求Liveness Detection,以步骤2返回的“livenessId”作为请求参数,获取Liveness分数及其对应的图像
`
官网参考:
活动检测许可证授权(步骤一)
Android or IOS(步骤二)
example Android sdk url address:SDK
(如果访问不了外网,可下载我上传csdn的SDK资源包 或 AndroidX SDK)
(个人免费csdn资源无需积分demo测试成功代码)
当下载完SDK后,可进行如下操作:
3.1 集成 SDK 到您的工程中
3.1.1 打开SDK文件夹,得到如下文件。
文件/文件夹名称 | 解释 |
---|---|
liveness | 集成活体检测功能的模块 |
android{
...
defaultConfig {
...
ndk {
abiFilters "armeabi","arm64-v8a","x86"
}
}
}
3.1.2 导入 liveness 模块到您的工程
导入模块时注意点说明:
①.liveness模块与app同级目录
②.livenness模块内的build.gradle下的vision版本记得更改
compileSdkVersion、targetSdkVersion等
③.app目录内的build.gradle下的dependencies依赖以及flatDir
加入:
repositories {
flatDir {
dirs project(':liveness').file('libs')
}
}
dependencies {
implementation project(":liveness")
}
④. 修改android目录下的setting.gradle文件,添加项目模块的引用
include ":liveness"
3.2 详细接入SDK说明
// 初始化方法不耗时,非必须在 application 中初始化,但要确保进入 LivenessActivity 之前完成调用
GuardianLivenessDetectionSDK.init(this,your market); // (Market的选择在下方可参考)
Market |
---|
Indonesia |
India |
Philippines |
Vietnam |
Thailand |
Malaysia |
Mexico |
Singapore |
Aksata |
Pakistan |
Nigeria |
CentralData |
最后一个参数 Market 是一个枚举类型,必须和您的账号所属国家的类别一致,否则无法通过授权。
String checkResult = GuardianLivenessDetectionSDK.setLicenseAndCheck(license);
if ("SUCCESS".equals(checkResult)) {
// license 有效
startLivenessActivity();
} else {
// license 不可用,过期/格式错误/appId未备案
}
SDK 默认不检查相机权限,如果您希望权限的申请交由 SDK 处理,可在 SDK 初始化方法调用后,调用如下方法,则 LivenessActivity 中会执行权限申请的操作:
GuardianLivenessDetectionSDK.letSDKHandleCameraPermission();
每次进行活体检测成功后,会返回唯一的 livenessId 和本次检测的 300*300 像素的清晰正面照片。
/**
* 请求状态码
*/
public static final int REQUEST_CODE_LIVENESS = xxxx;
/**
* 启动活体检测
*/
private void startLivenessActivity() {
Intent intent = new Intent(this, LivenessActivity.class);
startActivityForResult(intent, REQUEST_CODE_LIVENESS);
}
/**
1. 获取检测结果
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_LIVENESS) {
if (LivenessResult.isSuccess()) {// 活体检测成功
String livenessId = LivenessResult.getLivenessId();// 本次活体id
Bitmap livenessBitmap = LivenessResult.getLivenessBitmap();// 本次活体图片
} else {// 活体检测失败
String errorCode = LivenessResult.getErrorCode();// 失败错误码
String errorMsg = LivenessResult.getErrorMsg();// 失败原因
...
}
}
}
默认的动作顺序是 [眨眼]->[摇头],如需自定义动作顺序请参考如下代码:
在启动LivenessActivity页面前调用如下方法:
// 第一个布尔值代表是否打乱传入的动作顺序,true 代表打乱顺序。
GuardianLivenessDetectionSDK.setActionSequence(true,Detector.DetectionType.POS_YAW, Detector.DetectionType.MOUTH, Detector.DetectionType.BLINK);
您可以通过该方法将自己的用户唯一标识传给我们,我们会根据该标识建立映射关系。当遇到问题时,方便同我们进行日志追踪。
GuardianLivenessDetectionSDK.bindUser(String userId)
遮挡检测默认是关闭状态,如需开启遮挡检测,请在初始化SDK之后调用如下方法设置
GuardianLivenessDetectionSDK.isDetectOcclusion(true)
目前 SDK 支持中文,英文,印尼文,越南语,泰国语,印地语,西班牙语 七种语言/语音。根据手机当前语言自动切换,无需代码设置,如您仅支持一种语言,可自行删除其余国家的资源文件。
错误码 | 解释 |
---|---|
FACE_MISSING | 检测过程中人脸丢失 |
ACTION_TIMEOUT | 动作超时 |
MULTIPLE_FACE | 检测过程中出现多张人脸 |
MUCH_MOTION | 检测过程中动作幅度过大 |
AUTH_BAD_NETWORK | 授权请求网络失败 |
CHECKING_BAD_NETWORK | 动作结束后图像上传网络请求失败 |
DEVICE_NOT_SUPPORT | 该设备不支持活体检测 |
USER_GIVE_UP | 用户中途放弃检测 |
UNDEFINED | 未定义的其他错误类型 |
AUTH_PARAMETER_ERROR | 授权请求参数错误 |
AUTH_IAM_FAILED | 包名未备案 |
8.官方demo
package ai.advance.integration.demo;
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import com.blankj.utilcode.constant.PermissionConstants;
import com.blankj.utilcode.util.PermissionUtils;
import ai.advance.liveness.lib.GuardianLivenessDetectionSDK;
import ai.advance.liveness.lib.LivenessResult;
import ai.advance.liveness.lib.Market;
import ai.advance.liveness.sdk.activity.LivenessActivity;
public class MainActivity extends AppCompatActivity {
static final int REQUEST_CODE_LIVENESS = 1000;
private static final int PERMISSIONS_REQUEST_CODE = 1;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initKeyTypeButton();
initTicketButton();
initLicenseButton();
//相机权限授权
findViewById(R.id.key_type_button_camera).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "相机授权", Toast.LENGTH_SHORT).show();
//申请系统相机权限
startPreviewWithPermission();
}
});
}
private void startPreviewWithPermission() {
//权限申请
//PermissionUtils工具包权限类型:CAMERA相机
//callback回调监听授权或拒绝 onGranted 授权事件 onDenied否绝事件
PermissionUtils.permission(PermissionConstants.CAMERA)
.callback(new PermissionUtils.SimpleCallback() {
@Override
public void onGranted() {
try {
Toast.makeText(MainActivity.this, "相机授权申请成功", Toast.LENGTH_SHORT).show();
//申请成功后,可以调用相机拍摄/视频等操作
} catch (Exception ignored) {
Toast.makeText(MainActivity.this, "相机授权申请报错", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onDenied() {
//可以在此函数中调用 AlertDialog 提示用户相应操作等
Toast.makeText(MainActivity.this, "相机授权申请否决", Toast.LENGTH_SHORT).show();
}
}).request();
}
private void initLicenseButton() {
findViewById(R.id.license_type_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO 将此处的 license 修改
String license = null;
if (license == null) {
new AlertDialog.Builder(MainActivity.this).setMessage("请在 MainActivity 中给 license 赋值").setPositiveButton("确定", null).create().show();
} else {
boolean packageNamePass = checkPackageName();
if (packageNamePass) {
GuardianLivenessDetectionSDK.init(getApplication(), Market.Indonesia);
String checkResult = GuardianLivenessDetectionSDK.setLicenseAndCheck(license);
if ("SUCCESS".equals(checkResult)) {
// license 有效
checkPermissions();
} else {// license 不可用,过期或者格式错误
Toast.makeText(MainActivity.this, checkResult, Toast.LENGTH_SHORT).show();
}
}
}
}
});
}
private void initKeyTypeButton() {
findViewById(R.id.key_type_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//TODO 将此处的 key 修改为您的
String accessKey = "你的accessKey";
String secretKey = "你的secretKey";
Market market = Market.Indonesia;
if (accessKey == null || secretKey == null || market == null) {
new AlertDialog.Builder(MainActivity.this).setMessage("请在 MainActivity 中给 Key 赋值").setPositiveButton("确定", null).create().show();
} else {
boolean packageNamePass = checkPackageName();
if (packageNamePass) {
GuardianLivenessDetectionSDK.init(getApplication(), accessKey, secretKey, market);
checkPermissions();
}
}
}
});
}
private void initTicketButton() {
findViewById(R.id.ticket_type_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO 将此处的 ticket 修改
String ticket = null;
String queryId = null;
if (ticket == null) {
new AlertDialog.Builder(MainActivity.this).setMessage("请在 MainActivity 中给 ticket 赋值").setPositiveButton("确定", null).create().show();
} else {
GuardianLivenessDetectionSDK.init(getApplication(), Market.Indonesia);
GuardianLivenessDetectionSDK.setTicket(ticket);
GuardianLivenessDetectionSDK.setQueryId(queryId);
checkPermissions();
}
}
});
}
private boolean checkPackageName() {
if ("your.app.id".equals(getPackageName())) {
new AlertDialog.Builder(MainActivity.this).setMessage("请将 build.gradle 中的包名修改为您已备案的").setPositiveButton("确定", null).create().show();
return false;
}
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_LIVENESS:
// Call the following methods to get results
// String livenessId = LivenessResult.getLivenessId();
// Bitmap livenessBitmap = LivenessResult.getLivenessBitmap();
// String transactionId = LivenessResult.getTransactionId();
// boolean success = LivenessResult.isSuccess();
// String errorMsg = LivenessResult.getErrorMsg();
if (LivenessResult.isSuccess()) {
Toast.makeText(this, "Success", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, LivenessResult.getErrorCode(), Toast.LENGTH_SHORT).show();
}
break;
}
}
private boolean allPermissionsGranted() {
for (String permission : getRequiredPermissions()) {
if (ContextCompat.checkSelfPermission(this, permission)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/**
* Detect camera authorization
*/
public void checkPermissions() {
if (allPermissionsGranted()) {
onPermissionGranted();
} else {
ActivityCompat.requestPermissions(this, getRequiredPermissions(), PERMISSIONS_REQUEST_CODE);
}
}
public String[] getRequiredPermissions() {
return new String[]{Manifest.permission.CAMERA};
}
@Override
public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_REQUEST_CODE) {
//已授权
if (allGranted(grantResults)) {
onPermissionGranted();
} else {
onPermissionRefused();
}
}
}
/**
* Denied camera permissions
*/
public void onPermissionRefused() {
new AlertDialog.Builder(this).setMessage(getString(R.string.liveness_no_camera_permission)).setPositiveButton(getString(R.string.liveness_perform), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
}).create().show();
}
private boolean allGranted(int[] grantResults) {
boolean hasPermission = true;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
hasPermission = false;
}
}
return hasPermission;
}
/**
* Got camera permissions
*/
public void onPermissionGranted() {
Intent intent = new Intent(this, LivenessActivity.class);
//活体检测后回调至onActivityResult()
startActivityForResult(intent, REQUEST_CODE_LIVENESS);
}
}
9.个人亲自调试全部代码(成功)
个人免费无需积分资源demo代码下载全(https://download.csdn.net/download/mingketao/86503595)
注意advance密钥是要改为你自己的
package ai.advance.integration.demo;
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import ai.advance.liveness.lib.Detector;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.blankj.utilcode.constant.PermissionConstants;
import com.blankj.utilcode.util.PermissionUtils;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import ai.advance.liveness.lib.GuardianLivenessDetectionSDK;
import ai.advance.liveness.lib.LivenessResult;
import ai.advance.liveness.lib.Market;
import ai.advance.liveness.sdk.activity.LivenessActivity;
import okhttp3.Call;
public class MainActivity extends AppCompatActivity {
static final int REQUEST_CODE_LIVENESS = 1000;
private static final int PERMISSIONS_REQUEST_CODE = 1;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initKeyTypeButton();
initTicketButton();
initLicenseButton();
//相机权限授权
findViewById(R.id.key_type_button_camera).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "相机授权", Toast.LENGTH_SHORT).show();
//申请系统相机权限
startPreviewWithPermission();
}
});
}
private void startPreviewWithPermission() {
//权限申请
//PermissionUtils工具包权限类型:CAMERA相机
//callback回调监听授权或拒绝 onGranted 授权事件 onDenied否绝事件
PermissionUtils.permission(PermissionConstants.CAMERA)
.callback(new PermissionUtils.SimpleCallback() {
@Override
public void onGranted() {
try {
Toast.makeText(MainActivity.this, "相机授权申请成功", Toast.LENGTH_SHORT).show();
//申请成功后,可以调用相机拍摄/视频等操作
} catch (Exception ignored) {
Toast.makeText(MainActivity.this, "相机授权申请报错", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onDenied() {
//可以在此函数中调用 AlertDialog 提示用户相应操作等
Toast.makeText(MainActivity.this, "相机授权申请否决", Toast.LENGTH_SHORT).show();
}
}).request();
}
private void initLicenseButton() {
findViewById(R.id.license_type_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO 将此处的 license 修改
String license = "";
if (license == null) {
new AlertDialog.Builder(MainActivity.this).setMessage("请在 MainActivity 中给 license 赋值").setPositiveButton("确定", null).create().show();
} else {
boolean packageNamePass = checkPackageName();
if (packageNamePass) {
GuardianLivenessDetectionSDK.init(getApplication(), Market.Indonesia);
String checkResult = GuardianLivenessDetectionSDK.setLicenseAndCheck(license);
if ("SUCCESS".equals(checkResult)) {
// license 有效
checkPermissions();
} else {// license 不可用,过期或者格式错误
Toast.makeText(MainActivity.this, checkResult, Toast.LENGTH_SHORT).show();
}
}
}
}
});
}
private void initKeyTypeButton() {
findViewById(R.id.key_type_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//TODO 将此处的 key 修改为您的
String accessKey = "你的accessKey";
String secretKey = "你的secretKey";
Market market = Market.Indonesia;
if (accessKey == null || secretKey == null || market == null) {
new AlertDialog.Builder(MainActivity.this).setMessage("请在 MainActivity 中给 Key 赋值").setPositiveButton("确定", null).create().show();
} else {
boolean packageNamePass = checkPackageName();
if (packageNamePass) {
GuardianLivenessDetectionSDK.init(getApplication(), accessKey, secretKey, market);
checkPermissions();
}
}
}
});
}
private void initTicketButton() {
findViewById(R.id.ticket_type_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Map<String, String> params = new HashMap<>();
params.put("licenseEffectiveSeconds", "600");
String path = "https://api.advance.ai/openapi/liveness/v1/auth-license";
String json = "{\"licenseEffectiveSeconds\":\"600\"}";
Handler handler = new Handler() {};
http(handler, path, json, new HttpCallBack() {
@Override
public void onFinishi(String json) {
JSONObject jsonObject = JSONObject.parseObject(json);
String license = jsonObject.getJSONObject("data").get("license").toString();
if (license == null) {
new AlertDialog.Builder(MainActivity.this).setMessage(" Foto tidak dapat terdeteksi, silahkan ulangi").create().show();
} else {
GuardianLivenessDetectionSDK.init(getApplication(), Market.Indonesia);
//动作顺序 张嘴 眨眼 摇头...
// 第一个布尔值代表是否打乱传入的动作顺序,true 代表打乱顺序。 默认的动作顺序是 [眨眼]->[摇头]
GuardianLivenessDetectionSDK.setActionSequence(true, Detector.DetectionType.POS_YAW, Detector.DetectionType.MOUTH, Detector.DetectionType.BLINK);
String checkResult = GuardianLivenessDetectionSDK.setLicenseAndCheck(license);
if ("SUCCESS".equals(checkResult)) {
// license 有效
Intent intent = new Intent(MainActivity.this, LivenessActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent, REQUEST_CODE_LIVENESS);
} else {// license 不可用,过期或者格式错误
//Toast.makeText(AdvanceFaceActivity.this, checkResult, Toast.LENGTH_SHORT).show();
new AlertDialog.Builder(MainActivity.this).setMessage(" Foto tidak dapat terdeteksi, silahkan ulangi").create().show();
}
}
}
});
}
});
}
public static void http(final Handler handler, final String path, final String json, final HttpCallBack call){
new Thread(){
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Content-type","application/json");
//TODO 添加X-ADVAI-KEY
conn.setRequestProperty("X-ADVAI-KEY","需要添加你的key");
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
PrintWriter writer = new PrintWriter(conn.getOutputStream(),true);
writer.println(json);
writer.close();
BufferedReader br =new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));
final StringBuilder sb = new StringBuilder();
String l = "";
while( (l=br.readLine())!=null){
sb.append(l);
};
handler.post(new Runnable() {
@Override
public void run() {
call.onFinishi(sb.toString());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
private boolean checkPackageName() {
if ("com.ecreditpal.cashloan.indo".equals(getPackageName())) {
new AlertDialog.Builder(MainActivity.this).setMessage("请将 build.gradle 中的包名修改为您已备案的").setPositiveButton("确定", null).create().show();
return false;
}
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_LIVENESS:
// Call the following methods to get results
// String livenessId = LivenessResult.getLivenessId();
// Bitmap livenessBitmap = LivenessResult.getLivenessBitmap();
// String transactionId = LivenessResult.getTransactionId();
// boolean success = LivenessResult.isSuccess();
// String errorMsg = LivenessResult.getErrorMsg();
if (LivenessResult.isSuccess()) {
Toast.makeText(this, "Success", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, LivenessResult.getErrorCode(), Toast.LENGTH_SHORT).show();
}
break;
}
}
private boolean allPermissionsGranted() {
for (String permission : getRequiredPermissions()) {
if (ContextCompat.checkSelfPermission(this, permission)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/**
* Detect camera authorization
*/
public void checkPermissions() {
if (allPermissionsGranted()) {
onPermissionGranted();
} else {
ActivityCompat.requestPermissions(this, getRequiredPermissions(), PERMISSIONS_REQUEST_CODE);
}
}
public String[] getRequiredPermissions() {
return new String[]{Manifest.permission.CAMERA};
}
@Override
public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_REQUEST_CODE) {
//已授权
if (allGranted(grantResults)) {
onPermissionGranted();
} else {
onPermissionRefused();
}
}
}
/**
* Denied camera permissions
*/
public void onPermissionRefused() {
new AlertDialog.Builder(this).setMessage(getString(R.string.liveness_no_camera_permission)).setPositiveButton(getString(R.string.liveness_perform), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
}).create().show();
}
private boolean allGranted(int[] grantResults) {
boolean hasPermission = true;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
hasPermission = false;
}
}
return hasPermission;
}
/**
* Got camera permissions
*/
public void onPermissionGranted() {
Intent intent = new Intent(this, LivenessActivity.class);
//活体检测后回调至onActivityResult()
startActivityForResult(intent, REQUEST_CODE_LIVENESS);
}
}
10.问题解决
“no variants found for app”->解决方案下载android sdk28, 如下