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