如何使用Android中的Camera2 API在不预览的情况下拍摄多张照片?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Android中的Camera2 API在不预览的情况下拍摄多张照片?相关的知识,希望对你有一定的参考价值。

我需要在特定时间间隔(例如5秒)后使用Camera2 API捕获多张照片。我需要在没有预览的情况下进行操作。我可以在不预览的情况下捕获单张照片,但是我需要知道如何捕获多张照片?打开相机后,我不想一次又一次地设置所有参数,我只想在特定间隔后拍摄照片,一旦拍摄完所有照片,便会关闭相机。

也是仅第一次捕获图像。第二次,当我调用takepciture()方法时,什么也没发生。

下面是我的代码。

请帮助。

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
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.CameraMetadata;
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.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import androidx.annotation.NonNull;

import android.util.Log;
import android.util.Size;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class CameraAdmin 

    Context context;

    private static final String TAG = "CameraAdmin";

    private String mCameraId;
    private CameraCaptureSession mCaptureSession;
    private CameraDevice mCameraDevice;

    private HandlerThread backgroundThread;
    private ImageReader imageReader;
    private String cImgType,cFileToSave;
    public boolean CaptureCompleted;
    CaptureRequest.Builder captureBuilder;

    public CameraAdmin(Context context,String CameraID) 
        this.context = context;
        this.mCameraId=CameraID;
        this.CaptureCompleted=false;
    

    public void openCamera() 
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) 
            return;
        
        setUpCameraOutputs();
        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        try 
            manager.openCamera(mCameraId, mStateCallback, null);
         catch (Exception e) 
            e.printStackTrace();

        
    

    private void setUpCameraOutputs() 
        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        try 
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraId);

            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

            imageReader = ImageReader.newInstance(1920, 1080, ImageFormat.JPEG, /*maxImages*/2);
            imageReader.setOnImageAvailableListener(mOnImageAvailableListener, null);

            return;
         catch (CameraAccessException e) 
            e.printStackTrace();
         catch (NullPointerException e) 
            e.printStackTrace();
        
    

    private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() 

        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) 
            mCameraDevice = cameraDevice;
            createCameraCaptureSession();
        

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) 
            cameraDevice.close();
            mCameraDevice = null;
        

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

    ;

    private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() 

        @Override
        public void onImageAvailable(ImageReader reader) 
            Log.d(TAG, "ImageAvailable");
            final Image image = reader.acquireLatestImage();
            final ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            final byte[] bytes = new byte[buffer.capacity()];
            buffer.get(bytes);
            saveImageToDisk(bytes);
            Intent intent = new Intent();
            intent.setAction(MainActivity.MyBroadcastReceiver.ACTION);
            intent.putExtra("dataToPass", "Image Saved!");
            context.sendBroadcast(intent);
            image.close();
        
    ;

    private void saveImageToDisk(final byte[] bytes)
    
        final File file = new File(Environment.getExternalStorageDirectory() + "/" + cFileToSave +".jpg");
        try (final OutputStream output = new FileOutputStream(file)) 
            output.write(bytes);
            Log.d("FileSaved","FileSaved");

         catch (final IOException e) 
            Log.e(TAG, "Exception occurred while saving picture to external storage ", e);
        
    
    public void closeCamera() 
        try 
            if (null != mCaptureSession) 
                mCaptureSession.close();
                mCaptureSession = null;
            
            if (null != mCameraDevice) 
                mCameraDevice.close();
                mCameraDevice = null;
            
            if (null != imageReader) 
                imageReader.close();
                imageReader = null;
            
         catch (Exception e) 
            throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
         finally 
        
    


    private void createCameraCaptureSession() 
        try 

            captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            captureBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,-3);
            captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
            captureBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0f);
            captureBuilder.addTarget(imageReader.getSurface());

            mCameraDevice.createCaptureSession(Arrays.asList(imageReader.getSurface()),
                    new CameraCaptureSession.StateCallback() 
                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) 
                            if (null == mCameraDevice) 
                                return;
                            
                            mCaptureSession = cameraCaptureSession;
                        

                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) 
                            Log.d(TAG, "Configuration Failed");
                        
                    , null
            );
         catch (CameraAccessException e) 
            e.printStackTrace();
        
    

    public void takePicture(String ImgType,String FileToSave) 
        try 
            if (null == mCameraDevice) 
                return;
            
            this.cImgType = ImgType;
            this.cFileToSave = FileToSave;
            CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() 
                @Override
                public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) 
                
            ;

            mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
         catch (CameraAccessException e) 
            e.printStackTrace();
        
        Toast.makeText(context, file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
    

答案

您需要在CameraCaptureSession对象上配置重复请求。有关此文档,请访问:https://developer.android.com/reference/android/hardware/camera2/CameraCaptureSession.html#setRepeatingRequest(android.hardware.camera2.CaptureRequest,%20android.hardware.camera2.CameraCaptureSession.CaptureCallback,%20android.os.Handler)

以上是关于如何使用Android中的Camera2 API在不预览的情况下拍摄多张照片?的主要内容,如果未能解决你的问题,请参考以下文章

如何实现RTMP推送Android Camera2数据

如何使用Android的Camera2 API

如何在 Camera2 API Android 5.0 中获取单个预览帧?

Android:如何检查设备是不是实现了 Camera2 api 功能?

如何实现Android平台GB28181设备对接Camera2数据

Android Camera2 API:捕获视频而不预览