Browse Source

提交类型 处理bug
提交内容 处理打卡地址微调的时候没有保存到地址的bug

Bitliker 7 years ago
parent
commit
f94af936aa
64 changed files with 3735 additions and 6 deletions
  1. 1 1
      WeiChat/src/main/res/layout/fragment_attendance.xml
  2. 3 3
      WeiChat/version.properties
  3. 2 2
      app_modular/appworks/src/main/java/com/uas/appworks/OA/erp/activity/WorkActivity.java
  4. 2 0
      app_modular/faceplatform-release/build.gradle
  5. BIN
      app_modular/faceplatform-release/faceplatform-release.aar
  6. 1 0
      app_modular/faceplatform-ui/.gitignore
  7. 30 0
      app_modular/faceplatform-ui/build.gradle
  8. BIN
      app_modular/faceplatform-ui/libs/ast.jar
  9. 17 0
      app_modular/faceplatform-ui/proguard-rules.pro
  10. 15 0
      app_modular/faceplatform-ui/src/main/AndroidManifest.xml
  11. 464 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceDetectActivity.java
  12. 495 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceLivenessActivity.java
  13. 243 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceVeriftyActivity.java
  14. 246 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceVeriftyLiveActivity.java
  15. 189 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/config/FaceConfig.java
  16. 54 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/model/FaceVerify.java
  17. 89 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/Base64.java
  18. 123 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/BrightnessTools.java
  19. 25 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/CameraUtils.java
  20. 130 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/DeviceUuidFactory.java
  21. 50 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/EncryptUtils.java
  22. 68 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/VolumeUtils.java
  23. 237 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/FaceDetectRoundView.java
  24. 20 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/FaceRoundView.java
  25. 20 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/FaceRoundView.java~HEAD
  26. 20 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/FaceRoundView.java~HEAD_0
  27. 243 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/VeriftyDialog.java
  28. 86 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/WaveHelper.java
  29. 334 0
      app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/WaveView.java
  30. BIN
      app_modular/faceplatform-ui/src/main/jniLibs/arm64-v8a/libFaceSDK.so
  31. BIN
      app_modular/faceplatform-ui/src/main/jniLibs/arm64-v8a/libidl_license.so
  32. BIN
      app_modular/faceplatform-ui/src/main/jniLibs/armeabi-v7a/libFaceSDK.so
  33. BIN
      app_modular/faceplatform-ui/src/main/jniLibs/armeabi-v7a/libidl_license.so
  34. BIN
      app_modular/faceplatform-ui/src/main/jniLibs/x86/libFaceSDK.so
  35. BIN
      app_modular/faceplatform-ui/src/main/jniLibs/x86/libidl_license.so
  36. 25 0
      app_modular/faceplatform-ui/src/main/res/drawable/bg_tips.xml
  37. 22 0
      app_modular/faceplatform-ui/src/main/res/drawable/bg_tips_no.xml
  38. 11 0
      app_modular/faceplatform-ui/src/main/res/drawable/round_top_transparent_bg.xml
  39. 107 0
      app_modular/faceplatform-ui/src/main/res/layout/activity_face_detect.xml
  40. 96 0
      app_modular/faceplatform-ui/src/main/res/layout/activity_face_detect_v3100.xml
  41. 107 0
      app_modular/faceplatform-ui/src/main/res/layout/activity_face_liveness.xml
  42. 95 0
      app_modular/faceplatform-ui/src/main/res/layout/activity_face_liveness_v3100.xml
  43. 40 0
      app_modular/faceplatform-ui/src/main/res/layout/activity_face_verifty.xml
  44. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xhdpi/bg_face_round.png
  45. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xhdpi/ic_bottom_uu.png
  46. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xhdpi/ic_close.png
  47. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xhdpi/ic_disable_sound.png
  48. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xhdpi/ic_enable_sound.png
  49. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_bottom_uu.png
  50. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_close_ext.png
  51. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_disable_sound_ext.png
  52. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_enable_sound_ext.png
  53. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_success.png
  54. BIN
      app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_warning.png
  55. BIN
      app_modular/faceplatform-ui/src/main/res/raw/detect_face_in.mp3
  56. BIN
      app_modular/faceplatform-ui/src/main/res/raw/face_good.mp3
  57. BIN
      app_modular/faceplatform-ui/src/main/res/raw/liveness_eye.mp3
  58. BIN
      app_modular/faceplatform-ui/src/main/res/raw/liveness_head_down.mp3
  59. BIN
      app_modular/faceplatform-ui/src/main/res/raw/liveness_head_left.mp3
  60. BIN
      app_modular/faceplatform-ui/src/main/res/raw/liveness_head_left_right.mp3
  61. BIN
      app_modular/faceplatform-ui/src/main/res/raw/liveness_head_right.mp3
  62. BIN
      app_modular/faceplatform-ui/src/main/res/raw/liveness_head_up.mp3
  63. BIN
      app_modular/faceplatform-ui/src/main/res/raw/liveness_mouth.mp3
  64. 25 0
      app_modular/faceplatform-ui/src/main/res/values/strings.xml

+ 1 - 1
WeiChat/src/main/res/layout/fragment_attendance.xml

@@ -16,7 +16,7 @@
     <com.core.widget.view.oacalender.CalenderView
         android:id="@+id/calender"
         android:layout_width="match_parent"
-        android:layout_height="210dp" />
+        android:layout_height="230dp" />
 
     <FrameLayout
         android:layout_width="match_parent"

+ 3 - 3
WeiChat/version.properties

@@ -1,5 +1,5 @@
-#Wed Jul 04 11:24:14 CST 2018
+#Thu Jul 05 10:10:46 CST 2018
 debugName=502
-versionName=634
+versionName=636
 debugCode=502
-versionCode=175
+versionCode=177

+ 2 - 2
app_modular/appworks/src/main/java/com/uas/appworks/OA/erp/activity/WorkActivity.java

@@ -21,7 +21,7 @@ import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 import com.afollestad.materialdialogs.MaterialDialog;
-import com.baidu.idl.face.platform.ui.FaceVeriftyActivity;
+import com.baidu.idl.face.platform.ui.FaceVeriftyLiveActivity;
 import com.baidu.mapapi.model.LatLng;
 import com.baidu.mapapi.search.core.PoiInfo;
 import com.common.data.CalendarUtil;
