如何在Android中使用Camera2 API拍摄多张照片而不进行预览?
我需要在特定的时间间隔(比如5秒)后使用Camera2 API拍摄多张照片。 我需要在没有预览的情况下完成它。我可以在没有预览的情况下拍摄一张照片,但我需要知道如何拍摄多张照片? 一旦相机打开,我不想一次又一次地设置所有参数,我只想在特定的时间间隔后拍摄照片,一旦拍摄完所有照片,我就会关闭相机 也是第一次拍摄图像。第二次调用takepciture()方法时,什么也没发生 下面是我的代码 请帮忙如何在Android中使用Camera2 API拍摄多张照片而不进行预览?,android,android-camera2,Android,Android Camera2,我需要在特定的时间间隔(比如5秒)后使用Camera2 API拍摄多张照片。 我需要在没有预览的情况下完成它。我可以在没有预览的情况下拍摄一张照片,但我需要知道如何拍摄多张照片? 一旦相机打开,我不想一次又一次地设置所有参数,我只想在特定的时间间隔后拍摄照片,一旦拍摄完所有照片,我就会关闭相机 也是第一次拍摄图像。第二次调用takepciture()方法时,什么也没发生 下面是我的代码 请帮忙 import android.content.Context; import android.cont
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
对象上配置重复请求。此处有相关文档:您需要在CameraCaptureSession
对象上配置重复请求。这里有相关文档:正如我所提到的,我希望以2-3秒的间隔一张一张地拍摄图像,而不进行预览。我计划在后台通过WorkManager完成这项工作。有可能吗?你试过重复的请求了吗?这就是它的设计目的。在onConfigured
回调中。实际上,我尝试使用WorkManager拍摄照片并创建一个Camera类。我想捕捉这些照片,即使用户在活动之间切换。我发现,当活动被切换时,它会捕获一些垃圾图像。@Vito您能在Workmanager中捕获多个垃圾图像吗?我也在尝试着做同样的事情,但直到现在都没有成功。正如我提到的,我想一张一张地拍摄图像,间隔2-3秒,不需要预览。我计划在后台通过WorkManager完成这项工作。有可能吗?你试过重复的请求了吗?这就是它的设计目的。在onConfigured
回调中。实际上,我尝试使用WorkManager拍摄照片并创建一个Camera类。我想捕捉这些照片,即使用户在活动之间切换。我发现,当活动被切换时,它会捕获一些垃圾图像。@Vito您能在Workmanager中捕获多个垃圾图像吗?我也试着这么做,但到现在还没有成功。