赞
踩
职场小白迷上优美句子:
还是电影 《无问西东》中的台词,这句有点感人:
沈光耀的妈妈对沈光耀说:"当初你离家千里,来到这个地方读书,你父亲和我都没有反对过,因为,是我们想你,能享受到人生的乐趣,比如读万卷书行万里路,比如同你喜欢的女孩子结婚生子。注意不是给我增添子孙,而是你自己,能够享受为人父母的乐趣,你一生所要追求的功名利禄,没有什么是你的祖上没经历过的,那些只不过是人生的幻光。我怕,你还没想好怎么过这一生,你的命就没了啊!"
推荐两篇对Camera2的讲解非常详细的博客
新根 - - - Android Camera2 API和拍照与录像过程
Camera2.0新API下的摄像头预览、原始图像数据获取等_黄政的博客-CSDN博客
效果图:
源码地址:
github开源相机Camera2源码https://github.com/13767004362/Camera2App.git
- public class PictureOperater extends BaseCamera2Operator {
- private static final String TAG = PictureOperater.class.getSimpleName();
- private WorkThreadUtils workThreadManager;
- /**
- * 相机最大的预览宽度
- */
- private static final int MAX_PREVIEW_WIDTH = 1920;
- /**
- * 相机最大的预览高度
- */
- private static final int MAX_PREVIEW_HEIGHT = 1080;
- /**
- * 处理静态图片的输出
- */
- private ImageReader imageReader;
- /**
- * 相机传感器方向
- */
- private int mSensorOrientation;
- /**
- * 相机预览的大小Size
- */
- private Size mPreviewSize;
- /**
- * 是否支持自动对焦
- */
- private boolean mAutoFocusSupported;
- /**
- * 是否支持闪光灯
- */
- private boolean mFlashSupported;
- /**
- * 相机的Id
- */
- private String mCameraId;
-
- /**
- * 预览请求的Builder
- */
- private CaptureRequest.Builder mPreviewRequestBuilder;
- /**
- * 预览的请求
- */
- private CaptureRequest mPreviewRequest;
- private CameraCaptureSession mCaptureSession;
- /**
- * 开启相机的锁住时间
- */
- private final int LOCK_TIME = 2500;
-
- private Camera2Manager camera2Manager;
-
- /**
- * 最小的焦距
- */
- private float minimalFocalDistance = 0;
- /**
- * 最大的数字变焦值,缩放值
- */
- private float maxZoom = 0;
-
-
- public PictureOperater(Camera2Manager camera2Manager) {
- this.camera2Manager = camera2Manager;
- this.workThreadManager = camera2Manager.getWorkThreadManager();
- }
-
- @Override
- public void startOperate() {
-
- TextureView textureView = getTextureView();
- if (textureView.isAvailable()) {
- openCamera(getTextureViewContext(), textureView.getWidth(), textureView.getHeight());
- } else {
- textureView.setSurfaceTextureListener(mSurfaceTextureListener);
- }
- }
-
- @Override
- public void stopOperate() {
- Log.i(TAG, TAG+" 关闭相机的操作 ");
- closeCamera();
- }
-
- @Override
- public void openCamera(Activity activity, int width, int height) {
- if (PermissionsManager.checkCameraPermission(activity)) {
- setUpCameraOutputs(activity, width, height);
- configureTransform(activity, width, height);
- CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
- try {
- //打开相机需要一定时间,因锁住2.5秒,防止程序退出关闭相机
- if (!mCameraOpenCloseLock.tryAcquire(LOCK_TIME, TimeUnit.MILLISECONDS)) {
- throw new RuntimeException("Time out waiting to lock camera opening.");
- }
- manager.openCamera(mCameraId, stateCallback, workThreadManager.getBackgroundHandler());
- } catch (CameraAccessException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
- }
- }
- }
-
- @Override
- public void closePreviewSession() {
- if (mCaptureSession != null) {
- mCaptureSession.close();
- mCaptureSession = null;
- }
- }
-
- @Override
- public void configureTransform(Activity activity, int viewWidth, int viewHeight) {
- if (null == getTextureView() || null == mPreviewSize || null == activity) {
- return;
- }
- int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
- Matrix matrix = new Matrix();
- RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
- RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
- float centerX = viewRect.centerX();
- float centerY = viewRect.centerY();
- if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
- bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
- matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
- float scale = Math.max((float) viewHeight / mPreviewSize.getHeight(), (float) viewWidth / mPreviewSize.getWidth());
- matrix.postScale(scale, scale, centerX, centerY);
- matrix.postRotate(90 * (rotation - 2), centerX, centerY);
- } else if (Surface.ROTATION_180 == rotation) {
- matrix.postRotate(180, centerX, centerY);
- }
- getTextureView().setTransform(matrix);
- }
-
- @Override
- public void writePictureData(Image image) {
- if (camera2ResultCallBack != null) {
- camera2ResultCallBack.callBack(ObservableBuilder.createWriteCaptureImage(appContext, image));
- }
- }
-
- @Override
- public void startPreView() {
- //开启相机预览界面
- createCameraPreviewSession();
- }
-
- @Override
- public void cameraClick() {
-
- takePicture();
- }
-
- /**
- * 关闭当前的相机设备,释放资源
- */
- private void closeCamera() {
- try {
- mCameraOpenCloseLock.acquire();
- closePreviewSession();
- if (null != mCameraDevice) {
- mCameraDevice.close();
- mCameraDevice = null;
- }
- if (null != imageReader) {
- imageReader.close();
- imageReader = null;
- }
- } catch (InterruptedException e) {
- throw new RuntimeException("Interrupted while trying to lock camera closi" + "ng.", e);
- } finally {
- mCameraOpenCloseLock.release();
- }
- }
-
- /**
- * 拍照
- */
- public void takePicture() {
- ToastUtils.showToast(camera2Manager.getContext()," 客官,请别抖动,正在拍照中。");
- if (mAutoFocusSupported) {
- Log.i(TAG,TAG+"支持自动调焦,正在锁住焦点");
- lockFocus();
- } else {//设备不支持自动对焦,则直接拍照。
- Log.i(TAG,TAG+"不支持自动调焦,直接拍照");
- captureStillPicture();
- }
- }
-
- /**
- * 拍照的第一步,锁住焦点。
- */
- private void lockFocus() {
- try {
- //告诉相机,这里已经锁住焦点
- mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
- // 标识,正在进行拍照动作
- mState = STATE_WAITING_LOCK;
- //进行拍照处理
- mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, workThreadManager.getBackgroundHandler());
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 相机开始预览,创建一个CameraCaptureSession对象
- */
- private void createCameraPreviewSession() {
- try {
- SurfaceTexture texture = getTextureView().getSurfaceTexture();
- //assert断言表达式,为true继续。
- assert texture != null;
-
- // We configure the size of default buffer to be the size of camera preview we want.
- texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
-
- // 创建一个预览界面需要用到的Surface对象
- Surface surface = new Surface(texture);
-
- // 将CaptureRequest的构建器与Surface对象绑定在一起
- mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
- mPreviewRequestBuilder.addTarget(surface);
-
- // 为相机预览,创建一个CameraCaptureSession对象
- mCameraDevice.createCaptureSession(Arrays.asList(surface, imageReader.getSurface()), new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
- // 相机已经关闭
- if (null == mCameraDevice) {
- return;
- }
- //当cameraCaptureSession已经准备完成,开始显示预览界面
- mCaptureSession = cameraCaptureSession;
- setCameraCaptureSession();
- }
-
- @Override
- public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
- //配置失败
- }
- }, null);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
-
- /**
- * 设置CameraCaptureSession的特征:
- * <p>
- * 自动对焦,闪光灯
- */
- private void setCameraCaptureSession() {
- try {
- setFocus(mPreviewRequestBuilder);
- //若是需要则开启,闪光灯
- setAutoFlash(mPreviewRequestBuilder);
- // 最后,开启相机预览界面的显示
- mPreviewRequest = mPreviewRequestBuilder.build();
- //为CameraCaptureSession设置复用的CaptureRequest。
- mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, workThreadManager.getBackgroundHandler());
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- private float currentZoom;
-
- @Override
- public void notifyFocusState() {
- if (mPreviewRequestBuilder != null) {
- try {
- currentZoom = maxZoom * camera2Manager.getZoomProportion();
- setZoom(currentZoom);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- private Rect zoomRect;
-
- private void setZoom(float currentZoom) {
- try {
- zoomRect=createZoomReact();
- if (zoomRect==null){
- Log.i(TAG, "相机不支持 zoom " );
- return ;
- }
- mPreviewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION,zoomRect);
- mPreviewRequest = mPreviewRequestBuilder.build();
- Log.i(TAG, " 最大缩放值 " + maxZoom + " 设置缩放值 " + currentZoom );
- //为CameraCaptureSession设置复用的CaptureRequest。
- mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, workThreadManager.getBackgroundHandler());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 计算出zoom所对应的裁剪区域
- * @return
- */
- private Rect createZoomReact() {
- if (currentZoom==0){
- return null;
- }
- try {
- Rect rect = cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
- if (rect==null){
- return null;
- }
- zoomRect =Camera2Utils.createZoomRect(rect,currentZoom);
- Log.i(TAG, "zoom对应的 rect对应的区域 " + zoomRect.left + " " + zoomRect.right + " " + zoomRect.top + " " + zoomRect.bottom);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return zoomRect;
- }
-
- /**
- * -
- * 设置调焦方式:自动连续对焦还是手动调焦
- *
- * @param requestBuilder
- */
- private void setFocus(CaptureRequest.Builder requestBuilder) {
- /* if (camera2Manager.isManualFocus()) {
- float focusDistance = minimum_focus_distance * camera2Manager.getZoomProportion();
- setManualFocus(requestBuilder, focusDistance);
- } else {
- }*/
- setAutoFocus(requestBuilder);
- }
-
- /**
- * 设置连续自动对焦
- *
- * @param requestBuilder
- */
- private void setAutoFocus(CaptureRequest.Builder requestBuilder) {
- if (requestBuilder != null) {
- //为相机预览设置连续对焦。
- requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
- }
- }
-
- /**
- * 设置手动对焦,设置焦距值
- *
- * @param requestBuilder
- */
- private void setManualFocus(CaptureRequest.Builder requestBuilder, float distance) {
- //若是机器不支持焦距设置,则需要检查。
- try {
- if (requestBuilder != null) {
- //先关闭自动对焦的模式
- requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_OFF);
- requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_OFF);
- Log.i(TAG, "手动调焦的 " + distance + " 最大范围值是 " + minimum_focus_distance);
- //设置焦距值
- requestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, distance);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- /**
- * Camera state: Showing camera preview.
- * 相机预览状态
- */
- private static final int STATE_PREVIEW = 0;
-
- /**
- * Camera state: Waiting for the focus to be locked.
- * <p>
- * 相机拍照,被锁住,等待焦点状态
- */
- private static final int STATE_WAITING_LOCK = 1;
-
- /**
- * Camera state: Waiting for the exposure to be precapture state.
- */
- private static final int STATE_WAITING_PRECAPTURE = 2;
-
- /**
- * Camera state: Waiting for the exposure state to be something other than precapture.
- */
- private static final int STATE_WAITING_NON_PRECAPTURE = 3;
-
- /**
- * Camera state: Picture was taken.
- * 图片已经获取
- */
- private static final int STATE_PICTURE_TAKEN = 4;
-
- /**
- * The current state of camera state for taking pictures.
- *
- * @see #mCaptureCallback
- */
- private int mState = STATE_PREVIEW;
- /**
- * CameraCaptureSession.CaptureCallback : 处理捕获到的JPEG事件。
- */
- private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
- private void process(CaptureResult result) {
- switch (mState) {
- //正常预览状态
- case STATE_PREVIEW: {
- break;
- }
- //刚开始拍照,锁住,等待状态
- case STATE_WAITING_LOCK: {
- //当前自动对焦的状态
- Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
- if (afState == null) {
- captureStillPicture();
- } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
- // CONTROL_AE_STATE can be null on some devices
- Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
- if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
- mState = STATE_PICTURE_TAKEN;
- captureStillPicture();
- } else {
- runPrecaptureSequence();
- }
- }else{
- mState = STATE_PICTURE_TAKEN;
- captureStillPicture();
- }
- break;
- }
- //等待,预捕获
- case STATE_WAITING_PRECAPTURE: {
- // CONTROL_AE_STATE can be null on some devices
- Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
- if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE || aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
- mState = STATE_WAITING_NON_PRECAPTURE;
- }
- break;
- }
- //已经完成预捕获,直接拍照。
- case STATE_WAITING_NON_PRECAPTURE: {
- // CONTROL_AE_STATE can be null on some devices
- Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
- if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
- mState = STATE_PICTURE_TAKEN;
- captureStillPicture();
- }
- break;
-
- }
- default:
- break;
- }
- }
-
- @Override
- public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
- process(partialResult);
- }
-
- @Override
- public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
- process(result);
- }
- };
-
- /**
- * <p>
- * 运行预捕获的序列,为捕获一个静态图片
- */
- private void runPrecaptureSequence() {
- try {
- // 告诉相机,这里触发.
- mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
- //设置成预捕获状态,将需等待。
- mState = STATE_WAITING_PRECAPTURE;
- mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, workThreadManager.getBackgroundHandler());
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 拍照一个静态的图片
- * ,当在CaptureCallback监听器响应的时候调用该方法。
- * <p>
- * 当数字调焦缩放的时候,在写入图片数中也要设置。
- */
- private void captureStillPicture() {
- try {
- final Activity activity = getTextureViewContext();
- if (null == activity || null == mCameraDevice) {
- return;
- }
- // 创建一个拍照的CaptureRequest.Builder
- final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
-
- captureBuilder.addTarget(imageReader.getSurface());
- // 使用相同的AE和AF模式作为预览.
- captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
-
- //让相机中缩放效果和图片保持一致
- // zoomRect=createZoomReact();
- if (zoomRect != null) {
- Log.i(TAG," 拍照 添加裁剪区域 "+zoomRect.toString());
- captureBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomRect);
- }
- setAutoFlash(captureBuilder);
- // 方向
- int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
- captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, Camera2Utils.getOrientation(ORIENTATIONS, mSensorOrientation, rotation));
- CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
- @Override
- public void onCaptureCompleted(@NonNull CameraCaptureSession session
- , @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
- //拍照完成,进行释放焦点操作。
- unlockFocus();
- }
- };
- //先停止以前的预览状态
- mCaptureSession.stopRepeating();
- mCaptureSession.abortCaptures();
- //执行拍照状态
- mCaptureSession.capture(captureBuilder.build(), captureCallback, null);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 完成一些列拍照后,释放焦点。
- */
- private void unlockFocus() {
- try {
- // 重置一系列的对焦
- mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
- setAutoFlash(mPreviewRequestBuilder);
- mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, workThreadManager.getBackgroundHandler());
- // 恢复正常状态
- mState = STATE_PREVIEW;
- mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, workThreadManager.getBackgroundHandler());
- Log.i(TAG, TAG+" 拍照完成,释放焦点 unlockFocus() ");
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 设置是否开启闪光灯
- *
- * @param requestBuilder
- */
- private void setAutoFlash(CaptureRequest.Builder requestBuilder) {
- if (mFlashSupported) {
- requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
- }
- }
-
- /**
- * 获取到最大的焦距值
- */
- private float minimum_focus_distance;
- /**
- * 获取相机参数的类
- */
- private CameraCharacteristics cameraCharacteristics;
-
- /**
- * 设置Camera的相关参数变量,长、宽,且返回相机的Id.
- *
- * @param width
- * @param height
- */
- private void setUpCameraOutputs(Activity activity, int width, int height) {
- CameraManager manager = (CameraManager) getTextureViewContext().getSystemService(Context.CAMERA_SERVICE);
- try {
- //获取到可用的相机
- for (String cameraId : manager.getCameraIdList()) {
- //获取到每个相机的参数对象,包含前后摄像头,分辨率等
- cameraCharacteristics = manager.getCameraCharacteristics(cameraId);
- if (!Camera2Utils.matchCameraDirection(cameraCharacteristics, currentDirection)) {
- continue;
- }
- //存储流配置类
- StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- if (map == null) {
- continue;
- }
- //检查设备,是否支持自动对焦
- mAutoFocusSupported = Camera2Utils.checkAutoFocus(cameraCharacteristics);
- //获取最小焦距值。
- Float minFocalDistance = Camera2Utils.getMinimumFocusDistance(cameraCharacteristics);
- if (minFocalDistance != null) {
- minimum_focus_distance = minFocalDistance;
- }
-
- Float maxZoomValue = Camera2Utils.getMaxZoom(cameraCharacteristics);
- if (maxZoomValue != null) {
- maxZoom = maxZoomValue;
- }
- Log.i(TAG, (currentDirection == CameraCharacteristics.LENS_FACING_BACK ? "后" : "前") + " 摄像头 " + " 是否支持自动对焦 " + mAutoFocusSupported + " 获取到焦距的最大值 " + minimum_focus_distance + " 最大的缩放值 " + maxZoom);
- //对于静态图片,使用可用的最大值来拍摄。
- Size largest = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new CompareSizeByArea());
- //设置ImageReader,将大小,图片格式
- imageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(), ImageFormat.JPEG, /*maxImages*/2);
- imageReader.setOnImageAvailableListener(onImageAvailableListener, workThreadManager.getBackgroundHandler());
- //获取到屏幕的旋转角度,进一步判断是否,需要交换维度来获取预览大小
- int displayRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
- //获取相机传感器方向
- mSensorOrientation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
- boolean swappedDimensions = false;
- switch (displayRotation) {
- case Surface.ROTATION_0:
- case Surface.ROTATION_180:
- if (mSensorOrientation == 90 || mSensorOrientation == 270) {
- swappedDimensions = true;
- }
- break;
- case Surface.ROTATION_90:
- case Surface.ROTATION_270:
- if (mSensorOrientation == 0 || mSensorOrientation == 180) {
- swappedDimensions = true;
- }
- break;
- default:
- Log.e(TAG, "Display rotation is invalid: " + displayRotation);
- }
- Point displaySize = new Point();
- activity.getWindowManager().getDefaultDisplay().getSize(displaySize);
- int rotatedPreviewWidth = width;
- int rotatedPreviewHeight = height;
- int maxPreviewWidth = displaySize.x;
- int maxPreviewHeight = displaySize.y;
- //当角度反了的时候
- if (swappedDimensions) {
- rotatedPreviewWidth = height;
- rotatedPreviewHeight = width;
- maxPreviewWidth = displaySize.y;
- maxPreviewHeight = displaySize.x;
- }
- if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
- maxPreviewWidth = MAX_PREVIEW_WIDTH;
- }
- if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
- maxPreviewHeight = MAX_PREVIEW_HEIGHT;
- }
- mPreviewSize = Camera2Utils.chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
- rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
- maxPreviewHeight, largest, new CompareSizeByArea());
- // 计算出来的预览大小,设置成TextureView宽高.
- int orientation = activity.getResources().getConfiguration().orientation;
- AutoFitTextureView mTextureView = (AutoFitTextureView) getTextureView();
- //横屏
- if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
- mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
- } else {
- mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
- }
- // 检查,相机是否支持闪光。
- Boolean available = cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
- mFlashSupported = available == null ? false : available;
- mCameraId = cameraId;
- // Log.i(TAG, " 根据相机的前后摄像头" + mCameraId + " 方向是:" + currentDirection);
- return;
- }
- } catch (Exception e) {
- e.printStackTrace();
- //不支持该设备
- if (e instanceof NullPointerException) {
- ToastUtils.showToast(appContext, "设备不支持Camera2 API");
- }
- }
- }
-
-
- }
- public class VideoRecordOperator extends BaseCamera2Operator {
- public static final String TAG = VideoRecordOperator.class.getSimpleName();
- private WorkThreadUtils workThreadManager;
-
- /**
- * 视频录制的大小
- */
- private Size mVideoSize;
- /**
- * 相机预览的大小Size
- */
- private Size mPreviewSize;
- /**
- * MediaRecorder
- */
- private MediaRecorder mMediaRecorder;
- /**
- * 当前是否是在录制视频
- */
- private boolean mIsRecordingVideo;
- /**
- * 传感器的方向
- */
- private Integer mSensorOrientation;
- /**
- * 相机预览请求的Builder
- */
- private CaptureRequest.Builder mPreviewBuilder;
- /**
- * 点击开启录制时候创建的新视频文件路径
- */
- private String mNextVideoAbsolutePath;
- private CompositeSubscription compositeSubscription;
-
- private Camera2Manager camera2Manager;
-
- public VideoRecordOperator(Camera2Manager camera2Manager) {
- this.camera2Manager = camera2Manager;
- this.workThreadManager = camera2Manager.getWorkThreadManager();
- this.oldVideoPath = new CopyOnWriteArrayList<>();
- this.compositeSubscription = new CompositeSubscription();
- }
-
- @Override
- public void writePictureData(Image image) {
-
- }
-
- /**
- * 开始相机的预览界面,创建一个预览的session会话。
- */
- @Override
- public void startPreView() {
- TextureView mTextureView = getTextureView();
- if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
- return;
- }
- //开始相机预览
- try {
- closePreviewSession();
- SurfaceTexture texture = mTextureView.getSurfaceTexture();
- assert texture != null;
- texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
- mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
- Surface previewSurface = new Surface(texture);
- mPreviewBuilder.addTarget(previewSurface);
- //从拍照切换到摄像头,获取录像完成后需要重新恢复以前的状态
- float currentZoom = camera2Manager.getZoomProportion() * maxZoom;
- updateZoomRect(currentZoom);
- mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface),
- new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(@NonNull CameraCaptureSession session) {
- mPreviewSession = session;
- updatePreview();
- }
-
- @Override
- public void onConfigureFailed(@NonNull CameraCaptureSession session) {
- Activity activity = getTextureViewContext();
- if (null != activity) {
- Toast.makeText(activity, "相机预览配置失败", Toast.LENGTH_SHORT).show();
- }
- }
- }, workThreadManager.getBackgroundHandler());
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- if (null != mTextureView) {
- configureTransform(getTextureViewContext(), mTextureView.getWidth(), mTextureView.getHeight());
- }
- }
-
- /**
- * 在 startPreView()之后执行用于更新相机预览界面
- */
- private void updatePreview() {
- if (null == mCameraDevice) {
- return;
- }
- try {
- setUpCaptureRequestBuilder(mPreviewBuilder);
- mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, workThreadManager.getBackgroundHandler());
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- private void setUpCaptureRequestBuilder(CaptureRequest.Builder builder) {
- builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
- }
-
-
- /**
- * 为相机创建一个CameraCaptureSession
- */
- private CameraCaptureSession mPreviewSession;
-
- @Override
- public void closePreviewSession() {
- if (mPreviewSession != null) {
- mPreviewSession.close();
- mPreviewSession = null;
- }
- }
-
-
- @Override
-
-
- public void cameraClick() {
- if (mIsRecordingVideo) {
- stopRecordingVideo(true);
- } else {
- startRecordingVideo();
- }
- }
-
-
-
- /**
- * 停止录制
- */
- private void stopRecordingVideo(final boolean isFinish) {
-
- // UI
- mIsRecordingVideo = false;
- /**
- * 在MediaRecorder停止前,停止相机预览,防止抛出serious error异常。
- *
- * android.hardware.camera2.CameraAccessException: The camera device has encountered a serious error
- *
- * 解决方式:https://stackoverflow.com/questions/27907090/android-camera-2-api
- */
- try {
- mPreviewSession.stopRepeating();
- mPreviewSession.abortCaptures();
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- Subscription subscription = Observable
- //延迟三十毫秒
- .timer(30, TimeUnit.MICROSECONDS, Schedulers.computation())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(l -> {
- // 停止录制
- mMediaRecorder.stop();
- mMediaRecorder.reset();
- if (isFinish) {
- isRecordGonging = false;
- Log.i(TAG, "stopRecordingVideo 录制完成");
- if (camera2VideoRecordCallBack != null) {
- camera2VideoRecordCallBack.finishRecord();
- }
- mergeMultipleFileCallBack();
- mNextVideoAbsolutePath = null;
- this.oldVideoPath.clear();
- } else {//暂停的操作
- Log.i(TAG, "pauseRecordingVideo 录制暂停");
- //若是开始新的录制,原本暂停产生的多个文件合并成一个文件。
- this.oldVideoPath.add(mNextVideoAbsolutePath);
- if (oldVideoPath.size() > 1) {
- mergeMultipleFile();
- }
- mNextVideoAbsolutePath = null;
- }
- startPreView();
- });
- this.compositeSubscription.add(subscription);
- }
-
- /**
- * 暂停后又从新恢复录制,合并多个视频文件
- */
- private void mergeMultipleFile() {
- Log.i(TAG, " mergeMultipleFile 开始操作:文件个数 " + this.oldVideoPath.size());
- Subscription subscription = ObservableBuilder.createMergeMuiltFile(appContext, this.oldVideoPath.get(0), this.oldVideoPath.get(1))
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(filePath -> {
- this.oldVideoPath.clear();
- this.oldVideoPath.add(filePath);
- Log.i(TAG, " mergeMultipleFile 完成: 文件个数" + this.oldVideoPath.size());
- });
- this.compositeSubscription.add(subscription);
- }
-
- /**
- * 完成录制,输出最终的视频录制文件
- */
- private void mergeMultipleFileCallBack() {
- if (this.oldVideoPath.size() > 0) {
- Log.i(TAG, " mergeMultipleFileCallBack 开始操作:文件个数 " + this.oldVideoPath.size());
- Subscription subscription = ObservableBuilder.createMergeMuiltFile(appContext, this.oldVideoPath.get(0), mNextVideoAbsolutePath)
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(s -> {
- if (camera2ResultCallBack != null) {
- camera2ResultCallBack.callBack(ObservableBuilder.createVideo(s));
- }
- Log.i(TAG, " mergeMultipleFileCallBack 完成 且回调");
- ToastUtils.showToast(appContext, "视频文件保存在" + s);
- });
- this.compositeSubscription.add(subscription);
- } else {
- if (camera2ResultCallBack != null) {
- camera2ResultCallBack.callBack(ObservableBuilder.createVideo(mNextVideoAbsolutePath));
- }
- ToastUtils.showToast(appContext, "视频文件保存在" + mNextVideoAbsolutePath);
- }
- }
-
- /**
- * 暂停录制
- */
- public void pauseRecordingVideo() {
- stopRecordingVideo(false);
- }
-
- /**
- * 开始视频录制,创建一个录像的session会话。
- */
- private void startRecordingVideo() {
-
- Log.i(TAG, " startRecordingVideo 录制初始化 ");
- TextureView mTextureView = getTextureView();
- if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
- return;
- }
-
- try {
- closePreviewSession();
- setUpMediaRecorder();
- SurfaceTexture texture = mTextureView.getSurfaceTexture();
- assert texture != null;
- texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
- //创建录制的session会话
- mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
- List<Surface> surfaces = new ArrayList<>();
- // 为相机预览设置Surface
- Surface previewSurface = new Surface(texture);
- surfaces.add(previewSurface);
- mPreviewBuilder.addTarget(previewSurface);
- // 为 MediaRecorder设置Surface
- Surface recorderSurface = mMediaRecorder.getSurface();
- surfaces.add(recorderSurface);
- mPreviewBuilder.addTarget(recorderSurface);
- //与未录像的状态保持一致。
- if (zoomRect != null) {
- mPreviewBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomRect);
- }
- // Start a capture session
- // Once the session starts, we can update the UI and start recording
- mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
- mPreviewSession = cameraCaptureSession;
- updatePreview();
- Log.i(TAG, " startRecordingVideo 正式开始录制 ");
- getTextureViewContext().runOnUiThread(() -> {
- mIsRecordingVideo = true;
- isRecordGonging = true;
- mMediaRecorder.start();
- if (camera2VideoRecordCallBack != null) {
- camera2VideoRecordCallBack.startRecord();
- }
- });
- }
-
- @Override
- public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
- Activity activity = getTextureViewContext();
- if (null != activity) {
- Toast.makeText(activity.getApplicationContext(), "相机设备配置失败", Toast.LENGTH_SHORT).show();
- }
- }
- }, workThreadManager.getBackgroundHandler());
- } catch (CameraAccessException | IOException e) {
- e.printStackTrace();
- }
- }
-
-
- /**
- * 设置媒体录制器的配置参数
- * <p>
- * 音频,视频格式,文件路径,频率,编码格式等等
- *
- * @throws IOException
- */
- private void setUpMediaRecorder() throws IOException {
- final Activity activity = getTextureViewContext();
- if (null == activity) {
- return;
- }
- mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
- mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mNextVideoAbsolutePath = FileUtils.createVideoDiskFile(appContext, FileUtils.createVideoFileName()).getAbsolutePath();
- mMediaRecorder.setOutputFile(mNextVideoAbsolutePath);
- mMediaRecorder.setVideoEncodingBitRate(10000000);
- //每秒30帧
- mMediaRecorder.setVideoFrameRate(30);
- mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
- mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
- mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
- switch (mSensorOrientation) {
- case SENSOR_ORIENTATION_DEFAULT_DEGREES:
- mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
- break;
- case SENSOR_ORIENTATION_INVERSE_DEGREES:
- mMediaRecorder.setOrientationHint(ORIENTATIONS.get(rotation));
- break;
- default:
- break;
- }
- mMediaRecorder.prepare();
- }
-
- private List<String> oldVideoPath;
-
- @Override
- public void startOperate() {
- TextureView textureView = getTextureView();
- if (textureView.isAvailable()) {
- openCamera(getTextureViewContext(), textureView.getWidth(), textureView.getHeight());
- } else {
- textureView.setSurfaceTextureListener(mSurfaceTextureListener);
- }
- }
-
- @Override
- public void stopOperate() {
- try {
- mCameraOpenCloseLock.acquire();
- closePreviewSession();
- if (null != mCameraDevice) {
- mCameraDevice.close();
- mCameraDevice = null;
- }
- if (null != mMediaRecorder) {
- mMediaRecorder.release();
- mMediaRecorder = null;
- }
-
- } catch (InterruptedException e) {
- throw new RuntimeException("Interrupted while trying to lock camera closing.");
- } finally {
- mCameraOpenCloseLock.release();
- }
- }
-
- private boolean isRecordGonging = false;
-
- /**
- * 是否在进行视频录制,录制状态,包含进行中,暂停中。
- *
- * @return
- */
- public boolean isVideoRecord() {
- return isRecordGonging;
- }
-
- private Rect zoomRect;
-
- /**
- * 更新缩放,数字调焦
- *
- * @param currentZoom
- */
- private void updateZoomRect(float currentZoom) {
- try {
- Rect rect = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
- if (rect == null) {
- return;
- }
- zoomRect = Camera2Utils.createZoomRect(rect, currentZoom);
- if (zoomRect == null) {
- return;
- }
- Log.i(TAG, "zoom对应的 rect对应的区域 " + zoomRect.left + " " + zoomRect.right + " " + zoomRect.top + " " + zoomRect.bottom);
- mPreviewBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomRect);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private float maxZoom;
- private CameraCharacteristics characteristics;
-
- @Override
- protected void openCamera(Activity activity, int width, int height) {
- if (PermissionsManager.checkVideoRecordPermission(getTextureViewContext())) {
- if (null == activity || activity.isFinishing()) {
- return;
- }
-
- AutoFitTextureView textureView = (AutoFitTextureView) getTextureView();
- CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
- try {
- Log.d(TAG, "tryAcquire");
- if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
- throw new RuntimeException("锁住相机开启,超时");
- }
- for (String cameraId : manager.getCameraIdList()) {
- characteristics = manager.getCameraCharacteristics(cameraId);
- if (!Camera2Utils.matchCameraDirection(characteristics, currentDirection)) {
- continue;
- }
- //存储流配置类
- StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- if (map == null) {
- continue;
- }
- Log.i(TAG, "视频录制,重新配置相机设备" + currentDirection + " " + cameraId);
- mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
- Float maxZoomValue = Camera2Utils.getMaxZoom(characteristics);
- if (maxZoomValue != null) {
- maxZoom = maxZoomValue;
- }
- // 计算相机预览和视频录制的的Size
- mVideoSize = Camera2Utils.chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
- mPreviewSize = Camera2Utils.chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height, mVideoSize);
- int orientation = activity.getResources().getConfiguration().orientation;
- if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
- textureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
- } else {
- textureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
- }
- configureTransform(activity, width, height);
- mMediaRecorder = new MediaRecorder();
- manager.openCamera(cameraId, stateCallback, null);
- return;
- }
- } catch (CameraAccessException e) {
- ToastUtils.showToast(appContext, "不能访问相机");
- activity.finish();
- } catch (NullPointerException e) {
- ToastUtils.showToast(appContext, "当前设备不支持Camera2 API");
- } catch (InterruptedException e) {
- throw new RuntimeException("在锁住相机开启期间被打断.");
- }
- }
- }
-
- @Override
- protected void configureTransform(Activity activity, int viewWidth, int viewHeight) {
- TextureView textureView = getTextureView();
- if (null == textureView || null == mPreviewSize || null == activity) {
- return;
- }
- int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
- Matrix matrix = new Matrix();
- RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
- RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
- float centerX = viewRect.centerX();
- float centerY = viewRect.centerY();
- if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
- bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
- matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
- float scale = Math.max((float) viewHeight / mPreviewSize.getHeight(), (float) viewWidth / mPreviewSize.getWidth());
- matrix.postScale(scale, scale, centerX, centerY);
- matrix.postRotate(90 * (rotation - 2), centerX, centerY);
- }
- textureView.setTransform(matrix);
- }
-
- @Override
- public void notifyFocusState() {
- float currentZoom = camera2Manager.getZoomProportion() * maxZoom;
- updateZoomRect(currentZoom);
- updatePreview();
- }
-
- private Camera2VideoRecordCallBack camera2VideoRecordCallBack;
-
- public void setCamera2VideoRecordCallBack(Camera2VideoRecordCallBack camera2VideoRecordCallBack) {
- this.camera2VideoRecordCallBack = camera2VideoRecordCallBack;
- }
- }
- public class CameraFragment extends Fragment implements CameraContract.View<CameraContract.Presenter>
- , View.OnClickListener, RadioGroup.OnCheckedChangeListener
- , VerticalProgressBarLayout.VerticalMoveResultListener {
-
- public static final String TAG = CameraFragment.class.getSimpleName();
- private ImageView show_result_iv;
- private ImageView controller_state_iv;
- private VerticalProgressBarLayout verticalProgressBarLayout;
-
- public static CameraFragment newInstance() {
- CameraFragment cameraFragment = new CameraFragment();
- return cameraFragment;
- }
-
- private AutoFitTextureView textureView;
- private TextView show_record_tv, record_tip_circle;
- private View rootView;
- private CameraContract.Presenter presenter;
- private Animator flashAnimator;
-
-
- @Nullable
- @Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
- this.rootView = inflater.inflate(R.layout.fragment_camera, container, false);
- initView();
- return this.rootView;
- }
-
- @Override
- public void showToast(String content) {
- ToastUtils.showToastRunUIThread(getActivity(), content);
- }
-
- private void initView() {
- this.textureView = rootView.findViewById(R.id.camera_auto_fit_texture_view);
- this.show_result_iv = rootView.findViewById(R.id.camera_show);
- this.show_record_tv = rootView.findViewById(R.id.camera_video_record_tip_time_tv);
- this.record_tip_circle = rootView.findViewById(R.id.camera_video_record_tip_bg);
- this.rootView.findViewById(R.id.camera_btn).setOnClickListener(this);
- this.verticalProgressBarLayout = rootView.findViewById(R.id.camera_vertical_progress_bar);
- this.controller_state_iv = this.rootView.findViewById(R.id.camera_right_top_controller);
- this.controller_state_iv.setTag(CameraContract.View.MODE_RECORD_FINISH);
- this.controller_state_iv.setOnClickListener(this);
- this.show_result_iv.setOnClickListener(this);
- ((RadioGroup) this.rootView.findViewById(R.id.camera_switch_radioGroup)).setOnCheckedChangeListener(this);
- ((RadioGroup) this.rootView.findViewById(R.id.camera_direction_radioGroup)).setOnCheckedChangeListener(this);
- this.verticalProgressBarLayout.setVerticalMoveResultListener(this);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- if (presenter != null) {
- presenter.onResume();
- }
- }
-
- @Override
- public void onPause() {
- super.onPause();
- if (presenter != null) {
- presenter.onPause();
- }
- }
-
-
- @Override
- public void setPresenter(CameraContract.Presenter presenter) {
- this.presenter = presenter;
- }
-
- @Override
- public TextureView getCameraView() {
- return textureView;
- }
-
- protected String filePath;
-
- @Override
- public void loadPictureResult(String filePath) {
- this.filePath = filePath;
- GlideLoader.loadNetWorkResource(getActivity(), filePath, show_result_iv);
- }
-
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- //点击按钮,进行拍照或录像
- case R.id.camera_btn:
- this.presenter.takePictureOrVideo();
- break;
- // 控制视频录制的开关,包含暂停,恢复录制
- case R.id.camera_right_top_controller:
- int mode = (int) controller_state_iv.getTag();
- //录制状态中,可以暂停
- if (mode == CameraContract.View.MODE_RECORD_START) {
- this.presenter.stopRecord();
- }//暂停状态,可以继续开始录制
- else if (mode == CameraContract.View.MODE_RECORD_STOP) {
- this.presenter.restartRecord();
- }
- break;
- //查看大图
- case R.id.camera_show:
- if (!TextUtils.isEmpty(filePath)) {
- PictureActivity.openActivity(getActivity(), filePath);
- }
- break;
- default:
- break;
- }
- }
-
- @Override
- public void setTimingShow(String timing) {
- this.show_record_tv.setText(timing);
- }
-
- @Override
- public void switchRecordMode(int mode) {
- switch (mode) {
- //录制开始
- case CameraContract.View.MODE_RECORD_START:
- this.show_record_tv.setVisibility(View.VISIBLE);
- this.record_tip_circle.setVisibility(View.VISIBLE);
- this.controller_state_iv.setImageResource(R.drawable.camera_stop_iv);
- if (flashAnimator != null && flashAnimator.isRunning()) {
- flashAnimator.cancel();
- }
- break;
- //录制暂停
- case CameraContract.View.MODE_RECORD_STOP:
- this.controller_state_iv.setImageResource(R.drawable.camera_start_iv);
- this.show_record_tv.setVisibility(View.INVISIBLE);
- flashAnimator = AnimatorBuilder.createFlashAnimator(this.record_tip_circle);
- flashAnimator.start();
- break;
- //录制完成
- case CameraContract.View.MODE_RECORD_FINISH:
- this.show_record_tv.setText("");
- this.show_record_tv.setVisibility(View.GONE);
- this.record_tip_circle.setVisibility(View.GONE);
- this.controller_state_iv.setImageResource(R.drawable.camera_init_iv);
- break;
- default:
- break;
- }
- this.controller_state_iv.setTag(mode);
- }
-
- @Override
- public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
- switch (checkedId) {
- //切换成录像模式
- case R.id.camera_video_record_btn:
- this.presenter.switchMode(Constant.MODE_VIDEO_RECORD);
- break;
- //切换到拍照模式
- case R.id.camera_switch_picture_btn:
- this.presenter.switchMode(Constant.MODE_CAMERA);
- break;
- //切换到前摄像头
- case R.id.camera_direction_front:
- this.presenter.switchCamera(Camera2Manager.CAMERA_DIRECTION_FRONT);
- break;
- //切换到后摄像头
- case R.id.camera_direction_back:
- this.presenter.switchCamera(Camera2Manager.CAMERA_DIRECTION_BACK);
- break;
- default:
-
- break;
- }
- }
-
- @Override
- public void moveDistance(float verticalBias) {
- Log.d(TAG, "moveDistance--verticalBias: " + verticalBias);
- if (presenter != null) {
- presenter.setManualFocus(verticalBias);
- }
- }
- }
另外一个项目的效果图:
源码地址:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。