Доступ к AutoFocus/Flash с помощью Google Vision BarCode Reader
Я играю с оригинальным примером сканера BarCode здесь:
Они могут запускать автофокус / вспышку на заводе-изготовителе камеры следующим образом:
// Creates and starts the camera. Note that this uses a higher resolution in comparison
// to other detection examples to enable the barcode detector to detect small barcodes
// at long distances.
CameraSource.Builder builder = new CameraSource.Builder(getApplicationContext(), barcodeDetector)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedPreviewSize(1600, 1024)
.setRequestedFps(15.0f);
// make sure that auto focus is an available option
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
builder = builder.setFocusMode(
autoFocus ? Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE : null);
}
mCameraSource = builder
.setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null)
.build();
Однако этот метод в конструкторе cameraSource отсутствует в текущей версии, и поэтому этот параметр недоступен. Также мне нужно изменить FlashMode во время использования, так что это тоже не способ сделать это. Я нашел это уродливое решение для доступа к камере:
public static Camera getCamera(@NonNull CameraSource cameraSource) {
Field[] declaredFields = CameraSource.class.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getType() == Camera.class) {
field.setAccessible(true);
try {
Camera camera = (Camera) field.get(cameraSource);
if (camera != null) {
return camera;
}
return null;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
return null;
}
Хотя работает, не помогает: при звонке getParameters().setFocusMode()
Я получаю это исключение:
Attempt to invoke virtual method 'android.hardware.Camera$Parameters android.hardware.Camera.getParameters()' on a null object reference
Очевидно, что то, что я делаю, не является правильным способом сделать это, но, похоже, нет документации по этому поводу.
Спасибо за подсказки.
2 ответа
Просто оптимизируйте код следующим образом, и вы должны вызывать этот метод после создания класса Camera Source.
private Camera camera = null;
boolean flashmode=false;
private void flashOnButton() {
camera=getCamera(mCameraSource);
if (camera != null) {
try {
Camera.Parameters param = camera.getParameters();
param.setFlashMode(!flashmode?Camera.Parameters.FLASH_MODE_TORCH :Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(param);
flashmode = !flashmode;
if(flashmode){
showToast("Flash Switched ON");
}
else {
showToast("Flash Switched Off");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static Camera getCamera(@NonNull CameraSource cameraSource) {
Field[] declaredFields = CameraSource.class.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getType() == Camera.class) {
field.setAccessible(true);
try {
Camera camera = (Camera) field.get(cameraSource);
if (camera != null) {
return camera;
}
return null;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
return null;
}
Это поможет вам включить вспышку в Google Vision Api, используя объект камеры.
Вот рабочий вариант котлина:
private var flashmode: Boolean = false
private var camera: Camera? = null
private fun flashOnButton() {
camera = getCamera(cameraSource)
if (camera != null) {
try {
val param = camera!!.parameters
param.setFlashMode(if (!flashmode) Camera.Parameters.FLASH_MODE_TORCH else Camera.Parameters.FLASH_MODE_OFF)
camera?.parameters = param
flashmode = !flashmode
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
}
private fun getCamera(cameraSource: CameraSource): Camera? {
val declaredFields = CameraSource::class.java.declaredFields
for (field in declaredFields) {
if (field.type === Camera::class.java) {
field.isAccessible = true
try {
val camera = field.get(cameraSource) as Camera
return if (camera != null) {
camera
} else null
} catch (e: IllegalAccessException) {
e.printStackTrace()
}
break
}
}
return null
}
Это решение работает на данный момент. Но я не знаю, как с этим справиться, когда
android.hardware.Camera
больше не поддерживается в будущем. Может быть, есть лучшее решение без
android.hardware.Camera
?
Просто используйте CameraSource напрямую.
И у вас будет возможность использовать вспышку / фокус.
CameraSource
.setFlashMode()
.setFocusMode()