Commit 5b0d1c4f by 罗翻

增加人脸识别

parent 76ce3631
Showing with 5482 additions and 5 deletions
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')
}
# 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
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());
}
}
<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>
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);
}
}
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
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
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;
}
}
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
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
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
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
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();
}
}
}
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;
}
}
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
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);
}
}
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;
}
}
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
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;
}
}
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");
}
}
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();
}
}
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);
}
}
}
}
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();
}
}
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;
}
}
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;
}
}
<?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>
<?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>
<?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>
<?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>
<?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>
<?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>
<?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
<?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
<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
<?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
<?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
<?xml version="1.0" encoding="utf-8"?>
<resources>
<drawable name="red">#ffff0000</drawable>
</resources>
<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>
<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>
<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
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
......@@ -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);
}
......
......@@ -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);
}
......@@ -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());
}
}
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;
}
}
......@@ -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'
......
......@@ -6,4 +6,5 @@ include ':app',
':orderCenter',
':locationComponent',
':pickerview',
':wheelview'
':wheelview',
':IDCardLib'
......@@ -61,4 +61,6 @@ dependencies {
//ARouter
annotationProcessor "com.alibaba:arouter-compiler:$arouter_compiler_version"
compile project(':provider')
compile project(':IDCardLib')
// compile project(':livenesslib')
}
......@@ -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>
......@@ -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());
}
}
......@@ -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);
}
......@@ -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";
}
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;
}
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);
}
}
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("您传的身份证不合格,请重新上传!");
}
}));
}
}
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);
}
}
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("您传的身份证不合格,请重新上传!");
}
}));
}
}
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() {
}
}
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);
}
}
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;
}
}
......@@ -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");
}
......
......@@ -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>
<?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
<?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
<?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
<?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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment