Pārlūkot izejas kodu

功能开发:升级百度人脸SDK

Sora 1 gadu atpakaļ
vecāks
revīzija
a68e13463d
100 mainītis faili ar 4550 papildinājumiem un 834 dzēšanām
  1. 2 0
      .idea/gradle.xml
  2. 9 7
      app/build.gradle
  3. 13 1
      app/proguard-rules.pro
  4. 803 789
      app/src/main/AndroidManifest.xml
  5. 11 2
      app/src/main/java/com/sheep/gamegroup/module/home/fragment/FgtHome.java
  6. 11 10
      app/src/main/java/com/sheep/gamegroup/module/qrcode/FaceWithQRActivity.java
  7. 3 5
      app/src/main/java/com/sheep/gamegroup/module/qrcode/QRCodeCaptureHelper.java
  8. 2 2
      app/src/main/java/com/sheep/gamegroup/util/DeviceIDUtil.java
  9. 1 4
      app/src/main/java/com/sheep/gamegroup/view/activity/ActSetting.java
  10. 5 4
      app/src/main/java/com/sheep/gamegroup/view/activity/GameCertificationActivity.java
  11. 1 1
      app/src/main/java/com/sheep/gamegroup/view/activity/SplashAct.java
  12. 22 2
      app/src/main/java/com/sheep/jiuyan/samllsheep/SheepApp.java
  13. 1 1
      app/src/main/res/layout/act_qrcode.xml
  14. 2 6
      build.gradle
  15. 2 0
      faceplatform-release/build.gradle
  16. BIN
      faceplatform-release/faceplatform-release-4.1.5.aar
  17. 1 0
      faceplatform-ui/.gitignore
  18. 21 0
      faceplatform-ui/build.gradle
  19. 18 0
      faceplatform-ui/proguard-rules.pro
  20. 20 0
      faceplatform-ui/src/main/AndroidManifest.xml
  21. 84 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/BaseActivity.java
  22. 73 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/CameraActivity.java
  23. 563 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceDetectActivity.java
  24. 725 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceLivenessActivity.java
  25. 100 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceSDKResSettings.java
  26. 87 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/BrightnessUtils.java
  27. 102 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/CameraPreviewUtils.java
  28. 25 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/CameraUtils.java
  29. 81 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/FaceSDKHelper.java
  30. 36 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/IntentUtils.java
  31. 151 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/SecRequest.java
  32. 68 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/VolumeUtils.java
  33. 121 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/view/AlignTextView.java
  34. 240 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/CircleImageView.java
  35. 283 0
      faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/FaceDetectRoundView.java
  36. BIN
      faceplatform-ui/src/main/jniLibs/arm64-v8a/libbd_unifylicense.so
  37. BIN
      faceplatform-ui/src/main/jniLibs/arm64-v8a/libbdface_sdk.so
  38. BIN
      faceplatform-ui/src/main/jniLibs/arm64-v8a/libc++_shared.so
  39. BIN
      faceplatform-ui/src/main/jniLibs/arm64-v8a/libpaddle_light_api_shared.so
  40. BIN
      faceplatform-ui/src/main/jniLibs/armeabi-v7a/libbd_unifylicense.so
  41. BIN
      faceplatform-ui/src/main/jniLibs/armeabi-v7a/libbdface_sdk.so
  42. BIN
      faceplatform-ui/src/main/jniLibs/armeabi-v7a/libc++_shared.so
  43. BIN
      faceplatform-ui/src/main/jniLibs/armeabi-v7a/libpaddle_light_api_shared.so
  44. 36 0
      faceplatform-ui/src/main/res/drawable/anim_down.xml
  45. 24 0
      faceplatform-ui/src/main/res/drawable/anim_eye.xml
  46. 36 0
      faceplatform-ui/src/main/res/drawable/anim_left.xml
  47. 28 0
      faceplatform-ui/src/main/res/drawable/anim_mouth.xml
  48. 36 0
      faceplatform-ui/src/main/res/drawable/anim_right.xml
  49. 36 0
      faceplatform-ui/src/main/res/drawable/anim_up.xml
  50. 25 0
      faceplatform-ui/src/main/res/drawable/bg_tips.xml
  51. 22 0
      faceplatform-ui/src/main/res/drawable/bg_tips_no.xml
  52. 7 0
      faceplatform-ui/src/main/res/drawable/collect_image_close_selector.xml
  53. 7 0
      faceplatform-ui/src/main/res/drawable/collect_image_voice_selector.xml
  54. 6 0
      faceplatform-ui/src/main/res/drawable/home_checkbox_button_selector.xml
  55. BIN
      faceplatform-ui/src/main/res/drawable/icon_setting_layout_ischeck_no.png
  56. BIN
      faceplatform-ui/src/main/res/drawable/icon_setting_layout_ischeck_select_yes.png
  57. 6 0
      faceplatform-ui/src/main/res/drawable/setting_actionlive_checkbox_button_selector.xml
  58. 7 0
      faceplatform-ui/src/main/res/drawable/setting_image_close_selector.xml
  59. 20 0
      faceplatform-ui/src/main/res/drawable/setting_layout_bottom_round.xml
  60. 12 0
      faceplatform-ui/src/main/res/drawable/setting_layout_radius.xml
  61. 20 0
      faceplatform-ui/src/main/res/drawable/setting_layout_top_round.xml
  62. 11 0
      faceplatform-ui/src/main/res/drawable/setting_switch_thumb.xml
  63. 6 0
      faceplatform-ui/src/main/res/drawable/setting_switch_track_off.xml
  64. 6 0
      faceplatform-ui/src/main/res/drawable/setting_switch_track_on.xml
  65. 5 0
      faceplatform-ui/src/main/res/drawable/setting_switch_track_selector.xml
  66. 12 0
      faceplatform-ui/src/main/res/drawable/setting_toast_layout_radius.xml
  67. 7 0
      faceplatform-ui/src/main/res/drawable/success_button_recollect_selector.xml
  68. 7 0
      faceplatform-ui/src/main/res/drawable/success_button_return_selector.xml
  69. 106 0
      faceplatform-ui/src/main/res/layout/activity_face_detect_v3100.xml
  70. 114 0
      faceplatform-ui/src/main/res/layout/activity_face_liveness_v3100.xml
  71. 243 0
      faceplatform-ui/src/main/res/layout/layout_active_type.xml
  72. 18 0
      faceplatform-ui/src/main/res/layout/setting_toast_layout.xml
  73. BIN
      faceplatform-ui/src/main/res/mipmap-xhdpi/icon_home__titlebar_setting.png
  74. BIN
      faceplatform-ui/src/main/res/mipmap-xhdpi/icon_home_guide_handset.png
  75. BIN
      faceplatform-ui/src/main/res/mipmap-xhdpi/icon_home_guide_light.png
  76. BIN
      faceplatform-ui/src/main/res/mipmap-xhdpi/icon_home_guide_mask.png
  77. BIN
      faceplatform-ui/src/main/res/mipmap-xhdpi/icon_home_image_agreement.png
  78. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_00.png
  79. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_01.png
  80. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_02.png
  81. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_03.png
  82. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_04.png
  83. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_05.png
  84. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_06.png
  85. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_07.png
  86. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_08.png
  87. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_09.png
  88. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_10.png
  89. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_11.png
  90. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_12.png
  91. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_13.png
  92. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_14.png
  93. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_15.png
  94. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_16.png
  95. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_17.png
  96. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_18.png
  97. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_19.png
  98. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_20.png
  99. BIN
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_21.png
  100. 0 0
      faceplatform-ui/src/main/res/mipmap-xxhdpi/down_22.png

+ 2 - 0
.idea/gradle.xml

@@ -13,6 +13,8 @@
             <option value="$PROJECT_DIR$" />
             <option value="$PROJECT_DIR$/WaterWaveProgress" />
             <option value="$PROJECT_DIR$/app" />
+            <option value="$PROJECT_DIR$/faceplatform-release" />
+            <option value="$PROJECT_DIR$/faceplatform-ui" />
             <option value="$PROJECT_DIR$/joevideolib" />
             <option value="$PROJECT_DIR$/media/app" />
             <option value="$PROJECT_DIR$/media/cge_library" />

+ 9 - 7
app/build.gradle