@@ -277,7 +277,7 @@ public class WorkActivity extends OABaseActivity implements View.OnClickListener
                     requestPermission(Manifest.permission.CAMERA, new Runnable() {
                         @Override
                         public void run() {
-                            startActivityForResult(new Intent(ct, FaceVeriftyActivity.class), 0x223);
+                            startActivityForResult(new Intent(ct, FaceVeriftyLiveActivity.class), 0x223);
                         }
                     }, new Runnable() {
                         @Override

+ 2 - 0
app_modular/faceplatform-release/build.gradle

@@ -0,0 +1,2 @@
+configurations.maybeCreate("default")
+artifacts.add("default", file('faceplatform-release.aar'))

BIN
app_modular/faceplatform-release/faceplatform-release.aar


+ 1 - 0
app_modular/faceplatform-ui/.gitignore

@@ -0,0 +1 @@
+/build

+ 30 - 0
app_modular/faceplatform-ui/build.gradle

@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 Baidu, Inc. All Rights Reserved.
+ */
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion rootProject.ext.android.compileSdkVersion
+    buildToolsVersion rootProject.ext.android.buildToolsVersion
+
+    defaultConfig {
+        minSdkVersion rootProject.ext.android.minSdkVersion
+        targetSdkVersion rootProject.ext.android.targetSdkVersion
+        versionCode 1
+        versionName "1.0"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    compile project(':apputils')
+    compile project(path: ':faceplatform-release')
+}

BIN
app_modular/faceplatform-ui/libs/ast.jar


+ 17 - 0
app_modular/faceplatform-ui/proguard-rules.pro

@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/baidu/Documents/android/android_sdk_mac/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific detect_keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}

+ 15 - 0
app_modular/faceplatform-ui/src/main/AndroidManifest.xml

@@ -0,0 +1,15 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.baidu.idl.face.platform.ui">
+
+    <application android:label="@string/app_name">
+
+
+        <activity
+            android:name=".FaceVeriftyLiveActivity"
+            android:label="刷脸打卡" />
+        <activity
+            android:name=".FaceVeriftyActivity"
+            android:label="刷脸打卡" />
+    </application>
+
+</manifest>

+ 464 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceDetectActivity.java

@@ -0,0 +1,464 @@
+/**
+ * Copyright (C) 2017 Baidu Inc. All rights reserved.
+ */
+package com.baidu.idl.face.platform.ui;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.hardware.Camera;
+import android.media.AudioManager;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.baidu.aip.face.stat.Ast;
+import com.baidu.idl.face.platform.FaceConfig;
+import com.baidu.idl.face.platform.FaceSDKManager;
+import com.baidu.idl.face.platform.FaceStatusEnum;
+import com.baidu.idl.face.platform.IDetectStrategy;
+import com.baidu.idl.face.platform.IDetectStrategyCallback;
+import com.baidu.idl.face.platform.ui.utils.CameraUtils;
+import com.baidu.idl.face.platform.ui.utils.VolumeUtils;
+import com.baidu.idl.face.platform.ui.widget.FaceDetectRoundView;
+import com.baidu.idl.face.platform.utils.APIUtils;
+import com.baidu.idl.face.platform.utils.CameraPreviewUtils;
+import com.modular.apputils.activity.BaseNetActivity;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 人脸采集接口
+ */
+public abstract class FaceDetectActivity extends BaseNetActivity implements
+        SurfaceHolder.Callback,
+        Camera.PreviewCallback,
+        Camera.ErrorCallback,
+        VolumeUtils.VolumeCallback,
+        IDetectStrategyCallback {
+
+
+    // View
+    protected FrameLayout mFrameLayout;
+    protected SurfaceView mSurfaceView;
+    protected SurfaceHolder mSurfaceHolder;
+    protected TextView mTipsTopView;
+    protected FaceDetectRoundView mFaceDetectRoundView;
+
+
+    // 人脸信息
+    protected FaceConfig mFaceConfig;
+    protected IDetectStrategy mIDetectStrategy;
+    // 显示Size
+    private Rect mPreviewRect = new Rect();
+    protected int mDisplayWidth = 0;
+    protected int mDisplayHeight = 0;
+    protected int mSurfaceWidth = 0;
+    protected int mSurfaceHeight = 0;
+    protected Drawable mTipsIcon;
+    // 状态标识
+    protected volatile boolean mIsEnableSound = true;
+    protected boolean mIsCreateSurface = false;
+    protected volatile boolean mIsCompletion = false;
+    // 相机
+    protected Camera mCamera;
+    protected Camera.Parameters mCameraParam;
+    protected int mCameraId;
+    protected int mPreviewWidth;
+    protected int mPreviewHight;
+    protected int mPreviewDegree;
+    // 监听系统音量广播
+    protected BroadcastReceiver mVolumeReceiver;
+
+
+    @Override
+    protected int getLayoutId() {
+        return R.layout.activity_face_verifty;
+    }
+
+    @Override
+    public void preOnCreacte() {
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        Ast.getInstance().init(getApplicationContext(), "3.1.0.0", "facenormal");
+    }
+    @Override
+    protected void init() throws Exception {
+        DisplayMetrics dm = new DisplayMetrics();
+        Display display = this.getWindowManager().getDefaultDisplay();
+        display.getMetrics(dm);
+        mDisplayWidth = dm.widthPixels;
+        mDisplayHeight = dm.heightPixels;
+        com.baidu.idl.face.platform.ui.config.FaceConfig.initializeResId();
+        mFaceConfig = FaceSDKManager.getInstance().getFaceConfig();
+
+        AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+        int vol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
+        mIsEnableSound = vol > 0 ? mFaceConfig.isSound : false;
+
+        mFrameLayout =findViewById(R.id.liveness_surface_layout);
+        mFaceDetectRoundView = findViewById(R.id.liveness_face_round);
+        mTipsTopView = findViewById(R.id.liveness_top_tips);
+
+
+        mSurfaceView = new SurfaceView(this);
+        mSurfaceHolder = mSurfaceView.getHolder();
+        mSurfaceHolder.setSizeFromLayout();
+        mSurfaceHolder.addCallback(this);
+        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+
+        int w = mDisplayWidth;
+        int h = mDisplayHeight;
+
+        FrameLayout.LayoutParams cameraFL = new FrameLayout.LayoutParams(
+                (int) (w * FaceDetectRoundView.SURFACE_RATIO), (int) (h * FaceDetectRoundView.SURFACE_RATIO),
+                Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
+
+        mSurfaceView.setLayoutParams(cameraFL);
+        mFrameLayout.addView(mSurfaceView);
+
+
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        setVolumeControlStream(AudioManager.STREAM_MUSIC);
+        mVolumeReceiver = VolumeUtils.registerVolumeReceiver(this, this);
+        if (mTipsTopView != null) {
+            mTipsTopView.setText(R.string.detect_face_in);
+        }
+        startPreview();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        stopPreview();
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        VolumeUtils.unRegisterVolumeReceiver(this, mVolumeReceiver);
+        mVolumeReceiver = null;
+        if (mIDetectStrategy != null) {
+            mIDetectStrategy.reset();
+        }
+        stopPreview();
+        Ast.getInstance().immediatelyUpload();
+    }
+
+
+    @Override
+    public void volumeChanged() {
+        try {
+//            AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
+//            if (am != null) {
+//                int cv = am.getStreamVolume(AudioManager.STREAM_MUSIC);
+//                mIsEnableSound = cv > 0;
+//
+//                if (mIDetectStrategy != null) {
+//                    mIDetectStrategy.setDetectStrategySoundEnable(mIsEnableSound);
+//                }
+//            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private Camera open() {
+        Camera camera;
+        int numCameras = Camera.getNumberOfCameras();
+        if (numCameras == 0) {
+            return null;
+        }
+
+        int index = 0;
+        while (index < numCameras) {
+            Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
+            Camera.getCameraInfo(index, cameraInfo);
+            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+                break;
+            }
+            index++;
+        }
+
+        if (index < numCameras) {
+            camera = Camera.open(index);
+            mCameraId = index;
+        } else {
+            camera = Camera.open(0);
+            mCameraId = 0;
+        }
+        return camera;
+    }
+
+    protected void startPreview() {
+        if (mSurfaceView != null && mSurfaceView.getHolder() != null) {
+            mSurfaceHolder = mSurfaceView.getHolder();
+            mSurfaceHolder.addCallback(this);
+        }
+
+        if (mCamera == null) {
+            try {
+                mCamera = open();
+            } catch (RuntimeException e) {
+                e.printStackTrace();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        if (mCamera == null) {
+            return;
+        }
+        if (mCameraParam == null) {
+            mCameraParam = mCamera.getParameters();
+        }
+
+        mCameraParam.setPictureFormat(PixelFormat.JPEG);
+        int degree = displayOrientation(this);
+        mCamera.setDisplayOrientation(degree);
+        // 设置后无效,camera.setDisplayOrientation方法有效
+        mCameraParam.set("rotation", degree);
+        mPreviewDegree = degree;
+        if (mIDetectStrategy != null) {
+            mIDetectStrategy.setPreviewDegree(degree);
+        }
+
+        Point point = CameraPreviewUtils.getBestPreview(mCameraParam,
+                new Point(mDisplayWidth, mDisplayHeight));
+        mPreviewWidth = point.x;
+        mPreviewHight = point.y;
+        // Preview 768,432
+        mPreviewRect.set(0, 0, mPreviewHight, mPreviewWidth);
+
+        mCameraParam.setPreviewSize(mPreviewWidth, mPreviewHight);
+        mCamera.setParameters(mCameraParam);
+
+        try {
+            mCamera.setPreviewDisplay(mSurfaceHolder);
+            mCamera.stopPreview();
+            mCamera.setErrorCallback(this);
+            mCamera.setPreviewCallback(this);
+            mCamera.startPreview();
+        } catch (RuntimeException e) {
+            e.printStackTrace();
+            CameraUtils.releaseCamera(mCamera);
+            mCamera = null;
+        } catch (Exception e) {
+            e.printStackTrace();
+            CameraUtils.releaseCamera(mCamera);
+            mCamera = null;
+        }
+
+    }
+
+    protected void stopPreview() {
+        if (mCamera != null) {
+            try {
+                mCamera.setErrorCallback(null);
+                mCamera.setPreviewCallback(null);
+                mCamera.stopPreview();
+            } catch (RuntimeException e) {
+                e.printStackTrace();
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                CameraUtils.releaseCamera(mCamera);
+                mCamera = null;
+            }
+        }
+        if (mSurfaceHolder != null) {
+            mSurfaceHolder.removeCallback(this);
+        }
+        if (mIDetectStrategy != null) {
+            mIDetectStrategy = null;
+        }
+    }
+
+    private int displayOrientation(Context context) {
+        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        int rotation = windowManager.getDefaultDisplay().getRotation();
+        int degrees = 0;
+        switch (rotation) {
+            case Surface.ROTATION_0:
+                degrees = 0;
+                break;
+            case Surface.ROTATION_90:
+                degrees = 90;
+                break;
+            case Surface.ROTATION_180:
+                degrees = 180;
+                break;
+            case Surface.ROTATION_270:
+                degrees = 270;
+                break;
+            default:
+                degrees = 0;
+                break;
+        }
+        int result = (0 - degrees + 360) % 360;
+        if (APIUtils.hasGingerbread()) {
+            Camera.CameraInfo info = new Camera.CameraInfo();
+            Camera.getCameraInfo(mCameraId, info);
+            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+                result = (info.orientation + degrees) % 360;
+                result = (360 - result) % 360;
+            } else {
+                result = (info.orientation - degrees + 360) % 360;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+        mIsCreateSurface = true;
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder,
+                               int format,
+                               int width,
+                               int height) {
+        mSurfaceWidth = width;
+        mSurfaceHeight = height;
+        if (holder.getSurface() == null) {
+            return;
+        }
+        startPreview();
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        mIsCreateSurface = false;
+    }
+
+    @Override
+    public void onPreviewFrame(byte[] data, Camera camera) {
+
+        if (mIsCompletion) {
+            return;
+        }
+        if (mIDetectStrategy == null && mFaceDetectRoundView != null && mFaceDetectRoundView.getRound() > 0) {
+            mIDetectStrategy = FaceSDKManager.getInstance().getDetectStrategyModule();
+            mIDetectStrategy.setPreviewDegree(mPreviewDegree);
+            mIDetectStrategy.setDetectStrategySoundEnable(mIsEnableSound);
+
+            Rect detectRect = FaceDetectRoundView.getPreviewDetectRect(mDisplayWidth, mPreviewHight, mPreviewWidth);
+            mIDetectStrategy.setDetectStrategyConfig(mPreviewRect, detectRect, this);
+        }
+        if (mIDetectStrategy != null) {
+            mIDetectStrategy.detectStrategy(data);
+        }
+    }
+
+
+
+    @Override
+    public void onError(int error, Camera camera) {
+    }
+
+    @Override
+    public void onDetectCompletion(FaceStatusEnum status, String message,
+                                   HashMap<String, String> base64ImageMap) {
+        if (mIsCompletion) {
+            return;
+        }
+        onRefreshView(status, message);
+        if (status == FaceStatusEnum.OK) {
+            Ast.getInstance().faceHit();
+            mIsCompletion = true;
+            saveImage(base64ImageMap);
+        }
+    }
+
+    private void onRefreshView(FaceStatusEnum status, String message) {
+        switch (status) {
+            case OK:
+            case Liveness_Completion:
+                onRefreshTipsView(false, message);
+                mFaceDetectRoundView.onRefreshSuccessView(true);
+                break;
+            case Detect_PitchOutOfUpMaxRange:
+            case Detect_PitchOutOfDownMaxRange:
+            case Detect_PitchOutOfLeftMaxRange:
+            case Detect_PitchOutOfRightMaxRange:
+                onRefreshTipsView(false, message);
+                mFaceDetectRoundView.onRefreshSuccessView(false);
+                break;
+            case Error_LivenessTimeout:
+            case Error_Timeout:
+            case Error_DetectTimeout:
+                errorTimeOut();
+                onRefreshTipsView(false, message);
+                break;
+            default:
+                onRefreshTipsView(false, message);
+                mFaceDetectRoundView.onRefreshSuccessView(false);
+        }
+    }
+
+    private void onRefreshTipsView(boolean isAlert, String message) {
+        mFaceDetectRoundView.onRefreshTipsView(message);
+//        if (isAlert) {
+//            if (mTipsIcon == null) {
+//                mTipsIcon = getResources().getDrawable(R.mipmap.ic_warning);
+//                mTipsIcon.setBounds(0, 0, (int) (mTipsIcon.getMinimumWidth() * 0.7f),
+//                        (int) (mTipsIcon.getMinimumHeight() * 0.7f));
+//                mTipsTopView.setCompoundDrawablePadding(15);
+//            }
+//            mTipsTopView.setBackgroundResource(R.drawable.bg_tips);
+//            mTipsTopView.setText(R.string.detect_standard);
+//            mTipsTopView.setCompoundDrawables(mTipsIcon, null, null, null);
+//        } else {
+//            mTipsTopView.setBackgroundResource(R.drawable.bg_tips_no);
+//            mTipsTopView.setCompoundDrawables(null, null, null, null);
+//            if (!TextUtils.isEmpty(message)) {
+//                mTipsTopView.setText(message);
+//            }
+//        }
+    }
+
+
+
+    private void saveImage(HashMap<String, String> imageMap) {
+        Set<Map.Entry<String, String>> sets = imageMap.entrySet();
+        for (Map.Entry<String, String> entry : sets) {
+            String bmpBase64 = entry.getValue();
+            if (!TextUtils.isEmpty(bmpBase64)) {
+                saveBmpBase64Ok(bmpBase64);
+                break;
+            }
+        }
+    }
+
+
+    /**
+     * 重新开启
+     */
+    public void reSetDetect() {
+        mIsCompletion = false;
+        mIDetectStrategy = null;
+        startPreview();
+    }
+
+    public abstract void saveBmpBase64Ok(String bmpBase64);
+
+    public abstract void errorTimeOut();
+
+}
+

+ 495 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceLivenessActivity.java

@@ -0,0 +1,495 @@
+/**
+ * Copyright (C) 2017 Baidu Inc. All rights reserved.
+ */
+package com.baidu.idl.face.platform.ui;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.hardware.Camera;
+import android.media.AudioManager;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.baidu.aip.face.stat.Ast;
+import com.baidu.idl.face.platform.FaceConfig;
+import com.baidu.idl.face.platform.FaceSDKManager;
+import com.baidu.idl.face.platform.FaceStatusEnum;
+import com.baidu.idl.face.platform.ILivenessStrategy;
+import com.baidu.idl.face.platform.ILivenessStrategyCallback;
+import com.baidu.idl.face.platform.ui.utils.CameraUtils;
+import com.baidu.idl.face.platform.ui.utils.VolumeUtils;
+import com.baidu.idl.face.platform.ui.widget.FaceDetectRoundView;
+import com.baidu.idl.face.platform.utils.APIUtils;
+import com.baidu.idl.face.platform.utils.Base64Utils;
+import com.baidu.idl.face.platform.utils.CameraPreviewUtils;
+import com.modular.apputils.activity.BaseNetActivity;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 活体检测接口
+ */
+public abstract class FaceLivenessActivity extends BaseNetActivity implements
+        SurfaceHolder.Callback,
+        Camera.PreviewCallback,
+        Camera.ErrorCallback,
+        VolumeUtils.VolumeCallback,
+        ILivenessStrategyCallback {
+
+    public static final String TAG = FaceLivenessActivity.class.getSimpleName();
+
+    // View
+    protected FrameLayout mFrameLayout;
+    protected SurfaceView mSurfaceView;
+    protected SurfaceHolder mSurfaceHolder;
+    protected TextView mTipsTopView;
+    protected FaceDetectRoundView mFaceDetectRoundView;
+
+    // 人脸信息
+    protected FaceConfig mFaceConfig;
+    protected ILivenessStrategy mILivenessStrategy;
+    // 显示Size
+    private Rect mPreviewRect = new Rect();
+    protected int mDisplayWidth = 0;
+    protected int mDisplayHeight = 0;
+    protected int mSurfaceWidth = 0;
+    protected int mSurfaceHeight = 0;
+    protected Drawable mTipsIcon;
+    // 状态标识
+    protected volatile boolean mIsEnableSound = true;
+    protected boolean mIsCreateSurface = false;
+    protected boolean mIsCompletion = false;
+    // 相机
+    protected Camera mCamera;
+    protected Camera.Parameters mCameraParam;
+    protected int mCameraId;
+    protected int mPreviewWidth;
+    protected int mPreviewHight;
+    protected int mPreviewDegree;
+    // 监听系统音量广播
+    protected BroadcastReceiver mVolumeReceiver;
+
+    @Override
+    public void preOnCreacte() {
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        Ast.getInstance().init(getApplicationContext(), "3.1.0.0", "facenormal");
+    }
+
+    @Override
+    protected int getLayoutId() {
+        return R.layout.activity_face_verifty;
+    }
+
+    @Override
+    protected void init() throws Exception {
+
+        DisplayMetrics dm = new DisplayMetrics();
+        Display display = this.getWindowManager().getDefaultDisplay();
+        display.getMetrics(dm);
+        mDisplayWidth = dm.widthPixels;
+        mDisplayHeight = dm.heightPixels;
+
+        com.baidu.idl.face.platform.ui.config.FaceConfig.initializeResId();
+        mFaceConfig = FaceSDKManager.getInstance().getFaceConfig();
+
+        AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+        int vol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
+        mIsEnableSound = vol > 0 ? mFaceConfig.isSound : false;
+
+        mFrameLayout = findViewById(R.id.liveness_surface_layout);
+        mFaceDetectRoundView = findViewById(R.id.liveness_face_round);
+        mTipsTopView = findViewById(R.id.liveness_top_tips);
+
+
+        mSurfaceView = new SurfaceView(this);
+        mSurfaceHolder = mSurfaceView.getHolder();
+        mSurfaceHolder.setSizeFromLayout();
+        mSurfaceHolder.addCallback(this);
+        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+
+        int w = mDisplayWidth;
+        int h = mDisplayHeight;
+
+        FrameLayout.LayoutParams cameraFL = new FrameLayout.LayoutParams(
+                (int) (w * FaceDetectRoundView.SURFACE_RATIO), (int) (h * FaceDetectRoundView.SURFACE_RATIO),
+                Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
+
+        mSurfaceView.setLayoutParams(cameraFL);
+        mFrameLayout.addView(mSurfaceView);
+
+
+    }
+
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        setVolumeControlStream(AudioManager.STREAM_MUSIC);
+        mVolumeReceiver = VolumeUtils.registerVolumeReceiver(this, this);
+        if (mTipsTopView != null) {
+            mTipsTopView.setText(R.string.detect_face_in);
+        }
+        startPreview();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        stopPreview();
+    }
+
+    @Override
+    public void onStop() {
+        if (mILivenessStrategy != null) {
+            mILivenessStrategy.reset();
+        }
+        VolumeUtils.unRegisterVolumeReceiver(this, mVolumeReceiver);
+        mVolumeReceiver = null;
+        super.onStop();
+        stopPreview();
+        Ast.getInstance().immediatelyUpload();
+    }
+
+    @Override
+    public void finish() {
+        super.finish();
+    }
+
+    @Override
+    public void volumeChanged() {
+        try {
+            AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
+            if (am != null) {
+//                int cv = am.getStreamVolume(AudioManager.STREAM_MUSIC);
+//                mIsEnableSound = cv > 0;
+//                mSoundView.setImageResource(mIsEnableSound
+//                        ? R.mipmap.ic_enable_sound_ext : R.mipmap.ic_disable_sound_ext);
+//                if (mILivenessStrategy != null) {
+//                    mILivenessStrategy.setLivenessStrategySoundEnable(mIsEnableSound);
+//                }
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private Camera open() {
+        Camera camera;
+        int numCameras = Camera.getNumberOfCameras();
+        if (numCameras == 0) {
+            return null;
+        }
+
+        int index = 0;
+        while (index < numCameras) {
+            Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
+            Camera.getCameraInfo(index, cameraInfo);
+            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+                break;
+            }
+            index++;
+        }
+
+        if (index < numCameras) {
+            camera = Camera.open(index);
+            mCameraId = index;
+        } else {
+            camera = Camera.open(0);
+            mCameraId = 0;
+        }
+        return camera;
+    }
+
+    protected void startPreview() {
+        if (mSurfaceView != null && mSurfaceView.getHolder() != null) {
+            mSurfaceHolder = mSurfaceView.getHolder();
+            mSurfaceHolder.addCallback(this);
+        }
+
+        if (mCamera == null) {
+            try {
+                mCamera = open();
+            } catch (RuntimeException e) {
+                e.printStackTrace();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        if (mCamera == null) {
+            return;
+        }
+
+        if (mCameraParam == null) {
+            mCameraParam = mCamera.getParameters();
+        }
+
+        mCameraParam.setPictureFormat(PixelFormat.JPEG);
+        int degree = displayOrientation(this);
+        mCamera.setDisplayOrientation(degree);
+        // 设置后无效,camera.setDisplayOrientation方法有效
+        mCameraParam.set("rotation", degree);
+        mPreviewDegree = degree;
+
+        Point point = CameraPreviewUtils.getBestPreview(mCameraParam,
+                new Point(mDisplayWidth, mDisplayHeight));
+
+        mPreviewWidth = point.x;
+        mPreviewHight = point.y;
+        // Preview 768,432
+
+        if (mILivenessStrategy != null) {
+            mILivenessStrategy.setPreviewDegree(degree);
+        }
+
+        mPreviewRect.set(0, 0, mPreviewHight, mPreviewWidth);
+
+        mCameraParam.setPreviewSize(mPreviewWidth, mPreviewHight);
+        mCamera.setParameters(mCameraParam);
+
+        try {
+            mCamera.setPreviewDisplay(mSurfaceHolder);
+            mCamera.stopPreview();
+            mCamera.setErrorCallback(this);
+            mCamera.setPreviewCallback(this);
+            mCamera.startPreview();
+        } catch (RuntimeException e) {
+            e.printStackTrace();
+            CameraUtils.releaseCamera(mCamera);
+            mCamera = null;
+        } catch (Exception e) {
+            e.printStackTrace();
+            CameraUtils.releaseCamera(mCamera);
+            mCamera = null;
+        }
+    }
+
+    protected void stopPreview() {
+        if (mCamera != null) {
+            try {
+                mCamera.setErrorCallback(null);
+                mCamera.setPreviewCallback(null);
+                mCamera.stopPreview();
+            } catch (RuntimeException e) {
+                e.printStackTrace();
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                CameraUtils.releaseCamera(mCamera);
+                mCamera = null;
+            }
+        }
+        if (mSurfaceHolder != null) {
+            mSurfaceHolder.removeCallback(this);
+        }
+        if (mILivenessStrategy != null) {
+            mILivenessStrategy = null;
+        }
+    }
+
+    private int displayOrientation(Context context) {
+        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        int rotation = windowManager.getDefaultDisplay().getRotation();
+        int degrees = 0;
+        switch (rotation) {
+            case Surface.ROTATION_0:
+                degrees = 0;
+                break;
+            case Surface.ROTATION_90:
+                degrees = 90;
+                break;
+            case Surface.ROTATION_180:
+                degrees = 180;
+                break;
+            case Surface.ROTATION_270:
+                degrees = 270;
+                break;
+            default:
+                degrees = 0;
+                break;
+        }
+        int result = (0 - degrees + 360) % 360;
+        if (APIUtils.hasGingerbread()) {
+            Camera.CameraInfo info = new Camera.CameraInfo();
+            Camera.getCameraInfo(mCameraId, info);
+            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+                result = (info.orientation + degrees) % 360;
+                result = (360 - result) % 360;
+            } else {
+                result = (info.orientation - degrees + 360) % 360;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+        mIsCreateSurface = true;
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder,
+                               int format,
+                               int width,
+                               int height) {
+        mSurfaceWidth = width;
+        mSurfaceHeight = height;
+        if (holder.getSurface() == null) {
+            return;
+        }
+        startPreview();
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        mIsCreateSurface = false;
+    }
+
+    @Override
+    public void onPreviewFrame(byte[] data, Camera camera) {
+
+        if (mIsCompletion) {
+            return;
+        }
+
+        if (mILivenessStrategy == null) {
+            mILivenessStrategy = FaceSDKManager.getInstance().getLivenessStrategyModule();
+            mILivenessStrategy.setPreviewDegree(mPreviewDegree);
+            mILivenessStrategy.setLivenessStrategySoundEnable(mIsEnableSound);
+
+            Rect detectRect = FaceDetectRoundView.getPreviewDetectRect(
+                    mDisplayWidth, mPreviewHight, mPreviewWidth);
+            mILivenessStrategy.setLivenessStrategyConfig(
+                    mFaceConfig.getLivenessTypeList(), mPreviewRect, detectRect, this);
+        }
+        mILivenessStrategy.livenessStrategy(data);
+    }
+
+    @Override
+    public void onError(int error, Camera camera) {
+    }
+
+    @Override
+    public void onLivenessCompletion(FaceStatusEnum status, String message,
+                                     HashMap<String, String> base64ImageMap) {
+        if (mIsCompletion) {
+            return;
+        }
+
+        onRefreshView(status, message);
+        if (status == FaceStatusEnum.OK) {
+            Ast.getInstance().faceHit();
+            mIsCompletion = true;
+            saveImage(base64ImageMap);
+        }
+    }
+
+    private void onRefreshView(FaceStatusEnum status, String message) {
+        switch (status) {
+            case OK:
+            case Liveness_OK:
+            case Liveness_Completion:
+                onRefreshTipsView(false, message);
+                mFaceDetectRoundView.onRefreshSuccessView(true);
+                break;
+            case Detect_DataNotReady:
+            case Liveness_Eye:
+            case Liveness_Mouth:
+            case Liveness_HeadUp:
+            case Liveness_HeadDown:
+            case Liveness_HeadLeft:
+            case Liveness_HeadRight:
+            case Liveness_HeadLeftRight:
+                onRefreshTipsView(false, message);
+                mFaceDetectRoundView.onRefreshSuccessView(false);
+                break;
+            case Detect_PitchOutOfUpMaxRange:
+            case Detect_PitchOutOfDownMaxRange:
+            case Detect_PitchOutOfLeftMaxRange:
+            case Detect_PitchOutOfRightMaxRange:
+                onRefreshTipsView(true, message);
+                mFaceDetectRoundView.onRefreshSuccessView(false);
+                break;
+            case Error_LivenessTimeout:
+            case Error_Timeout:
+            case Error_DetectTimeout:
+                errorTimeOut();
+                onRefreshTipsView(false, message);
+                break;
+            default:
+                onRefreshTipsView(false, message);
+                mFaceDetectRoundView.onRefreshSuccessView(false);
+        }
+    }
+
+
+    //提示信息
+    private void onRefreshTipsView(boolean isAlert, String message) {
+        mFaceDetectRoundView.onRefreshTipsView(message);
+
+        if (isAlert) {
+            if (mTipsIcon == null) {
+                mTipsIcon = getResources().getDrawable(R.mipmap.ic_warning);
+                mTipsIcon.setBounds(0, 0, (int) (mTipsIcon.getMinimumWidth() * 0.7f),
+                        (int) (mTipsIcon.getMinimumHeight() * 0.7f));
+                mTipsTopView.setCompoundDrawablePadding(15);
+            }
+//            mTipsTopView.setBackgroundResource(R.drawable.bg_tips);
+            mTipsTopView.setText(R.string.detect_standard);
+            mTipsTopView.setCompoundDrawables(mTipsIcon, null, null, null);
+        } else {
+//            mTipsTopView.setBackgroundResource(R.drawable.bg_tips_no);
+            mTipsTopView.setCompoundDrawables(null, null, null, null);
+            if (!TextUtils.isEmpty(message)) {
+                mTipsTopView.setText(message);
+            }
+        }
+    }
+
+
+    private void saveImage(HashMap<String, String> imageMap) {
+        Set<Map.Entry<String, String>> sets = imageMap.entrySet();
+        for (Map.Entry<String, String> entry : sets) {
+            String bmpBase64 = entry.getValue();
+            if (!TextUtils.isEmpty(bmpBase64)) {
+                saveBmpBase64Ok(bmpBase64);
+                break;
+            }
+        }
+    }
+
+    private static Bitmap base64ToBitmap(String base64Data) {
+        byte[] bytes = Base64Utils.decode(base64Data, Base64Utils.NO_WRAP);
+        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
+    }
+
+    /**
+     * 重新开启
+     */
+    public void reSetDetect() {
+        mIsCompletion = false;
+        mILivenessStrategy = null;
+        startPreview();
+    }
+
+    public abstract void saveBmpBase64Ok(String bmpBase64);
+
+    public abstract void errorTimeOut();
+
+}

+ 243 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceVeriftyActivity.java

@@ -0,0 +1,243 @@
+package com.baidu.idl.face.platform.ui;
+
+import android.text.TextUtils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baidu.idl.face.platform.ui.config.FaceConfig;
+import com.baidu.idl.face.platform.ui.model.FaceVerify;
+import com.baidu.idl.face.platform.ui.widget.VeriftyDialog;
+import com.common.LogUtil;
+import com.common.data.JSONUtil;
+import com.common.data.ListUtils;
+import com.core.app.MyApplication;
+import com.core.model.User;
+import com.core.utils.CommonUtil;
+import com.me.network.app.http.HttpClient;
+import com.me.network.app.http.Method;
+import com.me.network.app.http.rx.Result2Listener;
+import com.me.network.app.http.rx.ResultSubscriber;
+
+public class FaceVeriftyActivity extends  FaceDetectActivity{
+
+    @Override
+    protected String getBaseUrl() {
+        return "https://aip.baidubce.com/";
+    }
+
+
+    //成功获取到Base64数据
+    @Override
+    public void saveBmpBase64Ok(String bmpBase64) {
+        String master = CommonUtil.getEnuu(ct);
+        String imid = MyApplication.getInstance().getLoginUserId();
+        verify(bmpBase64, master, imid);
+    }
+
+    @Override
+    public void errorTimeOut() {
+        showErrorDialog(getString(R.string.detect_timeout));
+    }
+
+
+    private void showRegisterDialog(final String faceBase64, final String group_id_list, final String user_id) {
+        new VeriftyDialog.Builder(this)
+                .setCanceledOnTouchOutside(false)
+                .setContent("您未录入人脸照片,点击\"确认\"录入系统")
+                .build(new VeriftyDialog.OnDialogClickListener() {
+                    @Override
+                    public void result(boolean clickSure) {
+                        if (clickSure) {
+                            String company = CommonUtil.getSharedPreferences(ct, "erp_commpany");
+                            String master = CommonUtil.getSharedPreferences(ct, "Master_ch");
+                            String name = CommonUtil.getName();
+                            User user = MyApplication.getInstance().mLoginUser;
+                            String phone = null;
+                            if (user != null) {
+                                phone = user.getTelephone();
+                            }
+                            String userInfo = company + "_" + master + "_" + phone + "_" + name;//公司名_帐套名_电话_姓名
+                            register(faceBase64, group_id_list, user_id, userInfo);
+                        } else {
+                            setResult(0);
+                            finish();
+                        }
+                    }
+                });
+
+    }
+
+    /**
+     * 验证后返回弹出窗口
+     *
+     * @param message
+     */
+    private void showErrorRegister(final boolean isPass, final String message) {
+        new VeriftyDialog.Builder(this)
+                .setCanceledOnTouchOutside(false)
+                .setContent(message)
+                .setShowCancel(false)
+                .build(new VeriftyDialog.OnDialogClickListener() {
+                    @Override
+                    public void result(boolean clickSure) {
+                        if (isPass) {
+                            setResult(clickSure ? RESULT_OK : 0);
+                            finish();
+                        } else {
+                            setResult(0);
+                            finish();
+                        }
+                    }
+                });
+
+    }
+
+
+    //验证和注册错误
+    private void showErrorDialog(String result) {
+        String message = "";
+        if (result.contains("liveness check fail")) {
+            message = "不能拿照片骗我哦";
+        } else {
+            message = result;
+        }
+        new VeriftyDialog.Builder(this)
+                .setCanceledOnTouchOutside(false)
+                .setContent(message)
+                .setSureText("再试一次")
+                .setShowCancel(true)
+                .build(new VeriftyDialog.OnDialogClickListener() {
+                    @Override
+                    public void result(boolean clickSure) {
+                        if (clickSure) {
+                            reSetDetect();
+                        } else {
+                            finish();
+                        }
+                    }
+                });
+    }
+
+    /**
+     * 校验身份
+     *
+     * @param faceBase64    脸部信息
+     * @param group_id_list 组Id
+     * @param user_id       用户Id
+     */
+    private void verify(final String faceBase64, final String group_id_list, final String user_id) {
+        showProgress();
+        FaceConfig.loadToken(new FaceConfig.FaceTokenListener() {
+            @Override
+            public void callBack(String accessToken) {
+                LogUtil.i("gong", "accessToken=" + accessToken);
+                httpClient.Api().send(new HttpClient.Builder()
+                        .url("rest/2.0/face/v3/search")
+                        .add("access_token", accessToken)
+                        .header("Content-Type", "application/json")
+                        .add("image", faceBase64)
+                        .add("image_type", "BASE64")
+                        .add("liveness_control", "HIGH")//NORMAL
+                        .add("user_id", user_id)
+                        .isDebug(true)
+                        .add("group_id_list", group_id_list)
+                        .method(Method.POST).build(), new ResultSubscriber<>(new Result2Listener<Object>() {
+                    @Override
+                    public void onResponse(Object o) {
+                        LogUtil.i("gong", "verify onResponse=" + o.toString());
+                        try {
+                            JSONObject object = JSON.parseObject(o.toString());
+                            String error_msg = JSONUtil.getText(object, "error_msg");
+                            if (TextUtils.isEmpty(error_msg) || error_msg.equals("SUCCESS")) {
+                                JSONObject result = JSONUtil.getJSONObject(object, "result");
+                                JSONArray user_list = JSONUtil.getJSONArray(result, "user_list");
+                                if (ListUtils.isEmpty(user_list)) {
+                                    //没有注册时候
+                                    showRegisterDialog(faceBase64, group_id_list, user_id);
+                                } else {
+                                    FaceVerify mFaceVerify = new FaceVerify();
+                                    for (int i = 0; i < user_list.size(); i++) {
+                                        JSONObject userObject = user_list.getJSONObject(i);
+                                        float score = JSONUtil.getFloat(userObject, "score");
+                                        if (mFaceVerify.getScore() < score) {
+                                            mFaceVerify.setScore(score);
+                                            mFaceVerify.setUserId(JSONUtil.getText(userObject, "user_id"));
+                                            mFaceVerify.setUserInfo(JSONUtil.getText(userObject, "user_info"));
+                                            mFaceVerify.setGroupId(JSONUtil.getText(userObject, "group_id"));
+                                            if (mFaceVerify.isPass()) {
+                                                break;
+                                            }
+                                        }
+                                    }
+                                    if (mFaceVerify.isPass()) {
+                                        setResult(RESULT_OK);
+                                        finish();
+                                    } else {
+                                        showErrorDialog("抱歉,没认出你哦");
+                                    }
+                                }
+                            } else {
+                                showErrorDialog(error_msg);
+                            }
+                        } catch (Exception e) {
+                        }
+                        dismissProgress();
+                    }
+
+                    @Override
+                    public void onFailure(Object t) {
+                        dismissProgress();
+                        LogUtil.i("gong", "verify onFailure=" + t.toString());
+                    }
+                }));
+            }
+        });
+    }
+
+    private void register(final String faceBase64, final String group_id, final String user_id, final String user_info) {
+        showProgress();
+        FaceConfig.loadToken(new FaceConfig.FaceTokenListener() {
+            @Override
+            public void callBack(String accessToken) {
+                LogUtil.i("gong", "accessToken=" + accessToken);
+                httpClient.Api().send(new HttpClient.Builder()
+                        .url("rest/2.0/face/v3/faceset/user/add")
+                        .add("access_token", accessToken)
+                        .header("Content-Type", "application/json")
+                        .add("image", faceBase64)
+                        .add("image_type", "BASE64")
+                        .add("quality_control", "HIGH")
+                        .add("liveness_control", "NORMAL")
+                        .add("user_id", user_id)
+                        .add("user_info", user_info)
+                        .isDebug(true)
+                        .add("group_id", group_id)
+                        .method(Method.POST).build(), new ResultSubscriber<>(new Result2Listener<Object>() {
+                    @Override
+                    public void onResponse(Object o) {
+                        LogUtil.i("gong", "verify onResponse=" + o.toString());
+                        try {
+                            JSONObject object = JSON.parseObject(o.toString());
+                            String error_msg = JSONUtil.getText(object, "error_msg");
+                            if (TextUtils.isEmpty(error_msg) || error_msg.equals("SUCCESS")) {
+                                setResult(RESULT_OK);
+                                finish();
+                            } else {
+                                showErrorDialog(error_msg);
+                            }
+                        } catch (Exception e) {
+                        }
+                        dismissProgress();
+                    }
+
+                    @Override
+                    public void onFailure(Object t) {
+                        dismissProgress();
+                        LogUtil.i("gong", "verify onFailure=" + t.toString());
+                    }
+                }));
+            }
+        });
+    }
+}

+ 246 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceVeriftyLiveActivity.java

@@ -0,0 +1,246 @@
+package com.baidu.idl.face.platform.ui;
+
+import android.text.TextUtils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baidu.idl.face.platform.ui.config.FaceConfig;
+import com.baidu.idl.face.platform.ui.model.FaceVerify;
+import com.baidu.idl.face.platform.ui.widget.VeriftyDialog;
+import com.common.LogUtil;
+import com.common.data.JSONUtil;
+import com.common.data.ListUtils;
+import com.core.app.MyApplication;
+import com.core.model.User;
+import com.core.utils.CommonUtil;
+import com.me.network.app.http.HttpClient;
+import com.me.network.app.http.Method;
+import com.me.network.app.http.rx.Result2Listener;
+import com.me.network.app.http.rx.ResultSubscriber;
+
+public class FaceVeriftyLiveActivity extends FaceLivenessActivity {
+
+
+    @Override
+    protected String getBaseUrl() {
+        return "https://aip.baidubce.com/";
+    }
+
+
+    //成功获取到Base64数据
+    @Override
+    public void saveBmpBase64Ok(String bmpBase64) {
+        String master = CommonUtil.getEnuu(ct);
+        String imid = MyApplication.getInstance().getLoginUserId();
+        verify(bmpBase64, master, imid);
+    }
+
+    @Override
+    public void errorTimeOut() {
+        showErrorDialog(getString(R.string.detect_timeout));
+    }
+
+
+    private void showRegisterDialog(final String faceBase64, final String group_id_list, final String user_id) {
+        new VeriftyDialog.Builder(this)
+                .setCanceledOnTouchOutside(false)
+                .setContent("您未录入人脸照片,点击\"确认\"录入系统")
+                .build(new VeriftyDialog.OnDialogClickListener() {
+                    @Override
+                    public void result(boolean clickSure) {
+                        if (clickSure) {
+                            String company = CommonUtil.getSharedPreferences(ct, "erp_commpany");
+                            String master = CommonUtil.getSharedPreferences(ct, "Master_ch");
+                            String name = CommonUtil.getName();
+                            User user = MyApplication.getInstance().mLoginUser;
+                            String phone = null;
+                            if (user != null) {
+                                phone = user.getTelephone();
+                            }
+                            String userInfo = company + "_" + master + "_" + phone + "_" + name;//公司名_帐套名_电话_姓名
+                            register(faceBase64, group_id_list, user_id, userInfo);
+                        } else {
+                            setResult(0);
+                            finish();
+                        }
+                    }
+                });
+
+    }
+
+    /**
+     * 验证后返回弹出窗口
+     *
+     * @param message
+     */
+    private void showErrorRegister(final boolean isPass, final String message) {
+        new VeriftyDialog.Builder(this)
+                .setCanceledOnTouchOutside(false)
+                .setContent(message)
+                .setShowCancel(false)
+                .build(new VeriftyDialog.OnDialogClickListener() {
+                    @Override
+                    public void result(boolean clickSure) {
+                        if (isPass) {
+                            setResult(clickSure ? RESULT_OK : 0);
+                            finish();
+                        } else {
+                            setResult(0);
+                            finish();
+                        }
+                    }
+                });
+
+    }
+
+
+    //验证和注册错误
+    private void showErrorDialog(String result) {
+        String message = "";
+        if (result.contains("liveness check fail")) {
+            message = "不能拿照片骗我哦";
+        } else {
+            message = result;
+        }
+        new VeriftyDialog.Builder(this)
+                .setCanceledOnTouchOutside(false)
+                .setContent(message)
+                .setSureText("再试一次")
+                .setShowCancel(true)
+                .build(new VeriftyDialog.OnDialogClickListener() {
+                    @Override
+                    public void result(boolean clickSure) {
+                        if (clickSure) {
+                            reSetDetect();
+                        } else {
+                            finish();
+                        }
+                    }
+                });
+    }
+
+    /**
+     * 校验身份
+     *
+     * @param faceBase64    脸部信息
+     * @param group_id_list 组Id
+     * @param user_id       用户Id
+     */
+    private void verify(final String faceBase64, final String group_id_list, final String user_id) {
+        showProgress();
+        FaceConfig.loadToken(new FaceConfig.FaceTokenListener() {
+            @Override
+            public void callBack(String accessToken) {
+                LogUtil.i("gong", "accessToken=" + accessToken);
+                httpClient.Api().send(new HttpClient.Builder()
+                        .url("rest/2.0/face/v3/search")
+                        .add("access_token", accessToken)
+                        .header("Content-Type", "application/json")
+                        .add("image", faceBase64)
+                        .add("image_type", "BASE64")
+                        .add("liveness_control", "NORMAL")
+                        .add("user_id", user_id)
+                        .isDebug(true)
+                        .add("group_id_list", group_id_list)
+                        .method(Method.POST).build(), new ResultSubscriber<>(new Result2Listener<Object>() {
+                    @Override
+                    public void onResponse(Object o) {
+                        LogUtil.i("gong", "verify onResponse=" + o.toString());
+                        try {
+                            JSONObject object = JSON.parseObject(o.toString());
+                            String error_msg = JSONUtil.getText(object, "error_msg");
+                            if (TextUtils.isEmpty(error_msg) || error_msg.equals("SUCCESS")) {
+                                JSONObject result = JSONUtil.getJSONObject(object, "result");
+                                JSONArray user_list = JSONUtil.getJSONArray(result, "user_list");
+                                if (ListUtils.isEmpty(user_list)) {
+                                    //没有注册时候
+                                    showRegisterDialog(faceBase64, group_id_list, user_id);
+                                } else {
+                                    FaceVerify mFaceVerify = new FaceVerify();
+                                    for (int i = 0; i < user_list.size(); i++) {
+                                        JSONObject userObject = user_list.getJSONObject(i);
+                                        float score = JSONUtil.getFloat(userObject, "score");
+                                        if (mFaceVerify.getScore() < score) {
+                                            mFaceVerify.setScore(score);
+                                            mFaceVerify.setUserId(JSONUtil.getText(userObject, "user_id"));
+                                            mFaceVerify.setUserInfo(JSONUtil.getText(userObject, "user_info"));
+                                            mFaceVerify.setGroupId(JSONUtil.getText(userObject, "group_id"));
+                                            if (mFaceVerify.isPass()) {
+                                                break;
+                                            }
+                                        }
+                                    }
+                                    if (mFaceVerify.isPass()) {
+                                        setResult(RESULT_OK);
+                                        finish();
+                                    } else {
+                                        showErrorDialog("抱歉,没认出你哦");
+                                    }
+                                }
+                            } else {
+                                showErrorDialog(error_msg);
+                            }
+                        } catch (Exception e) {
+                        }
+                        dismissProgress();
+                    }
+
+                    @Override
+                    public void onFailure(Object t) {
+                        dismissProgress();
+                        LogUtil.i("gong", "verify onFailure=" + t.toString());
+                    }
+                }));
+            }
+        });
+    }
+
+    private void register(final String faceBase64, final String group_id, final String user_id, final String user_info) {
+        showProgress();
+        FaceConfig.loadToken(new FaceConfig.FaceTokenListener() {
+            @Override
+            public void callBack(String accessToken) {
+                LogUtil.i("gong", "accessToken=" + accessToken);
+                httpClient.Api().send(new HttpClient.Builder()
+                        .url("rest/2.0/face/v3/faceset/user/add")
+                        .add("access_token", accessToken)
+                        .header("Content-Type", "application/json")
+                        .add("image", faceBase64)
+                        .add("image_type", "BASE64")
+                        .add("quality_control", "NORMAL")
+                        .add("liveness_control", "NORMAL")
+                        .add("user_id", user_id)
+                        .add("user_info", user_info)
+                        .isDebug(true)
+                        .add("group_id", group_id)
+                        .method(Method.POST).build(), new ResultSubscriber<>(new Result2Listener<Object>() {
+                    @Override
+                    public void onResponse(Object o) {
+                        LogUtil.i("gong", "verify onResponse=" + o.toString());
+                        try {
+                            JSONObject object = JSON.parseObject(o.toString());
+                            String error_msg = JSONUtil.getText(object, "error_msg");
+                            if (TextUtils.isEmpty(error_msg) || error_msg.equals("SUCCESS")) {
+                                setResult(RESULT_OK);
+                                finish();
+                            } else {
+                                showErrorDialog(error_msg);
+                            }
+                        } catch (Exception e) {
+                        }
+                        dismissProgress();
+                    }
+
+                    @Override
+                    public void onFailure(Object t) {
+                        dismissProgress();
+                        LogUtil.i("gong", "verify onFailure=" + t.toString());
+                    }
+                }));
+            }
+        });
+    }
+
+
+}

+ 189 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/config/FaceConfig.java

@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2017 Baidu, Inc. All Rights Reserved.
+ */
+package com.baidu.idl.face.platform.ui.config;
+
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.baidu.idl.face.platform.FaceEnvironment;
+import com.baidu.idl.face.platform.FaceSDKManager;
+import com.baidu.idl.face.platform.FaceStatusEnum;
+import com.baidu.idl.face.platform.LivenessTypeEnum;
+import com.baidu.idl.face.platform.ui.R;
+import com.common.LogUtil;
+import com.common.config.BaseConfig;
+import com.common.data.JSONUtil;
+import com.me.network.app.http.HttpClient;
+import com.me.network.app.http.Method;
+import com.me.network.app.http.rx.Result2Listener;
+import com.me.network.app.http.rx.ResultSubscriber;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FaceConfig {
+    public static final float VALUE_BRIGHTNESS = 30.0F;
+    public static final float VALUE_BLURNESS = 0.7F;
+    public static final float VALUE_OCCLUSION = 0.6F;
+    public static final int VALUE_HEAD_PITCH = 15;
+    public static final int VALUE_HEAD_YAW = 15;
+    public static final int VALUE_HEAD_ROLL = 15;
+    public static final int VALUE_CROP_FACE_SIZE = 400;
+    public static final int VALUE_MIN_FACE_SIZE = 120;
+    public static final float VALUE_NOT_FACE_THRESHOLD = 0.6F;
+
+    // 为了apiKey,secretKey为您调用百度人脸在线接口的,如注册,识别等。
+    // 为了的安全,建议放在您的服务端,端把人脸传给服务器,在服务端端进行人脸注册、识别放在示例里面是为了您快速看到效果
+    public static String apiKey = "8B4k81ViOG3XWAoG4dDgSB2I";
+    public static String secretKey = "hryH0Lhmmt0yvGSXTveTwcMIRCA7rfIK";
+    public static String licenseID = "UUFaceID-face-android";
+    public static String licenseFileName = "idl-license.face-android";
+    public static String accessToken;
+
+    public static void initFace(Context context) {
+        FaceSDKManager.getInstance().initialize(context, licenseID, licenseFileName);
+        com.baidu.idl.face.platform.FaceConfig config = FaceSDKManager.getInstance().getFaceConfig();
+        // SDK初始化已经设置完默认参数(推荐参数),您也根据实际需求进行数值调整
+        // 设置活体动作,通过设置list LivenessTypeEnum.Eye,LivenessTypeEnum.Mouth,LivenessTypeEnum.HeadUp,
+        // LivenessTypeEnum.HeadDown,LivenessTypeEnum.HeadLeft, LivenessTypeEnum.HeadRight,
+        // LivenessTypeEnum.HeadLeftOrRight
+
+        //活体检测内容
+        List<LivenessTypeEnum> livenessList = new ArrayList<>();
+//        livenessList.add(LivenessTypeEnum.Mouth);//张嘴
+        livenessList.add(LivenessTypeEnum.Eye);//眼
+//        livenessList.add(LivenessTypeEnum.HeadUp);
+//        livenessList.add(LivenessTypeEnum.HeadDown);
+//        livenessList.add(LivenessTypeEnum.HeadLeft);
+//        livenessList.add(LivenessTypeEnum.HeadRight);
+        config.setLivenessTypeList(livenessList);
+        // 设置 活体动作是否随机 boolean
+        config.setLivenessRandom(true);
+        config.setLivenessRandomCount(Math.min(livenessList.size(), 2));
+        // 模糊度范围 (0-1) 推荐小于0.7
+        config.setBlurnessValue(VALUE_BLURNESS);
+        // 光照范围 (0-1) 推荐大于40
+        config.setBrightnessValue(VALUE_BRIGHTNESS);
+        // 裁剪人脸大小
+        config.setCropFaceValue(VALUE_CROP_FACE_SIZE);
+        // 人脸yaw,pitch,row 角度,范围(-45,45),推荐-15-15
+        config.setHeadPitchValue(VALUE_HEAD_PITCH);
+        config.setHeadRollValue(VALUE_HEAD_ROLL);
+        config.setHeadYawValue(VALUE_HEAD_YAW);
+        // 最小检测人脸(在图片人脸能够被检测到最小值)80-200, 越小越耗性能,推荐120-200
+        config.setMinFaceSize(VALUE_MIN_FACE_SIZE);
+        // 人脸置信度(0-1)推荐大于0.6
+        config.setNotFaceValue(VALUE_NOT_FACE_THRESHOLD);
+        // 人脸遮挡范围 (0-1) 推荐小于0.5
+        config.setOcclusionValue(VALUE_OCCLUSION);
+        // 是否进行质量检测
+        config.setCheckFaceQuality(false);
+        // 人脸检测使用线程数
+        config.setFaceDecodeNumberOfThreads(3);
+        // 是否开启提示音
+        config.setSound(false);
+
+        FaceSDKManager.getInstance().setFaceConfig(config);
+
+    }
+
+
+    public static void loadToken(FaceTokenListener mFaceTokenListener) {
+        if (mFaceTokenListener != null) {
+            if (!TextUtils.isEmpty(accessToken)) {
+                mFaceTokenListener.callBack(accessToken);
+            } else {
+                initToken(mFaceTokenListener);
+            }
+        }
+    }
+
+    public static void initToken(final FaceTokenListener mFaceTokenListener) {
+        HttpClient httpClient = new HttpClient.Builder("https://aip.baidubce.com/").isDebug(BaseConfig.isDebug())
+                .connectTimeout(5000)
+                .readTimeout(5000).build();
+        httpClient.Api().get(new HttpClient.Builder()
+                .add("grant_type", "client_credentials")
+                .add("client_id", apiKey)
+                .method(Method.GET)
+                .url("oauth/2.0/token")
+                .add("client_secret", secretKey).build(), new ResultSubscriber<>(new Result2Listener<Object>() {
+            @Override
+            public void onResponse(Object o) {
+                LogUtil.i("gong", "initToken onResponse=" + o.toString());
+                try {
+                    String message = o.toString();
+                    accessToken = JSONUtil.getText(message, "access_token");
+                    if (mFaceTokenListener != null) {
+                        mFaceTokenListener.callBack(accessToken);
+                    }
+                } catch (Exception e) {
+
+                }
+            }
+
+            @Override
+            public void onFailure(Object t) {
+                LogUtil.i("gong", "initToken onFailure=" + t.toString());
+            }
+        }));
+    }
+
+
+    public interface FaceTokenListener {
+        void callBack(String accessToken);
+    }
+
+
+    public static void initializeResId() {
+
+        // Sound Res Id
+        FaceEnvironment.setSoundId(FaceStatusEnum.Detect_NoFace, R.raw.detect_face_in);
+        FaceEnvironment.setSoundId(FaceStatusEnum.Detect_FacePointOut, R.raw.detect_face_in);
+        FaceEnvironment.setSoundId(FaceStatusEnum.Liveness_Eye, R.raw.liveness_eye);
+        FaceEnvironment.setSoundId(FaceStatusEnum.Liveness_Mouth, R.raw.liveness_mouth);
+        FaceEnvironment.setSoundId(FaceStatusEnum.Liveness_HeadUp, R.raw.liveness_head_up);
+        FaceEnvironment.setSoundId(FaceStatusEnum.Liveness_HeadDown, R.raw.liveness_head_down);
+        FaceEnvironment.setSoundId(FaceStatusEnum.Liveness_HeadLeft, R.raw.liveness_head_left);
+        FaceEnvironment.setSoundId(FaceStatusEnum.Liveness_HeadRight, R.raw.liveness_head_right);
+        FaceEnvironment.setSoundId(FaceStatusEnum.Liveness_HeadLeftRight, R.raw.liveness_head_left_right);
+        FaceEnvironment.setSoundId(FaceStatusEnum.Liveness_OK, R.raw.face_good);
+        FaceEnvironment.setSoundId(FaceStatusEnum.OK, R.raw.face_good);
+
+        // Tips Res Id
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_NoFace, R.string.detect_no_face);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_FacePointOut, R.string.detect_face_in);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_PoorIllumintion, R.string.detect_low_light);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_ImageBlured, R.string.detect_keep);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_OccLeftEye, R.string.detect_occ_face);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_OccRightEye, R.string.detect_occ_face);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_OccNose, R.string.detect_occ_face);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_OccMouth, R.string.detect_occ_face);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_OccLeftContour, R.string.detect_occ_face);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_OccRightContour, R.string.detect_occ_face);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_OccChin, R.string.detect_occ_face);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_PitchOutOfUpMaxRange, R.string.detect_head_down);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_PitchOutOfDownMaxRange, R.string.detect_head_up);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_PitchOutOfLeftMaxRange, R.string.detect_head_right);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_PitchOutOfRightMaxRange, R.string.detect_head_left);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_FaceZoomIn, R.string.detect_zoom_in);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Detect_FaceZoomOut, R.string.detect_zoom_out);
+
+        FaceEnvironment.setTipsId(FaceStatusEnum.Liveness_Eye, R.string.liveness_eye);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Liveness_Mouth, R.string.liveness_mouth);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Liveness_HeadUp, R.string.liveness_head_up);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Liveness_HeadDown, R.string.liveness_head_down);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Liveness_HeadLeft, R.string.liveness_head_left);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Liveness_HeadRight, R.string.liveness_head_right);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Liveness_HeadLeftRight, R.string.liveness_head_left_right);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Liveness_OK, R.string.liveness_good);
+        FaceEnvironment.setTipsId(FaceStatusEnum.OK, R.string.liveness_good);
+
+        FaceEnvironment.setTipsId(FaceStatusEnum.Error_Timeout, R.string.detect_timeout);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Error_DetectTimeout, R.string.detect_timeout);
+        FaceEnvironment.setTipsId(FaceStatusEnum.Error_LivenessTimeout, R.string.detect_timeout);
+    }
+
+}

