安卓使用uvc协议调用usb外接摄像头

Java 自带的camera api只能获取简单的拍摄,无法实现类似手机的调倍数和调焦距。自己使用github上项目为大家试试能不能成功。

目前比较简单直接拉取就可以使用的是UVCAndroid这个项目源码。其他的只要你们能搜索到,我都尝试了,要不是libusb这个编译不出来,要不就是缺少ndk。

我接下来试试用ndk看可以运行成功不。

我的需求是,用代码页面滚动条控制摄像头的参数。有些usb摄像头还真的不好搞。有大佬成功过没。

下面代码是camera。可以运行成功,对一些没那么高要求的摄像头还是没问题的。

package com.hs.smart.cabinet.ui;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.donkingliang.imageselector.ImageSelectorActivity;
import com.hs.smart.cabinet.R;
import com.hs.smart.cabinet.helper.CameraControlsDialogFragment;
import com.hs.smart.cabinet.helper.ProcessPhotoAsyncTask;
import com.hs.smart.cabinet.utils.MyField;

import java.io.IOException;
import java.util.List;
import android.widget.SeekBar;

/************************************
 *@desc:这是拍照页面,使用第三个摄像头拍照
 * 即涉案涉财柜中的第三个摄像头
 *@Author: admin
 *@DateTime:2024/4/2 11:59
 *@Copyright: hskj
 *************************************/