@@ -15,7 +15,7 @@ android {
         multiDexEnabled true
         testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
         ndk {
-            abiFilters "armeabi-v7a","arm64-v8a"//, 'x86'//, 'armeabi-v7a', 'x86_64', 'arm64-v8a'
+            abiFilters "armeabi-v7a", "arm64-v8a"//, 'x86'//, 'armeabi-v7a', 'x86_64', 'arm64-v8a'
         }
 //        jackOptions {
 //            enabled true
@@ -171,14 +171,14 @@ dependencies {
     implementation files('libs/open_sdk_r5923_lite.jar')
 
     def miniSdkVersion = "1.57.30"
-    implementation ("com.tencent.qqmini:minigame:${miniSdkVersion}"){
+    implementation("com.tencent.qqmini:minigame:${miniSdkVersion}") {
         exclude group: 'com.squareup.okhttp3', module: 'okhttp'
     }
-    implementation ("com.tencent.qqmini:minigame_external:${miniSdkVersion}"){
+    implementation("com.tencent.qqmini:minigame_external:${miniSdkVersion}") {
         exclude group: 'com.squareup.okhttp3', module: 'okhttp'
     }
     // 如果不使用sdk的互联模块,可以不依赖
-    implementation ("com.tencent.qqmini:minigame_open_sdk_all:${miniSdkVersion}"){
+    implementation("com.tencent.qqmini:minigame_open_sdk_all:${miniSdkVersion}") {
         exclude group: 'com.squareup.okhttp3', module: 'okhttp'
     }
 
@@ -221,8 +221,8 @@ dependencies {
     implementation(name: 'alipaySdk-15.5.9', ext: 'aar')
     implementation(name: 'ad_dk_sdk', ext: 'aar')
     implementation(name: 'klevinSDK_2.0.0.21', ext: 'aar')
-    implementation(name: 'lygamewrapper-sheep-release', ext: 'aar'){
-        exclude group: 'com.google.android',module: 'exoplayer2'
+    implementation(name: 'lygamewrapper-sheep-release', ext: 'aar') {
+        exclude group: 'com.google.android', module: 'exoplayer2'
     }
 
     //其中latest.release指代最新版本号,也可以指定明确的版本号,例如1.2.0
@@ -500,7 +500,9 @@ dependencies {
     implementation files('libs/ipaynow_base_2.1.9_api1.0.0.jar')
     implementation files('libs/ipaynow_wechatpay_v2.0.5.jar')
 
-    implementation(name: 'face-sdk-release', ext: 'aar')
+//    implementation(name: 'face-sdk-release', ext: 'aar')
+    implementation project(':faceplatform-ui')
+//    implementation project(':faceplatform-release')
     implementation 'com.airbnb.android:lottie:2.7.0'
 }
 

+ 13 - 1
app/proguard-rules.pro

@@ -15,6 +15,7 @@
 -keepclassmembers class fqcn.of.javascript.interface.for.webview {
    public *;
 }
+-keep class androidx.core.app.CoreComponentFactory { *; }
 
 # Uncomment this to preserve the line number information for
 # debugging stack traces.
@@ -1051,4 +1052,15 @@
 }
 -keep class com.tencent.mm.sdk.** {
     *;
-}
+}
+
+-dontwarn com.baidu.idl.**
+-keep class com.baidu.idl.** { *; }
+-dontwarn com.baidu.vis.**
+-keep class com.baidu.vis.** { *; }
+-dontwarn com.baidu.liantian.**
+-keep class com.baidu.liantian.** { *; }
+-dontwarn com.baidu.protect.**
+-keep class com.baidu.protect.** { *; }
+-dontwarn com.baidu.ocr.**
+-keep class com.baidu.ocr.** { *; }

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 803 - 789
app/src/main/AndroidManifest.xml


+ 11 - 2
app/src/main/java/com/sheep/gamegroup/module/home/fragment/FgtHome.java

@@ -1,10 +1,12 @@
 package com.sheep.gamegroup.module.home.fragment;
 
 import android.os.Bundle;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentTransaction;
 import android.view.View;
 import android.widget.TextView;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentTransaction;
+
 import com.sheep.gamegroup.event.BigEvent;
 import com.sheep.gamegroup.model.entity.UserEntity;
 import com.sheep.gamegroup.util.DataUtil;
@@ -15,12 +17,19 @@ import com.sheep.gamegroup.view.fragment.FgtPersonalCenter;
 import com.sheep.gamegroup.view.fragment.FgtSmallSheep;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.base.BaseFragment;
+
 import org.greenrobot.eventbus.EventBus;
 import org.greenrobot.eventbus.Subscribe;
+
 import java.lang.ref.WeakReference;
+
 import butterknife.BindView;
 import butterknife.OnClick;
 
+/**
+ * 这个类疑似没有展示
+ */
+@Deprecated
 public class FgtHome extends BaseFragment {
 
     public static WeakReference<View> newsRef;

+ 11 - 10
app/src/main/java/com/sheep/gamegroup/module/qrcode/FaceWithQRActivity.java

@@ -7,16 +7,17 @@ import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.Settings;
-import androidx.annotation.NonNull;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
-import androidx.appcompat.app.AlertDialog;
 import android.text.TextUtils;
 import android.util.Log;
 import android.widget.Toast;
 
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
 import com.alibaba.fastjson.JSONObject;
-import com.baidu.idl.face.platform.FaceSDKManager;
+import com.baidu.idl.face.platform.ui.utils.FaceSDKHelper;
 import com.sheep.gamegroup.absBase.BaseActivity;
 import com.sheep.gamegroup.util.Constant;
 import com.sheep.gamegroup.util.Jump2View;
@@ -115,8 +116,8 @@ public class FaceWithQRActivity extends BaseActivity {
                 if (notAsk.size() > 0) {//拒绝不再提醒
 
                     Log.e("TAG", "onRequestPermissionsResult 拒绝不再提醒");
-                    try{
-                        permissionDialog = new  AlertDialog.Builder(this)
+                    try {
+                        permissionDialog = new AlertDialog.Builder(this)
                                 .setMessage("需要同意相机权限,完成人脸识别后才能支付")
                                 .setCancelable(false)
                                 .setNegativeButton("拒绝", new DialogInterface.OnClickListener() {
@@ -137,7 +138,7 @@ public class FaceWithQRActivity extends BaseActivity {
                                     }
                                 })
                                 .show();
-                    }catch (Exception e){
+                    } catch (Exception e) {
                         e.printStackTrace();
                     }
                 } else {
@@ -177,9 +178,9 @@ public class FaceWithQRActivity extends BaseActivity {
     private void dispatch() {
         if (!EmulatorDetectUtil.isEmulator()) {
             if (type == Constant.INTENT_DETECT_LIVENESS) {
-                FaceSDKManager.getInstance().goLivenessCheck(this, FaceSDKManager.NEED_FILEPATH);
+                FaceSDKHelper.getInstance().goLivenessCheck(this);
             } else {
-                FaceSDKManager.getInstance().goFaceDetect(this, FaceSDKManager.NEED_FILEPATH);
+                FaceSDKHelper.getInstance().goFaceDetect(this);
             }
         } else {
             showQRCode();

+ 3 - 5
app/src/main/java/com/sheep/gamegroup/module/qrcode/QRCodeCaptureHelper.java

@@ -5,8 +5,7 @@ import android.net.Uri;
 import android.text.TextUtils;
 
 import com.alibaba.fastjson.JSONObject;
-import com.baidu.idl.face.platform.FaceSDKManager;
-import com.bumptech.glide.Glide;
+import com.baidu.idl.face.platform.ui.utils.FaceSDKHelper;
 import com.sheep.gamegroup.model.entity.BaseMessage;
 import com.sheep.gamegroup.model.entity.QRCode;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
@@ -14,7 +13,6 @@ import com.sheep.gamegroup.util.Constant;
 import com.sheep.gamegroup.util.Jump2View;
 import com.sheep.gamegroup.util.LogUtil;
 import com.sheep.groups.creditcard.RegexUtils;
-import com.sheep.jiuyan.samllsheep.Config;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.utils.G;
 import com.sheep.jiuyan.samllsheep.utils.SpUtils;
@@ -65,9 +63,9 @@ public class QRCodeCaptureHelper {
 
     private static void handleAction(Activity activity, Uri uri, String extra) {
         if (uri.toString().startsWith("sheep://liveness")) {
-            FaceSDKManager.getInstance().goLivenessCheck(activity, FaceSDKManager.NEED_FILEPATH, Constant.INTENT_DETECT_FACE, extra);
+            FaceSDKHelper.getInstance().goLivenessCheck(activity, Constant.INTENT_DETECT_FACE);
         } else if (uri.toString().startsWith("sheep://facedetect")) {
-            FaceSDKManager.getInstance().goFaceDetect(activity, FaceSDKManager.NEED_FILEPATH, Constant.INTENT_DETECT_FACE, extra);
+            FaceSDKHelper.getInstance().goFaceDetect(activity, Constant.INTENT_DETECT_FACE);
         }
     }
 

+ 2 - 2
app/src/main/java/com/sheep/gamegroup/util/DeviceIDUtil.java

@@ -369,8 +369,6 @@ public class DeviceIDUtil {
         }
 
         try {
-            TelephonyManager tm = (TelephonyManager) mContext
-                    .getSystemService(Context.TELEPHONY_SERVICE);
             if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                 // TODO: Consider calling
                 //    ActivityCompat#requestPermissions
@@ -381,6 +379,8 @@ public class DeviceIDUtil {
                 // for ActivityCompat#requestPermissions for more details.
                 return null;
             }
+            TelephonyManager tm = (TelephonyManager) mContext
+                    .getSystemService(Context.TELEPHONY_SERVICE);
             if(tm == null)
                 return null;
             imei = tm.getDeviceId();

+ 1 - 4
app/src/main/java/com/sheep/gamegroup/view/activity/ActSetting.java

@@ -14,6 +14,7 @@ import com.sheep.gamegroup.model.entity.DialogConfig;
 import com.sheep.gamegroup.model.entity.Version;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
 import com.sheep.gamegroup.module.pay.activity.ActPayPassword;
+import com.baidu.idl.face.platform.ui.utils.FaceSDKHelper;
 import com.sheep.gamegroup.util.CommonUtil;
 import com.sheep.gamegroup.util.DataKey;
 import com.sheep.gamegroup.util.DataUtil;
@@ -24,11 +25,7 @@ import com.sheep.jiuyan.samllsheep.Config;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.utils.G;
-import com.sheep.jiuyan.samllsheep.utils.SpUtils;
 import com.sheep.jiuyan.samllsheep.utils.TitleBarUtils;
-import com.tencent.bugly.beta.Beta;
-
-import org.afinal.simplecache.ACache;
 
 import butterknife.BindView;
 import butterknife.OnClick;

+ 5 - 4
app/src/main/java/com/sheep/gamegroup/view/activity/GameCertificationActivity.java

@@ -2,10 +2,6 @@ package com.sheep.gamegroup.view.activity;
 
 import android.content.Intent;
 import android.graphics.Color;
-
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -13,6 +9,10 @@ import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
 import com.sheep.gamegroup.absBase.BaseActivity;
 import com.sheep.gamegroup.greendao.DDProviderHelper;
 import com.sheep.gamegroup.greendao.download.SdkLoginUser;
@@ -192,6 +192,7 @@ public class GameCertificationActivity extends BaseActivity {
 
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
         if (requestCode == Constant.INTENT_DETECT_FACE && resultCode == RESULT_OK && data != null) {
             String token = data.getStringExtra("token");
             String face = data.getStringExtra("face");

+ 1 - 1
app/src/main/java/com/sheep/gamegroup/view/activity/SplashAct.java

@@ -164,7 +164,7 @@ public class SplashAct extends BaseActivity {
     }
 
     void dialogAgree() {
-        ((SheepApp) getApplication()).initOtherSDK();
+//        ((SheepApp) getApplication()).initOtherSDK();
         if (!TextUtils.isEmpty(SpUtils.getToken(SheepApp.getInstance()))) {
             ApiJSONUtil.postUserDeviceLog();
         }

+ 22 - 2
app/src/main/java/com/sheep/jiuyan/samllsheep/SheepApp.java

@@ -17,6 +17,7 @@ import androidx.multidex.MultiDex;
 import androidx.multidex.MultiDexApplication;
 
 import com.baidu.idl.face.platform.FaceSDKManager;
+import com.baidu.idl.face.platform.listener.IInitCallback;
 import com.baidu.location.BDAbstractLocationListener;
 import com.baidu.location.BDLocation;
 import com.baidu.location.LocationClient;
@@ -129,6 +130,7 @@ public class SheepApp extends MultiDexApplication {
     private boolean gameFlag;
     private String wlan;
     private boolean needFace;
+    private boolean otherSDKInit = false;
 
     public void clearGameAuthData() {
         gameId = null;
@@ -369,6 +371,7 @@ public class SheepApp extends MultiDexApplication {
     }
 
     public void initOtherSDK() {
+        otherSDKInit = true;
         registerActivityLifecycleCallbacks(activityLifecycleCallbacks);
         //        小游戏
         MiniSDK.init(this, () -> Log.e("SNOW", "initComplete"));
@@ -439,7 +442,18 @@ public class SheepApp extends MultiDexApplication {
         SkinUtil.init();
 
         //初始化人脸识别
-        FaceSDKManager.getInstance().initialize(this, Config.FACE_LICENSE_ID, Config.FACE_LICENSE_FILE_NAME);
+        FaceSDKManager.getInstance().initialize(this, Config.FACE_LICENSE_ID, Config.FACE_LICENSE_FILE_NAME, new IInitCallback() {
+
+            @Override
+            public void initSuccess() {
+
+            }
+
+            @Override
+            public void initFailure(int i, String s) {
+
+            }
+        });
         /*try {
                 JLibrary.InitEntry(this);
             } catch (Exception e) {
@@ -476,7 +490,7 @@ public class SheepApp extends MultiDexApplication {
         }
         x.Ext.init(this);
         x.Ext.setDebug(org.xutils.BuildConfig.DEBUG); // 是否输出debug日志, 开启debug会影响性能.
-//        initOtherSDK();
+        initOtherSDK();
     }
 
     private IWXAPI wxApi;
@@ -643,6 +657,12 @@ public class SheepApp extends MultiDexApplication {
 
         @Override
         public void onActivityCreated(final Activity activity, Bundle savedInstanceState) {
+            if (!(activity instanceof SplashAct)) {
+                //如果不是启动activity,如果第三方的sdk没初始化,就要初始化第三方SDK
+                if (!otherSDKInit) {
+//                    initOtherSDK();
+                }
+            }
             if (/*activity instanceof SplashAct || */activity instanceof LoginAct) {
                 SysAppUtil.showVersionInfo(activity, SpUtils.getIgnoreMd5());
             } else if (YmConfig.isAvf(activity)) {

+ 1 - 1
app/src/main/res/layout/act_qrcode.xml

@@ -11,7 +11,7 @@
         android:layout_height="40dp"
         android:layout_marginTop="30dp"
         android:layout_marginRight="16dp"
-        android:src="@mipmap/ic_close_ext"
+        android:src="@mipmap/close"
         app:layout_constraintRight_toRightOf="parent"
         app:layout_constraintTop_toTopOf="parent" />
 

+ 2 - 6
build.gradle

@@ -7,9 +7,7 @@ buildscript {
     repositories {
         maven { url 'https://maven.aliyun.com/repository/jcenter' }
         maven { url 'https://maven.aliyun.com/repository/google' }
-        jcenter()
-        google()
-        mavenCentral()
+        maven { url 'https://maven.aliyun.com/repository/central' }
     }
     dependencies {
         classpath 'com.android.tools.build:gradle:7.1.2'
@@ -35,17 +33,15 @@ def isReleaseBuild() {
 
 allprojects {
     repositories {
-        mavenCentral()
         maven { url 'https://maven.aliyun.com/repository/jcenter' }
         maven { url 'https://maven.aliyun.com/repository/google' }
+        maven { url 'https://maven.aliyun.com/repository/central' }
         maven { url 'https://maven.aliyun.com/repository/public' }
         maven {
             url 'https://raw.githubusercontent.com/MDL-Sinlov/MDL-Android-Repo/master/mvn-repo/'
         }
         maven { url "https://github.com/KuaiFaMaster/kfsdk/raw/master" }
-        jcenter()
         maven { url "https://jitpack.io" }
-        google()
     }
 }
 

+ 2 - 0
faceplatform-release/build.gradle

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

BIN
faceplatform-release/faceplatform-release-4.1.5.aar


+ 1 - 0
faceplatform-ui/.gitignore

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

+ 21 - 0
faceplatform-ui/build.gradle

@@ -0,0 +1,21 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 25
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 25
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    api fileTree(dir: 'libs', include: ['*.jar'])
+    api project(path: ':faceplatform-release')
+}

+ 18 - 0
faceplatform-ui/proguard-rules.pro

@@ -0,0 +1,18 @@
+# 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 *;
+#}
+

+ 20 - 0
faceplatform-ui/src/main/AndroidManifest.xml

@@ -0,0 +1,20 @@
+<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="com.baidu.idl.face.platform.ui.FaceDetectActivity"
+            android:hardwareAccelerated="true"
+            android:launchMode="singleTop"
+            android:screenOrientation="portrait"
+            android:theme="@style/Theme_NoTitle" />
+        <activity
+            android:name="com.baidu.idl.face.platform.ui.FaceLivenessActivity"
+            android:hardwareAccelerated="true"
+            android:launchMode="singleTop"
+            android:screenOrientation="portrait"
+            android:theme="@style/Theme_NoTitle" />
+    </application>
+
+</manifest>

+ 84 - 0
faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/BaseActivity.java

@@ -0,0 +1,84 @@
+package com.baidu.idl.face.platform.ui;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+
+public class BaseActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        requestPermissions(99);
+    }
+
+    // 请求权限
+    public void requestPermissions(int requestCode) {
+        try {
+            if (Build.VERSION.SDK_INT >= 23) {
+                ArrayList<String> requestPerssionArr = new ArrayList<>();
+                int hasCamrea = checkSelfPermission(Manifest.permission.CAMERA);
+                if (hasCamrea != PackageManager.PERMISSION_GRANTED) {
+                    requestPerssionArr.add(Manifest.permission.CAMERA);
+                }
+
+                int hasSdcardRead = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
+                if (hasSdcardRead != PackageManager.PERMISSION_GRANTED) {
+                    requestPerssionArr.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+                }
+
+                int hasSdcardWrite = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+                if (hasSdcardWrite != PackageManager.PERMISSION_GRANTED) {
+                    requestPerssionArr.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+                }
+                // 是否应该显示权限请求
+                if (requestPerssionArr.size() >= 1) {
+                    String[] requestArray = new String[requestPerssionArr.size()];
+                    for (int i = 0; i < requestArray.length; i++) {
+                        requestArray[i] = requestPerssionArr.get(i);
+                    }
+                    requestPermissions(requestArray, requestCode);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String[] permissions,
+                                           int[] grantResults) {
+        boolean flag = false;
+        for (int i = 0; i < permissions.length; i++) {
+            if (PackageManager.PERMISSION_GRANTED == grantResults[i]) {
+                flag = true;
+            }
+        }
+    }
+
+    /**
+     * 自定义Toast
+     * @param message toast 消息
+     */
+    public void showCustomToast(String message) {
+        LayoutInflater layoutInflater = getLayoutInflater();
+        View inflate = layoutInflater.inflate(R.layout.setting_toast_layout,
+                (ViewGroup) findViewById(R.id.toast_layout));
+        TextView toastTxt = (TextView) inflate.findViewById(R.id.toast_txt);
+        toastTxt.setText(message);
+        Toast toast = new Toast(this);
+        toast.setDuration(Toast.LENGTH_SHORT);
+        toast.setGravity(Gravity.CENTER, 0, 0);
+        toast.setView(inflate);
+        toast.show();
+    }
+}

+ 73 - 0
faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/CameraActivity.java

@@ -0,0 +1,73 @@
+package com.baidu.idl.face.platform.ui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.baidu.idl.face.platform.model.ImageInfo;
+import com.baidu.idl.face.platform.utils.Base64Utils;
+import com.baidu.idl.face.platform.utils.BitmapUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CameraActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    protected void handleBest(HashMap<String, ImageInfo> imageSrcMap) {
+        // 将原图集合中的图片按照质量降序排序,最终选取质量最优的一张原图图片
+        String bmpStr = null;
+        if (imageSrcMap != null && imageSrcMap.size() > 0) {
+            List<Map.Entry<String, ImageInfo>> list2 = new ArrayList<>(imageSrcMap.entrySet());
+            Collections.sort(list2, new Comparator<Map.Entry<String, ImageInfo>>() {
+
+                @Override
+                public int compare(Map.Entry<String, ImageInfo> o1,
+                                   Map.Entry<String, ImageInfo> o2) {
+                    String[] key1 = o1.getKey().split("_");
+                    String score1 = key1[2];
+                    String[] key2 = o2.getKey().split("_");
+                    String score2 = key2[2];
+                    // 降序排序
+                    return Float.valueOf(score2).compareTo(Float.valueOf(score1));
+                }
+            });
+            bmpStr = list2.get(0).getValue().getBase64();
+
+            // 获取原图中的加密或非加密的base64
+//            int secType = mFaceConfig.getSecType();
+//            String base64;
+//            if (secType == 0) {
+//                base64 = list2.get(0).getValue().getBase64();
+//            } else {
+//                base64 = list2.get(0).getValue().getSecBase64();
+//            }
+        }
+        String facePath = saveBaseImage(bmpStr);
+        Intent result = new Intent();
+        result.putExtra("bestPath", facePath);
+        setResult(RESULT_OK, result);
+        finish();
+    }
+
+    protected String saveBaseImage(String base64) {
+        byte[] bytes = Base64Utils.decode(base64, Base64Utils.NO_WRAP);
+        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
+        File faceImage = new File(getFilesDir(), "face.jpg");
+        Log.d("saveBaseImage", faceImage.getAbsolutePath());
+//        BitmapUtils.compressToFile(bitmap, 100, faceImage.getAbsolutePath());
+        BitmapUtils.saveBitmap(faceImage, bitmap);
+        return faceImage.getAbsolutePath();
+    }
+}

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

@@ -0,0 +1,563 @@
+/**
+ * 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.os.Bundle;
+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.View;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.baidu.idl.face.platform.FaceConfig;
+import com.baidu.idl.face.platform.FaceSDKManager;
+import com.baidu.idl.face.platform.FaceStatusNewEnum;
+import com.baidu.idl.face.platform.IDetectStrategy;
+import com.baidu.idl.face.platform.IDetectStrategyCallback;
+import com.baidu.idl.face.platform.model.ImageInfo;
+import com.baidu.idl.face.platform.ui.utils.BrightnessUtils;
+import com.baidu.idl.face.platform.ui.utils.CameraPreviewUtils;
+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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 人脸采集接口
+ */
+public class FaceDetectActivity extends CameraActivity implements
+        SurfaceHolder.Callback,
+        Camera.PreviewCallback,
+        Camera.ErrorCallback,
+        VolumeUtils.VolumeCallback,
+        IDetectStrategyCallback {
+
+    public static final String TAG = FaceDetectActivity.class.getSimpleName();
+
+    // View
+    protected View mRootView;
+    protected FrameLayout mFrameLayout;
+    protected SurfaceView mSurfaceView;
+    protected SurfaceHolder mSurfaceHolder;
+    protected ImageView mCloseView;
+    protected ImageView mSoundView;
+    protected ImageView mSuccessView;
+    protected TextView mTipsTopView;
+    protected FaceDetectRoundView mFaceDetectRoundView;
+    protected LinearLayout mImageLayout;
+    protected LinearLayout mImageLayout2;
+    public View mViewBg;
+    // 人脸信息
+    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 HashMap<String, String> mBase64ImageMap = new HashMap<String, String>();
+    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;
+    // 是否弹窗
+    protected boolean mHasShownTimeoutDialog;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setScreenBright();
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        setContentView(R.layout.activity_face_detect_v3100);
+        DisplayMetrics dm = new DisplayMetrics();
+        Display display = this.getWindowManager().getDefaultDisplay();
+        display.getMetrics(dm);
+        mDisplayWidth = dm.widthPixels;
+        mDisplayHeight = dm.heightPixels;
+
+        FaceSDKResSettings.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;
+
+        mRootView = this.findViewById(R.id.detect_root_layout);
+        mFrameLayout = (FrameLayout) mRootView.findViewById(R.id.detect_surface_layout);
+
+        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;
+
+        // surfaceView使用屏幕分辨率的大小
+//        FrameLayout.LayoutParams cameraFL = new FrameLayout.LayoutParams(
+//                (int) (w * FaceDetectRoundView.SURFACE_RATIO), (int) (h * FaceDetectRoundView.SURFACE_RATIO),
+//                Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
+        // surfaceView使用640*480的大小
+        FrameLayout.LayoutParams cameraFL = new FrameLayout.LayoutParams(
+                (int) (w * FaceDetectRoundView.SURFACE_RATIO * FaceDetectRoundView.RECT_RATIO),
+                (int) (w * FaceDetectRoundView.SURFACE_RATIO * FaceDetectRoundView.RECT_RATIO * 640.0f / 480.0f),
+                Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
+
+        mSurfaceView.setLayoutParams(cameraFL);
+        mFrameLayout.addView(mSurfaceView);
+
+        mRootView.findViewById(R.id.detect_close).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                onBackPressed();
+            }
+        });
+
+        mFaceDetectRoundView = (FaceDetectRoundView) mRootView.findViewById(R.id.detect_face_round);
+        mFaceDetectRoundView.setIsActiveLive(false);
+        mCloseView = (ImageView) mRootView.findViewById(R.id.detect_close);
+        mSoundView = (ImageView) mRootView.findViewById(R.id.detect_sound);
+        mSoundView.setImageResource(mIsEnableSound ?
+                R.mipmap.icon_titlebar_voice2 : R.drawable.collect_image_voice_selector);
+        mSoundView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mIsEnableSound = !mIsEnableSound;
+                mSoundView.setImageResource(mIsEnableSound ?
+                        R.mipmap.icon_titlebar_voice2 : R.drawable.collect_image_voice_selector);
+                if (mIDetectStrategy != null) {
+                    mIDetectStrategy.setDetectStrategySoundEnable(mIsEnableSound);
+                }
+            }
+        });
+        mTipsTopView = (TextView) mRootView.findViewById(R.id.detect_top_tips);
+        mSuccessView = (ImageView) mRootView.findViewById(R.id.detect_success_image);
+
+        mImageLayout = (LinearLayout) mRootView.findViewById(R.id.detect_result_image_layout);
+        mImageLayout2 = (LinearLayout) mRootView.findViewById(R.id.detect_result_image_layout2);
+        mViewBg = findViewById(R.id.view_bg);
+        if (mBase64ImageMap != null) {
+            mBase64ImageMap.clear();
+        }
+    }
+
+    /**
+     * 设置屏幕亮度
+     */
+    private void setScreenBright() {
+        int currentBright = BrightnessUtils.getScreenBrightness(this);
+        BrightnessUtils.setBrightness(this, currentBright + 100);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (!mHasShownTimeoutDialog) {
+            setVolumeControlStream(AudioManager.STREAM_MUSIC);
+            mVolumeReceiver = VolumeUtils.registerVolumeReceiver(this, this);
+            if (mFaceDetectRoundView != null) {
+                mFaceDetectRoundView.setTipTopText("请将脸移入取景框");
+            }
+            startPreview();
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (mIDetectStrategy != null) {
+            mIDetectStrategy.reset();
+        }
+        super.onPause();
+        VolumeUtils.unRegisterVolumeReceiver(this, mVolumeReceiver);
+        mVolumeReceiver = null;
+        mIsCompletion = false;
+        stopPreview();
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+    }
+
+    @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.icon_titlebar_voice2 : R.mipmap.icon_titlebar_voice1);
+                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) {
+            CameraUtils.releaseCamera(mCamera);
+            mCamera = null;
+        }
+
+        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);
+
+        // 获取前置摄像头预览角度,为90度
+        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));
+        // 以640 * 480为基准选取分辨率
+        Point point = CameraPreviewUtils.getBestPreview(mCameraParam,
+                new Point(640, 480));
+
+        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.reset();
+            mIDetectStrategy = null;
+        }
+    }
+
+    /**
+     * 获取摄像头预览角度
+     *
+     * @param context 当前上下文
+     * @return
+     */
+    private int displayOrientation(Context context) {
+        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        if (windowManager == null) {
+            return 90;
+        }
+
+        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(FaceStatusNewEnum status, String message,
+                                   HashMap<String, ImageInfo> base64ImageCropMap,
+                                   HashMap<String, ImageInfo> base64ImageSrcMap) {
+        if (mIsCompletion) {
+            return;
+        }
+
+        onRefreshView(status, message);
+
+        if (status == FaceStatusNewEnum.OK) {
+            mIsCompletion = true;
+            handleBest(base64ImageSrcMap);
+            // saveAllImage(base64ImageCropMap, base64ImageSrcMap);
+        }
+    }
+
+    private void onRefreshView(FaceStatusNewEnum status, String message) {
+        switch (status) {
+            case OK:
+                mFaceDetectRoundView.setTipTopText(message);
+                // onRefreshSuccessView(true);
+                // onRefreshTipsView(false, message);
+                break;
+            case DetectRemindCodePitchOutofUpRange:
+            case DetectRemindCodePitchOutofDownRange:
+            case DetectRemindCodeYawOutofLeftRange:
+            case DetectRemindCodeYawOutofRightRange:
+                mFaceDetectRoundView.setTipTopText(message);
+                // onRefreshTipsView(true, message);
+                // onRefreshSuccessView(false);
+                break;
+            default:
+                mFaceDetectRoundView.setTipTopText(message);
+                // onRefreshTipsView(false, message);
+                // onRefreshSuccessView(false);
+        }
+    }
+
+    private static Bitmap base64ToBitmap(String base64Data) {
+        byte[] bytes = Base64Utils.decode(base64Data, Base64Utils.NO_WRAP);
+        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
+    }
+
+    // ----------------------------------------供调试用----------------------------------------------
+    private void saveAllImage(HashMap<String, ImageInfo> imageCropMap, HashMap<String, ImageInfo> imageSrcMap) {
+        if (imageCropMap != null && imageCropMap.size() > 0) {
+            List<Map.Entry<String, ImageInfo>> list1 = new ArrayList<>(imageCropMap.entrySet());
+            Collections.sort(list1, new Comparator<Map.Entry<String, ImageInfo>>() {
+
+                @Override
+                public int compare(Map.Entry<String, ImageInfo> o1,
+                                   Map.Entry<String, ImageInfo> o2) {
+                    String[] key1 = o1.getKey().split("_");
+                    String score1 = key1[2];
+                    String[] key2 = o2.getKey().split("_");
+                    String score2 = key2[2];
+                    // 降序排序
+                    return Float.valueOf(score2).compareTo(Float.valueOf(score1));
+                }
+            });
+            setImageView1(list1);
+        }
+
+        if (imageSrcMap != null && imageSrcMap.size() > 0) {
+            List<Map.Entry<String, ImageInfo>> list2 = new ArrayList<>(imageSrcMap.entrySet());
+            Collections.sort(list2, new Comparator<Map.Entry<String, ImageInfo>>() {
+
+                @Override
+                public int compare(Map.Entry<String, ImageInfo> o1,
+                                   Map.Entry<String, ImageInfo> o2) {
+                    String[] key1 = o1.getKey().split("_");
+                    String score1 = key1[2];
+                    String[] key2 = o2.getKey().split("_");
+                    String score2 = key2[2];
+                    // 降序排序
+                    return Float.valueOf(score2).compareTo(Float.valueOf(score1));
+                }
+            });
+            setImageView2(list2);
+        }
+    }
+
+    private void setImageView1(List<Map.Entry<String, ImageInfo>> list) {
+        Bitmap bmp = null;
+        mImageLayout.removeAllViews();
+        for (Map.Entry<String, ImageInfo> entry : list) {
+            bmp = base64ToBitmap(entry.getValue().getBase64());
+            ImageView iv = new ImageView(this);
+            iv.setImageBitmap(bmp);
+            mImageLayout.addView(iv, new LinearLayout.LayoutParams(300, 300));
+        }
+    }
+
+    private void setImageView2(List<Map.Entry<String, ImageInfo>> list) {
+        Bitmap bmp = null;
+        mImageLayout2.removeAllViews();
+        for (Map.Entry<String, ImageInfo> entry : list) {
+            bmp = base64ToBitmap(entry.getValue().getBase64());
+            ImageView iv = new ImageView(this);
+            iv.setImageBitmap(bmp);
+            mImageLayout2.addView(iv, new LinearLayout.LayoutParams(300, 300));
+        }
+    }
+}

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

@@ -0,0 +1,725 @@
+/**
+ * Copyright (C) 2017 Baidu Inc. All rights reserved.
+ */
+package com.baidu.idl.face.platform.ui;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.hardware.Camera;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.baidu.idl.face.platform.FaceConfig;
+import com.baidu.idl.face.platform.FaceSDKManager;
+import com.baidu.idl.face.platform.FaceStatusNewEnum;
+import com.baidu.idl.face.platform.ILivenessStrategy;
+import com.baidu.idl.face.platform.ILivenessStrategyCallback;
+import com.baidu.idl.face.platform.ILivenessViewCallback;
+import com.baidu.idl.face.platform.LivenessTypeEnum;
+import com.baidu.idl.face.platform.manager.TimeManager;
+import com.baidu.idl.face.platform.model.FaceExtInfo;
+import com.baidu.idl.face.platform.model.ImageInfo;
+import com.baidu.idl.face.platform.ui.utils.BrightnessUtils;
+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.ui.utils.CameraPreviewUtils;
+import com.baidu.idl.face.platform.utils.DensityUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import com.baidu.idl.face.platform.utils.BitmapUtils;
+/**
+ * 活体检测接口
+ */
+public class FaceLivenessActivity extends CameraActivity implements
+        SurfaceHolder.Callback,
+        Camera.PreviewCallback,
+        Camera.ErrorCallback,
+        VolumeUtils.VolumeCallback,
+        ILivenessStrategyCallback,
+        ILivenessViewCallback {
+
+    public static final String TAG = FaceLivenessActivity.class.getSimpleName();
+
+    // View
+    protected View mRootView;
+    protected FrameLayout mFrameLayout;
+    protected SurfaceView mSurfaceView;
+    protected SurfaceHolder mSurfaceHolder;
+    protected ImageView mCloseView;
+    protected ImageView mSoundView;
+    protected ImageView mSuccessView;
+    protected TextView mTipsTopView;
+    protected FaceDetectRoundView mFaceDetectRoundView;
+    protected LinearLayout mImageLayout;
+    protected LinearLayout mImageLayout2;
+    private RelativeLayout mRelativeAddImageView;
+    private ImageView mImageAnim;
+    public View mViewBg;
+    // 人脸信息
+    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;
+    // 是否弹窗
+    protected boolean mHasShownTimeoutDialog;
+
+    private Context mContext;
+    private AnimationDrawable mAnimationDrawable;
+    private LivenessTypeEnum mLivenessType = null;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setScreenBright();
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        setContentView(R.layout.activity_face_liveness_v3100);
+        mContext = FaceLivenessActivity.this;
+        DisplayMetrics dm = new DisplayMetrics();
+        Display display = this.getWindowManager().getDefaultDisplay();
+        display.getMetrics(dm);
+        mDisplayWidth = dm.widthPixels;
+        mDisplayHeight = dm.heightPixels;
+
+        FaceSDKResSettings.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;
+
+        mRootView = this.findViewById(R.id.liveness_root_layout);
+        mFrameLayout = (FrameLayout) mRootView.findViewById(R.id.liveness_surface_layout);
+
+        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;
+
+        // surfaceView使用屏幕分辨率的大小
+//        FrameLayout.LayoutParams cameraFL = new FrameLayout.LayoutParams(
+//                (int) (w * FaceDetectRoundView.SURFACE_RATIO), (int) (h * FaceDetectRoundView.SURFACE_RATIO),
+//                Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
+        // surfaceView使用640*480的大小
+        FrameLayout.LayoutParams cameraFL = new FrameLayout.LayoutParams(
+                (int) (w * FaceDetectRoundView.SURFACE_RATIO * FaceDetectRoundView.RECT_RATIO),
+                (int) (w * FaceDetectRoundView.SURFACE_RATIO * FaceDetectRoundView.RECT_RATIO * 640.0f / 480.0f),
+                Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
+
+        mSurfaceView.setLayoutParams(cameraFL);
+        mFrameLayout.addView(mSurfaceView);
+
+        mRootView.findViewById(R.id.liveness_close).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                onBackPressed();
+            }
+        });
+
+        mFaceDetectRoundView = (FaceDetectRoundView) mRootView.findViewById(R.id.liveness_face_round);
+        mFaceDetectRoundView.setIsActiveLive(true);
+        mCloseView = (ImageView) mRootView.findViewById(R.id.liveness_close);
+        mSoundView = (ImageView) mRootView.findViewById(R.id.liveness_sound);
+        mSoundView.setImageResource(mIsEnableSound ?
+                R.mipmap.icon_titlebar_voice2 : R.drawable.collect_image_voice_selector);
+        mSoundView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mIsEnableSound = !mIsEnableSound;
+                mSoundView.setImageResource(mIsEnableSound ?
+                        R.mipmap.icon_titlebar_voice2 : R.drawable.collect_image_voice_selector);
+                if (mILivenessStrategy != null) {
+                    mILivenessStrategy.setLivenessStrategySoundEnable(mIsEnableSound);
+                }
+            }
+        });
+        mTipsTopView = (TextView) mRootView.findViewById(R.id.liveness_top_tips);
+        mSuccessView = (ImageView) mRootView.findViewById(R.id.liveness_success_image);
+
+        mImageLayout = (LinearLayout) mRootView.findViewById(R.id.liveness_result_image_layout);
+        mImageLayout2 = (LinearLayout) mRootView.findViewById(R.id.liveness_result_image_layout2);
+        mRelativeAddImageView = (RelativeLayout) mRootView.findViewById(R.id.relative_add_image_view);
+        addImageView();
+        mViewBg = findViewById(R.id.view_live_bg);
+    }
+
+    /**
+     * 设置屏幕亮度
+     */
+    private void setScreenBright() {
+        int currentBright = BrightnessUtils.getScreenBrightness(this);
+        BrightnessUtils.setBrightness(this, currentBright + 100);
+    }
+
+    /**
+     * 动态加载ImageView
+     */
+    private void addImageView() {
+        mFaceDetectRoundView.post(new Runnable() {
+            @Override
+            public void run() {
+                mImageAnim = new ImageView(FaceLivenessActivity.this);
+                RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup
+                        .LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+                layoutParams.height = DensityUtils.dip2px(mContext, 110); // 设置图片的高度
+                layoutParams.width = DensityUtils.dip2px(mContext, 87);   // 设置图片的宽度
+                float halfHeight = mFaceDetectRoundView.getHeight() / 2;
+                layoutParams.setMargins(0, (int) (halfHeight - (halfHeight * FaceDetectRoundView.HEIGHT_RATIO))
+                        - layoutParams.height / 2, 0, 0);
+                layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
+                mImageAnim.setLayoutParams(layoutParams);
+                mImageAnim.setScaleType(ImageView.ScaleType.FIT_XY);  // 使图片充满控件大小
+                mRelativeAddImageView.addView(mImageAnim);
+            }
+        });
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (!mHasShownTimeoutDialog) {
+            setVolumeControlStream(AudioManager.STREAM_MUSIC);
+            mVolumeReceiver = VolumeUtils.registerVolumeReceiver(this, this);
+            if (mFaceDetectRoundView != null) {
+                mFaceDetectRoundView.setTipTopText("请将脸移入取景框");
+            }
+            startPreview();
+        }
+    }
+
+    @Override
+    protected void onRestart() {
+        super.onRestart();
+        Log.e(TAG, "onRestart");
+    }
+
+    @Override
+    public void onPause() {
+        if (mILivenessStrategy != null) {
+            mILivenessStrategy.reset();
+        }
+        VolumeUtils.unRegisterVolumeReceiver(this, mVolumeReceiver);
+        mVolumeReceiver = null;
+        mFaceDetectRoundView.setProcessCount(0,
+                mFaceConfig.getLivenessTypeList().size());
+        super.onPause();
+        stopPreview();
+        mIsCompletion = false;
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+    }
+
+    @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.icon_titlebar_voice2 : R.mipmap.icon_titlebar_voice1);
+                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) {
+            CameraUtils.releaseCamera(mCamera);
+            mCamera = null;
+        }
+
+        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);
+
+        // 获取前置摄像头预览角度,为90度
+        int degree = displayOrientation(this);
+        mCamera.setDisplayOrientation(degree);
+        // 设置后无效,camera.setDisplayOrientation方法有效
+        mCameraParam.set("rotation", degree);
+        mPreviewDegree = degree;
+
+        // 以屏幕分辨率为基准选取分辨率
+//        Point point = CameraPreviewUtils.getBestPreview(mCameraParam,
+//                new Point(mDisplayWidth, mDisplayHeight));
+        // 以640 * 480为基准选取分辨率
+        Point point = CameraPreviewUtils.getBestPreview(mCameraParam,
+                new Point(640, 480));
+
+        mPreviewWidth = point.x;
+        mPreviewHight = point.y;
+        // Log.e(TAG, "x = " + mPreviewWidth + " y = " + mPreviewHight);
+        // 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;
+        }
+    }
+
+    /**
+     * 获取摄像头预览角度
+     * @param context 当前上下文
+     * @return
+     */
+    private int displayOrientation(Context context) {
+        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        if (windowManager == null) {
+            return 90;
+        }
+
+        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(this);
+            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(FaceStatusNewEnum status, String message,
+                                     HashMap<String, ImageInfo> base64ImageCropMap,
+                                     HashMap<String, ImageInfo> base64ImageSrcMap, int currentLivenessCount) {
+        if (mIsCompletion) {
+            return;
+        }
+
+        onRefreshView(status, message, currentLivenessCount);
+
+        if (status == FaceStatusNewEnum.OK) {
+            mIsCompletion = true;
+            handleBest(base64ImageSrcMap);
+            // saveAllImage(base64ImageCropMap, base64ImageSrcMap);
+        }
+    }
+
+    private void onRefreshView(FaceStatusNewEnum status, String message, int currentLivenessCount) {
+        switch (status) {
+            case OK:
+            case FaceLivenessActionComplete:
+            case DetectRemindCodeTooClose:
+            case DetectRemindCodeTooFar:
+            case DetectRemindCodeBeyondPreviewFrame:
+            case DetectRemindCodeNoFaceDetected:
+                // onRefreshTipsView(false, message);
+                mFaceDetectRoundView.setTipTopText(message);
+                mFaceDetectRoundView.setTipSecondText("");
+                mFaceDetectRoundView.setProcessCount(currentLivenessCount,
+                        mFaceConfig.getLivenessTypeList().size());
+                // onRefreshSuccessView(true);
+                stopAnim();
+                break;
+            case FaceLivenessActionTypeLiveEye:
+            case FaceLivenessActionTypeLiveMouth:
+            case FaceLivenessActionTypeLivePitchUp:
+            case FaceLivenessActionTypeLivePitchDown:
+            case FaceLivenessActionTypeLiveYawLeft:
+            case FaceLivenessActionTypeLiveYawRight:
+            case FaceLivenessActionTypeLiveYaw:
+                mFaceDetectRoundView.setTipTopText(message);
+                mFaceDetectRoundView.setTipSecondText("");
+                mFaceDetectRoundView.setProcessCount(currentLivenessCount,
+                        mFaceConfig.getLivenessTypeList().size());
+                // onRefreshTipsView(false, message);
+                // onRefreshSuccessView(false);
+                break;
+            case DetectRemindCodePitchOutofUpRange:
+            case DetectRemindCodePitchOutofDownRange:
+            case DetectRemindCodeYawOutofLeftRange:
+            case DetectRemindCodeYawOutofRightRange:
+                mFaceDetectRoundView.setTipTopText("请保持正脸");
+                mFaceDetectRoundView.setTipSecondText(message);
+                mFaceDetectRoundView.setProcessCount(currentLivenessCount,
+                        mFaceConfig.getLivenessTypeList().size());
+                // onRefreshSuccessView(false);
+                // onRefreshTipsView(true, message);
+                break;
+            case FaceLivenessActionCodeTimeout:    // 动作超时,播放教程动画
+                mFaceDetectRoundView.setProcessCount(currentLivenessCount,
+                        mFaceConfig.getLivenessTypeList().size());
+                // 帧动画开启
+                if (mRelativeAddImageView.getVisibility() == View.INVISIBLE) {
+                    mRelativeAddImageView.setVisibility(View.VISIBLE);
+                }
+                loadAnimSource();
+                // 监听帧动画时间
+                int duration = 0;
+                for (int i = 0; i < mAnimationDrawable.getNumberOfFrames(); i++) {
+                    // 计算动画播放的时间
+                    duration += mAnimationDrawable.getDuration(i);
+                }
+                TimeManager.getInstance().setActiveAnimTime(duration);
+                break;
+            default:
+                mFaceDetectRoundView.setTipTopText("请保持正脸");
+                mFaceDetectRoundView.setTipSecondText(message);
+                mFaceDetectRoundView.setProcessCount(currentLivenessCount,
+                        mFaceConfig.getLivenessTypeList().size());
+                // onRefreshSuccessView(false);
+                // onRefreshTipsView(false, message);
+                break;
+        }
+    }
+
+    // 加载动画
+    private void loadAnimSource() {
+        if (mLivenessType != null) {
+            switch (mLivenessType) {
+                case Eye:
+                    mImageAnim.setBackgroundResource(R.drawable.anim_eye);
+                    break;
+//                case HeadLeftOrRight:
+//                    mImageAnim.setBackgroundResource(R.drawable.anim_shake);
+//                    break;
+                case HeadLeft:
+                    mImageAnim.setBackgroundResource(R.drawable.anim_left);
+                    break;
+                case HeadRight:
+                    mImageAnim.setBackgroundResource(R.drawable.anim_right);
+                    break;
+                case HeadDown:
+                    mImageAnim.setBackgroundResource(R.drawable.anim_down);
+                    break;
+                case HeadUp:
+                    mImageAnim.setBackgroundResource(R.drawable.anim_up);
+                    break;
+                case Mouth:
+                    mImageAnim.setBackgroundResource(R.drawable.anim_mouth);
+                    break;
+                default:
+                    break;
+            }
+            mAnimationDrawable = (AnimationDrawable) mImageAnim.getBackground();
+            mAnimationDrawable.start();
+        }
+    }
+
+    private static Bitmap base64ToBitmap(String base64Data) {
+        byte[] bytes = Base64Utils.decode(base64Data, Base64Utils.NO_WRAP);
+        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
+    }
+
+    @Override
+    public void setCurrentLiveType(LivenessTypeEnum liveType) {
+        mLivenessType = liveType;
+    }
+
+    @Override
+    public void viewReset() {
+        mFaceDetectRoundView.setProcessCount(0, 1);
+    }
+
+    @Override
+    public void animStop() {
+        stopAnim();
+    }
+
+    @Override
+    public void setFaceInfo(FaceExtInfo faceInfo) {
+        // TODO:传递FaceInfo信息,便于调试画人脸检测框和人脸检测区域(使用时,将注释放开)
+        // if (mFaceDetectRoundView != null) {
+        //     mFaceDetectRoundView.setFaceInfo(faceInfo);
+        // }
+    }
+
+    private void stopAnim() {
+        if (mAnimationDrawable != null) {
+            mAnimationDrawable.stop();
+            mAnimationDrawable = null;
+        }
+        if (mRelativeAddImageView.getVisibility() == View.VISIBLE) {
+            mRelativeAddImageView.setVisibility(View.INVISIBLE);
+        }
+    }
+
+    // ----------------------------------------供调试用----------------------------------------------
+    private void saveAllImage(HashMap<String, ImageInfo> imageCropMap, HashMap<String, ImageInfo> imageSrcMap) {
+        if (imageCropMap != null && imageCropMap.size() > 0) {
+            List<Map.Entry<String, ImageInfo>> list1 = new ArrayList<>(imageCropMap.entrySet());
+            Collections.sort(list1, new Comparator<Map.Entry<String, ImageInfo>>() {
+
+                @Override
+                public int compare(Map.Entry<String, ImageInfo> o1,
+                                   Map.Entry<String, ImageInfo> o2) {
+                    String[] key1 = o1.getKey().split("_");
+                    String score1 = key1[2];
+                    String[] key2 = o2.getKey().split("_");
+                    String score2 = key2[2];
+                    // 降序排序
+                    return Float.valueOf(score2).compareTo(Float.valueOf(score1));
+                }
+            });
+            setImageView1(list1);
+        }
+
+        if (imageSrcMap != null && imageSrcMap.size() > 0) {
+            List<Map.Entry<String, ImageInfo>> list2 = new ArrayList<>(imageSrcMap.entrySet());
+            Collections.sort(list2, new Comparator<Map.Entry<String, ImageInfo>>() {
+
+                @Override
+                public int compare(Map.Entry<String, ImageInfo> o1,
+                                   Map.Entry<String, ImageInfo> o2) {
+                    String[] key1 = o1.getKey().split("_");
+                    String score1 = key1[2];
+                    String[] key2 = o2.getKey().split("_");
+                    String score2 = key2[2];
+                    // 降序排序
+                    return Float.valueOf(score2).compareTo(Float.valueOf(score1));
+                }
+            });
+            setImageView2(list2);
+        }
+    }
+
+    private void setImageView1(List<Map.Entry<String, ImageInfo>> list) {
+        Bitmap bmp = null;
+        mImageLayout.removeAllViews();
+        for (Map.Entry<String, ImageInfo> entry : list) {
+            bmp = base64ToBitmap(entry.getValue().getBase64());
+            ImageView iv = new ImageView(this);
+            iv.setImageBitmap(bmp);
+            mImageLayout.addView(iv, new LinearLayout.LayoutParams(300, 300));
+        }
+    }
+
+    private void setImageView2(List<Map.Entry<String, ImageInfo>> list) {
+        Bitmap bmp = null;
+        mImageLayout2.removeAllViews();
+        for (Map.Entry<String, ImageInfo> entry : list) {
+            bmp = base64ToBitmap(entry.getValue().getBase64());
+            ImageView iv = new ImageView(this);
+            iv.setImageBitmap(bmp);
+            mImageLayout2.addView(iv, new LinearLayout.LayoutParams(300, 300));
+        }
+    }
+}

+ 100 - 0
faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/FaceSDKResSettings.java

@@ -0,0 +1,100 @@
+/**
+ * Copyright (C) 2017 Baidu Inc. All rights reserved.
+ */
+package com.baidu.idl.face.platform.ui;
+
+import com.baidu.idl.face.platform.FaceEnvironment;
+import com.baidu.idl.face.platform.FaceStatusNewEnum;
+
+/**
+ * sdk使用Res资源设置功能
+ */
+public class FaceSDKResSettings {
+
+    /**
+     * 初始化Id(新)
+     */
+    public static void initializeResId() {
+        // Sound Res Id
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.DetectRemindCodeNoFaceDetected,
+                R.raw.detect_face_in);
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.DetectRemindCodeBeyondPreviewFrame,
+                R.raw.detect_face_in);
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.DetectRemindCodeNoFaceDetected,
+                R.raw.detect_face_in);
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.FaceLivenessActionTypeLiveEye,
+                R.raw.liveness_eye);
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.FaceLivenessActionTypeLiveMouth,
+                R.raw.liveness_mouth);
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.FaceLivenessActionTypeLivePitchUp,
+                R.raw.liveness_head_up);
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.FaceLivenessActionTypeLivePitchDown,
+                R.raw.liveness_head_down);
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.FaceLivenessActionTypeLiveYawLeft,
+                R.raw.liveness_head_left);
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.FaceLivenessActionTypeLiveYawRight,
+                R.raw.liveness_head_right);
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.FaceLivenessActionComplete,
+                R.raw.face_good);
+        FaceEnvironment.setSoundId(FaceStatusNewEnum.OK, R.raw.face_good);
+
+        // Tips Res Id
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeNoFaceDetected,
+                R.string.detect_face_in);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeBeyondPreviewFrame,
+                R.string.detect_face_in);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodePoorIllumination,
+                R.string.detect_low_light);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeImageBlured,
+                R.string.detect_keep);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeOcclusionLeftEye,
+                R.string.detect_occ_left_eye);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeOcclusionRightEye,
+                R.string.detect_occ_right_eye);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeOcclusionNose,
+                R.string.detect_occ_nose);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeOcclusionMouth,
+                R.string.detect_occ_mouth);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeOcclusionLeftContour,
+                R.string.detect_occ_left_check);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeOcclusionRightContour,
+                R.string.detect_occ_right_check);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeOcclusionChinContour,
+                R.string.detect_occ_chin);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodePitchOutofUpRange,
+                R.string.detect_head_down);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodePitchOutofDownRange,
+                R.string.detect_head_up);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeYawOutofLeftRange,
+                R.string.detect_head_right);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeYawOutofRightRange,
+                R.string.detect_head_left);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeTooFar,
+                R.string.detect_zoom_in);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeTooClose,
+                R.string.detect_zoom_out);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeLeftEyeClosed,
+                R.string.detect_left_eye_close);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeRightEyeClosed,
+                R.string.detect_right_eye_close);
+
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.FaceLivenessActionTypeLiveEye,
+                R.string.liveness_eye);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.FaceLivenessActionTypeLiveMouth,
+                R.string.liveness_mouth);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.FaceLivenessActionTypeLivePitchUp,
+                R.string.liveness_head_up);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.FaceLivenessActionTypeLivePitchDown,
+                R.string.liveness_head_down);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.FaceLivenessActionTypeLiveYawLeft,
+                R.string.liveness_head_left);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.FaceLivenessActionTypeLiveYawRight,
+                R.string.liveness_head_right);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.FaceLivenessActionComplete,
+                R.string.liveness_good);
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.OK, R.string.liveness_good);
+
+        FaceEnvironment.setTipsId(FaceStatusNewEnum.DetectRemindCodeTimeout,
+                R.string.detect_timeout);
+    }
+}

