|
@@ -0,0 +1,780 @@
|
|
|
+package com.cjt2325.cameralibrary;
|
|
|
+
|
|
|
+import android.animation.AnimatorSet;
|
|
|
+import android.animation.ObjectAnimator;
|
|
|
+import android.content.Context;
|
|
|
+import android.graphics.Bitmap;
|
|
|
+import android.graphics.BitmapFactory;
|
|
|
+import android.graphics.ImageFormat;
|
|
|
+import android.graphics.Matrix;
|
|
|
+import android.graphics.Rect;
|
|
|
+import android.graphics.RectF;
|
|
|
+import android.graphics.YuvImage;
|
|
|
+import android.hardware.Camera;
|
|
|
+import android.hardware.Sensor;
|
|
|
+import android.hardware.SensorEvent;
|
|
|
+import android.hardware.SensorEventListener;
|
|
|
+import android.hardware.SensorManager;
|
|
|
+import android.media.MediaRecorder;
|
|
|
+import android.os.Build;
|
|
|
+import android.os.Environment;
|
|
|
+import android.util.Log;
|
|
|
+import android.view.Surface;
|
|
|
+import android.view.SurfaceHolder;
|
|
|
+import android.widget.ImageView;
|
|
|
+
|
|
|
+import com.cjt2325.cameralibrary.listener.ErrorListener;
|
|
|
+import com.cjt2325.cameralibrary.util.AngleUtil;
|
|
|
+import com.cjt2325.cameralibrary.util.CameraParamUtil;
|
|
|
+import com.cjt2325.cameralibrary.util.CheckPermission;
|
|
|
+import com.cjt2325.cameralibrary.util.DeviceUtil;
|
|
|
+import com.cjt2325.cameralibrary.util.FileUtil;
|
|
|
+import com.cjt2325.cameralibrary.util.LogUtil;
|
|
|
+import com.cjt2325.cameralibrary.util.ScreenUtils;
|
|
|
+
|
|
|
+import java.io.ByteArrayOutputStream;
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+import static android.graphics.Bitmap.createBitmap;
|
|
|
+
|
|
|
+/**
|
|
|
+ * =====================================
|
|
|
+ * 作 者: 陈嘉桐
|
|
|
+ * 版 本:1.1.4
|
|
|
+ * 创建日期:2017/4/25
|
|
|
+ * 描 述:camera操作单例
|
|
|
+ * =====================================
|
|
|
+ */
|
|
|
+@SuppressWarnings("deprecation")
|
|
|
+public class CameraInterface implements Camera.PreviewCallback {
|
|
|
+
|
|
|
+ private static final String TAG = "CJT";
|
|
|
+
|
|
|
+ private volatile static CameraInterface mCameraInterface;
|
|
|
+
|
|
|
+ public static void destroyCameraInterface() {
|
|
|
+ if (mCameraInterface != null) {
|
|
|
+ mCameraInterface = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Camera mCamera;
|
|
|
+ private Camera.Parameters mParams;
|
|
|
+ private boolean isPreviewing = false;
|
|
|
+
|
|
|
+ private int SELECTED_CAMERA = -1;
|
|
|
+ private int CAMERA_POST_POSITION = -1;
|
|
|
+ private int CAMERA_FRONT_POSITION = -1;
|
|
|
+
|
|
|
+ private SurfaceHolder mHolder = null;
|
|
|
+ private float screenProp = -1.0f;
|
|
|
+
|
|
|
+ private boolean isRecorder = false;
|
|
|
+ private MediaRecorder mediaRecorder;
|
|
|
+ private String videoFileName;
|
|
|
+ private String saveVideoPath;
|
|
|
+ private String videoFileAbsPath;
|
|
|
+ private Bitmap videoFirstFrame = null;
|
|
|
+
|
|
|
+ private ErrorListener errorLisenter;
|
|
|
+
|
|
|
+ private ImageView mSwitchView;
|
|
|
+ private ImageView mFlashLamp;
|
|
|
+
|
|
|
+ private int preview_width;
|
|
|
+ private int preview_height;
|
|
|
+
|
|
|
+ private int angle = 0;
|
|
|
+ private int cameraAngle = 90;//摄像头角度 默认为90度
|
|
|
+ private int rotation = 0;
|
|
|
+ private byte[] firstFrame_data;
|
|
|
+
|
|
|
+ public static final int TYPE_RECORDER = 0x090;
|
|
|
+ public static final int TYPE_CAPTURE = 0x091;
|
|
|
+ private int nowScaleRate = 0;
|
|
|
+ private int recordScleRate = 0;
|
|
|
+
|
|
|
+ //视频质量
|
|
|
+ private int mediaQuality = JCameraView.MEDIA_QUALITY_MIDDLE;
|
|
|
+ private SensorManager sm = null;
|
|
|
+
|
|
|
+ //获取CameraInterface单例
|
|
|
+ public static synchronized CameraInterface getInstance() {
|
|
|
+ if (mCameraInterface == null)
|
|
|
+ synchronized (CameraInterface.class) {
|
|
|
+ if (mCameraInterface == null)
|
|
|
+ mCameraInterface = new CameraInterface();
|
|
|
+ }
|
|
|
+ return mCameraInterface;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setSwitchView(ImageView mSwitchView, ImageView mFlashLamp) {
|
|
|
+ this.mSwitchView = mSwitchView;
|
|
|
+ this.mFlashLamp = mFlashLamp;
|
|
|
+ if (mSwitchView != null) {
|
|
|
+ cameraAngle = CameraParamUtil.getInstance().getCameraDisplayOrientation(mSwitchView.getContext(),
|
|
|
+ SELECTED_CAMERA);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private SensorEventListener sensorEventListener = new SensorEventListener() {
|
|
|
+ public void onSensorChanged(SensorEvent event) {
|
|
|
+ if (Sensor.TYPE_ACCELEROMETER != event.sensor.getType()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ float[] values = event.values;
|
|
|
+ angle = AngleUtil.getSensorAngle(values[0], values[1]);
|
|
|
+ rotationAnimation();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ //切换摄像头icon跟随手机角度进行旋转
|
|
|
+ private void rotationAnimation() {
|
|
|
+ if (mSwitchView == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (rotation != angle) {
|
|
|
+ int start_rotaion = 0;
|
|
|
+ int end_rotation = 0;
|
|
|
+ switch (rotation) {
|
|
|
+ case 0:
|
|
|
+ start_rotaion = 0;
|
|
|
+ switch (angle) {
|
|
|
+ case 90:
|
|
|
+ end_rotation = -90;
|
|
|
+ break;
|
|
|
+ case 270:
|
|
|
+ end_rotation = 90;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 90:
|
|
|
+ start_rotaion = -90;
|
|
|
+ switch (angle) {
|
|
|
+ case 0:
|
|
|
+ end_rotation = 0;
|
|
|
+ break;
|
|
|
+ case 180:
|
|
|
+ end_rotation = -180;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 180:
|
|
|
+ start_rotaion = 180;
|
|
|
+ switch (angle) {
|
|
|
+ case 90:
|
|
|
+ end_rotation = 270;
|
|
|
+ break;
|
|
|
+ case 270:
|
|
|
+ end_rotation = 90;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 270:
|
|
|
+ start_rotaion = 90;
|
|
|
+ switch (angle) {
|
|
|
+ case 0:
|
|
|
+ end_rotation = 0;
|
|
|
+ break;
|
|
|
+ case 180:
|
|
|
+ end_rotation = 180;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ ObjectAnimator animC = ObjectAnimator.ofFloat(mSwitchView, "rotation", start_rotaion, end_rotation);
|
|
|
+ ObjectAnimator animF = ObjectAnimator.ofFloat(mFlashLamp, "rotation", start_rotaion, end_rotation);
|
|
|
+ AnimatorSet set = new AnimatorSet();
|
|
|
+ set.playTogether(animC, animF);
|
|
|
+ set.setDuration(500);
|
|
|
+ set.start();
|
|
|
+ rotation = angle;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("ResultOfMethodCallIgnored")
|
|
|
+ void setSaveVideoPath(String saveVideoPath) {
|
|
|
+ this.saveVideoPath = saveVideoPath;
|
|
|
+ File file = new File(saveVideoPath);
|
|
|
+ if (!file.exists()) {
|
|
|
+ file.mkdirs();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void setZoom(float zoom, int type) {
|
|
|
+ if (mCamera == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (mParams == null) {
|
|
|
+ mParams = mCamera.getParameters();
|
|
|
+ }
|
|
|
+ if (!mParams.isZoomSupported() || !mParams.isSmoothZoomSupported()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch (type) {
|
|
|
+ case TYPE_RECORDER:
|
|
|
+ //如果不是录制视频中,上滑不会缩放
|
|
|
+ if (!isRecorder) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (zoom >= 0) {
|
|
|
+ //每移动50个像素缩放一个级别
|
|
|
+ int scaleRate = (int) (zoom / 40);
|
|
|
+ if (scaleRate <= mParams.getMaxZoom() && scaleRate >= nowScaleRate && recordScleRate != scaleRate) {
|
|
|
+ mParams.setZoom(scaleRate);
|
|
|
+ mCamera.setParameters(mParams);
|
|
|
+ recordScleRate = scaleRate;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case TYPE_CAPTURE:
|
|
|
+ if (isRecorder) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //每移动50个像素缩放一个级别
|
|
|
+ int scaleRate = (int) (zoom / 50);
|
|
|
+ if (scaleRate < mParams.getMaxZoom()) {
|
|
|
+ nowScaleRate += scaleRate;
|
|
|
+ if (nowScaleRate < 0) {
|
|
|
+ nowScaleRate = 0;
|
|
|
+ } else if (nowScaleRate > mParams.getMaxZoom()) {
|
|
|
+ nowScaleRate = mParams.getMaxZoom();
|
|
|
+ }
|
|
|
+ mParams.setZoom(nowScaleRate);
|
|
|
+ mCamera.setParameters(mParams);
|
|
|
+ }
|
|
|
+ LogUtil.i("setZoom = " + nowScaleRate);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ void setMediaQuality(int quality) {
|
|
|
+ this.mediaQuality = quality;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onPreviewFrame(byte[] data, Camera camera) {
|
|
|
+ firstFrame_data = data;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setFlashMode(String flashMode) {
|
|
|
+ if (mCamera == null)
|
|
|
+ return;
|
|
|
+ Camera.Parameters params = mCamera.getParameters();
|
|
|
+ params.setFlashMode(flashMode);
|
|
|
+ mCamera.setParameters(params);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public interface CameraOpenOverCallback {
|
|
|
+ void cameraHasOpened();
|
|
|
+ }
|
|
|
+
|
|
|
+ private CameraInterface() {
|
|
|
+ findAvailableCameras();
|
|
|
+ SELECTED_CAMERA = CAMERA_POST_POSITION;
|
|
|
+ saveVideoPath = "";
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * open Camera
|
|
|
+ */
|
|
|
+ void doOpenCamera(CameraOpenOverCallback callback) {
|
|
|
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
|
+ if (!CheckPermission.isCameraUseable(SELECTED_CAMERA) && this.errorLisenter != null) {
|
|
|
+ this.errorLisenter.onError();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (mCamera == null) {
|
|
|
+ openCamera(SELECTED_CAMERA);
|
|
|
+ }
|
|
|
+ callback.cameraHasOpened();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setFlashModel() {
|
|
|
+ mParams = mCamera.getParameters();
|
|
|
+ mParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); //设置camera参数为Torch模式
|
|
|
+ mCamera.setParameters(mParams);
|
|
|
+ }
|
|
|
+
|
|
|
+ private synchronized void openCamera(int id) {
|
|
|
+ try {
|
|
|
+ this.mCamera = Camera.open(id);
|
|
|
+ } catch (Exception var3) {
|
|
|
+ var3.printStackTrace();
|
|
|
+ if (this.errorLisenter != null) {
|
|
|
+ this.errorLisenter.onError();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Build.VERSION.SDK_INT > 17 && this.mCamera != null) {
|
|
|
+ try {
|
|
|
+ this.mCamera.enableShutterSound(false);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ Log.e("CJT", "enable shutter sound faild");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized void switchCamera(SurfaceHolder holder, float screenProp) {
|
|
|
+ if (SELECTED_CAMERA == CAMERA_POST_POSITION) {
|
|
|
+ SELECTED_CAMERA = CAMERA_FRONT_POSITION;
|
|
|
+ } else {
|
|
|
+ SELECTED_CAMERA = CAMERA_POST_POSITION;
|
|
|
+ }
|
|
|
+ doDestroyCamera();
|
|
|
+ LogUtil.i("open start");
|
|
|
+ openCamera(SELECTED_CAMERA);
|
|
|
+// mCamera = Camera.open();
|
|
|
+ if (Build.VERSION.SDK_INT > 17 && this.mCamera != null) {
|
|
|
+ try {
|
|
|
+ this.mCamera.enableShutterSound(false);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ LogUtil.i("open end");
|
|
|
+ doStartPreview(holder, screenProp);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * doStartPreview
|
|
|
+ */
|
|
|
+ public void doStartPreview(SurfaceHolder holder, float screenProp) {
|
|
|
+ if (isPreviewing) {
|
|
|
+ LogUtil.i("doStartPreview isPreviewing");
|
|
|
+ }
|
|
|
+ if (this.screenProp < 0) {
|
|
|
+ this.screenProp = screenProp;
|
|
|
+ }
|
|
|
+ if (holder == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.mHolder = holder;
|
|
|
+ if (mCamera != null) {
|
|
|
+ try {
|
|
|
+ mParams = mCamera.getParameters();
|
|
|
+ Camera.Size previewSize = CameraParamUtil.getInstance().getPreviewSize(mParams
|
|
|
+ .getSupportedPreviewSizes(), 1000, screenProp);
|
|
|
+ Camera.Size pictureSize = CameraParamUtil.getInstance().getPictureSize(mParams
|
|
|
+ .getSupportedPictureSizes(), 1200, screenProp);
|
|
|
+
|
|
|
+ mParams.setPreviewSize(previewSize.width, previewSize.height);
|
|
|
+
|
|
|
+ preview_width = previewSize.width;
|
|
|
+ preview_height = previewSize.height;
|
|
|
+
|
|
|
+ mParams.setPictureSize(pictureSize.width, pictureSize.height);
|
|
|
+
|
|
|
+ if (CameraParamUtil.getInstance().isSupportedFocusMode(
|
|
|
+ mParams.getSupportedFocusModes(),
|
|
|
+ Camera.Parameters.FOCUS_MODE_AUTO)) {
|
|
|
+ mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
|
|
+ }
|
|
|
+ if (CameraParamUtil.getInstance().isSupportedPictureFormats(mParams.getSupportedPictureFormats(),
|
|
|
+ ImageFormat.JPEG)) {
|
|
|
+ mParams.setPictureFormat(ImageFormat.JPEG);
|
|
|
+ mParams.setJpegQuality(100);
|
|
|
+ }
|
|
|
+ mCamera.setParameters(mParams);
|
|
|
+ mParams = mCamera.getParameters();
|
|
|
+ mCamera.setPreviewDisplay(holder); //SurfaceView
|
|
|
+ mCamera.setDisplayOrientation(cameraAngle);//浏览角度
|
|
|
+ mCamera.setPreviewCallback(this); //每一帧回调
|
|
|
+ mCamera.startPreview();//启动浏览
|
|
|
+ isPreviewing = true;
|
|
|
+ Log.i(TAG, "=== Start Preview ===");
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 停止预览
|
|
|
+ */
|
|
|
+ public void doStopPreview() {
|
|
|
+ if (null != mCamera) {
|
|
|
+ try {
|
|
|
+ mCamera.setPreviewCallback(null);
|
|
|
+ mCamera.stopPreview();
|
|
|
+ //这句要在stopPreview后执行,不然会卡顿或者花屏
|
|
|
+ mCamera.setPreviewDisplay(null);
|
|
|
+ isPreviewing = false;
|
|
|
+ Log.i(TAG, "=== Stop Preview ===");
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 销毁Camera
|
|
|
+ */
|
|
|
+ void doDestroyCamera() {
|
|
|
+ errorLisenter = null;
|
|
|
+ if (null != mCamera) {
|
|
|
+ try {
|
|
|
+ mCamera.setPreviewCallback(null);
|
|
|
+ mSwitchView = null;
|
|
|
+ mFlashLamp = null;
|
|
|
+ mCamera.stopPreview();
|
|
|
+ //这句要在stopPreview后执行,不然会卡顿或者花屏
|
|
|
+ mCamera.setPreviewDisplay(null);
|
|
|
+ mHolder = null;
|
|
|
+ isPreviewing = false;
|
|
|
+ mCamera.release();
|
|
|
+ mCamera = null;
|
|
|
+// destroyCameraInterface();
|
|
|
+ Log.i(TAG, "=== Destroy Camera ===");
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Log.i(TAG, "=== Camera Null===");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 拍照
|
|
|
+ */
|
|
|
+ private int nowAngle;
|
|
|
+
|
|
|
+ public void takePicture(final TakePictureCallback callback) {
|
|
|
+ if (mCamera == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch (cameraAngle) {
|
|
|
+ case 90:
|
|
|
+ nowAngle = Math.abs(angle + cameraAngle) % 360;
|
|
|
+ break;
|
|
|
+ case 270:
|
|
|
+ nowAngle = Math.abs(cameraAngle - angle);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+//
|
|
|
+ Log.i("CJT", angle + " = " + cameraAngle + " = " + nowAngle);
|
|
|
+ mCamera.takePicture(null, null, new Camera.PictureCallback() {
|
|
|
+ @Override
|
|
|
+ public void onPictureTaken(byte[] data, Camera camera) {
|
|
|
+ Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
|
|
|
+ Matrix matrix = new Matrix();
|
|
|
+ if (SELECTED_CAMERA == CAMERA_POST_POSITION) {
|
|
|
+ matrix.setRotate(nowAngle);
|
|
|
+ } else if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
|
|
|
+ matrix.setRotate(360 - nowAngle);
|
|
|
+ matrix.postScale(-1, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ bitmap = createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
|
|
+ if (callback != null) {
|
|
|
+ if (nowAngle == 90 || nowAngle == 270) {
|
|
|
+ callback.captureResult(bitmap, true);
|
|
|
+ } else {
|
|
|
+ callback.captureResult(bitmap, false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ //启动录像
|
|
|
+ public void startRecord(Surface surface, float screenProp, ErrorCallback callback) {
|
|
|
+ mCamera.setPreviewCallback(null);
|
|
|
+ final int nowAngle = (angle + 90) % 360;
|
|
|
+ //获取第一帧图片
|
|
|
+ Camera.Parameters parameters = mCamera.getParameters();
|
|
|
+ int width = parameters.getPreviewSize().width;
|
|
|
+ int height = parameters.getPreviewSize().height;
|
|
|
+ YuvImage yuv = new YuvImage(firstFrame_data, parameters.getPreviewFormat(), width, height, null);
|
|
|
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
|
+ yuv.compressToJpeg(new Rect(0, 0, width, height), 50, out);
|
|
|
+ byte[] bytes = out.toByteArray();
|
|
|
+ videoFirstFrame = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
|
|
|
+ Matrix matrix = new Matrix();
|
|
|
+ if (SELECTED_CAMERA == CAMERA_POST_POSITION) {
|
|
|
+ matrix.setRotate(nowAngle);
|
|
|
+ } else if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
|
|
|
+ matrix.setRotate(270);
|
|
|
+ }
|
|
|
+ videoFirstFrame = createBitmap(videoFirstFrame, 0, 0, videoFirstFrame.getWidth(), videoFirstFrame
|
|
|
+ .getHeight(), matrix, true);
|
|
|
+
|
|
|
+ if (isRecorder) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (mCamera == null) {
|
|
|
+ openCamera(SELECTED_CAMERA);
|
|
|
+ }
|
|
|
+ if (mediaRecorder == null) {
|
|
|
+ mediaRecorder = new MediaRecorder();
|
|
|
+ }
|
|
|
+ if (mParams == null) {
|
|
|
+ mParams = mCamera.getParameters();
|
|
|
+ }
|
|
|
+ List<String> focusModes = mParams.getSupportedFocusModes();
|
|
|
+ if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
|
|
|
+ mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
|
|
|
+ }
|
|
|
+ mCamera.setParameters(mParams);
|
|
|
+ mCamera.unlock();
|
|
|
+ mediaRecorder.reset();
|
|
|
+ mediaRecorder.setCamera(mCamera);
|
|
|
+ mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
|
|
|
+
|
|
|
+ mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
|
|
|
+
|
|
|
+ mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
|
|
|
+ mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
|
|
|
+ mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
|
|
|
+
|
|
|
+
|
|
|
+ Camera.Size videoSize;
|
|
|
+ if (mParams.getSupportedVideoSizes() == null) {
|
|
|
+ videoSize = CameraParamUtil.getInstance().getPreviewSize(mParams.getSupportedPreviewSizes(), 600,
|
|
|
+ screenProp);
|
|
|
+ } else {
|
|
|
+ videoSize = CameraParamUtil.getInstance().getPreviewSize(mParams.getSupportedVideoSizes(), 600,
|
|
|
+ screenProp);
|
|
|
+ }
|
|
|
+ Log.i(TAG, "setVideoSize width = " + videoSize.width + "height = " + videoSize.height);
|
|
|
+ if (videoSize.width == videoSize.height) {
|
|
|
+ mediaRecorder.setVideoSize(preview_width, preview_height);
|
|
|
+ } else {
|
|
|
+ mediaRecorder.setVideoSize(videoSize.width, videoSize.height);
|
|
|
+ }
|
|
|
+// if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
|
|
|
+// mediaRecorder.setOrientationHint(270);
|
|
|
+// } else {
|
|
|
+// mediaRecorder.setOrientationHint(nowAngle);
|
|
|
+//// mediaRecorder.setOrientationHint(90);
|
|
|
+// }
|
|
|
+
|
|
|
+ if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
|
|
|
+ //手机预览倒立的处理
|
|
|
+ if (cameraAngle == 270) {
|
|
|
+ //横屏
|
|
|
+ if (nowAngle == 0) {
|
|
|
+ mediaRecorder.setOrientationHint(180);
|
|
|
+ } else if (nowAngle == 270) {
|
|
|
+ mediaRecorder.setOrientationHint(270);
|
|
|
+ } else {
|
|
|
+ mediaRecorder.setOrientationHint(90);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (nowAngle == 90) {
|
|
|
+ mediaRecorder.setOrientationHint(270);
|
|
|
+ } else if (nowAngle == 270) {
|
|
|
+ mediaRecorder.setOrientationHint(90);
|
|
|
+ } else {
|
|
|
+ mediaRecorder.setOrientationHint(nowAngle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ mediaRecorder.setOrientationHint(nowAngle);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (DeviceUtil.isHuaWeiRongyao()) {
|
|
|
+ mediaRecorder.setVideoEncodingBitRate(4 * 100000);
|
|
|
+ } else {
|
|
|
+ mediaRecorder.setVideoEncodingBitRate(mediaQuality);
|
|
|
+ }
|
|
|
+ mediaRecorder.setPreviewDisplay(surface);
|
|
|
+
|
|
|
+ videoFileName = "video_" + System.currentTimeMillis() + ".mp4";
|
|
|
+ if (saveVideoPath.equals("")) {
|
|
|
+ saveVideoPath = Environment.getExternalStorageDirectory().getPath();
|
|
|
+ }
|
|
|
+ videoFileAbsPath = saveVideoPath + File.separator + videoFileName;
|
|
|
+ mediaRecorder.setOutputFile(videoFileAbsPath);
|
|
|
+ try {
|
|
|
+ mediaRecorder.prepare();
|
|
|
+ mediaRecorder.start();
|
|
|
+ isRecorder = true;
|
|
|
+ } catch (IllegalStateException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ Log.i("CJT", "startRecord IllegalStateException");
|
|
|
+ if (this.errorLisenter != null) {
|
|
|
+ this.errorLisenter.onError();
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ Log.i("CJT", "startRecord IOException");
|
|
|
+ if (this.errorLisenter != null) {
|
|
|
+ this.errorLisenter.onError();
|
|
|
+ }
|
|
|
+ } catch (RuntimeException e) {
|
|
|
+ Log.i("CJT", "startRecord RuntimeException");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //停止录像
|
|
|
+ public void stopRecord(boolean isShort, StopRecordCallback callback) {
|
|
|
+ if (!isRecorder) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (mediaRecorder != null) {
|
|
|
+ mediaRecorder.setOnErrorListener(null);
|
|
|
+ mediaRecorder.setOnInfoListener(null);
|
|
|
+ mediaRecorder.setPreviewDisplay(null);
|
|
|
+ try {
|
|
|
+ mediaRecorder.stop();
|
|
|
+ } catch (RuntimeException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ mediaRecorder = null;
|
|
|
+ mediaRecorder = new MediaRecorder();
|
|
|
+ } finally {
|
|
|
+ if (mediaRecorder != null) {
|
|
|
+ mediaRecorder.release();
|
|
|
+ }
|
|
|
+ mediaRecorder = null;
|
|
|
+ isRecorder = false;
|
|
|
+ }
|
|
|
+ if (isShort) {
|
|
|
+ if (FileUtil.deleteFile(videoFileAbsPath)) {
|
|
|
+ callback.recordResult(null, null);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ doStopPreview();
|
|
|
+ String fileName = saveVideoPath + File.separator + videoFileName;
|
|
|
+ callback.recordResult(fileName, videoFirstFrame);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void findAvailableCameras() {
|
|
|
+ Camera.CameraInfo info = new Camera.CameraInfo();
|
|
|
+ int cameraNum = Camera.getNumberOfCameras();
|
|
|
+ for (int i = 0; i < cameraNum; i++) {
|
|
|
+ Camera.getCameraInfo(i, info);
|
|
|
+ switch (info.facing) {
|
|
|
+ case Camera.CameraInfo.CAMERA_FACING_FRONT:
|
|
|
+ CAMERA_FRONT_POSITION = info.facing;
|
|
|
+ break;
|
|
|
+ case Camera.CameraInfo.CAMERA_FACING_BACK:
|
|
|
+ CAMERA_POST_POSITION = info.facing;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ int handlerTime = 0;
|
|
|
+
|
|
|
+ public void handleFocus(final Context context, final float x, final float y, final FocusCallback callback) {
|
|
|
+ if (mCamera == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ final Camera.Parameters params = mCamera.getParameters();
|
|
|
+ Rect focusRect = calculateTapArea(x, y, 1f, context);
|
|
|
+ mCamera.cancelAutoFocus();
|
|
|
+ if (params.getMaxNumFocusAreas() > 0) {
|
|
|
+ List<Camera.Area> focusAreas = new ArrayList<>();
|
|
|
+ focusAreas.add(new Camera.Area(focusRect, 800));
|
|
|
+ params.setFocusAreas(focusAreas);
|
|
|
+ } else {
|
|
|
+ Log.i(TAG, "focus areas not supported");
|
|
|
+ callback.focusSuccess();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ final String currentFocusMode = params.getFocusMode();
|
|
|
+ try {
|
|
|
+ params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
|
|
+ mCamera.setParameters(params);
|
|
|
+ mCamera.autoFocus(new Camera.AutoFocusCallback() {
|
|
|
+ @Override
|
|
|
+ public void onAutoFocus(boolean success, Camera camera) {
|
|
|
+ if (success || handlerTime > 10) {
|
|
|
+ Camera.Parameters params = camera.getParameters();
|
|
|
+ params.setFocusMode(currentFocusMode);
|
|
|
+ camera.setParameters(params);
|
|
|
+ handlerTime = 0;
|
|
|
+ callback.focusSuccess();
|
|
|
+ } else {
|
|
|
+ handlerTime++;
|
|
|
+ handleFocus(context, x, y, callback);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } catch (Exception e) {
|
|
|
+ Log.e(TAG, "autoFocus failer");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private static Rect calculateTapArea(float x, float y, float coefficient, Context context) {
|
|
|
+ float focusAreaSize = 300;
|
|
|
+ int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();
|
|
|
+ int centerX = (int) (x / ScreenUtils.getScreenWidth(context) * 2000 - 1000);
|
|
|
+ int centerY = (int) (y / ScreenUtils.getScreenHeight(context) * 2000 - 1000);
|
|
|
+ int left = clamp(centerX - areaSize / 2, -1000, 1000);
|
|
|
+ int top = clamp(centerY - areaSize / 2, -1000, 1000);
|
|
|
+ RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
|
|
|
+ return new Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), Math.round(rectF
|
|
|
+ .bottom));
|
|
|
+ }
|
|
|
+
|
|
|
+ private static int clamp(int x, int min, int max) {
|
|
|
+ if (x > max) {
|
|
|
+ return max;
|
|
|
+ }
|
|
|
+ if (x < min) {
|
|
|
+ return min;
|
|
|
+ }
|
|
|
+ return x;
|
|
|
+ }
|
|
|
+
|
|
|
+ void setErrorLinsenter(ErrorListener errorLisenter) {
|
|
|
+ this.errorLisenter = errorLisenter;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public interface StopRecordCallback {
|
|
|
+ void recordResult(String url, Bitmap firstFrame);
|
|
|
+ }
|
|
|
+
|
|
|
+ interface ErrorCallback {
|
|
|
+ void onError();
|
|
|
+ }
|
|
|
+
|
|
|
+ public interface TakePictureCallback {
|
|
|
+ void captureResult(Bitmap bitmap, boolean isVertical);
|
|
|
+ }
|
|
|
+
|
|
|
+ public interface FocusCallback {
|
|
|
+ void focusSuccess();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ void registerSensorManager(Context context) {
|
|
|
+ if (sm == null) {
|
|
|
+ sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
|
|
+ }
|
|
|
+ sm.registerListener(sensorEventListener, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager
|
|
|
+ .SENSOR_DELAY_NORMAL);
|
|
|
+ }
|
|
|
+
|
|
|
+ void unregisterSensorManager(Context context) {
|
|
|
+ if (sm == null) {
|
|
|
+ sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
|
|
+ }
|
|
|
+ sm.unregisterListener(sensorEventListener);
|
|
|
+ }
|
|
|
+
|
|
|
+ void isPreview(boolean res) {
|
|
|
+ this.isPreviewing = res;
|
|
|
+ }
|
|
|
+}
|