+ 54 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/model/FaceVerify.java

@@ -0,0 +1,54 @@
+package com.baidu.idl.face.platform.ui.model;
+
+public class FaceVerify {
+    private final int SCORE_PASS = 85;
+
+    private String mpbBase64;
+    private String userId;
+    private String groupId;
+    private String userInfo;
+    private float score;
+
+    public String getMpbBase64() {
+        return mpbBase64;
+    }
+
+    public void setMpbBase64(String mpbBase64) {
+        this.mpbBase64 = mpbBase64;
+    }
+
+    public boolean isPass(){
+        return score>=SCORE_PASS;
+    }
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(String groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getUserInfo() {
+        return userInfo;
+    }
+
+    public void setUserInfo(String userInfo) {
+        this.userInfo = userInfo;
+    }
+
+    public float getScore() {
+        return score;
+    }
+
+    public void setScore(float score) {
+        this.score = score;
+    }
+}

+ 89 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/Base64.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 Baidu, Inc. All Rights Reserved.
+ */
+package com.baidu.idl.face.platform.ui.utils;
+
+/**
+ * Created by wangtianfei01 on 17/4/6.
+ */
+
+public class Base64 {
+
+    private static char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
+            .toCharArray();
+    private static byte[] codes = new byte[256];
+
+    public static char[] encode(byte[] data) {
+        char[] out = new char[((data.length + 2) / 3) * 4];
+        for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {
+            boolean quad = false;
+            boolean trip = false;
+            int val = (0xFF & (int) data[i]);
+            val <<= 8;
+            if ((i + 1) < data.length) {
+                val |= (0xFF & (int) data[i + 1]);
+                trip = true;
+            }
+            val <<= 8;
+            if ((i + 2) < data.length) {
+                val |= (0xFF & (int) data[i + 2]);
+                quad = true;
+            }
+            out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
+            val >>= 6;
+            out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
+            val >>= 6;
+            out[index + 1] = alphabet[val & 0x3F];
+            val >>= 6;
+            out[index + 0] = alphabet[val & 0x3F];
+        }
+        return out;
+    }
+
+    public static byte[] decode(char[] data) {
+        int len = ((data.length + 3) / 4) * 3;
+        if (data.length > 0 && data[data.length - 1] == '=') {
+            --len;
+        }
+        if (data.length > 1 && data[data.length - 2] == '=') {
+            --len;
+        }
+        byte[] out = new byte[len];
+        int shift = 0;
+        int accum = 0;
+        int index = 0;
+        for (int ix = 0; ix < data.length; ix++) {
+            int value = codes[data[ix] & 0xFF];
+            if (value >= 0) {
+                accum <<= 6;
+                shift += 6;
+                accum |= value;
+                if (shift >= 8) {
+                    shift -= 8;
+                    out[index++] = (byte) ((accum >> shift) & 0xff);
+                }
+            }
+        }
+        if (index != out.length) {
+            throw new Error("miscalculated data length!");
+        }
+        return out;
+    }
+
+    static {
+        for (int i = 0; i < 256; i++) {
+            codes[i] = -1;
+        }
+        for (int i = 'A'; i <= 'Z'; i++) {
+            codes[i] = (byte) (i - 'A');
+        }
+        for (int i = 'a'; i <= 'z'; i++) {
+            codes[i] = (byte) (26 + i - 'a');
+        }
+        for (int i = '0'; i <= '9'; i++) {
+            codes[i] = (byte) (52 + i - '0');
+        }
+        codes['+'] = 62;
+        codes['/'] = 63;
+    }
+}

+ 123 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/BrightnessTools.java

@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2017 Baidu, Inc. All Rights Reserved.
+ */
+package com.baidu.idl.face.platform.ui.utils;
+
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.util.Log;
+import android.view.WindowManager;
+
+
+public class BrightnessTools {
+
+    /**
+     * 判断是否开启了自动亮度调节
+     */
+
+    public static boolean isAutoBrightness(ContentResolver aContentResolver) {
+        boolean automicBrightness = false;
+        try {
+            automicBrightness = Settings.System.getInt(aContentResolver,
+                    Settings.System.SCREEN_BRIGHTNESS_MODE) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
+        } catch (SettingNotFoundException e) {
+            e.printStackTrace();
+        }
+        return automicBrightness;
+    }
+
+    /**
+     * 获取屏幕的亮度
+     *
+     * @param activity
+     * @return
+     */
+    public static int getScreenBrightness(Activity activity) {
+        int nowBrightnessValue = 0;
+        ContentResolver resolver = activity.getContentResolver();
+        try {
+            nowBrightnessValue = Settings.System.getInt(
+                    resolver, Settings.System.SCREEN_BRIGHTNESS);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return nowBrightnessValue;
+    }
+
+    /**
+     * 设置亮度
+     *
+     * @param activity
+     * @param brightness
+     */
+    public static void setBrightness(Activity activity, int brightness) {
+        // Settings.System.putInt(activity.getContentResolver(),
+
+        // Settings.System.SCREEN_BRIGHTNESS_MODE,
+
+        // Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+
+        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
+
+        lp.screenBrightness = Float.valueOf(brightness) * (1f / 255f);
+        Log.d("lxy", "set  lp.screenBrightness == " + lp.screenBrightness);
+
+        activity.getWindow().setAttributes(lp);
+    }
+
+    // 那么,能设置了,但是为什么还是会出现,设置了,没反映呢?
+
+    // 嘿嘿,那是因为,开启了自动调节功能了,那如何关闭呢?这才是最重要的:
+
+    /**
+     * 停止自动亮度调节
+     *
+     * @param activity
+     */
+    public static void stopAutoBrightness(Activity activity) {
+
+        Settings.System.putInt(activity.getContentResolver(),
+
+                Settings.System.SCREEN_BRIGHTNESS_MODE,
+
+                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+    }
+
+
+    /**
+     * 开启亮度自动调节
+     *
+     * @param activity
+     */
+    public static void startAutoBrightness(Activity activity) {
+
+        Settings.System.putInt(activity.getContentResolver(),
+
+                Settings.System.SCREEN_BRIGHTNESS_MODE,
+
+                Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+    }
+
+    // 至此,应该说操作亮度的差不多都有了,结束!
+    // 哎,本来认为是应该结束了,但是悲剧得是,既然像刚才那样设置的话,只能在当前的activity中有作用,一段退出的时候,会发现毫无作用,悲剧,原来是忘记了保存了。汗!
+
+    /**
+     * 保存亮度设置状态
+     *
+     * @param resolver
+     * @param brightness
+     */
+    public static void saveBrightness(ContentResolver resolver, int brightness) {
+        Uri uri = Settings.System
+                .getUriFor("screen_brightness");
+
+        Settings.System.putInt(resolver, "screen_brightness",
+                brightness);
+        // resolver.registerContentObserver(uri, true, myContentObserver);
+        resolver.notifyChange(uri, null);
+    }
+}

+ 25 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/CameraUtils.java

@@ -0,0 +1,25 @@
+/**
+ * Copyright (C) 2017 Baidu Inc. All rights reserved.
+ */
+package com.baidu.idl.face.platform.ui.utils;
+
+import android.hardware.Camera;
+
+/**
+ * CameraUtils
+ */
+public class CameraUtils {
+
+    public static final String TAG = CameraUtils.class.getSimpleName();
+
+    public static void releaseCamera(Camera camera) {
+        try {
+            camera.release();
+        } catch (RuntimeException e2) {
+            e2.printStackTrace();
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        } finally {
+        }
+    }
+}

+ 130 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/DeviceUuidFactory.java

@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2017 Baidu, Inc. All Rights Reserved.
+ */
+package com.baidu.idl.face.platform.ui.utils;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Environment;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.UUID;
+
+/**
+ * Created by wangtianfei01 on 17/4/6.
+ */
+
+public class DeviceUuidFactory {
+    protected static final String PREFS_FILE = "dev_id.xml";
+    protected static final String DEVICE_UUID_FILE_NAME = ".dev_id.txt";
+    protected static final String PREFS_DEVICE_ID = "dev_id";
+    protected static final String KEY = "cyril'98";
+    protected static UUID uuid;
+
+    public static String init(Context context) {
+        if (uuid == null) {
+            synchronized (DeviceUuidFactory.class) {
+                if (uuid == null) {
+                    final SharedPreferences prefs = context.getSharedPreferences(PREFS_FILE, 0);
+                    final String id = prefs.getString(PREFS_DEVICE_ID, null);
+                    if (id != null) {
+                        uuid = UUID.fromString(id);
+                    } else {
+                        if (recoverDeviceUuidFromSD() != null) {
+                            uuid = UUID.fromString(recoverDeviceUuidFromSD());
+                        } else {
+                            final String androidId =
+                                    Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
+                            try {
+                                if (!"9774d56d682e549c".equals(androidId)) {
+                                    uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
+                                    try {
+                                        saveDeviceUuidToSD(EncryptUtils.encryptDES(uuid.toString(), KEY));
+                                    } catch (Exception e) {
+                                        e.printStackTrace();
+                                    }
+                                } else {
+                                    @SuppressLint("MissingPermission") String deviceId = ((TelephonyManager) context
+                                            .getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
+                                    uuid = deviceId != null ? UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")) :
+                                            UUID.randomUUID();
+                                    try {
+                                        saveDeviceUuidToSD(EncryptUtils.encryptDES(uuid.toString(), KEY));
+                                    } catch (Exception e) {
+                                        e.printStackTrace();
+                                    }
+                                }
+                            } catch (UnsupportedEncodingException e) {
+                                throw new RuntimeException(e);
+                            }
+                        }
+                        prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString()).commit();
+                    }
+                }
+            }
+        }
+        return uuid.toString();
+    }
+
+    private static String recoverDeviceUuidFromSD() {
+        try {
+            String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath();
+            File dir = new File(dirPath);
+            File uuidFile = new File(dir, DEVICE_UUID_FILE_NAME);
+            if (!dir.exists() || !uuidFile.exists()) {
+                return null;
+            }
+            FileReader fileReader = new FileReader(uuidFile);
+            StringBuilder sb = new StringBuilder();
+            char[] buffer = new char[100];
+            int readCount;
+            while ((readCount = fileReader.read(buffer)) > 0) {
+                sb.append(buffer, 0, readCount);
+            }
+            // 通过UUID.fromString来检查uuid的格式正确性
+            UUID uuid = UUID.fromString(EncryptUtils.decryptDES(sb.toString(), KEY));
+            return uuid.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    private static void saveDeviceUuidToSD(String uuid) {
+        String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath();
+        File targetFile = new File(dirPath, DEVICE_UUID_FILE_NAME);
+        if (targetFile != null) {
+            if (targetFile.exists()) {
+                OutputStreamWriter osw;
+                try {
+                    osw = new OutputStreamWriter(new FileOutputStream(targetFile), "utf-8");
+                    try {
+                        osw.write(uuid);
+                        osw.flush();
+                        osw.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                } catch (UnsupportedEncodingException e) {
+                    e.printStackTrace();
+                } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+    }
+
+    public static UUID getUuid() {
+        return uuid;
+    }
+}

+ 50 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/EncryptUtils.java

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 Baidu, Inc. All Rights Reserved.
+ */
+package com.baidu.idl.face.platform.ui.utils;
+
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Created by wangtianfei01 on 17/4/6.
+ */
+
+public class EncryptUtils {
+    public static String encryptDES(String encryptString, String encryptKey) throws Exception {
+        // 返回实现指定转换的Cipher对象 "算法/模式/填充"
+        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
+        // 创建一个DESKeySpec对象,使用8个字节的key作为DES密钥的内容
+        DESKeySpec desKeySpec = new DESKeySpec(encryptKey.getBytes("UTF-8"));
+        // 返回转换指定算法的秘密密钥的SecretKeyFactory对象
+        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
+        // 根据提供的密钥生成SecretKey对象
+        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
+        // 使用iv中的字节作为iv来构造一个iv ParameterSpec对象。复制该缓冲区的内容来防止后续修改
+        IvParameterSpec iv = new IvParameterSpec(encryptKey.getBytes());
+        // 用密钥和一组算法参数初始化此 Cipher;Cipher:加密、解密、密钥包装或密钥解包,具体取决于 opmode 的值。
+        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
+        // 加密同时解码成字符串返回
+        return new String(Base64.encode(cipher.doFinal(encryptString.getBytes("UTF-8"))));
+    }
+
+    public static String decryptDES(String decodeString, String decodeKey) throws Exception {
+        // 使用指定密钥构造IV
+        IvParameterSpec iv = new IvParameterSpec(decodeKey.getBytes());
+        // 根据给定的字节数组和指定算法构造一个密钥。
+        SecretKeySpec skeySpec = new SecretKeySpec(decodeKey.getBytes(), "DES");
+        // 返回实现指定转换的 Cipher 对象
+        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
+        // 解密初始化
+        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
+        // 解码返回
+        byte[] byteMi = Base64.decode(decodeString.toCharArray());
+        byte[] decryptedData = cipher.doFinal(byteMi);
+        return new String(decryptedData);
+    }
+}

+ 68 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/VolumeUtils.java

@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2017 Baidu Inc. All rights reserved.
+ */
+package com.baidu.idl.face.platform.ui.utils;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.Log;
+
+/**
+ * VolumeUtils
+ * 描述:系统音量监听
+ */
+public class VolumeUtils {
+
+    public static final String TAG = VolumeUtils.class.getSimpleName();
+
+    public interface VolumeCallback {
+        void volumeChanged();
+    }
+
+    public static class VolumeReceiver extends BroadcastReceiver {
+
+        private VolumeCallback callback;
+
+        public VolumeReceiver(VolumeCallback cb) {
+            callback = cb;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals("android.media.VOLUME_CHANGED_ACTION")
+                    && callback != null) {
+                Log.e(TAG, "android.media.VOLUME_CHANGED_ACTION");
+                callback.volumeChanged();
+            }
+        }
+    }
+
+    public static BroadcastReceiver registerVolumeReceiver(Context context, VolumeCallback callback) {
+        VolumeReceiver mVolumeReceiver = null;
+        try {
+            mVolumeReceiver = new VolumeReceiver(callback);
+            IntentFilter filter = new IntentFilter();
+            filter.addAction("android.media.VOLUME_CHANGED_ACTION");
+            context.registerReceiver(mVolumeReceiver, filter);
+        } catch (IllegalArgumentException ex1) {
+            ex1.printStackTrace();
+        } catch (Exception ex2) {
+            ex2.printStackTrace();
+        }
+        return mVolumeReceiver;
+    }
+
+    public static void unRegisterVolumeReceiver(Context context, BroadcastReceiver receiver) {
+        try {
+            if (context != null && receiver != null) {
+                context.unregisterReceiver(receiver);
+            }
+        } catch (IllegalArgumentException ex1) {
+            ex1.printStackTrace();
+        } catch (Exception ex2) {
+            ex2.printStackTrace();
+        }
+    }
+}

+ 237 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/FaceDetectRoundView.java

@@ -0,0 +1,237 @@
+/**
+ * Copyright (C) 2017 Baidu Inc. All rights reserved.
+ */
+package com.baidu.idl.face.platform.ui.widget;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Typeface;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.baidu.idl.face.platform.ui.R;
+import com.baidu.idl.face.platform.utils.DensityUtils;
+import com.common.system.DisplayUtil;
+
+/**
+ * 人脸检测区域View
+ */
+public class FaceDetectRoundView extends View {
+
+    public static final float SURFACE_HEIGHT = 1000f;
+    public static final float SURFACE_RATIO = 0.75f;
+    public static final float WIDTH_SPACE_RATIO = 0.33f;
+    public static final float HEIGHT_RATIO = 0.1f;
+    public static final float HEIGHT_EXT_RATIO = 0.2f;
+    public static final int CIRCLE_SPACE = 2;
+    public static final int PATH_SPACE = 16;
+    public static final int PATH_SMALL_SPACE = 12;
+    public static final int PATH_WIDTH = 6;
+
+    public final int COLOR_BG = Color.parseColor("#FFFFFF");
+    public final int COLOR_RECT = COLOR_BG;
+    public final int COLOR_ROUND = Color.parseColor("#DCDCDC");
+    public final int COLOR_ROUND_PASS = Color.parseColor("#10B0D9");
+
+
+    private Paint mBGPaint;//全局背景
+    private Paint mPathPaint;//扫描区外框,就是那个圈外面的
+    private Paint mFaceRoundPaint;
+
+    private Paint mTextTopPaint;//画上面的提示语
+    private Paint mTextBottomPaint;//画下面的提示语
+    private Paint mTextTipPaint;//画提示语
+    private Paint mArcTipPaint;//画提示语的背景
+
+    private RectF mOvalRect;
+    private Rect mFaceRect;
+    private Rect mFaceDetectRect;
+
+    private float mX;//原点
+    private float mY;//原点
+    private float mR;//半径
+    private boolean mIsSuccess = false;
+
+    private float mTipY;
+    private float mTipX;
+    private String mTipMessage;
+    private float mTopTextX;//
+    private float mTopTextY;//
+    private float mBottomTextX;//
+    private float mBottomTextY;//
+    private final Bitmap mSuccessBitmap;
+
+    public FaceDetectRoundView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+        float pathWidth = DensityUtils.dip2px(context, PATH_WIDTH);
+
+        mBGPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mBGPaint.setColor(COLOR_BG);
+        mBGPaint.setStyle(Paint.Style.STROKE);
+        mBGPaint.setAntiAlias(true);
+        mBGPaint.setDither(true);
+
+        mPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mPathPaint.setColor(COLOR_ROUND);
+        mPathPaint.setStrokeWidth(pathWidth);
+        mPathPaint.setStyle(Paint.Style.STROKE);
+        mPathPaint.setAntiAlias(true);
+        mPathPaint.setDither(true);
+
+
+        mFaceRoundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mFaceRoundPaint.setColor(COLOR_ROUND);
+        mFaceRoundPaint.setStyle(Paint.Style.FILL);
+        mFaceRoundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+        mFaceRoundPaint.setAntiAlias(true);
+        mFaceRoundPaint.setDither(true);
+
+
+        mTextBottomPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mTextBottomPaint.setColor(Color.parseColor("#FF10B0D9"));
+        mTextBottomPaint.setTextSize(DensityUtils.dip2px(context, 17));
+
+        mTextTopPaint = new Paint(mTextBottomPaint);
+        mTextTopPaint.setColor(Color.parseColor("#FF616161"));
+        mTextTopPaint.setTypeface(Typeface.DEFAULT_BOLD);
+        mTextTopPaint.setTextSize(DensityUtils.dip2px(context, 20));
+
+        mTextTipPaint = new Paint(mTextBottomPaint);
+        mTextTipPaint.setColor(Color.WHITE);
+        mTextTipPaint.setTextSize(DensityUtils.dip2px(context, 12));
+
+        mArcTipPaint = new Paint();
+        mArcTipPaint.setColor(Color.parseColor("#646464"));
+        mArcTipPaint.setColor(Color.BLACK);
+        mArcTipPaint.setAntiAlias(true);//取消锯齿
+        mArcTipPaint.setStyle(Paint.Style.FILL);//设置画圆弧的画笔的属性为描边(空心),个人喜欢叫它描边,叫空心有点会引起歧义
+        mArcTipPaint.setStrokeWidth(pathWidth);
+
+        mSuccessBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_success);
+
+    }
+
+
+    public void onRefreshTipsView(String message) {
+        mTipMessage=message;
+        if (!TextUtils.isEmpty(message)) {
+            if (mTipY == 0) {
+                float mTipHeight = mTextTipPaint.getFontMetrics().top - mTextTipPaint.getFontMetrics().bottom + DensityUtils.dip2px(getContext(), 10);
+                mTipY = (mY - mR) + mTipHeight + DisplayUtil.dip2px(getContext(), 40);
+            }
+            float mTipWidth = mTextTipPaint.measureText(message);
+            mTipX = mX - mTipWidth / 2;
+            postInvalidate();
+        }
+    }
+
+    public void onRefreshSuccessView(boolean mIsSuccess) {
+        this.mIsSuccess = mIsSuccess;
+        mPathPaint.setColor(mIsSuccess ? COLOR_ROUND_PASS : COLOR_ROUND);
+        postInvalidate();
+    }
+
+    public void processDrawState(boolean isDrawDash) {
+        onRefreshSuccessView(isDrawDash);
+    }
+
+    public float getRound() {
+        return mR;
+    }
+
+    public Rect getFaceRoundRect() {
+        return mFaceRect;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        float canvasWidth = right - left;
+        float canvasHeight = bottom - top;
+
+        float x = canvasWidth / 2;
+        float y = (canvasHeight / 2) - ((canvasHeight / 2) * HEIGHT_RATIO);
+        float r = (canvasWidth / 2) - ((canvasWidth / 2) * WIDTH_SPACE_RATIO);
+        if (mFaceRect == null) {
+            mFaceRect = new Rect((int) (x - r),
+                    (int) (y - r),
+                    (int) (x + r),
+                    (int) (y + r));
+        }
+        if (mFaceDetectRect == null) {
+            float hr = r + (r * HEIGHT_EXT_RATIO);
+            mFaceDetectRect = new Rect((int) (x - r),
+                    (int) (y - hr),
+                    (int) (x + r),
+                    (int) (y + hr));
+        }
+
+        if (mOvalRect == null) {
+            mOvalRect = new RectF(mX - mR, mY - mR,
+                    mX + mR, mY + mR);
+        }
+
+        mX = x;
+        mY = y;
+        mR = r;
+        mBGPaint.setStrokeWidth((top - bottom) / 2 - mR);
+
+        mTopTextX = mX - mTextTopPaint.measureText("赏个脸呗") / 2;
+        mTopTextY = mY - mR - DensityUtils.dip2px(getContext(), 20);
+        mBottomTextX = mX - mTextBottomPaint.measureText("拿起手机,眨眨眼") / 2;
+        mBottomTextY = mY + mR + DensityUtils.dip2px(getContext(), 40);
+
+
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        //画背景
+//        canvas.drawColor(Color.WHITE);
+//        canvas.drawARGB();
+        canvas.drawPaint(mBGPaint);
+//        canvas.drawCircle(mX, mY, getHeight() / 2, mBGPaint);
+        //画外框
+        canvas.drawCircle(mX, mY, mR - CIRCLE_SPACE + mPathPaint.getStrokeWidth(), mPathPaint);
+        canvas.drawCircle(mX, mY, mR, mFaceRoundPaint);
+
+        //画文字
+        canvas.drawText("赏个脸呗!", mTopTextX, mTopTextY, mTextTopPaint);
+        canvas.drawText("拿起手机,眨眨眼", mBottomTextX, mBottomTextY, mTextBottomPaint);
+
+        //画提示语
+//        canvas.drawArc(new RectF(mX, mY, 200, 200), -90, 120, true, mArcTipPaint);
+        if (!TextUtils.isEmpty(mTipMessage)){
+            canvas.drawText(mTipMessage, mTipX,mTipY,mTextTipPaint);
+        }
+        //画成功标识
+        if (mIsSuccess) {
+            canvas.drawBitmap(mSuccessBitmap, mX - mSuccessBitmap.getWidth() / 2, mY - mSuccessBitmap.getHeight() / 2, mPathPaint);
+        }
+    }
+
+
+    public static Rect getPreviewDetectRect(int w, int pw, int ph) {
+        float round = (w / 2) - ((w / 2) * WIDTH_SPACE_RATIO);
+        float x = pw / 2;
+        float y = (ph / 2) - ((ph / 2) * HEIGHT_RATIO);
+        float r = (pw / 2) > round ? round : (pw / 2);
+        float hr = r + (r * HEIGHT_EXT_RATIO);
+        Rect rect = new Rect((int) (x - r),
+                (int) (y - hr),
+                (int) (x + r),
+                (int) (y + hr));
+        return rect;
+    }
+
+}

+ 20 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/FaceRoundView.java

@@ -0,0 +1,20 @@
+package com.baidu.idl.face.platform.ui.widget;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class FaceRoundView extends View {
+    public FaceRoundView(Context context) {
+        super(context);
+    }
+
+    public FaceRoundView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public FaceRoundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+}

+ 20 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/FaceRoundView.java~HEAD

@@ -0,0 +1,20 @@
+package com.baidu.idl.face.platform.ui.widget;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class FaceRoundView extends View {
+    public FaceRoundView(Context context) {
+        super(context);
+    }
+
+    public FaceRoundView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public FaceRoundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+}

+ 20 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/FaceRoundView.java~HEAD_0

@@ -0,0 +1,20 @@
+package com.baidu.idl.face.platform.ui.widget;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class FaceRoundView extends View {
+    public FaceRoundView(Context context) {
+        super(context);
+    }
+
+    public FaceRoundView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public FaceRoundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+}

+ 243 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/VeriftyDialog.java

@@ -0,0 +1,243 @@
+package com.baidu.idl.face.platform.ui.widget;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentActivity;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.TextView;
+
+import com.baidu.idl.face.platform.ui.R;
+
+import java.io.Serializable;
+
+public class VeriftyDialog extends DialogFragment {
+    private final String KEY_TITLE = "title";
+    private final String KEY_CONTENT = "content";
+    private final String KEY_CANCEL_TEXT = "cancelText";
+    private final String KEY_SURE_TEXT = "sureText";
+    private final String KEY_GRAVITY = "gravity";
+    private final String KEY_CANCELED_ON_TOUCH_OUTSIDE = "canceledOnTouchOutside";
+    private final String KEY_LISTENER = "Listener";
+    private final String KEY_ANIMATIONS_STYLE = "AnimationsStyle";
+    private final String KEY_DIALOG_STYLE = "DialogStyle";
+    private final String KEY_SHOW_CANCEL = "showCancel";
+
+    private TextView titleTv;
+    private TextView messageTv;
+    private TextView cancelTv;
+    private TextView sureTv;
+    private OnDialogClickListener dialogClickListener;
+
+
+    public static VeriftyDialog newInstance(Bundle args) {
+        VeriftyDialog fragment = new VeriftyDialog();
+        fragment.setArguments(args);
+        return fragment;
+    }
+    @Override
+    public void onStart() {
+        super.onStart();
+        Dialog dialog = getDialog();
+        if (dialog != null) {
+            DisplayMetrics dm = new DisplayMetrics();
+            //设置弹框的占屏宽
+            getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
+            dialog.getWindow().setLayout((int) (dm.widthPixels * 0.8), ViewGroup.LayoutParams.WRAP_CONTENT);
+        }
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
+        return LayoutInflater.from(getActivity()).inflate(R.layout.common_prompt_dialog, null);
+    }
+
+    @Override
+    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        titleTv = (TextView) view.findViewById(R.id.title_tv);
+        messageTv = (TextView) view.findViewById(R.id.message_tv);
+        cancelTv = (TextView) view.findViewById(R.id.goto_tv);
+        sureTv = (TextView) view.findViewById(R.id.sure_tv);
+        initView();
+    }
+
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        int animationsStyle = -1;
+        int dialogStyle = -1;
+        int gravity = -1;
+        boolean canceledOnTouchOutside = true;
+        Bundle args = getArguments();
+        if (args != null) {
+            gravity = args.getInt(KEY_GRAVITY, -1);
+            animationsStyle = args.getInt(KEY_ANIMATIONS_STYLE, -1);
+            dialogStyle = args.getInt(KEY_DIALOG_STYLE, -1);
+            canceledOnTouchOutside = args.getBoolean(KEY_CANCELED_ON_TOUCH_OUTSIDE, true);
+        }
+        Dialog dialog = new Dialog(getActivity(), dialogStyle == -1 ? R.style.PromptDialogStyle : dialogStyle);
+        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        dialog.setCanceledOnTouchOutside(canceledOnTouchOutside);
+        dialog.setCancelable(canceledOnTouchOutside);
+        dialog.getWindow().setBackgroundDrawable(getResources().getDrawable(R.drawable.pop_round_bg));
+        if (animationsStyle > 0) {
+            dialog.getWindow().setWindowAnimations(animationsStyle);
+        }
+        Window window = dialog.getWindow();
+        window.setGravity(gravity);
+        return dialog;
+    }
+
+    private void initView() {
+        String title = getString(R.string.app_name);
+        String content = "";
+        String cancelText = getString(R.string.common_cancel);
+        String sureText = getString(R.string.common_sure);
+        boolean showCancel = true;
+        Bundle args = getArguments();
+        if (args != null) {
+            title = args.getString(KEY_TITLE, title);
+            content = args.getString(KEY_CONTENT, content);
+            cancelText = args.getString(KEY_CANCEL_TEXT, cancelText);
+            sureText = args.getString(KEY_SURE_TEXT, sureText);
+            showCancel = args.getBoolean(KEY_SHOW_CANCEL, true);
+            if (args.getSerializable(KEY_LISTENER) != null && args.getSerializable(KEY_LISTENER) instanceof OnDialogClickListener) {
+                dialogClickListener = (OnDialogClickListener) args.getSerializable(KEY_LISTENER);
+            }
+        }
+        titleTv.setText(title);
+        messageTv.setText(content);
+        sureTv.setText(sureText);
+        if (showCancel) {
+            cancelTv.setVisibility(View.VISIBLE);
+            cancelTv.setOnClickListener(mOnClickListener);
+            cancelTv.setText(cancelText);
+        } else {
+            cancelTv.setVisibility(View.GONE);
+        }
+        sureTv.setOnClickListener(mOnClickListener);
+    }
+
+    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View view) {
+            if (dialogClickListener != null) {
+                dialogClickListener.result(view == sureTv);
+            }
+            dismiss();
+        }
+    };
+
+    public static class Builder {
+
+        private final String KEY_SHOW_CANCEL = "showCancel";
+        private final String KEY_TITLE = "title";
+        private final String KEY_CONTENT = "content";
+        private final String KEY_CANCEL_TEXT = "cancelText";
+        private final String KEY_SURE_TEXT = "sureText";
+        private final String KEY_GRAVITY = "gravity";
+        private final String KEY_CANCELED_ON_TOUCH_OUTSIDE = "canceledOnTouchOutside";
+        private final String KEY_LISTENER = "Listener";
+        private final String KEY_ANIMATIONS_STYLE = "AnimationsStyle";
+        private final String KEY_DIALOG_STYLE = "DialogStyle";
+
+        private String title;
+        private String content;
+        private String cancelText;
+        private String sureText;
+        private int gravity;
+        private int animationsStyle;
+        private int dialogStyle;
+        private boolean canceledOnTouchOutside;
+        private boolean showCancel;
+        private Context ct;
+
+
+        public Builder(Context ct) {
+            this.ct = ct;
+            this.showCancel = true;
+            this.canceledOnTouchOutside = true;
+        }
+
+        public Builder setShowCancel(boolean showCancel) {
+            this.showCancel = showCancel;
+            return this;
+        }
+
+        public Builder setCanceledOnTouchOutside(boolean canceledOnTouchOutside) {
+            this.canceledOnTouchOutside = canceledOnTouchOutside;
+            return this;
+        }
+
+        public Builder setDialogStyle(int dialogStyle) {
+            this.dialogStyle = dialogStyle;
+            return this;
+        }
+
+        public Builder setGravity(int gravity) {
+            this.gravity = gravity;
+            return this;
+        }
+
+        public Builder setAnimationsStyle(int animationsStyle) {
+            this.animationsStyle = animationsStyle;
+            return this;
+        }
+
+        public Builder setTitle(String title) {
+            this.title = title;
+            return this;
+        }
+
+        public Builder setContent(String content) {
+            this.content = content;
+            return this;
+        }
+
+        public Builder setCancelText(String cancelText) {
+            this.cancelText = cancelText;
+            return this;
+        }
+
+        public Builder setSureText(String sureText) {
+            this.sureText = sureText;
+            return this;
+        }
+
+        public VeriftyDialog build(OnDialogClickListener mOnClickListener) {
+            Bundle args = new Bundle();
+            args.putString(KEY_TITLE, title);
+            args.putString(KEY_CONTENT, content);
+            args.putString(KEY_CANCEL_TEXT, cancelText);
+            args.putString(KEY_SURE_TEXT, sureText);
+            args.putString(KEY_SURE_TEXT, sureText);
+            args.putBoolean(KEY_CANCELED_ON_TOUCH_OUTSIDE, canceledOnTouchOutside);
+            args.putInt(KEY_GRAVITY, gravity);
+            args.putInt(KEY_ANIMATIONS_STYLE, animationsStyle);
+            args.putInt(KEY_DIALOG_STYLE, dialogStyle);
+            args.putBoolean(KEY_SHOW_CANCEL, showCancel);
+            if (mOnClickListener != null) {
+                args.putSerializable(KEY_LISTENER, mOnClickListener);
+            }
+            VeriftyDialog mVeriftyDialog = VeriftyDialog.newInstance(args);
+            if (ct != null && ct instanceof FragmentActivity) {
+                mVeriftyDialog.show(((FragmentActivity) ct).getSupportFragmentManager(), "prompt");
+            }
+            return mVeriftyDialog;
+        }
+
+
+    }
+
+    public interface OnDialogClickListener extends Serializable {
+        void result(boolean clickSure);
+    }
+}

+ 86 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/WaveHelper.java

@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 Baidu, Inc. All Rights Reserved.
+ */
+package com.baidu.idl.face.platform.ui.widget;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 人脸识别登录波纹动画
+ *
+ * @author liujinhui
+ * @date 2017/11/28
+ */
+
+public class WaveHelper {
+    private WaveView mWaveView;
+    private AnimatorSet mAnimatorSet;
+
+    /**
+     * 构造
+     *
+     * @param waveView
+     */
+    public WaveHelper(WaveView waveView) {
+        mWaveView = waveView;
+        initAnimation();
+    }
+
+    /**
+     * 动画开始
+     */
+    public void start() {
+        mWaveView.setShowWave(true);
+        if (mAnimatorSet != null) {
+            mAnimatorSet.start();
+        }
+    }
+
+    /**
+     * 动画初始化
+     */
+    private void initAnimation() {
+        List<Animator> animators = new ArrayList<>();
+
+        ObjectAnimator waveShiftAnim = ObjectAnimator.ofFloat(
+                mWaveView, "waveShiftRatio", 0f, 1f);
+        waveShiftAnim.setRepeatCount(ValueAnimator.INFINITE);
+        waveShiftAnim.setDuration(500);
+        waveShiftAnim.setInterpolator(new LinearInterpolator());
+        animators.add(waveShiftAnim);
+
+        ObjectAnimator waterLevelAnim = ObjectAnimator.ofFloat(
+                mWaveView, "waterLevelRatio", 0.25f, 0.25f);
+        waterLevelAnim.setDuration(1000);
+        waterLevelAnim.setInterpolator(new DecelerateInterpolator());
+        animators.add(waterLevelAnim);
+
+        ObjectAnimator amplitudeAnim = ObjectAnimator.ofFloat(
+                mWaveView, "amplitudeRatio", 0.05f, 0.05f);
+        amplitudeAnim.setRepeatCount(ValueAnimator.REVERSE);
+        amplitudeAnim.setRepeatMode(ValueAnimator.REVERSE);
+        amplitudeAnim.setDuration(1000);
+        amplitudeAnim.setInterpolator(new LinearInterpolator());
+        animators.add(amplitudeAnim);
+
+        mAnimatorSet = new AnimatorSet();
+        mAnimatorSet.playTogether(animators);
+    }
+
+    /**
+     * 动画取消
+     */
+    public void cancel() {
+        if (mAnimatorSet != null) {
+            mAnimatorSet.end();
+        }
+    }
+}

+ 334 - 0
app_modular/faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/WaveView.java

@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2017 Baidu, Inc. All Rights Reserved.
+ */
+package com.baidu.idl.face.platform.ui.widget;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Shader;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * sin函数绘制人脸识别登录波浪纹
+ *
+ * @author liujinhui
+ * @date 2017/11/28
+ */
+
+public class WaveView extends View {
+
+    private static final float DEFAULT_AMPLITUDE_RATIO = 0.05f;
+    private static final float DEFAULT_WATER_LEVEL_RATIO = 0.5f;
+    private static final float DEFAULT_WAVE_LENGTH_RATIO = 1.0f;
+    private static final float DEFAULT_WAVE_SHIFT_RATIO = 0.0f;
+    private static final int DEFAULT_STROKE_WIDTH = 2;
+
+    private static final int DEFAULT_BEHIND_WAVE_COLOR = Color.parseColor("#28FFFFFF");
+    private static final int DEFAULT_FRONT_WAVE_COLOR = Color.parseColor("#3CFFFFFF");
+    private static final ShapeType DEFAULT_WAVE_SHAPE = ShapeType.CIRCLE;
+
+    private boolean mShowWave;
+    private BitmapShader mWaveShader;
+    private Matrix mShaderMatrix;
+    private Paint mViewPaint;
+    private Paint mBorderPaint;
+    private float mDefaultAmplitude;
+    private float mDefaultWaterLevel;
+    private float mDefaultWaveLength;
+    private double mDefaultAngularFrequency;
+    private float mAmplitudeRatio = DEFAULT_AMPLITUDE_RATIO;
+    private float mWaveLengthRatio = DEFAULT_WAVE_LENGTH_RATIO;
+    private float mWaterLevelRatio = DEFAULT_WATER_LEVEL_RATIO;
+    private float mWaveShiftRatio = DEFAULT_WAVE_SHIFT_RATIO;
+
+    private int mBehindWaveColor = DEFAULT_BEHIND_WAVE_COLOR;
+    private int mFrontWaveColor = DEFAULT_FRONT_WAVE_COLOR;
+    private ShapeType mShapeType = DEFAULT_WAVE_SHAPE;
+
+    public enum ShapeType {
+        CIRCLE,
+        SQUARE
+    }
+
+    public WaveView(Context context) {
+        super(context);
+        init();
+    }
+
+    public WaveView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public WaveView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    /**
+     * 初始化
+     */
+    private void init() {
+        mShaderMatrix = new Matrix();
+        mViewPaint = new Paint();
+        mViewPaint.setAntiAlias(true);
+    }
+
+    /**
+     * 获取波纹摆动频率 (0-1,默认为0)
+     *
+     * @return
+     */
+    public float getWaveShiftRatio() {
+        return mWaveShiftRatio;
+    }
+
+    /**
+     * 设置波纹水平摆动频率
+     *
+     * @param waveShiftRatio (0-1,默认为0)
+     */
+    public void setWaveShiftRatio(float waveShiftRatio) {
+        if (mWaveShiftRatio != waveShiftRatio) {
+            mWaveShiftRatio = waveShiftRatio;
+            invalidate();
+        }
+    }
+
+    /**
+     * 获取波纹垂直摆动频率(0-1,默认为0.5)
+     *
+     * @return
+     */
+    public float getWaterLevelRatio() {
+        return mWaterLevelRatio;
+    }
+
+    /**
+     * 设置波纹垂直摆动频率 (0-1,默认为0.5)
+     *
+     * @param waterLevelRatio
+     */
+    public void setWaterLevelRatio(float waterLevelRatio) {
+        if (mWaterLevelRatio != waterLevelRatio) {
+            mWaterLevelRatio = waterLevelRatio;
+            invalidate();
+        }
+    }
+
+    /**
+     * 获取波纹振幅频率(0-1之间)
+     *
+     * @return
+     */
+    public float getAmplitudeRatio() {
+        return mAmplitudeRatio;
+    }
+
+    /**
+     * 设置波纹振幅频率(0-1之间)
+     *
+     * @param amplitudeRatio
+     */
+    public void setAmplitudeRatio(float amplitudeRatio) {
+        if (mAmplitudeRatio != amplitudeRatio) {
+            mAmplitudeRatio = amplitudeRatio;
+            invalidate();
+        }
+    }
+
+    /**
+     * 获取波纹水平方向的长度比率(0-1之间)
+     *
+     * @return
+     */
+    public float getWaveLengthRatio() {
+        return mWaveLengthRatio;
+    }
+
+    /**
+     * 设置波纹水平方向的长度比率 (0-1之间)
+     *
+     * @param waveLengthRatio
+     */
+    public void setWaveLengthRatio(float waveLengthRatio) {
+        mWaveLengthRatio = waveLengthRatio;
+    }
+
+    /**
+     * 是否显示
+     *
+     * @return
+     */
+    public boolean isShowWave() {
+        return mShowWave;
+    }
+
+    /**
+     * 设置是否显示
+     *
+     * @param showWave
+     */
+    public void setShowWave(boolean showWave) {
+        mShowWave = showWave;
+    }
+
+    /**
+     * 设置圆形或矩形外框边界
+     *
+     * @param width
+     * @param color
+     */
+    public void setBorder(int width, int color) {
+        if (mBorderPaint == null) {
+            mBorderPaint = new Paint();
+            mBorderPaint.setAntiAlias(true);
+            mBorderPaint.setStyle(Style.STROKE);
+        }
+        mBorderPaint.setColor(color);
+        mBorderPaint.setStrokeWidth(width);
+
+        invalidate();
+    }
+
+    /**
+     * 设置波纹颜色
+     *
+     * @param behindWaveColor
+     * @param frontWaveColor
+     */
+    public void setWaveColor(int behindWaveColor, int frontWaveColor) {
+        mBehindWaveColor = behindWaveColor;
+        mFrontWaveColor = frontWaveColor;
+
+        if (getWidth() > 0 && getHeight() > 0) {
+            mWaveShader = null;
+            createShader();
+            invalidate();
+        }
+    }
+
+    /**
+     * 设置外框样式
+     *
+     * @param shapeType
+     */
+    public void setShapeType(ShapeType shapeType) {
+        mShapeType = shapeType;
+        invalidate();
+    }
+
+    /**
+     * 重载尺寸改变
+     *
+     * @param w
+     * @param h
+     * @param oldw
+     * @param oldh
+     */
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+
+        createShader();
+    }
+
+    /**
+     * 通过sin函数计算x及y的波动和振幅
+     */
+    private void createShader() {
+        mDefaultAngularFrequency = 2.0f * Math.PI / DEFAULT_WAVE_LENGTH_RATIO / getWidth();
+        mDefaultAmplitude = getHeight() * DEFAULT_AMPLITUDE_RATIO;
+        mDefaultWaterLevel = getHeight() * DEFAULT_WATER_LEVEL_RATIO;
+        mDefaultWaveLength = getWidth();
+
+        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+
+        Paint wavePaint = new Paint();
+        wavePaint.setStrokeWidth(DEFAULT_STROKE_WIDTH);
+        wavePaint.setAntiAlias(true);
+
+        // 通过sin函数计算y
+        final int endX = getWidth() + 1;
+        final int endY = getHeight() + 1;
+        float[] waveY = new float[endX];
+
+        wavePaint.setColor(mBehindWaveColor);
+        for (int beginX = 0; beginX < endX; beginX++) {
+            double wx = beginX * mDefaultAngularFrequency;
+            float beginY = (float) (mDefaultWaterLevel + mDefaultAmplitude * Math.sin(wx));
+            canvas.drawLine(beginX, beginY, beginX, endY, wavePaint);
+
+            waveY[beginX] = beginY;
+        }
+
+        wavePaint.setColor(mFrontWaveColor);
+        final int wave2Shift = (int) (mDefaultWaveLength / 4);
+        for (int beginX = 0; beginX < endX; beginX++) {
+            canvas.drawLine(beginX, waveY[(beginX + wave2Shift) % endX], beginX, endY, wavePaint);
+        }
+
+        mWaveShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
+        mViewPaint.setShader(mWaveShader);
+    }
+
+    /**
+     * canvas绘制
+     *
+     * @param canvas
+     */
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mShowWave && mWaveShader != null) {
+            if (mViewPaint.getShader() == null) {
+                mViewPaint.setShader(mWaveShader);
+            }
+
+            mShaderMatrix.setScale(
+                    mWaveLengthRatio / DEFAULT_WAVE_LENGTH_RATIO,
+                    mAmplitudeRatio / DEFAULT_AMPLITUDE_RATIO,
+                    0,
+                    mDefaultWaterLevel);
+
+            mShaderMatrix.postTranslate(
+                    mWaveShiftRatio * getWidth(),
+                    (DEFAULT_WATER_LEVEL_RATIO - mWaterLevelRatio) * getHeight());
+
+            mWaveShader.setLocalMatrix(mShaderMatrix);
+
+            float borderWidth = mBorderPaint == null ? 0f : mBorderPaint.getStrokeWidth();
+            switch (mShapeType) {
+                case CIRCLE:
+                    if (borderWidth > 0) {
+                        canvas.drawCircle(getWidth() / 2f, getHeight() / 2f,
+                                (getWidth() - borderWidth) / 2f - 1f, mBorderPaint);
+                    }
+                    float radius = getWidth() / 2f - borderWidth;
+                    canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, mViewPaint);
+                    break;
+                case SQUARE:
+                    if (borderWidth > 0) {
+                        canvas.drawRect(
+                                borderWidth / 2f,
+                                borderWidth / 2f,
+                                getWidth() - borderWidth / 2f - 0.5f,
+                                getHeight() - borderWidth / 2f - 0.5f,
+                                mBorderPaint);
+                    }
+                    canvas.drawRect(borderWidth, borderWidth, getWidth() - borderWidth,
+                            getHeight() - borderWidth, mViewPaint);
+                    break;
+            }
+        } else {
+            mViewPaint.setShader(null);
+        }
+    }
+}