+ 87 - 0
faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/BrightnessUtils.java

@@ -0,0 +1,87 @@
+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.util.Log;
+import android.view.WindowManager;
+
+/**
+ * 调节屏幕亮度工具类
+ * Created by v_liujialu01 on 2020/3/13.
+ */
+
+public class BrightnessUtils {
+    private static final String TAG = "BrightnessUtils";
+
+    /**
+     * 判断是否开启了自动亮度调节
+     */
+    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 (Settings.SettingNotFoundException e) {
+            e.printStackTrace();
+        }
+        return automicBrightness;
+    }
+
+    /**
+     * 获取屏幕的亮度
+     */
+    public static int getScreenBrightness(Activity activity) {
+        int nowBrightnessValue = 0;
+        ContentResolver resolver = activity.getContentResolver();
+        try {
+            nowBrightnessValue = android.provider.Settings.System.getInt(
+                    resolver, Settings.System.SCREEN_BRIGHTNESS);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return nowBrightnessValue;
+    }
+
+    /**
+     * 设置亮度
+     */
+    public static void setBrightness(Activity activity, int brightness) {
+        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
+        lp.screenBrightness = Float.valueOf(brightness) * (1f / 255f);
+        Log.d(TAG, "set  lp.screenBrightness == " + lp.screenBrightness);
+        activity.getWindow().setAttributes(lp);
+    }
+
+    /**
+     * 停止自动亮度调节
+     */
+    public static void stopAutoBrightness(Activity activity) {
+        Settings.System.putInt(activity.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS_MODE,
+                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+    }
+
+    /**
+     * 开启亮度自动调节
+     */
+    public static void startAutoBrightness(Activity activity) {
+        Settings.System.putInt(activity.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS_MODE,
+                Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+    }
+
+    /**
+     * 保存亮度设置状态
+     */
+    public static void saveBrightness(ContentResolver resolver, int brightness) {
+        Uri uri = android.provider.Settings.System
+                .getUriFor("screen_brightness");
+
+        android.provider.Settings.System.putInt(resolver, "screen_brightness",
+                brightness);
+        resolver.notifyChange(uri, null);
+    }
+}

+ 102 - 0
faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/CameraPreviewUtils.java

@@ -0,0 +1,102 @@
+/**
+ * Copyright (C) 2016 Baidu Inc. All rights reserved.
+ */
+package com.baidu.idl.face.platform.ui.utils;
+
+import android.graphics.Point;
+import android.hardware.Camera;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * 相机配置
+ */
+public final class CameraPreviewUtils {
+
+    private static final String TAG = CameraPreviewUtils.class.getSimpleName();
+    private static final int MIN_PREVIEW_PIXELS = 640 * 480;
+    private static final int MAX_PREVIEW_PIXELS = 1920 * 1080;
+
+    public static Point getBestPreview(Camera.Parameters parameters, Point screenResolution) {
+
+        List<Camera.Size> rawSupportedSizes = parameters.getSupportedPreviewSizes();
+        if (rawSupportedSizes == null) {
+            Camera.Size defaultSize = parameters.getPreviewSize();
+            return new Point(640, 480);
+            // return new Point(defaultSize.width, defaultSize.height);
+        }
+
+        List<Camera.Size> supportedPictureSizes = new ArrayList<Camera.Size>(rawSupportedSizes);
+        Collections.sort(supportedPictureSizes, new Comparator<Camera.Size>() {
+            @Override
+            public int compare(Camera.Size a, Camera.Size b) {
+                int aPixels = a.height * a.width;
+                int bPixels = b.height * b.width;
+                if (bPixels < aPixels) {
+                    return -1;
+                }
+                if (bPixels > aPixels) {
+                    return 1;
+                }
+                return 0;
+            }
+        });
+
+        final double screenAspectRatio = (screenResolution.x > screenResolution.y) ?
+                ((double) screenResolution.x / (double) screenResolution.y) :
+                ((double) screenResolution.y / (double) screenResolution.x);
+
+        Camera.Size selectedSize = null;
+        double selectedMinus = -1;
+        double selectedPreviewSize = 0;
+        Iterator<Camera.Size> it = supportedPictureSizes.iterator();
+        while (it.hasNext()) {
+            Camera.Size supportedPreviewSize = it.next();
+            int realWidth = supportedPreviewSize.width;
+            int realHeight = supportedPreviewSize.height;
+//            Log.e(TAG, "preview size " + realWidth + " " + realHeight);
+            if (realWidth * realHeight < MIN_PREVIEW_PIXELS) {
+                it.remove();
+                continue;
+            } else if (realWidth * realHeight > MAX_PREVIEW_PIXELS) {
+                it.remove();
+                continue;
+            } else if (realHeight > realWidth) {  // 过滤其横屏分辨率
+                it.remove();
+                continue;
+            } else if (realHeight % 2 != 0 || realWidth % 2 != 0) {
+                it.remove();
+                continue;
+            } else {
+                double aRatio = (supportedPreviewSize.width > supportedPreviewSize.height) ?
+                        ((double) supportedPreviewSize.width / (double) supportedPreviewSize.height) :
+                        ((double) supportedPreviewSize.height / (double) supportedPreviewSize.width);
+                double minus = Math.abs(aRatio - screenAspectRatio);
+
+                boolean selectedFlag = false;
+                if ((selectedMinus == -1 && minus <= 0.25f)
+                        || (selectedMinus >= minus && minus <= 0.25f)) {
+                    selectedFlag = true;
+                }
+                if (selectedFlag) {
+                    selectedMinus = minus;
+                    selectedSize = supportedPreviewSize;
+                    selectedPreviewSize = realWidth * realHeight;
+                }
+            }
+        }
+
+        if (selectedSize != null) {
+            Camera.Size preview = selectedSize;
+            return new Point(preview.width, preview.height);
+        } else {
+            Camera.Size defaultSize = parameters.getPreviewSize();
+            // return new Point(defaultSize.width, defaultSize.height);
+            return new Point(640, 480);
+        }
+    }
+}

+ 25 - 0
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 {
+        }
+    }
+}

