Android SDK接入

本文档介绍如何使用阿里云IDaaSIFAA SDK for Android,涵盖SDK的集成方法、核心功能和使用示例,帮助开发者快速实现基于IFAA标准的本地生物特征认证功能。

概述

SDK & Demo 下载包内容说明

  1. SDK & Demo 主文件:包含核心开发工具包及示例代码,助您快速集成与测试。详情请参见SDK&Demo下载

  2. 认证服务SDK:提供完整的身份认证功能模块,支持多种验证方式,确保安全接入。

  3. AppSignGet.apk 工具:用于一键获取指定包名应用的签名信息,简化签名配置流程。详情请参见AppSignGet.apk

前期准备

准备工作

如果应用开启了手机号认证服务,请确保终端设备已经开启4G网络(联通、移动支持3G网络,但接口耗时会增加),手机号认证授权之后,联通电信可立即使用,移动需等待10分钟后使用。

接入流程

image.png

运行demo工程

  1. 解压Android Demo工程。

  2. 需要将包名、应用ID(appId)、应用密钥(appKey)、修改为正确的值。

  3. 修改FetchAccessTokenCallBackImpl.fetchAccessToken方法,完成获取应用授权token。

搭建开发环境

应用必须运行在Android 5.0+平台上,需要支持androidx, compileSdk 30+。

  1. 导入aar,将下载SDK拷贝到项目libs目录下。

    导入SDK

  2. 添加依赖。

    添加依赖

  3. 混淆忽略,若开启资源混淆,需要配置

    # etas 对外提供的类不被混淆
    -keep public class com.esandinfo.etas.ETASManager** { *; }
    -keep public class com.esandinfo.etas.EtasResult** { *; }
    -keep public class com.esandinfo.etas.IfaaBaseInfo {*;}
    -keep public class com.esandinfo.etas.IfaaBaseInfo$* {*;}
    -keep public class com.esandinfo.etas.IfaaCommon {*;}
    -keep public class com.esandinfo.etas.IfaaCommon$* {*;}
    -keep public class com.esandinfo.etas.model.json.** {*;}
    -keep public class com.esandinfo.etas.biz.** {*;}
    -keep public class com.esandinfo.etas.IfaaRequestBaseInfo {*;}
    -keep public class com.esandinfo.etas.callback.** {*;}
    -keep public class com.esandinfo.etas.utils.IfaaClient {*;}
    # ifaa 原始接⼝不被混淆
    -keep class org.ifaa.** {*;}
    # 保留所有的本地native⽅法不被混淆
    -keepclasseswithmembernames class * {
    native <methods>;
    }
    #号码认证配置
    -keep public class  R.drawable.authsdk*
    -keep public class  R.layout.authsdk*
    -keep public class  R.anim.authsdk*
    -keep public class  R.id.authsdk*
    -keep public class  R.string.authsdk*
    -keep public class  R.style.authsdk*
    #SDK不被混淆
    -keep class com.idsmanager.doraemonlibrary.** {*;}
  4. 权限添加。

    <uses-permission android:name="android.permission.INTERNET" />   <!--网络权限-->
    <uses-permission android:name="android.permission.USE_FINGERPRINT" />   <!--指纹权限-->
    <uses-permission android:name="android.permission.MANAGE_FINGERPRINT" />  <!--指纹管理权限-->
    <uses-permission android:name="cn.org.ifaa.permission.USE_IFAA_MANAGER" />    <!--⼈脸权限-->
    <uses-permission android:name="android.permission.USE_FACERECOGNITION" />
    <uses-permission android:name="oppo.permission.USE_FACE" /> <!--个别⼚商⼈脸权限-->
    <uses-permission android:name="android.permission.CAMERA" /><!--相机权限,需要⽤户进⾏授权-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- 检查wifi网络状态 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 检查网络状态 -->
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <!-- 切换网络通道 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 本地信息缓存 -->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- 开关Wi-Fi状态,解决中国机型移动网络权限问题需要 -->
  5. 网络权限配置,修改AndroidManifest.xml。

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        package="com.idsmanager.doraemondemoactivity">
    
    ...
    
      <application
           ...
            android:networkSecurityConfig="@xml/network_security_config"
           >
           ...
    
    </manifest>
  6. res目录下创建xml目录以及network_security_config.xml文件。

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <base-config cleartextTrafficPermitted="true" />
        <domain-config cleartextTrafficPermitted="true" >
            <domain includeSubdomains="true">enrichgw.10010.com</domain> <!-- 联通内部5G请求域名,开发者需要添加 -->
            <domain includeSubdomains="true">onekey.cmpassport.com</domain>  <!-- 移动内部请求域名,开发者需要添加 -->
    
        </domain-config>
    </network-security-config>
  7. 添加Activity 声明。在AndroidManifest.xml添加Activity声明。

            <!--联通电信授权页-->
            <!--如果不需要使用窗口模式,不要使用authsdk_activity_dialog主题,会出现异常动画-->
            <!--如果需要使用authsdk_activity_dialog主题,则screenOrientation一定不能指定明确的方向,
                比如portrait、sensorPortrait,在8.0的系统上不允许窗口模式指定orientation,会发生Crash,需要指定为behind,
                然后在授权页的前一个页面指定具体的orientation-->
            <!--  使用弹窗模式必须添加。-->
            <activity
                android:name="com.mobile.auth.gatewayauth.LoginAuthActivity"
                android:configChanges="orientation|keyboardHidden|screenSize"
                android:exported="false"
                android:launchMode="singleTop"
                android:theme="@style/authsdk_activity_dialog" />
            <!--二次弹窗界面-->
            <activity
                android:name="com.mobile.auth.gatewayauth.PrivacyDialogActivity"
                android:configChanges="orientation|keyboardHidden|screenSize"
                android:exported="false"
                android:launchMode="singleTop"
                android:screenOrientation="behind"
                android:theme="@style/authsdk_activity_dialog" />
            <!--协议页面webview-->
            <activity
                android:name="com.mobile.auth.gatewayauth.activity.AuthWebVeiwActivity"
                android:configChanges="orientation|keyboardHidden|screenSize"
                android:exported="false"
                android:launchMode="singleTop"
                android:screenOrientation="behind" />
        
  8. Support 包。

    1. androidx.appcompat:appcompat:1.3.1

    2. com.android.support.constraint:constraint-layout:1.0.2.或者更高版本。

  9. 获取app md5 签名值。使用Android studio gradle,点击signingReport,得到MD5签名值,将冒号去掉并转小写。

    说明

    debug包和release包签名是不一样的,避免用debug的签名值用于生产测试。

    111

