使用camera2 API无需预览即可捕获图片

我想要实现的是捕获图片而不显示预览,直接将输出发送到ImageReader 。 我使用Camera2Basic示例作为起点。 但是,我的ImageReader的回调永远不会被调用,因此没有图像被发送到它的Surface 。 我真的需要先显示预览吗?

这是摄像机代码,它按照异步回调的流程排序:

 private ImageReader imageReader; private Handler backgroundHandler; private HandlerThread backgroundThread; private String cameraId; private CameraDevice cameraDevice; private CameraCaptureSession cameraCaptureSession; @Override public void onCreate() { setupCamera2(); } private void setupCamera2() { CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { for (String cameraId : manager.getCameraIdList()) { CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); if (characteristics.get(CameraCharacteristics.LENS_FACING) != CameraCharacteristics.LENS_FACING_FRONT) { continue; } this.cameraId = cameraId; int[] picSize = Settings.getPictureSize(); int picWidth = picSize[0]; int picHeight = picSize[1]; imageReader = ImageReader.newInstance(picWidth, picHeight, ImageFormat.JPEG, 2); imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler); } } catch (CameraAccessException | NullPointerException e) { e.printStackTrace(); } } private void openCamera2() { CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { manager.openCamera(cameraId, cameraStateCallback, backgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } private final CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice device) { cameraDevice = device; createCameraCaptureSession(); } @Override public void onDisconnected(CameraDevice cameraDevice) {} @Override public void onError(CameraDevice cameraDevice, int error) {} }; private void createCaptureSession() { List outputSurfaces = new LinkedList(); outputSurfaces.add(imageReader.getSurface()); try { cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(CameraCaptureSession session) { cameraCaptureSession = session; } @Override public void onConfigureFailed(CameraCaptureSession session) {} }, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private final ImageReader.OnImageAvailableListener onImageAvailableListener = new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { createCaptureRequest(); } }; private void createCaptureRequest() { try { CaptureRequest.Builder requestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); requestBuilder.addTarget(imageReader.getSurface()); // Focus requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // Orientation int rotation = windowManager.getDefaultDisplay().getRotation(); requestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); cameraCaptureSession.capture(requestBuilder.build(), camera2Callback, null); } catch (CameraAccessException e) { e.printStackTrace(); } } 

  • 如何在三星Galaxy Tab上使用相机闪光灯/ LED作为手电筒?
  • 如何检查相机是否被任何应用程序打开
  • Google Vision API示例:让CameraSource成为焦点
  • Android如何修复相机方向
  • NativeScript:自定义摄像头视图
  • 使用input type = file capture = camera在Android浏览器中上传照片时,防止将照片自动保存到图库
  • 用android ndk拍照 - 相机api
  • 在Android中以编程方式确定摄像机分辨率(即百万像素)
  • 您应该在“onConfigured”function中捕获照片,但不能在onImageAvailable上捕获。

     public void onConfigured(CameraCaptureSession session) { cameraCaptureSession = session; createCaptureRequest(); } 

    在这个函数“onImageAvailable”中,你应该保存图像,

     Image image = mImageReader.acquireLatestImage(); ByteBuffer buffer = image.getPlanes()[0].getBuffer(); byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes); try { save(bytes, file); } catch (IOException e) { e.printStackTrace(); } image.close(); 

    在session.capture()之后将调用“onImageAvailable”函数。

    由于我一直在努力寻找它是如何工作的,所以这里是一个可以处理图像数据的最小工作Android服务。 但是,在创建之前可能需要一些时间才能调用启动服务!

     import android.app.Service; import android.content.Intent; import android.graphics.ImageFormat; 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.media.Image; import android.media.ImageReader; import android.os.IBinder; import android.util.Log; import java.util.Arrays; public class VideoProcessingService extends Service { private static final String TAG = "VideoProcessing"; private static final int CAMERA = CameraCharacteristics.LENS_FACING_FRONT; private CameraDevice camera; private CameraCaptureSession session; private ImageReader imageReader; private CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { VideoProcessingService.this.camera = camera; } @Override public void onDisconnected(CameraDevice camera) {} @Override public void onError(CameraDevice camera, int error) {} }; private CameraCaptureSession.StateCallback sessionStateCallback = new CameraCaptureSession.StateCallback() { @Override public void onConfigured(CameraCaptureSession session) { VideoProcessingService.this.session = session; try { session.setRepeatingRequest(createCaptureRequest(), null, null); } catch (CameraAccessException e){ Log.e(TAG, e.getMessage()); } } @Override public void onConfigureFailed(CameraCaptureSession session) {} }; private ImageReader.OnImageAvailableListener onImageAvailableListener = new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader){ Image img = reader.acquireLatestImage(); processImage(img); img.close(); } }; @Override public void onCreate() { CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE); try { manager.openCamera(getCamera(manager), cameraStateCallback, null); imageReader = ImageReader.newInstance(320, 240, ImageFormat.YUV_420_888, 30 * 600); //fps * 10 min imageReader.setOnImageAvailableListener(onImageAvailableListener, null); } catch (CameraAccessException e){ Log.e(TAG, e.getMessage()); } } /** * Return the Camera Id which matches the field CAMERA. */ public String getCamera(CameraManager manager){ try { for (String cameraId : manager.getCameraIdList()) { CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING); if (cOrientation == CAMERA) { return cameraId; } } } catch (CameraAccessException e){ e.printStackTrace(); } return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { try { camera.createCaptureSession(Arrays.asList(imageReader.getSurface()), sessionStateCallback, null); } catch (CameraAccessException e){ Log.e(TAG, e.getMessage()); } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { try { session.abortCaptures(); } catch (CameraAccessException e){ Log.e(TAG, e.getMessage()); } session.close(); } /** * Process image data as desired. */ private void processImage(Image image){ //Process image data } private CaptureRequest createCaptureRequest() { try { CaptureRequest.Builder builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); builder.addTarget(imageReader.getSurface()); return builder.build(); } catch (CameraAccessException e) { Log.e(TAG, e.getMessage()); return null; } } @Override public IBinder onBind(Intent intent) { return null; } } 

    由于我长期以来一直在努力使用CAMERA2 API,寻找如何在设备上没有预览的情况下拍摄照片,我在GitHub上创建了一个完全符合你想要的项目(也许更多) https ://github.com/hzitoun/android-camera2-secret-picture-taker

    在此处输入图像描述

    希望有帮助:)