BIN
app_modular/faceplatform-ui/src/main/jniLibs/arm64-v8a/libFaceSDK.so


BIN
app_modular/faceplatform-ui/src/main/jniLibs/arm64-v8a/libidl_license.so


BIN
app_modular/faceplatform-ui/src/main/jniLibs/armeabi-v7a/libFaceSDK.so


BIN
app_modular/faceplatform-ui/src/main/jniLibs/armeabi-v7a/libidl_license.so


BIN
app_modular/faceplatform-ui/src/main/jniLibs/x86/libFaceSDK.so


BIN
app_modular/faceplatform-ui/src/main/jniLibs/x86/libidl_license.so


+ 25 - 0
app_modular/faceplatform-ui/src/main/res/drawable/bg_tips.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <shape>
+            <stroke android:width="1dp" android:color="#F6A623" />
+            <corners android:radius="18dp" />
+            <solid android:color="#0000" />
+        </shape>
+    </item>
+    <item android:state_focused="true">
+        <shape>
+            <stroke android:width="1dp" android:color="#F6A623" />
+            <corners android:radius="18dp" />
+            <solid android:color="#0000" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <stroke android:width="1dp" android:color="#F6A623" />
+            <corners android:radius="18dp" />
+            <solid android:color="#0000" />
+        </shape>
+    </item>
+</selector>  
+