SDK 调用说明

需要在APP中集成安全认证客户端SDK,并在服务端完成API对接。应用密钥和服务密钥获取请查看应用管理。

IFAA认证SDK方法说明

初始化

此接口需要开发者调用服务端SDK获取应用授权Token接口,自定义回调函数,然后通过FetchAccessTokenCallBackImpl回传给移动端SDK

/**
  * 初始化 DoraemonManager
  *
  * @param context
  * @param appId   应用密钥,找到安全认证应用,应用详情中拷贝 应用ID
  * @param appKey  应用密钥,找到安全认证应用,点击复制密钥
  * @param fetchAccessTokenCallBack 获取accessToken回调
*/
DoraemonManager.init(context, appId, appKey, new FetchAccessTokenCallBackImpl(), new DoraemonCallback() {
   @Override
   public void onFailure(Exception e) {
       Log.e(TAG, "DoraemonManager init faild", e);
       MainActivity.this.showToast("SDK初始化失败!" + e.getMessage());
   }

   @Override
   public void onSuccess(Object data) {
       Log.e(TAG, "DoraemonManager init success");
       MainActivity.this.showToast("SDK初始化成功!");
   }
});

FetchAccessTokenCallBackImpl 需要获取AccessToken后返回给SDK,示例如下

public class FetchAccessTokenCallBackImpl implements FetchAccessTokenCallBack {
    private static final String TAG = FetchAccessTokenCallBackImpl.class.getSimpleName();
    /**
     * 获取AccessToken回调方法
     *
     * @return
     */
    @Override
    public AccessTokenInfoResult fetchAccessToken(FetchAccessTokenRequest fetchAccessTokenRequest) {
        AccessTokenInfoResult callbackResult = new AccessTokenInfoResult();
        try {
            AccessTokenInfo accessTokenInfo =new AccessTokenInfo();
            /**
             * TODO:获取应用授权Token
             * 需要根据文档开发后端接口获取,获取后返回接口
             * Token必须是同步获取的
             * https://help.aliyun.com/zh/idaas/security-authentication/developer-reference/fetchaccesstoken?spm=a2c4g.11186623.0.i1
             */
            accessTokenInfo.setAccess_token(?);
            accessTokenInfo.setRefresh_token(?);
            accessTokenInfo.setExpires_in(?);
            callbackResult.setSuccess(true);
            callbackResult.setMessage("获取accessToken成功。");
            callbackResult.setAccessTokenInfo(accessTokenInfo);
        } catch (Exception e) {
            Log.e(TAG, "getAccessTokenRun exception", e);
            callbackResult.setSuccess(false);
            callbackResult.setMessage(e.getMessage());
        }
        return callbackResult;
    }
}

