├── .gitattributes ├── .gitignore ├── .idea ├── caches │ └── build_file_checksums.ser ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── libs │ ├── aip-java-sdk-4.3.2.jar │ ├── json-20160810.jar │ └── log4j-1.2.17.jar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── frontcamera │ │ ├── ApiFaceSample.java │ │ ├── CameraSurfaceHolder.java │ │ ├── FaceTask.java │ │ ├── FrontCamera.java │ │ ├── MainActivity.java │ │ ├── OpenDoorListener.java │ │ ├── RegisterDoorButtonListener.java │ │ └── SurfaceViewCallback.java │ └── res │ ├── layout │ └── activity_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | app/src/main/java/com/frontcamera/SecretConfig.java 10 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eMous/AndroidCameraDemoWithBaiDuFaceRecognitionAPI/70f7867bda6292327698081e55c5ea26cfdfc81f/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidCameraDemoWithBaiDuFaceRecognitionAPI 2 | 3 | 百度人脸识别(闸机、门禁类型)Android Demo 4 | 5 | 最基础版本的相机画面显示部分代码 Forked from [sadaharusong/FrontCamera](https://github.com/sadaharusong/FrontCamera/) 6 | 7 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.frontcamera" 9 | minSdkVersion 19 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.2.1' 26 | compile files('libs/log4j-1.2.17.jar') 27 | compile files('libs/json-20160810.jar') 28 | compile files('libs/aip-java-sdk-4.3.2.jar') 29 | } 30 | -------------------------------------------------------------------------------- /app/libs/aip-java-sdk-4.3.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eMous/AndroidCameraDemoWithBaiDuFaceRecognitionAPI/70f7867bda6292327698081e55c5ea26cfdfc81f/app/libs/aip-java-sdk-4.3.2.jar -------------------------------------------------------------------------------- /app/libs/json-20160810.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eMous/AndroidCameraDemoWithBaiDuFaceRecognitionAPI/70f7867bda6292327698081e55c5ea26cfdfc81f/app/libs/json-20160810.jar -------------------------------------------------------------------------------- /app/libs/log4j-1.2.17.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eMous/AndroidCameraDemoWithBaiDuFaceRecognitionAPI/70f7867bda6292327698081e55c5ea26cfdfc81f/app/libs/log4j-1.2.17.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/frontcamera/ApiFaceSample.java: -------------------------------------------------------------------------------- 1 | package com.frontcamera; 2 | 3 | import android.os.Handler; 4 | import android.os.Message; 5 | import android.view.Gravity; 6 | import android.widget.Toast; 7 | 8 | import com.baidu.aip.face.AipFace; 9 | import com.baidu.aip.face.FaceVerifyRequest; 10 | 11 | import org.json.JSONArray; 12 | import org.json.JSONException; 13 | import org.json.JSONObject; 14 | 15 | import java.util.ArrayList; 16 | import java.util.HashMap; 17 | 18 | 19 | public class ApiFaceSample { 20 | 21 | private static final double PASS_SCORE = 85; 22 | private static final double ALIVE_CHECK_THRESHOLD = 0.95; 23 | 24 | private static final int PIC_ALIVE = 755; 25 | private static final int PIC_MATCH = 427; 26 | private static final int FACE_REGISTER = 800; 27 | private static final int NET_ERROR = 955; 28 | //设置APPID/AK/SK 29 | public static final String APP_ID = SecretConfig.APP_ID; 30 | public static final String API_KEY = SecretConfig.API_KEY; 31 | public static final String SECRET_KEY = SecretConfig.SECRET_KEY; 32 | 33 | public AipFace mClient; 34 | 35 | private static ApiFaceSample _instance; 36 | Handler mHandler; 37 | 38 | private ApiFaceSample() { 39 | mClient = new AipFace(APP_ID, API_KEY, SECRET_KEY); 40 | // 可选:设置网络连接参数 41 | mClient.setConnectionTimeoutInMillis(2000); 42 | mClient.setSocketTimeoutInMillis(60000); 43 | 44 | //// 可选:设置代理服务器地址, http和socket二选一,或者均不设置 45 | //mClient.setHttpProxy("proxy_host", proxy_port); // 设置http代理 46 | //mClient.setSocketProxy("proxy_host", proxy_port); // 设置socket代理 47 | 48 | // // 可选:设置log4j日志输出格式,若不设置,则使用默认配置 49 | // // 也可以直接通过jvm启动参数设置此环境变量 50 | // System.setProperty("aip.log4j.conf", "path/to/your/log4j.properties"); 51 | mHandler = new Handler() { 52 | @Override 53 | public void handleMessage(Message msg) { 54 | super.handleMessage(msg); 55 | try { 56 | JSONObject json = (JSONObject) msg.obj; 57 | switch (msg.what) { 58 | case PIC_ALIVE: 59 | 60 | int ret = json.getInt("error_code"); 61 | if (ret == 0) { 62 | double live_score = json.getJSONObject("result").getDouble("face_liveness"); 63 | if (live_score > ALIVE_CHECK_THRESHOLD) { 64 | Toast toast = Toast.makeText(SurfaceViewCallback.getInstacne().context, "活体识别成功,人脸识别开门中……" + Double.toString(live_score), Toast.LENGTH_SHORT); 65 | toast.setGravity(Gravity.CENTER, 0, 0); 66 | toast.show(); 67 | ApiFaceSample.getInstance().match(SurfaceViewCallback.getInstacne().mCurrentFrame64, "anon"); 68 | } else { 69 | Toast toast = Toast.makeText(SurfaceViewCallback.getInstacne().context, "活体识别失败,请再次尝试开门" + Double.toString(live_score), Toast.LENGTH_SHORT); 70 | toast.setGravity(Gravity.CENTER, 0, 0); 71 | toast.show(); 72 | } 73 | } else { 74 | Toast toast = Toast.makeText(SurfaceViewCallback.getInstacne().context, "活体识别失败,请再次尝试开门" +json.getString("error_msg") , Toast.LENGTH_SHORT); 75 | toast.setGravity(Gravity.CENTER, 0, 0); 76 | toast.show(); 77 | } 78 | break; 79 | case PIC_MATCH: 80 | JSONArray jsonArray = json.getJSONObject("result").getJSONArray("user_list"); 81 | int size = jsonArray.length(); 82 | if (size == 0) { 83 | Toast toast = Toast.makeText(SurfaceViewCallback.getInstacne().context, "人脸识别失败0,请再次尝试开门", Toast.LENGTH_SHORT); 84 | toast.setGravity(Gravity.CENTER, 0, 0); 85 | toast.show(); 86 | } else { 87 | double score = ((JSONObject) jsonArray.get(0)).getDouble("score"); 88 | if (score > PASS_SCORE) { 89 | Toast toast = Toast.makeText(SurfaceViewCallback.getInstacne().context, "人脸识别成功,门已开", Toast.LENGTH_SHORT); 90 | toast.setGravity(Gravity.CENTER, 0, 0); 91 | toast.show(); 92 | } else { 93 | Toast toast = Toast.makeText(SurfaceViewCallback.getInstacne().context, "人脸识别失败1,请再次尝试开门" + Double.toString(score), Toast.LENGTH_SHORT); 94 | toast.setGravity(Gravity.CENTER, 0, 0); 95 | toast.show(); 96 | } 97 | } 98 | break; 99 | case NET_ERROR: 100 | Toast toast = Toast.makeText(SurfaceViewCallback.getInstacne().context, "网络异常", Toast.LENGTH_SHORT); 101 | toast.setGravity(Gravity.CENTER, 0, 0); 102 | toast.show(); 103 | break; 104 | } 105 | } catch (Exception e) { 106 | 107 | } 108 | } 109 | }; 110 | } 111 | 112 | public static ApiFaceSample getInstance() { 113 | if (_instance == null) 114 | _instance = new ApiFaceSample(); 115 | 116 | return _instance; 117 | } 118 | 119 | public void faceverify(final String base64) { 120 | 121 | new Thread(new Runnable() { 122 | @Override 123 | public void run() { 124 | String image = base64; 125 | FaceVerifyRequest req = new FaceVerifyRequest(image, "BASE64"); 126 | ArrayList list = new ArrayList(); 127 | list.add(req); 128 | JSONObject res = mClient.faceverify(list); 129 | 130 | try { 131 | if (res.getString("error_code") == "SDK108") { 132 | Message msg = Message.obtain(); 133 | msg.what = NET_ERROR; 134 | msg.obj = res; 135 | mHandler.sendMessage(msg); 136 | } 137 | System.out.println(res.toString()); 138 | } catch (JSONException e) { 139 | e.printStackTrace(); 140 | } 141 | 142 | 143 | Message msg = Message.obtain(); 144 | msg.what = PIC_ALIVE; 145 | msg.obj = res; 146 | mHandler.sendMessage(msg); 147 | } 148 | }).start(); 149 | } 150 | 151 | public void register(final String base64, final String user_id) { 152 | 153 | 154 | new Thread(new Runnable() { 155 | @Override 156 | public void run() { 157 | 158 | // debug 159 | // 传入可选参数调用接口 160 | HashMap options0 = new HashMap(); 161 | String groupId0 = "facegroup"; 162 | String userId0 = user_id; 163 | // 删除用户 164 | JSONObject res0 = mClient.deleteUser(groupId0, userId0, options0); 165 | 166 | 167 | // 传入可选参数调用接口 168 | HashMap options1 = new HashMap(); 169 | // 用户信息查询 170 | JSONObject res1 = mClient.getUser(userId0, groupId0, options1); 171 | 172 | 173 | // 获取用户人脸列表 174 | JSONObject res2 = mClient.faceGetlist(userId0, groupId0, options1); 175 | 176 | // 获取用户列表 177 | JSONObject res3 = mClient.getGroupUsers(groupId0, options1); 178 | // debug 179 | 180 | 181 | // 传入可选参数调用接口 182 | HashMap options = new HashMap(); 183 | options.put("user_info", "user's info"); 184 | options.put("quality_control", "NORMAL"); 185 | options.put("liveness_control", "LOW"); 186 | 187 | String image = base64; 188 | String imageType = "BASE64"; 189 | String groupId = "facegroup"; 190 | String userId = user_id; 191 | 192 | // 人脸注册 193 | JSONObject res = mClient.addUser(image, imageType, groupId, userId, options); 194 | 195 | Message msg = Message.obtain(); 196 | msg.what = FACE_REGISTER; 197 | msg.obj = res; 198 | mHandler.sendMessage(msg); 199 | } 200 | }).start(); 201 | } 202 | 203 | public void match(final String base64, final String userId) { 204 | new Thread(new Runnable() { 205 | @Override 206 | public void run() { 207 | // 传入可选参数调用接口 208 | HashMap options = new HashMap(); 209 | options.put("quality_control", "NORMAL"); 210 | options.put("liveness_control", "LOW"); 211 | options.put("user_id", userId); 212 | options.put("max_user_num", "1"); 213 | 214 | String image = base64; 215 | String imageType = "BASE64"; 216 | String groupIdList = "facegroup"; 217 | 218 | // 人脸搜索 219 | JSONObject res = mClient.search(image, imageType, groupIdList, options); 220 | 221 | Message msg = Message.obtain(); 222 | msg.what = PIC_MATCH; 223 | msg.obj = res; 224 | mHandler.sendMessage(msg); 225 | } 226 | }).start(); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /app/src/main/java/com/frontcamera/CameraSurfaceHolder.java: -------------------------------------------------------------------------------- 1 | package com.frontcamera; 2 | 3 | import android.content.Context; 4 | import android.view.SurfaceHolder; 5 | import android.view.SurfaceView; 6 | 7 | /** 8 | * Created by zhousong on 2016/9/18. 9 | * 相机界面SurfaceView的Holder类 10 | */ 11 | public class CameraSurfaceHolder { 12 | Context context; 13 | SurfaceHolder surfaceHolder; 14 | SurfaceView surfaceView; 15 | SurfaceViewCallback callback = SurfaceViewCallback.getInstacne(); 16 | 17 | /** 18 | * 设置相机界面SurfaceView的Holder 19 | * @param context 从相机所在的Activity传入的context 20 | * @param surfaceView Holder所绑定的响应的SurfaceView 21 | * */ 22 | public void setCameraSurfaceHolder(Context context, SurfaceView surfaceView) { 23 | this.context = context; 24 | this.surfaceView = surfaceView; 25 | surfaceHolder = surfaceView.getHolder(); 26 | surfaceHolder.addCallback(callback); 27 | surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 28 | callback.setContext(context); 29 | } 30 | 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/frontcamera/FaceTask.java: -------------------------------------------------------------------------------- 1 | package com.frontcamera; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.graphics.Rect; 6 | import android.graphics.YuvImage; 7 | import android.hardware.Camera; 8 | import android.os.AsyncTask; 9 | import android.util.Log; 10 | 11 | import java.io.ByteArrayOutputStream; 12 | 13 | /** 14 | * Created by zhousong on 2016/9/28. 15 | * 单独的任务类。继承AsyncTask,来处理从相机实时获取的耗时操作 16 | */ 17 | public class FaceTask extends AsyncTask{ 18 | private byte[] mData; 19 | Camera mCamera; 20 | private static final String TAG = "CameraTag"; 21 | //构造函数 22 | FaceTask(byte[] data , Camera camera) 23 | { 24 | this.mData = data; 25 | this.mCamera = camera; 26 | 27 | } 28 | @Override 29 | protected Object doInBackground(Object[] params) { 30 | Camera.Parameters parameters = mCamera.getParameters(); 31 | int imageFormat = parameters.getPreviewFormat(); 32 | int w = parameters.getPreviewSize().width; 33 | int h = parameters.getPreviewSize().height; 34 | 35 | Rect rect = new Rect(0, 0, w, h); 36 | YuvImage yuvImg = new YuvImage(mData, imageFormat, w, h, null); 37 | try { 38 | ByteArrayOutputStream outputstream = new ByteArrayOutputStream(); 39 | yuvImg.compressToJpeg(rect, 100, outputstream); 40 | Bitmap rawbitmap = BitmapFactory.decodeByteArray(outputstream.toByteArray(), 0, outputstream.size()); 41 | Log.i(TAG, "onPreviewFrame: rawbitmap:" + rawbitmap.toString()); 42 | 43 | String currentBase64 = SurfaceViewCallback.bitmapToBase64(rawbitmap); 44 | SurfaceViewCallback.getInstacne().setmCurrentFrame64(currentBase64); 45 | SurfaceViewCallback.getInstacne().addFrameToQueue(currentBase64); 46 | 47 | //若要存储可以用下列代码,格式为jpg 48 | /* BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/fp.jpg")); 49 | img.compressToJpeg(rect, 100, bos); 50 | bos.flush(); 51 | bos.close(); 52 | mCamera.startPreview(); 53 | */ 54 | } 55 | catch (Exception e) 56 | { 57 | Log.e(TAG, "onPreviewFrame: 获取相机实时数据失败" + e.getLocalizedMessage()); 58 | } 59 | return null; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/frontcamera/FrontCamera.java: -------------------------------------------------------------------------------- 1 | package com.frontcamera; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.hardware.Camera; 7 | import android.util.Log; 8 | import android.view.Surface; 9 | 10 | /** 11 | * Created by zhousong on 2016/9/18. 12 | * 相机类,相机的调用 13 | */ 14 | public class FrontCamera { 15 | static final String TAG = "Camera"; 16 | Camera mCamera; 17 | int mCurrentCamIndex = 0; 18 | boolean previewing; 19 | 20 | public void setCamera(Camera camera) 21 | { 22 | this.mCamera = camera; 23 | } 24 | 25 | public int getCurrentCamIndex() 26 | { 27 | return this.mCurrentCamIndex; 28 | } 29 | 30 | public boolean getPreviewing() 31 | { 32 | return this.previewing; 33 | } 34 | 35 | Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() { 36 | @Override 37 | public void onShutter() { 38 | 39 | } 40 | }; 41 | 42 | Camera.PictureCallback rawPictureCallback = new Camera.PictureCallback() { 43 | @Override 44 | public void onPictureTaken(byte[] data, Camera camera) { 45 | 46 | } 47 | }; 48 | 49 | Camera.PictureCallback jpegPictureCallback = new Camera.PictureCallback() { 50 | @Override 51 | public void onPictureTaken(byte[] data, Camera camera) { 52 | Bitmap bitmap = null; 53 | bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); 54 | Log.i(TAG, "已经获取了bitmap:" + bitmap.toString()); 55 | previewing = false; 56 | //需要保存可执行下面 57 | /* new Thread(new Runnable() { 58 | @Override 59 | public void run() { 60 | String filePath = ImageUtil.getSaveImgePath(); 61 | File file = new File(filePath); 62 | FileOutputStream fos = null; 63 | try { 64 | fos = new FileOutputStream(file, true); 65 | fos.write(data); 66 | ImageUtil.saveImage(file, data, filePath); 67 | fos.close(); 68 | 69 | } catch (Exception e) { 70 | e.printStackTrace(); 71 | } 72 | 73 | } 74 | }).start();*/ 75 | try { 76 | Thread.sleep(2000); 77 | } catch (InterruptedException e) { 78 | e.printStackTrace(); 79 | } 80 | mCamera.startPreview();//重新开启预览 ,不然不能继续拍照 81 | previewing = true; 82 | } 83 | 84 | 85 | }; 86 | 87 | //初始化相机 88 | public Camera initCamera() { 89 | int cameraCount = 0; 90 | Camera cam = null; 91 | Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); 92 | cameraCount = Camera.getNumberOfCameras(); 93 | previewing = true; 94 | 95 | for (int camIdx = 0; camIdx < cameraCount; camIdx++) { 96 | Camera.getCameraInfo(camIdx, cameraInfo); 97 | //在这里打开的是前置摄像头,可修改打开后置OR前置 98 | if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 99 | try { 100 | cam = Camera.open(camIdx); 101 | mCurrentCamIndex = camIdx; 102 | } catch (RuntimeException e) { 103 | Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage()); 104 | } 105 | } 106 | } 107 | return cam; 108 | } 109 | 110 | /** 111 | * 停止相机 112 | * @param mCamera 需要停止的相机对象 113 | * */ 114 | public void StopCamera(Camera mCamera) { 115 | mCamera.setPreviewCallback(null); 116 | mCamera.stopPreview(); 117 | mCamera.release(); 118 | mCamera = null; 119 | previewing = false; 120 | } 121 | 122 | /** 123 | * 旋转屏幕后自动适配(若只用到竖的,也可不要) 124 | * 已经在manifests中让此Activity只能竖屏了 125 | * @param activity 相机显示在的Activity 126 | * @param cameraId 相机的ID 127 | * @param camera 相机对象 128 | */ 129 | public static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) 130 | { 131 | Camera.CameraInfo info = new Camera.CameraInfo(); 132 | Camera.getCameraInfo(cameraId, info); 133 | int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 134 | int degrees = 0; 135 | switch (rotation) 136 | { 137 | case Surface.ROTATION_0: degrees = 0; break; 138 | case Surface.ROTATION_90: degrees = 90; break; 139 | case Surface.ROTATION_180: degrees = 180; break; 140 | case Surface.ROTATION_270: degrees = 270; break; 141 | } 142 | int result; 143 | if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) 144 | { 145 | result = (info.orientation + degrees) % 360; 146 | result = (360 - result) % 360; // compensate the mirror 147 | } 148 | else 149 | { 150 | // back-facing 151 | result = (info.orientation - degrees + 360) % 360; 152 | } 153 | camera.setDisplayOrientation(result); 154 | } 155 | 156 | } 157 | -------------------------------------------------------------------------------- /app/src/main/java/com/frontcamera/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.frontcamera; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.view.SurfaceView; 7 | import android.widget.Button; 8 | 9 | 10 | 11 | public class MainActivity extends Activity { 12 | Context context = MainActivity.this; 13 | SurfaceView surfaceView; 14 | CameraSurfaceHolder mCameraSurfaceHolder = new CameraSurfaceHolder(); 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | initView(); 20 | } 21 | 22 | public void initView() 23 | { 24 | setContentView(R.layout.activity_main); 25 | surfaceView = (SurfaceView) findViewById(R.id.surfaceView1); 26 | mCameraSurfaceHolder.setCameraSurfaceHolder(context,surfaceView); 27 | 28 | Button openDoorButton = (Button)findViewById(R.id.openDoorButton); 29 | openDoorButton.setOnClickListener(OpenDoorListener.getInstance()); 30 | 31 | Button RegisterDoorButton = (Button)findViewById(R.id.registerDoorButton); 32 | RegisterDoorButton.setOnClickListener(RegisterDoorButtonListener.getInstance()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/frontcamera/OpenDoorListener.java: -------------------------------------------------------------------------------- 1 | package com.frontcamera; 2 | 3 | import android.view.Gravity; 4 | import android.view.View; 5 | import android.widget.Button; 6 | import android.widget.Toast; 7 | 8 | public class OpenDoorListener implements Button.OnClickListener { 9 | private static OpenDoorListener _instance; 10 | 11 | // 通过 surfaceViewCallBack 来获取最近的图像帧 12 | private SurfaceViewCallback surfaceViewCallBack; 13 | private OpenDoorListener(){ 14 | super(); 15 | } 16 | 17 | public static OpenDoorListener getInstance(){ 18 | if (_instance != null) 19 | return _instance; 20 | else{ 21 | _instance = new OpenDoorListener(); 22 | return _instance; 23 | } 24 | } 25 | 26 | public void rigsterSurfaceViewCallback(SurfaceViewCallback callback){ 27 | surfaceViewCallBack = callback; 28 | } 29 | @Override 30 | public void onClick(View v){ 31 | Toast toast = Toast.makeText(v.getContext(),"开门中……",Toast.LENGTH_SHORT); 32 | toast.setGravity(Gravity.CENTER, 0, 0); 33 | toast.show(); 34 | 35 | ApiFaceSample.getInstance().faceverify(SurfaceViewCallback.getInstacne().mCurrentFrame64); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/frontcamera/RegisterDoorButtonListener.java: -------------------------------------------------------------------------------- 1 | package com.frontcamera; 2 | 3 | import android.view.Gravity; 4 | import android.view.View; 5 | import android.widget.Button; 6 | import android.widget.Toast; 7 | 8 | public class RegisterDoorButtonListener implements Button.OnClickListener { 9 | private static RegisterDoorButtonListener _instance; 10 | 11 | // 通过 surfaceViewCallBack 来获取最近的图像帧 12 | private SurfaceViewCallback surfaceViewCallBack; 13 | private RegisterDoorButtonListener(){ 14 | super(); 15 | } 16 | 17 | public static RegisterDoorButtonListener getInstance(){ 18 | if (_instance == null) 19 | _instance = new RegisterDoorButtonListener(); 20 | 21 | return _instance; 22 | } 23 | 24 | public void rigsterSurfaceViewCallback(SurfaceViewCallback callback){ 25 | surfaceViewCallBack = callback; 26 | } 27 | @Override 28 | public void onClick(View v){ 29 | Toast toast = Toast.makeText(v.getContext(),"注册中……",Toast.LENGTH_SHORT); 30 | toast.setGravity(Gravity.CENTER, 0, 0); 31 | toast.show(); 32 | 33 | ApiFaceSample.getInstance().register(SurfaceViewCallback.getInstacne().mCurrentFrame64,"anon"); 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/frontcamera/SurfaceViewCallback.java: -------------------------------------------------------------------------------- 1 | package com.frontcamera; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.content.Intent; 7 | import android.graphics.Bitmap; 8 | import android.graphics.BitmapFactory; 9 | import android.hardware.Camera; 10 | import android.os.Handler; 11 | import android.os.Message; 12 | import android.util.Base64; 13 | import android.util.Log; 14 | import android.view.SurfaceHolder; 15 | 16 | import java.io.ByteArrayOutputStream; 17 | import java.io.IOException; 18 | import java.util.ArrayList; 19 | import java.util.LinkedList; 20 | import java.util.List; 21 | import java.util.Queue; 22 | 23 | 24 | /** 25 | * Created by zhousong on 2016/9/19. 26 | * 相机界面SurfaceView的回调类 27 | */ 28 | public final class SurfaceViewCallback implements android.view.SurfaceHolder.Callback, Camera.PreviewCallback { 29 | 30 | // 每隔多少毫秒缓存一张照片 31 | static final int mInterval = 300; 32 | // 一共缓存多少张照片 33 | static final int mPhotoCount = 5; 34 | 35 | static SurfaceViewCallback _instance; 36 | Long mLastTime = new Long(0); 37 | 38 | public Queue getmFramesBase64() { 39 | return mFramesBase64; 40 | } 41 | 42 | public void setmFramesBase64(Queue mFramesBase64) { 43 | this.mFramesBase64 = mFramesBase64; 44 | } 45 | 46 | public String getmCurrentFrame64() { 47 | return mCurrentFrame64; 48 | } 49 | 50 | public void setmCurrentFrame64(String mCurrentFrame64) { 51 | this.mCurrentFrame64 = mCurrentFrame64; 52 | } 53 | 54 | Queue mFramesBase64 = new LinkedList<>(); 55 | String mCurrentFrame64; 56 | 57 | 58 | 59 | Context context; 60 | static final String TAG = "Camera"; 61 | FrontCamera mFrontCamera = new FrontCamera(); 62 | boolean previewing = mFrontCamera.getPreviewing(); 63 | Camera mCamera; 64 | FaceTask mFaceTask; 65 | 66 | public static SurfaceViewCallback getInstacne() { 67 | if (_instance != null) 68 | return _instance; 69 | else { 70 | _instance = new SurfaceViewCallback(); 71 | return _instance; 72 | } 73 | } 74 | 75 | private SurfaceViewCallback() { 76 | super(); 77 | } 78 | 79 | public void setContext(Context context) { 80 | this.context = context; 81 | } 82 | 83 | public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 84 | if (previewing) { 85 | mCamera.stopPreview(); 86 | Log.i(TAG, "停止预览"); 87 | } 88 | 89 | try { 90 | mCamera.setPreviewDisplay(arg0); 91 | mCamera.startPreview(); 92 | mCamera.setPreviewCallback(this); 93 | Log.i(TAG, "开始预览"); 94 | 95 | OpenDoorListener.getInstance().rigsterSurfaceViewCallback(this); 96 | //调用旋转屏幕时自适应 97 | //setCameraDisplayOrientation(MainActivity.this, mCurrentCamIndex, mCamera); 98 | } catch (Exception e) { 99 | } 100 | } 101 | 102 | public void surfaceCreated(SurfaceHolder holder) { 103 | //初始化前置摄像头 104 | mFrontCamera.setCamera(mCamera); 105 | mCamera = mFrontCamera.initCamera(); 106 | mCamera.setPreviewCallback(this); 107 | //适配竖排固定角度 108 | Log.i(TAG, "context: " + context.toString()); 109 | Log.i(TAG, "mFrontCamera: " + mFrontCamera.toString()); 110 | Log.i(TAG, "mCamera: " + mCamera.toString()); 111 | FrontCamera.setCameraDisplayOrientation((Activity) context, mFrontCamera.getCurrentCamIndex(), mCamera); 112 | } 113 | 114 | public void surfaceDestroyed(SurfaceHolder holder) { 115 | mFrontCamera.StopCamera(mCamera); 116 | } 117 | 118 | /** 119 | * 相机实时数据的回调 120 | * 121 | * @param data 相机获取的数据,格式是YUV 122 | * @param camera 相应相机的对象 123 | */ 124 | @Override 125 | public void onPreviewFrame(byte[] data, Camera camera) { 126 | 127 | 128 | 129 | if (mFaceTask != null) { 130 | switch (mFaceTask.getStatus()) { 131 | case RUNNING: 132 | return; 133 | case PENDING: 134 | mFaceTask.cancel(false); 135 | break; 136 | } 137 | 138 | } 139 | mFaceTask = new FaceTask(data, camera); 140 | mFaceTask.execute((Void) null); 141 | //Log.i(TAG, "onPreviewFrame: 启动了Task"); 142 | 143 | } 144 | /** 145 | * 把当前帧选择性的加入到存储容器里 146 | * 147 | * @param data64 相机获取的数据 148 | */ 149 | public void addFrameToQueue(String data64){ 150 | Long nowTime = System.currentTimeMillis(); 151 | if (nowTime - mLastTime > mInterval){ 152 | if (mFramesBase64.size() >= mPhotoCount) 153 | mFramesBase64.remove(); 154 | 155 | mFramesBase64.add(data64); 156 | mLastTime = nowTime; 157 | } 158 | } 159 | 160 | 161 | // 162 | // private void alertText(final String title, final String message) { 163 | // this.runOnUiThread(new Runnable() { 164 | // @Override 165 | // public void run() { 166 | // alertDialog.setTitle(title) 167 | // .setMessage(message) 168 | // .setPositiveButton("确定", new DialogInterface.OnClickListener() { 169 | // @Override 170 | // public void onClick(DialogInterface dialog, int which) { 171 | // 172 | // Intent intent = new Intent(); 173 | // intent.putExtra("bestimage_path", bestImagePath); 174 | // setResult(Activity.RESULT_OK, intent); 175 | // finish(); 176 | // } 177 | // }) 178 | // .show(); 179 | // } 180 | // }); 181 | // } 182 | 183 | 184 | /** 185 | * cai hua shuai 186 | * bitmap转为base64 187 | * @param bitmap 188 | * @return 189 | */ 190 | public static String bitmapToBase64(Bitmap bitmap) { 191 | 192 | String result = null; 193 | ByteArrayOutputStream baos = null; 194 | try { 195 | if (bitmap != null) { 196 | baos = new ByteArrayOutputStream(); 197 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); 198 | 199 | baos.flush(); 200 | baos.close(); 201 | 202 | byte[] bitmapBytes = baos.toByteArray(); 203 | result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT); 204 | } 205 | } catch (IOException e) { 206 | e.printStackTrace(); 207 | } finally { 208 | try { 209 | if (baos != null) { 210 | baos.flush(); 211 | baos.close(); 212 | } 213 | } catch (IOException e) { 214 | e.printStackTrace(); 215 | } 216 | } 217 | return result; 218 | } 219 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 18 | 19 | 20 |