Android接入

本文介绍人脸保镖方案的Android端接入流程。

使用须知

重要
  • 为帮助落实针对您产品集成第三方SDK情况所应履行的隐私合规义务,降低隐私违规风险,进而实现您产品合规运营的业务目标,请您务必确保选用阿里云文档中心官网发布的最新版本产品。在使用人脸保镖前,请您务必仔细了解个人信息处理规定及《SDK隐私权政策》。

  • 人脸保镖单独集成方案的应用,依赖业务侧具备成熟的人脸识别算法和风险策略运营体系。建议您可以先和商务经理沟通评估业务场景匹配程度。

Android SDK使用限制如下:

  • 不支持模拟器。

  • 仅支持Android 4.4及以上系统版本的移动智能设备(手机或Pad)接入。

  • 目前支持 arm、armv7 和 arm64 三个架构。

接入步骤

前期准备

接入前需要进行权限配置和SDK依赖配置,您可以参考下面的步骤操作。

权限说明

为保证人脸作弊的识别效果,当前 SDK 需要以下权限:

权限内容

是否必选

备注

android.permission.INTERNET

保证 SDK 可以联网。

android.permission.ACCESS_NETWORK_STATE

用于获取设备网络状态信息。

android.permission.READ_PHONE_STATE

否(推荐赋予)

该部分权限在 Android 6.0 以上系统中需要动态获取。

说明

如果您要启用相关权限,那么在接入 SDK 并调用 initWithOptions 初始化接口之前,确保您的 App 已经被授予了相关权限。

android.permission.WRITE_EXTERNAL_STORAGE

否(推荐赋予)

android.permission.READ_EXTERNAL_STORAGE

否(推荐赋予)

依赖配置

  1. 下载 Android SDK(请联系商务经理获取),并解压。SDK 为 Android 标准的 .aar 包。

    说明
    • 单架构的 SO 文件在 2M 左右。

    • 人脸保镖 SDK 为了保证自身的抗逆向性以及数据在网络传输过程中的安全性,SDK 中有大量的插花、膨胀及加解密操作,所以 SDK 体积会相对较大。

  2. 拷贝解压后的 aar 文件到工程的 libs 目录下,并在 APP 的 build.gradle 中添加以下依赖关系:

    // 人脸保镖 SDK
    implementation(fileTree(dir: "libs", includes: ["*.aar"]))
    
    // 三方网络库依赖
    implementation 'com.squareup.okhttp3:okhttp:3.11.0'
    implementation 'com.squareup.okio:okio:1.14.0
重要

三方网络库不能省略,否则会造成人脸保镖 SDK 无法联网。

接口混淆配置(重要)

如果您的工程使用了代码混淆,请务必在App工程的proguard-rules.pro文件中添加如下配置信息,以防止接口被混淆处理后造成功能异常。

-keep class face.security.device.api.** {*;}
-dontwarn face.security.device.api.**

调用SDK

前期准备完成后,可按照下面三个步骤完成客户端接入。

  1. 初始化(initWithOptions)

  2. 获取客户端Token(getDeviceToken)

  3. 携带Token请求服务端

1. 初始化(initWithOptions)

SDK 内部初始化,在 App 启动的时候,您需要尽可能早地调用该函数 。

  • 函数原型

    public void initWithOptions(Context ctx, 
                           String userAppKey,
                           Map<String, String> options,
                           FaceSecInitListener securityInitListener);
  • 调用示例

    public class CustomApplication extends Application {
        private static String ALIYUN_APPKEY = "123e4567e89b12d3a45642661417****";
        @Override
        public void onCreate() {
            super.onCreate();
            // 初始化人脸保镖SDK,initWithOptions接口需要在APP启动尽可能早的时候调用。
            Map<String, String> options = new HashMap<>();
            options.put("IPv6", "0"); // 设置为IPv4
            options.put("DataSwitch", "0"); // 设置为初始化阶段采集
            FaceSecDevice.getInstance().initWithOptions(this, ALIYUN_APPKEY, options, null);
        }
    }
  • 参数说明

    • ctx:当前 Application Context,或 Activity Context。

    • userAppKey:用于标识用户身份,阿里云分配的AppKey,请联系商务经理获取。

      重要

      人脸保镖单独集成方案的应用,依赖业务侧具备成熟的人脸识别算法和风险策略运营体系。建议您可以先和商务经理沟通评估业务场景匹配程度。

    • options:信息采集可选项,默认可以为null。可选参数如下:

      字段名

      说明

      示例

      IPv6

      是否使用IPv6域名上报设备信息:

      • "0"(默认):否(使用IPv4域名)

      • "1":是(使用IPv6域名)

      "1"

      DataSwitch

      是否获取Token上报设备信息:

      • "0"(默认):否(初始化时上报)

      • "1":是(获取Token时上报)

      说明

      建议采用默认配置。

      "1"

    • securityInitListener:初始化回调监听接口,可在回调中判断初始化是否成功, 默认可以传入null。

      securityInitListener定义

      public interface FaceSecInitListener {
          // code表示接口调用状态码
          void onInitFinish(int code);
      }

      code 字段取值范围可参考code返回值