生物识别注册(指纹、人脸)

/**
  * 生物识别注册
  * @param ifaaAuthTypeEnum
  * @param userID
  * @param doraemonCallback
  */
DoraemonManager.ifaaRegist(IfaaBaseInfo.IFAAAuthTypeEnum.AUTHTYPE_FINGERPRINT, userID, new DoraemonCallback() {
     @Override
     public void onFailure(Exception e) {
         Log.e(TAG, "Finger regist faild", e);
         MainActivity.this.showToast("指纹注册失败!" + e.getMessage());
     }

     @Override
     public void onSuccess(Object data) {
         Log.e(TAG, "Finger regist success");
         MainActivity.this.showToast("指纹注册成功!" + data);
     }
});

生物识别登录(指纹、人脸)

/**
  * 生物识别登录
  *
  * @param ifaaAuthTypeEnum
  * @param userID
  * @param doraemonCallback
  */
DoraemonManager.ifaaLogin(IfaaBaseInfo.IFAAAuthTypeEnum.AUTHTYPE_FINGERPRINT, userID, new DoraemonCallback() {
     @Override
     public void onFailure(Exception e) {
         Log.e(TAG, "Finger login faild", e);
         if (e instanceof AppException) {
             MainActivity.this.showToast("指纹登录失败!code=" + ((AppException) e).getCode() + " message=" + e.getMessage());
         } else {
             MainActivity.this.showToast("指纹登录失败!" + e.getMessage());
         }
     }

    @Override
    public void onSuccess(Object data) {
          Log.e(TAG, "Finger login success");
          MainActivity.this.showToast("指纹登录成功!" + data);
    }
 });

获取支持的生物识别类型

/**
  * 获取支持的生物识别类型
  *
  * @param context 上下文
  * @return
*/
List<IfaaBaseInfo.IFAAAuthTypeEnum> supportBIOTypes = DoraemonManager.getSupportBIOTypes(MainActivity.this);

生物识别注销

/**
  * 生物识别注销
  * @param ifaaAuthTypeEnum 认证类型
  * @param userID 用户ID
  * @param doraemonCallback 回调方法
  */
DoraemonManager.ifaaCancelRegist(authtypeFingerprint, userID, new DoraemonCallback() {
     @Override
     public void onFailure(Exception e) {
          Log.e(TAG, "Finger regist faild", e);
          MainActivity.this.showToast("注销失败!" + e.getMessage());
     }
      @Override
      public void onSuccess(Object data) {
          Log.e(TAG, "Finger regist success");
          MainActivity.this.showToast("注销成功!" + data);
      }
});

获取SDK版本号

DoraemonManager.getVersion()

校验JwtToken

最后需要校验JwtToken来确保此次认证结果真实有效。