生搬硬套,代码纯属缝合,仅用于自己记忆
package com.szzysk.weibo.activity.chat; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.params.StreamConfigurationMap; import android.media.ImageReader; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Size; import android.util.SparseIntArray; import android.view.Surface; import android.view.TextureView; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import com.szzysk.weibo.R; import com.szzysk.weibo.base.BaseActivity; import com.szzysk.weibo.utils.FileUtils; import com.szzysk.weibo.utils.LogU; import com.szzysk.weibo.utils.OnTwoTabDialogListener; import com.szzysk.weibo.utils.Screen; import com.szzysk.weibo.utils.TToast; import com.szzysk.weibo.view.dialog.CameraDialog; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.concurrent.Semaphore; import butterknife.BindView; import butterknife.ButterKnife; public class CameraActivity extends BaseActivity { @BindView(R.id.sView) TextureView mTextureView; @BindView(R.id.mImage_camera) ImageView mImage_camera; @BindView(R.id.mImage_video) ImageView mImage_video; @BindView(R.id.mImage) ImageView mImage; @BindView(R.id.mImage_stop) ImageView mImage_stop; @BindView(R.id.mText_time) TextView mText_time; @BindView(R.id.mText_tip) TextView mText_tip; private CameraActivity cameraActivity; private boolean isRecording = true; private boolean isPicture = true; private MediaRecorder mMediaRecorder; private CameraCaptureSession mCaptureSession; private CameraCaptureSession mPhotoCaptureSession; private CameraDevice mCameraDevice; private String mCurrentSelectCamera; private String mFaceSelectCamera; private String mTempCamera; private CaptureRequest.Builder mPreviewBuilder; private CaptureRequest.Builder mCameraDevicePhotoCaptureRequest; private CameraManager mCameraManager; private int deviceWidth; private int deviceHeigh; private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); private static final SparseIntArray ORIENTATIONS_FACE = new SparseIntArray(); private CameraCaptureSession.StateCallback mSessionStateCallback; private CameraDevice.StateCallback mCameraDeviceStateCallback; private CameraCaptureSession.CaptureCallback mCaptureCallback; static {// /为了使照片竖直显示 ORIENTATIONS.append(Surface.ROTATION_0, 90); ORIENTATIONS.append(Surface.ROTATION_90, 0); ORIENTATIONS.append(Surface.ROTATION_180, 270); ORIENTATIONS.append(Surface.ROTATION_270, 180); } static {// /为了使照片竖直显示 ORIENTATIONS_FACE.append(Surface.ROTATION_0, 270); ORIENTATIONS_FACE.append(Surface.ROTATION_90, 180); ORIENTATIONS_FACE.append(Surface.ROTATION_180, 90); ORIENTATIONS_FACE.append(Surface.ROTATION_270, 0); } private Semaphore mCameraOpenCloseLock = new Semaphore(1); private File file; private ImageReader mImageReader; private HandlerThread mBackgroundThread; private CaptureRequest mPreviewRequest; private int videoTime; private boolean isFace = false; private String randomImageFilePath; @Override protected int getContentLayout() { return R.layout.activity_camera; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); cameraActivity = this; ButterKnife.bind(this); Screen screen = new Screen(); screen.fullScreen(this, true); DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); //因为我这里是将预览铺满屏幕,所以直接获取屏幕分辨率 deviceWidth = displayMetrics.widthPixels; deviceHeigh = displayMetrics.heightPixels; LogU.d("getMatchingSize2: 屏幕密度宽度=" + deviceWidth + ", 屏幕密度高度=" + deviceHeigh); initChildHandler(); initCaptureCallback(); initCameraDeviceStateCallback(); //初始化(相机拍照) initMediaRecorder(); mImage_stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); mImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { switchCamera(); } }); mImage_camera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isPicture) { // TToast.showToastCenter(CameraActivity.this, "拍照"); // lockFocus(); Bitmap bitmap_get = mTextureView.getBitmap(); randomImageFilePath = FileUtils.getRandomImageFilePath(CameraActivity.this); randomImageFilePath = FileUtils.saveFileByBitmap(CameraActivity.this, bitmap_get, randomImageFilePath).getAbsolutePath(); timeHandler.sendEmptyMessage(3); } else { // stopRecorder(); } } }); mImage_video.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { LogU.d("isPicture=" + isPicture + ",isRecording=" + isRecording); if (!isPicture && isRecording) { mText_time.setVisibility(View.VISIBLE); TToast.showToastCenter(CameraActivity.this, "开始录像"); resetSession(); startRecorder(); timeHandler.sendEmptyMessage(1); isRecording = false; } else if (!isPicture && !isRecording) { TToast.showToastCenter(CameraActivity.this, "结束录像"); stopRecorder(); } } }); mImage_video.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { if (!isPicture && isRecording) { isPicture = true; initCameraDeviceStateCallback(); initTextureViewStateListener(); //切换拍照 mImage_video.setVisibility(View.GONE); mImage_camera.setVisibility(View.VISIBLE); mText_tip.setText("轻触拍照,长按切换录像"); mText_time.setVisibility(View.GONE); } return false; } }); mImage_camera.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { if (isPicture) { isPicture = false; initStateCallback(); initCameraDeviceStateCallback(); initTextureViewStateListener(); //切换录像 mImage_video.setVisibility(View.VISIBLE); mImage_camera.setVisibility(View.GONE); mText_tip.setText("轻触录像,长按切换拍照"); } return false; } }); } public void switchCamera() { if (isFace) { mCurrentSelectCamera = mTempCamera; isFace = false; } else { mCurrentSelectCamera = mFaceSelectCamera; isFace = true; } closeCamera(); initCameraDeviceStateCallback(); initTextureViewStateListener(); } TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { LogU.d("onSurfaceTextureAvailable"); initCameraManager(); selectCamera(); if (isPicture) { initImageReader(width, height); } openCamera(); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { //configureTransform(width, height); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { return true; } @Override public void onSurfaceTextureUpdated(SurfaceTexture texture) { } }; private void initImageReader(int width, int height) { mImageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG,/*maxImages*/7); mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mChildHandler); } private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { LogU.w("reader.hashCode()=" + reader.hashCode()); if (isPicture && TextUtils.isEmpty(randomImageFilePath)) { randomImageFilePath = FileUtils.getRandomImageFilePath(CameraActivity.this); Runnable runnable = FileUtils.savePicture(reader.acquireNextImage(), new File(randomImageFilePath)); mChildHandler.post(runnable); timeHandler.sendEmptyMessage(3); } } }; /** * 初始化TextureView的纹理生成监听,只有纹理生成准备好了。我们才能去进行摄像头的初始化工作让TextureView接收摄像头预览画面 */ private void initTextureViewStateListener() { if (mTextureView.isAvailable()) { if (isPicture) { Size cameraSize = getMatchingSize2(); initImageReader(cameraSize.getWidth(), cameraSize.getHeight()); } openCamera(); } else { mTextureView.setSurfaceTextureListener(mSurfaceTextureListener); } } private Handler mChildHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(@NonNull Message msg) { LogU.e("mChildHandler"); return false; } }); private Handler timeHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(@NonNull Message msg) { switch (msg.what) { case 1: videoTime = 30; mText_time.setText("00:" + videoTime); timeHandler.sendEmptyMessageDelayed(2, 1000); break; case 2: videoTime = videoTime - 1; mText_time.setText("00:" + videoTime); if (videoTime == 0) { stopRecorder(); } else { timeHandler.sendEmptyMessageDelayed(2, 1000); } break; case 3: CameraDialog cameraDialog = new CameraDialog(CameraActivity.this, randomImageFilePath, new OnTwoTabDialogListener() { @Override public void onButton() { Intent intent = new Intent(); intent.putExtra("PhotoPath", randomImageFilePath); intent.putExtra("result_type", 0); setResult(RESULT_OK, intent); finish(); } @Override public void onCancel() { randomImageFilePath = null; createCameraPreviewSession(); // finish(); // if (null != mImageReader) { // mImageReader.close(); // mImageReader = null; // } // //重新拍照 // initTextureViewStateListener(); // initCameraDeviceStateCallback(); } }); cameraDialog.showDialog(); break; } return false; } }); /** * 初始化子线程Handler,操作Camera2需要一个子线程的Handler */ private void initChildHandler() { HandlerThread handlerThread = new HandlerThread("Camera2Demo"); handlerThread.start(); mChildHandler = new Handler(handlerThread.getLooper()); } /** * 初始化MediaRecorder */ private void initMediaRecorder() { mMediaRecorder = new MediaRecorder(); } /** * 配置录制视频相关数据 */ private void configMediaRecorder() { try { file = new File(FileUtils.getRandomVideoMP4FilePath(this)); // File file = new File(getExternalCacheDir(), "demo.mp4"); LogU.d("configMediaRecorder=" + file.getAbsolutePath()); if (file.exists()) { file.delete(); } mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置音频来源 mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);//设置视频来源 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);//设置输出格式 mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);//设置音频编码格式,请注意这里使用默认,实际app项目需要考虑兼容问题,应该选择AAC mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);//设置视频编码格式,请注意这里使用默认,实际app项目需要考虑兼容问题,应该选择H264 mMediaRecorder.setVideoEncodingBitRate(8 * 1024 * 1920);//设置比特率 一般是 1*分辨率 到 10*分辨率 之间波动。比特率越大视频越清晰但是视频文件也越大。 mMediaRecorder.setVideoFrameRate(30);//设置帧数 选择 30即可, 过大帧数也会让视频文件更大当然也会更流畅,但是没有多少实际提升。人眼极限也就30帧了。 Size size = getMatchingSize2(); mMediaRecorder.setVideoSize(size.getWidth(), size.getHeight()); if (isFace) { mMediaRecorder.setOrientationHint(270); } else { mMediaRecorder.setOrientationHint(90); } Surface surface = new Surface(mTextureView.getSurfaceTexture()); mMediaRecorder.setPreviewDisplay(surface); mMediaRecorder.setOutputFile(file.getAbsolutePath()); mMediaRecorder.prepare(); } catch (IOException e) { e.printStackTrace(); LogU.d("IOException=" + e.getLocalizedMessage()); } catch (Exception e) { LogU.d("Exception=" + e.getLocalizedMessage()); } } /** * 重新配置录制视频时的CameraCaptureSession */ private void resetSession() { try { mCaptureSession.stopRepeating();//停止预览,准备切换到录制视频 mCaptureSession.close();//关闭预览的会话,需要重新创建录制视频的会话 mCaptureSession = null; } catch (CameraAccessException e) { e.printStackTrace(); } configMediaRecorder(); Size cameraSize = getMatchingSize2(); SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); surfaceTexture.setDefaultBufferSize(cameraSize.getWidth(), cameraSize.getHeight()); Surface previewSurface = new Surface(surfaceTexture); Surface recorderSurface = mMediaRecorder.getSurface();//从获取录制视频需要的Surface try { mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);// 自动对焦 mPreviewBuilder.addTarget(previewSurface); mPreviewBuilder.addTarget(recorderSurface); //请注意这里设置了Arrays.asList(previewSurface,recorderSurface) 2个Surface,很好理解录制视频也需要有画面预览,第一个是预览的Surface,第二个是录制视频使用的Surface mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, recorderSurface), mSessionStateCallback, mChildHandler); } catch (CameraAccessException e) { LogU.e("CameraAccessException=" + e.getLocalizedMessage()); } catch (Exception e) { LogU.e("resetSession Exception=" + e.getLocalizedMessage()); } } /** * 开始录制视频 */ private void startRecorder() { if (mMediaRecorder != null) { mMediaRecorder.start(); } } /** * 暂停录制视频(暂停后视频文件会自动保存) */ private void stopRecorder() { if (mMediaRecorder != null) { mMediaRecorder.stop(); mMediaRecorder.release(); if (timeHandler != null) { timeHandler.removeCallbacksAndMessages(null); } // mMediaRecorder.reset(); Intent intent = new Intent(); intent.putExtra("VideoPath", file.getAbsolutePath()); intent.putExtra("result_type", 1); setResult(RESULT_OK, intent); finish(); } } /** * 初始化Camera2的相机管理,CameraManager用于获取摄像头分辨率,摄像头方向,摄像头id与打开摄像头的工作 */ private void initCameraManager() { mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); } /** * 选择一颗我们需要使用的摄像头,主要是选择使用前摄还是后摄或者是外接摄像头 */ private void selectCamera() { if (mCameraManager == null) { LogU.d("selectCamera: CameraManager is null"); return; } try { String[] cameraIdList = mCameraManager.getCameraIdList(); //获取当前设备的全部摄像头id集合 if (cameraIdList.length == 0) { LogU.d("selectCamera: cameraIdList length is 0"); } for (String cameraId : cameraIdList) { //遍历所有摄像头 CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);//得到当前id的摄像头描述特征 Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); //获取摄像头的方向特征信息 if (facing == CameraCharacteristics.LENS_FACING_FRONT) {//这里选择了前摄像头 mFaceSelectCamera = cameraId; } if (facing == CameraCharacteristics.LENS_FACING_BACK) { //这里选择了后摄像头 mCurrentSelectCamera = cameraId; mTempCamera = cameraId; } } } catch (CameraAccessException e) { LogU.e("CameraAccessException=" + e.getLocalizedMessage()); } } private void initCameraDeviceStateCallback() { mCameraDeviceStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { if (isPicture) { LogU.d("摄像头被打开 "); mCameraOpenCloseLock.release(); mCameraDevice = camera; createCameraPreviewSession(); } else { LogU.d("录像头被打开 "); //摄像头被打开 try { mCameraDevice = camera; Size cameraSize = getMatchingSize2();//计算获取需要的摄像头分辨率 SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();//得到纹理 surfaceTexture.setDefaultBufferSize(cameraSize.getWidth(), cameraSize.getHeight()); Surface previewSurface = new Surface(surfaceTexture); mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); mPreviewBuilder.addTarget(previewSurface); // 为相机预览,创建一个CameraCaptureSession对象 mCameraDevice.createCaptureSession(Arrays.asList(previewSurface), mSessionStateCallback, mChildHandler);//创建数据捕获会话,用于摄像头画面预览,这里需要等待mSessionStateCallback回调 } catch (CameraAccessException e) { e.printStackTrace(); } } } @Override public void onDisconnected(CameraDevice cameraDevice) { if (isPicture) { //摄像头断开 mCameraOpenCloseLock.release(); cameraDevice.close(); mCameraDevice = null; } } @Override public void onError(CameraDevice cameraDevice, int error) { if (isPicture) { //异常 mCameraOpenCloseLock.release(); cameraDevice.close(); mCameraDevice = null; } } }; } private void initStateCallback() { mSessionStateCallback = new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { mCaptureSession = session; try { //执行重复获取数据请求,等于一直获取数据呈现预览画面,mSessionCaptureCallback会返回此次操作的信息回调 mCaptureSession.setRepeatingRequest(mPreviewBuilder.build(), mCaptureCallback, mChildHandler); } catch (CameraAccessException e) { e.printStackTrace(); LogU.e("CameraAccessException=" + e.getLocalizedMessage()); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { LogU.d("onConfigureFailed"); //开启预览失败 } }; } private void initCaptureCallback() { mCaptureCallback = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) { super.onCaptureStarted(session, request, timestamp, frameNumber); } @Override public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) { super.onCaptureProgressed(session, request, partialResult); // LogU.d("isPicture="+isPicture+",mState="+mState); if (isPicture) { mPhotoCaptureSession = session; checkState(partialResult); } else { mCaptureSession = session; } } @Override public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) { super.onCaptureCompleted(session, request, result); if (isPicture) { mPhotoCaptureSession = session; checkState(result); } else { mCaptureSession = session; } } @Override public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) { super.onCaptureFailed(session, request, failure); //开启预览失败 // LogU.e("onCaptureFailed"); } }; } private void checkState(CaptureResult result) { switch (mState) { case STATE_PREVIEW: // We have nothing to do when the camera preview is working normally. break; case STATE_WAITING_PRECAPTURE: Integer afState = result.get(CaptureResult.CONTROL_AF_STATE); // LogU.d("afState =" + afState); if (afState == null) { captureStillPicture(); } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState || CaptureResult.CONTROL_AF_STATE_INACTIVE == afState) { Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) { captureStillPicture(); } else { //runPrecaptureSequence();//视频拍摄 LogU.d("视频拍摄"); } } break; } } private void captureStillPicture() { try { if (null == mCameraDevice) { LogU.d("mCameraDevice=null"); return; } final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); captureBuilder.addTarget(mImageReader.getSurface());//拍照时,是将mImageReader.getSurface()作为目标 captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); int rotation = getWindowManager().getDefaultDisplay().getRotation(); // LogU.d("rotation=" + rotation); if (isFace) { captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS_FACE.get(rotation)); } else { captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); } CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) { if (isPicture) { unlockFocus();//恢复预览 } } }; mPhotoCaptureSession.stopRepeating(); mPhotoCaptureSession.abortCaptures(); mPhotoCaptureSession.capture(captureBuilder.build(), CaptureCallback, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private static final int STATE_PREVIEW = 1; private static final int STATE_WAITING_PRECAPTURE = 2; private int mState = STATE_PREVIEW; private void unlockFocus() { try { mCameraDevicePhotoCaptureRequest.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL); mCameraDevicePhotoCaptureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); mState = STATE_PREVIEW; mPhotoCaptureSession.setRepeatingRequest(mCameraDevicePhotoCaptureRequest.build(), mCaptureCallback, mChildHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } private void createCameraPreviewSession() { try { SurfaceTexture texture = mTextureView.getSurfaceTexture(); Size matchingSize2 = getMatchingSize2(); LogU.d("Width=" + mTextureView.getWidth() + ",Height=" + mTextureView.getHeight()); texture.setDefaultBufferSize(matchingSize2.getWidth(), matchingSize2.getHeight()); Surface surface = new Surface(texture); mCameraDevicePhotoCaptureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); mCameraDevicePhotoCaptureRequest.addTarget(surface);//预览时,是将Surface()作为目标 mState = STATE_PREVIEW; Surface surface1 = mImageReader.getSurface(); LogU.e("surface1=" + surface1.hashCode()); mCameraDevice.createCaptureSession(Arrays.asList(surface, surface1), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { if (mCameraDevice == null) { LogU.d("null == mCameraDevice"); return; } mPhotoCaptureSession = cameraCaptureSession; try { mCameraDevicePhotoCaptureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); mCameraDevicePhotoCaptureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); mPreviewRequest = mCameraDevicePhotoCaptureRequest.build(); mPhotoCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mChildHandler); } catch (Exception e) { LogU.e("set preview builder failed." + e.getLocalizedMessage()); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { LogU.e("Camera configuration Failed"); } }, mChildHandler); } catch (CameraAccessException e) { LogU.e("CameraAccessException=" + e.getLocalizedMessage()); } } /** * 打开摄像头,这里打开摄像头后,我们需要等待mCameraDeviceStateCallback的回调 */ @SuppressLint("MissingPermission") private void openCamera() { try { mCameraManager.openCamera(mCurrentSelectCamera, mCameraDeviceStateCallback, mChildHandler); } catch (CameraAccessException e) { e.printStackTrace(); LogU.e("openCamera=" + e.getLocalizedMessage()); } } /** * 计算需要的使用的摄像头分辨率 * * @return */ private Size getMatchingSize2() { Size selectSize = null; try { CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(mCurrentSelectCamera); StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); Size[] sizes = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG); /** * 循环40次,让宽度范围从最小逐步增加,找到最符合屏幕宽度的分辨率, * 你要是不放心那就增加循环,肯定会找到一个分辨率,不会出现此方法返回一个null的Size的情况 * ,但是循环越大后获取的分辨率就越不匹配 */ for (int j = 1; j < 41; j++) { for (int i = 0; i < sizes.length; i++) { //遍历所有Size Size itemSize = sizes[i]; // LogU.d("当前itemSize 宽=" + itemSize.getWidth() + "高=" + itemSize.getHeight()); //判断当前Size高度小于屏幕宽度+j*5 && 判断当前Size高度大于屏幕宽度-j*5 && 判断当前Size宽度小于当前屏幕高度 if (itemSize.getHeight() < (deviceWidth + j * 5) && itemSize.getHeight() > (deviceWidth - j * 5)) { if (selectSize != null) { //如果之前已经找到一个匹配的宽度 if (Math.abs(deviceHeigh - itemSize.getWidth()) < Math.abs(deviceHeigh - selectSize.getWidth())) { //求绝对值算出最接近设备高度的尺寸 selectSize = itemSize; continue; } } else { selectSize = itemSize; } } } if (selectSize != null) { //如果不等于null 说明已经找到了 跳出循环 break; } } } catch (CameraAccessException e) { e.printStackTrace(); } LogU.w("getMatchingSize2: 选择的分辨率宽度=" + selectSize.getWidth() + ",选择的分辨率高度=" + selectSize.getHeight()); return selectSize; } private void lockFocus() { try { mCameraDevicePhotoCaptureRequest.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START); // mCaptureSession.capture(mPreviewBuilder.build(), mCaptureCallback, mChildHandler); if (isPicture) { mState = STATE_WAITING_PRECAPTURE; mPhotoCaptureSession.capture(mCameraDevicePhotoCaptureRequest.build(), mCaptureCallback, mChildHandler); } } catch (CameraAccessException e) { LogU.e("CameraAccessException=" + e.getLocalizedMessage()); } catch (Exception e) { LogU.e("lockFocus Exception=" + e.getLocalizedMessage()); } } private void closeCamera() { try { mCameraOpenCloseLock.acquire(); if (null != mPhotoCaptureSession) { mPhotoCaptureSession.close(); mPhotoCaptureSession = null; } if (null != mCameraDevice) { mCameraDevice.close(); mCameraDevice = null; } if (null != mImageReader) { mImageReader.close(); mImageReader = null; } } catch (InterruptedException e) { throw new RuntimeException("Interrupted while trying to lock camera closing.", e); } finally { mCameraOpenCloseLock.release(); } } private void startBackgroundThread() { mBackgroundThread = new HandlerThread("CameraBackground"); mBackgroundThread.start(); mChildHandler = new Handler(mBackgroundThread.getLooper()); } private void stopBackgroundThread() { if (mBackgroundThread != null) { mBackgroundThread.quitSafely(); try { mBackgroundThread.join(); mBackgroundThread = null; mChildHandler = null; } catch (InterruptedException e) { e.printStackTrace(); } } } @Override protected void onResume() { super.onResume(); if (isPicture) { startBackgroundThread(); initTextureViewStateListener(); } } @Override protected void onPause() { super.onPause(); if (isPicture) { closeCamera(); stopBackgroundThread(); } } @Override protected void onDestroy() { super.onDestroy(); if (mMediaRecorder != null) { mMediaRecorder.release(); mMediaRecorder = null; } if (timeHandler != null) { timeHandler.removeCallbacksAndMessages(null); } } }