2. 获取客户端Token(getDeviceToken

获取客户端 token,并上报到业务自己的服务器,后续通过服务器端查询阿里云人脸保镖接口(DescribeFaceGuardRisk),从而获取客户端设备的风险识别信息。

重要
  • getDeviceToken 接口相对比较耗时,请务必在 APP 非主线程上调用,否则可能会引起 ANR 而导致 APP Crash。

  • 因为数据上报可能存在延迟,请确保 SDK 的 initWithOptions 接口和 getDeviceToken 接口调用时间间隔2秒以上

  • 调用 getDeviceToken 时建议传入 bizId,可以将本次 token 和业务唯一认证 ID 绑定,后在服务端查询结果时将ID一起传入,可进行防止Token被篡改的校验。

  • 调用示例

    new Thread() {
        @Override
        public void run() {
            // 推荐传入bizId,防止deviceToken被篡改。
            String bizId = "1234567890abcdef1234567890ab****";
            FaceSecToken deviceToken = FaceSecDevice.getInstance().getDeviceToken(bizId);
            if(null != deviceToken){
                if(FaceSecCode.SC_SUCCESS == deviceToken.code){
                    Log.d("AliyunFace", "token: " + deviceToken.token);
                } else {
                    Log.e("AliyunFace", "getDeviceToken error, code: " + deviceToken.code);
                }
            } else {
                Log.e("AliyunFace", "getDeviceToken is null.");
            }
        }
    }.start();
  • 参数

    bizId:客户的业务ID,可用于关联业务IDtoken。默认情况可以不传。

  • 返回值

    • FaceSecToken 类型,定义如下:

      public class FaceSecToken {
          // 接口调用状态码
          public int code;
          
          // 用于服务器端查询结果的token字符串。
          public String token;
      }
    • code:返回接口调用状态码,可用于判断接口调用是否成功。

      code返回值

      FaceSecCode

      Code

      备注

      SC_SUCCESS

      10000

      SDK初始化成功。

      SC_NOT_INIT

      10001

      SDK未初始化。

      SC_NOT_PERMISSION

      10002

      SDK需要的Android基础权限未完全授权。

      SC_UNKNOWN_ERROR

      10003

      系统未知错误。

      SC_NETWORK_ERROR

      10004

      网络错误。

      SC_NETWORK_ERROR_EMPTY

      10005

      网络错误,返回内容为空串。

      SC_NETWORK_ERROR_INVALID

      10006

      网络返回的格式非法。

      SC_PARSE_SRV_CFG_ERROR

      10007

      服务端配置解析失败。

      SC_NETWORK_RET_CODE_ERROR

      10008

      网关返回失败。

      SC_APPKEY_EMPTY

      10009

      AppKey为空。

      SC_PARAMS_ERROR

      10010

      其他参数错误。

      SC_FGKEY_ERROR

      10011

      密钥计算错误

      SC_APPKEY_ERROR

      10012

      APPKey 无效

    • token:返回 token 字符串信息,可用于业务后续查询阿里云人脸保镖接口。

      重要

      token 字符串在网络环境良好的场景下,长度为 600 字节左右;在网络环境较差的场景下,返回的长度在 2.5K 左右。

      如果业务上出现了大量长 token,首先请确保客户端的网络是畅通的;其次,请确保 SDK 的 initWithOptions 接口和 getDeviceToken 接口调用间隔在 2 秒以上。

3. 携带Token请求服务端

成功获取deviceToken(FaceSecToken.token)后,可携带此参数请求业务服务器,由服务端查询并校验结果。具体操作,请参见服务端API接口

完整代码示例

import face.security.device.api.FaceSecDevice;
import face.security.device.api.FaceSecInitListener;
import face.security.device.api.FaceSecToken;
import face.security.device.api.FaceSecCode;

public class MainActivity extends AppCompatActivity {
  private static String APPKEY_CHINA = "123e4567e89b12d3a45642661417****";
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      initSecurityDevice();
  }

  private void initSecurityDevice() {
      Map<String, String> options = new HashMap<>();
      options.put("IPv6", "0");
      options.put("DataSwitch", "0");
      FaceSecDevice.getInstance().initWithOptions(MainActivity.this,
              APPKEY_CHINA, options, null);

      // 建议延时2秒调用
      try {
          Thread.sleep(2000);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
      
      new Thread() {
          @Override
          public void run() {
              FaceSecToken st = FaceSecDevice.getInstance().getDeviceToken();
              if(null != st){
                  if(FaceSecCode.SC_SUCCESS == st.code){
                      Log.d("AliyunFaceGuard", "token: " + st.token);
                  } else {
                      Log.e("AliyunFaceGuard", "getDevicetoken error, code: " + st.code);
                  }
              } else {
                  Log.e("AliyunFaceGuard", "getDevicetoken is null.");
              }
          }
      }.start();
  }
}