+ 81 - 0
faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/FaceSDKHelper.java

@@ -0,0 +1,81 @@
+/**
+ * Copyright (C) 2017 Baidu Inc. All rights reserved.
+ */
+package com.baidu.idl.face.platform.ui.utils;
+
+import android.app.Activity;
+import android.content.Intent;
+
+import com.baidu.idl.face.platform.FaceConfig;
+import com.baidu.idl.face.platform.FaceSDKManager;
+import com.baidu.idl.face.platform.LivenessTypeEnum;
+import com.baidu.idl.face.platform.ui.FaceDetectActivity;
+import com.baidu.idl.face.platform.ui.FaceLivenessActivity;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * FaceSDK功能接口
+ */
+public class FaceSDKHelper {
+    public final static int NEED_FILEPATH = 1;
+    public final static int REQUEST_FACE_LIVENESS = 1001;
+    public final static int REQUEST_FACE_DETECT = 1002;
+    private static FaceSDKHelper instance = null;
+
+    private FaceSDKHelper() {
+    }
+
+    public static FaceSDKHelper getInstance() {
+        if (instance == null) {
+            synchronized (FaceSDKHelper.class) {
+                if (instance == null) {
+                    instance = new FaceSDKHelper();
+                }
+            }
+        }
+        return instance;
+    }
+
+    private List<LivenessTypeEnum> getRandoms(int count, List<LivenessTypeEnum> list) {
+        List<LivenessTypeEnum> result = new ArrayList<>();
+        Random r = new Random(System.currentTimeMillis());
+        for (int i = 0; i < count; i++) {
+            int index = r.nextInt(list.size());
+            result.add(list.remove(index));
+        }
+        return result;
+    }
+
+    public void goLivenessCheck(Activity activity) {
+        goLivenessCheck(activity, REQUEST_FACE_LIVENESS);
+    }
+
+    public void goLivenessCheck(Activity activity, int requestCode) {
+        List<LivenessTypeEnum> arr = Arrays.asList(LivenessTypeEnum.Eye,
+                LivenessTypeEnum.HeadDown,
+                LivenessTypeEnum.HeadUp,
+                LivenessTypeEnum.Mouth,
+                LivenessTypeEnum.HeadLeft,
+                LivenessTypeEnum.HeadRight,
+                LivenessTypeEnum.Eye);
+        List<LivenessTypeEnum> list = new ArrayList<>(arr);
+        FaceConfig mFaceConfig = FaceSDKManager.getInstance().getFaceConfig();
+        mFaceConfig.setLivenessTypeList(getRandoms(3, list));
+        Intent in = new Intent(activity, FaceLivenessActivity.class);
+        activity.startActivityForResult(in, requestCode);
+    }
+
+    public void goFaceDetect(Activity activity) {
+        goFaceDetect(activity,REQUEST_FACE_DETECT);
+    }
+
+    public void goFaceDetect(Activity activity, int requestCode) {
+        Intent in = new Intent(activity, FaceDetectActivity.class);
+        activity.startActivityForResult(in, requestCode);
+    }
+
+}