+ 22 - 0
app_modular/faceplatform-ui/src/main/res/drawable/bg_tips_no.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <shape>
+            <corners android:radius="15dp" />
+            <solid android:color="#0000" />
+        </shape>
+    </item>
+    <item android:state_focused="true">
+        <shape>
+            <corners android:radius="15dp" />
+            <solid android:color="#0000" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <corners android:radius="15dp" />
+            <solid android:color="#0000" />
+        </shape>
+    </item>
+</selector>  
+

+ 11 - 0
app_modular/faceplatform-ui/src/main/res/drawable/round_top_transparent_bg.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape>
+            <solid android:color="@color/base_bg" />
+            <corners android:topRightRadius="360dp"
+                android:topLeftRadius="360dp"/>
+            <padding android:bottom="0.5dp" android:left="0.5dp" android:right="0.5dp" android:top="0.5dp" />
+        </shape>
+    </item>
+</selector>

+ 107 - 0
app_modular/faceplatform-ui/src/main/res/layout/activity_face_detect.xml

@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/detect_root_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <FrameLayout
+        android:id="@+id/detect_surface_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <SurfaceView
+            android:id="@+id/detect_surface_view"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+        <ImageView
+            android:id="@+id/detect_surface_overlay_image"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_centerHorizontal="true"
+            android:background="@mipmap/bg_face_round" />
+    </FrameLayout>
+
+    <LinearLayout
+        android:id="@+id/detect_surface_overlay_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="0.8" />
+
+        <TextView
+            android:id="@+id/detect_tips"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_above="@id/detect_surface_overlay_layout"
+            android:layout_centerHorizontal="true"
+            android:layout_gravity="center_horizontal"
+            android:gravity="center"
+            android:text="@string/detect_face_in"
+            android:textColor="#00E5EE"
+            android:textSize="16sp" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="3"
+            android:orientation="horizontal">
+
+            <View
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="0.05" />
+
+            <ImageView
+                android:id="@+id/detect_surface_overlay"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_gravity="center_horizontal"
+                android:layout_weight="0.9"
+                android:background="#09ffffff"
+                android:visibility="visible" />
+
+            <View
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="0.05" />
+        </LinearLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1" />
+    </LinearLayout>
+
+    <ImageView
+        android:id="@+id/detect_close"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_margin="20dp"
+        android:src="@mipmap/ic_close" />
+
+    <ImageView
+        android:id="@+id/detect_sound"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_margin="20dp"
+        android:src="@mipmap/ic_enable_sound" />
+
+    <HorizontalScrollView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true">
+
+        <LinearLayout
+            android:id="@+id/detect_result_image_layout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal"></LinearLayout>
+    </HorizontalScrollView>
+</RelativeLayout>

