刚开始使用Camera2框架,因为它增加了对相机底层功能的控制。然而,我在快速打开和关闭手电筒时遇到了一些问题。使用旧的相机API,我可以切换闪光灯,同时提供预览通过:
try
{
android.hardware.Camera.Parameters parameters = c.getParameters();
if (parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_OFF))
{
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
Log.i("HeartBeatAlgorithm", "LightOn");
}
else if (parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_TORCH))
{
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
Log.i("HeartBeatAlgorithm", "LightOff");
}
c.setParameters(parameters);
}
catch (Exception exception)
{
c.release();
c = null;
}
手电筒会很快打开或关闭,不会有任何明显的中断。然而,对于Camera2,闪光模式似乎是CaptureSession的一个属性,这意味着需要创建一个全新的CaptureSession来更改闪光模式,即:
try
{
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface surface = new Surface(texture);
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
if (mLightNowOn == true)
{
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
}
else
{
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
}
mPreviewRequestBuilder.addTarget(surface);
mPreviewRequest = mPreviewRequestBuilder.build();
mCameraDevice.createCaptureSession(Arrays.asList(surface), mSessionStateCallback, null);
}
catch (CameraAccessException e)
{
e.printStackTrace();
}
正如开发人员文档中所提到的,"创建会话是一项昂贵的操作,可能需要数百毫秒,因为它需要配置相机设备的内部管道,并为将图像发送到所需目标分配内存缓冲区。"确实如此,而且我的应用程序在切换闪光灯模式时会出现明显的延迟。
我真的需要能够快速切换闪光灯模式,而不会打断预览太多。有什么办法解决这个问题吗?还是由于新的API管道而不可避免?
并非每次都必须创建全新的捕获会话才能更改闪存模式。相反,您可以在现有的捕获会话上创建重复的预览请求,每次只设置NewRepeating请求,例如:
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE,CaptureRequest.fLASSH_MODE_TORCH);。。。mPreviewRequest=mPreviewRequestBuilder.build();。。。mCaptureSession.setReatingRequest(mPreviewRequest、captureCallBack、backgroundHandler);
您可以多次重复此序列。
这看起来有点古怪,但Ivan的输入对我有效…
如果不明显的话,变量名称看起来像类/接口名称。您必须在外部范围中声明它们。
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
captureRequest = captureRequestBuilder.build();
cameraCaptureSession.setRepeatingRequest(captureRequest, null, backgroundHandler);
torchButton = findViewById(R.id.button);
torchButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(!lightOn) {
try {
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
captureRequest = captureRequestBuilder.build();
cameraCaptureSession.setRepeatingRequest(captureRequest, null, backgroundHandler);
lightOn = true;
} catch (CameraAccessException e) {}
}
else if(lightOn) {
try {
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
captureRequest = captureRequestBuilder.build();
cameraCaptureSession.setRepeatingRequest(captureRequest, null, backgroundHandler);
lightOn = false;
} catch (CameraAccessException e) {}
}
}
});
这样,你可以在关闭手电筒的情况下开始预览,但这可以通过点击按钮来控制。