package com.manna.codec.surface; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.os.Handler; import android.util.Log; import android.view.Surface; import android.view.Window; import android.view.WindowManager; import com.manna.codec.utils.DisplayUtils; import java.io.IOException; import java.util.List; /** * 相机管理类 */ public class CameraManager { private static final String TAG = "CameraManager.class"; private SurfaceTexture surfaceTexture; private Camera camera; private Context context; private int screenWidth; private int screenHeight; private int previewWidth; private int previewHeight; private int defaultCameraId = 0; public CameraManager(Context context) { this.context = context; this.screenWidth = DisplayUtils.getScreenWidth(context); this.screenHeight = DisplayUtils.getScreenHeight(context); } public void startCamera(SurfaceTexture surfaceTexture, int cameraId) { this.surfaceTexture = surfaceTexture; startCamera(cameraId); } private void startCamera(int cameraId) { try { camera = Camera.open(cameraId); camera.setPreviewTexture(surfaceTexture); Camera.Parameters parameters = camera.getParameters(); parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); parameters.setPreviewFormat(ImageFormat.NV21); //设置对焦模式,后置摄像头开启时打开,切换到前置时关闭(三星、华为不能设置前置对焦,魅族、小米部分机型可行) if (cameraId == 0) { //小米、魅族手机存在对焦无效情况,需要针对设备适配,想要无感知对焦完全适配最好是监听加速度传感器 camera.cancelAutoFocus(); //这种设置方式存在屏幕闪烁一下问题,包括Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } Camera.Size size = getCameraSize(parameters.getSupportedPreviewSizes(), screenWidth, screenHeight, 0.1f); parameters.setPreviewSize(size.width, size.height); //水平方向未旋转,所以宽就是竖直方向的高,对应旋转操作 Log.d(TAG, "startCamera: 预览宽:" + size.width + " -- " + "预览高:" + size.height); previewWidth = size.width; previewHeight = size.height; size = getCameraSize(parameters.getSupportedPictureSizes(), screenWidth, screenHeight, 0.1f); parameters.setPictureSize(size.width, size.height); //水平方向未旋转,所以宽就是竖直方向的高 Log.d(TAG, "startCamera: 图片宽:" + size.width + " -- " + "图片高:" + size.height); camera.setParameters(parameters); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } private void stopPreview() { if (camera != null) { camera.stopPreview(); camera.release(); camera = null; } } public void autoFocus() { if (camera != null) { camera.autoFocus(null); } } public int getPreviewWidth() { return previewWidth; } public int getPreviewHeight() { return previewHeight; } /** * 获取相机硬件实际支持的预览大小、图像大小 * * @param cameraSize List<Camera.Size> * @param width 屏幕宽 * @param height 屏幕高 * @param diff 加权重比 * @return 实际支持的预览大小、图像大小 */ private Camera.Size getCameraSize(List<Camera.Size> cameraSize, int width, int height, double diff) { if (width < height) { int temp = height; height = width; width = temp; } double ratio = (double) width / height; if (cameraSize == null || cameraSize.isEmpty()) { Log.d(TAG, "getCameraSize: 获取相机预览数据失败"); return null; } Camera.Size outputSize = null; for (Camera.Size currentSize : cameraSize) { double currentRatio = (double) currentSize.width / currentSize.height; double currentDiff = Math.abs(currentRatio - ratio); if (currentDiff > diff) { continue; } if (outputSize == null) { outputSize = currentSize; } else { if (outputSize.width * outputSize.height < currentSize.width * currentSize.height) { outputSize = currentSize; } } diff = currentDiff; } if (outputSize == null) { diff += 0.1f; if (diff > 1.0f) { outputSize = cameraSize.get(0); } else { outputSize = getCameraSize(cameraSize, width, height, diff); } } return outputSize; } /** * 设置闪光灯 * * @param flashMode :开关控制 */ public void setFlashMode(String flashMode) { boolean isFlashDevice = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH); if (!isFlashDevice) { //不支持闪光灯 return; } Camera.Parameters parameters = camera.getParameters(); parameters.setFlashMode(flashMode); camera.setParameters(parameters); } /** * 切换摄像头 */ public void switchCamera() { int cameraCount = Camera.getNumberOfCameras(); Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); for (int i = 0; i < cameraCount; i++) { Camera.getCameraInfo(i, cameraInfo); if (defaultCameraId == 0) { //后置切前置 if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { restartCameraPreview(i); defaultCameraId = i; break; } } else { //前置切后置 if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { restartCameraPreview(i); defaultCameraId = i; break; } } } } /** * 重新预览Camera * * @param cameraId :cameraId */ private void restartCameraPreview(int cameraId) { stopPreview(); startCamera(cameraId); } /** * 返回当前缩放值 * * @param scaleRatio 缩放系数, 0 表示不缩放,1 表示放大,2 表示缩小 * @return int */ public int getZoomValue(int scaleRatio) { Camera.Parameters parameters = camera.getParameters(); if (!parameters.isZoomSupported()) { return -1; } if (scaleRatio == 0) { return -1; } int defaultZoom = parameters.getZoom(); int zoomValue; if (scaleRatio == 1) { zoomValue = defaultZoom + 1; if (zoomValue < parameters.getMaxZoom()) { parameters.setZoom(zoomValue); camera.setParameters(parameters); } } else { zoomValue = defaultZoom - 1; if (zoomValue >= 0) { parameters.setZoom(zoomValue); camera.setParameters(parameters); } } return zoomValue; } /** * 设置缩放值 * * @param zoomValue :SeekBar拖动的值 */ public void setZoomValue(int zoomValue) { Camera.Parameters parameters = camera.getParameters(); if (!parameters.isZoomSupported()) { return; } Log.d(TAG, "setZoomValue: " + zoomValue); Log.d(TAG, "setZoomValue: Camera最大缩放值" + getMaxZoomValue()); if (zoomValue > getMaxZoomValue()) { zoomValue = getMaxZoomValue(); } parameters.setZoom(zoomValue); camera.setParameters(parameters); } /** * 返回默认最大缩放值 * * @return int */ public int getMaxZoomValue() { Camera.Parameters parameters = camera.getParameters(); if (!parameters.isZoomSupported()) { return -1; } return parameters.getMaxZoom(); } }