+ 36 - 0
faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/IntentUtils.java

@@ -0,0 +1,36 @@
+package com.baidu.idl.face.platform.ui.utils;
+
+public class IntentUtils {
+    private static IntentUtils instance = null;
+
+    private String mBitmap;
+
+    /**
+     * 单例模式
+     * @return FaceSDKManager实体
+     */
+    public static IntentUtils getInstance() {
+        if (instance == null) {
+            synchronized (IntentUtils.class) {
+                if (instance == null) {
+                    instance = new IntentUtils();
+                }
+            }
+        }
+        return instance;
+    }
+
+    public void setBitmap(String bitmap) {
+        mBitmap = bitmap;
+    }
+
+    public String getBitmap() {
+        return mBitmap;
+    }
+
+    public void release() {
+        if (instance != null) {
+            instance = null;
+        }
+    }
+}

+ 151 - 0
faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/utils/SecRequest.java

@@ -0,0 +1,151 @@
+package com.baidu.idl.face.platform.ui.utils;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.baidu.idl.face.platform.FaceSDKManager;
+
+import org.json.JSONObject;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+
+/**
+ * 数据加密请求
+ * Created by v_liujialu01 on 2020/4/15.
+ */
+
+public class SecRequest {
+    private static final String TAG = SecRequest.class.getSimpleName();
+
+    private static final String REQUEST_URL = "http://10.138.32.176:8518/api/v3/person/verify_sec?appid=7758258";
+
+//    JSONObject jsonObject = new JSONObject();
+//    jsonObject.put("image_type", "BASE64");                           // 图片类型
+//    jsonObject.put("image", secBase64);                               // 图片加密字符串
+//    jsonObject.put("id_card_number", "101111111111111111");           // 身份证号
+//    jsonObject.put("name", URLDecoder.decode("张三", "UTF-8"));       // 姓名
+//    jsonObject.put("quality_control", "NONE");                        // 质量控制
+//    jsonObject.put("liveness_control", "NONE");                       // 活体控制
+//    jsonObject.put("risk_identify", true);                            // 是否开启风控人证
+//    jsonObject.put("zid", LH.gzfi(FaceDetectActivity.this, null, 5001, null));   // zid
+//    jsonObject.put("ip", "172.30.154.173");                           // ip
+//    jsonObject.put("phone", "13000000000");                           // 手机号
+//    jsonObject.put("image_sec", true);                                // 是否进行图片加密
+//    jsonObject.put("app", "Android");                                 // 应用类型
+//    jsonObject.put("ev", "smrz");                                     // 用途
+
+    public static void sendMessage(final Context context, final String secBase64, final int secType) {
+        Runnable runnable = new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    JSONObject jsonObject = new JSONObject();
+                    jsonObject.put("image_type", "BASE64");
+                    jsonObject.put("image", secBase64);
+                    jsonObject.put("id_card_number", "101111111111111111");
+                    jsonObject.put("name", URLDecoder.decode("张三", "UTF-8"));
+                    jsonObject.put("quality_control", "NONE");
+                    jsonObject.put("liveness_control", "NONE");
+                    // TODO:是否开启风控认证,但如果sceType为false时,该参数必须传入false
+                    jsonObject.put("risk_identify", false);
+                    jsonObject.put("zid", FaceSDKManager.getInstance().getZid(context));
+                    jsonObject.put("ip", "172.30.154.173");
+                    jsonObject.put("phone", "13000000000");
+                    if (secType == 0) {
+                        jsonObject.put("image_sec", false);
+                    } else if (secType == 1) {
+                        jsonObject.put("image_sec", true);
+                    }
+                    jsonObject.put("app", "Android");
+                    jsonObject.put("ev", "smrz");
+
+                    requestPost(jsonObject.toString(), REQUEST_URL);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        };
+        Thread thread = new Thread(runnable);
+        thread.start();
+    }
+
+    private static String requestPost(String paramStr, String requestUrl) {
+        HttpURLConnection conn = null; // 连接对象
+        int responseCode = -1;
+        String resultData = null;
+
+        OutputStream outputStream = null;
+        InputStream inputStream = null;
+        ByteArrayOutputStream baos = null;
+        try {
+            URL url = new URL(requestUrl);
+            conn = (HttpURLConnection) url.openConnection();
+            System.setProperty("sun.net.client.defaultConnectTimeout", "8000");
+            System.setProperty("sun.net.client.defaultReadTimeout", "8000");
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            conn.setRequestMethod("POST");
+            conn.setUseCaches(false);
+            conn.setRequestProperty("User-Agent",
+                    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;");
+            conn.setRequestProperty("Accept-Language", "zh-CN");
+            conn.setRequestProperty("Connection", "Keep-Alive");
+            conn.setRequestProperty("Charset", "UTF-8");
+            conn.setRequestProperty("Content-Type", "application/json");
+            conn.connect();
+            outputStream = conn.getOutputStream();
+            outputStream.write(paramStr.getBytes());
+            outputStream.flush();
+            outputStream.close();
+            responseCode = conn.getResponseCode();
+            Log.e(TAG, "request code " + responseCode);
+            if (HttpURLConnection.HTTP_OK == responseCode) {
+                inputStream = conn.getInputStream();
+                byte[] buffer = new byte[1024];
+                baos = new ByteArrayOutputStream();
+                int len = -1;
+                while ((len = inputStream.read(buffer)) != -1) {
+                    baos.write(buffer, 0, len);
+                }
+                byte[] b = baos.toByteArray();
+                resultData = new String(b, "utf-8");
+                baos.flush();
+                Log.e(TAG, "request data " + resultData);
+            }
+        } catch (MalformedURLException e) {
+            Log.e(TAG, "MalformedURLException " + e.getMessage());
+            e.printStackTrace();
+        } catch (IOException e) {
+            Log.e(TAG, "IOException " + e.getMessage());
+            e.printStackTrace();
+        } catch (Exception e) {
+            Log.e(TAG, "Exception " + e.getMessage());
+            e.printStackTrace();
+        } finally {
+            try {
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+                if (baos != null) {
+                    baos.close();
+                }
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+                if (conn != null) {
+                    conn.disconnect();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return resultData;
+    }
+}

+ 68 - 0
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();
+        }
+    }
+}