public class TakePhotoActivity extends AppCompatActivity
        implements View.OnClickListener, Camera.PreviewCallback {
    private SurfaceView surfaceView;
    private Button photograph;
    private Button switchs;
    private CameraControlsDialogFragment mControlsDialog;

    private Button camerasettings;
    private int rotation;
    private int shortSize;
    private int longSize;
    private Camera camera;
    private Camera.CameraInfo cameraInfo;
    private Camera.Parameters parameters;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_take_photo);
        initView();
    }

    private void initView() {
        surfaceView = (SurfaceView) findViewById(R.id.camera_view);
        photograph = (Button) findViewById(R.id.photograph);
        switchs = (Button) findViewById(R.id.switchs);
        camerasettings = (Button) findViewById(R.id.camerasettings);
        photograph.setOnClickListener(this);
        switchs.setOnClickListener(this);
        camerasettings.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.photograph:    //拍照
                if (camera == null) {
                    Toast.makeText(this, "请打开相机", Toast.LENGTH_SHORT).show();
                    return;
                }
                parameters = camera.getParameters();
                parameters.setPictureFormat(ImageFormat.JPEG);
                camera.setParameters(parameters);
                camera.startPreview();
                camera.takePicture(null, null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        ProcessPhotoAsyncTask myTask = new ProcessPhotoAsyncTask(TakePhotoActivity.this,
                                cameraInfo.facing,
                                data,
                                camera,
                                processImageHandler
                        );
                        myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                    }
                });

                break;

            case R.id.switchs:
                gotoTakePhoto();
                break;
            case R.id.camerasettings:
                showCameraControlsDialog();
                break;
        }
    }
    private void showCameraControlsDialog() {
        if (mControlsDialog == null) {
            mControlsDialog = new CameraControlsDialogFragment();
        }

        // When DialogFragment is not showing
        if (!mControlsDialog.isAdded()) {
            mControlsDialog.show(getSupportFragmentManager(), "controls_dialog");
        }
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            int[] a = new int[2];
            surfaceView.getLocationOnScreen(a);
            shortSize = surfaceView.getHeight();     //横屏为宽度,竖屏为高度
            longSize = surfaceView.getWidth();
            rotation = getWindowManager().getDefaultDisplay().getRotation();
            cameraInfo = new Camera.CameraInfo();
            checkCameraPermission();
        }
    }

    private Handler processImageHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    String filePath = (String) msg.obj;
                    Intent data = new Intent();
                    data.putExtra(MyField.KEY_CARGO_PHOTO_PATH, filePath);
                    setResult(RESULT_OK, data);
                    finish();
                    break;
                default:
                    break;
            }
        }
    };


    // 1.申请相机权限---------------------------------------------------------------------------
    private void checkCameraPermission() {
        //检查是否有相机权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            //没权限,请求权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    1);
        } else {
            //有权限
            //Log.d("MainActivity", "有权限");
            getCameras(0);  //0为后摄,1为前摄
        }
    }

    //权限请求回调
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1:
                if (grantResults != null && grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //用户同意权限
                    getCameras(0);  //0为后摄,1为前摄
                } else {
                    // 权限被用户拒绝了,可以提示用户,关闭界面等等。
                    Toast.makeText(this, "拒绝权限,请去设置里面手动开启权限", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

    //预览数据监听
    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        camera.addCallbackBuffer(data);
    }

    /*
   3.查找指定摄像头ID,根据摄像头ID打开指定的相机----------------------------------------------------------------------------------------------
       根据摄像头的朝向查找指定摄像头id
       0代表后摄的朝向,但是它不一定是后摄的id
       1代表前摄的朝向
   */
    public void getCameras(int lens_facing) {
        //先释放相机资源
        releaseCamera();
        //获取相机信息
        if (cameraInfo == null) {
            cameraInfo = new Camera.CameraInfo();
        }
        //获取相机个数
        int cameraCount = Camera.getNumberOfCameras();
        if (lens_facing >= cameraCount-1) {
            //获取id最大的一个相机
            lens_facing = cameraCount-1;
        }


        //由于不知道第几个是前置摄像头,遍历获取前置摄像头
        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
            Camera.getCameraInfo(camIdx, cameraInfo);

            if (camIdx == lens_facing) {
                //根据id打开相机
                //Log.d("MainActivity", "相机id为" + camIdx);
                camera = Camera.open(camIdx);
                setPreview();
                break;
            }
        }
    }

    /*
    4.设置预览参数和相机参数后开启预览-----------------------------------------------------------
     */
    public void setPreview() {
        try {
            //设置摄像头参数
            parameters = camera.getParameters();
            //设置预览大小
            parameters.setPreviewSize(1920, 1080);
            //设置图片大小,拍照
            parameters.setPictureSize(1920, 1080);
            //设置预览格式,所有的相机都支持 NV21格式
            parameters.setPreviewFormat(ImageFormat.NV21);
            //设置聚焦
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            // 获取焦距范围
//            List<Integer> zoomRatios = parameters.getZoomRatios();
//
//            // 设置焦距
//            int desiredZoom = 50; // 设置为焦距范围内的一个值
//            int zoomIndex = zoomRatios.indexOf(desiredZoom);
//            parameters.setZoom(zoomIndex);
            //修改相机摄像头参数
            camera.setParameters(parameters);
            //修改相机预览方向
            camera.setDisplayOrientation(adjustCameraOrientation());
            //绑定预览视图
            camera.setPreviewDisplay(surfaceView.getHolder());
            //设置预览数据监听
            camera.setPreviewCallbackWithBuffer(this);
            //开始预览
            camera.startPreview();
        } catch (IOException e) {
        }
    }

    //获取预览最佳尺寸
    private Camera.Size getBestSize() {
        List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
        Camera.Size bestSize = null;
        float uiRatio = (float) longSize / shortSize;
        float minRatio = uiRatio;
        for (Camera.Size previewSize : sizes) {
            float cameraRatio = (float) previewSize.width / previewSize.height;

            //如果找不到比例相同的,找一个最近的,防止预览变形
            float offset = Math.abs(cameraRatio - minRatio);
            if (offset < minRatio) {
                minRatio = offset;
                bestSize = previewSize;
            }
            //比例相同
            if (uiRatio == cameraRatio) {
                bestSize = previewSize;
                break;
            }
        }
        return bestSize;
    }

    /**
     * 调整预览方向
     * 由于手机的图片数据都来自摄像头硬件传感器,这个传感器默认的方向横向的,所以要根据前后摄像头调整方向
     */
    private int adjustCameraOrientation() {
        //判断当前的横竖屏

        int degress = 0;
        //获取手机的方向
        switch (rotation) {
            case Surface.ROTATION_0:
                degress = 0;
                break;
            case Surface.ROTATION_90:
                degress = 90;
                break;
            case Surface.ROTATION_180:
                degress = 180;
                break;
            case Surface.ROTATION_270:
                degress = 270;
                break;
        }
        int result = 0;
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            //后置摄像头
            result = (cameraInfo.orientation - degress + 360) % 360;
        } else if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            //前置摄像头,多一步镜像
            result = (cameraInfo.orientation + degress) % 360;
            result = (360 - result) % 360;
        }
        return result;
    }

    //释放相机资源
    private void releaseCamera() {
        if (camera != null) {
            camera.stopPreview();
            camera.stopFaceDetection();
            camera.setPreviewCallback(null);
            camera.release();
            camera = null;
        }
    }
    private int currentCameraId = 2;
    private void gotoTakePhoto() {
        getCameras(currentCameraId);
        //切换摄像头
        int cameraCount = Camera.getNumberOfCameras();
        if (currentCameraId < cameraCount - 1) {
            currentCameraId += 1;
        } else {
            currentCameraId = 0;
        }
        if (currentCameraId < 0 || currentCameraId >= cameraCount) {
            currentCameraId = 0;
        }
    }
}

