Prevent crash on devices with camera killswitches.

Addresses #13450.
This commit is contained in:
Nicholas Tinsley
2024-03-27 14:42:04 -04:00
parent f126df2120
commit b0ea8d7df5
4 changed files with 19 additions and 5 deletions

View File

@@ -377,10 +377,14 @@ public class CameraXFragment extends LoggingFragment implements CameraFragment {
selfieFlash = requireView().findViewById(R.id.camera_selfie_flash); selfieFlash = requireView().findViewById(R.id.camera_selfie_flash);
captureButton.setOnClickListener(v -> { captureButton.setOnClickListener(v -> {
captureButton.setEnabled(false); if (cameraController.isInitialized()) {
flipButton.setEnabled(false); captureButton.setEnabled(false);
flashButton.setEnabled(false); flipButton.setEnabled(false);
onCaptureClicked(); flashButton.setEnabled(false);
onCaptureClicked();
} else {
Log.i(TAG, "Camera capture button clicked but the camera controller is not yet initialized.");
}
}); });
previewView.setScaleType(PREVIEW_SCALE_TYPE); previewView.setScaleType(PREVIEW_SCALE_TYPE);

View File

@@ -27,6 +27,8 @@ import java.util.concurrent.Executor
interface CameraXController { interface CameraXController {
fun isInitialized(): Boolean
fun initializeAndBind(context: Context, lifecycleOwner: LifecycleOwner) fun initializeAndBind(context: Context, lifecycleOwner: LifecycleOwner)
@RequiresPermission(Manifest.permission.CAMERA) @RequiresPermission(Manifest.permission.CAMERA)

View File

@@ -31,6 +31,10 @@ import java.util.concurrent.Executor
class PlatformCameraController(context: Context) : CameraXController { class PlatformCameraController(context: Context) : CameraXController {
val delegate = LifecycleCameraController(context) val delegate = LifecycleCameraController(context)
override fun isInitialized(): Boolean {
return delegate.initializationFuture.isDone
}
override fun initializeAndBind(context: Context, lifecycleOwner: LifecycleOwner) { override fun initializeAndBind(context: Context, lifecycleOwner: LifecycleOwner) {
delegate.bindToLifecycle(lifecycleOwner) delegate.bindToLifecycle(lifecycleOwner)
delegate.setCameraSelector(CameraXUtil.toCameraSelector(TextSecurePreferences.getDirectCaptureCameraId(context))) delegate.setCameraSelector(CameraXUtil.toCameraSelector(TextSecurePreferences.getDirectCaptureCameraId(context)))

View File

@@ -110,6 +110,10 @@ class SignalCameraController(
private lateinit var extensionsManager: ExtensionsManager private lateinit var extensionsManager: ExtensionsManager
private lateinit var cameraProperty: Camera private lateinit var cameraProperty: Camera
override fun isInitialized(): Boolean {
return this::cameraProvider.isInitialized && this::extensionsManager.isInitialized
}
override fun initializeAndBind(context: Context, lifecycleOwner: LifecycleOwner) { override fun initializeAndBind(context: Context, lifecycleOwner: LifecycleOwner) {
bindToLifecycle(lifecycleOwner) { Log.d(TAG, "Camera initialization and binding complete.") } bindToLifecycle(lifecycleOwner) { Log.d(TAG, "Camera initialization and binding complete.") }
} }
@@ -117,7 +121,7 @@ class SignalCameraController(
@RequiresPermission(Manifest.permission.CAMERA) @RequiresPermission(Manifest.permission.CAMERA)
override fun bindToLifecycle(lifecycleOwner: LifecycleOwner, onCameraBoundListener: Runnable) { override fun bindToLifecycle(lifecycleOwner: LifecycleOwner, onCameraBoundListener: Runnable) {
ThreadUtil.assertMainThread() ThreadUtil.assertMainThread()
if (this::cameraProvider.isInitialized && this::extensionsManager.isInitialized) { if (isInitialized()) {
bindToLifecycleInternal() bindToLifecycleInternal()
onCameraBoundListener.run() onCameraBoundListener.run()
} else if (!listenerAdded) { } else if (!listenerAdded) {