+ 96 - 0
app_modular/faceplatform-ui/src/main/res/layout/activity_face_detect_v3100.xml

@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/detect_root_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <FrameLayout
+        android:id="@+id/detect_surface_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+    <com.baidu.idl.face.platform.ui.widget.FaceDetectRoundView
+        android:id="@+id/detect_face_round"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <LinearLayout
+        android:id="@+id/detect_surface_overlay_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="0.15" />
+
+        <TextView
+            android:id="@+id/detect_top_tips"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_gravity="center_horizontal"
+            android:gravity="center"
+            android:paddingLeft="12dp"
+            android:paddingRight="12dp"
+            android:paddingTop="8dp"
+            android:paddingBottom="8dp"
+            android:text="@string/detect_face_in"
+            android:textColor="#F6A623"
+            android:textSize="18sp" />
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="0.65" />
+
+        <TextView
+            android:id="@+id/detect_bottom_tips"
+            android:layout_width="wrap_content"
+            android:layout_height="0dp"
+            android:layout_centerHorizontal="true"
+            android:layout_gravity="center_horizontal"
+            android:layout_weight="0.36"
+            android:gravity="center|top"
+            android:text=""
+            android:textColor="#D0D0D0"
+            android:textSize="16sp" />
+    </LinearLayout>
+
+    <ImageView
+        android:id="@+id/detect_close"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_margin="20dp"
+        android:visibility="gone"
+        android:src="@mipmap/ic_close_ext" />
+
+    <ImageView
+        android:id="@+id/detect_sound"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_margin="@dimen/padding"
+        android:src="@mipmap/ic_enable_sound_ext" />
+
+    <ImageView
+        android:id="@+id/detect_success_image"
+        android:layout_width="45dp"
+        android:layout_height="45dp"
+        android:src="@mipmap/ic_success"
+        android:visibility="invisible" />
+
+    <HorizontalScrollView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true">
+
+        <LinearLayout
+            android:id="@+id/detect_result_image_layout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal"></LinearLayout>
+    </HorizontalScrollView>
+</RelativeLayout>

