为什么打开闪光灯会改变相机的对焦模式?
Why turning on flash change the focus mode of the camera?
我有 2 个可以通过按钮控制的 AF 焦距和一个用于闪光灯的开关。
为什么if ELSE for flashligh in updatePreview() 会影响对焦模式为auto?当我注释掉该部分时(IF ELSE for flashligh),自动对焦模式和焦距与 btnFocus 配合良好。
如何解决这个问题,同时仍然允许用户打开和关闭手电筒?
private float focusDistance = 0;
private int flashSwitch = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = (TextureView)findViewById(R.id.textureView);
//From Java 1.4 , you can use keyword 'assert' to check expression true or false
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
btnFocus = (Button)findViewById(R.id.btnFocus);
btnFlash = (Button)findViewById(R.id.btnFlash);
btnFocus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
changeFocus();
}
});
btnFlash.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Flash();
}
});
}
private void Flash() {
if(cameraDevice == null)
return;
if(flashSwitch == 0 ) {
Toast.makeText(MainActivity.this, "Flash Turn On ", Toast.LENGTH_SHORT).show();
flashSwitch = 1;
}
else{
Toast.makeText(MainActivity.this, "Flash Turn Off ", Toast.LENGTH_SHORT).show();
flashSwitch = 0;
}
createCameraPreview();
}
private void changeFocus() {
if(cameraDevice == null)
return;
if(focusDistance == 0 )
focusDistance = 10;
else
focusDistance = 0;
Toast.makeText(MainActivity.this, "Focus Change "+ focusDistance, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
private void createCameraPreview() {
try{
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(),imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
if(cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(MainActivity.this, "Changed", Toast.LENGTH_SHORT).show();
}
},null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
如果您取消注释部分,问题将在打开闪光灯和更改焦点时出现。
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
try{
// if you uncomment this part the problem will come out
// if(flashSwitch == 0){
// captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
// }
// else{
// captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
// }
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_OFF);
captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, focusDistance);
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
预期输出
可以在不影响对焦模式的情况下手动打开和关闭闪光灯。
在 updatePreview()
中,您在 captureRequestBuilder
中解决所有密钥之前向 cameraCaptureSessions
发送了多个捕获请求。尝试先设置所有键,然后发送一个重复的捕获请求。
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
try{
if(flashSwitch == 0){
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
}
else{
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
}
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_OFF);
captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, focusDistance);
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
我认为您的问题可能出在您设置请求的方式上。
您应该首先创建预览,并且只创建一次,按照您的方式,每次切换 flash and/or 焦点时都在创建预览。
我建议使用一些默认设置在 onStart
中创建预览:
focusDistance = 0;
flashSwitch = CaptureRequest.FLASH_MODE_OFF;
然后在 Flash() 和 changeFocus()
中调用 updatePreview()
而不是调用 createCameraPreview()
,您的更新预览将如下所示:
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
try{
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, flashSwitch);
captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, focusDistance);
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
我有 2 个可以通过按钮控制的 AF 焦距和一个用于闪光灯的开关。
为什么if ELSE for flashligh in updatePreview() 会影响对焦模式为auto?当我注释掉该部分时(IF ELSE for flashligh),自动对焦模式和焦距与 btnFocus 配合良好。
如何解决这个问题,同时仍然允许用户打开和关闭手电筒?
private float focusDistance = 0;
private int flashSwitch = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = (TextureView)findViewById(R.id.textureView);
//From Java 1.4 , you can use keyword 'assert' to check expression true or false
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
btnFocus = (Button)findViewById(R.id.btnFocus);
btnFlash = (Button)findViewById(R.id.btnFlash);
btnFocus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
changeFocus();
}
});
btnFlash.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Flash();
}
});
}
private void Flash() {
if(cameraDevice == null)
return;
if(flashSwitch == 0 ) {
Toast.makeText(MainActivity.this, "Flash Turn On ", Toast.LENGTH_SHORT).show();
flashSwitch = 1;
}
else{
Toast.makeText(MainActivity.this, "Flash Turn Off ", Toast.LENGTH_SHORT).show();
flashSwitch = 0;
}
createCameraPreview();
}
private void changeFocus() {
if(cameraDevice == null)
return;
if(focusDistance == 0 )
focusDistance = 10;
else
focusDistance = 0;
Toast.makeText(MainActivity.this, "Focus Change "+ focusDistance, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
private void createCameraPreview() {
try{
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(),imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
if(cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(MainActivity.this, "Changed", Toast.LENGTH_SHORT).show();
}
},null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
如果您取消注释部分,问题将在打开闪光灯和更改焦点时出现。
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
try{
// if you uncomment this part the problem will come out
// if(flashSwitch == 0){
// captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
// }
// else{
// captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
// }
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_OFF);
captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, focusDistance);
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
预期输出
可以在不影响对焦模式的情况下手动打开和关闭闪光灯。
在 updatePreview()
中,您在 captureRequestBuilder
中解决所有密钥之前向 cameraCaptureSessions
发送了多个捕获请求。尝试先设置所有键,然后发送一个重复的捕获请求。
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
try{
if(flashSwitch == 0){
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
}
else{
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
}
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_OFF);
captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, focusDistance);
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
我认为您的问题可能出在您设置请求的方式上。
您应该首先创建预览,并且只创建一次,按照您的方式,每次切换 flash and/or 焦点时都在创建预览。
我建议使用一些默认设置在 onStart
中创建预览:
focusDistance = 0;
flashSwitch = CaptureRequest.FLASH_MODE_OFF;
然后在 Flash() 和 changeFocus()
中调用 updatePreview()
而不是调用 createCameraPreview()
,您的更新预览将如下所示:
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
try{
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, flashSwitch);
captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, focusDistance);
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}