当前位置:   article > 正文

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

安卓uvc 摄像头

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

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

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

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

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

  1. package com.hs.smart.cabinet.ui;
  2. import android.Manifest;
  3. import android.content.Intent;
  4. import android.content.pm.PackageManager;
  5. import android.graphics.ImageFormat;
  6. import android.hardware.Camera;
  7. import android.os.AsyncTask;
  8. import android.os.Bundle;
  9. import android.os.Handler;
  10. import android.os.Message;
  11. import android.view.Surface;
  12. import android.view.SurfaceView;
  13. import android.view.View;
  14. import android.widget.Button;
  15. import android.widget.Toast;
  16. import androidx.appcompat.app.AppCompatActivity;
  17. import androidx.core.app.ActivityCompat;
  18. import androidx.core.content.ContextCompat;
  19. import com.donkingliang.imageselector.ImageSelectorActivity;
  20. import com.hs.smart.cabinet.R;
  21. import com.hs.smart.cabinet.helper.CameraControlsDialogFragment;
  22. import com.hs.smart.cabinet.helper.ProcessPhotoAsyncTask;
  23. import com.hs.smart.cabinet.utils.MyField;
  24. import java.io.IOException;
  25. import java.util.List;
  26. import android.widget.SeekBar;
  27. /************************************
  28. *@desc:这是拍照页面,使用第三个摄像头拍照
  29. * 即涉案涉财柜中的第三个摄像头
  30. *@Author: admin
  31. *@DateTime:2024/4/2 11:59
  32. *@Copyright: hskj
  33. *************************************/
  34. public class TakePhotoActivity extends AppCompatActivity
  35. implements View.OnClickListener, Camera.PreviewCallback {
  36. private SurfaceView surfaceView;
  37. private Button photograph;
  38. private Button switchs;
  39. private CameraControlsDialogFragment mControlsDialog;
  40. private Button camerasettings;
  41. private int rotation;
  42. private int shortSize;
  43. private int longSize;
  44. private Camera camera;
  45. private Camera.CameraInfo cameraInfo;
  46. private Camera.Parameters parameters;
  47. @Override
  48. protected void onCreate(Bundle savedInstanceState) {
  49. super.onCreate(savedInstanceState);
  50. setContentView(R.layout.activity_take_photo);
  51. initView();
  52. }
  53. private void initView() {
  54. surfaceView = (SurfaceView) findViewById(R.id.camera_view);
  55. photograph = (Button) findViewById(R.id.photograph);
  56. switchs = (Button) findViewById(R.id.switchs);
  57. camerasettings = (Button) findViewById(R.id.camerasettings);
  58. photograph.setOnClickListener(this);
  59. switchs.setOnClickListener(this);
  60. camerasettings.setOnClickListener(this);
  61. }
  62. @Override
  63. public void onClick(View v) {
  64. switch (v.getId()) {
  65. case R.id.photograph: //拍照
  66. if (camera == null) {
  67. Toast.makeText(this, "请打开相机", Toast.LENGTH_SHORT).show();
  68. return;
  69. }
  70. parameters = camera.getParameters();
  71. parameters.setPictureFormat(ImageFormat.JPEG);
  72. camera.setParameters(parameters);
  73. camera.startPreview();
  74. camera.takePicture(null, null, new Camera.PictureCallback() {
  75. @Override
  76. public void onPictureTaken(byte[] data, Camera camera) {
  77. ProcessPhotoAsyncTask myTask = new ProcessPhotoAsyncTask(TakePhotoActivity.this,
  78. cameraInfo.facing,
  79. data,
  80. camera,
  81. processImageHandler
  82. );
  83. myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
  84. }
  85. });
  86. break;
  87. case R.id.switchs:
  88. gotoTakePhoto();
  89. break;
  90. case R.id.camerasettings:
  91. showCameraControlsDialog();
  92. break;
  93. }
  94. }
  95. private void showCameraControlsDialog() {
  96. if (mControlsDialog == null) {
  97. mControlsDialog = new CameraControlsDialogFragment();
  98. }
  99. // When DialogFragment is not showing
  100. if (!mControlsDialog.isAdded()) {
  101. mControlsDialog.show(getSupportFragmentManager(), "controls_dialog");
  102. }
  103. }
  104. @Override
  105. public void onWindowFocusChanged(boolean hasFocus) {
  106. super.onWindowFocusChanged(hasFocus);
  107. if (hasFocus) {
  108. int[] a = new int[2];
  109. surfaceView.getLocationOnScreen(a);
  110. shortSize = surfaceView.getHeight(); //横屏为宽度,竖屏为高度
  111. longSize = surfaceView.getWidth();
  112. rotation = getWindowManager().getDefaultDisplay().getRotation();
  113. cameraInfo = new Camera.CameraInfo();
  114. checkCameraPermission();
  115. }
  116. }
  117. private Handler processImageHandler = new Handler() {
  118. @Override
  119. public void handleMessage(Message msg) {
  120. switch (msg.what) {
  121. case 1:
  122. String filePath = (String) msg.obj;
  123. Intent data = new Intent();
  124. data.putExtra(MyField.KEY_CARGO_PHOTO_PATH, filePath);
  125. setResult(RESULT_OK, data);
  126. finish();
  127. break;
  128. default:
  129. break;
  130. }
  131. }
  132. };
  133. // 1.申请相机权限---------------------------------------------------------------------------
  134. private void checkCameraPermission() {
  135. //检查是否有相机权限
  136. if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED &&
  137. ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
  138. //没权限,请求权限
  139. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
  140. 1);
  141. } else {
  142. //有权限
  143. //Log.d("MainActivity", "有权限");
  144. getCameras(0); //0为后摄,1为前摄
  145. }
  146. }
  147. //权限请求回调
  148. @Override
  149. public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
  150. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  151. switch (requestCode) {
  152. case 1:
  153. if (grantResults != null && grantResults.length > 0
  154. && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  155. //用户同意权限
  156. getCameras(0); //0为后摄,1为前摄
  157. } else {
  158. // 权限被用户拒绝了,可以提示用户,关闭界面等等。
  159. Toast.makeText(this, "拒绝权限,请去设置里面手动开启权限", Toast.LENGTH_SHORT).show();
  160. }
  161. break;
  162. }
  163. }
  164. //预览数据监听
  165. @Override
  166. public void onPreviewFrame(byte[] data, Camera camera) {
  167. camera.addCallbackBuffer(data);
  168. }
  169. /*
  170. 3.查找指定摄像头ID,根据摄像头ID打开指定的相机----------------------------------------------------------------------------------------------
  171. 根据摄像头的朝向查找指定摄像头id
  172. 0代表后摄的朝向,但是它不一定是后摄的id
  173. 1代表前摄的朝向
  174. */
  175. public void getCameras(int lens_facing) {
  176. //先释放相机资源
  177. releaseCamera();
  178. //获取相机信息
  179. if (cameraInfo == null) {
  180. cameraInfo = new Camera.CameraInfo();
  181. }
  182. //获取相机个数
  183. int cameraCount = Camera.getNumberOfCameras();
  184. if (lens_facing >= cameraCount-1) {
  185. //获取id最大的一个相机
  186. lens_facing = cameraCount-1;
  187. }
  188. //由于不知道第几个是前置摄像头,遍历获取前置摄像头
  189. for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
  190. Camera.getCameraInfo(camIdx, cameraInfo);
  191. if (camIdx == lens_facing) {
  192. //根据id打开相机
  193. //Log.d("MainActivity", "相机id为" + camIdx);
  194. camera = Camera.open(camIdx);
  195. setPreview();
  196. break;
  197. }
  198. }
  199. }
  200. /*
  201. 4.设置预览参数和相机参数后开启预览-----------------------------------------------------------
  202. */
  203. public void setPreview() {
  204. try {
  205. //设置摄像头参数
  206. parameters = camera.getParameters();
  207. //设置预览大小
  208. parameters.setPreviewSize(1920, 1080);
  209. //设置图片大小,拍照
  210. parameters.setPictureSize(1920, 1080);
  211. //设置预览格式,所有的相机都支持 NV21格式
  212. parameters.setPreviewFormat(ImageFormat.NV21);
  213. //设置聚焦
  214. parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
  215. // 获取焦距范围
  216. // List<Integer> zoomRatios = parameters.getZoomRatios();
  217. //
  218. // // 设置焦距
  219. // int desiredZoom = 50; // 设置为焦距范围内的一个值
  220. // int zoomIndex = zoomRatios.indexOf(desiredZoom);
  221. // parameters.setZoom(zoomIndex);
  222. //修改相机摄像头参数
  223. camera.setParameters(parameters);
  224. //修改相机预览方向
  225. camera.setDisplayOrientation(adjustCameraOrientation());
  226. //绑定预览视图
  227. camera.setPreviewDisplay(surfaceView.getHolder());
  228. //设置预览数据监听
  229. camera.setPreviewCallbackWithBuffer(this);
  230. //开始预览
  231. camera.startPreview();
  232. } catch (IOException e) {
  233. }
  234. }
  235. //获取预览最佳尺寸
  236. private Camera.Size getBestSize() {
  237. List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
  238. Camera.Size bestSize = null;
  239. float uiRatio = (float) longSize / shortSize;
  240. float minRatio = uiRatio;
  241. for (Camera.Size previewSize : sizes) {
  242. float cameraRatio = (float) previewSize.width / previewSize.height;
  243. //如果找不到比例相同的,找一个最近的,防止预览变形
  244. float offset = Math.abs(cameraRatio - minRatio);
  245. if (offset < minRatio) {
  246. minRatio = offset;
  247. bestSize = previewSize;
  248. }
  249. //比例相同
  250. if (uiRatio == cameraRatio) {
  251. bestSize = previewSize;
  252. break;
  253. }
  254. }
  255. return bestSize;
  256. }
  257. /**
  258. * 调整预览方向
  259. * 由于手机的图片数据都来自摄像头硬件传感器,这个传感器默认的方向横向的,所以要根据前后摄像头调整方向
  260. */
  261. private int adjustCameraOrientation() {
  262. //判断当前的横竖屏
  263. int degress = 0;
  264. //获取手机的方向
  265. switch (rotation) {
  266. case Surface.ROTATION_0:
  267. degress = 0;
  268. break;
  269. case Surface.ROTATION_90:
  270. degress = 90;
  271. break;
  272. case Surface.ROTATION_180:
  273. degress = 180;
  274. break;
  275. case Surface.ROTATION_270:
  276. degress = 270;
  277. break;
  278. }
  279. int result = 0;
  280. if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
  281. //后置摄像头
  282. result = (cameraInfo.orientation - degress + 360) % 360;
  283. } else if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
  284. //前置摄像头,多一步镜像
  285. result = (cameraInfo.orientation + degress) % 360;
  286. result = (360 - result) % 360;
  287. }
  288. return result;
  289. }
  290. //释放相机资源
  291. private void releaseCamera() {
  292. if (camera != null) {
  293. camera.stopPreview();
  294. camera.stopFaceDetection();
  295. camera.setPreviewCallback(null);
  296. camera.release();
  297. camera = null;
  298. }
  299. }
  300. private int currentCameraId = 2;
  301. private void gotoTakePhoto() {
  302. getCameras(currentCameraId);
  303. //切换摄像头
  304. int cameraCount = Camera.getNumberOfCameras();
  305. if (currentCameraId < cameraCount - 1) {
  306. currentCameraId += 1;
  307. } else {
  308. currentCameraId = 0;
  309. }
  310. if (currentCameraId < 0 || currentCameraId >= cameraCount) {
  311. currentCameraId = 0;
  312. }
  313. }
  314. }

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

  1. package com.hs.smart.cabinet.ui;
  2. import android.Manifest;
  3. import android.content.Context;
  4. import android.content.DialogInterface;
  5. import android.content.Intent;
  6. import android.content.pm.PackageManager;
  7. import android.graphics.ImageFormat;
  8. import android.graphics.Rect;
  9. import android.hardware.camera2.CameraAccessException;
  10. import android.hardware.camera2.CameraCaptureSession;
  11. import android.hardware.camera2.CameraCharacteristics;
  12. import android.hardware.camera2.CameraDevice;
  13. import android.hardware.camera2.CameraManager;
  14. import android.hardware.camera2.CaptureRequest;
  15. import android.hardware.camera2.TotalCaptureResult;
  16. import android.hardware.camera2.params.StreamConfigurationMap;
  17. import android.media.Image;
  18. import android.media.ImageReader;
  19. import android.os.Bundle;
  20. import android.os.Handler;
  21. import android.os.HandlerThread;
  22. import android.os.Message;
  23. import android.util.Log;
  24. import android.util.Size;
  25. import android.util.SparseIntArray;
  26. import android.view.Surface;
  27. import android.view.SurfaceHolder;
  28. import android.view.SurfaceView;
  29. import android.view.View;
  30. import android.widget.Button;
  31. import android.widget.Toast;
  32. import androidx.annotation.NonNull;
  33. import androidx.appcompat.app.AppCompatActivity;
  34. import androidx.core.app.ActivityCompat;
  35. import androidx.core.content.ContextCompat;
  36. import com.hs.smart.cabinet.R;
  37. import com.hs.smart.cabinet.helper.CameraControlsDialogFragment;
  38. import com.hs.smart.cabinet.helper.CameraControlsDialogFragmentTest;
  39. import com.hs.smart.cabinet.helper.ProcessPhotoAsyncTask;
  40. import com.hs.smart.cabinet.utils.MyField;
  41. import java.nio.ByteBuffer;
  42. import java.util.ArrayList;
  43. import java.util.Arrays;
  44. import java.util.List;
  45. public class TakePhotoZoomActivity extends AppCompatActivity implements View.OnClickListener {
  46. private SurfaceView surfaceView;
  47. private Button photograph;
  48. private Button switchs;
  49. private CameraControlsDialogFragmentTest mControlsDialog;
  50. private Button camerasettings;
  51. private int rotation;
  52. private int shortSize;
  53. private int longSize;
  54. private CameraDevice cameraDevice;
  55. private CameraCaptureSession captureSession;
  56. private CaptureRequest.Builder captureRequestBuilder;
  57. private ImageReader imageReader;
  58. private CameraManager cameraManager;
  59. private Handler backgroundHandler;
  60. private String currentCameraId;
  61. private SurfaceHolder surfaceHolder;
  62. private static final int CAMERA_PERMISSION_REQUEST_CODE = 200;
  63. private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
  64. static {
  65. ORIENTATIONS.append(Surface.ROTATION_0, 90);
  66. ORIENTATIONS.append(Surface.ROTATION_90, 0);
  67. ORIENTATIONS.append(Surface.ROTATION_180, 270);
  68. ORIENTATIONS.append(Surface.ROTATION_270, 180);
  69. }
  70. private float currentZoomLevel = 1.0f;
  71. private float currentFocusDistance = 0.0f;
  72. private boolean supportsAutoFocus;
  73. private boolean supportsZoom;
  74. private float maxZoom;
  75. private boolean cameraCapabilitiesInitialized = false;
  76. private boolean isDialogVisible = false;
  77. // 添加变量用于记录当前焦距值
  78. @Override
  79. protected void onCreate(Bundle savedInstanceState) {
  80. super.onCreate(savedInstanceState);
  81. setContentView(R.layout.activity_take_photo);
  82. initView();
  83. HandlerThread handlerThread = new HandlerThread("CameraBackground");
  84. handlerThread.start();
  85. backgroundHandler = new Handler(handlerThread.getLooper());
  86. }
  87. private void initView() {
  88. surfaceView = findViewById(R.id.camera_view);
  89. photograph = findViewById(R.id.photograph);
  90. switchs = findViewById(R.id.switchs);
  91. camerasettings = findViewById(R.id.camerasettings);
  92. photograph.setOnClickListener(this);
  93. switchs.setOnClickListener(this);
  94. camerasettings.setOnClickListener(this);
  95. surfaceHolder = surfaceView.getHolder();
  96. surfaceHolder.addCallback(new SurfaceHolder.Callback() {
  97. @Override
  98. public void surfaceCreated(@NonNull SurfaceHolder holder) {
  99. // Setup camera when the surface is created
  100. setupAndOpenCamera();
  101. }
  102. @Override
  103. public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
  104. }
  105. @Override
  106. public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
  107. closeCamera();
  108. }
  109. });
  110. }
  111. private void setupAndOpenCamera() {
  112. cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
  113. try {
  114. currentCameraId = cameraManager.getCameraIdList()[0];
  115. CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(currentCameraId);
  116. StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
  117. // Continue with your camera setup...
  118. imageReader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 1);
  119. cameraManager.openCamera(currentCameraId, new CameraDevice.StateCallback() {
  120. @Override
  121. public void onOpened(@NonNull CameraDevice camera) {
  122. cameraDevice = camera;
  123. createCameraPreviewSession();
  124. }
  125. @Override
  126. public void onDisconnected(@NonNull CameraDevice camera) {
  127. camera.close();
  128. cameraDevice = null;
  129. }
  130. @Override
  131. public void onError(@NonNull CameraDevice camera, int error) {
  132. camera.close();
  133. cameraDevice = null;
  134. }
  135. }, backgroundHandler);
  136. } catch (CameraAccessException e) {
  137. e.printStackTrace();
  138. } catch (SecurityException e) {
  139. e.printStackTrace();
  140. }
  141. }
  142. @Override
  143. public void onClick(View v) {
  144. switch (v.getId()) {
  145. case R.id.photograph:
  146. takePictureWithCurrentFocusDistance();
  147. break;
  148. case R.id.switchs:
  149. switchCamera();
  150. break;
  151. case R.id.camerasettings:
  152. showCameraControlsDialog();
  153. break;
  154. default:
  155. break;
  156. }
  157. }
  158. private void createCameraPreviewSession() {
  159. try {
  160. surfaceHolder.setFixedSize(640, 480);
  161. captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
  162. captureRequestBuilder.addTarget(surfaceHolder.getSurface());
  163. cameraDevice.createCaptureSession(
  164. Arrays.asList(surfaceHolder.getSurface(), imageReader.getSurface()),
  165. new CameraCaptureSession.StateCallback() {
  166. @Override
  167. public void onConfigured(@NonNull CameraCaptureSession session) {
  168. if (cameraDevice == null) return;
  169. captureSession = session;
  170. try {
  171. captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
  172. captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
  173. } catch (CameraAccessException e) {
  174. e.printStackTrace();
  175. }
  176. }
  177. @Override
  178. public void onConfigureFailed(@NonNull CameraCaptureSession session) {
  179. }
  180. }, null);
  181. } catch (CameraAccessException e) {
  182. e.printStackTrace();
  183. }
  184. }
  185. private void takePicture() {
  186. if (cameraDevice == null) return;
  187. try {
  188. CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
  189. captureBuilder.addTarget(imageReader.getSurface());
  190. captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, captureRequestBuilder.get(CaptureRequest.CONTROL_AF_MODE));
  191. captureSession.stopRepeating();
  192. captureSession.capture(captureBuilder.build(), new CameraCaptureSession.CaptureCallback() {
  193. @Override
  194. public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
  195. super.onCaptureCompleted(session, request, result);
  196. try {
  197. captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
  198. } catch (CameraAccessException e) {
  199. e.printStackTrace();
  200. }
  201. }
  202. }, backgroundHandler);
  203. } catch (CameraAccessException e) {
  204. e.printStackTrace();
  205. }
  206. }
  207. private void takePictureWithCurrentFocusDistance() {
  208. if (cameraDevice == null) return;
  209. try {
  210. // 创建新的 CaptureRequest.Builder 对象
  211. CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
  212. captureBuilder.addTarget(imageReader.getSurface());
  213. // 设置最新的焦距值参数
  214. captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF); // 确保对焦模式为手动
  215. captureBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, currentFocusDistance); // 使用最新的焦距值
  216. // 暂停重复请求,以便进行单次拍照
  217. captureSession.stopRepeating();
  218. // 拍照并在拍照完成后恢复重复请求
  219. captureSession.capture(captureBuilder.build(), new CameraCaptureSession.CaptureCallback() {
  220. @Override
  221. public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
  222. super.onCaptureCompleted(session, request, result);
  223. try {
  224. // 拍照完成后,恢复重复请求以保持预览
  225. captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
  226. } catch (CameraAccessException e) {
  227. e.printStackTrace();
  228. }
  229. }
  230. }, backgroundHandler);
  231. } catch (CameraAccessException e) {
  232. e.printStackTrace();
  233. }
  234. }
  235. @Override
  236. public void onWindowFocusChanged(boolean hasFocus) {
  237. super.onWindowFocusChanged(hasFocus);
  238. if (hasFocus) {
  239. int[] a = new int[2];
  240. surfaceView.getLocationOnScreen(a);
  241. shortSize = surfaceView.getHeight(); //横屏为宽度,竖屏为高度
  242. longSize = surfaceView.getWidth();
  243. rotation = getWindowManager().getDefaultDisplay().getRotation();
  244. checkCameraPermission();
  245. }
  246. }
  247. private final Handler processImageHandler = new Handler() {
  248. @Override
  249. public void handleMessage(Message msg) {
  250. switch (msg.what) {
  251. case 1:
  252. String filePath = (String) msg.obj;
  253. Intent data = new Intent();
  254. data.putExtra(MyField.KEY_CARGO_PHOTO_PATH, filePath);
  255. setResult(RESULT_OK, data);
  256. finish();
  257. break;
  258. default:
  259. break;
  260. }
  261. }
  262. };
  263. private void checkCameraPermission() {
  264. if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
  265. ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
  266. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_PERMISSION_REQUEST_CODE);
  267. } else {
  268. List<String> usbCameraIds = getUsbCameraIds(getBaseContext());
  269. setupCamera(usbCameraIds.get(0));
  270. openCamera();
  271. }
  272. }
  273. @Override
  274. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  275. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  276. if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
  277. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  278. setupCamera(Integer.toString(CameraCharacteristics.LENS_FACING_BACK));
  279. openCamera();
  280. } else {
  281. Toast.makeText(this, "拒绝权限,请去设置里面手动开启权限", Toast.LENGTH_SHORT).show();
  282. }
  283. }
  284. }
  285. private void setupCamera(String cameraId) {
  286. // 初始化 CameraManager
  287. cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
  288. try {
  289. Log.d("SetupCamera", "Setting up camera with ID: " + cameraId);
  290. CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
  291. StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
  292. // 预览尺寸设置、ImageReader初始化和回调设置
  293. Size[] sizes = map.getOutputSizes(SurfaceHolder.class);
  294. Size bestSize = getBestSize(sizes);
  295. // 配置 ImageReader 用于接收图像数据
  296. imageReader = ImageReader.newInstance(bestSize.getWidth(), bestSize.getHeight(), ImageFormat.JPEG, 1);
  297. imageReader.setOnImageAvailableListener(imageAvailableListener, backgroundHandler);
  298. // 设置当前摄像头 ID
  299. currentCameraId = cameraId;
  300. } catch (CameraAccessException e) {
  301. Log.e("SetupCamera", "CameraAccessException: " + e.getMessage());
  302. e.printStackTrace();
  303. }
  304. }
  305. private Size getBestSize(Size[] sizes) {
  306. float uiRatio = (float) longSize / shortSize;
  307. float minRatio = uiRatio;
  308. Size bestSize = sizes[0];
  309. for (Size size : sizes) {
  310. float cameraRatio = (float) size.getWidth() / size.getHeight();
  311. float offset = Math.abs(cameraRatio - minRatio);
  312. if (offset < minRatio) {
  313. minRatio = offset;
  314. bestSize = size;
  315. }
  316. if (uiRatio == cameraRatio) {
  317. bestSize = size;
  318. break;
  319. }
  320. }
  321. return bestSize;
  322. }
  323. private void openCamera() {
  324. try {
  325. if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
  326. return;
  327. }
  328. Log.d("OpenCamera", "Opening camera with ID: " + currentCameraId);
  329. cameraManager.openCamera(currentCameraId, cameraStateCallback, backgroundHandler);
  330. } catch (CameraAccessException e) {
  331. Log.e("OpenCamera", "CameraAccessException: " + e.getMessage());
  332. e.printStackTrace();
  333. }
  334. }
  335. private final CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() {
  336. @Override
  337. public void onOpened(@NonNull CameraDevice camera) {
  338. cameraDevice = camera;
  339. createCameraPreviewSession();
  340. }
  341. @Override
  342. public void onDisconnected(@NonNull CameraDevice camera) {
  343. camera.close();
  344. cameraDevice = null;
  345. }
  346. @Override
  347. public void onError(@NonNull CameraDevice camera, int error) {
  348. camera.close();
  349. cameraDevice = null;
  350. }
  351. };
  352. private final CameraCaptureSession.StateCallback captureStateCallback = new CameraCaptureSession.StateCallback() {
  353. @Override
  354. public void onConfigured(@NonNull CameraCaptureSession session) {
  355. captureSession = session;
  356. try {
  357. // 自动对焦
  358. captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
  359. // 开始预览
  360. captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
  361. } catch (CameraAccessException e) {
  362. e.printStackTrace();
  363. }
  364. }
  365. @Override
  366. public void onConfigureFailed(@NonNull CameraCaptureSession session) {
  367. Toast.makeText(TakePhotoZoomActivity.this, "配置失败", Toast.LENGTH_SHORT).show();
  368. }
  369. };
  370. // 镜头图像可用时调用
  371. private final ImageReader.OnImageAvailableListener imageAvailableListener = new ImageReader.OnImageAvailableListener() {
  372. @Override
  373. public void onImageAvailable(ImageReader reader) {
  374. Image image = null;
  375. try {
  376. image = reader.acquireLatestImage();
  377. if (image != null) {
  378. // 处理图片数据
  379. ByteBuffer buffer = image.getPlanes()[0].getBuffer();
  380. byte[] data = new byte[buffer.remaining()];
  381. buffer.get(data);
  382. new ProcessPhotoAsyncTask(TakePhotoZoomActivity.this, Integer.valueOf(currentCameraId), data, null, processImageHandler).execute();
  383. }
  384. } finally {
  385. if (image != null) {
  386. image.close();
  387. }
  388. }
  389. }
  390. };
  391. private void switchCamera() {
  392. closeCamera();
  393. if (currentCameraId.equals(Integer.toString(CameraCharacteristics.LENS_FACING_BACK))) {
  394. setupCamera(Integer.toString(CameraCharacteristics.LENS_FACING_FRONT));
  395. } else {
  396. setupCamera(Integer.toString(CameraCharacteristics.LENS_FACING_BACK));
  397. }
  398. openCamera();
  399. }
  400. @Override
  401. protected void onPause() {
  402. closeCamera();
  403. super.onPause();
  404. }
  405. public static List<String> getUsbCameraIds(Context context) {
  406. List<String> usbCameraIds = new ArrayList<>();
  407. try {
  408. CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
  409. for (String cameraId : cameraManager.getCameraIdList()) {
  410. CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
  411. Integer hardwareLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
  412. if (hardwareLevel != null && hardwareLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL) {
  413. usbCameraIds.add(cameraId);
  414. }
  415. }
  416. } catch (CameraAccessException e) {
  417. e.printStackTrace();
  418. }
  419. return usbCameraIds;
  420. }
  421. // 更新缩放
  422. public void setZoom(float zoomLevel) {
  423. try {
  424. Rect zoomRect = calculateZoomRect(zoomLevel);
  425. CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
  426. captureBuilder.addTarget(imageReader.getSurface());
  427. captureBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomRect);
  428. captureSession.setRepeatingRequest(captureBuilder.build(), null, backgroundHandler);
  429. currentZoomLevel = zoomLevel;
  430. } catch (CameraAccessException e) {
  431. e.printStackTrace();
  432. }
  433. }
  434. private Rect calculateZoomRect(float zoomLevel) {
  435. CameraCharacteristics characteristics = null;
  436. try {
  437. characteristics = cameraManager.getCameraCharacteristics(currentCameraId);
  438. } catch (CameraAccessException e) {
  439. throw new RuntimeException(e);
  440. }
  441. Rect activeArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
  442. int cropWidth = (int) (activeArraySize.width() / zoomLevel);
  443. int cropHeight = (int) (activeArraySize.height() / zoomLevel);
  444. int cropLeft = (activeArraySize.width() - cropWidth) / 2;
  445. int cropTop = (activeArraySize.height() - cropHeight) / 2;
  446. return new Rect(cropLeft, cropTop, cropLeft + cropWidth, cropTop + cropHeight);
  447. }
  448. private void showCameraControlsDialog() {
  449. if (!cameraCapabilitiesInitialized) {
  450. initializeCameraCapabilities();
  451. }
  452. if (isDialogVisible) return;
  453. CameraControlsDialogFragment dialog = CameraControlsDialogFragment.newInstance(supportsAutoFocus, supportsZoom, maxZoom);
  454. dialog.show(getSupportFragmentManager(), "CameraControlsDialogFragment");
  455. isDialogVisible = true;
  456. // 监听对话框消失事件,重置标记
  457. getSupportFragmentManager().executePendingTransactions();
  458. dialog.getDialog().setOnDismissListener(dialogInterface -> isDialogVisible = false);
  459. }
  460. private void initializeCameraCapabilities() {
  461. cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
  462. try {
  463. CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(currentCameraId);
  464. checkCameraCapabilities(characteristics);
  465. cameraCapabilitiesInitialized = true;
  466. } catch (CameraAccessException e) {
  467. e.printStackTrace();
  468. }
  469. }
  470. private void checkCameraCapabilities(CameraCharacteristics characteristics) {
  471. int[] afModes = characteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
  472. supportsAutoFocus = afModes != null && afModes.length > 0;
  473. for (int mode : afModes) {
  474. if (mode == CameraCharacteristics.CONTROL_AF_MODE_OFF) {
  475. supportsAutoFocus = true;
  476. break;
  477. }
  478. }
  479. Float maxZoom = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
  480. supportsZoom = maxZoom != null && maxZoom > 1.0;
  481. this.maxZoom = supportsZoom ? maxZoom : 1.0f;
  482. }
  483. public void setFocusDistance(float distance) {
  484. if (cameraDevice == null || captureSession == null) return;
  485. try {
  486. // 在原有的 captureRequestBuilder 上直接进行修改
  487. captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
  488. captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, distance);
  489. // 重新设置重复请求以应用新的对焦距离
  490. captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
  491. currentFocusDistance = distance;
  492. } catch (CameraAccessException e) {
  493. e.printStackTrace();
  494. }
  495. }
  496. private void closeCamera() {
  497. if (captureSession != null) {
  498. captureSession.close();
  499. captureSession = null;
  500. }
  501. if (cameraDevice != null) {
  502. cameraDevice.close();
  503. cameraDevice = null;
  504. }
  505. if (imageReader != null) {
  506. imageReader.close();
  507. imageReader = null;
  508. }
  509. }
  510. @Override
  511. protected void onDestroy() {
  512. super.onDestroy();
  513. closeCamera();
  514. }
  515. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/1017149
推荐阅读
相关标签
  

闽ICP备14008679号