+ 107 - 0
app_modular/faceplatform-ui/src/main/res/layout/activity_face_liveness.xml

@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/liveness_root_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <FrameLayout
+        android:id="@+id/liveness_surface_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <SurfaceView
+            android:id="@+id/liveness_surface_view"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+        <ImageView
+            android:id="@+id/liveness_surface_overlay_image"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_centerHorizontal="true"
+            android:background="@mipmap/bg_face_round" />
+    </FrameLayout>
+
+    <LinearLayout
+        android:id="@+id/liveness_surface_overlay_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="0.8" />
+
+        <TextView
+            android:id="@+id/liveness_tips"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_above="@id/liveness_surface_overlay_layout"
+            android:layout_centerHorizontal="true"
+            android:layout_gravity="center_horizontal"
+            android:gravity="center"
+            android:text="@string/detect_face_in"
+            android:textColor="#00E5EE"
+            android:textSize="16sp" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="3"
+            android:orientation="horizontal">
+
+            <View
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="0.05" />
+
+            <ImageView
+                android:id="@+id/liveness_surface_overlay"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_gravity="center_horizontal"
+                android:layout_weight="0.9"
+                android:background="#09ffffff"
+                android:visibility="invisible" />
+
+            <View
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="0.05" />
+        </LinearLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1" />
+    </LinearLayout>
+
+    <ImageView
+        android:id="@+id/liveness_close"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_margin="20dp"
+        android:src="@mipmap/ic_close" />
+
+    <ImageView
+        android:id="@+id/liveness_sound"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_margin="20dp"
+        android:src="@mipmap/ic_enable_sound" />
+
+    <HorizontalScrollView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true">
+
+        <LinearLayout
+            android:id="@+id/liveness_result_image_layout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal"></LinearLayout>
+    </HorizontalScrollView>
+</RelativeLayout>

