781 lines
27 KiB
Java
Executable File
781 lines
27 KiB
Java
Executable File
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.ScreenUtils;
|
||
import com.sucstepsoft.cm_utils.utils.LogUtils;
|
||
|
||
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);
|
||
}
|
||
LogUtils.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();
|
||
LogUtils.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();
|
||
}
|
||
}
|
||
LogUtils.i("open end");
|
||
doStartPreview(holder, screenProp);
|
||
}
|
||
|
||
/**
|
||
* doStartPreview
|
||
*/
|
||
public void doStartPreview(SurfaceHolder holder, float screenProp) {
|
||
if (isPreviewing) {
|
||
LogUtils.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_2_TS);
|
||
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;
|
||
}
|
||
}
|