+ 121 - 0
faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/view/AlignTextView.java

@@ -0,0 +1,121 @@
+package com.baidu.idl.face.platform.ui.view;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.text.Layout;
+import android.text.StaticLayout;
+import android.text.TextPaint;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+/**
+ * Created by v_shishuaifeng on 2020/3/12.
+ */
+
+public class AlignTextView extends TextView {
+    private int mLineY;
+    private int mViewWidth;
+
+    public AlignTextView(Context context) {
+        super(context);
+    }
+
+    public AlignTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        TextPaint paint = getPaint();
+        paint.setColor(getCurrentTextColor());
+        // 返回绘制状态的资源ID数组表示视图的当前状态
+        paint.drawableState = getDrawableState();
+        // 对View上的内容进行测量后得到的View内容占据的宽度
+        // 前提是你必须在父布局的onLayout()方法或者此View的onDraw()方法里调用measure(0,0);
+        // 否则你得到的结果和getWidth()得到的结果一样。
+        mViewWidth = getMeasuredWidth();
+        // 获取文本
+        String text = getText().toString();
+        mLineY = 0;
+        mLineY += getTextSize();
+        // 获取用于显示当前文本的布局
+        Layout layout = getLayout();
+        if (layout == null) {
+            return;
+        }
+        Paint.FontMetrics fm = paint.getFontMetrics();
+        int textHeight = (int) Math.ceil(fm.descent - fm.ascent);
+        textHeight = (int) (textHeight * layout.getSpacingMultiplier() + layout.getSpacingAdd());
+        for (int i = 0; i < layout.getLineCount(); i++) {
+            // 返回文本中的指定行开头的偏移
+            int lineStart = layout.getLineStart(i);
+            // 返回文本中的指定行最后一个字符的偏移
+            int lineEnd = layout.getLineEnd(i);
+            float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint());
+            String line = text.substring(lineStart, lineEnd);
+            if (line.equals("")) {
+                break;
+            }
+            if (i < layout.getLineCount() - 1) {
+                if (needScale(line)) {
+                    drawScaledText(canvas, line, width);
+                } else {
+                    canvas.drawText(line, 0, mLineY, paint);
+                }
+            } else {
+                canvas.drawText(line, 0, mLineY, paint);
+            }
+            // 增加行高
+            mLineY += textHeight;
+        }
+
+    }
+
+    private void drawScaledText(Canvas canvas, String line, float width) {
+        float x = 0;
+        if (isFirstLineOfParagraph(line)) {
+            String blanks = "  ";
+            canvas.drawText(blanks, x, mLineY, getPaint());
+            float bw = StaticLayout.getDesiredWidth(blanks, getPaint());
+            x += bw;
+            line = line.substring(3);
+        }
+        int gapCount = line.length() - 1;
+        int i = 0;
+        if (line.length() > 2 && line.charAt(0) == 12288
+                && line.charAt(1) == 12288) {
+            String substring = line.substring(0, 2);
+            float cw = StaticLayout.getDesiredWidth(substring, getPaint());
+            canvas.drawText(substring, x, mLineY, getPaint());
+            x += cw;
+            i += 2;
+        }
+        float d = (mViewWidth - width) / gapCount;
+        for (; i < line.length(); i++) {
+            String c = String.valueOf(line.charAt(i));
+            float cw = StaticLayout.getDesiredWidth(c, getPaint());
+            canvas.drawText(c, x, mLineY, getPaint());
+            x += cw + d;
+        }
+    }
+
+    private boolean isFirstLineOfParagraph(String line) {
+        return line.length() > 3 && line.charAt(0) == ' ' && line.charAt(1) == ' ';
+    }
+
+    private boolean needScale(String line) {
+        if (line.length() == 0) {
+            return false;
+        } else {
+            return line.charAt(line.length() - 1) != '\n';
+        }
+    }
+}

+ 240 - 0
faceplatform-ui/src/main/java/com/baidu/idl/face/platform/ui/widget/CircleImageView.java

@@ -0,0 +1,240 @@
+package com.baidu.idl.face.platform.ui.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+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.RectF;
+import android.graphics.Shader;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import com.baidu.idl.face.platform.ui.R;
+
+
+/**
+ * Created by v_liujialu01 on 2018/12/3.
+ */
+
+@SuppressLint("AppCompatCustomView")
+public class CircleImageView extends ImageView {
+    private static final String TAG = CircleImageView.class.getSimpleName();
+    private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
+    private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
+    private static final int COLORDRAWABLE_DIMENSION = 2;
+    private static final int DEFAULT_BORDER_WIDTH = 0;
+    private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
+    private final RectF mDrawableRect = new RectF();
+    private final RectF mBorderRect = new RectF();
+    private final Matrix mShaderMatrix = new Matrix();
+    private final Paint mBitmapPaint = new Paint();
+    private final Paint mBorderPaint = new Paint();
+    private int mBorderColor = DEFAULT_BORDER_COLOR;
+    private int mBorderWidth = DEFAULT_BORDER_WIDTH;
+    private Bitmap mBitmap;
+    private BitmapShader mBitmapShader;
+    private int mBitmapWidth;
+    private int mBitmapHeight;
+    private float mDrawableRadius;
+    private float mBorderRadius;
+    private boolean mReady;
+    private boolean mSetupPending;
+
+    public CircleImageView(Context context) {
+        super(context);
+        init();
+    }
+
+    public CircleImageView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView,
+                defStyle, 0);
+        mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width,
+                DEFAULT_BORDER_WIDTH);
+        mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);
+        a.recycle();
+        init();
+    }
+
+    private void init() {
+        super.setScaleType(SCALE_TYPE);
+        mReady = true;
+        if (mSetupPending) {
+            setup();
+            mSetupPending = false;
+        }
+    }
+
+    @Override
+    public ScaleType getScaleType() {
+        return SCALE_TYPE;
+    }
+
+    @Override
+    public void setScaleType(ScaleType scaleType) {
+        // LogUtils.i(TAG, "scaleType = " + scaleType);
+    }
+
+    @Override
+    public void setAdjustViewBounds(boolean adjustViewBounds) {
+        if (adjustViewBounds) {
+            throw new IllegalArgumentException("adjustViewBounds not supported.");
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (getDrawable() == null) {
+            return;
+        }
+        canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
+        if (mBorderWidth != 0) {
+            canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);
+        }
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        setup();
+    }
+
+    public int getBorderColor() {
+        return mBorderColor;
+    }
+
+    public void setBorderColor(int borderColor) {
+        if (borderColor == mBorderColor) {
+            return;
+        }
+        mBorderColor = borderColor;
+        mBorderPaint.setColor(mBorderColor);
+        invalidate();
+    }
+
+    public int getBorderWidth() {
+        return mBorderWidth;
+    }
+
+    public void setBorderWidth(int borderWidth) {
+        if (borderWidth == mBorderWidth) {
+            return;
+        }
+        mBorderWidth = borderWidth;
+        setup();
+    }
+
+    @Override
+    public void setImageBitmap(Bitmap bm) {
+        super.setImageBitmap(bm);
+        mBitmap = bm;
+        setup();
+    }
+
+    @Override
+    public void setImageDrawable(Drawable drawable) {
+        super.setImageDrawable(drawable);
+        mBitmap = getBitmapFromDrawable(drawable);
+        setup();
+    }
+
+    @Override
+    public void setImageResource(int resId) {
+        super.setImageResource(resId);
+        mBitmap = getBitmapFromDrawable(getDrawable());
+        setup();
+    }
+
+    @Override
+    public void setImageURI(Uri uri) {
+        super.setImageURI(uri);
+        mBitmap = getBitmapFromDrawable(getDrawable());
+        setup();
+    }
+
+    private Bitmap getBitmapFromDrawable(Drawable drawable) {
+        try {
+
+            if (drawable instanceof BitmapDrawable) {
+                return ((BitmapDrawable) drawable).getBitmap();
+            }
+
+            Bitmap bitmap;
+            if (drawable instanceof ColorDrawable) {
+                bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION,
+                        BITMAP_CONFIG);
+            } else {
+                bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
+                        BITMAP_CONFIG);
+            }
+            Canvas canvas = new Canvas(bitmap);
+            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+            drawable.draw(canvas);
+            return bitmap;
+        } catch (Exception e) {
+            // LogUtils.e(TAG, "e = " + e.getMessage());
+            return null;
+        }
+    }
+
+    private void setup() {
+        if (!mReady) {
+            mSetupPending = true;
+            return;
+        }
+        if (mBitmap == null) {
+            return;
+        }
+        int power = 2;
+        mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
+        mBitmapPaint.setAntiAlias(true);
+        mBitmapPaint.setShader(mBitmapShader);
+        mBorderPaint.setStyle(Paint.Style.STROKE);
+        mBorderPaint.setAntiAlias(true);
+        mBorderPaint.setColor(mBorderColor);
+        mBorderPaint.setStrokeWidth(mBorderWidth);
+        mBitmapHeight = mBitmap.getHeight();
+        mBitmapWidth = mBitmap.getWidth();
+        mBorderRect.set(0, 0, getWidth(), getHeight());
+        mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / power,
+                (mBorderRect.width() - mBorderWidth) / power);
+        mDrawableRect.set(mBorderWidth, mBorderWidth,
+                mBorderRect.width() - mBorderWidth,
+                mBorderRect.height() - mBorderWidth);
+        mDrawableRadius = Math.min(mDrawableRect.height() / power, mDrawableRect.width() / power);
+        updateShaderMatrix();
+        invalidate();
+    }
+
+    private void updateShaderMatrix() {
+        float scale;
+        float dx = 0;
+        float dy = 0;
+        float power = 0.5f;
+        mShaderMatrix.set(null);
+        if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
+            scale = mDrawableRect.height() / (float) mBitmapHeight;
+            dx = (mDrawableRect.width() - mBitmapWidth * scale) * power;
+        } else {
+            scale = mDrawableRect.width() / (float) mBitmapWidth;
+            dy = (mDrawableRect.height() - mBitmapHeight * scale) * power;
+        }
+        mShaderMatrix.setScale(scale, scale);
+        mShaderMatrix.postTranslate((int) (dx + power) + mBorderWidth,
+                (int) (dy + power) + mBorderWidth);
+        mBitmapShader.setLocalMatrix(mShaderMatrix);
+    }
+}

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