+ 95 - 0
app_modular/faceplatform-ui/src/main/res/layout/activity_face_liveness_v3100.xml

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/liveness_root_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <FrameLayout
+        android:id="@+id/liveness_surface_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"></FrameLayout>
+
+    <com.baidu.idl.face.platform.ui.widget.FaceDetectRoundView
+        android:id="@+id/liveness_face_round"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <LinearLayout
+        android:id="@+id/liveness_surface_overlay_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="0.15" />
+
+        <TextView
+            android:id="@+id/liveness_top_tips"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_gravity="center_horizontal"
+            android:gravity="center"
+            android:paddingBottom="8dp"
+            android:paddingLeft="12dp"
+            android:paddingRight="12dp"
+            android:paddingTop="8dp"
+            android:text="@string/detect_face_in"
+            android:textColor="#F6A623"
+            android:textSize="18sp" />
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="0.65" />
+
+        <TextView
+            android:id="@+id/liveness_bottom_tips"
+            android:layout_width="wrap_content"
+            android:layout_height="0dp"
+            android:layout_centerHorizontal="true"
+            android:layout_gravity="center_horizontal"
+            android:layout_weight="0.36"
+            android:gravity="center|top"
+            android:text=""
+            android:textColor="#D0D0D0"
+            android:textSize="16sp" />
+    </LinearLayout>
+
+    <ImageView
+        android:id="@+id/liveness_close"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_margin="20dp"
+        android:src="@mipmap/ic_close_ext" />
+
+    <ImageView
+        android:id="@+id/liveness_sound"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_margin="20dp"
+        android:src="@mipmap/ic_enable_sound_ext" />
+
+    <ImageView
+        android:id="@+id/liveness_success_image"
+        android:layout_width="45dp"
+        android:layout_height="45dp"
+        android:src="@mipmap/ic_success"
+        android:visibility="visible" />
+
+    <HorizontalScrollView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true">
+
+        <LinearLayout
+            android:id="@+id/liveness_result_image_layout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal"></LinearLayout>
+    </HorizontalScrollView>
+</RelativeLayout>

+ 40 - 0
app_modular/faceplatform-ui/src/main/res/layout/activity_face_verifty.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:background="@color/white"
+    android:layout_height="match_parent">
+
+    <FrameLayout
+        android:id="@+id/liveness_surface_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <TextView
+        android:id="@+id/liveness_top_tips"
+        android:layout_width="match_parent"
+        android:layout_height="170dp"
+        android:layout_centerHorizontal="true"
+        android:layout_gravity="center_horizontal"
+        android:gravity="center|bottom"
+        android:padding="8dp"
+        android:visibility="gone"
+        android:text="@string/detect_face_in"
+        android:textColor="@color/white"
+        android:textSize="12sp" />
+
+    <com.baidu.idl.face.platform.ui.widget.FaceDetectRoundView
+        android:id="@+id/liveness_face_round"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="visible" />
+
+
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="18dp"
+        android:layout_alignParentBottom="true"
+        android:layout_marginBottom="20dp"
+        android:src="@mipmap/ic_bottom_uu"/>
+
+
+</RelativeLayout>

BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xhdpi/bg_face_round.png


BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xhdpi/ic_bottom_uu.png


BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xhdpi/ic_close.png


BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xhdpi/ic_disable_sound.png


BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xhdpi/ic_enable_sound.png


BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_bottom_uu.png


BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_close_ext.png


BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_disable_sound_ext.png


BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_enable_sound_ext.png


BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_success.png


BIN
app_modular/faceplatform-ui/src/main/res/mipmap-xxhdpi/ic_warning.png


BIN
app_modular/faceplatform-ui/src/main/res/raw/detect_face_in.mp3


BIN
app_modular/faceplatform-ui/src/main/res/raw/face_good.mp3


BIN
app_modular/faceplatform-ui/src/main/res/raw/liveness_eye.mp3


BIN
app_modular/faceplatform-ui/src/main/res/raw/liveness_head_down.mp3


BIN
app_modular/faceplatform-ui/src/main/res/raw/liveness_head_left.mp3


BIN
app_modular/faceplatform-ui/src/main/res/raw/liveness_head_left_right.mp3


BIN
app_modular/faceplatform-ui/src/main/res/raw/liveness_head_right.mp3


BIN
app_modular/faceplatform-ui/src/main/res/raw/liveness_head_up.mp3


BIN
app_modular/faceplatform-ui/src/main/res/raw/liveness_mouth.mp3


+ 25 - 0
app_modular/faceplatform-ui/src/main/res/values/strings.xml

@@ -0,0 +1,25 @@
+<resources>
+    <string name="detect_no_face">未检测到人脸</string>
+    <string name="detect_face_in">把脸移入框内</string>
+    <string name="detect_zoom_in">手机拿近一点</string>
+    <string name="detect_zoom_out">手机拿远一点</string>
+    <string name="detect_head_up">建议略微抬头</string>
+    <string name="detect_head_down">建议略微低头</string>
+    <string name="detect_head_left">建议略微向左转头</string>
+    <string name="detect_head_right">建议略微向右转头</string>
+    <string name="detect_occ_face">脸部有遮挡</string>
+    <string name="detect_low_light">光线再亮些</string>
+    <string name="detect_keep">请保持不动</string>
+    <string name="detect_standard">请正对手机</string>
+    <string name="detect_timeout">检测超时</string>
+    <string name="liveness_eye">眨眨眼</string>
+    <string name="liveness_eye_left">请眨眨左边眼睛</string>
+    <string name="liveness_eye_right">请眨眨右边眼睛</string>
+    <string name="liveness_mouth">张张嘴</string>
+    <string name="liveness_head_left">向左缓慢转头</string>
+    <string name="liveness_head_right">向右缓慢转头</string>
+    <string name="liveness_head_left_right">摇摇头</string>
+    <string name="liveness_head_up">缓慢抬头</string>
+    <string name="liveness_head_down">缓慢低头</string>
+    <string name="liveness_good">非常好</string>
+</resources>