下面代码是camera2。可以运行成功,对一些没那么高要求的摄像头还是没问题的。

package com.hs.smart.cabinet.ui;

import android.Manifest;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.Rect;
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.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.hs.smart.cabinet.R;
import com.hs.smart.cabinet.helper.CameraControlsDialogFragment;
import com.hs.smart.cabinet.helper.CameraControlsDialogFragmentTest;
import com.hs.smart.cabinet.helper.ProcessPhotoAsyncTask;
import com.hs.smart.cabinet.utils.MyField;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class TakePhotoZoomActivity extends AppCompatActivity implements View.OnClickListener {
    private SurfaceView surfaceView;
    private Button photograph;
    private Button switchs;
    private CameraControlsDialogFragmentTest mControlsDialog;
    private Button camerasettings;
    private int rotation;
    private int shortSize;
    private int longSize;
    private CameraDevice cameraDevice;
    private CameraCaptureSession captureSession;
    private CaptureRequest.Builder captureRequestBuilder;
    private ImageReader imageReader;
    private CameraManager cameraManager;
    private Handler backgroundHandler;
    private String currentCameraId;
    private SurfaceHolder surfaceHolder;
    private static final int CAMERA_PERMISSION_REQUEST_CODE = 200;
    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

    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);
    }

    private float currentZoomLevel = 1.0f;
    private float currentFocusDistance = 0.0f;
    private boolean supportsAutoFocus;
    private boolean supportsZoom;
    private float maxZoom;
    private boolean cameraCapabilitiesInitialized = false;
    private boolean isDialogVisible = false;
    // 添加变量用于记录当前焦距值


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_take_photo);

        initView();
        HandlerThread handlerThread = new HandlerThread("CameraBackground");
        handlerThread.start();
        backgroundHandler = new Handler(handlerThread.getLooper());
    }

    private void initView() {
        surfaceView = findViewById(R.id.camera_view);
        photograph = findViewById(R.id.photograph);
        switchs = findViewById(R.id.switchs);
        camerasettings = findViewById(R.id.camerasettings);
        photograph.setOnClickListener(this);
        switchs.setOnClickListener(this);
        camerasettings.setOnClickListener(this);

        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(@NonNull SurfaceHolder holder) {
                // Setup camera when the surface is created
                setupAndOpenCamera();
            }

            @Override
            public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
            }

            @Override
            public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
                closeCamera();
            }
        });
    }

    private void setupAndOpenCamera() {
        cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            currentCameraId = cameraManager.getCameraIdList()[0];
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(currentCameraId);

            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            // Continue with your camera setup...
            imageReader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 1);
            cameraManager.openCamera(currentCameraId, new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice camera) {
                    cameraDevice = camera;
                    createCameraPreviewSession();
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice camera) {
                    camera.close();
                    cameraDevice = null;
                }

                @Override
                public void onError(@NonNull CameraDevice camera, int error) {
                    camera.close();
                    cameraDevice = null;
                }
            }, backgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.photograph:
                takePictureWithCurrentFocusDistance();
                break;
            case R.id.switchs:
                switchCamera();
                break;
            case R.id.camerasettings:
                showCameraControlsDialog();
                break;
            default:
                break;
        }
    }

    private void createCameraPreviewSession() {
        try {
            surfaceHolder.setFixedSize(640, 480);
            captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            captureRequestBuilder.addTarget(surfaceHolder.getSurface());

            cameraDevice.createCaptureSession(
                    Arrays.asList(surfaceHolder.getSurface(), imageReader.getSurface()),
                    new CameraCaptureSession.StateCallback() {
                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession session) {
                            if (cameraDevice == null) return;
                            captureSession = session;
                            try {
                                captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                                captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
                            } catch (CameraAccessException e) {
                                e.printStackTrace();
                            }
                        }

                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                        }
                    }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void takePicture() {
        if (cameraDevice == null) return;
        try {
            CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureBuilder.addTarget(imageReader.getSurface());
            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, captureRequestBuilder.get(CaptureRequest.CONTROL_AF_MODE));

            captureSession.stopRepeating();
            captureSession.capture(captureBuilder.build(), new CameraCaptureSession.CaptureCallback() {
                @Override
                public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                    super.onCaptureCompleted(session, request, result);
                    try {
                        captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }
            }, backgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
    private void takePictureWithCurrentFocusDistance() {
        if (cameraDevice == null) return;
        try {
            // 创建新的 CaptureRequest.Builder 对象
            CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureBuilder.addTarget(imageReader.getSurface());

            // 设置最新的焦距值参数
            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF); // 确保对焦模式为手动
            captureBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, currentFocusDistance); // 使用最新的焦距值

            // 暂停重复请求,以便进行单次拍照
            captureSession.stopRepeating();

            // 拍照并在拍照完成后恢复重复请求
            captureSession.capture(captureBuilder.build(), new CameraCaptureSession.CaptureCallback() {
                @Override
                public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                    super.onCaptureCompleted(session, request, result);
                    try {
                        // 拍照完成后,恢复重复请求以保持预览
                        captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }
            }, backgroundHandler);

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            int[] a = new int[2];
            surfaceView.getLocationOnScreen(a);
            shortSize = surfaceView.getHeight();     //横屏为宽度,竖屏为高度
            longSize = surfaceView.getWidth();
            rotation = getWindowManager().getDefaultDisplay().getRotation();
            checkCameraPermission();
        }
    }

    private final Handler processImageHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    String filePath = (String) msg.obj;
                    Intent data = new Intent();
                    data.putExtra(MyField.KEY_CARGO_PHOTO_PATH, filePath);
                    setResult(RESULT_OK, data);
                    finish();
                    break;
                default:
                    break;
            }
        }
    };

    private void checkCameraPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_PERMISSION_REQUEST_CODE);
        } else {
            List<String> usbCameraIds = getUsbCameraIds(getBaseContext());
            setupCamera(usbCameraIds.get(0));
            openCamera();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                setupCamera(Integer.toString(CameraCharacteristics.LENS_FACING_BACK));
                openCamera();
            } else {
                Toast.makeText(this, "拒绝权限,请去设置里面手动开启权限", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void setupCamera(String cameraId) {
        // 初始化 CameraManager
        cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            Log.d("SetupCamera", "Setting up camera with ID: " + cameraId);
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

            // 预览尺寸设置、ImageReader初始化和回调设置
            Size[] sizes = map.getOutputSizes(SurfaceHolder.class);
            Size bestSize = getBestSize(sizes);

            // 配置 ImageReader 用于接收图像数据
            imageReader = ImageReader.newInstance(bestSize.getWidth(), bestSize.getHeight(), ImageFormat.JPEG, 1);
            imageReader.setOnImageAvailableListener(imageAvailableListener, backgroundHandler);

            // 设置当前摄像头 ID
            currentCameraId = cameraId;
        } catch (CameraAccessException e) {
            Log.e("SetupCamera", "CameraAccessException: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private Size getBestSize(Size[] sizes) {
        float uiRatio = (float) longSize / shortSize;
        float minRatio = uiRatio;
        Size bestSize = sizes[0];
        for (Size size : sizes) {
            float cameraRatio = (float) size.getWidth() / size.getHeight();
            float offset = Math.abs(cameraRatio - minRatio);
            if (offset < minRatio) {
                minRatio = offset;
                bestSize = size;
            }
            if (uiRatio == cameraRatio) {
                bestSize = size;
                break;
            }
        }
        return bestSize;
    }

    private void openCamera() {
        try {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            Log.d("OpenCamera", "Opening camera with ID: " + currentCameraId);
            cameraManager.openCamera(currentCameraId, cameraStateCallback, backgroundHandler);
        } catch (CameraAccessException e) {
            Log.e("OpenCamera", "CameraAccessException: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private final CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            cameraDevice = camera;
            createCameraPreviewSession();
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            camera.close();
            cameraDevice = null;
        }

        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
            camera.close();
            cameraDevice = null;
        }
    };


    private final CameraCaptureSession.StateCallback captureStateCallback = new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            captureSession = session;
            try {
                // 自动对焦
                captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                // 开始预览
                captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
            Toast.makeText(TakePhotoZoomActivity.this, "配置失败", Toast.LENGTH_SHORT).show();
        }
    };
    // 镜头图像可用时调用
    private final ImageReader.OnImageAvailableListener imageAvailableListener = new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
            Image image = null;
            try {
                image = reader.acquireLatestImage();
                if (image != null) {
                    // 处理图片数据
                    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    byte[] data = new byte[buffer.remaining()];
                    buffer.get(data);
                    new ProcessPhotoAsyncTask(TakePhotoZoomActivity.this, Integer.valueOf(currentCameraId), data, null, processImageHandler).execute();
                }
            } finally {
                if (image != null) {
                    image.close();
                }
            }
        }
    };

    private void switchCamera() {
        closeCamera();
        if (currentCameraId.equals(Integer.toString(CameraCharacteristics.LENS_FACING_BACK))) {
            setupCamera(Integer.toString(CameraCharacteristics.LENS_FACING_FRONT));
        } else {
            setupCamera(Integer.toString(CameraCharacteristics.LENS_FACING_BACK));
        }
        openCamera();
    }

    @Override
    protected void onPause() {
        closeCamera();
        super.onPause();
    }

    public static List<String> getUsbCameraIds(Context context) {
        List<String> usbCameraIds = new ArrayList<>();
        try {
            CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
            for (String cameraId : cameraManager.getCameraIdList()) {
                CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
                Integer hardwareLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
                if (hardwareLevel != null && hardwareLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL) {
                    usbCameraIds.add(cameraId);
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        return usbCameraIds;
    }


    // 更新缩放
    public void setZoom(float zoomLevel) {
        try {
            Rect zoomRect = calculateZoomRect(zoomLevel);
            CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            captureBuilder.addTarget(imageReader.getSurface());
            captureBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomRect);
            captureSession.setRepeatingRequest(captureBuilder.build(), null, backgroundHandler);
            currentZoomLevel = zoomLevel;
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private Rect calculateZoomRect(float zoomLevel) {
        CameraCharacteristics characteristics = null;
        try {
            characteristics = cameraManager.getCameraCharacteristics(currentCameraId);
        } catch (CameraAccessException e) {
            throw new RuntimeException(e);
        }
        Rect activeArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
        int cropWidth = (int) (activeArraySize.width() / zoomLevel);
        int cropHeight = (int) (activeArraySize.height() / zoomLevel);
        int cropLeft = (activeArraySize.width() - cropWidth) / 2;
        int cropTop = (activeArraySize.height() - cropHeight) / 2;
        return new Rect(cropLeft, cropTop, cropLeft + cropWidth, cropTop + cropHeight);
    }

    private void showCameraControlsDialog() {
        if (!cameraCapabilitiesInitialized) {
            initializeCameraCapabilities();
        }
        if (isDialogVisible) return;

        CameraControlsDialogFragment dialog = CameraControlsDialogFragment.newInstance(supportsAutoFocus, supportsZoom, maxZoom);
        dialog.show(getSupportFragmentManager(), "CameraControlsDialogFragment");
        isDialogVisible = true;

        // 监听对话框消失事件,重置标记
        getSupportFragmentManager().executePendingTransactions();
        dialog.getDialog().setOnDismissListener(dialogInterface -> isDialogVisible = false);
    }

    private void initializeCameraCapabilities() {
        cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(currentCameraId);
            checkCameraCapabilities(characteristics);
            cameraCapabilitiesInitialized = true;
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void checkCameraCapabilities(CameraCharacteristics characteristics) {
        int[] afModes = characteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
        supportsAutoFocus = afModes != null && afModes.length > 0;
        for (int mode : afModes) {
            if (mode == CameraCharacteristics.CONTROL_AF_MODE_OFF) {
                supportsAutoFocus = true;
                break;
            }
        }
        Float maxZoom = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
        supportsZoom = maxZoom != null && maxZoom > 1.0;
        this.maxZoom = supportsZoom ? maxZoom : 1.0f;
    }

    public void setFocusDistance(float distance) {
        if (cameraDevice == null || captureSession == null) return;
        try {
            // 在原有的 captureRequestBuilder 上直接进行修改
            captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
            captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, distance);

            // 重新设置重复请求以应用新的对焦距离
            captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
            currentFocusDistance = distance;
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }


    private void closeCamera() {
        if (captureSession != null) {
            captureSession.close();
            captureSession = null;
        }
        if (cameraDevice != null) {
            cameraDevice.close();
            cameraDevice = null;
        }
        if (imageReader != null) {
            imageReader.close();
            imageReader = null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        closeCamera();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值