From 5b0d1c4f2e909024c8832754c975fb51a54d7ce8 Mon Sep 17 00:00:00 2001 From: luofan <lf@dayu.ai> Date: Mon, 14 May 2018 19:43:19 +0800 Subject: [PATCH] 增加人脸识别 --- IDCardLib/.gitignore | 1 + IDCardLib/build.gradle | 38 ++++++++++++++++++++++++++++++++++++++ IDCardLib/libs/arm64-v8a/libMegviiIDCardQuality_1.2.2.so | Bin 0 -> 1186400 bytes IDCardLib/libs/arm64-v8a/liblivenessdetection_v2.4.5.so | Bin 0 -> 658008 bytes IDCardLib/libs/armeabi-v7a/libMegviiIDCardQuality_1.2.2.so | Bin 0 -> 767748 bytes IDCardLib/libs/armeabi-v7a/liblivenessdetection_v2.4.5.so | Bin 0 -> 513768 bytes IDCardLib/libs/idcardquality-proguard-1.2.2.jar | Bin 0 -> 21525 bytes IDCardLib/libs/licensemanager-v1.1.jar | Bin 0 -> 3787 bytes IDCardLib/libs/livenessdetection-proguard-2.4.5.jar | Bin 0 -> 49106 bytes IDCardLib/libs/x86/liblivenessdetection_v2.4.5.so | Bin 0 -> 694036 bytes IDCardLib/proguard-rules.pro | 25 +++++++++++++++++++++++++ IDCardLib/src/androidTest/java/com/megvii/idcardlib/ExampleInstrumentedTest.java | 26 ++++++++++++++++++++++++++ IDCardLib/src/main/AndroidManifest.xml | 31 +++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/FaceMask.java | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/IDCardScanActivity.java | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/LivenessActivity.java | 496 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/ConUtil.java | 444 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/Constant.java | 14 ++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/DialogUtil.java | 34 ++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/FaceCamera.java | 299 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/ICamera.java | 319 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/IDetection.java | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/IFile.java | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/IMediaPlayer.java | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/MyTextView.java | 23 +++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/RotaterUtil.java | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/Screen.java | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/SensorUtil.java | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/SharedUtil.java | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/util/Util.java | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/view/AutoRatioImageview.java | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/view/CircleProgressBar.java | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/view/IDCardIndicator.java | 319 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/java/com/megvii/idcardlib/view/IDCardNewIndicator.java | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/res/anim/liveness_leftout.xml | 10 ++++++++++ IDCardLib/src/main/res/anim/liveness_rightin.xml | 10 ++++++++++ IDCardLib/src/main/res/drawable-xhdpi/bg_nothing.png | Bin 0 -> 121 bytes IDCardLib/src/main/res/drawable-xhdpi/circle.png | Bin 0 -> 24879 bytes IDCardLib/src/main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 728 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_eye.png | Bin 0 -> 39110 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_faceppinside.png | Bin 0 -> 21858 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_head.png | Bin 0 -> 40257 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_head_down.png | Bin 0 -> 37538 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_head_left.png | Bin 0 -> 41425 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_head_right.png | Bin 0 -> 41494 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_head_up.png | Bin 0 -> 40561 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_bottom_tips.png | Bin 0 -> 17285 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_camera_mask.png | Bin 0 -> 1283 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_head_mask.png | Bin 0 -> 12401 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_left.png | Bin 0 -> 41425 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_mouth.png | Bin 0 -> 43938 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_right.png | Bin 0 -> 41494 bytes IDCardLib/src/main/res/drawable-xhdpi/liveness_surfacemask.9.png | Bin 0 -> 3304 bytes IDCardLib/src/main/res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 43405 bytes IDCardLib/src/main/res/drawable-xxhdpi/liveness_phoneimage.png | Bin 0 -> 59359 bytes IDCardLib/src/main/res/drawable-xxhdpi/loading_background.jpg | Bin 0 -> 773096 bytes IDCardLib/src/main/res/drawable-xxhdpi/sfz_back.png | Bin 0 -> 12860 bytes IDCardLib/src/main/res/drawable-xxhdpi/sfz_front.png | Bin 0 -> 14977 bytes IDCardLib/src/main/res/drawable/liveness_eye_open_closed.xml | 5 +++++ IDCardLib/src/main/res/drawable/liveness_head_pitch.xml | 7 +++++++ IDCardLib/src/main/res/drawable/liveness_head_yaw.xml | 7 +++++++ IDCardLib/src/main/res/drawable/liveness_mouth_open_closed.xml | 5 +++++ IDCardLib/src/main/res/drawable/rectangle.xml | 8 ++++++++ IDCardLib/src/main/res/layout/bottom_title_layout.xml | 33 +++++++++++++++++++++++++++++++++ IDCardLib/src/main/res/layout/idcardscan_layout.xml | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/res/layout/liveness_detection_step.xml | 36 ++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/res/layout/liveness_layout.xml | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/res/raw/idcardmodel | Bin 0 -> 246195 bytes IDCardLib/src/main/res/raw/livenessmodel | Bin 0 -> 468552 bytes IDCardLib/src/main/res/raw/meglive_eye_blink.mp3 | Bin 0 -> 17180 bytes IDCardLib/src/main/res/raw/meglive_failed.mp3 | Bin 0 -> 76948 bytes IDCardLib/src/main/res/raw/meglive_mouth_open.mp3 | Bin 0 -> 18016 bytes IDCardLib/src/main/res/raw/meglive_pitch_down.mp3 | Bin 0 -> 26375 bytes IDCardLib/src/main/res/raw/meglive_success.mp3 | Bin 0 -> 50617 bytes IDCardLib/src/main/res/raw/meglive_well_done.mp3 | Bin 0 -> 17180 bytes IDCardLib/src/main/res/raw/meglive_yaw.mp3 | Bin 0 -> 47691 bytes IDCardLib/src/main/res/raw/model | Bin 0 -> 468552 bytes IDCardLib/src/main/res/values/color.xml | 4 ++++ IDCardLib/src/main/res/values/dimens.xml | 9 +++++++++ IDCardLib/src/main/res/values/strings.xml | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IDCardLib/src/main/res/values/styles.xml | 27 +++++++++++++++++++++++++++ IDCardLib/src/test/java/com/megvii/idcardlib/ExampleUnitTest.java | 17 +++++++++++++++++ app/src/main/java/com/dayu/bigfish/ui/MainActivity.java | 4 ++-- baseSDK/src/main/java/com/dayu/base/api/APIService.java | 12 ++++++++++++ baseSDK/src/main/java/com/dayu/base/api/BaseApiFactory.java | 6 ++++++ baseSDK/src/main/java/com/dayu/utils/GlideImageLoader.java | 43 +++++++++++++++++++++++++++++++++++++++++++ baseSDK/src/main/res/drawable-hdpi/icon_next_button.png | Bin 0 -> 30860 bytes baseSDK/src/main/res/drawable-xhdpi/icon_next_button.png | Bin 0 -> 50521 bytes baseSDK/src/main/res/drawable-xxhdpi/icon_next_button.png | Bin 0 -> 112680 bytes baseSDK/src/main/res/drawable-xxxhdpi/icon_next_button.png | Bin 0 -> 198742 bytes build.gradle | 2 +- settings.gradle | 3 ++- userCenter/build.gradle | 2 ++ userCenter/src/main/debug/AndroidManifest.xml | 9 +++++++++ userCenter/src/main/java/com/dayu/usercenter/api/UserApiFactory.java | 8 ++++++++ userCenter/src/main/java/com/dayu/usercenter/api/UserService.java | 20 ++++++++++++++++++++ userCenter/src/main/java/com/dayu/usercenter/common/UserConstant.java | 6 ++++++ userCenter/src/main/java/com/dayu/usercenter/data/protocol/MegLive.java | 34 ++++++++++++++++++++++++++++++++++ userCenter/src/main/java/com/dayu/usercenter/presenter/certification/CertificaitonContract.java | 25 +++++++++++++++++++++++++ userCenter/src/main/java/com/dayu/usercenter/presenter/certification/CertificaitonPresenter.java | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ userCenter/src/main/java/com/dayu/usercenter/presenter/facecertification/FaceCertificaitonContract.java | 24 ++++++++++++++++++++++++ userCenter/src/main/java/com/dayu/usercenter/presenter/facecertification/FaceCertificaitonPresenter.java | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ userCenter/src/main/java/com/dayu/usercenter/ui/activity/CertificationResultActivity.java | 22 ++++++++++++++++++++++ userCenter/src/main/java/com/dayu/usercenter/ui/activity/FaceCertificationActivity.java | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ userCenter/src/main/java/com/dayu/usercenter/ui/activity/IdentityCertificationActivity.java | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ userCenter/src/main/java/com/dayu/usercenter/ui/fragment/HomePersonFragment.java | 1 - userCenter/src/main/release/AndroidManifest.xml | 9 +++++++++ userCenter/src/main/res/drawable-hdpi/icon_certificaiton_succeed.png | Bin 0 -> 16190 bytes userCenter/src/main/res/drawable-hdpi/icon_certification_failure.png | Bin 0 -> 11391 bytes userCenter/src/main/res/drawable-hdpi/icon_certification_notice.png | Bin 0 -> 11353 bytes userCenter/src/main/res/drawable-hdpi/icon_first.png | Bin 0 -> 13557 bytes userCenter/src/main/res/drawable-hdpi/icon_idcard_front.png | Bin 0 -> 21162 bytes userCenter/src/main/res/drawable-hdpi/icon_idcard_side.png | Bin 0 -> 21018 bytes userCenter/src/main/res/drawable-hdpi/icon_second.png | Bin 0 -> 13923 bytes userCenter/src/main/res/drawable-hdpi/icon_third.png | Bin 0 -> 13796 bytes userCenter/src/main/res/drawable-xhdpi/icon_certificaiton_succeed.png | Bin 0 -> 22547 bytes userCenter/src/main/res/drawable-xhdpi/icon_certification_failure.png | Bin 0 -> 15695 bytes userCenter/src/main/res/drawable-xhdpi/icon_certification_notice.png | Bin 0 -> 16071 bytes userCenter/src/main/res/drawable-xhdpi/icon_first.png | Bin 0 -> 18045 bytes userCenter/src/main/res/drawable-xhdpi/icon_idcard_front.png | Bin 0 -> 29880 bytes userCenter/src/main/res/drawable-xhdpi/icon_idcard_side.png | Bin 0 -> 29439 bytes userCenter/src/main/res/drawable-xhdpi/icon_index.png | Bin 0 -> 5695 bytes userCenter/src/main/res/drawable-xhdpi/icon_second.png | Bin 0 -> 19386 bytes userCenter/src/main/res/drawable-xhdpi/icon_third.png | Bin 0 -> 18289 bytes userCenter/src/main/res/drawable-xxhdpi/icon_certification_failure.png | Bin 0 -> 24835 bytes userCenter/src/main/res/drawable-xxhdpi/icon_certification_notice.png | Bin 0 -> 27791 bytes userCenter/src/main/res/drawable-xxhdpi/icon_certification_succeed.png | Bin 0 -> 35601 bytes userCenter/src/main/res/drawable-xxhdpi/icon_first.png | Bin 0 -> 30866 bytes userCenter/src/main/res/drawable-xxhdpi/icon_idcard_front.png | Bin 0 -> 48928 bytes userCenter/src/main/res/drawable-xxhdpi/icon_idcard_side.png | Bin 0 -> 47642 bytes userCenter/src/main/res/drawable-xxhdpi/icon_index.png | Bin 0 -> 9846 bytes userCenter/src/main/res/drawable-xxhdpi/icon_second.png | Bin 0 -> 32437 bytes userCenter/src/main/res/drawable-xxhdpi/icon_third.png | Bin 0 -> 31404 bytes userCenter/src/main/res/drawable-xxxhdpi/icon_certification_failure.png | Bin 0 -> 36153 bytes userCenter/src/main/res/drawable-xxxhdpi/icon_certification_notice.png | Bin 0 -> 40906 bytes userCenter/src/main/res/drawable-xxxhdpi/icon_certification_succeed.png | Bin 0 -> 51020 bytes userCenter/src/main/res/drawable-xxxhdpi/icon_first.png | Bin 0 -> 42275 bytes userCenter/src/main/res/drawable-xxxhdpi/icon_idcard_front.png | Bin 0 -> 70063 bytes userCenter/src/main/res/drawable-xxxhdpi/icon_idcard_side.png | Bin 0 -> 68605 bytes userCenter/src/main/res/drawable-xxxhdpi/icon_index.png | Bin 0 -> 13477 bytes userCenter/src/main/res/drawable-xxxhdpi/icon_second.png | Bin 0 -> 45168 bytes userCenter/src/main/res/drawable-xxxhdpi/icon_third.png | Bin 0 -> 42990 bytes userCenter/src/main/res/layout/activity_certification_layout.xml | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ userCenter/src/main/res/layout/activity_certification_result.xml | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ userCenter/src/main/res/layout/activity_face_certification.xml | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ userCenter/src/main/res/layout/dialog_image.xml | 12 ++++++++++++ 146 files changed, 5463 insertions(+), 5 deletions(-) create mode 100644 IDCardLib/.gitignore create mode 100644 IDCardLib/build.gradle create mode 100755 IDCardLib/libs/arm64-v8a/libMegviiIDCardQuality_1.2.2.so create mode 100755 IDCardLib/libs/arm64-v8a/liblivenessdetection_v2.4.5.so create mode 100755 IDCardLib/libs/armeabi-v7a/libMegviiIDCardQuality_1.2.2.so create mode 100755 IDCardLib/libs/armeabi-v7a/liblivenessdetection_v2.4.5.so create mode 100644 IDCardLib/libs/idcardquality-proguard-1.2.2.jar create mode 100644 IDCardLib/libs/licensemanager-v1.1.jar create mode 100755 IDCardLib/libs/livenessdetection-proguard-2.4.5.jar create mode 100755 IDCardLib/libs/x86/liblivenessdetection_v2.4.5.so create mode 100644 IDCardLib/proguard-rules.pro create mode 100644 IDCardLib/src/androidTest/java/com/megvii/idcardlib/ExampleInstrumentedTest.java create mode 100644 IDCardLib/src/main/AndroidManifest.xml create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/FaceMask.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/IDCardScanActivity.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/LivenessActivity.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/ConUtil.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/Constant.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/DialogUtil.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/FaceCamera.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/ICamera.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/IDetection.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/IFile.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/IMediaPlayer.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/MyTextView.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/RotaterUtil.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/Screen.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/SensorUtil.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/SharedUtil.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/util/Util.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/view/AutoRatioImageview.java create mode 100755 IDCardLib/src/main/java/com/megvii/idcardlib/view/CircleProgressBar.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/view/IDCardIndicator.java create mode 100644 IDCardLib/src/main/java/com/megvii/idcardlib/view/IDCardNewIndicator.java create mode 100644 IDCardLib/src/main/res/anim/liveness_leftout.xml create mode 100644 IDCardLib/src/main/res/anim/liveness_rightin.xml create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/bg_nothing.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/circle.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_eye.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_faceppinside.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_head.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_head_down.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_head_left.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_head_right.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_head_up.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_bottom_tips.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_camera_mask.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_head_mask.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_left.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_mouth.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_right.png create mode 100644 IDCardLib/src/main/res/drawable-xhdpi/liveness_surfacemask.9.png create mode 100644 IDCardLib/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 IDCardLib/src/main/res/drawable-xxhdpi/liveness_phoneimage.png create mode 100644 IDCardLib/src/main/res/drawable-xxhdpi/loading_background.jpg create mode 100644 IDCardLib/src/main/res/drawable-xxhdpi/sfz_back.png create mode 100644 IDCardLib/src/main/res/drawable-xxhdpi/sfz_front.png create mode 100644 IDCardLib/src/main/res/drawable/liveness_eye_open_closed.xml create mode 100644 IDCardLib/src/main/res/drawable/liveness_head_pitch.xml create mode 100644 IDCardLib/src/main/res/drawable/liveness_head_yaw.xml create mode 100644 IDCardLib/src/main/res/drawable/liveness_mouth_open_closed.xml create mode 100644 IDCardLib/src/main/res/drawable/rectangle.xml create mode 100644 IDCardLib/src/main/res/layout/bottom_title_layout.xml create mode 100644 IDCardLib/src/main/res/layout/idcardscan_layout.xml create mode 100644 IDCardLib/src/main/res/layout/liveness_detection_step.xml create mode 100644 IDCardLib/src/main/res/layout/liveness_layout.xml create mode 100644 IDCardLib/src/main/res/raw/idcardmodel create mode 100755 IDCardLib/src/main/res/raw/livenessmodel create mode 100644 IDCardLib/src/main/res/raw/meglive_eye_blink.mp3 create mode 100644 IDCardLib/src/main/res/raw/meglive_failed.mp3 create mode 100644 IDCardLib/src/main/res/raw/meglive_mouth_open.mp3 create mode 100644 IDCardLib/src/main/res/raw/meglive_pitch_down.mp3 create mode 100644 IDCardLib/src/main/res/raw/meglive_success.mp3 create mode 100644 IDCardLib/src/main/res/raw/meglive_well_done.mp3 create mode 100644 IDCardLib/src/main/res/raw/meglive_yaw.mp3 create mode 100644 IDCardLib/src/main/res/raw/model create mode 100644 IDCardLib/src/main/res/values/color.xml create mode 100644 IDCardLib/src/main/res/values/dimens.xml create mode 100644 IDCardLib/src/main/res/values/strings.xml create mode 100644 IDCardLib/src/main/res/values/styles.xml create mode 100644 IDCardLib/src/test/java/com/megvii/idcardlib/ExampleUnitTest.java create mode 100644 baseSDK/src/main/res/drawable-hdpi/icon_next_button.png create mode 100644 baseSDK/src/main/res/drawable-xhdpi/icon_next_button.png create mode 100644 baseSDK/src/main/res/drawable-xxhdpi/icon_next_button.png create mode 100644 baseSDK/src/main/res/drawable-xxxhdpi/icon_next_button.png create mode 100644 userCenter/src/main/java/com/dayu/usercenter/data/protocol/MegLive.java create mode 100755 userCenter/src/main/java/com/dayu/usercenter/presenter/certification/CertificaitonContract.java create mode 100644 userCenter/src/main/java/com/dayu/usercenter/presenter/certification/CertificaitonPresenter.java create mode 100755 userCenter/src/main/java/com/dayu/usercenter/presenter/facecertification/FaceCertificaitonContract.java create mode 100644 userCenter/src/main/java/com/dayu/usercenter/presenter/facecertification/FaceCertificaitonPresenter.java create mode 100644 userCenter/src/main/java/com/dayu/usercenter/ui/activity/CertificationResultActivity.java create mode 100644 userCenter/src/main/java/com/dayu/usercenter/ui/activity/FaceCertificationActivity.java create mode 100644 userCenter/src/main/java/com/dayu/usercenter/ui/activity/IdentityCertificationActivity.java create mode 100644 userCenter/src/main/res/drawable-hdpi/icon_certificaiton_succeed.png create mode 100644 userCenter/src/main/res/drawable-hdpi/icon_certification_failure.png create mode 100644 userCenter/src/main/res/drawable-hdpi/icon_certification_notice.png create mode 100644 userCenter/src/main/res/drawable-hdpi/icon_first.png create mode 100644 userCenter/src/main/res/drawable-hdpi/icon_idcard_front.png create mode 100644 userCenter/src/main/res/drawable-hdpi/icon_idcard_side.png create mode 100644 userCenter/src/main/res/drawable-hdpi/icon_second.png create mode 100644 userCenter/src/main/res/drawable-hdpi/icon_third.png create mode 100644 userCenter/src/main/res/drawable-xhdpi/icon_certificaiton_succeed.png create mode 100644 userCenter/src/main/res/drawable-xhdpi/icon_certification_failure.png create mode 100644 userCenter/src/main/res/drawable-xhdpi/icon_certification_notice.png create mode 100644 userCenter/src/main/res/drawable-xhdpi/icon_first.png create mode 100644 userCenter/src/main/res/drawable-xhdpi/icon_idcard_front.png create mode 100644 userCenter/src/main/res/drawable-xhdpi/icon_idcard_side.png create mode 100644 userCenter/src/main/res/drawable-xhdpi/icon_index.png create mode 100644 userCenter/src/main/res/drawable-xhdpi/icon_second.png create mode 100644 userCenter/src/main/res/drawable-xhdpi/icon_third.png create mode 100644 userCenter/src/main/res/drawable-xxhdpi/icon_certification_failure.png create mode 100644 userCenter/src/main/res/drawable-xxhdpi/icon_certification_notice.png create mode 100644 userCenter/src/main/res/drawable-xxhdpi/icon_certification_succeed.png create mode 100644 userCenter/src/main/res/drawable-xxhdpi/icon_first.png create mode 100644 userCenter/src/main/res/drawable-xxhdpi/icon_idcard_front.png create mode 100644 userCenter/src/main/res/drawable-xxhdpi/icon_idcard_side.png create mode 100644 userCenter/src/main/res/drawable-xxhdpi/icon_index.png create mode 100644 userCenter/src/main/res/drawable-xxhdpi/icon_second.png create mode 100644 userCenter/src/main/res/drawable-xxhdpi/icon_third.png create mode 100644 userCenter/src/main/res/drawable-xxxhdpi/icon_certification_failure.png create mode 100644 userCenter/src/main/res/drawable-xxxhdpi/icon_certification_notice.png create mode 100644 userCenter/src/main/res/drawable-xxxhdpi/icon_certification_succeed.png create mode 100644 userCenter/src/main/res/drawable-xxxhdpi/icon_first.png create mode 100644 userCenter/src/main/res/drawable-xxxhdpi/icon_idcard_front.png create mode 100644 userCenter/src/main/res/drawable-xxxhdpi/icon_idcard_side.png create mode 100644 userCenter/src/main/res/drawable-xxxhdpi/icon_index.png create mode 100644 userCenter/src/main/res/drawable-xxxhdpi/icon_second.png create mode 100644 userCenter/src/main/res/drawable-xxxhdpi/icon_third.png create mode 100644 userCenter/src/main/res/layout/activity_certification_layout.xml create mode 100644 userCenter/src/main/res/layout/activity_certification_result.xml create mode 100644 userCenter/src/main/res/layout/activity_face_certification.xml create mode 100644 userCenter/src/main/res/layout/dialog_image.xml diff --git a/IDCardLib/.gitignore b/IDCardLib/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/IDCardLib/.gitignore @@ -0,0 +1 @@ +/build diff --git a/IDCardLib/build.gradle b/IDCardLib/build.gradle new file mode 100644 index 0000000..de4c546 --- /dev/null +++ b/IDCardLib/build.gradle @@ -0,0 +1,38 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion compile_sdk_version + buildToolsVersion build_tools_version + + defaultConfig { + minSdkVersion min_sdk_version + targetSdkVersion target_sdk_version + versionCode version_code + versionName verson_name + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + buildTypes { + release { + minifyEnabled isReleaseMinify + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + sourceSets{ + main{ + jniLibs.srcDir(['libs']) + } + } +} + +dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + compile 'com.android.support:appcompat-v7:25.3.1' + testCompile 'junit:junit:4.12' + implementation files('libs/licensemanager-v1.1.jar') + implementation files('libs/livenessdetection-proguard-2.4.5.jar') +} diff --git a/IDCardLib/libs/arm64-v8a/libMegviiIDCardQuality_1.2.2.so b/IDCardLib/libs/arm64-v8a/libMegviiIDCardQuality_1.2.2.so new file mode 100755 index 0000000..16112f8 Binary files /dev/null and b/IDCardLib/libs/arm64-v8a/libMegviiIDCardQuality_1.2.2.so differ diff --git a/IDCardLib/libs/arm64-v8a/liblivenessdetection_v2.4.5.so b/IDCardLib/libs/arm64-v8a/liblivenessdetection_v2.4.5.so new file mode 100755 index 0000000..54bc527 Binary files /dev/null and b/IDCardLib/libs/arm64-v8a/liblivenessdetection_v2.4.5.so differ diff --git a/IDCardLib/libs/armeabi-v7a/libMegviiIDCardQuality_1.2.2.so b/IDCardLib/libs/armeabi-v7a/libMegviiIDCardQuality_1.2.2.so new file mode 100755 index 0000000..53baf1e Binary files /dev/null and b/IDCardLib/libs/armeabi-v7a/libMegviiIDCardQuality_1.2.2.so differ diff --git a/IDCardLib/libs/armeabi-v7a/liblivenessdetection_v2.4.5.so b/IDCardLib/libs/armeabi-v7a/liblivenessdetection_v2.4.5.so new file mode 100755 index 0000000..cf436cc Binary files /dev/null and b/IDCardLib/libs/armeabi-v7a/liblivenessdetection_v2.4.5.so differ diff --git a/IDCardLib/libs/idcardquality-proguard-1.2.2.jar b/IDCardLib/libs/idcardquality-proguard-1.2.2.jar new file mode 100644 index 0000000..813bf2d Binary files /dev/null and b/IDCardLib/libs/idcardquality-proguard-1.2.2.jar differ diff --git a/IDCardLib/libs/licensemanager-v1.1.jar b/IDCardLib/libs/licensemanager-v1.1.jar new file mode 100644 index 0000000..23baa24 Binary files /dev/null and b/IDCardLib/libs/licensemanager-v1.1.jar differ diff --git a/IDCardLib/libs/livenessdetection-proguard-2.4.5.jar b/IDCardLib/libs/livenessdetection-proguard-2.4.5.jar new file mode 100755 index 0000000..b4657ad Binary files /dev/null and b/IDCardLib/libs/livenessdetection-proguard-2.4.5.jar differ diff --git a/IDCardLib/libs/x86/liblivenessdetection_v2.4.5.so b/IDCardLib/libs/x86/liblivenessdetection_v2.4.5.so new file mode 100755 index 0000000..870bff0 Binary files /dev/null and b/IDCardLib/libs/x86/liblivenessdetection_v2.4.5.so differ diff --git a/IDCardLib/proguard-rules.pro b/IDCardLib/proguard-rules.pro new file mode 100644 index 0000000..6686c30 --- /dev/null +++ b/IDCardLib/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/wyc/Library/Android/sdk/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 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 *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/IDCardLib/src/androidTest/java/com/megvii/idcardlib/ExampleInstrumentedTest.java b/IDCardLib/src/androidTest/java/com/megvii/idcardlib/ExampleInstrumentedTest.java new file mode 100644 index 0000000..7d69e98 --- /dev/null +++ b/IDCardLib/src/androidTest/java/com/megvii/idcardlib/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.megvii.idcardlib; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumentation test, which will execute on an Android device. + * + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.megvii.idcardlib.test", appContext.getPackageName()); + } +} diff --git a/IDCardLib/src/main/AndroidManifest.xml b/IDCardLib/src/main/AndroidManifest.xml new file mode 100644 index 0000000..660d561 --- /dev/null +++ b/IDCardLib/src/main/AndroidManifest.xml @@ -0,0 +1,31 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + + package="com.megvii.idcardlib"> + + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.CAMERA" /> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.RECORD_AUDIO" /> + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> + <uses-permission android:name="android.permission.VIBRATE" /> + + + <application + android:allowBackup="true" android:label="@string/app_name" + android:supportsRtl="true" + > + <activity + android:name="com.megvii.idcardlib.IDCardScanActivity" + android:label="@string/app_name" + android:theme="@android:style/Theme.Holo.NoActionBar.TranslucentDecor" + android:screenOrientation="portrait" + android:configChanges="keyboardHidden|orientation|screenSize" + > + </activity> + <activity + android:name=".LivenessActivity" + android:screenOrientation="portrait" /> + </application> + +</manifest> diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/FaceMask.java b/IDCardLib/src/main/java/com/megvii/idcardlib/FaceMask.java new file mode 100644 index 0000000..d50e5bc --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/FaceMask.java @@ -0,0 +1,62 @@ + +package com.megvii.idcardlib; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.View; + +import com.megvii.livenessdetection.DetectionFrame; + + +public class FaceMask extends View { + public static final int Threshold = 30; + Paint localPaint = null; + RectF mFaceRect = new RectF(); + RectF mDrawRect = null; + private int normal_colour = 0xff00b4ff; + private int high_colour = 0xffff0000; + private boolean isFraontalCamera = true; + + public FaceMask(Context context, AttributeSet atti) { + super(context, atti); + mDrawRect = new RectF(); + localPaint = new Paint(); + localPaint.setColor(normal_colour); + localPaint.setStrokeWidth(5); + localPaint.setStyle(Paint.Style.STROKE); + } + + public void setFaceInfo(DetectionFrame faceInfo) { + if (faceInfo != null) + mFaceRect = faceInfo.getFacePos(); + else { + mFaceRect = null; + } + postInvalidate(); + } + + public void setFrontal(boolean isFrontal) + { + this.isFraontalCamera = isFrontal; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (mFaceRect == null) + return; + if (isFraontalCamera) { + mDrawRect.set(getWidth() * (1 - mFaceRect.right), getHeight() + * mFaceRect.top, getWidth() * (1 - mFaceRect.left), + getHeight() + * mFaceRect.bottom); + } else { + mDrawRect.set(getWidth() * mFaceRect.left, getHeight() * mFaceRect.top, getWidth() + * mFaceRect.right, getHeight() * mFaceRect.bottom); + } + canvas.drawRect(mDrawRect, localPaint); + } +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/IDCardScanActivity.java b/IDCardLib/src/main/java/com/megvii/idcardlib/IDCardScanActivity.java new file mode 100644 index 0000000..785a03a --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/IDCardScanActivity.java @@ -0,0 +1,400 @@ +package com.megvii.idcardlib; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.SurfaceTexture; +import android.hardware.Camera; +import android.os.Bundle; +import android.os.Vibrator; +import android.view.TextureView; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; +import com.megvii.idcardlib.util.DialogUtil; +import com.megvii.idcardlib.util.ICamera; +import com.megvii.idcardlib.util.RotaterUtil; +import com.megvii.idcardlib.util.Util; +import com.megvii.idcardlib.view.IDCardIndicator; +import com.megvii.idcardlib.view.IDCardNewIndicator; +import com.megvii.idcardquality.IDCardQualityAssessment; +import com.megvii.idcardquality.IDCardQualityResult; +import com.megvii.idcardquality.bean.IDCardAttr; +import java.math.BigDecimal; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; + +public class IDCardScanActivity extends Activity implements TextureView.SurfaceTextureListener, Camera.PreviewCallback { + + private TextureView textureView; + private DialogUtil mDialogUtil; + private ICamera mICamera;// 照相机工具类 + private IDCardQualityAssessment idCardQualityAssessment = null; + private IDCardNewIndicator mNewIndicatorView; + private IDCardIndicator mIdCardIndicator; + private IDCardAttr.IDCardSide mSide; + private DecodeThread mDecoder = null; + private boolean mIsVertical = false; + private TextView fps; + private TextView errorType; + private TextView horizontalTitle, verticalTitle; + private TextView logInfo; + private View debugRectangle; + private boolean isDebugMode = false; + int continuousClickCount = 0; + long lastClickMillis = 0; + private Vibrator vibrator; + private float mInBound, mIsIDCard; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.idcardscan_layout); + init(); + initData(); + } + + private void init() { + vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + mSide = getIntent().getIntExtra("side", 0) == 0 ? IDCardAttr.IDCardSide.IDCARD_SIDE_FRONT + : IDCardAttr.IDCardSide.IDCARD_SIDE_BACK; + mIsVertical = getIntent().getBooleanExtra("isvertical", false); + mICamera = new ICamera(mIsVertical); + mDialogUtil = new DialogUtil(this); + textureView = (TextureView) findViewById(R.id.idcardscan_layout_surface); + textureView.setSurfaceTextureListener(this); + textureView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mICamera.autoFocus(); + } + }); + fps = (TextView) findViewById(R.id.idcardscan_layout_fps); + logInfo = (TextView) findViewById(R.id.text_debug_info); + errorType = (TextView) findViewById(R.id.idcardscan_layout_error_type); + horizontalTitle = (TextView) findViewById(R.id.idcardscan_layout_horizontalTitle); + verticalTitle = (TextView) findViewById(R.id.idcardscan_layout_verticalTitle); + mFrameDataQueue = new LinkedBlockingDeque<byte[]>(1); + mNewIndicatorView = (IDCardNewIndicator) findViewById(R.id.idcardscan_layout_newIndicator); + mIdCardIndicator = (IDCardIndicator) findViewById(R.id.idcardscan_layout_indicator); + debugRectangle = findViewById(R.id.debugRectangle); + + OnClickListener onClickListener = new OnClickListener() { + @Override + public void onClick(View v) { + mICamera.autoFocus(); + launchDebugMode(); + } + }; + mNewIndicatorView.setOnClickListener(onClickListener); + mIdCardIndicator.setOnClickListener(onClickListener); + + if (mIsVertical) { + horizontalTitle.setVisibility(View.GONE); + verticalTitle.setVisibility(View.VISIBLE); + mIdCardIndicator.setVisibility(View.VISIBLE); + mNewIndicatorView.setVisibility(View.GONE); + mIdCardIndicator.setCardSideAndOrientation(mIsVertical, mSide); + mNewIndicatorView.setCardSideAndOrientation(mIsVertical, mSide); + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } else { + horizontalTitle.setVisibility(View.VISIBLE); + verticalTitle.setVisibility(View.GONE); + mIdCardIndicator.setVisibility(View.GONE); + mNewIndicatorView.setVisibility(View.VISIBLE); + mIdCardIndicator.setCardSideAndOrientation(mIsVertical, mSide); + mNewIndicatorView.setCardSideAndOrientation(mIsVertical, mSide); + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + + if (mDecoder == null) { + mDecoder = new DecodeThread(); + } + if (!mDecoder.isAlive()) { + mDecoder.start(); + } + } + + private void launchDebugMode() { + long currentMillis = System.currentTimeMillis(); + if (continuousClickCount == 0 || (continuousClickCount > 0 && currentMillis - lastClickMillis < 200)) { + continuousClickCount++; + } + lastClickMillis = currentMillis; + if (continuousClickCount == 6) { + isDebugMode = true; + continuousClickCount = 0; + } + } + + private void setDebugRectanglePosition() { + + Rect debugRoi; + if (!mIsVertical) { + debugRoi = mNewIndicatorView.getMargin(); + } else { + debugRoi = mIdCardIndicator.getMargin(); + } + final Rect fDebugRect = debugRoi; + + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) debugRectangle.getLayoutParams(); + params.setMargins(fDebugRect.left, fDebugRect.top, fDebugRect.right, fDebugRect.bottom); + debugRectangle.setLayoutParams(params); + } + + /** + * 初始化数据 + */ + private void initData() { + idCardQualityAssessment = new IDCardQualityAssessment.Builder().setIsIgnoreShadow(true).setIsIgnoreHighlight(false).build(); + boolean initSuccess = idCardQualityAssessment.init(this, Util.readModel(this)); + if (!initSuccess) { + mDialogUtil.showDialog("检测器初始化失败"); + } else { + mInBound = idCardQualityAssessment.mInBound; + mIsIDCard = idCardQualityAssessment.mIsIdcard; + } + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mDialogUtil.onDestory(); + try { + if (mDecoder != null) { + mDecoder.interrupt(); + mDecoder.join(); + mDecoder = null; + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + idCardQualityAssessment.release(); + idCardQualityAssessment = null; + } + + private void doPreview() { + if (!mHasSurface) + return; + + mICamera.startPreview(textureView.getSurfaceTexture()); + setDebugRectanglePosition(); + } + + private boolean mHasSurface = false; + + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + Camera mCamera = mICamera.openCamera(this); + if (mCamera != null) { + RelativeLayout.LayoutParams layout_params = mICamera.getLayoutParam(this); + textureView.setLayoutParams(layout_params); + mNewIndicatorView.setLayoutParams(layout_params); + mIdCardIndicator.setLayoutParams(layout_params); + } else { + mDialogUtil.showDialog("打开摄像头失败"); + return; + } + mHasSurface = true; + doPreview(); + mICamera.actionDetect(this); + + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + mICamera.closeCamera(); + mHasSurface = false; + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + + } + + @Override + public void onPreviewFrame(final byte[] data, Camera camera) { + mFrameDataQueue.offer(data); + } + + private BlockingQueue<byte[]> mFrameDataQueue; + + private class DecodeThread extends Thread { + boolean mHasSuccess = false; + int mCount = 0; + int mTimSum = 0; + private IDCardQualityResult.IDCardFailedType mLstErrType; + + @Override + public void run() { + byte[] imgData = null; + try { + while ((imgData = mFrameDataQueue.take()) != null) { + if (mHasSuccess) + return; + int imageWidth = mICamera.cameraWidth; + int imageHeight = mICamera.cameraHeight; + + imgData = RotaterUtil.rotate(imgData, imageWidth, imageHeight, + mICamera.getCameraAngle(IDCardScanActivity.this)); + if (mIsVertical) { + imageWidth = mICamera.cameraHeight; + imageHeight = mICamera.cameraWidth; + } + long start = System.currentTimeMillis(); + RectF rectF; + if (!mIsVertical) { + rectF = mNewIndicatorView.getPosition(); + } else { + rectF = mIdCardIndicator.getPosition(); + } + Rect roi = new Rect(); + roi.left = (int) (rectF.left * imageWidth); + roi.top = (int) (rectF.top * imageHeight); + roi.right = (int) (rectF.right * imageWidth); + roi.bottom = (int) (rectF.bottom * imageHeight); + + if (!isEven01(roi.left)) + roi.left = roi.left + 1; + if (!isEven01(roi.top)) + roi.top = roi.top + 1; + if (!isEven01(roi.right)) + roi.right = roi.right - 1; + if (!isEven01(roi.bottom)) + roi.bottom = roi.bottom - 1; + + final IDCardQualityResult result = idCardQualityAssessment.getQuality(imgData, imageWidth, + imageHeight, mSide, roi); + + long end = System.currentTimeMillis(); + + final long perFrameMillis = end - start; + mCount++; + mTimSum += (end - start); + + runOnUiThread(new Runnable() { + @Override + public void run() { + if (isDebugMode) { + if (result != null && result.attr != null) { + String debugResult = "clear: " + new BigDecimal(result.attr.lowQuality).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() + "\n" + + "in_bound: " + new BigDecimal(result.attr.inBound).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() + "\n" + + "is_idcard: " + new BigDecimal(result.attr.isIdcard).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue() + "\n" + + "flare: " + result.attr.specularHightlightCount + "\n" + + "shadow: " + result.attr.shadowCount + "\n" + + "millis: " + perFrameMillis; + logInfo.setText(debugResult); + } + debugRectangle.setVisibility(View.VISIBLE); + } else { + logInfo.setText(""); + debugRectangle.setVisibility(View.GONE); + } + } + }); + + if (result != null) { + if (result.attr != null) { + float inBound = result.attr.inBound; + float isIDCard = result.attr.isIdcard; + if (isIDCard > mIsIDCard && inBound > 0) + if (!mIsVertical) + mNewIndicatorView.setBackColor(IDCardScanActivity.this, 0xaa000000); + else + mIdCardIndicator.setBackColor(IDCardScanActivity.this, 0xaa000000); + else if (!mIsVertical) + mNewIndicatorView.setBackColor(IDCardScanActivity.this, 0x00000000); + else + mIdCardIndicator.setBackColor(IDCardScanActivity.this, 0x00000000); + } + if (result.isValid()) { + vibrator.vibrate(new long[]{0, 50, 50, 100, 50}, -1); + mHasSuccess = true; + handleSuccess(result); + return; + } else { + if (!mIsVertical) + mNewIndicatorView.setBackColor(IDCardScanActivity.this, 0x00000000); + else + mIdCardIndicator.setBackColor(IDCardScanActivity.this, 0x00000000); + runOnUiThread(new Runnable() { + @Override + public void run() { + List<IDCardQualityResult.IDCardFailedType> failTypes = (result == null) ? null : result.fails; + if (failTypes != null) { + StringBuilder stringBuilder = new StringBuilder(); + IDCardQualityResult.IDCardFailedType errType = failTypes.get(0); + if (mIsVertical) + verticalTitle.setText(Util.errorType2HumanStr(failTypes.get(0), mSide)); + else + horizontalTitle.setText(Util.errorType2HumanStr(failTypes.get(0), mSide)); + mLstErrType = errType; + errorType.setText(stringBuilder.toString()); + } else { + verticalTitle.setText(""); + horizontalTitle.setText(""); + } + if (mCount != 0&& mTimSum!=0) + fps.setText((1000 * mCount / mTimSum) + " FPS"); + } + }); + } + } + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private void handleSuccess(IDCardQualityResult result) { + Intent intent = new Intent(); + intent.putExtra("side", mSide == IDCardAttr.IDCardSide.IDCARD_SIDE_FRONT ? 0 : 1); + intent.putExtra("idcardImg", Util.bmp2byteArr(result.croppedImageOfIDCard())); + if (result.attr.side == IDCardAttr.IDCardSide.IDCARD_SIDE_FRONT) { + intent.putExtra("portraitImg", Util.bmp2byteArr(result.croppedImageOfPortrait())); + } + setResult(RESULT_OK, intent); + Util.cancleToast(IDCardScanActivity.this); + finish(); + } + } + + public static void startMe(Context context, IDCardAttr.IDCardSide side) { + if (side == null || context == null) + return; + Intent intent = new Intent(context, IDCardScanActivity.class); + intent.putExtra("side", side == IDCardAttr.IDCardSide.IDCARD_SIDE_FRONT ? 0 : 1); + context.startActivity(intent); + } + + // 用取余运算 + public boolean isEven01(int num) { + if (num % 2 == 0) { + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/LivenessActivity.java b/IDCardLib/src/main/java/com/megvii/idcardlib/LivenessActivity.java new file mode 100644 index 0000000..a6df5d0 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/LivenessActivity.java @@ -0,0 +1,496 @@ +package com.megvii.idcardlib; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.SurfaceTexture; +import android.hardware.Camera; +import android.hardware.Camera.CameraInfo; +import android.hardware.Camera.PreviewCallback; +import android.hardware.Camera.Size; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.view.TextureView; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.megvii.idcardlib.util.ConUtil; +import com.megvii.idcardlib.util.DialogUtil; +import com.megvii.idcardlib.util.FaceCamera; +import com.megvii.idcardlib.util.IDetection; +import com.megvii.idcardlib.util.IMediaPlayer; +import com.megvii.idcardlib.util.Screen; +import com.megvii.idcardlib.util.SensorUtil; +import com.megvii.idcardlib.view.CircleProgressBar; +import com.megvii.livenessdetection.DetectionConfig; +import com.megvii.livenessdetection.DetectionFrame; +import com.megvii.livenessdetection.Detector; +import com.megvii.livenessdetection.Detector.DetectionFailedType; +import com.megvii.livenessdetection.Detector.DetectionListener; +import com.megvii.livenessdetection.Detector.DetectionType; +import com.megvii.livenessdetection.FaceQualityManager; +import com.megvii.livenessdetection.FaceQualityManager.FaceQualityErrorType; +import com.megvii.livenessdetection.bean.FaceIDDataStruct; +import com.megvii.livenessdetection.bean.FaceInfo; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +public class LivenessActivity extends Activity + implements PreviewCallback, DetectionListener, TextureView.SurfaceTextureListener { + + private TextureView camerapreview; + private FaceMask mFaceMask;// 画脸位置的类(调试时会用到) + private ProgressBar mProgressBar;// 网络上传请求验证时出现的ProgressBar + private LinearLayout headViewLinear;// "请在光线充足的情况下进行检测"这个视图 + private RelativeLayout rootView;// 根视图 + private TextView timeOutText; + private RelativeLayout timeOutRel; + private CircleProgressBar mCircleProgressBar; + private Detector mDetector;// 活体检测器 + private FaceCamera mICamera;// 照相机工具类 + private Handler mainHandler; + private HandlerThread mHandlerThread = new HandlerThread("videoEncoder"); + private Handler mHandler; + private JSONObject jsonObject; + private IMediaPlayer mIMediaPlayer;// 多媒体工具类 + private IDetection mIDetection; + private DialogUtil mDialogUtil; + private TextView promptText; + private boolean isHandleStart;// 是否开始检测 + private FaceQualityManager mFaceQualityManager; + private SensorUtil sensorUtil; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.liveness_layout); + init(); + initData(); + } + + private void init() { + sensorUtil = new SensorUtil(this); + Screen.initialize(this); + mainHandler = new Handler(); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()); + mIMediaPlayer = new IMediaPlayer(this); + mDialogUtil = new DialogUtil(this); + rootView = (RelativeLayout) findViewById(R.id.liveness_layout_rootRel); + mIDetection = new IDetection(this, rootView); + mFaceMask = (FaceMask) findViewById(R.id.liveness_layout_facemask); + mICamera = new FaceCamera(); + promptText = (TextView) findViewById(R.id.liveness_layout_promptText); + camerapreview = (TextureView) findViewById(R.id.liveness_layout_textureview); + camerapreview.setSurfaceTextureListener(this); + mProgressBar = (ProgressBar) findViewById(R.id.liveness_layout_progressbar); + mProgressBar.setVisibility(View.INVISIBLE); + headViewLinear = (LinearLayout) findViewById(R.id.liveness_layout_bottom_tips_head); + headViewLinear.setVisibility(View.VISIBLE); + timeOutRel = (RelativeLayout) findViewById(R.id.detection_step_timeoutRel); + timeOutText = (TextView) findViewById(R.id.detection_step_timeout_garden); + mCircleProgressBar = (CircleProgressBar) findViewById(R.id.detection_step_timeout_progressBar); + + mIDetection.viewsInit(); + } + + /** + * 初始化数据 + */ + private void initData() { + // 初始化活体检测器 + DetectionConfig config = new DetectionConfig.Builder().build(); + mDetector = new Detector(this, config); + boolean initSuccess = mDetector.init(this, ConUtil.readModel(this), ""); + if (!initSuccess) { + mDialogUtil.showDialog(getString(R.string.meglive_detect_initfailed)); + } + // 初始化动画 + new Thread(new Runnable() { + @Override + public void run() { + mIDetection.animationInit(); + } + }).start(); + } + + @Override + protected void onResume() { + super.onResume(); + isHandleStart = false; + int cameraID = 1; + if (!FaceCamera.hasFrontFacingCamera()) + cameraID = 0; + // 打开照相机 + Camera mCamera = mICamera.openCamera(this, cameraID); + if (mCamera != null) { + CameraInfo cameraInfo = new CameraInfo(); + Camera.getCameraInfo(cameraID, cameraInfo); + mFaceMask.setFrontal(cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT); + // 获取到相机分辨率对应的显示大小,并把这个值复制给camerapreview + RelativeLayout.LayoutParams layout_params = mICamera.getLayoutParam(); + camerapreview.setLayoutParams(layout_params); + mFaceMask.setLayoutParams(layout_params); + // 初始化人脸质量检测管理类 + mFaceQualityManager = new FaceQualityManager(1 - 0.5f, 0.5f); + mIDetection.mCurShowIndex = -1; + + } else { + mDialogUtil.showDialog(getString(R.string.meglive_camera_initfailed)); + } + } + + /** + * 开始检测 + */ + private void handleStart() { + if (isHandleStart) + return; + isHandleStart = true; + // 开始动画 + Animation animationIN = AnimationUtils.loadAnimation(LivenessActivity.this, R.anim.liveness_rightin); + Animation animationOut = AnimationUtils.loadAnimation(LivenessActivity.this, R.anim.liveness_leftout); + headViewLinear.startAnimation(animationOut); + mIDetection.mAnimViews[0].setVisibility(View.VISIBLE); + mIDetection.mAnimViews[0].startAnimation(animationIN); + animationOut.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + timeOutRel.setVisibility(View.VISIBLE); + } + }); + // 开始活体检测 + mainHandler.post(mTimeoutRunnable); + + jsonObject = new JSONObject(); + } + + private Runnable mTimeoutRunnable = new Runnable() { + @Override + public void run() { + // 倒计时开始 + initDetecteSession(); + if (mIDetection.mDetectionSteps != null) + changeType(mIDetection.mDetectionSteps.get(0), 10); + } + }; + + private void initDetecteSession() { + if (mICamera.mCamera == null) + return; + + mProgressBar.setVisibility(View.INVISIBLE); + mIDetection.detectionTypeInit(); + + mCurStep = 0; + mDetector.reset(); + mDetector.changeDetectionType(mIDetection.mDetectionSteps.get(0)); + } + + /** + * 照相机预览数据回调 (PreviewCallback的接口回调方法) + */ + @Override + public void onPreviewFrame(final byte[] data, Camera camera) { + Size previewsize = camera.getParameters().getPreviewSize(); + int angle = 360 - mICamera.getCameraAngle(this); + if (mICamera.cameraId == 0) + angle = angle - 180; + // 活体检测器检测 + mDetector.doDetection(data, previewsize.width, previewsize.height, angle); + } + + /** + * 活体验证成功 (DetectionListener的接口回调方法) + */ + @Override + public DetectionType onDetectionSuccess(final DetectionFrame validFrame) { + mIMediaPlayer.reset(); + mCurStep++; + mFaceMask.setFaceInfo(null); + + if (mCurStep == mIDetection.mDetectionSteps.size()) { + mProgressBar.setVisibility(View.VISIBLE); + getLivenessData(); + } else + changeType(mIDetection.mDetectionSteps.get(mCurStep), 10); + + // 检测器返回值:如果不希望检测器检测则返回DetectionType.DONE,如果希望检测器检测动作则返回要检测的动作 + return mCurStep >= mIDetection.mDetectionSteps.size() ? DetectionType.DONE + : mIDetection.mDetectionSteps.get(mCurStep); + } + + private void getLivenessData() { + new Thread(new Runnable() { + @Override + public void run() { + final FaceIDDataStruct idDataStruct = mDetector.getFaceIDDataStruct(); + final String delta = idDataStruct.delta; + final Map<String, byte[]> images = idDataStruct.images; + runOnUiThread(new Runnable() { + @Override + public void run() { + handleResult(R.string.verify_success, delta, images); + } + }); +// for (String key : idDataStruct.images.keySet()) { +// byte[] data = idDataStruct.images.get(key); +// if (key.equals("image_best")) { +// byte[] imageBestData = data;// 这是最好的一张图片 +// } else if (key.equals("image_env")) { +// byte[] imageEnvData = data;// 这是一张全景图 +// } else { +// // 其余为其他图片,根据需求自取 +// } +// } + } + }).start(); + } + + /** + * 活体检测失败 (DetectionListener的接口回调方法) + */ + @Override + public void onDetectionFailed(final DetectionFailedType type) { + //除下述类型外,还存在其它类型错误,但是不建议提示用户,详细可打印type.toString(),参考活体接口文档 + int resourceID = R.string.liveness_detection_failed; + switch (type) { + case ACTIONBLEND: + resourceID = R.string.liveness_detection_failed_action_blend; + break; + case NOTVIDEO: + resourceID = R.string.liveness_detection_failed_not_video; + break; + case TIMEOUT: + resourceID = R.string.liveness_detection_failed_timeout; + break; + + } + handleResult(resourceID, null, null); + } + + /** + * 活体验证中(这个方法会持续不断的回调,返回照片detection信息) (DetectionListener的接口回调方法) + */ + @Override + public void onFrameDetected(long timeout, DetectionFrame detectionFrame) { + // 如果需要适配加速度传感有问题的机型,可以加入超时自动过垂直判断机制,使用判断条件: sensorUtil.isVertical()||sensorUtil.isSensorFault() + if (sensorUtil.isVertical()) { + faceOcclusion(detectionFrame); + handleNotPass(timeout); + mFaceMask.setFaceInfo(detectionFrame); + } else { + if (sensorUtil.Y == 0 && Build.MANUFACTURER.equals("HUAWEI")) + promptText.setText(R.string.meglive_getpermission_motion); + else + promptText.setText(R.string.meglive_phone_vertical); + } + } + + /** + * 照镜子环节 + * 流程:1,先从返回的DetectionFrame中获取FaceInfo。在FaceInfo中可以先判断这张照片上的人脸是否有被遮挡的状况 + * ,入股有直接return + * 2,如果没有遮挡就把SDK返回的DetectionFramed传入人脸质量检测管理类mFaceQualityManager中获取FaceQualityErrorType的list + * 3.通过返回的list来判断这张照片上的人脸是否合格。 + * 如果返回list为空或list中FaceQualityErrorType的对象数量为0则表示这张照片合格开始进行活体检测 + */ + private void faceOcclusion(DetectionFrame detectionFrame) { + mFailFrame++; + if (detectionFrame != null) { + FaceInfo faceInfo = detectionFrame.getFaceInfo(); + if (faceInfo != null) { + if (faceInfo.eyeLeftOcclusion > 0.5 || faceInfo.eyeRightOcclusion > 0.5) { + if (mFailFrame > 10) { + mFailFrame = 0; + promptText.setText(R.string.meglive_keep_eyes_open); + } + return; + } + if (faceInfo.mouthOcclusion > 0.5) { + if (mFailFrame > 10) { + mFailFrame = 0; + promptText.setText(R.string.meglive_keep_mouth_open); + } + return; + } + boolean faceTooLarge = faceInfo.faceTooLarge; + mIDetection.checkFaceTooLarge(faceTooLarge); + } + } + // 从人脸质量检测管理类中获取错误类型list + faceInfoChecker(mFaceQualityManager.feedFrame(detectionFrame)); + } + + private int mFailFrame = 0; + + public void faceInfoChecker(List<FaceQualityErrorType> errorTypeList) { + if (errorTypeList == null || errorTypeList.size() == 0) + handleStart(); + else { + String infoStr = ""; + FaceQualityErrorType errorType = errorTypeList.get(0); + if (errorType == FaceQualityErrorType.FACE_NOT_FOUND) { + infoStr = getString(R.string.face_not_found); + } else if (errorType == FaceQualityErrorType.FACE_POS_DEVIATED) { + infoStr = getString(R.string.face_not_found); + } else if (errorType == FaceQualityErrorType.FACE_NONINTEGRITY) { + infoStr = getString(R.string.face_not_found); + } else if (errorType == FaceQualityErrorType.FACE_TOO_DARK) { + infoStr = getString(R.string.face_too_dark); + } else if (errorType == FaceQualityErrorType.FACE_TOO_BRIGHT) { + infoStr = getString(R.string.face_too_bright); + } else if (errorType == FaceQualityErrorType.FACE_TOO_SMALL) { + infoStr = getString(R.string.face_too_small); + } else if (errorType == FaceQualityErrorType.FACE_TOO_LARGE) { + infoStr = getString(R.string.face_too_large); + } else if (errorType == FaceQualityErrorType.FACE_TOO_BLURRY) { + infoStr = getString(R.string.face_too_blurry); + } else if (errorType == FaceQualityErrorType.FACE_OUT_OF_RECT) { + infoStr = getString(R.string.face_out_of_rect); + } + + if (mFailFrame > 10) { + mFailFrame = 0; + promptText.setText(infoStr); + } + } + } + + /** + * 跳转Activity传递信息 + */ + private void handleResult(final int resID, String delta, Map<String, byte[]> images) { + String resultString = getResources().getString(resID); + try { + jsonObject.put("result", resultString); + jsonObject.put("resultcode", resID); + } catch (JSONException e) { + e.printStackTrace(); + } + Intent intent = new Intent(); + Bundle bundle = new Bundle(); + bundle.putString("result", jsonObject.toString()); + bundle.putString("delta", delta); + bundle.putSerializable("images", (Serializable) images); + intent.putExtras(bundle); + setResult(RESULT_OK, intent); + + finish(); + } + + private int mCurStep = 0;// 检测动作的次数 + + public void changeType(final Detector.DetectionType detectiontype, long timeout) { + // 动画切换 + mIDetection.changeType(detectiontype, timeout); + mFaceMask.setFaceInfo(null); + + // 语音播放 + if (mCurStep == 0) { + mIMediaPlayer.doPlay(mIMediaPlayer.getSoundRes(detectiontype)); + } else { + mIMediaPlayer.doPlay(R.raw.meglive_well_done); + mIMediaPlayer.setOnCompletionListener(detectiontype); + } + } + + public void handleNotPass(final long remainTime) { + if (remainTime > 0) { + mainHandler.post(new Runnable() { + @Override + public void run() { + timeOutText.setText(remainTime / 1000 + ""); + mCircleProgressBar.setProgress((int) (remainTime / 100)); + } + }); + } + } + + private boolean mHasSurface = false; + + /** + * TextureView启动成功后 启动相机预览和添加活体检测回调 + * (TextureView.SurfaceTextureListener的接口回调方法) + */ + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + mHasSurface = true; + doPreview(); + + // 添加活体检测回调 (本Activity继承了DetectionListener) + mDetector.setDetectionListener(this); + // 添加相机预览回调(本Activity继承了PreviewCallback) + mICamera.actionDetect(this); + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + } + + /** + * TextureView销毁后 (TextureView.SurfaceTextureListener的接口回调方法) + */ + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + mHasSurface = false; + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + } + + private void doPreview() { + if (!mHasSurface) + return; + + mICamera.startPreview(camerapreview.getSurfaceTexture()); + } + + @Override + protected void onPause() { + super.onPause(); + mainHandler.removeCallbacksAndMessages(null); + mICamera.closeCamera(); + mIMediaPlayer.close(); + finish(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mDetector != null) + mDetector.release(); + mDialogUtil.onDestory(); + mIDetection.onDestroy(); + sensorUtil.release(); + if (mHandlerThread != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + mHandlerThread.quitSafely(); + } else { + mHandlerThread.quit(); + } + } + + } +} \ No newline at end of file diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/ConUtil.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/ConUtil.java new file mode 100644 index 0000000..ecd1a0a --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/ConUtil.java @@ -0,0 +1,444 @@ +package com.megvii.idcardlib.util; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager.NameNotFoundException; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.graphics.RectF; +import android.media.ExifInterface; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.telephony.TelephonyManager; +import android.util.Base64; +import android.view.Gravity; +import android.view.inputmethod.InputMethodManager; +import android.widget.Toast; + +import com.megvii.idcardlib.R; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Random; +import java.util.UUID; + +public class ConUtil { + + /** + * 根据byte数组,生成文件 + */ + public static String saveJPGFile(Context mContext, byte[] data, String key) { + if (data == null) + return null; + + File mediaStorageDir = mContext.getExternalFilesDir(Constant.cacheImage); + + if (!mediaStorageDir.exists()) { + if (!mediaStorageDir.mkdirs()) { + return null; + } + } + + BufferedOutputStream bos = null; + FileOutputStream fos = null; + try { + String jpgFileName = System.currentTimeMillis() + "" + new Random().nextInt(1000000) + "_" + key + ".jpg"; + fos = new FileOutputStream(mediaStorageDir + "/" + jpgFileName); + bos = new BufferedOutputStream(fos); + bos.write(data); + return mediaStorageDir.getAbsolutePath() + "/" + jpgFileName; + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (bos != null) { + try { + bos.close(); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + if (fos != null) { + try { + fos.close(); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + } + return null; + } + + public static void copyModels(Context context) { + File dstModelFile = new File(context.getExternalFilesDir(null), "model"); + if (dstModelFile.exists()) { + return; + } + + try { + String tmpFile = "model"; + BufferedInputStream inputStream = new BufferedInputStream(context.getAssets().open(tmpFile)); + BufferedOutputStream foutputStream = new BufferedOutputStream(new FileOutputStream(dstModelFile)); + + byte[] buffer = new byte[1024]; + int readcount = -1; + while ((readcount = inputStream.read(buffer)) != -1) { + foutputStream.write(buffer, 0, readcount); + } + foutputStream.close(); + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static byte[] readModel(Context context) { + InputStream inputStream = null; + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int count = -1; + try { + inputStream = context.getResources().openRawResource(R.raw.livenessmodel); + while ((count = inputStream.read(buffer)) != -1) { + byteArrayOutputStream.write(buffer, 0, count); + } + byteArrayOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return byteArrayOutputStream.toByteArray(); + } + + public static String getUUIDString(Context mContext) { + String KEY_UUID = "key_uuid"; + SharedUtil sharedUtil = new SharedUtil(mContext); + String uuid = sharedUtil.getStringValueByKey(KEY_UUID); + if (uuid != null && uuid.trim().length() != 0) + return uuid; + + uuid = UUID.randomUUID().toString(); + uuid = Base64.encodeToString(uuid.getBytes(), Base64.DEFAULT); + sharedUtil.saveStringValue(KEY_UUID, uuid); + return uuid; + } + + public static String getPhoneNumber(Context mContext) { + TelephonyManager phoneMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + return phoneMgr.getLine1Number(); + } + + public static String getDeviceID(Context mContext) { + TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + return tm.getDeviceId(); + } + + public static String getMacAddress(Context mContext) { + WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + WifiInfo info = wifi.getConnectionInfo(); + String address = info.getMacAddress(); + if (address != null && address.length() > 0) { + address = address.replace(":", ""); + } + return address; + } + + /** + * 获取bitmap的灰度图像 + */ + public static byte[] getGrayscale(Bitmap bitmap) { + if (bitmap == null) + return null; + + byte[] ret = new byte[bitmap.getWidth() * bitmap.getHeight()]; + for (int j = 0; j < bitmap.getHeight(); ++j) + for (int i = 0; i < bitmap.getWidth(); ++i) { + int pixel = bitmap.getPixel(i, j); + int red = ((pixel & 0x00FF0000) >> 16); + int green = ((pixel & 0x0000FF00) >> 8); + int blue = pixel & 0x000000FF; + ret[j * bitmap.getWidth() + i] = (byte) ((299 * red + 587 * green + 114 * blue) / 1000); + } + return ret; + } + + /** + * 读取图片属性:旋转的角度 + * + * @param path + * 图片绝对路径 + * @return degree旋转的角度 + */ + public static int readPictureDegree(String path) { + int degree = 0; + try { + ExifInterface exifInterface = new ExifInterface(path); + int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, + ExifInterface.ORIENTATION_NORMAL); + switch (orientation) { + case ExifInterface.ORIENTATION_ROTATE_90: + degree = 90; + break; + case ExifInterface.ORIENTATION_ROTATE_180: + degree = 180; + break; + case ExifInterface.ORIENTATION_ROTATE_270: + degree = 270; + break; + } + } catch (IOException e) { + e.printStackTrace(); + } + return degree; + } + + /** + * 旋转图片 + * + * @param angle + * @param bitmap + * @return Bitmap + */ + public static Bitmap rotateImage(int angle, Bitmap bitmap) { + // 图片旋转矩阵 + Matrix matrix = new Matrix(); + matrix.postRotate(angle); + // 得到旋转后的图片 + Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); + return resizedBitmap; + } + + private static Bitmap getBitMap(String fileSrc, int dstWidth) { + if (dstWidth == -1) { + return BitmapFactory.decodeFile(fileSrc); + } + // 获取图片的宽和高 + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(fileSrc, options); + + // 压缩图片 + options.inSampleSize = Math.max(1, + (int) (Math.max((double) options.outWidth / dstWidth, (double) options.outHeight / dstWidth))); + options.inJustDecodeBounds = false; + return BitmapFactory.decodeFile(fileSrc, options); + } + + /** + * 压缩图 + */ + public static Bitmap getBitmapConsiderExif(String imagePath) { + + // 获取照相后的bitmap + // Bitmap tmpBitmap = BitmapFactory.decodeFile(imagePath); + Bitmap tmpBitmap = getBitMap(imagePath, 800); + if (tmpBitmap == null) + return null; + Matrix matrix = new Matrix(); + matrix.postRotate(readPictureDegree(imagePath)); + tmpBitmap = Bitmap.createBitmap(tmpBitmap, 0, 0, tmpBitmap.getWidth(), tmpBitmap.getHeight(), matrix, true); + tmpBitmap = tmpBitmap.copy(Config.ARGB_8888, true); + + int hight = tmpBitmap.getHeight() > tmpBitmap.getWidth() ? tmpBitmap.getHeight() : tmpBitmap.getWidth(); + + float scale = hight / 800.0f; + + if (scale > 1) { + tmpBitmap = Bitmap.createScaledBitmap(tmpBitmap, (int) (tmpBitmap.getWidth() / scale), + (int) (tmpBitmap.getHeight() / scale), false); + } + return tmpBitmap; + } + + /** + * 切图 + */ + public static Bitmap cropImage(RectF rect, Bitmap bitmap) { + float width = rect.width() * 2; + if (width > bitmap.getWidth()) { + width = bitmap.getWidth(); + } + + float hight = rect.height() * 2; + if (hight > bitmap.getHeight()) { + hight = bitmap.getHeight(); + } + + float l = rect.centerX() - (width / 2); + if (l < 0) { + l = 0; + } + float t = rect.centerY() - (hight / 2); + if (t < 0) { + t = 0; + } + if (l + width > bitmap.getWidth()) { + width = bitmap.getWidth() - l; + } + if (t + hight > bitmap.getHeight()) { + hight = bitmap.getHeight() - t; + } + + return Bitmap.createBitmap(bitmap, (int) l, (int) t, (int) width, (int) hight); + + } + + /** + * 切图 + */ + public static Bitmap cutImage(RectF rect, String imagePath) { + Bitmap bitmap = BitmapFactory.decodeFile(imagePath); + return cropImage(rect, bitmap); + + } + + /** + * 照相机拍照后照片存储路径 + */ + public static File getOutputMediaFile(Context mContext) { + File mediaStorageDir = mContext.getExternalFilesDir(Constant.cacheCampareImage); + if (!mediaStorageDir.exists()) { + if (!mediaStorageDir.mkdirs()) { + return null; + } + } + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + File mediaFile; + + mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"); + return mediaFile; + } + + /** + * 隐藏软键盘 + */ + public static void isGoneKeyBoard(Activity activity) { + if (activity.getCurrentFocus() != null) { + // 隐藏软键盘 + ((InputMethodManager) activity.getSystemService(activity.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow( + activity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + + /** + * 输出toast + */ + public static void showToast(Context context, String str) { + if (context != null) { + Toast toast = Toast.makeText(context, str, Toast.LENGTH_SHORT); + // 可以控制toast显示的位置 + toast.setGravity(Gravity.TOP, 0, 30); + toast.show(); + } + } + + /** + * 输出长时间toast + */ + public static void showLongToast(Context context, String str) { + if (context != null) { + Toast toast = Toast.makeText(context, str, Toast.LENGTH_LONG); + // 可以控制toast显示的位置 + toast.setGravity(Gravity.TOP, 0, 30); + toast.show(); + } + } + + /** + * 获取APP版本名 + */ + public static String getVersionName(Context context) { + try { + String versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; + return versionName; + } catch (NameNotFoundException e) { + e.printStackTrace(); + return null; + } + } + + /** + * 镜像旋转 + */ + public static Bitmap convert(Bitmap bitmap, boolean mIsFrontalCamera) { + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + Bitmap newbBitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图 + Canvas cv = new Canvas(newbBitmap); + Matrix m = new Matrix(); + // m.postScale(1, -1); //镜像垂直翻转 + if (mIsFrontalCamera) { + m.postScale(-1, 1); // 镜像水平翻转 + } + // m.postRotate(-90); //旋转-90度 + Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0, 0, w, h, m, true); + cv.drawBitmap(bitmap2, new Rect(0, 0, bitmap2.getWidth(), bitmap2.getHeight()), new Rect(0, 0, w, h), null); + return newbBitmap; + } + + /** + * 保存bitmap至指定Picture文件夹 + */ + public static String saveBitmap(Context mContext, Bitmap bitmaptosave) { + if (bitmaptosave == null) + return null; + + File mediaStorageDir = mContext.getExternalFilesDir(Constant.cacheImage); + + if (!mediaStorageDir.exists()) { + if (!mediaStorageDir.mkdirs()) { + return null; + } + } + // String bitmapFileName = System.currentTimeMillis() + ".jpg"; + String bitmapFileName = System.currentTimeMillis() + ""; + FileOutputStream fos = null; + try { + fos = new FileOutputStream(mediaStorageDir + "/" + bitmapFileName); + boolean successful = bitmaptosave.compress(Bitmap.CompressFormat.JPEG, 75, fos); + + if (successful) + return mediaStorageDir.getAbsolutePath() + "/" + bitmapFileName; + else + return null; + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } finally { + try { + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 时间格式化(格式到秒) + */ + public static String getFormatterTime(long time) { + Date d = new Date(time); + SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd"); + String data = formatter.format(d); + return data; + } + +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/Constant.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/Constant.java new file mode 100644 index 0000000..5c73d62 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/Constant.java @@ -0,0 +1,14 @@ + +package com.megvii.idcardlib.util; + +import android.os.Environment; + + +public class Constant { + + public static String cacheText = "livenessDemo_text"; + public static String cacheImage = "livenessDemo_image"; + public static String cacheVideo = "livenessDemo_video"; + public static String cacheCampareImage = "livenessDemo_campareimage"; + public static String dirName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/faceapp"; +} \ No newline at end of file diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/DialogUtil.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/DialogUtil.java new file mode 100644 index 0000000..d4cbe56 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/DialogUtil.java @@ -0,0 +1,34 @@ +package com.megvii.idcardlib.util; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; + +public class DialogUtil { + + private Activity activity; + private AlertDialog alertDialog; + + public DialogUtil(Activity activity) { + this.activity = activity; + } + + public void showDialog(String message) { + alertDialog = new AlertDialog.Builder(activity) + .setTitle(message) + .setNegativeButton("确认", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + activity.finish(); + } + }).setCancelable(false).create(); + alertDialog.show(); + } + + public void onDestory() { + if(alertDialog!=null) { + alertDialog.dismiss(); + } + activity = null; + } +} \ No newline at end of file diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/FaceCamera.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/FaceCamera.java new file mode 100644 index 0000000..20d2332 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/FaceCamera.java @@ -0,0 +1,299 @@ +package com.megvii.idcardlib.util; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.graphics.SurfaceTexture; +import android.graphics.YuvImage; +import android.hardware.Camera; +import android.hardware.Camera.CameraInfo; +import android.os.Build; +import android.view.Surface; +import android.widget.RelativeLayout; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * 照相机工具类 + */ +public class FaceCamera { + public Camera mCamera; + public int cameraWidth; + public int cameraHeight; + public int cameraId = 1;//前置摄像头 + + public FaceCamera() { + } + + /** + * 打开相机 + */ + public Camera openCamera(Activity activity,int cameraId) { + try { + this.cameraId=cameraId; + mCamera = Camera.open(cameraId); + CameraInfo cameraInfo = new CameraInfo(); + Camera.getCameraInfo(cameraId, cameraInfo); + Camera.Parameters params = mCamera.getParameters(); + Camera.Size bestPreviewSize = calBestPreviewSize( + mCamera.getParameters(), 640, 480); + cameraWidth = bestPreviewSize.width; + cameraHeight = bestPreviewSize.height; + params.setPreviewSize(cameraWidth, cameraHeight); + mCamera.setDisplayOrientation(getCameraAngle(activity)); + mCamera.setParameters(params); + return mCamera; + } catch (Exception e) { + return null; + } + } + + /** + * 通过屏幕参数、相机预览尺寸计算布局参数 + */ + public RelativeLayout.LayoutParams getLayoutParam() { + + Camera.Size previewSize = mCamera.getParameters().getPreviewSize(); + float scale = Math.min(Screen.mWidth * 1.0f / previewSize.height, + Screen.mHeight * 1.0f / previewSize.width); + int layout_width = (int) (scale * previewSize.height); + int layout_height = (int) (scale * previewSize.width); + + RelativeLayout.LayoutParams layout_params = new RelativeLayout.LayoutParams( + layout_width, layout_height); + + return layout_params; + } + + + + /** + * 如果需要全屏预览,打开下列注释,并注释掉上方getLayoutParam() 方法,openCamera()中调节分辨率到1280 X 720, + * 在部分华为机型(存在底部虚拟键的状态栏)需要设置 LivenessActivity 的Theme 为: + * android:theme="@android:style/Theme.Holo.NoActionBar.TranslucentDecor" 才可以预览正常。 + */ +// public RelativeLayout.LayoutParams getLayoutParam() { +// float scale = cameraWidth * 1.0f / cameraHeight; +// int layout_width = Screen.mWidth; +// int layout_height = (int) (layout_width * scale); +// if (Screen.mWidth >= Screen.mHeight) { +// layout_height = Screen.mHeight; +// layout_width = (int) (layout_height / scale); +// } +// +// RelativeLayout.LayoutParams layout_params = new RelativeLayout.LayoutParams( +// layout_width, layout_height); +// layout_params.addRule(RelativeLayout.CENTER_HORIZONTAL);// 设置照相机水平居中 +// return layout_params; +// } + + /** + * 开始检测脸 + * + */ + public void actionDetect(Camera.PreviewCallback mActivity) { + try { + if (mCamera != null) { + mCamera.setPreviewCallback(mActivity); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Start preview. + * + * @param surfaceTexture the surface texture + */ + public void startPreview(SurfaceTexture surfaceTexture) { + try { + if (mCamera != null) { + try { + mCamera.setPreviewTexture(surfaceTexture); + mCamera.startPreview(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Close camera. + */ + public void closeCamera() { + try { + if (mCamera != null) { + mCamera.stopPreview(); + mCamera.setPreviewCallback(null); + mCamera.release(); + mCamera = null; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 通过传入的宽高算出最接近于宽高值的相机大小 + */ + private Camera.Size calBestPreviewSize(Camera.Parameters camPara, + final int width, final int height) { + List<Camera.Size> allSupportedSize = camPara.getSupportedPreviewSizes(); + ArrayList<Camera.Size> widthLargerSize = new ArrayList<Camera.Size>(); + for (Camera.Size tmpSize : allSupportedSize) { + if (tmpSize.width > tmpSize.height) { + widthLargerSize.add(tmpSize); + } + } + + Collections.sort(widthLargerSize, new Comparator<Camera.Size>() { + @Override + public int compare(Camera.Size lhs, Camera.Size rhs) { + int off_one = Math.abs(lhs.width * lhs.height - width * height); + int off_two = Math.abs(rhs.width * rhs.height - width * height); + return off_one - off_two; + } + }); + + return widthLargerSize.get(0); + } + + public Camera getCameraSafely(int cameraId) { + Camera camera = null; + try { + camera = Camera.open(cameraId); + } catch (Exception e) { + camera = null; + } + return camera; + } + + + public RelativeLayout.LayoutParams getParams(Camera camera) { + Camera.Parameters camPara = camera.getParameters(); + Camera.Size bestPreviewSize = calBestPreviewSize(camPara, + Screen.mWidth, Screen.mHeight); + cameraWidth = bestPreviewSize.width; + cameraHeight = bestPreviewSize.height; + camPara.setPreviewSize(cameraWidth, cameraHeight); + camera.setParameters(camPara); + + float scale = bestPreviewSize.width / bestPreviewSize.height; + + RelativeLayout.LayoutParams layoutPara = new RelativeLayout.LayoutParams( + (int) (bestPreviewSize.width), + (int) (bestPreviewSize.width / scale)); + + layoutPara.addRule(RelativeLayout.CENTER_HORIZONTAL);// 设置照相机水平居中 + return layoutPara; + } + + + public Bitmap getBitMap(byte[] data, Camera camera, boolean mIsFrontalCamera) { + int width = camera.getParameters().getPreviewSize().width; + int height = camera.getParameters().getPreviewSize().height; + YuvImage yuvImage = new YuvImage(data, camera.getParameters() + .getPreviewFormat(), width, height, null); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + yuvImage.compressToJpeg(new Rect(0, 0, width, height), 80, + byteArrayOutputStream); + byte[] jpegData = byteArrayOutputStream.toByteArray(); + // 获取照相后的bitmap + Bitmap tmpBitmap = BitmapFactory.decodeByteArray(jpegData, 0, + jpegData.length); + Matrix matrix = new Matrix(); + matrix.reset(); + if (mIsFrontalCamera) { + matrix.setRotate(-90); + } else { + matrix.setRotate(90); + } + tmpBitmap = Bitmap.createBitmap(tmpBitmap, 0, 0, tmpBitmap.getWidth(), + tmpBitmap.getHeight(), matrix, true); + tmpBitmap = tmpBitmap.copy(Bitmap.Config.ARGB_8888, true); + + int hight = tmpBitmap.getHeight() > tmpBitmap.getWidth() ? tmpBitmap + .getHeight() : tmpBitmap.getWidth(); + + float scale = hight / 800.0f; + + if (scale > 1) { + tmpBitmap = Bitmap.createScaledBitmap(tmpBitmap, + (int) (tmpBitmap.getWidth() / scale), + (int) (tmpBitmap.getHeight() / scale), false); + } + return tmpBitmap; + } + + /** + * 获取照相机旋转角度 + */ + public int getCameraAngle(Activity activity) { + int rotateAngle = 90; + CameraInfo info = new CameraInfo(); + Camera.getCameraInfo(cameraId, info); + int rotation = activity.getWindowManager().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; + } + + if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { + rotateAngle = (info.orientation + degrees) % 360; + rotateAngle = (360 - rotateAngle) % 360; // compensate the mirror + } else { // back-facing + rotateAngle = (info.orientation - degrees + 360) % 360; + } + return rotateAngle; + } + + + public static boolean hasFrontFacingCamera() { + final int CAMERA_FACING_BACK = 1; + return checkCameraFacing(CAMERA_FACING_BACK); + } + + private static boolean checkCameraFacing(final int facing) { + if (getSdkVersion() < Build.VERSION_CODES.GINGERBREAD) { + return false; + } + final int cameraCount = Camera.getNumberOfCameras(); + CameraInfo info = new CameraInfo(); + for (int i = 0; i < cameraCount; i++) { + Camera.getCameraInfo(i, info); + if (facing == info.facing) { + return true; + } + } + return false; + } + + /** + * Gets sdk version. + */ + public static int getSdkVersion() { + return Build.VERSION.SDK_INT; + } +} \ No newline at end of file diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/ICamera.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/ICamera.java new file mode 100644 index 0000000..b1a0d2e --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/ICamera.java @@ -0,0 +1,319 @@ +package com.megvii.idcardlib.util; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.graphics.SurfaceTexture; +import android.graphics.YuvImage; +import android.hardware.Camera; +import android.hardware.Camera.CameraInfo; +import android.hardware.Camera.Parameters; +import android.view.Surface; +import android.widget.RelativeLayout; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * 照相机工具类 + */ +public class ICamera { + + public Camera mCamera; + public int cameraWidth; + public int cameraHeight; + private int cameraId = 0;// 后置摄像头 + private boolean mIsVertical = false; + private int screenWidth; + private int screenHeight; + + public ICamera(boolean isVertical) { + this.mIsVertical = isVertical; + } + + public static Camera.Size getNearestRatioSize(Parameters para, + final int screenWidth, final int screenHeight) { + List<Camera.Size> supportedSize = para.getSupportedPreviewSizes(); + for (Camera.Size tmp : supportedSize) { + if (tmp.width == 1280 && tmp.height == 720) { + return tmp; + } + if (tmp.width == 960 && tmp.height == 540) { + return tmp; + } + } + Collections.sort(supportedSize, new Comparator<Camera.Size>() { + @Override + public int compare(Camera.Size lhs, Camera.Size rhs) { + int diff1 = (((int) ((1000 * (Math.abs(lhs.width + / (float) lhs.height - screenWidth + / (float) screenHeight))))) << 16) + - lhs.width; + int diff2 = (((int) (1000 * (Math.abs(rhs.width + / (float) rhs.height - screenWidth + / (float) screenHeight)))) << 16) + - rhs.width; + + return diff1 - diff2; + } + }); + + return supportedSize.get(0); + } + + /** + * 打开相机 + */ + public Camera openCamera(Activity activity) { + try { + screenWidth = activity.getWindowManager().getDefaultDisplay() + .getWidth(); + screenHeight = activity.getWindowManager().getDefaultDisplay() + .getHeight(); + mCamera = Camera.open(cameraId); + CameraInfo cameraInfo = new CameraInfo(); + Camera.getCameraInfo(cameraId, cameraInfo); + Parameters params = mCamera.getParameters(); +// Camera.Size bestPreviewSize = getNearestRatioSize( +// mCamera.getParameters(), screenWidth, screenHeight); + Camera.Size bestPreviewSize = + calBestPreviewSize(mCamera.getParameters(), screenWidth, screenHeight); + cameraWidth = bestPreviewSize.width; + cameraHeight = bestPreviewSize.height; + params.setPreviewSize(cameraWidth, cameraHeight); + List<String> focusModes = params.getSupportedFocusModes(); + if (focusModes + .contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { + params.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + } + mCamera.setDisplayOrientation(getCameraAngle(activity)); + mCamera.setParameters(params); + return mCamera; + } catch (Exception e) { + return null; + } + } + + public void autoFocus() { + try { + if (mCamera != null) { + Parameters parameters = mCamera.getParameters(); + List<String> focusModes = parameters.getSupportedFocusModes(); + if (focusModes.contains(Parameters.FOCUS_MODE_AUTO)) { + parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO); + mCamera.cancelAutoFocus(); + parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO); + mCamera.setParameters(parameters); + mCamera.autoFocus(null); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + // 通过屏幕参数、相机预览尺寸计算布局参数 + public RelativeLayout.LayoutParams getLayoutParam(Activity activity) { + + float scale = cameraWidth * 1.0f / cameraHeight; +// int layout_width = screenWidth; +// int layout_height = (int) (layout_width * 1.0f * scale); + int layout_width = (int) (screenHeight * 1.0f / scale); + int layout_height = screenHeight; + if(!mIsVertical){ + layout_height = screenWidth; + layout_width = (int) (layout_height * 1.0f * scale); + } + RelativeLayout.LayoutParams layout_params = new RelativeLayout.LayoutParams( + layout_width, layout_height); + layout_params.addRule(RelativeLayout.CENTER_HORIZONTAL);// 设置照相机水平居中 + return layout_params; + } + + /** + * 开始检测脸 + */ + public void actionDetect(Camera.PreviewCallback mActivity) { + try{ + if (mCamera != null) { + mCamera.setPreviewCallback(mActivity); + } + }catch (Exception e){ + + } + } + + public void startPreview(SurfaceTexture surfaceTexture) { + try { + if (mCamera != null) { + try { + mCamera.setPreviewTexture(surfaceTexture); + mCamera.startPreview(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + + } + } + + public void closeCamera() { + try { + if (mCamera != null) { + mCamera.stopPreview(); + mCamera.setPreviewCallback(null); + mCamera.release(); + mCamera = null; + } + }catch (Exception e){ + + } + + } + + /** + * 通过传入的宽高算出最接近于宽高值的相机大小 + */ + private Camera.Size calBestPreviewSize(Parameters camPara, + final int width, final int height) { + List<Camera.Size> allSupportedSize = camPara.getSupportedPreviewSizes(); + ArrayList<Camera.Size> widthLargerSize = new ArrayList<Camera.Size>(); + for (Camera.Size tmpSize : allSupportedSize) { + if (tmpSize.width > tmpSize.height) { + if (tmpSize.width > 1920) { + widthLargerSize.add(tmpSize); + } else if (tmpSize.width > 1280) { + tmpSize.width = 1920; + tmpSize.height = 1080; + widthLargerSize.add(tmpSize); + } else if (tmpSize.width > 1080) { + tmpSize.width = 1280; + tmpSize.height = 720; + widthLargerSize.add(tmpSize); + } else { + widthLargerSize.add(tmpSize); + } + } + } + + Collections.sort(widthLargerSize, new Comparator<Camera.Size>() { + @Override + public int compare(Camera.Size lhs, Camera.Size rhs) { + int off_one = Math.abs(lhs.width * lhs.height - width * height); + int off_two = Math.abs(rhs.width * rhs.height - width * height); + return off_one - off_two; + } + }); + + return widthLargerSize.get(0); + } + + /** + * 打开前置或后置摄像头 + */ + public Camera getCameraSafely(int cameraId) { + Camera camera = null; + try { + camera = Camera.open(cameraId); + } catch (Exception e) { + camera = null; + } + return camera; + } + + public RelativeLayout.LayoutParams getParams(Camera camera) { + Parameters camPara = camera.getParameters(); + // 注意Screen是否初始化 + Camera.Size bestPreviewSize = calBestPreviewSize(camPara, screenWidth, + screenHeight); + cameraWidth = bestPreviewSize.width; + cameraHeight = bestPreviewSize.height; + camPara.setPreviewSize(cameraWidth, cameraHeight); + camera.setParameters(camPara); + + float scale = bestPreviewSize.width / bestPreviewSize.height; + + RelativeLayout.LayoutParams layoutPara = new RelativeLayout.LayoutParams( + (int) (bestPreviewSize.width), + (int) (bestPreviewSize.width / scale)); + + layoutPara.addRule(RelativeLayout.CENTER_HORIZONTAL);// 设置照相机水平居中 + return layoutPara; + } + + public Bitmap getBitMap(byte[] data, Camera camera, boolean mIsFrontalCamera) { + int width = camera.getParameters().getPreviewSize().width; + int height = camera.getParameters().getPreviewSize().height; + YuvImage yuvImage = new YuvImage(data, camera.getParameters() + .getPreviewFormat(), width, height, null); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + yuvImage.compressToJpeg(new Rect(0, 0, width, height), 80, + byteArrayOutputStream); + byte[] jpegData = byteArrayOutputStream.toByteArray(); + // 获取照相后的bitmap + Bitmap tmpBitmap = BitmapFactory.decodeByteArray(jpegData, 0, + jpegData.length); + Matrix matrix = new Matrix(); + matrix.reset(); + if (mIsFrontalCamera) { + matrix.setRotate(-90); + } else { + matrix.setRotate(90); + } + tmpBitmap = Bitmap.createBitmap(tmpBitmap, 0, 0, tmpBitmap.getWidth(), + tmpBitmap.getHeight(), matrix, true); + tmpBitmap = tmpBitmap.copy(Bitmap.Config.ARGB_8888, true); + + int hight = tmpBitmap.getHeight() > tmpBitmap.getWidth() ? tmpBitmap + .getHeight() : tmpBitmap.getWidth(); + + float scale = hight / 800.0f; + + if (scale > 1) { + tmpBitmap = Bitmap.createScaledBitmap(tmpBitmap, + (int) (tmpBitmap.getWidth() / scale), + (int) (tmpBitmap.getHeight() / scale), false); + } + return tmpBitmap; + } + + /** + * 获取照相机旋转角度 + */ + public int getCameraAngle(Activity activity) { + int rotateAngle = 90; + CameraInfo info = new CameraInfo(); + Camera.getCameraInfo(cameraId, info); + int rotation = activity.getWindowManager().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; + } + + if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { + rotateAngle = (info.orientation + degrees) % 360; + rotateAngle = (360 - rotateAngle) % 360; // compensate the mirror + } else { // back-facing + rotateAngle = (info.orientation - degrees + 360) % 360; + } + return rotateAngle; + } +} \ No newline at end of file diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/IDetection.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/IDetection.java new file mode 100644 index 0000000..7367255 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/IDetection.java @@ -0,0 +1,177 @@ +package com.megvii.idcardlib.util; + +import android.content.Context; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.ImageView; +import android.widget.TextView; + +import com.megvii.idcardlib.R; +import com.megvii.livenessdetection.Detector; +import com.megvii.livenessdetection.Detector.DetectionType; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; + +/** + * 实体验证工具类 + */ +public class IDetection { + + private View rootView; + private Context mContext; + + public View[] mAnimViews; + private int num = 3;// 动作数量 + private HashMap<Integer, Drawable> mDrawableCache; + public int mCurShowIndex = -1;// 现在底部展示试图的索引值 + public ArrayList<Detector.DetectionType> mDetectionSteps;// 活体检测动作列表 + + public IDetection(Context mContext, View view) { + this.mContext = mContext; + this.rootView = view; + mDrawableCache = new HashMap<Integer, Drawable>(); + } + + public void animationInit() { + int[] reses = { R.drawable.liveness_head_pitch, R.drawable.liveness_head_yaw, + R.drawable.liveness_mouth_open_closed, R.drawable.liveness_eye_open_closed }; + for (int oneRes : reses) { + mDrawableCache.put(oneRes, (mContext.getResources().getDrawable(oneRes))); + } + } + + public void viewsInit() { + mAnimViews = new View[2]; + mAnimViews[0] = (rootView.findViewById(R.id.liveness_layout_first_layout)); + mAnimViews[1] = (rootView.findViewById(R.id.liveness_layout_second_layout)); + for (View tmpView : mAnimViews) { + tmpView.setVisibility(View.INVISIBLE); + } + } + + public void changeType(final Detector.DetectionType detectiontype, long timeout) { + Animation animationIN = AnimationUtils.loadAnimation(mContext, R.anim.liveness_rightin); + Animation animationOut = AnimationUtils.loadAnimation(mContext, R.anim.liveness_leftout); + + if (mCurShowIndex != -1) // 已经存在layout 需要移除之 + { + mAnimViews[mCurShowIndex].setVisibility(View.INVISIBLE); + mAnimViews[mCurShowIndex].setAnimation(animationOut); + } else { + mAnimViews[0].setVisibility(View.INVISIBLE); + mAnimViews[0].startAnimation(animationOut); + } + + mCurShowIndex = mCurShowIndex == -1 ? 0 : (mCurShowIndex == 0 ? 1 : 0); + initAnim(detectiontype, mAnimViews[mCurShowIndex]); + mAnimViews[mCurShowIndex].setVisibility(View.VISIBLE); + mAnimViews[mCurShowIndex].startAnimation(animationIN); + } + + TextView detectionNameText; + String detectionNameStr; + + private void initAnim(Detector.DetectionType detectiontype, View layoutView) { + ImageView tmpImageView = (ImageView) layoutView.findViewById(R.id.detection_step_image); + tmpImageView.setImageDrawable(getDrawRes(detectiontype)); + + ((AnimationDrawable) tmpImageView.getDrawable()).start(); + detectionNameText = (TextView) layoutView.findViewById(R.id.detection_step_name); + detectionNameStr = getDetectionName(detectiontype); + detectionNameText.setText(detectionNameStr); + } + + public void checkFaceTooLarge(boolean isLarge) { + if (detectionNameStr != null && detectionNameText != null) { + if (isLarge && !detectionNameText.getText().toString().equals(mContext.getString(R.string.face_too_large))) { + detectionNameText.setText(R.string.face_too_large); + } else if(!isLarge && detectionNameText.getText().toString().equals(mContext.getString(R.string.face_too_large))){ + detectionNameText.setText(detectionNameStr); + } + } + } + + private Drawable getDrawRes(Detector.DetectionType detectionType) { + int resID = -1; + switch (detectionType) { + case POS_PITCH: + case POS_PITCH_UP: + case POS_PITCH_DOWN: + resID = R.drawable.liveness_head_pitch; + break; + case POS_YAW_LEFT: + case POS_YAW_RIGHT: + case POS_YAW: + resID = R.drawable.liveness_head_yaw; + break; + case MOUTH: + resID = R.drawable.liveness_mouth_open_closed; + break; + case BLINK: + resID = R.drawable.liveness_eye_open_closed; + break; + } + Drawable cachedDrawAble = mDrawableCache.get(resID); + if (cachedDrawAble != null) + return cachedDrawAble; + else { + Drawable drawable = mContext.getResources().getDrawable(resID); + mDrawableCache.put(resID, (drawable)); + return drawable; + } + } + + private String getDetectionName(Detector.DetectionType detectionType) { + String detectionName = null; + switch (detectionType) { + case POS_PITCH: + detectionName = mContext.getString(R.string.meglive_pitch); + break; + case POS_YAW: + detectionName = mContext.getString(R.string.meglive_yaw); + break; + case MOUTH: + detectionName = mContext.getString(R.string.meglive_mouth_open_closed); + break; + case BLINK: + detectionName = mContext.getString(R.string.meglive_eye_open_closed); + break; + case POS_YAW_LEFT: + detectionName = mContext.getString(R.string.meglive_pos_yaw_left); + break; + case POS_YAW_RIGHT: + detectionName = mContext.getString(R.string.meglive_pos_yaw_right); + break; + } + return detectionName; + } + + /** + * 初始化检测动作 + */ + public void detectionTypeInit() { + ArrayList<DetectionType> tmpTypes = new ArrayList<Detector.DetectionType>(); + tmpTypes.add(Detector.DetectionType.BLINK);// 眨眼 + tmpTypes.add(Detector.DetectionType.MOUTH);// 张嘴 + tmpTypes.add(Detector.DetectionType.POS_PITCH);// 缓慢点头 + tmpTypes.add(Detector.DetectionType.POS_YAW);// 左右摇头 + Collections.shuffle(tmpTypes);// 打乱顺序 + mDetectionSteps = new ArrayList<DetectionType>(num); + for (int i = 0; i < num; i++) { + mDetectionSteps.add(tmpTypes.get(i)); + } + } + + public void onDestroy() { + rootView = null; + mContext = null; + if (mDrawableCache != null) { + mDrawableCache.clear(); + } + } +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/IFile.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/IFile.java new file mode 100644 index 0000000..861829f --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/IFile.java @@ -0,0 +1,77 @@ +package com.megvii.idcardlib.util; + + +import com.megvii.livenessdetection.DetectionFrame; +import com.megvii.livenessdetection.Detector; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; + +/** + * 文件工具类 + */ +public class IFile { + + public IFile() { + } + + /** + * 把图片保存到文件夹 + */ + public boolean save(Detector mDetector, String session, + JSONObject jsonObject) { + List<DetectionFrame> frames = mDetector.getValidFrame(); + if (frames.size() == 0) { + return false; + } + + try { + String dirPath = Constant.dirName + "/" + session; + File dir = new File(dirPath); + if (!dir.exists()) { + dir.mkdirs(); + } + for (int i = 0; i < frames.size(); i++) { + File file = new File(dir, session + "-" + i + ".jpg"); + FileOutputStream fileOutputStream = new FileOutputStream(file); + fileOutputStream.write(frames.get(i).getCroppedFaceImageData()); + JSONArray jsonArray = jsonObject.getJSONArray("imgs"); + jsonArray.put(file.getAbsoluteFile()); + fileOutputStream.flush(); + fileOutputStream.close(); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + + /** + * 把LOG保存到本地 + */ + public boolean saveLog(String session, String name) { + try { + String dirPath = Constant.dirName + "/" + session; + File dir = new File(dirPath); + if (!dir.exists()) { + dir.mkdirs(); + } + File file = new File(dir, "Log.txt"); + FileOutputStream fileOutputStream = new FileOutputStream(file, true); + String str = "\n" + session + ", " + name; + fileOutputStream.write(str.getBytes()); + fileOutputStream.flush(); + fileOutputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/IMediaPlayer.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/IMediaPlayer.java new file mode 100644 index 0000000..6ebc1d9 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/IMediaPlayer.java @@ -0,0 +1,98 @@ +package com.megvii.idcardlib.util; + +import android.content.Context; +import android.content.res.AssetFileDescriptor; +import android.media.MediaPlayer; + +import com.megvii.idcardlib.R; +import com.megvii.livenessdetection.Detector; + +public class IMediaPlayer { + public MediaPlayer mMediaPlayer; + private Context mContext; + + public IMediaPlayer(Context mContext) { + this.mContext = mContext; + mMediaPlayer = new MediaPlayer(); + } + + public void close(){ + mContext = null; + if (mMediaPlayer != null) { + mMediaPlayer.reset(); + mMediaPlayer.release(); + mMediaPlayer = null; + } + } + + /** + *重置 (重新设置播放器引擎) + */ + public void reset(){ + if (mMediaPlayer != null) { + mMediaPlayer.reset(); + } + } + + /** + *播放成功回调接口 + */ + public void setOnCompletionListener(final Detector.DetectionType detectiontype){ + if (mMediaPlayer == null) { + mMediaPlayer = new MediaPlayer(); + } + mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mediaPlayer) { + doPlay(getSoundRes(detectiontype)); + mMediaPlayer.setOnCompletionListener(null); + } + }); + } + + /** + * 多媒体播放 + */ + public void doPlay(int rawId) { + if (this.mMediaPlayer == null) + return; + mMediaPlayer.reset(); + try { + AssetFileDescriptor localAssetFileDescriptor = mContext.getResources().openRawResourceFd(rawId); + mMediaPlayer.setDataSource(localAssetFileDescriptor.getFileDescriptor(), + localAssetFileDescriptor.getStartOffset(), + localAssetFileDescriptor.getLength()); + localAssetFileDescriptor.close(); + mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mp) { + mMediaPlayer.start(); + } + }); + mMediaPlayer.prepareAsync(); + } catch (Exception localIOException) { + localIOException.printStackTrace(); + } + } + + public int getSoundRes(Detector.DetectionType detectionType) { + int resID = -1; + switch (detectionType) { + case POS_PITCH: + resID = R.raw.meglive_pitch_down; + break; + case POS_YAW_LEFT: + case POS_YAW_RIGHT: + case POS_YAW: + resID = R.raw.meglive_yaw; + break; + case MOUTH: + resID = R.raw.meglive_mouth_open; + break; + case BLINK: + resID = R.raw.meglive_eye_blink; + break; + } + return resID; + } +} \ No newline at end of file diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/MyTextView.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/MyTextView.java new file mode 100644 index 0000000..766f8e0 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/MyTextView.java @@ -0,0 +1,23 @@ +package com.megvii.idcardlib.util; + +import android.content.Context; +import android.graphics.Canvas; +import android.util.AttributeSet; +import android.widget.TextView; + +public class MyTextView extends TextView { + public MyTextView(Context context) { + super(context); + } + + public MyTextView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onDraw(Canvas canvas) { + // 倾斜度45,上下左右居中 + canvas.rotate(90, getMeasuredWidth() * 10 / 25, getMeasuredHeight() * 10 / 25); + super.onDraw(canvas); + } +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/RotaterUtil.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/RotaterUtil.java new file mode 100644 index 0000000..a936a6b --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/RotaterUtil.java @@ -0,0 +1,110 @@ +package com.megvii.idcardlib.util; + + +public class RotaterUtil { + + public static byte[] rotate(byte[] data, int imageWidth, int imageHeight, + int rotate) { + switch (rotate) { + case 0: + return data; + case 90: + return rotateYUV420Degree90(data, imageWidth, imageHeight); + case 180: + return rotateYUV420Degree180(data, imageWidth, imageHeight); + case 270: + return rotateYUV420Degree270(data, imageWidth, imageHeight); + } + return data; + } + + public static byte[] rotateYUV420Degree90(byte[] data, int imageWidth, + int imageHeight) { + byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2]; + // Rotate the Y luma + int i = 0; + for (int x = 0; x < imageWidth; x++) { + for (int y = imageHeight - 1; y >= 0; y--) { + yuv[i] = data[y * imageWidth + x]; + i++; + } + + } + // int offset = imageWidth * imageHeight; + // for (int x = 0; x < imageWidth / 2; x ++) + // for (int y = imageHeight / 2 - 1; y >= 0; y --) { + // yuv[i] = data[offset + (y * imageWidth) + x]; + // i ++ ; + // yuv[i] = data[offset + (y * imageWidth) + x + 1]; + // i ++; + // } + + // Rotate the U and V color components + i = imageWidth * imageHeight * 3 / 2 - 1; + for (int x = imageWidth - 1; x > 0; x = x - 2) { + for (int y = 0; y < imageHeight / 2; y++) { + yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x]; + i--; + yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + + (x - 1)]; + i--; + } + } + return yuv; + } + + public static byte[] rotateYUV420Degree180(byte[] data, int imageWidth, + int imageHeight) { + byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2]; + int i = 0; + int count = 0; + + for (i = imageWidth * imageHeight - 1; i >= 0; i--) { + yuv[count] = data[i]; + count++; + } + + i = imageWidth * imageHeight * 3 / 2 - 1; + for (i = imageWidth * imageHeight * 3 / 2 - 1; i >= imageWidth + * imageHeight; i -= 2) { + yuv[count++] = data[i - 1]; + yuv[count++] = data[i]; + } + return yuv; + } + + public static byte[] rotateYUV420Degree270(byte[] data, int imageWidth, + int imageHeight) { + byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2]; + // Rotate the Y luma + + int index = 0; + int i = 0; + for (int x = imageWidth - 1; x >= 0; x--) { + index = 0; + for (int y = 0; y < imageHeight; y++) { + yuv[i] = data[index + x]; + i++; + + index += imageWidth; + } + + } + // Rotate the U and V color components + i = imageWidth * imageHeight; + int count = imageWidth * imageHeight; + for (int x = imageWidth - 1; x > 0; x = x - 2) { + index = count; + for (int y = 0; y < imageHeight / 2; y++) { + + yuv[i] = data[index + (x - 1)]; + i++; + yuv[i] = data[index + x]; + i++; + + index += imageWidth; + } + } + return yuv; + } +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/Screen.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/Screen.java new file mode 100644 index 0000000..59ab762 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/Screen.java @@ -0,0 +1,94 @@ +package com.megvii.idcardlib.util; + +import android.content.Context; +import android.content.res.Resources; +import android.util.DisplayMetrics; + +public class Screen { + + public static float LEFTMENU_UI_PERCENT = 0.15f; + public static int mNotificationBarHeight; + + public static int mScreenWidth; + public static int mScreenHeight; + public static int mWidth; + public static int mHeight; + public static float densityDpi; + public static float density; + + public static float drawWidth; + public static float drawHeight; + + private static final int PADDING_L = 30; + private static final int PADDING_R = 30; + private static final int PADDING_T = 50; + private static final int PADDING_B = 40; + + public static float drawPaddingLeft; + public static float drawPaddingRight; + public static float drawPaddingTop; + public static float drawPaddingBottom; + + public static int drawRows; + public static float lineHeight; + public static float line_space = 0; + public static float charHeight; + + public static void initialize(Context context) { + if (drawWidth == 0 || drawHeight == 0 || mWidth == 0 || mHeight == 0 + || density == 0) { + Resources res = context.getResources(); + DisplayMetrics metrics = res.getDisplayMetrics(); + // TODO // - 50 + density = metrics.density; + mNotificationBarHeight = (int) (35 * density); + mWidth = metrics.widthPixels;// - (int)(50 * density) + mHeight = metrics.heightPixels/* - mNotificationBarHeight */;// - + // (int)(50 + // * + // density) + mScreenWidth = metrics.widthPixels; + mScreenHeight = metrics.heightPixels; + + densityDpi = metrics.densityDpi; + + drawPaddingLeft = density * PADDING_L; + drawPaddingRight = density * PADDING_R; + drawPaddingTop = density * PADDING_T; + drawPaddingBottom = density * PADDING_B; + + drawWidth = mWidth - drawPaddingLeft - drawPaddingRight; + // TODO 如果非全屏,�?��减去标题栏的高度 + drawHeight = mHeight - drawPaddingTop - drawPaddingBottom; + } + } + + public static String clipImageUrl(String url, String add) { + String temp = null; + if (url != null) { + if (add != null) { + if (url.endsWith(".jpg") || url.endsWith(".png") + || url.endsWith(".gif") || url.endsWith(".bmp")) { + String end = url.substring(url.length() - 4, url.length()); + int point = url.lastIndexOf("."); + int index = url.lastIndexOf("/"); + if (index != -1) { + String sub = url.substring(index + 1, point); + if (sub.endsWith("_m") || sub.endsWith("_b") + || sub.endsWith("_s")) { + String clip = sub.substring(0, sub.length() - 2); + temp = url.substring(0, index + 1) + clip + add + + end; + } else { + temp = url.substring(0, index + 1) + sub + add + + end; + } + } + } + } else { + temp = url; + } + } + return temp; + } +} \ No newline at end of file diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/SensorUtil.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/SensorUtil.java new file mode 100644 index 0000000..89a1b6b --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/SensorUtil.java @@ -0,0 +1,73 @@ +package com.megvii.idcardlib.util; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Handler; + +/** + *传感器工具类 + */ +public class SensorUtil implements SensorEventListener { + public float Y; + private SensorManager mSensorManager; + private Sensor mSensor; + private boolean isFail; + private Handler mHandler; + + public SensorUtil(Context context) { + init(context); + } + + private void init(Context context) { + mSensorManager = (SensorManager) context + .getSystemService(Context.SENSOR_SERVICE); + mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + if (mSensor != null) { + mSensorManager.registerListener(this, mSensor, + SensorManager.SENSOR_DELAY_NORMAL); + } else { + isFail = true; + } + mHandler = new Handler(); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + isFail = true; + } + }, 3000); + } + + @Override + public void onSensorChanged(SensorEvent event) { + Y = event.values[1]; + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + + } + + public void release() { + if (mSensor != null && mSensorManager != null) { + mSensorManager.unregisterListener(this); + } + if (mHandler != null) { + mHandler.removeCallbacksAndMessages(null); + } + } + + public boolean isVertical() { + if (Y >= 8) + return true; + + return false; + } + + public boolean isSensorFault() { + return isFail; + } + +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/SharedUtil.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/SharedUtil.java new file mode 100644 index 0000000..eea5811 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/SharedUtil.java @@ -0,0 +1,207 @@ +package com.megvii.idcardlib.util; + +import java.util.Map; + +import android.content.Context; +import android.content.SharedPreferences; + + +/** + * Save Data To SharePreference Or Get Data from SharePreference + * + * @author wanglx + *通过SharedPreferences来存储数据,自定义类型 + */ +public class SharedUtil { + private static String TAG = "PushSharePreference"; + private Context ctx; + private String FileName = "YueSuoPing"; + + public SharedUtil(Context ctx) { + this.ctx = ctx; + } + + /** + * Set int value into SharePreference + * + * @param + * @param key + * @param value + */ + //通过SharedPreferences来存储键值对 + public void saveIntValue(String key, int value) { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharePre.edit(); + editor.putInt(key, value); + editor.commit(); + } + + /** + * Set int value into SharePreference + * + * @param key + * @param value + */ + //通过SharedPreferences来存储键值对 + public void saveLongValue(String key, long value) { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharePre.edit(); + editor.putLong(key, value); + editor.commit(); + } + + public void writeDownStartApplicationTime() { + SharedPreferences sp = ctx.getSharedPreferences(FileName, Context.MODE_PRIVATE); + long now = System.currentTimeMillis(); +// Calendar calendar = Calendar.getInstance(); + //Date now = calendar.getTime(); +// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd:hh-mm-ss"); + SharedPreferences.Editor editor = sp.edit(); + //editor.putString("启动时间", now.toString()); + editor.putLong("nowtimekey", now); + editor.commit(); + + } + + /** + * Set Boolean value into SharePreference + * + * @param + * @param key + * @param value + */ + public void saveBooleanValue(String key, boolean value) { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharePre.edit(); + editor.putBoolean(key, value); + editor.commit(); + } + + /** + * Remove key from SharePreference + * + * @param key + */ + public void removeSharePreferences(String key) { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharePre.edit(); + editor.remove(key); + editor.commit(); + } + + /** + * + * + * @param key + * @return + */ + public boolean contains(String key) { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + return sharePre.contains(key); + } + + /** + * Get all value + * + * @return + */ + @SuppressWarnings("unchecked") + public Map<String, Object> getAllMap() { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + return (Map<String, Object>) sharePre.getAll(); + } + + /** + * Get Integer Value + * + * @param key + * @return + */ + public Integer getIntValueByKey(String key) { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + return sharePre.getInt(key, -1); + } + + /** + * Get Integer Value + * + * @param fileName + * @param key + * @return + */ + public Long getLongValueByKey(String key) { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + return sharePre.getLong(key, -1); + } + + + /** + * Set String value into SharePreference + * + * @param key + * @param value + */ + public void saveStringValue(String key, String value) { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharePre.edit(); + editor.putString(key, value); + editor.commit(); + } + + /** + * Get String Value + * 通过输入的key来获得userid + * @param key + * @return + */ + public String getStringValueByKey(String key) { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + return sharePre.getString(key, null); + } + + public Boolean getBooleanValueByKey(String key) { + SharedPreferences sharePre = ctx.getSharedPreferences(FileName, + Context.MODE_PRIVATE); + return sharePre.getBoolean(key, false); + } + + /** + * Get Value, Remove key + * + * @param key + * @return + */ + public Integer getIntValueAndRemoveByKey(String key) { + Integer value = getIntValueByKey(key); + removeSharePreferences(key); + return value; + } + + /** + * 设置userkey + * + * @param userkey + */ + public void setUserkey(String userkey) { + this.saveStringValue("params_userkey", userkey); + } + + /** + * 获取userkey + * + */ + public String getUserkey() { + return this.getStringValueByKey("params_userkey"); + } + +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/util/Util.java b/IDCardLib/src/main/java/com/megvii/idcardlib/util/Util.java new file mode 100644 index 0000000..422bd65 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/util/Util.java @@ -0,0 +1,218 @@ +package com.megvii.idcardlib.util; + +import android.content.Context; +import android.graphics.Bitmap; +import android.hardware.Camera; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.telephony.TelephonyManager; +import android.util.Base64; +import android.view.Gravity; +import android.widget.Toast; + +import com.megvii.idcardlib.R; +import com.megvii.idcardquality.IDCardQualityResult; +import com.megvii.idcardquality.bean.IDCardAttr; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +/** + * Created by binghezhouke on 15-8-12. + */ +public class Util { + + public static Toast toast; + + /** + * 输出toast + */ + public static void showToast(Context context, String str) { + if (context != null) { + if (toast != null) { + toast.cancel(); + } + toast = Toast.makeText(context, str, Toast.LENGTH_SHORT); + // 可以控制toast显示的位�? + toast.setGravity(Gravity.TOP, 0, 30); + toast.show(); + } + } + + /** + * 取消弹出toast + */ + public static void cancleToast(Context context) { + if (context != null) { + if (toast != null) { + toast.cancel(); + } + } + } + + public static String getUUIDString(Context mContext) { + String KEY_UUID = "key_uuid"; + SharedUtil sharedUtil = new SharedUtil(mContext); + String uuid = sharedUtil.getStringValueByKey(KEY_UUID); + if (uuid != null && uuid.trim().length() != 0) + return uuid; + + uuid = UUID.randomUUID().toString(); + uuid = Base64.encodeToString(uuid.getBytes(), Base64.DEFAULT); + sharedUtil.saveStringValue(KEY_UUID, uuid); + return uuid; + } + + + public static String getPhoneNumber(Context mContext) { + TelephonyManager phoneMgr = (TelephonyManager) mContext + .getSystemService(Context.TELEPHONY_SERVICE); + return phoneMgr.getLine1Number(); + } + + public static String getDeviceID(Context mContext) { + TelephonyManager tm = (TelephonyManager) mContext + .getSystemService(Context.TELEPHONY_SERVICE); + return tm.getDeviceId(); + } + + public static String getMacAddress(Context mContext) { + WifiManager wifi = (WifiManager) mContext + .getSystemService(Context.WIFI_SERVICE); + WifiInfo info = wifi.getConnectionInfo(); + String address = info.getMacAddress(); + if(address != null && address.length() > 0){ + address = address.replace(":", ""); + } + return address; + } + + public static Camera.Size getNearestRatioSize(Camera.Parameters para, + final int screenWidth, final int screenHeight) { + List<Camera.Size> supportedSize = para.getSupportedPreviewSizes(); + for (Camera.Size tmp : supportedSize) { + if (tmp.width == 1280 && tmp.height == 720) { + return tmp; + } + } + Collections.sort(supportedSize, new Comparator<Camera.Size>() { + @Override + public int compare(Camera.Size lhs, Camera.Size rhs) { + int diff1 = (((int) ((1000 * (Math.abs(lhs.width + / (float) lhs.height - screenWidth + / (float) screenHeight))))) << 16) + - lhs.width; + int diff2 = (((int) (1000 * (Math.abs(rhs.width + / (float) rhs.height - screenWidth + / (float) screenHeight)))) << 16) + - rhs.width; + + return diff1 - diff2; + } + }); + + return supportedSize.get(0); + } + + + public static String getTimeStr() { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmss"); + return simpleDateFormat.format(new Date()); + } + + public static void closeStreamSilently(OutputStream os) { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + + } + } + } + + public static byte[] bmp2byteArr(Bitmap bmp) { + if (bmp == null || bmp.isRecycled()) + return null; + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + bmp.compress(Bitmap.CompressFormat.JPEG,90, byteArrayOutputStream); + Util.closeStreamSilently(byteArrayOutputStream); + return byteArrayOutputStream.toByteArray(); + } + + public static String errorType2HumanStr(IDCardQualityResult.IDCardFailedType type, IDCardAttr.IDCardSide side) { + String result = null; + switch (type) { + case QUALITY_FAILED_TYPE_NOIDCARD: + result = "请将身份证置于提示框内"; + break; + case QUALITY_FAILED_TYPE_BLUR: + result = "请点击屏幕对焦"; + break; + case QUALITY_FAILED_TYPE_BRIGHTNESSTOOHIGH: + result = "太亮"; + break; + case QUALITY_FAILED_TYPE_BRIGHTNESSTOOLOW: + result = "太暗"; + break; + case QUALITY_FAILED_TYPE_OUTSIDETHEROI: + result = "请将身份证与提示框对齐"; + break; + case QUALITY_FAILED_TYPE_SIZETOOLARGE: + result = "请将身份证与提示框对齐"; + break; + case QUALITY_FAILED_TYPE_SIZETOOSMALL: + result = "请将身份证与提示框对齐"; + break; + case QUALITY_FAILED_TYPE_SPECULARHIGHLIGHT: + result = "请调整拍摄位置,以去除光斑"; + break; + case QUALITY_FAILED_TYPE_TILT: + result = "请将身份证摆正"; + break; + case QUALITY_FAILED_TYPE_SHADOW: + result = "请调整拍摄位置,以去除阴影"; + break; + case QUALITY_FAILED_TYPE_WRONGSIDE: + if (side == IDCardAttr.IDCardSide.IDCARD_SIDE_BACK) + result = "请翻到国徽面"; + else { + result = "请翻到人像面"; + } + break; + } + return result; + } + + public static byte[] readModel(Context context) { + InputStream inputStream = null; + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int count = -1; + try { + inputStream = context.getResources().openRawResource(R.raw.idcardmodel); + while ((count = inputStream.read(buffer)) != -1) { + byteArrayOutputStream.write(buffer, 0, count); + } + byteArrayOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return byteArrayOutputStream.toByteArray(); + } +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/view/AutoRatioImageview.java b/IDCardLib/src/main/java/com/megvii/idcardlib/view/AutoRatioImageview.java new file mode 100644 index 0000000..b881d9d --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/view/AutoRatioImageview.java @@ -0,0 +1,62 @@ +package com.megvii.idcardlib.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ImageView; + +/** + * Created by binghezhouke on 14-1-2. + */ +public class AutoRatioImageview extends ImageView { + private float mRatio = -1; + private int mPrefer = 0; + + public AutoRatioImageview(Context context) { + super(context); + } + + public AutoRatioImageview(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public AutoRatioImageview(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + int viewWidth = MeasureSpec.getSize(widthMeasureSpec); + int viewHeight = MeasureSpec.getSize(heightMeasureSpec); + + if (mRatio < 0) { + //this case means the ration is auto ratio + if (getDrawable() == null) { + //no image settled, invoke super onMeasure + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } else { + + int drawableWidth = getDrawable().getIntrinsicWidth(); + int drawableHeight = getDrawable().getIntrinsicHeight(); + if (mPrefer == 0) { + // consider width + + setMeasuredDimension(viewWidth, + viewWidth * drawableHeight / drawableWidth); + } else { + setMeasuredDimension(viewHeight * drawableWidth / drawableHeight, viewHeight); + } + } + } else { + // this view is fixed ratio + if (mPrefer == 0) { + // consider view width + setMeasuredDimension(viewWidth, + (int) (viewWidth * mRatio)); + } else { + setMeasuredDimension((int) (viewHeight / mRatio), viewWidth); + } + } + + } +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/view/CircleProgressBar.java b/IDCardLib/src/main/java/com/megvii/idcardlib/view/CircleProgressBar.java new file mode 100755 index 0000000..bd95919 --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/view/CircleProgressBar.java @@ -0,0 +1,90 @@ + +package com.megvii.idcardlib.view; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.SweepGradient; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.view.View; + +/** + *画倒计时圆通过传递 Progress和max来画 + */ +public class CircleProgressBar extends View { + + private static final int STD_WIDTH = 20; + private static final int STD_RADIUS = 75; + + private final TextPaint textPaint; + SweepGradient sweepGradient = null; + private int progress = 100; + private int max = 100; + private Paint paint; + private RectF oval; + private int mWidth = STD_WIDTH; + private int mRadius = STD_RADIUS; + private Bitmap bit; + + public CircleProgressBar(Context context, AttributeSet attrs) { + super(context, attrs); + paint = new Paint(); + oval = new RectF(); + textPaint = new TextPaint(); + // bit = BitmapFactory.decodeResource(getResources(), R.drawable.mg_liveness_circle); + sweepGradient = new SweepGradient(getWidth() / 2, getHeight() / 2, new int[]{0xfffe9a8e, 0xff3fd1e4 + , 0xffdc968e}, null); + } + + public int getMax() { + return max; + } + + public void setMax(int max) { + this.max = max; + } + + public int getProgress() { + return progress; + } + + public void setProgress(int progress) { + this.progress = progress; + invalidate(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + int use = width > height ? height : width; + int sum = STD_WIDTH + STD_RADIUS; + try { + mWidth = (STD_WIDTH * use) / (2 * sum); + mRadius = (STD_RADIUS * use) / (2 * sum); + } catch (Exception e) { + mWidth = 1; + mRadius = 1; + } + setMeasuredDimension(use, use); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + paint.setAntiAlias(true); + paint.setFlags(Paint.ANTI_ALIAS_FLAG); + paint.setColor(0xff000000); + paint.setStrokeWidth(mWidth);// 设置画笔宽度 + paint.setStyle(Paint.Style.STROKE);// 设置中空的样式 + canvas.drawCircle(mWidth + mRadius, mWidth + mRadius, mRadius, paint);// 在中心为(100,100)的地方画个半径为55的圆,宽度为setStrokeWidth:10,也就是灰色的底边 + paint.setColor(0xff3fd1e4);// 设置画笔为绿色 + oval.set(mWidth, mWidth, mRadius * 2 + mWidth, (mRadius * 2 + mWidth));// 设置类似于左上角坐标(45,45),右下角坐标(155,155),这样也就保证了半径为55 + canvas.drawArc(oval, -90, ((float) progress / max) * 360, false, paint);// 画圆弧,第二个参数为:起始角度,第三个为跨的角度,第四个为true的时候是实心,false的时候为空心 + paint.reset(); + + } +} diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/view/IDCardIndicator.java b/IDCardLib/src/main/java/com/megvii/idcardlib/view/IDCardIndicator.java new file mode 100644 index 0000000..a87706f --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/view/IDCardIndicator.java @@ -0,0 +1,319 @@ +package com.megvii.idcardlib.view; + +//import com.megvii.idcard.sdk.IDCard.Card; +//import com.megvii.idcard.sdk.IDCard.Faculae; +//import com.megvii.idcard.sdk.IDCard.IDCardQuality; +//import com.megvii.idcard.sdk.IDCard.PointF; +//import com.megvii.idcard.sdk.IDCard.Shadow; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.View; + +import com.megvii.idcardlib.R; +import com.megvii.idcardquality.bean.IDCardAttr; + +/** + * Created by binghezhouke on 15-8-12. + */ +public class IDCardIndicator extends View { + private Rect mShowRect = null; + private Rect mDrawRect = null; + private Paint mDrawPaint = null; + private float IDCARD_RATIO = 856.0f / 540.0f; + private float CONTENT_RATIO = 1f; + private float SHOW_CONTENT_RATIO = CONTENT_RATIO * 13.0f / 16.0f; + private Rect mTmpRect = null; + private int backColor = 0x00000000; + + private void init() { + mShowRect = new Rect(); + mDrawRect = new Rect(); + mTmpRect = new Rect(); + mDrawPaint = new Paint(); + mDrawPaint.setDither(true); + mDrawPaint.setAntiAlias(true); + mDrawPaint.setStrokeWidth(10); + mDrawPaint.setStyle(Paint.Style.STROKE); + mDrawPaint.setColor(0xff0000ff); + } + + public void setBackColor(Activity activity, int backColor) { + if (this.backColor != backColor) { + this.backColor = backColor; + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + IDCardIndicator.this.invalidate(); + } + }); + } + } + + public IDCardIndicator(Context context) { + super(context); + init(); + } + + public IDCardIndicator(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public IDCardIndicator(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + int centerX = width >> 1; + int centerY = height >> 1; + int content_width = 0; + int content_height = 0; + if (width / (float) (height) < IDCARD_RATIO) // the view is to high + { + content_width = (int) (width * SHOW_CONTENT_RATIO); + content_height = (int) (content_width / IDCARD_RATIO); + } else { // the view is too wide + content_height = (int) (height * SHOW_CONTENT_RATIO); + content_width = (int) (content_height * IDCARD_RATIO); + } + + mShowRect.left = centerX - content_width / 2; + mShowRect.top = centerY - content_height / 2; + mShowRect.right = centerX + content_width / 2; + mShowRect.bottom = centerY + content_height / 2; + getActualRect(width, height); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + } + + private boolean mIsVertical; + private IDCardAttr.IDCardSide mIdCardSide; + + public void setCardSideAndOrientation(boolean mIsVertical, IDCardAttr.IDCardSide mIDCardSide) { + this.mIsVertical = mIsVertical; + this.mIdCardSide = mIDCardSide; + } + + + public void setContentRatio(boolean mIsVertical) { + this.mIsVertical = mIsVertical; + if (mIsVertical) + CONTENT_RATIO = 1.0f; + else + CONTENT_RATIO = 0.8f; + + SHOW_CONTENT_RATIO = CONTENT_RATIO * 13.0f / 16.0f; + invalidate(); + } + + /** + * 实际给算法的大小 + */ + private void getActualRect(int width, int height) { + + int content_width = 0; + int content_height = 0; + int centerX = width >> 1; + int centerY = height >> 1; + + if (width / (float) (height) < IDCARD_RATIO) // the view is to high + { + content_width = (int) (width * CONTENT_RATIO); + content_height = (int) (content_width / IDCARD_RATIO); + } else { // the view is too wide + content_height = (int) (height * CONTENT_RATIO); + content_width = (int) (content_height * IDCARD_RATIO); + } + + mDrawRect.left = centerX - content_width / 2; + mDrawRect.top = centerY - content_height / 2; + mDrawRect.right = centerX + content_width / 2; + mDrawRect.bottom = centerY + content_height / 2; + } + + @Override + protected void onDraw(Canvas canvas) { + // background + mDrawPaint.setStyle(Paint.Style.FILL); + mDrawPaint.setColor(backColor); + + // top + mTmpRect.set(0, 0, getWidth(), mShowRect.top); + canvas.drawRect(mTmpRect, mDrawPaint); + // bottom + mTmpRect.set(0, mShowRect.bottom, getWidth(), getHeight()); + canvas.drawRect(mTmpRect, mDrawPaint); + // left + mTmpRect.set(0, mShowRect.top, mShowRect.left, mShowRect.bottom); + canvas.drawRect(mTmpRect, mDrawPaint); + // right + mTmpRect.set(mShowRect.right, mShowRect.top, getWidth(), mShowRect.bottom); + canvas.drawRect(mTmpRect, mDrawPaint); + + drawViewfinder(canvas); + + drawFaculae(canvas); + super.onDraw(canvas); + } + +// public void setiCardQuality(IDCardQuality iCardQuality) { +// this.iCardQuality = iCardQuality; +// faculaeWidth = mDrawRect.width(); +// faculaeHeight = mDrawRect.height(); +// +// faculaePaint = new Paint(); +// faculaePaint.setStrokeWidth(5); +// +// this.postInvalidate(); +// +// } + + // private IDCardQuality iCardQuality; + private Paint faculaePaint; + private int faculaeWidth, faculaeHeight; + + private void drawFaculae(Canvas canvas) { +// if (faculaePaint == null || iCardQuality == null) { +// return; +// } +// Shadow[] Shadows = iCardQuality.Shadows; +// Faculae[] faculaes = iCardQuality.faculaes; +// Card[] cards = iCardQuality.cards; +// faculaePaint.setColor(0xffaa0000); +// int drawOffsetH = mDrawRect.top; +// int drawOffsetW = mDrawRect.left; +// if (mIsVertical) { +// drawOffsetH = mDrawRect.top; +// drawOffsetW = mDrawRect.left; +// } +// +// Log.w("ceshi", "drawOffset++++++====" + drawOffsetH + ", " + mIsVertical + ", " + mDrawRect); +// +// for (int i = 0; i < Shadows.length; i++) { +// PointF[] vertex = Shadows[i].vertex; +// for (int j = 0; j < vertex.length; j++) { +// float startx = vertex[j].x * faculaeWidth; +// float starty = vertex[j].y * faculaeHeight; +// float endx = vertex[(j + 1) % vertex.length].x * faculaeWidth; +// float endy = vertex[(j + 1) % vertex.length].y * faculaeHeight; +// canvas.drawLine(startx + drawOffsetW, starty + drawOffsetH, endx + drawOffsetW, endy + drawOffsetH, faculaePaint); +// } +// } +// faculaePaint.setColor(0xff00aa00); +// for (int i = 0; i < faculaes.length; i++) { +// PointF[] vertex = faculaes[i].vertex; +// for (int j = 0; j < vertex.length; j++) { +// float startx = vertex[j].x * faculaeWidth; +// float starty = vertex[j].y * faculaeHeight; +// float endx = vertex[(j + 1) % vertex.length].x * faculaeWidth; +// float endy = vertex[(j + 1) % vertex.length].y * faculaeHeight; +// canvas.drawLine(startx + drawOffsetW, starty + drawOffsetH, endx + drawOffsetW, endy + drawOffsetH, faculaePaint); +// } +// } +// +// faculaePaint.setColor(0xff0000aa); +// for (int i = 0; i < cards.length; i++) { +// PointF[] vertex = cards[i].vertex; +// for (int j = 0; j < vertex.length; j++) { +// float startx = vertex[j].x * faculaeWidth; +// float starty = vertex[j].y * faculaeHeight; +// float endx = vertex[(j + 1) % vertex.length].x * faculaeWidth; +// float endy = vertex[(j + 1) % vertex.length].y * faculaeHeight; +// canvas.drawLine(startx + drawOffsetW, starty + drawOffsetH, endx + drawOffsetW, endy + drawOffsetH, faculaePaint); +// } +// } + } + + private void drawViewfinder(Canvas canvas) { + int finderColor = 0XFF00D3FF; + mDrawPaint.setStyle(Paint.Style.STROKE); + mDrawPaint.setColor(finderColor); + mDrawPaint.setStrokeWidth(4); + int length = mShowRect.height() / 16; + // 四个蓝色的角 + // left top + canvas.drawLine(mShowRect.left, mShowRect.top, mShowRect.left + length, mShowRect.top, mDrawPaint); + canvas.drawLine(mShowRect.left, mShowRect.top, mShowRect.left, mShowRect.top + length, mDrawPaint); + + // right top + canvas.drawLine(mShowRect.right, mShowRect.top, mShowRect.right - length, mShowRect.top, mDrawPaint); + canvas.drawLine(mShowRect.right, mShowRect.top, mShowRect.right, mShowRect.top + length, mDrawPaint); + + // left bottom + canvas.drawLine(mShowRect.left, mShowRect.bottom, mShowRect.left + length, mShowRect.bottom, mDrawPaint); + canvas.drawLine(mShowRect.left, mShowRect.bottom, mShowRect.left, mShowRect.bottom - length, mDrawPaint); + + // right bottom + canvas.drawLine(mShowRect.right, mShowRect.bottom, mShowRect.right - length, mShowRect.bottom, mDrawPaint); + canvas.drawLine(mShowRect.right, mShowRect.bottom, mShowRect.right, mShowRect.bottom - length, mDrawPaint); + + // 两个角中间的线 + mDrawPaint.setColor(0XBBFFFFFF); + mDrawPaint.setStrokeWidth(2); + // top + canvas.drawLine(mShowRect.left + length, mShowRect.top, mShowRect.right - length, mShowRect.top, mDrawPaint); + // left + canvas.drawLine(mShowRect.left, mShowRect.top + length, mShowRect.left, mShowRect.bottom - length, mDrawPaint); + // right + canvas.drawLine(mShowRect.right, mShowRect.top + length, mShowRect.right, mShowRect.bottom - length, + mDrawPaint); + // bottom + canvas.drawLine(mShowRect.left + length, mShowRect.bottom, mShowRect.right - length, mShowRect.bottom, + mDrawPaint); + + int bitmapId = 0; + if (mIdCardSide == IDCardAttr.IDCardSide.IDCARD_SIDE_FRONT) + bitmapId = R.drawable.sfz_front; + else if (mIdCardSide == IDCardAttr.IDCardSide.IDCARD_SIDE_BACK) + bitmapId = R.drawable.sfz_back; + Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(), bitmapId); + Rect mSrcRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + Rect mDesRect = new Rect(mShowRect.left, mShowRect.top, mShowRect.left + mShowRect.width(), mShowRect.top + mShowRect.height()); + canvas.drawBitmap(bitmap, mSrcRect, mDesRect, null); + } + + public RectF getShowPosition() { + RectF rectF = new RectF(); + rectF.left = mShowRect.left / (float) getWidth(); + rectF.top = mShowRect.top / (float) getHeight(); + rectF.right = mShowRect.right / (float) getWidth(); + rectF.bottom = mShowRect.bottom / (float) getHeight(); + return rectF; + } + + public RectF getPosition() { + RectF rectF = new RectF(); + rectF.left = mDrawRect.left / (float) getWidth(); + rectF.top = mDrawRect.top / (float) getHeight(); + rectF.right = mDrawRect.right / (float) getWidth(); + rectF.bottom = mDrawRect.bottom / (float) getHeight(); + return rectF; + } + + public Rect getMargin() { + Rect rect = new Rect(); + rect.left = mDrawRect.left; + rect.top = mDrawRect.top; + rect.right = getWidth() - mDrawRect.right; + rect.bottom = getHeight() - mDrawRect.bottom; + return rect; + } +} + diff --git a/IDCardLib/src/main/java/com/megvii/idcardlib/view/IDCardNewIndicator.java b/IDCardLib/src/main/java/com/megvii/idcardlib/view/IDCardNewIndicator.java new file mode 100644 index 0000000..58b612d --- /dev/null +++ b/IDCardLib/src/main/java/com/megvii/idcardlib/view/IDCardNewIndicator.java @@ -0,0 +1,224 @@ +package com.megvii.idcardlib.view; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.View; + +import com.megvii.idcardlib.R; +import com.megvii.idcardquality.bean.IDCardAttr; + +/** + * Created by binghezhouke on 15-8-12. + */ +public class IDCardNewIndicator extends View { + private Rect mShowDrawRect = null; + private Rect mDrawRect = null; + private Paint mDrawPaint = null; + private Paint mDrawRightPaint = null; + private float IDCARD_RATIO = 856.0f / 540.0f; + private float CONTENT_RATIO = 0.8f; + private float SHOW_CONTENT_RATIO = CONTENT_RATIO * 13.0f / 16.0f; + + private float RIGHT_RATIO = 0.2f; + private RectF rightRectf = null; + private Rect mTmpRect = null; + private Rect mTmpRect_test = null; + private Bitmap rightBitmap; + private String rightText; + private int right_width = 0; + private int right_height = 0; + private int backColor = 0x00000000; + + private void init() { + rightRectf = new RectF(); + mShowDrawRect = new Rect(); + mDrawRect = new Rect(); + mTmpRect = new Rect(); + mTmpRect_test = new Rect(); + mDrawRightPaint = new Paint(); + mDrawRightPaint.setColor(0XFFFFFFFF); + mDrawPaint = new Paint(); + mDrawPaint.setDither(true); + mDrawPaint.setAntiAlias(true); + mDrawPaint.setStrokeWidth(10); + mDrawPaint.setStyle(Paint.Style.STROKE); + mDrawPaint.setColor(0xff0000ff); + } + + public void setBackColor(Activity activity, int backColor) { + if (this.backColor != backColor) { + this.backColor = backColor; + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + IDCardNewIndicator.this.invalidate(); + } + }); + } + } + + public void setRightImage(boolean isFront) { + if (isFront) { + rightText = "请将身份证正"; + rightBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sfz_front); + } else { + rightText = "请将身份证背"; + rightBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sfz_back); + } + } + + public IDCardNewIndicator(Context context) { + super(context); + init(); + } + + public IDCardNewIndicator(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public IDCardNewIndicator(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + // 只考虑横屏 + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + + right_width = (int) (width * RIGHT_RATIO); + right_height = (int) (right_width / IDCARD_RATIO); + + // 实际身份证位置的中心点 + int centerY = height >> 1; + int centerX = width >> 1; + + int content_width = (int) ((width - right_width) * CONTENT_RATIO); + int content_height = (int) (content_width / IDCARD_RATIO); + + mDrawRect.left = centerX - content_width / 2; + mDrawRect.top = centerY - content_height / 2; + mDrawRect.right = content_width + mDrawRect.left; + mDrawRect.bottom = content_height + mDrawRect.top; + + int content_show_width = (int) ((width - right_width) * SHOW_CONTENT_RATIO); + int content_show_height = (int) (content_show_width / IDCARD_RATIO); + + mShowDrawRect.left = (int)(centerX - content_show_width / 2.0f); + mShowDrawRect.top = centerY - content_show_height / 2; + mShowDrawRect.right = content_show_width + mShowDrawRect.left; + mShowDrawRect.bottom = content_show_height + mShowDrawRect.top; + + rightRectf.top = mShowDrawRect.top; + rightRectf.left = mDrawRect.right; + rightRectf.right = width - 20; + rightRectf.bottom = rightRectf.width() / IDCARD_RATIO + rightRectf.top; + } + + @Override + protected void onDraw(Canvas canvas) { + // background + mDrawPaint.setStyle(Paint.Style.FILL); + mDrawPaint.setColor(backColor); + + drawViewfinder(canvas); + //onDrawRight(canvas); + } + + private boolean mIsVertical; + private IDCardAttr.IDCardSide mIdCardSide; + + public void setCardSideAndOrientation(boolean mIsVertical, IDCardAttr.IDCardSide mIDCardSide) { + this.mIsVertical = mIsVertical; + this.mIdCardSide = mIDCardSide; + } + + private void drawViewfinder(Canvas canvas) { + // top + mTmpRect.set(0, 0, getWidth(), mShowDrawRect.top); + canvas.drawRect(mTmpRect, mDrawPaint); + // bottom + mTmpRect.set(0, mShowDrawRect.bottom, getWidth(), getHeight()); + canvas.drawRect(mTmpRect, mDrawPaint); + // left + mTmpRect.set(0, mShowDrawRect.top, mShowDrawRect.left, mShowDrawRect.bottom); + canvas.drawRect(mTmpRect, mDrawPaint); + // right + mTmpRect.set(mShowDrawRect.right, mShowDrawRect.top, getWidth(), mShowDrawRect.bottom); + canvas.drawRect(mTmpRect, mDrawPaint); + + // rect + mDrawPaint.setStyle(Paint.Style.STROKE); + mDrawPaint.setColor(0xff5fc0d2); + mDrawPaint.setStrokeWidth(5); + int length = mShowDrawRect.height() / 16; + // left top + canvas.drawLine(mShowDrawRect.left, mShowDrawRect.top, mShowDrawRect.left + length, mShowDrawRect.top, + mDrawPaint); + canvas.drawLine(mShowDrawRect.left, mShowDrawRect.top, mShowDrawRect.left, mShowDrawRect.top + length, + mDrawPaint); + + // right top + canvas.drawLine(mShowDrawRect.right, mShowDrawRect.top, mShowDrawRect.right - length, mShowDrawRect.top, + mDrawPaint); + canvas.drawLine(mShowDrawRect.right, mShowDrawRect.top, mShowDrawRect.right, mShowDrawRect.top + length, + mDrawPaint); + + // left bottom + canvas.drawLine(mShowDrawRect.left, mShowDrawRect.bottom, mShowDrawRect.left + length, mShowDrawRect.bottom, + mDrawPaint); + canvas.drawLine(mShowDrawRect.left, mShowDrawRect.bottom, mShowDrawRect.left, mShowDrawRect.bottom - length, + mDrawPaint); + + // right bottom + canvas.drawLine(mShowDrawRect.right, mShowDrawRect.bottom, mShowDrawRect.right - length, mShowDrawRect.bottom, + mDrawPaint); + canvas.drawLine(mShowDrawRect.right, mShowDrawRect.bottom, mShowDrawRect.right, mShowDrawRect.bottom - length, + mDrawPaint); + + int bitmapId = 0; + if (mIdCardSide == IDCardAttr.IDCardSide.IDCARD_SIDE_FRONT) + bitmapId = R.drawable.sfz_front; + else if (mIdCardSide == IDCardAttr.IDCardSide.IDCARD_SIDE_BACK) + bitmapId = R.drawable.sfz_back; + Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(), bitmapId); + Rect mSrcRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + Rect mDesRect = new Rect(mShowDrawRect.left, mShowDrawRect.top, mShowDrawRect.left + mShowDrawRect.width(), mShowDrawRect.top + mShowDrawRect.height()); + canvas.drawBitmap(bitmap, mSrcRect, mDesRect, null); + } + + private void onDrawRight(Canvas canvas) { + canvas.drawBitmap(rightBitmap, null, rightRectf, null); + int textSize = right_width / 6; + mDrawRightPaint.setTextSize(textSize * 4 / 5); + canvas.drawText(rightText + "面", rightRectf.left, rightRectf.bottom + textSize, mDrawRightPaint); + canvas.drawText("置于框内", rightRectf.left, rightRectf.bottom + textSize * 2, mDrawRightPaint); + } + + public RectF getPosition() { + RectF rectF = new RectF(); + rectF.left = mDrawRect.left / (float) getWidth(); + rectF.top = mDrawRect.top / (float) getHeight(); + rectF.right = mDrawRect.right / (float) getWidth(); + rectF.bottom = mDrawRect.bottom / (float) getHeight(); + return rectF; + } + public Rect getMargin() { + Rect rect = new Rect(); + rect.left = mDrawRect.left; + rect.top = mDrawRect.top; + rect.right = getWidth() - mDrawRect.right; + rect.bottom = getHeight() - mDrawRect.bottom; + return rect; + } +} diff --git a/IDCardLib/src/main/res/anim/liveness_leftout.xml b/IDCardLib/src/main/res/anim/liveness_leftout.xml new file mode 100644 index 0000000..47b7952 --- /dev/null +++ b/IDCardLib/src/main/res/anim/liveness_leftout.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<translate xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/linear_interpolator" + android:duration="200" + android:fillAfter="true" + android:fromXDelta="0" + android:toXDelta="-100%" + > + +</translate> diff --git a/IDCardLib/src/main/res/anim/liveness_rightin.xml b/IDCardLib/src/main/res/anim/liveness_rightin.xml new file mode 100644 index 0000000..99fb1b4 --- /dev/null +++ b/IDCardLib/src/main/res/anim/liveness_rightin.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<translate xmlns:android="http://schemas.android.com/apk/res/android" + android:duration="200" + android:interpolator="@android:anim/linear_interpolator" + android:fromXDelta="100%" + android:toXDelta="0%" + android:fillAfter="true" + > + +</translate> diff --git a/IDCardLib/src/main/res/drawable-xhdpi/bg_nothing.png b/IDCardLib/src/main/res/drawable-xhdpi/bg_nothing.png new file mode 100644 index 0000000..f3fb412 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/bg_nothing.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/circle.png b/IDCardLib/src/main/res/drawable-xhdpi/circle.png new file mode 100644 index 0000000..61b5c32 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/circle.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/ic_launcher.png b/IDCardLib/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..f4fd5f5 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_eye.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_eye.png new file mode 100644 index 0000000..d7a55b2 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_eye.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_faceppinside.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_faceppinside.png new file mode 100644 index 0000000..f480d80 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_faceppinside.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_head.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_head.png new file mode 100644 index 0000000..727f514 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_head.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_down.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_down.png new file mode 100644 index 0000000..084cd0f Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_down.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_left.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_left.png new file mode 100644 index 0000000..2482d99 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_left.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_right.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_right.png new file mode 100644 index 0000000..faedef4 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_right.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_up.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_up.png new file mode 100644 index 0000000..13fcd70 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_head_up.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_bottom_tips.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_bottom_tips.png new file mode 100644 index 0000000..a6677cf Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_bottom_tips.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_camera_mask.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_camera_mask.png new file mode 100644 index 0000000..9d0c220 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_camera_mask.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_head_mask.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_head_mask.png new file mode 100644 index 0000000..12592e4 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_layout_head_mask.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_left.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_left.png new file mode 100644 index 0000000..24d97c1 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_left.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_mouth.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_mouth.png new file mode 100644 index 0000000..64ee0be Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_mouth.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_right.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_right.png new file mode 100644 index 0000000..9948e88 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_right.png differ diff --git a/IDCardLib/src/main/res/drawable-xhdpi/liveness_surfacemask.9.png b/IDCardLib/src/main/res/drawable-xhdpi/liveness_surfacemask.9.png new file mode 100644 index 0000000..945c201 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xhdpi/liveness_surfacemask.9.png differ diff --git a/IDCardLib/src/main/res/drawable-xxhdpi/ic_launcher.png b/IDCardLib/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..c645f8d Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/IDCardLib/src/main/res/drawable-xxhdpi/liveness_phoneimage.png b/IDCardLib/src/main/res/drawable-xxhdpi/liveness_phoneimage.png new file mode 100644 index 0000000..f17ea62 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xxhdpi/liveness_phoneimage.png differ diff --git a/IDCardLib/src/main/res/drawable-xxhdpi/loading_background.jpg b/IDCardLib/src/main/res/drawable-xxhdpi/loading_background.jpg new file mode 100644 index 0000000..e22d01a Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xxhdpi/loading_background.jpg differ diff --git a/IDCardLib/src/main/res/drawable-xxhdpi/sfz_back.png b/IDCardLib/src/main/res/drawable-xxhdpi/sfz_back.png new file mode 100644 index 0000000..c124654 Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xxhdpi/sfz_back.png differ diff --git a/IDCardLib/src/main/res/drawable-xxhdpi/sfz_front.png b/IDCardLib/src/main/res/drawable-xxhdpi/sfz_front.png new file mode 100644 index 0000000..df0c79b Binary files /dev/null and b/IDCardLib/src/main/res/drawable-xxhdpi/sfz_front.png differ diff --git a/IDCardLib/src/main/res/drawable/liveness_eye_open_closed.xml b/IDCardLib/src/main/res/drawable/liveness_eye_open_closed.xml new file mode 100644 index 0000000..5df367d --- /dev/null +++ b/IDCardLib/src/main/res/drawable/liveness_eye_open_closed.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<animation-list xmlns:android="http://schemas.android.com/apk/res/android"> +<item android:drawable="@drawable/liveness_head" android:duration="500"/> +<item android:drawable="@drawable/liveness_eye" android:duration="500"/> +</animation-list> diff --git a/IDCardLib/src/main/res/drawable/liveness_head_pitch.xml b/IDCardLib/src/main/res/drawable/liveness_head_pitch.xml new file mode 100644 index 0000000..77bc24a --- /dev/null +++ b/IDCardLib/src/main/res/drawable/liveness_head_pitch.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<animation-list xmlns:android="http://schemas.android.com/apk/res/android"> +<item android:drawable="@drawable/liveness_head" android:duration="500"/> +<item android:drawable="@drawable/liveness_head_up" android:duration="500"/> +<item android:drawable="@drawable/liveness_head" android:duration="500"/> +<item android:drawable="@drawable/liveness_head_down" android:duration="500"/> +</animation-list> diff --git a/IDCardLib/src/main/res/drawable/liveness_head_yaw.xml b/IDCardLib/src/main/res/drawable/liveness_head_yaw.xml new file mode 100644 index 0000000..e959201 --- /dev/null +++ b/IDCardLib/src/main/res/drawable/liveness_head_yaw.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<animation-list xmlns:android="http://schemas.android.com/apk/res/android"> +<item android:drawable="@drawable/liveness_head" android:duration="500"/> +<item android:drawable="@drawable/liveness_right" android:duration="500"/> +<item android:drawable="@drawable/liveness_head" android:duration="500"/> +<item android:drawable="@drawable/liveness_left" android:duration="500"/> +</animation-list> diff --git a/IDCardLib/src/main/res/drawable/liveness_mouth_open_closed.xml b/IDCardLib/src/main/res/drawable/liveness_mouth_open_closed.xml new file mode 100644 index 0000000..4217a07 --- /dev/null +++ b/IDCardLib/src/main/res/drawable/liveness_mouth_open_closed.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<animation-list xmlns:android="http://schemas.android.com/apk/res/android"> +<item android:drawable="@drawable/liveness_head" android:duration="500"/> +<item android:drawable="@drawable/liveness_mouth" android:duration="500"/> +</animation-list> diff --git a/IDCardLib/src/main/res/drawable/rectangle.xml b/IDCardLib/src/main/res/drawable/rectangle.xml new file mode 100644 index 0000000..ff763ab --- /dev/null +++ b/IDCardLib/src/main/res/drawable/rectangle.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/listview_background_shape"> + <stroke android:width="2dp" android:color="#FF00FF00" /> + <padding android:left="2dp" + android:top="2dp" + android:right="2dp" + android:bottom="2dp" /> +</shape> \ No newline at end of file diff --git a/IDCardLib/src/main/res/layout/bottom_title_layout.xml b/IDCardLib/src/main/res/layout/bottom_title_layout.xml new file mode 100644 index 0000000..8a5f07e --- /dev/null +++ b/IDCardLib/src/main/res/layout/bottom_title_layout.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/activity_loading_rootRel" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:orientation="horizontal" > + + <View + android:layout_width="0dip" + android:layout_height="1dip" + android:layout_weight="1" + android:layout_marginLeft="15dip" + android:background="#D6D4D2" /> + + <TextView + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:layout_weight="2.5" + android:gravity="center" + android:text="Powered by FaceID" + android:textColor="#D6D4D2" + android:textSize="16sp" /> + + <View + android:layout_width="0dip" + android:layout_height="1dip" + android:layout_weight="1" + android:layout_marginRight="15dip" + android:background="#D6D4D2" /> + +</LinearLayout> \ No newline at end of file diff --git a/IDCardLib/src/main/res/layout/idcardscan_layout.xml b/IDCardLib/src/main/res/layout/idcardscan_layout.xml new file mode 100644 index 0000000..5a6f1fe --- /dev/null +++ b/IDCardLib/src/main/res/layout/idcardscan_layout.xml @@ -0,0 +1,116 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:id="@+id/idcardscan_layout"> + + <TextureView + android:id="@+id/idcardscan_layout_surface" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + <com.megvii.idcardlib.view.IDCardNewIndicator + android:id="@+id/idcardscan_layout_newIndicator" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:clickable="false" + android:focusable="false" /> + + <com.megvii.idcardlib.view.IDCardIndicator + android:id="@+id/idcardscan_layout_indicator" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:clickable="false" + android:focusable="false" /> + + <LinearLayout + android:id="@+id/idcardscan_layout_idCardImageRel" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:gravity="center" + android:visibility="gone" + android:layout_marginBottom="30dip" + android:layout_alignParentBottom="true" + > + <com.megvii.idcardlib.view.AutoRatioImageview + android:id="@+id/idcardscan_layout_idCardImage" + android:layout_width="140dip" + android:layout_height="wrap_content" + android:scaleType="centerCrop" + android:src="@drawable/sfz_front" + /> + <TextView + android:id="@+id/idcardscan_layout_idCardText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="#ffffffff" + android:textSize="12sp" + android:text="请将身份证正面置于框内" + /> + </LinearLayout> + + <TextView + android:id="@+id/idcardscan_layout_fps" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="#00ff00" + android:visibility="gone" /> + + <TextView + android:id="@+id/idcardscan_layout_error_type" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:background="#7f000000" + android:textColor="#ffffffff" + android:visibility="gone" /> + + <com.megvii.idcardlib.util.MyTextView + android:id="@+id/idcardscan_layout_topTitle" + android:layout_width="wrap_content" + android:layout_height="300dp" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" + android:background="#7f000000" + android:textColor="#ffffffff" + android:visibility="gone" /> + + <TextView + android:id="@+id/idcardscan_layout_horizontalTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_marginTop="32dip" + android:textColor="#ffffffff" + android:textSize="18sp" /> + <TextView + android:id="@+id/idcardscan_layout_verticalTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_marginTop="105dip" + android:textColor="#ffffffff" + android:textSize="18sp" /> + + <View + android:id="@+id/debugRectangle" + android:layout_height="match_parent" + android:layout_width="match_parent" + android:background="@drawable/rectangle" + android:visibility="gone"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:gravity="right" + android:layout_marginBottom="50dp"> + <TextView + android:layout_width="120dp" + android:layout_height="match_parent" + android:id="@+id/text_debug_info" + android:textColor="#FFFFFFFF" + android:gravity="left"/> + </LinearLayout> +</RelativeLayout> \ No newline at end of file diff --git a/IDCardLib/src/main/res/layout/liveness_detection_step.xml b/IDCardLib/src/main/res/layout/liveness_detection_step.xml new file mode 100644 index 0000000..93369f7 --- /dev/null +++ b/IDCardLib/src/main/res/layout/liveness_detection_step.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/main_pos_layout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="#00000000" + > + + <LinearLayout + android:id="@+id/detection_step_linear" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:gravity="center_horizontal" + android:orientation="vertical" > + + <TextView + android:id="@+id/detection_step_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:text="眨眼" + android:textColor="#00ACDF" + android:textSize="20sp" + android:visibility="visible" /> + + <ImageView + android:id="@+id/detection_step_image" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="10dip" + android:layout_marginTop="15dip" + android:src="@drawable/liveness_head" /> + </LinearLayout> + +</RelativeLayout> \ No newline at end of file diff --git a/IDCardLib/src/main/res/layout/liveness_layout.xml b/IDCardLib/src/main/res/layout/liveness_layout.xml new file mode 100644 index 0000000..4bbf7ab --- /dev/null +++ b/IDCardLib/src/main/res/layout/liveness_layout.xml @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/liveness_layout_rootRel" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <TextureView + android:id="@+id/liveness_layout_textureview" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + <com.megvii.idcardlib.view.AutoRatioImageview + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:src="@drawable/liveness_layout_camera_mask" /> + + <com.megvii.idcardlib.FaceMask + android:id="@+id/liveness_layout_facemask" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> + + <com.megvii.idcardlib.view.AutoRatioImageview + android:id="@+id/liveness_layout_head_mask" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:src="@drawable/liveness_layout_head_mask" /> + + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_below="@id/liveness_layout_head_mask" + android:background="#F6F5F4" > + + <include + android:id="@+id/activity_main_bottomTitle" + android:layout_width="match_parent" + android:layout_height="40dip" + android:layout_alignParentBottom="true" + layout="@layout/bottom_title_layout" /> + + <include + android:id="@+id/liveness_layout_first_layout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_above="@+id/activity_main_bottomTitle" + android:layout_marginBottom="15dip" + android:layout_marginTop="15dip" + layout="@layout/liveness_detection_step" + android:visibility="invisible" /> + + <include + android:id="@+id/liveness_layout_second_layout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_above="@+id/activity_main_bottomTitle" + android:layout_marginBottom="15dip" + android:layout_marginTop="15dip" + layout="@layout/liveness_detection_step" + android:visibility="gone" /> + + <LinearLayout + android:id="@+id/liveness_layout_bottom_tips_head" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_above="@+id/activity_main_bottomTitle" + android:layout_centerHorizontal="true" + android:gravity="center" + android:orientation="vertical" + android:visibility="visible" > + + <TextView + android:id="@+id/liveness_layout_promptText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="5dip" + android:text="@string/meglive_prompt" + android:textColor="#00ACDF" + android:textSize="16dp" /> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dip" + android:src="@drawable/liveness_phoneimage" /> + </LinearLayout> + + <RelativeLayout + android:id="@+id/detection_step_timeoutRel" + android:layout_width="35dip" + android:layout_height="35dip" + android:layout_alignParentRight="true" + android:layout_margin="5dip" + android:visibility="invisible" > + + <TextView + android:id="@+id/detection_step_timeout_garden" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:text="10" + android:textColor="#00BEE2" + android:textSize="20sp" /> + + <com.megvii.idcardlib.view.CircleProgressBar + android:id="@+id/detection_step_timeout_progressBar" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_centerInParent="true" /> + </RelativeLayout> + </RelativeLayout> + + <ImageView + android:layout_width="70dp" + android:layout_height="70dp" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_marginRight="20dp" + android:scaleType="centerInside" + android:src="@drawable/liveness_faceppinside" /> + + <ProgressBar + android:id="@+id/liveness_layout_progressbar" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:visibility="invisible" /> + +</RelativeLayout> \ No newline at end of file diff --git a/IDCardLib/src/main/res/raw/idcardmodel b/IDCardLib/src/main/res/raw/idcardmodel new file mode 100644 index 0000000..529052f Binary files /dev/null and b/IDCardLib/src/main/res/raw/idcardmodel differ diff --git a/IDCardLib/src/main/res/raw/livenessmodel b/IDCardLib/src/main/res/raw/livenessmodel new file mode 100755 index 0000000..26e1592 Binary files /dev/null and b/IDCardLib/src/main/res/raw/livenessmodel differ diff --git a/IDCardLib/src/main/res/raw/meglive_eye_blink.mp3 b/IDCardLib/src/main/res/raw/meglive_eye_blink.mp3 new file mode 100644 index 0000000..d90583c Binary files /dev/null and b/IDCardLib/src/main/res/raw/meglive_eye_blink.mp3 differ diff --git a/IDCardLib/src/main/res/raw/meglive_failed.mp3 b/IDCardLib/src/main/res/raw/meglive_failed.mp3 new file mode 100644 index 0000000..76f0238 Binary files /dev/null and b/IDCardLib/src/main/res/raw/meglive_failed.mp3 differ diff --git a/IDCardLib/src/main/res/raw/meglive_mouth_open.mp3 b/IDCardLib/src/main/res/raw/meglive_mouth_open.mp3 new file mode 100644 index 0000000..f90f414 Binary files /dev/null and b/IDCardLib/src/main/res/raw/meglive_mouth_open.mp3 differ diff --git a/IDCardLib/src/main/res/raw/meglive_pitch_down.mp3 b/IDCardLib/src/main/res/raw/meglive_pitch_down.mp3 new file mode 100644 index 0000000..2ec8b99 Binary files /dev/null and b/IDCardLib/src/main/res/raw/meglive_pitch_down.mp3 differ diff --git a/IDCardLib/src/main/res/raw/meglive_success.mp3 b/IDCardLib/src/main/res/raw/meglive_success.mp3 new file mode 100644 index 0000000..49a85f1 Binary files /dev/null and b/IDCardLib/src/main/res/raw/meglive_success.mp3 differ diff --git a/IDCardLib/src/main/res/raw/meglive_well_done.mp3 b/IDCardLib/src/main/res/raw/meglive_well_done.mp3 new file mode 100644 index 0000000..eda5204 Binary files /dev/null and b/IDCardLib/src/main/res/raw/meglive_well_done.mp3 differ diff --git a/IDCardLib/src/main/res/raw/meglive_yaw.mp3 b/IDCardLib/src/main/res/raw/meglive_yaw.mp3 new file mode 100644 index 0000000..f601e43 Binary files /dev/null and b/IDCardLib/src/main/res/raw/meglive_yaw.mp3 differ diff --git a/IDCardLib/src/main/res/raw/model b/IDCardLib/src/main/res/raw/model new file mode 100644 index 0000000..26e1592 Binary files /dev/null and b/IDCardLib/src/main/res/raw/model differ diff --git a/IDCardLib/src/main/res/values/color.xml b/IDCardLib/src/main/res/values/color.xml new file mode 100644 index 0000000..d155eac --- /dev/null +++ b/IDCardLib/src/main/res/values/color.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <drawable name="red">#ffff0000</drawable> +</resources> diff --git a/IDCardLib/src/main/res/values/dimens.xml b/IDCardLib/src/main/res/values/dimens.xml new file mode 100644 index 0000000..2a289cb --- /dev/null +++ b/IDCardLib/src/main/res/values/dimens.xml @@ -0,0 +1,9 @@ +<resources> + + <!-- Default screen margins, per the Android Design guidelines. --> + <dimen name="title_hight">50dip</dimen> + <dimen name="activity_horizontal_margin">16dp</dimen> + <dimen name="activity_vertical_margin">16dp</dimen> + + +</resources> diff --git a/IDCardLib/src/main/res/values/strings.xml b/IDCardLib/src/main/res/values/strings.xml new file mode 100644 index 0000000..41a95dd --- /dev/null +++ b/IDCardLib/src/main/res/values/strings.xml @@ -0,0 +1,59 @@ +<resources> + <string name="app_name">IDCardLib</string> + <string name="meglive_prompt">请在光线充足的情况下进行检测</string> + <string name="meglive_detect_initfailed">检测器初始化失败</string> + <string name="meglive_camera_initfailed">打开前置摄像头失败</string> + <string name="meglive_getpermission_motion">请打开手机读取运动数据权限</string> + <string name="meglive_phone_vertical">请竖直握紧手机</string> + <string name="meglive_keep_eyes_open">请勿用手遮挡眼睛</string> + <string name="meglive_keep_mouth_open">请勿用手遮挡嘴巴</string> + <string name="face_not_found">请让我看到您的正脸</string> + <string name="face_too_dark">请让光线再亮点</string> + <string name="face_too_bright">请让光线再暗点</string> + <string name="face_too_small">请再靠近一些</string> + <string name="face_too_large">请再离远一些</string> + <string name="face_too_blurry">请避免侧光和背光</string> + <string name="face_out_of_rect">请保持脸在人脸框中</string> + <string name="meglive_pitch">缓慢点头</string> + <string name="meglive_yaw">左右摇头</string> + <string name="meglive_mouth_open_closed">张嘴</string> + <string name="meglive_eye_open_closed">眨眼</string> + <string name="meglive_pos_yaw_left">左转</string> + <string name="meglive_pos_yaw_right">右转</string> + <string name="tipsmouth">Open your mouth and close.</string> + <string name="tipblink">Do blink with your eyes.</string> + <string name="tippose">Rotate your pose vertically.</string> + <string name="facelost">Face Lost</string> + <string name="timeout">超时</string> + <string name="authok">Success</string> + <string name="aufail">Failed</string> + <string name="steps">活体检测:</string> + <string name="pos_detection">POS</string> + <string name="mouth_detection">MOUTH</string> + <string name="blink_detection">BLINK</string> + + <array name="detect_type"> + <item>眨眼</item> + <item>张嘴</item> + <item>摇头</item> + </array> + <array name="detect_result"> + <item></item> + <item>LIVEPASS</item> + <item>人脸追踪失败</item> + <item>超时失败</item> + <item>LIVENOTPASS</item> + </array> + + <string name="loading_text">使用说明:\n1、首先您需要输入姓名;\n2、之后您需要按照屏幕上的提示完成3个动作,以通过活体检测,同时软件会将您的人脸图像发送至服务器进行人脸验证;\n3、如果您没有通过活体检测或者人脸验证,则登录失败,反之则登录成功。</string> + <string name="loading_confirm">OK,I Know</string> + <string name="netowrk_parse_failed">解析服务器数据失败</string> + <string name="network_error">网络请求失败</string> + <string name="verify_error">验证失败</string> + <string name="verify_success">验证成功</string> + <string name="liveness_detection_failed">活体检测失败</string> + <string name="liveness_detection_failed_timeout">活体检测超时失败</string> + <string name="liveness_detection_failed_action_blend">活体检测动作错误</string> + <string name="liveness_detection_failed_not_video">活体检测连续性检测失败</string> + <string name="novalidframe">没有合适的图像用于人脸识别</string> +</resources> diff --git a/IDCardLib/src/main/res/values/styles.xml b/IDCardLib/src/main/res/values/styles.xml new file mode 100644 index 0000000..c005544 --- /dev/null +++ b/IDCardLib/src/main/res/values/styles.xml @@ -0,0 +1,27 @@ +<resources> + + <!-- + Base application theme, dependent on API level. This theme is replaced + by AppBaseTheme from res/values-vXX/styles.xml on newer devices. + --> + <style name="AppBaseTheme" parent="android:Theme.Holo.Light.NoActionBar.Fullscreen"> + <!-- + Theme customizations available in newer API levels can go in + res/values-vXX/styles.xml, while customizations related to + backward-compatibility can go here. + --> + </style> + + <!-- Application theme. --> + <style name="AppTheme" parent="AppBaseTheme"> + <!-- All customizations that are NOT specific to a particular API-level can go here. --> + </style> + <!-- style for auto ratio ImageView --> + <declare-styleable name="AutoRatioImageView"> + + <!-- -ratio 高/宽 --> + <attr name="ratio" format="float" /> + <attr name="prefer" format="integer" /> + </declare-styleable> + +</resources> \ No newline at end of file diff --git a/IDCardLib/src/test/java/com/megvii/idcardlib/ExampleUnitTest.java b/IDCardLib/src/test/java/com/megvii/idcardlib/ExampleUnitTest.java new file mode 100644 index 0000000..06ac6ce --- /dev/null +++ b/IDCardLib/src/test/java/com/megvii/idcardlib/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.megvii.idcardlib; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dayu/bigfish/ui/MainActivity.java b/app/src/main/java/com/dayu/bigfish/ui/MainActivity.java index 7ef4351..872902c 100644 --- a/app/src/main/java/com/dayu/bigfish/ui/MainActivity.java +++ b/app/src/main/java/com/dayu/bigfish/ui/MainActivity.java @@ -31,11 +31,11 @@ import com.dayu.common.Constants; import com.dayu.event.DownloadBean; import com.dayu.location.base.LocationUtils; import com.dayu.message.ui.fragment.HomeMessageFragment; -import com.dayu.order.ui.activity.ReceivingActivity; import com.dayu.order.ui.fragment.HomeOrderFragment; import com.dayu.provider.event.RefreshReceivingNum; import com.dayu.provider.event.SwtichFragment; import com.dayu.provider.router.RouterPath; +import com.dayu.usercenter.ui.activity.IdentityCertificationActivity; import com.dayu.usercenter.ui.fragment.HomePersonFragment; import com.dayu.utils.badgeNumberManger.BadgeNumberManager; import com.dayu.widgets.CustomDialog; @@ -259,7 +259,7 @@ public class MainActivity extends BaseActivity<MainPresenter, ActivityMainBindin @Override public void dumpReceActivity() { - Intent intent = new Intent(mActivity, ReceivingActivity.class); + Intent intent = new Intent(mActivity, IdentityCertificationActivity.class); startActivity(intent); overridePendingTransition(R.anim.slide_bottom_in, 0); } diff --git a/baseSDK/src/main/java/com/dayu/base/api/APIService.java b/baseSDK/src/main/java/com/dayu/base/api/APIService.java index 5164682..8587296 100755 --- a/baseSDK/src/main/java/com/dayu/base/api/APIService.java +++ b/baseSDK/src/main/java/com/dayu/base/api/APIService.java @@ -13,6 +13,7 @@ import retrofit2.http.GET; import retrofit2.http.Multipart; import retrofit2.http.POST; import retrofit2.http.Part; +import retrofit2.http.Query; import retrofit2.http.Streaming; import retrofit2.http.Url; @@ -45,4 +46,15 @@ public interface APIService { @POST(Constants.UP_PHOTO) Observable<BaseResponse<List<String>>> uploadPhoto( @Part MultipartBody.Part part); + + /** + * 上传图片多张,无水印. + * + * @param partMap + * @return + */ + @Multipart + @POST(Constants.UP_PHOTO) + Observable<BaseResponse<List<String>>> uploadPhoto( + @Part MultipartBody.Part[] partMap, @Query("style") String style); } diff --git a/baseSDK/src/main/java/com/dayu/base/api/BaseApiFactory.java b/baseSDK/src/main/java/com/dayu/base/api/BaseApiFactory.java index 1f812c8..fde92bd 100644 --- a/baseSDK/src/main/java/com/dayu/base/api/BaseApiFactory.java +++ b/baseSDK/src/main/java/com/dayu/base/api/BaseApiFactory.java @@ -19,4 +19,10 @@ public class BaseApiFactory { public static Observable<List<String>> uploadPhoto(MultipartBody.Part part) { return Api.getService(APIService.class).uploadPhoto(part).compose(Api.applySchedulers()); } + + public static Observable<List<String>> uploadPhoto(MultipartBody.Part[] part, String style) { + return Api.getService(APIService.class).uploadPhoto(part, style).compose(Api.applySchedulers()); + } + + } diff --git a/baseSDK/src/main/java/com/dayu/utils/GlideImageLoader.java b/baseSDK/src/main/java/com/dayu/utils/GlideImageLoader.java index 325426a..49313cb 100755 --- a/baseSDK/src/main/java/com/dayu/utils/GlideImageLoader.java +++ b/baseSDK/src/main/java/com/dayu/utils/GlideImageLoader.java @@ -1,6 +1,8 @@ package com.dayu.utils; import android.content.Context; +import android.graphics.Bitmap; +import android.os.Environment; import android.support.annotation.DrawableRes; import android.widget.ImageView; @@ -9,6 +11,14 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.request.RequestOptions; import com.dayu.baselibrary.R; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade; /** @@ -34,4 +44,37 @@ public class GlideImageLoader { .apply(options) .into(view); } + + /** + * 压缩图片(质量压缩) + * + * @param bitmap + */ + public static File compressImage(Bitmap bitmap, String name) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 + int options = 100; + while (baos.toByteArray().length / 1024 > 500) { //循环判断如果压缩后图片是否大于500kb,大于继续压缩 + baos.reset();//重置baos即清空baos + options -= 10;//每次都减少10 + bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中 + } + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); + Date date = new Date(System.currentTimeMillis()); + String filename = format.format(date); + File file = new File(Environment.getExternalStorageDirectory() + "/dayu/", filename + name + ".jpg"); + try { + FileOutputStream fos = new FileOutputStream(file); + try { + fos.write(baos.toByteArray()); + fos.flush(); + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return file; + } } diff --git a/baseSDK/src/main/res/drawable-hdpi/icon_next_button.png b/baseSDK/src/main/res/drawable-hdpi/icon_next_button.png new file mode 100644 index 0000000..f26c752 Binary files /dev/null and b/baseSDK/src/main/res/drawable-hdpi/icon_next_button.png differ diff --git a/baseSDK/src/main/res/drawable-xhdpi/icon_next_button.png b/baseSDK/src/main/res/drawable-xhdpi/icon_next_button.png new file mode 100644 index 0000000..a07cc6c Binary files /dev/null and b/baseSDK/src/main/res/drawable-xhdpi/icon_next_button.png differ diff --git a/baseSDK/src/main/res/drawable-xxhdpi/icon_next_button.png b/baseSDK/src/main/res/drawable-xxhdpi/icon_next_button.png new file mode 100644 index 0000000..7650a77 Binary files /dev/null and b/baseSDK/src/main/res/drawable-xxhdpi/icon_next_button.png differ diff --git a/baseSDK/src/main/res/drawable-xxxhdpi/icon_next_button.png b/baseSDK/src/main/res/drawable-xxxhdpi/icon_next_button.png new file mode 100644 index 0000000..ea08799 Binary files /dev/null and b/baseSDK/src/main/res/drawable-xxxhdpi/icon_next_button.png differ diff --git a/build.gradle b/build.gradle index a0be593..b259407 100755 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { ext.verson_name = "1.5.0" ext.gradle_version = '3.0.1' ext.isReleaseMinify = true - ext.isDebugMinify = true + ext.isDebugMinify = false ext.arouter_api_version = '1.3.1' ext.arouter_compiler_version = '1.1.4' diff --git a/settings.gradle b/settings.gradle index fe10059..70f3947 100755 --- a/settings.gradle +++ b/settings.gradle @@ -6,4 +6,5 @@ include ':app', ':orderCenter', ':locationComponent', ':pickerview', - ':wheelview' + ':wheelview', + ':IDCardLib' diff --git a/userCenter/build.gradle b/userCenter/build.gradle index 219670c..98ccc3d 100644 --- a/userCenter/build.gradle +++ b/userCenter/build.gradle @@ -61,4 +61,6 @@ dependencies { //ARouter annotationProcessor "com.alibaba:arouter-compiler:$arouter_compiler_version" compile project(':provider') + compile project(':IDCardLib') +// compile project(':livenesslib') } diff --git a/userCenter/src/main/debug/AndroidManifest.xml b/userCenter/src/main/debug/AndroidManifest.xml index 801b73f..a851b7f 100644 --- a/userCenter/src/main/debug/AndroidManifest.xml +++ b/userCenter/src/main/debug/AndroidManifest.xml @@ -44,5 +44,14 @@ <activity android:name=".ui.activity.LicenceDetailActivity" android:screenOrientation="portrait" /> + <activity + android:name=".ui.activity.IdentityCertificationActivity" + android:screenOrientation="portrait" /> + <activity + android:name=".ui.activity.FaceCertificationActivity" + android:screenOrientation="portrait" /> + <activity + android:name=".ui.activity.CertificationResultActivity" + android:screenOrientation="portrait" /> </application> </manifest> diff --git a/userCenter/src/main/java/com/dayu/usercenter/api/UserApiFactory.java b/userCenter/src/main/java/com/dayu/usercenter/api/UserApiFactory.java index 1e3c980..547ad05 100644 --- a/userCenter/src/main/java/com/dayu/usercenter/api/UserApiFactory.java +++ b/userCenter/src/main/java/com/dayu/usercenter/api/UserApiFactory.java @@ -77,4 +77,12 @@ public class UserApiFactory { public static Observable<LicenceInfo> getLicence(int id) { return Api.getService(UserService.class).getLicence(id).compose(Api.applySchedulers()); } + + public static Observable<Boolean> verifyIdentity(String front, String side) { + return Api.getDownloadService(UserService.class).verifyIdentity(front, side).compose(Api.applySchedulers()); + } + + public static Observable<Boolean> verifyMegLive(RequestBody body) { + return Api.getDownloadService(UserService.class).verifyMegLive(body).compose(Api.applySchedulers()); + } } diff --git a/userCenter/src/main/java/com/dayu/usercenter/api/UserService.java b/userCenter/src/main/java/com/dayu/usercenter/api/UserService.java index 15c54bc..303bd51 100755 --- a/userCenter/src/main/java/com/dayu/usercenter/api/UserService.java +++ b/userCenter/src/main/java/com/dayu/usercenter/api/UserService.java @@ -156,9 +156,29 @@ public interface UserService { /** * 获取资质详情. + * * @param id * @return */ @GET(UserConstant.PERSON_LICENCE) Observable<BaseResponse<LicenceInfo>> getLicence(@Path("id") int id); + + /** + * 身份证识别. + * + * @param cardFront + * @param cardBack + * @return + */ + @GET(UserConstant.IDENTITY_OCR) + Observable<BaseResponse<Boolean>> verifyIdentity(@Query("cardFrontUrl") String cardFront, @Query("cardBackUrl") String cardBack); + + /** + * 活体检测. + * + * @param body + * @return + */ + @POST(UserConstant.FACE_OCR) + Observable<BaseResponse<Boolean>> verifyMegLive(@Body RequestBody body); } diff --git a/userCenter/src/main/java/com/dayu/usercenter/common/UserConstant.java b/userCenter/src/main/java/com/dayu/usercenter/common/UserConstant.java index 4fdef0c..2f6e972 100644 --- a/userCenter/src/main/java/com/dayu/usercenter/common/UserConstant.java +++ b/userCenter/src/main/java/com/dayu/usercenter/common/UserConstant.java @@ -6,6 +6,8 @@ package com.dayu.usercenter.common; */ public class UserConstant { + public static final String FRONT_URL = "front_url"; + public static final String BACK_URL = "back_url"; /** * 登录. @@ -66,4 +68,8 @@ public class UserConstant { public final static String PERSON_LICENCE = "/api-user/" + "licenceInfo/{id}"; + public final static String IDENTITY_OCR = "/api-detect/" + "detect/cardOcr"; + + public final static String FACE_OCR = "/api-detect/" + "detect/megLiveVerify"; + } diff --git a/userCenter/src/main/java/com/dayu/usercenter/data/protocol/MegLive.java b/userCenter/src/main/java/com/dayu/usercenter/data/protocol/MegLive.java new file mode 100644 index 0000000..8117db1 --- /dev/null +++ b/userCenter/src/main/java/com/dayu/usercenter/data/protocol/MegLive.java @@ -0,0 +1,34 @@ +package com.dayu.usercenter.data.protocol; + +/** + * Created by luofan + * on 2018/5/14. + */ + +public class MegLive { +// "cardBackUrl": "string", +// "cardFrontUrl": "string", +// "checkDelta": "string", +// "comparisonType": "string", +// "delta": "string", +// "imageAction1Url": "string", +// "imageAction2Url": "string", +// "imageAction3Url": "string", +// "imageAction4Url": "string", +// "imageAction5Url": "string", +// "imageBestUrl": "string", +// "imageEnvUrl": "string", +// "imageRef1Url": "string", +// "imageRef2Url": "string", +// "imageRef3Url": "string", +// "multiOrientedDetection": "string" +// private String cardBackUrl; +// private String cardFrontUrl; +// private String checkDelta; +// private String cardBackUrl; +// private String cardBackUrl; +// private String cardBackUrl; +// private String cardBackUrl; +// private String cardBackUrl; +// private String cardBackUrl; +} diff --git a/userCenter/src/main/java/com/dayu/usercenter/presenter/certification/CertificaitonContract.java b/userCenter/src/main/java/com/dayu/usercenter/presenter/certification/CertificaitonContract.java new file mode 100755 index 0000000..2207b83 --- /dev/null +++ b/userCenter/src/main/java/com/dayu/usercenter/presenter/certification/CertificaitonContract.java @@ -0,0 +1,25 @@ +package com.dayu.usercenter.presenter.certification; + + +import com.dayu.base.ui.presenter.BasePresenter; +import com.dayu.common.BaseView; + +import java.io.File; +import java.util.List; + +/** + * Created by luo + * on 2016/8/4. + */ +public interface CertificaitonContract { + + interface View extends BaseView { + List<File> getFile(); + } + + abstract class Presenter extends BasePresenter<View> { + public abstract void commitePhoto(); + + public abstract void verifyIdentity(List<String> list); + } +} diff --git a/userCenter/src/main/java/com/dayu/usercenter/presenter/certification/CertificaitonPresenter.java b/userCenter/src/main/java/com/dayu/usercenter/presenter/certification/CertificaitonPresenter.java new file mode 100644 index 0000000..0a2d3f4 --- /dev/null +++ b/userCenter/src/main/java/com/dayu/usercenter/presenter/certification/CertificaitonPresenter.java @@ -0,0 +1,65 @@ +package com.dayu.usercenter.presenter.certification; + +import android.os.Bundle; + +import com.dayu.base.api.BaseApiFactory; +import com.dayu.usercenter.api.UserApiFactory; +import com.dayu.usercenter.common.UserConstant; +import com.dayu.usercenter.ui.activity.FaceCertificationActivity; +import com.dayu.utils.ToastUtils; + +import java.io.File; +import java.util.List; + +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; + +/** + * Created by luofan + * on 2017/11/14. + */ +public class CertificaitonPresenter extends CertificaitonContract.Presenter { + + @Override + public void onAttached() { + } + + @Override + public void commitePhoto() { +// mView.startActivity(FaceCertificationActivity.class); + BaseApiFactory.uploadPhoto(packPhoto(mView.getFile()), "nowatermark").subscribe(baseObserver(list -> { + Bundle bundle = new Bundle(); + bundle.putString(UserConstant.FRONT_URL, list.get(0)); + bundle.putString(UserConstant.BACK_URL, list.get(1)); + mView.startActivity(FaceCertificationActivity.class, bundle); + })); + } + + private MultipartBody.Part[] packPhoto(List<File> files) { + MultipartBody.Part[] part = new MultipartBody.Part[files.size()]; + for (int i = 0; i < files.size(); i++) { + RequestBody requestFile = + RequestBody.create(MediaType.parse("multipart/form-data"), files.get(i)); + MultipartBody.Part body = + MultipartBody.Part.createFormData("fileUpload", files.get(i).getName(), requestFile); + part[i] = body; + } + return part; + } + + @Override + public void verifyIdentity(List<String> list) { + UserApiFactory.verifyIdentity(list.get(0), list.get(1)).subscribe(baseObserver(aBoolean -> { + if (aBoolean) { + ToastUtils.showShortToast("身份证上传成功!"); + Bundle bundle = new Bundle(); + bundle.putString(UserConstant.FRONT_URL, list.get(0)); + bundle.putString(UserConstant.BACK_URL, list.get(1)); + mView.startActivity(FaceCertificationActivity.class, bundle); + } else { + ToastUtils.showShortToast("您传的身份证不合格,请重新上传!"); + } + })); + } +} diff --git a/userCenter/src/main/java/com/dayu/usercenter/presenter/facecertification/FaceCertificaitonContract.java b/userCenter/src/main/java/com/dayu/usercenter/presenter/facecertification/FaceCertificaitonContract.java new file mode 100755 index 0000000..b5e5d9d --- /dev/null +++ b/userCenter/src/main/java/com/dayu/usercenter/presenter/facecertification/FaceCertificaitonContract.java @@ -0,0 +1,24 @@ +package com.dayu.usercenter.presenter.facecertification; + + +import com.dayu.base.ui.presenter.BasePresenter; +import com.dayu.common.BaseView; + +import java.io.File; +import java.util.List; + +/** + * Created by luo + * on 2016/8/4. + */ +public interface FaceCertificaitonContract { + + interface View extends BaseView { + } + + abstract class Presenter extends BasePresenter<View> { + public abstract void commitePhoto(List<File> list,String delta); + + public abstract void verifyIdentity(List<String> list); + } +} diff --git a/userCenter/src/main/java/com/dayu/usercenter/presenter/facecertification/FaceCertificaitonPresenter.java b/userCenter/src/main/java/com/dayu/usercenter/presenter/facecertification/FaceCertificaitonPresenter.java new file mode 100644 index 0000000..7ab2b4b --- /dev/null +++ b/userCenter/src/main/java/com/dayu/usercenter/presenter/facecertification/FaceCertificaitonPresenter.java @@ -0,0 +1,80 @@ +package com.dayu.usercenter.presenter.facecertification; + +import android.os.Bundle; + +import com.dayu.base.api.BaseApiFactory; +import com.dayu.usercenter.api.UserApiFactory; +import com.dayu.usercenter.common.UserConstant; +import com.dayu.usercenter.ui.activity.CertificationResultActivity; +import com.dayu.utils.ToastUtils; + +import org.json.JSONObject; + +import java.io.File; +import java.util.HashMap; +import java.util.List; + +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; + +/** + * Created by luofan + * on 2017/11/14. + */ +public class FaceCertificaitonPresenter extends FaceCertificaitonContract.Presenter { + private String mDelta; + private String mFrontCardUrl; + private String mBackCardUrl; + + @Override + public void onAttached() { + Bundle bundle = mView.getBundle(); + mFrontCardUrl = bundle.getString(UserConstant.FRONT_URL); + mBackCardUrl = bundle.getString(UserConstant.BACK_URL); + } + + @Override + public void commitePhoto(List<File> list, String delta) { + mDelta = delta; + BaseApiFactory.uploadPhoto(packPhoto(list),"nowatermark").subscribe(baseObserver(this::verifyIdentity)); + } + + private MultipartBody.Part[] packPhoto(List<File> files) { + MultipartBody.Part[] part = new MultipartBody.Part[files.size()]; + for (int i = 0; i < files.size(); i++) { + RequestBody requestFile = + RequestBody.create(MediaType.parse("multipart/form-data"), files.get(i)); + MultipartBody.Part body = + MultipartBody.Part.createFormData("fileUpload", files.get(i).getName(), requestFile); + part[i] = body; + } + return part; + } + + @Override + public void verifyIdentity(List<String> list) { + HashMap<String, Object> params = new HashMap<>(); + params.put("cardBackUrl", mFrontCardUrl); + params.put("cardFrontUrl", mBackCardUrl); + params.put("checkDelta", 0); + params.put("comparisonType", 1); + params.put("delta", mDelta); + params.put("imageAction1Url", list.get(2)); + params.put("imageAction2Url", list.get(3)); + params.put("imageAction3Url", list.get(4)); + params.put("imageBestUrl", list.get(0)); + params.put("imageEnvUrl", list.get(1)); + params.put("multiOrientedDetection", 1); + JSONObject jsonObject = new JSONObject(params); + RequestBody body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString()); + UserApiFactory.verifyMegLive(body).subscribe(baseObserver(aBoolean -> { + if (aBoolean) { + ToastUtils.showShortToast("身份证上传成功!"); + mView.startActivity(CertificationResultActivity.class); + } else { + ToastUtils.showShortToast("您传的身份证不合格,请重新上传!"); + } + })); + } +} diff --git a/userCenter/src/main/java/com/dayu/usercenter/ui/activity/CertificationResultActivity.java b/userCenter/src/main/java/com/dayu/usercenter/ui/activity/CertificationResultActivity.java new file mode 100644 index 0000000..e6ff6fb --- /dev/null +++ b/userCenter/src/main/java/com/dayu/usercenter/ui/activity/CertificationResultActivity.java @@ -0,0 +1,22 @@ +package com.dayu.usercenter.ui.activity; + +import com.dayu.base.ui.activity.DataBindingActivity; +import com.dayu.usercenter.R; +import com.dayu.usercenter.databinding.ActivityCertificationResultBinding; + +/** + * Created by luofan + * on 2018/5/10. + */ + +public class CertificationResultActivity extends DataBindingActivity<ActivityCertificationResultBinding> { + @Override + public int getLayoutId() { + return R.layout.activity_certification_result; + } + + @Override + public void initView() { + + } +} diff --git a/userCenter/src/main/java/com/dayu/usercenter/ui/activity/FaceCertificationActivity.java b/userCenter/src/main/java/com/dayu/usercenter/ui/activity/FaceCertificationActivity.java new file mode 100644 index 0000000..343575b --- /dev/null +++ b/userCenter/src/main/java/com/dayu/usercenter/ui/activity/FaceCertificationActivity.java @@ -0,0 +1,119 @@ +package com.dayu.usercenter.ui.activity; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.BitmapFactory; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; + +import com.dayu.base.ui.activity.BaseActivity; +import com.dayu.usercenter.R; +import com.dayu.usercenter.databinding.ActivityFaceCertificationBinding; +import com.dayu.usercenter.presenter.facecertification.FaceCertificaitonContract; +import com.dayu.usercenter.presenter.facecertification.FaceCertificaitonPresenter; +import com.dayu.utils.GlideImageLoader; +import com.dayu.utils.ToastUtils; +import com.megvii.idcardlib.LivenessActivity; +import com.megvii.idcardlib.util.ConUtil; +import com.megvii.licensemanager.Manager; +import com.megvii.livenessdetection.LivenessLicenseManager; + +import java.io.File; +import java.util.ArrayList; +import java.util.Map; + +import static android.os.Build.VERSION_CODES.M; + +/** + * Created by luofan + * on 2018/5/10. + */ + +public class FaceCertificationActivity extends BaseActivity<FaceCertificaitonPresenter, ActivityFaceCertificationBinding> + implements FaceCertificaitonContract.View { + private String uuid; + private static final int PAGE_INTO_LIVENESS = 100; + public static final int EXTERNAL_STORAGE_REQ_CAMERA_CODE = 10; + + @Override + public int getLayoutId() { + return R.layout.activity_face_certification; + } + + @Override + public void initView() { + mBind.tvNext.setOnClickListener(v -> requestCameraPerm()); + mBind.titleBack.setOnClickListener(v -> finish()); + mBind.tvTitle.setText("实名认证"); + uuid = ConUtil.getUUIDString(this); + new Thread(() -> { + Manager manager = new Manager(FaceCertificationActivity.this); + LivenessLicenseManager licenseManager = new LivenessLicenseManager(FaceCertificationActivity.this); + manager.registerLicenseManager(licenseManager); + manager.takeLicenseFromNetwork(uuid); + if (licenseManager.checkCachedLicense() < 0) { + runOnUiThread(() -> ToastUtils.showShortToast("授权失败")); + } + }).start(); + } + + private void requestCameraPerm() { + if (android.os.Build.VERSION.SDK_INT >= M) { + if (ContextCompat.checkSelfPermission(this, + Manifest.permission.CAMERA) + != PackageManager.PERMISSION_GRANTED) { + //进行权限请求 + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.CAMERA}, + EXTERNAL_STORAGE_REQ_CAMERA_CODE); + } else { + enterNextPage(); + } + } else { + enterNextPage(); + } + } + + private void enterNextPage() { + startActivityForResult(new Intent(this, LivenessActivity.class), PAGE_INTO_LIVENESS); + } + + @Override + public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) { + if (requestCode == EXTERNAL_STORAGE_REQ_CAMERA_CODE) { + if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {// Permission Granted + ConUtil.showToast(this, "获取相机权限失败"); + } else + enterNextPage(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == PAGE_INTO_LIVENESS && resultCode == RESULT_OK) { + String delta = data.getStringExtra("delta"); + int code = data.getIntExtra("resultcode", 0); + Map<String, byte[]> images = (Map<String, byte[]>) data.getSerializableExtra("images"); + ArrayList<File> list = new ArrayList<>(); + byte[] image_best = images.get("image_best"); + byte[] image_env = images.get("image_env"); + byte[] image_action1 = images.get("imageAction1"); + byte[] image_action2 = images.get("imageAction2"); + byte[] image_action3 = images.get("imageAction3"); + list.add(GlideImageLoader.compressImage(BitmapFactory.decodeByteArray(image_best, 0, image_best.length), "best")); + list.add(GlideImageLoader.compressImage(BitmapFactory.decodeByteArray(image_env, 0, image_best.length), "env")); + list.add(GlideImageLoader.compressImage(BitmapFactory.decodeByteArray(image_action1, 0, image_best.length), "action1")); + list.add(GlideImageLoader.compressImage(BitmapFactory.decodeByteArray(image_action2, 0, image_best.length), "action2")); + list.add(GlideImageLoader.compressImage(BitmapFactory.decodeByteArray(image_action3, 0, image_best.length), "action3")); + mPresenter.commitePhoto(list, delta); + } + } + + @Override + public void setPresenter() { + mBind.setPresenter(mPresenter); + } +} diff --git a/userCenter/src/main/java/com/dayu/usercenter/ui/activity/IdentityCertificationActivity.java b/userCenter/src/main/java/com/dayu/usercenter/ui/activity/IdentityCertificationActivity.java new file mode 100644 index 0000000..72aee32 --- /dev/null +++ b/userCenter/src/main/java/com/dayu/usercenter/ui/activity/IdentityCertificationActivity.java @@ -0,0 +1,207 @@ +package com.dayu.usercenter.ui.activity; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; + +import com.dayu.base.ui.activity.BaseActivity; +import com.dayu.usercenter.R; +import com.dayu.usercenter.databinding.ActivityCertificationLayoutBinding; +import com.dayu.usercenter.presenter.certification.CertificaitonContract; +import com.dayu.usercenter.presenter.certification.CertificaitonPresenter; +import com.dayu.utils.ToastUtils; +import com.megvii.idcardlib.IDCardScanActivity; +import com.megvii.idcardlib.util.Util; +import com.megvii.idcardquality.IDCardQualityLicenseManager; +import com.megvii.licensemanager.Manager; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import static android.os.Build.VERSION_CODES.M; +import static com.dayu.utils.GlideImageLoader.compressImage; + +/** + * Created by luofan + * on 2018/5/10. + */ + +public class IdentityCertificationActivity extends BaseActivity<CertificaitonPresenter, ActivityCertificationLayoutBinding> + implements CertificaitonContract.View { + public static final int EXTERNAL_STORAGE_REQ_CAMERA_CODE = 10; + private static final int INTO_IDCARDSCAN_PAGE = 100; + private String uuid; + private int mSide = 0; + private boolean mFrontFlag = false; + private boolean mSideFlag = false; + private Bitmap mFrontBitmap; + private Bitmap mSideBitmap; + + @Override + public void setPresenter() { + mBind.setPresenter(mPresenter); + } + + @Override + public int getLayoutId() { + return R.layout.activity_certification_layout; + } + + @Override + public void initView() { + mBind.tvTitle.setText("实名认证"); + mBind.ivFront.setOnClickListener(v -> { + if (mFrontFlag) { + imgMax(mFrontBitmap); + } else { + requestCameraPerm(0); + } + }); + mBind.ivSide.setOnClickListener(v -> { + if (mSideFlag) { + imgMax(mSideBitmap); + } else { + requestCameraPerm(1); + } + }); + mBind.ivFrontDelete.setOnClickListener(v -> { + mFrontBitmap = null; + mFrontFlag = false; + mBind.ivFront.setImageResource(R.drawable.icon_idcard_front); + mBind.ivNext.setAlpha(0.5f); + mBind.rlNext.setClickable(false); + mBind.ivFrontDelete.setVisibility(View.GONE); + }); + mBind.ivSideDelete.setOnClickListener(v -> { + mSideBitmap = null; + mSideFlag = false; + mBind.ivSide.setImageResource(R.drawable.icon_idcard_side); + mBind.ivNext.setAlpha(0.5f); + mBind.rlNext.setClickable(false); + mBind.ivSideDelete.setVisibility(View.GONE); + }); + mBind.ivNext.setAlpha(0.5f); + mBind.rlNext.setClickable(false); + + uuid = Util.getUUIDString(this); + new Thread(() -> { + Manager manager = new Manager(IdentityCertificationActivity.this); + IDCardQualityLicenseManager idCardLicenseManager = new IDCardQualityLicenseManager( + IdentityCertificationActivity.this); + manager.registerLicenseManager(idCardLicenseManager); + manager.takeLicenseFromNetwork(uuid); + if (idCardLicenseManager.checkCachedLicense() > 0) { + UIAuthState(true); + } else { + UIAuthState(false); + } + }).start(); + } + + private void requestCameraPerm(int side) { + mSide = side; + if (android.os.Build.VERSION.SDK_INT >= M) { + if (ContextCompat.checkSelfPermission(this, + Manifest.permission.CAMERA) + != PackageManager.PERMISSION_GRANTED) { + //进行权限请求 + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.CAMERA}, + EXTERNAL_STORAGE_REQ_CAMERA_CODE); + } else { + enterNextPage(side); + } + } else { + enterNextPage(side); + } + } + + private void UIAuthState(final boolean isSuccess) { + runOnUiThread(() -> authState(isSuccess)); + } + + private void authState(boolean isSuccess) { + if (isSuccess) { + } else { + runOnUiThread(() -> ToastUtils.showShortToast("联网授权失败!请检查网络或找服务商")); + } + } + + private void enterNextPage(int side) { + Intent intent = new Intent(this, IDCardScanActivity.class); + intent.putExtra("side", side); + intent.putExtra("isvertical", true); + startActivityForResult(intent, INTO_IDCARDSCAN_PAGE); + } + + @Override + public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) { + if (requestCode == EXTERNAL_STORAGE_REQ_CAMERA_CODE) { + if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {// Permission Granted + Util.showToast(this, "获取相机权限失败"); + } else { + enterNextPage(mSide); + } + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == INTO_IDCARDSCAN_PAGE && resultCode == RESULT_OK) { + runOnUiThread(() -> { + byte[] idcardImgData = data.getByteArrayExtra("idcardImg"); + Bitmap idcardBmp = BitmapFactory.decodeByteArray(idcardImgData, 0, + idcardImgData.length); + if (mSide == 0) { + mFrontBitmap = idcardBmp; + mBind.ivFront.setImageBitmap(idcardBmp); + mBind.ivFrontDelete.setVisibility(View.VISIBLE); + byte[] portraitImgData = data.getByteArrayExtra( + "portraitImg"); + Bitmap img = BitmapFactory.decodeByteArray(portraitImgData, 0, + portraitImgData.length); + mFrontFlag = true; + } else { + mSideBitmap = idcardBmp; + mBind.ivSide.setImageBitmap(idcardBmp); + mSideFlag = true; + mBind.ivSideDelete.setVisibility(View.VISIBLE); + } + if (mFrontFlag && mSideFlag) { + mBind.ivNext.setAlpha(1f); + mBind.rlNext.setClickable(true); + } + }); + } + } + + public void imgMax(Bitmap bitmap) { + LayoutInflater inflater = LayoutInflater.from(mActivity); + View imgEntryView = inflater.inflate(R.layout.dialog_image, null); + final AlertDialog dialog = new AlertDialog.Builder(mActivity).create(); + ImageView img = imgEntryView.findViewById(R.id.large_image); + img.setImageBitmap(bitmap); + dialog.setView(imgEntryView); + dialog.show(); + imgEntryView.setOnClickListener(paramView -> dialog.cancel()); + } + + @Override + public List<File> getFile() { + ArrayList<File> list = new ArrayList<>(); + list.add(compressImage(mFrontBitmap,"front")); + list.add(compressImage(mSideBitmap,"back")); + return list; + } +} diff --git a/userCenter/src/main/java/com/dayu/usercenter/ui/fragment/HomePersonFragment.java b/userCenter/src/main/java/com/dayu/usercenter/ui/fragment/HomePersonFragment.java index c2a14d5..0f44a16 100644 --- a/userCenter/src/main/java/com/dayu/usercenter/ui/fragment/HomePersonFragment.java +++ b/userCenter/src/main/java/com/dayu/usercenter/ui/fragment/HomePersonFragment.java @@ -160,7 +160,6 @@ public class HomePersonFragment extends BaseFragment<HomePersonPresenter, Fragme @Override public void dumpToOrderRecord() { - Bundle bundle = new Bundle(); ARouter.getInstance().build(RouterPath.PATH_ORDER_HISTORY).navigation(); MobclickAgent.onEvent(mActivity, "order_record"); } diff --git a/userCenter/src/main/release/AndroidManifest.xml b/userCenter/src/main/release/AndroidManifest.xml index 2896953..25b517f 100644 --- a/userCenter/src/main/release/AndroidManifest.xml +++ b/userCenter/src/main/release/AndroidManifest.xml @@ -36,6 +36,15 @@ <activity android:name=".ui.activity.LicenceDetailActivity" android:screenOrientation="portrait" /> + <activity + android:name=".ui.activity.IdentityCertificationActivity" + android:screenOrientation="portrait" /> + <activity + android:name=".ui.activity.FaceCertificationActivity" + android:screenOrientation="portrait" /> + <activity + android:name=".ui.activity.CertificationResultActivity" + android:screenOrientation="portrait" /> </application> </manifest> diff --git a/userCenter/src/main/res/drawable-hdpi/icon_certificaiton_succeed.png b/userCenter/src/main/res/drawable-hdpi/icon_certificaiton_succeed.png new file mode 100644 index 0000000..198bea0 Binary files /dev/null and b/userCenter/src/main/res/drawable-hdpi/icon_certificaiton_succeed.png differ diff --git a/userCenter/src/main/res/drawable-hdpi/icon_certification_failure.png b/userCenter/src/main/res/drawable-hdpi/icon_certification_failure.png new file mode 100644 index 0000000..25a98f3 Binary files /dev/null and b/userCenter/src/main/res/drawable-hdpi/icon_certification_failure.png differ diff --git a/userCenter/src/main/res/drawable-hdpi/icon_certification_notice.png b/userCenter/src/main/res/drawable-hdpi/icon_certification_notice.png new file mode 100644 index 0000000..351ba99 Binary files /dev/null and b/userCenter/src/main/res/drawable-hdpi/icon_certification_notice.png differ diff --git a/userCenter/src/main/res/drawable-hdpi/icon_first.png b/userCenter/src/main/res/drawable-hdpi/icon_first.png new file mode 100644 index 0000000..9a5f6d8 Binary files /dev/null and b/userCenter/src/main/res/drawable-hdpi/icon_first.png differ diff --git a/userCenter/src/main/res/drawable-hdpi/icon_idcard_front.png b/userCenter/src/main/res/drawable-hdpi/icon_idcard_front.png new file mode 100644 index 0000000..d1b1fdb Binary files /dev/null and b/userCenter/src/main/res/drawable-hdpi/icon_idcard_front.png differ diff --git a/userCenter/src/main/res/drawable-hdpi/icon_idcard_side.png b/userCenter/src/main/res/drawable-hdpi/icon_idcard_side.png new file mode 100644 index 0000000..bb0ba99 Binary files /dev/null and b/userCenter/src/main/res/drawable-hdpi/icon_idcard_side.png differ diff --git a/userCenter/src/main/res/drawable-hdpi/icon_second.png b/userCenter/src/main/res/drawable-hdpi/icon_second.png new file mode 100644 index 0000000..8d7ff3e Binary files /dev/null and b/userCenter/src/main/res/drawable-hdpi/icon_second.png differ diff --git a/userCenter/src/main/res/drawable-hdpi/icon_third.png b/userCenter/src/main/res/drawable-hdpi/icon_third.png new file mode 100644 index 0000000..39e06b6 Binary files /dev/null and b/userCenter/src/main/res/drawable-hdpi/icon_third.png differ diff --git a/userCenter/src/main/res/drawable-xhdpi/icon_certificaiton_succeed.png b/userCenter/src/main/res/drawable-xhdpi/icon_certificaiton_succeed.png new file mode 100644 index 0000000..d7dbca9 Binary files /dev/null and b/userCenter/src/main/res/drawable-xhdpi/icon_certificaiton_succeed.png differ diff --git a/userCenter/src/main/res/drawable-xhdpi/icon_certification_failure.png b/userCenter/src/main/res/drawable-xhdpi/icon_certification_failure.png new file mode 100644 index 0000000..ff89214 Binary files /dev/null and b/userCenter/src/main/res/drawable-xhdpi/icon_certification_failure.png differ diff --git a/userCenter/src/main/res/drawable-xhdpi/icon_certification_notice.png b/userCenter/src/main/res/drawable-xhdpi/icon_certification_notice.png new file mode 100644 index 0000000..b0fbf73 Binary files /dev/null and b/userCenter/src/main/res/drawable-xhdpi/icon_certification_notice.png differ diff --git a/userCenter/src/main/res/drawable-xhdpi/icon_first.png b/userCenter/src/main/res/drawable-xhdpi/icon_first.png new file mode 100644 index 0000000..761f015 Binary files /dev/null and b/userCenter/src/main/res/drawable-xhdpi/icon_first.png differ diff --git a/userCenter/src/main/res/drawable-xhdpi/icon_idcard_front.png b/userCenter/src/main/res/drawable-xhdpi/icon_idcard_front.png new file mode 100644 index 0000000..b5dd7d0 Binary files /dev/null and b/userCenter/src/main/res/drawable-xhdpi/icon_idcard_front.png differ diff --git a/userCenter/src/main/res/drawable-xhdpi/icon_idcard_side.png b/userCenter/src/main/res/drawable-xhdpi/icon_idcard_side.png new file mode 100644 index 0000000..1e45b58 Binary files /dev/null and b/userCenter/src/main/res/drawable-xhdpi/icon_idcard_side.png differ diff --git a/userCenter/src/main/res/drawable-xhdpi/icon_index.png b/userCenter/src/main/res/drawable-xhdpi/icon_index.png new file mode 100644 index 0000000..e0bd700 Binary files /dev/null and b/userCenter/src/main/res/drawable-xhdpi/icon_index.png differ diff --git a/userCenter/src/main/res/drawable-xhdpi/icon_second.png b/userCenter/src/main/res/drawable-xhdpi/icon_second.png new file mode 100644 index 0000000..59fa270 Binary files /dev/null and b/userCenter/src/main/res/drawable-xhdpi/icon_second.png differ diff --git a/userCenter/src/main/res/drawable-xhdpi/icon_third.png b/userCenter/src/main/res/drawable-xhdpi/icon_third.png new file mode 100644 index 0000000..3225416 Binary files /dev/null and b/userCenter/src/main/res/drawable-xhdpi/icon_third.png differ diff --git a/userCenter/src/main/res/drawable-xxhdpi/icon_certification_failure.png b/userCenter/src/main/res/drawable-xxhdpi/icon_certification_failure.png new file mode 100644 index 0000000..cee6b47 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxhdpi/icon_certification_failure.png differ diff --git a/userCenter/src/main/res/drawable-xxhdpi/icon_certification_notice.png b/userCenter/src/main/res/drawable-xxhdpi/icon_certification_notice.png new file mode 100644 index 0000000..9935ce3 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxhdpi/icon_certification_notice.png differ diff --git a/userCenter/src/main/res/drawable-xxhdpi/icon_certification_succeed.png b/userCenter/src/main/res/drawable-xxhdpi/icon_certification_succeed.png new file mode 100644 index 0000000..da2cbca Binary files /dev/null and b/userCenter/src/main/res/drawable-xxhdpi/icon_certification_succeed.png differ diff --git a/userCenter/src/main/res/drawable-xxhdpi/icon_first.png b/userCenter/src/main/res/drawable-xxhdpi/icon_first.png new file mode 100644 index 0000000..82e4494 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxhdpi/icon_first.png differ diff --git a/userCenter/src/main/res/drawable-xxhdpi/icon_idcard_front.png b/userCenter/src/main/res/drawable-xxhdpi/icon_idcard_front.png new file mode 100644 index 0000000..5647a90 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxhdpi/icon_idcard_front.png differ diff --git a/userCenter/src/main/res/drawable-xxhdpi/icon_idcard_side.png b/userCenter/src/main/res/drawable-xxhdpi/icon_idcard_side.png new file mode 100644 index 0000000..daad839 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxhdpi/icon_idcard_side.png differ diff --git a/userCenter/src/main/res/drawable-xxhdpi/icon_index.png b/userCenter/src/main/res/drawable-xxhdpi/icon_index.png new file mode 100644 index 0000000..8afefbc Binary files /dev/null and b/userCenter/src/main/res/drawable-xxhdpi/icon_index.png differ diff --git a/userCenter/src/main/res/drawable-xxhdpi/icon_second.png b/userCenter/src/main/res/drawable-xxhdpi/icon_second.png new file mode 100644 index 0000000..61844f7 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxhdpi/icon_second.png differ diff --git a/userCenter/src/main/res/drawable-xxhdpi/icon_third.png b/userCenter/src/main/res/drawable-xxhdpi/icon_third.png new file mode 100644 index 0000000..b1c90dd Binary files /dev/null and b/userCenter/src/main/res/drawable-xxhdpi/icon_third.png differ diff --git a/userCenter/src/main/res/drawable-xxxhdpi/icon_certification_failure.png b/userCenter/src/main/res/drawable-xxxhdpi/icon_certification_failure.png new file mode 100644 index 0000000..4046ea9 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxxhdpi/icon_certification_failure.png differ diff --git a/userCenter/src/main/res/drawable-xxxhdpi/icon_certification_notice.png b/userCenter/src/main/res/drawable-xxxhdpi/icon_certification_notice.png new file mode 100644 index 0000000..1f0bd05 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxxhdpi/icon_certification_notice.png differ diff --git a/userCenter/src/main/res/drawable-xxxhdpi/icon_certification_succeed.png b/userCenter/src/main/res/drawable-xxxhdpi/icon_certification_succeed.png new file mode 100644 index 0000000..9c96463 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxxhdpi/icon_certification_succeed.png differ diff --git a/userCenter/src/main/res/drawable-xxxhdpi/icon_first.png b/userCenter/src/main/res/drawable-xxxhdpi/icon_first.png new file mode 100644 index 0000000..7643bc4 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxxhdpi/icon_first.png differ diff --git a/userCenter/src/main/res/drawable-xxxhdpi/icon_idcard_front.png b/userCenter/src/main/res/drawable-xxxhdpi/icon_idcard_front.png new file mode 100644 index 0000000..413386f Binary files /dev/null and b/userCenter/src/main/res/drawable-xxxhdpi/icon_idcard_front.png differ diff --git a/userCenter/src/main/res/drawable-xxxhdpi/icon_idcard_side.png b/userCenter/src/main/res/drawable-xxxhdpi/icon_idcard_side.png new file mode 100644 index 0000000..32af2bf Binary files /dev/null and b/userCenter/src/main/res/drawable-xxxhdpi/icon_idcard_side.png differ diff --git a/userCenter/src/main/res/drawable-xxxhdpi/icon_index.png b/userCenter/src/main/res/drawable-xxxhdpi/icon_index.png new file mode 100644 index 0000000..15a0c3e Binary files /dev/null and b/userCenter/src/main/res/drawable-xxxhdpi/icon_index.png differ diff --git a/userCenter/src/main/res/drawable-xxxhdpi/icon_second.png b/userCenter/src/main/res/drawable-xxxhdpi/icon_second.png new file mode 100644 index 0000000..fd6c658 Binary files /dev/null and b/userCenter/src/main/res/drawable-xxxhdpi/icon_second.png differ diff --git a/userCenter/src/main/res/drawable-xxxhdpi/icon_third.png b/userCenter/src/main/res/drawable-xxxhdpi/icon_third.png new file mode 100644 index 0000000..f42601e Binary files /dev/null and b/userCenter/src/main/res/drawable-xxxhdpi/icon_third.png differ diff --git a/userCenter/src/main/res/layout/activity_certification_layout.xml b/userCenter/src/main/res/layout/activity_certification_layout.xml new file mode 100644 index 0000000..906411f --- /dev/null +++ b/userCenter/src/main/res/layout/activity_certification_layout.xml @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="utf-8"?> +<layout xmlns:android="http://schemas.android.com/apk/res/android"> + + <data> + + <variable + name="presenter" + type="com.dayu.usercenter.presenter.certification.CertificaitonPresenter" /> + </data> + + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <RelativeLayout style="@style/title"> + + <TextView + android:id="@+id/tv_title" + style="@style/text_title" /> + + <ImageView + android:id="@+id/title_back" + style="@style/title_image_back" + + /> + + <TextView + android:id="@+id/tv_right_title" + style="@style/title_right_text" + android:textSize="15sp" + android:visibility="gone" /> + </RelativeLayout> + + <ImageView style="@style/card_line" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="#F5F5F5"> + + <ImageView + android:id="@+id/iv_index" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="5dp" + android:layout_marginLeft="@dimen/dp_15" + android:layout_marginRight="@dimen/dp_15" + android:layout_marginTop="5dp" + android:src="@drawable/icon_first" /> + </LinearLayout> + + <RelativeLayout + android:layout_width="209dp" + android:layout_height="133dp" + android:layout_gravity="center" + android:layout_marginTop="@dimen/dp_30"> + + <ImageView + android:id="@+id/iv_front" + android:layout_width="209dp" + android:layout_height="133dp" + android:src="@drawable/icon_idcard_front" /> + + <ImageView + android:id="@+id/iv_front_delete" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:src="@drawable/img_photo_delete" + android:visibility="gone" /> + </RelativeLayout> + + + <RelativeLayout + android:layout_width="209dp" + android:layout_height="133dp" + android:layout_gravity="center" + android:layout_marginBottom="31dp" + android:layout_marginTop="30dp"> + + <ImageView + android:id="@+id/iv_side" + android:layout_width="209dp" + android:layout_height="133dp" + android:src="@drawable/icon_idcard_side" /> + + <ImageView + android:id="@+id/iv_side_delete" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:src="@drawable/img_photo_delete" + android:visibility="gone" /> + </RelativeLayout> + + <RelativeLayout + android:id="@+id/rl_next" + android:layout_width="match_parent" + android:layout_height="47dp" + android:layout_marginBottom="54dp" + android:onClick="@{()->presenter.commitePhoto()}"> + + <ImageView + android:id="@+id/iv_next" + android:layout_width="match_parent" + android:layout_height="47dp" + android:layout_marginLeft="@dimen/dp_15" + android:layout_marginRight="15dp" + android:background="@drawable/icon_next_button" + android:gravity="center" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:text="下一步" + android:textColor="@color/white" + android:textSize="@dimen/sp_16" /> + </RelativeLayout> + + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:text="信息仅用于身份验证,大鱼师傅保障您的信息安全" + android:textColor="@color/default_editext_color" + android:textSize="@dimen/sp_14" /> + </LinearLayout> +</layout> \ No newline at end of file diff --git a/userCenter/src/main/res/layout/activity_certification_result.xml b/userCenter/src/main/res/layout/activity_certification_result.xml new file mode 100644 index 0000000..cb112e5 --- /dev/null +++ b/userCenter/src/main/res/layout/activity_certification_result.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?> +<layout xmlns:android="http://schemas.android.com/apk/res/android"> + + <data> + + </data> + + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <RelativeLayout style="@style/title"> + + <TextView + android:id="@+id/tv_title" + style="@style/text_title" /> + + <ImageView + android:id="@+id/title_back" + style="@style/title_image_back" /> + + <TextView + android:id="@+id/tv_right_title" + style="@style/title_right_text" + android:textSize="15sp" + android:visibility="gone" /> + </RelativeLayout> + + <ImageView style="@style/card_line" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="#F5F5F5"> + + <ImageView + android:id="@+id/iv_index" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="5dp" + android:layout_marginLeft="@dimen/dp_15" + android:layout_marginRight="@dimen/dp_15" + android:layout_marginTop="5dp" + android:src="@drawable/icon_third" /> + </LinearLayout> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginTop="93dp" + android:src="@drawable/icon_certificaiton_succeed" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginTop="22dp" + android:text="恭喜,认证成功!" + android:textColor="@color/default_text_color" + android:textSize="@dimen/sp_16" + android:textStyle="bold" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginTop="18dp" + android:text="快去看看有没有可接的工单吧~" + android:textColor="@color/text_color" + android:textSize="@dimen/sp_14" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginTop="90dp" + android:background="@drawable/icon_next_button" + android:gravity="center" + android:text="确定" + android:textColor="@color/white" + android:textSize="@dimen/sp_16" /> + </LinearLayout> +</layout> \ No newline at end of file diff --git a/userCenter/src/main/res/layout/activity_face_certification.xml b/userCenter/src/main/res/layout/activity_face_certification.xml new file mode 100644 index 0000000..4598557 --- /dev/null +++ b/userCenter/src/main/res/layout/activity_face_certification.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8"?> +<layout> + + <data> + + <variable + name="presenter" + type="com.dayu.usercenter.presenter.facecertification.FaceCertificaitonPresenter" /> + </data> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <RelativeLayout style="@style/title"> + + <TextView + android:id="@+id/tv_title" + style="@style/text_title" /> + + <ImageView + android:id="@+id/title_back" + style="@style/title_image_back" /> + + <TextView + android:id="@+id/tv_right_title" + style="@style/title_right_text" + android:textSize="15sp" + android:visibility="gone" /> + </RelativeLayout> + + <ImageView style="@style/card_line" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="#F5F5F5"> + + <ImageView + android:id="@+id/iv_index" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="5dp" + android:layout_marginLeft="@dimen/dp_15" + android:layout_marginRight="@dimen/dp_15" + android:layout_marginTop="5dp" + android:src="@drawable/icon_second" /> + </LinearLayout> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginBottom="30dp" + android:layout_marginTop="74dp" + android:src="@drawable/icon_certification_notice" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginBottom="@dimen/dp_11" + android:text="刷脸成功小秘诀" + android:textColor="#FF424242" + android:textSize="16sp" + android:textStyle="bold" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginBottom="74dp" + android:text="刷脸成功小秘诀" + android:textColor="#FF424242" + android:textSize="14sp" /> + + <TextView + android:id="@+id/tv_next" + android:layout_width="match_parent" + android:layout_height="47dp" + android:layout_marginLeft="15dp" + android:layout_marginRight="15dp" + android:background="@drawable/icon_next_button" + android:gravity="center" + android:text="我知道了" + android:textColor="@color/white" + android:textSize="@dimen/sp_16" /> + </LinearLayout> +</layout> \ No newline at end of file diff --git a/userCenter/src/main/res/layout/dialog_image.xml b/userCenter/src/main/res/layout/dialog_image.xml new file mode 100644 index 0000000..c434154 --- /dev/null +++ b/userCenter/src/main/res/layout/dialog_image.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:orientation="vertical"> + + <ImageView + android:id="@+id/large_image" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> +</LinearLayout> \ No newline at end of file -- libgit2 0.25.0