Commit 5b0d1c4f by 罗翻

增加人脸识别

parent 76ce3631
Showing with 3034 additions and 4 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.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.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 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("您传的身份证不合格,请重新上传!");
}
}));
}
}
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