@@ -0,0 +1,283 @@
+/**
+ * Copyright (C) 2017 Baidu Inc. All rights reserved.
+ */
+package com.baidu.idl.face.platform.ui.widget;
+
+import android.content.Context;
+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.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+
+import com.baidu.idl.face.platform.model.FaceExtInfo;
+import com.baidu.idl.face.platform.utils.DensityUtils;
+
+/**
+ * 人脸检测区域View
+ */
+public class FaceDetectRoundView extends View {
+
+    private static final String TAG = FaceDetectRoundView.class.getSimpleName();
+
+    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 = 5;
+    public static final int PATH_SPACE = 16;
+    public static final int PATH_SMALL_SPACE = 12;
+    public static final int CIRCLE_LINE_WIDTH = 3;
+    public static final float RECT_RATIO = 0.9f;
+
+    public static final int COLOR_BG = Color.parseColor("#FFFFFF");
+    // public static final int COLOR_RECT = Color.parseColor("#FFFFFF");
+    public static final int COLOR_ROUND = Color.parseColor("#FFA800");
+    public static final int COLOR_CIRCLE_LINE = Color.parseColor("#CCCCCC");
+    public static final int COLOR_CIRCLE_SELECT_LINE = Color.parseColor("#00BAF2");
+
+    private Paint mBGPaint;
+    private Paint mFaceRoundPaint;
+    private Paint mCircleLinePaint;
+    private Paint mCircleLineSelectPaint;
+    private Rect mFaceRect;
+    private Rect mFaceDetectRect;
+    private Paint mTextSecondPaint;
+    private Paint mTextTopPaint;
+
+    private float mX;
+    private float mY;
+    private float mR;
+    private int mTotalActiveCount;
+    private int mSuccessActiveCount;
+    private boolean mIsActiveLive;
+    private String mTipSecondText;
+    private String mTipTopText;
+
+    private static float mRatioX;
+    private static float mRatioY;
+    private FaceExtInfo mFaceExtInfo;
+
+    public FaceDetectRoundView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+
+        // DisplayMetrics dm = context.getResources().getDisplayMetrics();
+        // float pathSpace = DensityUtils.dip2px(context, PATH_SPACE);
+        // float pathSmallSpace = DensityUtils.dip2px(context, PATH_SMALL_SPACE);
+        float circleLineWidth = DensityUtils.dip2px(context, CIRCLE_LINE_WIDTH);
+
+        mBGPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mBGPaint.setColor(COLOR_BG);
+        mBGPaint.setStyle(Paint.Style.FILL);
+        mBGPaint.setAntiAlias(true);
+        mBGPaint.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);
+
+        mCircleLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mCircleLinePaint.setColor(COLOR_CIRCLE_LINE);
+        mCircleLinePaint.setStrokeWidth(circleLineWidth);
+        mCircleLinePaint.setStyle(Paint.Style.STROKE);
+        mCircleLinePaint.setAntiAlias(true);
+        mCircleLinePaint.setDither(true);
+
+        mCircleLineSelectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mCircleLineSelectPaint.setColor(COLOR_CIRCLE_SELECT_LINE);
+        mCircleLineSelectPaint.setStrokeWidth(circleLineWidth);
+        mCircleLineSelectPaint.setStyle(Paint.Style.STROKE);
+        mCircleLineSelectPaint.setAntiAlias(true);
+        mCircleLineSelectPaint.setDither(true);
+
+        mTextSecondPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mTextSecondPaint.setColor(Color.parseColor("#666666"));
+        mTextSecondPaint.setTextSize(DensityUtils.dip2px(getContext(), 16));
+        mTextSecondPaint.setTextAlign(Paint.Align.CENTER);
+        mTextSecondPaint.setAntiAlias(true);
+        mTextSecondPaint.setDither(true);
+
+        mTextTopPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mTextTopPaint.setColor(Color.parseColor("#000000"));
+        mTextTopPaint.setTextSize(DensityUtils.dip2px(getContext(), 22));
+        mTextTopPaint.setTextAlign(Paint.Align.CENTER);
+        mTextTopPaint.setAntiAlias(true);
+        mTextTopPaint.setDither(true);
+    }
+
+    public void setProcessCount(int successActiveCount, int totalActiveCount) {
+        mSuccessActiveCount = successActiveCount;
+        mTotalActiveCount = totalActiveCount;
+        postInvalidate();
+    }
+
+    public void setFaceInfo(FaceExtInfo faceExtInfo) {
+        mFaceExtInfo = faceExtInfo;
+        postInvalidate();
+    }
+
+    public void setIsActiveLive(boolean isActiveLive) {
+        mIsActiveLive = isActiveLive;
+    }
+
+    public void setTipTopText(String tipTopText) {
+        mTipTopText = tipTopText;
+        if (!TextUtils.isEmpty(tipTopText)) {
+            invalidate();
+        }
+    }
+
+    public void setTipSecondText(String tipSecondText) {
+        mTipSecondText = tipSecondText;
+        if (!TextUtils.isEmpty(tipSecondText)) {
+            invalidate();
+        }
+    }
+
+    public float getRound() {
+        return mR;
+    }
+
+    public Rect getFaceRoundRect() {
+        if (mFaceRect != null) {
+            Log.e(TAG, mFaceRect.toString());
+        }
+        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));
+        }
+        mX = x;
+        mY = y;
+        mR = r;
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        canvas.drawColor(Color.TRANSPARENT);
+        canvas.drawPaint(mBGPaint);
+        canvas.drawCircle(mX, mY, mR, mFaceRoundPaint);
+        // TODO:画检测区域(用于调试,这4个参数分别表示屏幕宽高和手机摄像头分辨率宽高,需要手动修改)
+        // TODO:(使用时,将注释放开)
+        // canvas.drawRect(getPreviewDetectRect(1080, 1920, 432, 768), mCircleLinePaint);
+        // TODO:画人脸检测框(用于调试,使用时,将注释放开)
+        // if (getFaceInfoRect(mFaceExtInfo) != null) {
+        //     canvas.drawRect(getFaceInfoRect(mFaceExtInfo), mCircleLinePaint);
+        // }
+        // 画文字
+        if (!TextUtils.isEmpty(mTipSecondText)) {
+            canvas.drawText(mTipSecondText, mX, mY - mR - 40 - 25 - 59, mTextSecondPaint);
+        }
+        if (!TextUtils.isEmpty(mTipTopText)) {
+            canvas.drawText(mTipTopText, mX, mY - mR - 40 - 25 - 59 - 90, mTextTopPaint);
+        }
+        if (mIsActiveLive) {
+            canvas.translate(mX, mY);
+            // 画默认进度
+            drawCircleLine(canvas);
+            // 画成功进度
+            drawSuccessCircleLine(canvas);
+        }
+    }
+
+    // 画默认刻度线
+    private void drawCircleLine(Canvas canvas) {
+        canvas.save();
+        canvas.rotate(-90);
+        for (int j = 0; j < 360; j += 6) {
+            canvas.drawLine(mR + 40, 0, mR + 40 + 25,
+                    0, mCircleLinePaint);
+            canvas.rotate(6);
+        }
+        canvas.restore();
+    }
+
+    // 画成功刻度线
+    private void drawSuccessCircleLine(Canvas canvas) {
+        int degree = (int) ((float) mSuccessActiveCount / (float) mTotalActiveCount * 360.0f);
+        // Log.e(TAG, "selectDegree = " + degree);
+        canvas.save();
+        canvas.rotate(-90);
+        for (int j = 0; j < degree; j += 6) {
+            canvas.drawLine(mR + 40, 0, mR + 40 + 25,
+                    0, mCircleLineSelectPaint);
+            canvas.rotate(6);
+        }
+        canvas.restore();
+    }
+
+    // ----------------------------------------供调试用----------------------------------------------
+
+    // 获取人脸检测区域
+    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));
+        // Log.e(TAG, "FaceRoundView getPreviewDetectRect " + pw + "-" + ph + "-" + rect.toString());
+        return rect;
+    }
+
+    // 获取人脸检测区域(调试使用)
+    public static Rect getPreviewDetectRect(int w, int h, int pw, int ph) {
+        float round = (w / 2) - ((w / 2) * WIDTH_SPACE_RATIO);
+        mRatioX = (w * 1.0f) / (pw * 1.0f);
+        mRatioY = (h * 1.0f) / (ph * 1.0f);  // 获取屏幕宽高和手机摄像头宽高的比值,用于映射
+        float x = pw / 2.0f * mRatioX;
+        float y = (ph / 2.0f * mRatioY) - ((ph / 2.0f * mRatioY) * HEIGHT_RATIO);
+        float r = (pw / 2.0f * mRatioX) > round ? round : (pw / 2.0f * mRatioX);
+        float hr = r + (r * HEIGHT_EXT_RATIO);
+        Rect rect = new Rect((int) (x - r),
+                (int) (y - hr),
+                (int) (x + r),
+                (int) (y + hr));
+        // Log.e(TAG, "FaceRoundView getPreviewDetectRect " + pw + "-" + ph + "-" + rect.toString());
+        return rect;
+    }
+
+    // 获取人脸检测框(调试使用)
+    public static Rect getFaceInfoRect(FaceExtInfo faceInfo) {
+        if (faceInfo == null) {
+            return null;
+        }
+        return faceInfo.getFaceRect(mRatioX, mRatioY, SURFACE_RATIO);
+    }
+
+}

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


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


BIN
faceplatform-ui/src/main/jniLibs/arm64-v8a/libc++_shared.so


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


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


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


BIN
faceplatform-ui/src/main/jniLibs/armeabi-v7a/libc++_shared.so


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


+ 36 - 0
faceplatform-ui/src/main/res/drawable/anim_down.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="true">
+    <item android:drawable="@mipmap/down_00" android:duration="50"/>
+    <item android:drawable="@mipmap/down_01" android:duration="50"/>
+    <item android:drawable="@mipmap/down_02" android:duration="50"/>
+    <item android:drawable="@mipmap/down_03" android:duration="50"/>
+    <item android:drawable="@mipmap/down_04" android:duration="50"/>
+    <item android:drawable="@mipmap/down_05" android:duration="50"/>
+    <item android:drawable="@mipmap/down_06" android:duration="50"/>
+    <item android:drawable="@mipmap/down_07" android:duration="50"/>
+    <item android:drawable="@mipmap/down_08" android:duration="50"/>
+    <item android:drawable="@mipmap/down_09" android:duration="50"/>
+    <item android:drawable="@mipmap/down_10" android:duration="50"/>
+    <item android:drawable="@mipmap/down_11" android:duration="50"/>
+    <item android:drawable="@mipmap/down_12" android:duration="50"/>
+    <item android:drawable="@mipmap/down_13" android:duration="50"/>
+    <item android:drawable="@mipmap/down_14" android:duration="50"/>
+    <item android:drawable="@mipmap/down_15" android:duration="50"/>
+    <item android:drawable="@mipmap/down_16" android:duration="50"/>
+    <item android:drawable="@mipmap/down_17" android:duration="50"/>
+    <item android:drawable="@mipmap/down_18" android:duration="50"/>
+    <item android:drawable="@mipmap/down_19" android:duration="50"/>
+    <item android:drawable="@mipmap/down_20" android:duration="50"/>
+    <item android:drawable="@mipmap/down_21" android:duration="50"/>
+    <item android:drawable="@mipmap/down_22" android:duration="50"/>
+    <item android:drawable="@mipmap/down_23" android:duration="50"/>
+    <item android:drawable="@mipmap/down_24" android:duration="50"/>
+    <item android:drawable="@mipmap/down_25" android:duration="50"/>
+    <item android:drawable="@mipmap/down_26" android:duration="50"/>
+    <item android:drawable="@mipmap/down_27" android:duration="50"/>
+    <item android:drawable="@mipmap/down_28" android:duration="50"/>
+    <item android:drawable="@mipmap/down_29" android:duration="50"/>
+    <item android:drawable="@mipmap/down_30" android:duration="50"/>
+    <item android:drawable="@mipmap/down_31" android:duration="50"/>
+</animation-list>

+ 24 - 0
faceplatform-ui/src/main/res/drawable/anim_eye.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="true">
+    <item android:drawable="@mipmap/eye_00" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_01" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_02" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_03" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_04" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_05" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_06" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_07" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_08" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_09" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_10" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_11" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_12" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_13" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_14" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_15" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_16" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_17" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_18" android:duration="100"/>
+    <item android:drawable="@mipmap/eye_19" android:duration="100"/>
+</animation-list>

+ 36 - 0
faceplatform-ui/src/main/res/drawable/anim_left.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="true">
+    <item android:drawable="@mipmap/left_00" android:duration="50"/>
+    <item android:drawable="@mipmap/left_01" android:duration="50"/>
+    <item android:drawable="@mipmap/left_02" android:duration="50"/>
+    <item android:drawable="@mipmap/left_03" android:duration="50"/>
+    <item android:drawable="@mipmap/left_04" android:duration="50"/>
+    <item android:drawable="@mipmap/left_05" android:duration="50"/>
+    <item android:drawable="@mipmap/left_06" android:duration="50"/>
+    <item android:drawable="@mipmap/left_07" android:duration="50"/>
+    <item android:drawable="@mipmap/left_08" android:duration="50"/>
+    <item android:drawable="@mipmap/left_09" android:duration="50"/>
+    <item android:drawable="@mipmap/left_10" android:duration="50"/>
+    <item android:drawable="@mipmap/left_11" android:duration="50"/>
+    <item android:drawable="@mipmap/left_12" android:duration="50"/>
+    <item android:drawable="@mipmap/left_13" android:duration="50"/>
+    <item android:drawable="@mipmap/left_14" android:duration="50"/>
+    <item android:drawable="@mipmap/left_15" android:duration="50"/>
+    <item android:drawable="@mipmap/left_16" android:duration="50"/>
+    <item android:drawable="@mipmap/left_17" android:duration="50"/>
+    <item android:drawable="@mipmap/left_18" android:duration="50"/>
+    <item android:drawable="@mipmap/left_19" android:duration="50"/>
+    <item android:drawable="@mipmap/left_20" android:duration="50"/>
+    <item android:drawable="@mipmap/left_21" android:duration="50"/>
+    <item android:drawable="@mipmap/left_22" android:duration="50"/>
+    <item android:drawable="@mipmap/left_23" android:duration="50"/>
+    <item android:drawable="@mipmap/left_24" android:duration="50"/>
+    <item android:drawable="@mipmap/left_25" android:duration="50"/>
+    <item android:drawable="@mipmap/left_26" android:duration="50"/>
+    <item android:drawable="@mipmap/left_27" android:duration="50"/>
+    <item android:drawable="@mipmap/left_28" android:duration="50"/>
+    <item android:drawable="@mipmap/left_29" android:duration="50"/>
+    <item android:drawable="@mipmap/left_30" android:duration="50"/>
+    <item android:drawable="@mipmap/left_31" android:duration="50"/>
+</animation-list>

+ 28 - 0
faceplatform-ui/src/main/res/drawable/anim_mouth.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="true">
+    <item android:drawable="@mipmap/mouth_00" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_01" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_02" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_03" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_04" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_05" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_06" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_07" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_08" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_09" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_10" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_11" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_12" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_13" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_14" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_15" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_16" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_17" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_18" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_19" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_20" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_21" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_22" android:duration="50"/>
+    <item android:drawable="@mipmap/mouth_23" android:duration="50"/>
+</animation-list>

+ 36 - 0
faceplatform-ui/src/main/res/drawable/anim_right.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="true">
+    <item android:drawable="@mipmap/right_00" android:duration="50"/>
+    <item android:drawable="@mipmap/right_01" android:duration="50"/>
+    <item android:drawable="@mipmap/right_02" android:duration="50"/>
+    <item android:drawable="@mipmap/right_03" android:duration="50"/>
+    <item android:drawable="@mipmap/right_04" android:duration="50"/>
+    <item android:drawable="@mipmap/right_05" android:duration="50"/>
+    <item android:drawable="@mipmap/right_06" android:duration="50"/>
+    <item android:drawable="@mipmap/right_07" android:duration="50"/>
+    <item android:drawable="@mipmap/right_08" android:duration="50"/>
+    <item android:drawable="@mipmap/right_09" android:duration="50"/>
+    <item android:drawable="@mipmap/right_10" android:duration="50"/>
+    <item android:drawable="@mipmap/right_11" android:duration="50"/>
+    <item android:drawable="@mipmap/right_12" android:duration="50"/>
+    <item android:drawable="@mipmap/right_13" android:duration="50"/>
+    <item android:drawable="@mipmap/right_14" android:duration="50"/>
+    <item android:drawable="@mipmap/right_15" android:duration="50"/>
+    <item android:drawable="@mipmap/right_16" android:duration="50"/>
+    <item android:drawable="@mipmap/right_17" android:duration="50"/>
+    <item android:drawable="@mipmap/right_18" android:duration="50"/>
+    <item android:drawable="@mipmap/right_19" android:duration="50"/>
+    <item android:drawable="@mipmap/right_20" android:duration="50"/>
+    <item android:drawable="@mipmap/right_21" android:duration="50"/>
+    <item android:drawable="@mipmap/right_22" android:duration="50"/>
+    <item android:drawable="@mipmap/right_23" android:duration="50"/>
+    <item android:drawable="@mipmap/right_24" android:duration="50"/>
+    <item android:drawable="@mipmap/right_25" android:duration="50"/>
+    <item android:drawable="@mipmap/right_26" android:duration="50"/>
+    <item android:drawable="@mipmap/right_27" android:duration="50"/>
+    <item android:drawable="@mipmap/right_28" android:duration="50"/>
+    <item android:drawable="@mipmap/right_29" android:duration="50"/>
+    <item android:drawable="@mipmap/right_30" android:duration="50"/>
+    <item android:drawable="@mipmap/right_31" android:duration="50"/>
+</animation-list>

+ 36 - 0
faceplatform-ui/src/main/res/drawable/anim_up.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="true">
+    <item android:drawable="@mipmap/up_00" android:duration="50"/>
+    <item android:drawable="@mipmap/up_01" android:duration="50"/>
+    <item android:drawable="@mipmap/up_02" android:duration="50"/>
+    <item android:drawable="@mipmap/up_03" android:duration="50"/>
+    <item android:drawable="@mipmap/up_04" android:duration="50"/>
+    <item android:drawable="@mipmap/up_05" android:duration="50"/>
+    <item android:drawable="@mipmap/up_06" android:duration="50"/>
+    <item android:drawable="@mipmap/up_07" android:duration="50"/>
+    <item android:drawable="@mipmap/up_08" android:duration="50"/>
+    <item android:drawable="@mipmap/up_09" android:duration="50"/>
+    <item android:drawable="@mipmap/up_10" android:duration="50"/>
+    <item android:drawable="@mipmap/up_11" android:duration="50"/>
+    <item android:drawable="@mipmap/up_12" android:duration="50"/>
+    <item android:drawable="@mipmap/up_13" android:duration="50"/>
+    <item android:drawable="@mipmap/up_14" android:duration="50"/>
+    <item android:drawable="@mipmap/up_15" android:duration="50"/>
+    <item android:drawable="@mipmap/up_16" android:duration="50"/>
+    <item android:drawable="@mipmap/up_17" android:duration="50"/>
+    <item android:drawable="@mipmap/up_18" android:duration="50"/>
+    <item android:drawable="@mipmap/up_19" android:duration="50"/>
+    <item android:drawable="@mipmap/up_20" android:duration="50"/>
+    <item android:drawable="@mipmap/up_21" android:duration="50"/>
+    <item android:drawable="@mipmap/up_22" android:duration="50"/>
+    <item android:drawable="@mipmap/up_23" android:duration="50"/>
+    <item android:drawable="@mipmap/up_24" android:duration="50"/>
+    <item android:drawable="@mipmap/up_25" android:duration="50"/>
+    <item android:drawable="@mipmap/up_26" android:duration="50"/>
+    <item android:drawable="@mipmap/up_27" android:duration="50"/>
+    <item android:drawable="@mipmap/up_28" android:duration="50"/>
+    <item android:drawable="@mipmap/up_29" android:duration="50"/>
+    <item android:drawable="@mipmap/up_30" android:duration="50"/>
+    <item android:drawable="@mipmap/up_31" android:duration="50"/>
+</animation-list>

