先上效果图,本文只摘取部分代码, 完整代码请戳 https://github.com/ycy726619/WaterRecord
1.全屏预览 首先先创建一个RecordCameraView继承于TextureView
1.全屏预览 首先先创建一个RecordCameraView继承于TextureView
public class RecordCameraView extends TextureView {}
构造函数
public RecordCameraView(Context context) {
this(context, null); } public RecordCameraView(Context context, AttributeSet attrs) {
this(context, attrs, 0); } public RecordCameraView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); initView(context); }
测量预览宽高,这里如果是width < height * mRatioWidth / mRatioHeight那么预览的就是实际拍摄画面。
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); if (0 == mRatioWidth || 0 == mRatioHeight) {
setMeasuredDimension(width, height); } else {
//全屏预览 width > height * mRatioWidth / mRatioHeight if (width > height * mRatioWidth / mRatioHeight) {
setMeasuredDimension(width, width * mRatioHeight / mRatioWidth); } else {
setMeasuredDimension(height * mRatioWidth / mRatioHeight, height); } }}
预览线程
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("CameraBackground"); mBackgroundThread.start(); mBackgroundHandler = new Handler(mBackgroundThread.getLooper());}
打开相机
private void openCamera(int width, int height) {
CameraManager manager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE); try {
Log.e(TAG, "tryAcquire"); if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("锁定相机开启时间已过。"); } String cameraId = manager.getCameraIdList()[0]; CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); StreamConfigurationMap map = characteristics .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); if (map == null) {
throw new RuntimeException("无法获得可用的预览/视频大小"); } mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class)); mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height, mVideoSize); int orientation = getResources().getConfiguration().orientation; if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight()); } else {
mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth()); } configureTransform(width, height); mMediaRecorder = new MediaRecorder(); manager.openCamera(cameraId, mStateCallback, null); } catch (CameraAccessException e) {
Log.e(TAG, "无法进入相机"); } catch (NullPointerException e) {
Log.e(TAG, "此设备不支持Camera2 API"); } catch (InterruptedException e) {
throw new RuntimeException("试图锁定相机打开时被打断"); }}
相机状态回调
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override public void onOpened(@NonNull CameraDevice cameraDevice) {
mCameraDevice = cameraDevice; startPreview(); mCameraOpenCloseLock.release(); if (null != mTextureView) configureTransform(mTextureView.getWidth(), mTextureView.getHeight()); } @Override public void onDisconnected(@NonNull CameraDevice cameraDevice) {
mCameraOpenCloseLock.release(); cameraDevice.close(); mCameraDevice = null; } @Override public void onError(@NonNull CameraDevice cameraDevice, in