使用Camera2 后台静默拍照的代码
时间: 2023-11-26 16:14:57 浏览: 165
以下是使用 Camera2 API 进行后台静默拍照的示例代码:
```java
public class Camera2Service extends Service {
private CameraManager mCameraManager;
private ImageReader mImageReader;
private Size mImageSize;
private CameraDevice mCameraDevice;
private CameraCaptureSession mCaptureSession;
private HandlerThread mBackgroundThread;
private Handler mBackgroundHandler;
private static final int STATE_PREVIEW = 0;
private static final int STATE_WAITING_LOCK = 1;
private static final int STATE_WAITING_PRECAPTURE = 2;
private static final int STATE_WAITING_NON_PRECAPTURE = 3;
private static final int STATE_PICTURE_TAKEN = 4;
private int mState = STATE_PREVIEW;
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
startPreview();
}
@Override
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
cameraDevice.close();
mCameraDevice = null;
}
@Override
public void onError(@NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
mCameraDevice = null;
}
};
private final CameraCaptureSession.StateCallback mSessionCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
mCaptureSession = cameraCaptureSession;
try {
CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
builder.addTarget(mImageReader.getSurface());
builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
mCaptureSession.setRepeatingRequest(builder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
}
};
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader imageReader) {
Image image = imageReader.acquireLatestImage();
// do something with the image
image.close();
}
};
@Override
public void onCreate() {
super.onCreate();
mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
mBackgroundThread = new HandlerThread("Camera2Service");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
String cameraId = mCameraManager.getCameraIdList()[0];
CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
StreamConfigurationMap streamConfigurationMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
mImageSize = streamConfigurationMap.getOutputSizes(SurfaceTexture.class)[0];
mImageReader = ImageReader.newInstance(mImageSize.getWidth(), mImageSize.getHeight(), ImageFormat.JPEG, 2);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
mCameraManager.openCamera(cameraId, mStateCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
stopBackgroundThread();
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
}
private void startPreview() {
try {
CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
SurfaceTexture texture = new SurfaceTexture(0);
texture.setDefaultBufferSize(mImageSize.getWidth(), mImageSize.getHeight());
Surface surface = new Surface(texture);
builder.addTarget(surface);
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), mSessionCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void stopBackgroundThread() {
if (mBackgroundThread != null) {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
```
在 `onStartCommand()` 方法中,我们通过 `CameraManager` 获取相机设备,并创建一个 `ImageReader` 对象,用于获取拍照后的图片数据。然后我们在后台线程中打开相机,并在相机设备状态回调中启动预览。当相机预览开始后,我们就可以在 `CameraCaptureSession` 中发起拍照请求,请求的结果会在 `ImageReader.OnImageAvailableListener` 中回调。注意,在 `onDestroy()` 方法中,我们需要释放相机资源和后台线程。
此示例中我们使用了 `CameraDevice.TEMPLATE_RECORD` 模板来创建拍照请求,这样可以确保在后台静默拍照时能够正常工作。如果您需要更多的控制权,可以尝试使用其他模板,例如 `CameraDevice.TEMPLATE_STILL_CAPTURE`。
阅读全文