+ 25 - 0
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
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>  
+

+ 7 - 0
faceplatform-ui/src/main/res/drawable/collect_image_close_selector.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+        android:drawable="@mipmap/icon_titlebar_close_p" />
+    <item android:state_pressed="false"
+        android:drawable="@mipmap/icon_titlebar_close" />
+</selector>

+ 7 - 0
faceplatform-ui/src/main/res/drawable/collect_image_voice_selector.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+        android:drawable="@mipmap/icon_titlebar_voice_close_p" />
+    <item android:state_pressed="false"
+        android:drawable="@mipmap/icon_titlebar_voice_close" />
+</selector>

+ 6 - 0
faceplatform-ui/src/main/res/drawable/home_checkbox_button_selector.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@mipmap/icon_home_guide_ischeck_yes" android:state_checked="true" />
+    <item android:drawable="@mipmap/icon_home_guide_ischeck_no" android:state_checked="false" />
+    <item android:drawable="@mipmap/icon_home_guide_ischeck_no" />
+</selector>

BIN
faceplatform-ui/src/main/res/drawable/icon_setting_layout_ischeck_no.png


BIN
faceplatform-ui/src/main/res/drawable/icon_setting_layout_ischeck_select_yes.png


+ 6 - 0
faceplatform-ui/src/main/res/drawable/setting_actionlive_checkbox_button_selector.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/icon_setting_layout_ischeck_select_yes" android:state_checked="true" />
+    <item android:drawable="@drawable/icon_setting_layout_ischeck_no" android:state_checked="false" />
+    <item android:drawable="@drawable/icon_setting_layout_ischeck_no" />
+</selector>

+ 7 - 0
faceplatform-ui/src/main/res/drawable/setting_image_close_selector.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+        android:drawable="@mipmap/icon_titlebar_back_p" />
+    <item android:state_pressed="false"
+        android:drawable="@mipmap/icon_home_titlebar_back_agreement_return" />
+</selector>

+ 20 - 0
faceplatform-ui/src/main/res/drawable/setting_layout_bottom_round.xml

@@ -0,0 +1,20 @@
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <!-- rectangle表示为矩形 -->
+
+    <!-- 填充的颜色 -->
+    <solid android:color="#ffffff" />
+
+    <!-- 边框的颜色和粗细 -->
+    <!--<stroke
+        android:width="1dp"
+        android:color="#B0E0E6" />-->
+
+    <!-- android:radius 圆角的半径 -->
+    <corners
+        android:topLeftRadius="0dp"
+        android:topRightRadius="0dp"
+        android:bottomRightRadius="8dp"
+        android:bottomLeftRadius="8dp" />
+
+</shape>

+ 12 - 0
faceplatform-ui/src/main/res/drawable/setting_layout_radius.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <!-- 填充的颜色 -->
+    <solid android:color="#ffffff" />
+
+    <!-- 设置按钮的四个角为弧形 -->
+    <!-- android:radius 弧形的半径 -->
+    <corners android:radius="8dp" />
+
+</shape> 

+ 20 - 0
faceplatform-ui/src/main/res/drawable/setting_layout_top_round.xml

@@ -0,0 +1,20 @@
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <!-- rectangle表示为矩形 -->
+
+    <!-- 填充的颜色 -->
+    <solid android:color="#ffffff" />
+
+    <!-- 边框的颜色和粗细 -->
+    <!--<stroke
+        android:width="1dp"
+        android:color="#B0E0E6" />-->
+
+    <!-- android:radius 圆角的半径 -->
+    <corners
+        android:topLeftRadius="8dp"
+        android:topRightRadius="8dp"
+        android:bottomRightRadius="0dp"
+        android:bottomLeftRadius="0dp" />
+
+</shape>

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

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <solid android:color="#FFF" />
+    <stroke
+        android:width="3dp"
+        android:color="#00000000" />
+    <size
+        android:width="20dp"
+        android:height="20dp" />
+</shape>

+ 6 - 0
faceplatform-ui/src/main/res/drawable/setting_switch_track_off.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="#CCCCCC" />
+    <corners android:radius="20dp" />
+</shape>

+ 6 - 0
faceplatform-ui/src/main/res/drawable/setting_switch_track_on.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="#00BAF2" />
+    <corners android:radius="20dp" />
+</shape>

+ 5 - 0
faceplatform-ui/src/main/res/drawable/setting_switch_track_selector.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/setting_switch_track_on" android:state_checked="true" />
+    <item android:drawable="@drawable/setting_switch_track_off" android:state_checked="false" />
+</selector>

+ 12 - 0
faceplatform-ui/src/main/res/drawable/setting_toast_layout_radius.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <!-- 填充的颜色 -->
+    <solid android:color="#000000" />
+
+    <!-- 设置按钮的四个角为弧形 -->
+    <!-- android:radius 弧形的半径 -->
+    <corners android:radius="20dp" />
+
+</shape> 

+ 7 - 0
faceplatform-ui/src/main/res/drawable/success_button_recollect_selector.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+        android:drawable="@mipmap/icon_btn_main_p" />
+    <item android:state_pressed="false"
+        android:drawable="@mipmap/icon_btn_main_normal" />
+</selector>

+ 7 - 0
faceplatform-ui/src/main/res/drawable/success_button_return_selector.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+        android:drawable="@mipmap/icon_btn_less_p" />
+    <item android:state_pressed="false"
+        android:drawable="@mipmap/icon_btn_less_normal" />
+</selector>

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

@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:background="@color/background"
+    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"></FrameLayout>
+
+    <com.baidu.idl.face.platform.ui.widget.FaceDetectRoundView
+        android:id="@+id/detect_face_round"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <ImageView
+        android:id="@+id/detect_close"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="20dp"
+        android:layout_marginLeft="23dp"
+        android:src="@drawable/collect_image_close_selector" />
+
+    <ImageView
+        android:id="@+id/detect_sound"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_marginTop="20dp"
+        android:layout_marginRight="21dp"
+        android:src="@mipmap/icon_titlebar_voice2" />
+
+    <TextView
+        android:id="@+id/detect_top_tips"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_below="@id/detect_close"
+        android:layout_marginTop="24dp"
+        android:layout_gravity="center_horizontal"
+        android:gravity="center"
+        android:visibility="gone"
+        android:text="@string/detect_face_in"
+        android:textColor="#000000"
+        android:textSize="22sp" />
+
+    <ImageView
+        android:id="@+id/detect_success_image"
+        android:layout_width="45dp"
+        android:layout_height="45dp"
+        android:src="@mipmap/ic_success"
+        android:visibility="gone" />
+
+    <!--底部背景及文字-->
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@mipmap/icon_collect_bottom"
+        android:layout_alignParentBottom="true"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/collect_bottom_txt"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true"
+        android:layout_marginBottom="15dp"
+        android:textSize="@dimen/collect_bottom_font"
+        android:textColor="@color/collect_bottom_color"/>
+
+    <HorizontalScrollView
+        android:id="@+id/horizon1"
+        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"/>
+    </HorizontalScrollView>
+
+    <HorizontalScrollView
+        android:id="@+id/horizon2"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_above="@id/horizon1"
+        android:layout_marginBottom="5dp">
+
+        <LinearLayout
+            android:id="@+id/detect_result_image_layout2"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal"/>
+    </HorizontalScrollView>
+
+    <View
+        android:id="@+id/view_bg"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#7000"
+        android:visibility="gone"/>
+</RelativeLayout>

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

@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/liveness_root_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/background">
+
+    <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" />
+
+    <!--用于承载ImageView-->
+    <RelativeLayout
+        android:id="@+id/relative_add_image_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="invisible"/>
+
+    <ImageView
+        android:id="@+id/liveness_close"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="20dp"
+        android:layout_marginLeft="23dp"
+        android:src="@drawable/collect_image_close_selector" />
+
+    <ImageView
+        android:id="@+id/liveness_sound"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_marginTop="20dp"
+        android:layout_marginRight="21dp"
+        android:src="@mipmap/icon_titlebar_voice2" />
+
+    <ImageView
+        android:id="@+id/liveness_success_image"
+        android:layout_width="45dp"
+        android:layout_height="45dp"
+        android:src="@mipmap/ic_success"
+        android:visibility="invisible" />
+
+    <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:layout_below="@+id/liveness_close"
+        android:layout_marginTop="24dp"
+        android:gravity="center"
+        android:text="@string/detect_face_in"
+        android:textColor="#000000"
+        android:visibility="gone"
+        android:textSize="22sp" />
+
+    <!--底部背景及文字-->
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@mipmap/icon_collect_bottom"
+        android:layout_alignParentBottom="true"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/collect_bottom_txt"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true"
+        android:layout_marginBottom="15dp"
+        android:textSize="@dimen/collect_bottom_font"
+        android:textColor="@color/collect_bottom_color"/>
+
+    <HorizontalScrollView
+        android:id="@+id/horizon1"
+        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"/>
+    </HorizontalScrollView>
+
+    <HorizontalScrollView
+        android:id="@+id/horizon2"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_above="@id/horizon1"
+        android:layout_marginBottom="5dp">
+
+        <LinearLayout
+            android:id="@+id/liveness_result_image_layout2"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal"/>
+    </HorizontalScrollView>
+
+    <View
+        android:id="@+id/view_live_bg"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#7000"
+        android:visibility="gone"/>
+
+</RelativeLayout>

+ 243 - 0
faceplatform-ui/src/main/res/layout/layout_active_type.xml

@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/layout_active_type"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <!--眨眨眼-->
+    <RelativeLayout
+        android:id="@+id/blink_layout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:background="@color/home_text_color_white">
+
+        <CheckBox
+            android:id="@+id/actionlive_blink_checkbox"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="17dp"
+            android:background="@drawable/setting_actionlive_checkbox_button_selector"
+            android:button="@null"
+            android:checked="false" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="10dp"
+            android:textSize="16sp"
+            android:layout_toRightOf="@id/actionlive_blink_checkbox"
+            android:text="@string/setting_actionlive_blink_txt"
+            android:textColor="@color/home_text_color_black" />
+    </RelativeLayout>
+
+    <!--张嘴-->
+    <RelativeLayout
+        android:id="@+id/open_mouth_layout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/blink_layout"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:layout_marginTop="1dp"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:background="@drawable/setting_layout_bottom_round">
+
+        <CheckBox
+            android:id="@+id/actionlive_open_mouth_checkbox"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="17dp"
+            android:background="@drawable/setting_actionlive_checkbox_button_selector"
+            android:button="@null"
+            android:checked="false" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="10dp"
+            android:textSize="16sp"
+            android:layout_toRightOf="@id/actionlive_open_mouth_checkbox"
+            android:text="@string/setting_actionlive_open_mouth_txt"
+            android:textColor="@color/home_text_color_black" />
+    </RelativeLayout>
+
+    <!--向右摇头-->
+    <RelativeLayout
+        android:id="@+id/right_turn_layout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/open_mouth_layout"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:layout_marginTop="1dp"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:background="@color/home_text_color_white">
+
+        <CheckBox
+            android:id="@+id/actionlive_right_turn_checkbox"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="17dp"
+            android:background="@drawable/setting_actionlive_checkbox_button_selector"
+            android:button="@null"
+            android:checked="false" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="10dp"
+            android:layout_toRightOf="@id/actionlive_right_turn_checkbox"
+            android:text="@string/setting_actionlive_turn_right_txt"
+            android:textSize="16sp"
+            android:textColor="@color/home_text_color_black" />
+    </RelativeLayout>
+
+    <!--向左摇头-->
+    <RelativeLayout
+        android:id="@+id/left_turn_layout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/right_turn_layout"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:layout_marginTop="1dp"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:background="@color/home_text_color_white">
+
+        <CheckBox
+            android:id="@+id/actionlive_left_turn_checkbox"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="17dp"
+            android:background="@drawable/setting_actionlive_checkbox_button_selector"
+            android:button="@null"
+            android:checked="false" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="10dp"
+            android:textSize="16sp"
+            android:layout_toRightOf="@id/actionlive_left_turn_checkbox"
+            android:text="@string/setting_actionlive_turn_left_txt"
+            android:textColor="@color/home_text_color_black" />
+    </RelativeLayout>
+
+    <!--向上抬头-->
+    <RelativeLayout
+        android:id="@+id/look_up_layout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/left_turn_layout"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:layout_marginTop="1dp"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:background="@color/home_text_color_white">
+
+        <CheckBox
+            android:id="@+id/actionlive_look_up_checkbox"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="17dp"
+            android:background="@drawable/setting_actionlive_checkbox_button_selector"
+            android:button="@null"
+            android:checked="false" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="10dp"
+            android:layout_toRightOf="@id/actionlive_look_up_checkbox"
+            android:text="@string/setting_actionlive_look_up_txt"
+            android:textSize="16sp"
+            android:textColor="@color/home_text_color_black" />
+    </RelativeLayout>
+
+    <!--想下低头-->
+    <RelativeLayout
+        android:id="@+id/nod_layout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/look_up_layout"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:layout_marginTop="1dp"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:background="@drawable/setting_layout_bottom_round">
+
+        <CheckBox
+            android:id="@+id/actionlive_nod_checkbox"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="17dp"
+            android:background="@drawable/setting_actionlive_checkbox_button_selector"
+            android:button="@null"
+            android:checked="false" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="10dp"
+            android:layout_toRightOf="@id/actionlive_nod_checkbox"
+            android:text="@string/setting_actionlive_nod_txt"
+            android:textSize="16sp"
+            android:textColor="@color/home_text_color_black" />
+    </RelativeLayout>
+
+    <!--左右摇头-->
+    <RelativeLayout
+        android:id="@+id/shake_head_layout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@+id/nod_layout"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:layout_marginTop="0.4dp"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:visibility="gone"
+        android:background="@color/home_text_color_white">
+
+        <CheckBox
+            android:id="@+id/actionlive_shake_head_checkbox"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="17dp"
+            android:background="@drawable/setting_actionlive_checkbox_button_selector"
+            android:button="@null"
+            android:checked="false" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="10dp"
+            android:layout_toRightOf="@id/actionlive_shake_head_checkbox"
+            android:text="@string/setting_actionlive_shake_head_txt"
+            android:textSize="16sp"
+            android:textColor="@color/home_text_color_black" />
+    </RelativeLayout>
+
+</RelativeLayout>

+ 18 - 0
faceplatform-ui/src/main/res/layout/setting_toast_layout.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/toast_layout"
+    android:layout_width="wrap_content"
+    android:alpha="0.8"
+    android:background="@drawable/setting_toast_layout_radius"
+    android:layout_height="wrap_content">
+    <TextView
+        android:id="@+id/toast_txt"
+        android:layout_centerHorizontal="true"
+        android:layout_marginRight="20dp"
+        android:layout_marginLeft="20dp"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="10dp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textColor="#ffffff"/>
+</RelativeLayout>

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


+ 0 - 0
faceplatform-ui/src/main/res/mipmap-xxhdpi/down_22.png


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels