From 538024de61aacbaa6d31f39e8178f63148a15fc8 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 29 Nov 2022 11:50:54 +0300 Subject: [PATCH] android: Show user's camera when system camera is unavailable (#1458) * android: Show user's camera when system camera is unavailable * Multiple places of camera launcher Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> --- .../simplex/app/views/chat/ComposeView.kt | 4 +-- .../simplex/app/views/helpers/GetImageView.kt | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt index 2cd2e78062..c8de638bbf 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt @@ -167,7 +167,7 @@ fun ComposeView( } val cameraPermissionLauncher = rememberPermissionLauncher { isGranted: Boolean -> if (isGranted) { - cameraLauncher.launch(null) + cameraLauncher.launchWithFallback() } else { Toast.makeText(context, generalGetString(R.string.toast_permission_denied), Toast.LENGTH_SHORT).show() } @@ -239,7 +239,7 @@ fun ComposeView( AttachmentOption.TakePhoto -> { when (PackageManager.PERMISSION_GRANTED) { ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) -> { - cameraLauncher.launch(null) + cameraLauncher.launchWithFallback() } else -> { cameraPermissionLauncher.launch(Manifest.permission.CAMERA) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt index 82e7a27de8..80788473ad 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt @@ -3,6 +3,7 @@ package chat.simplex.app.views.helpers import android.Manifest import android.app.Activity import android.content.* +import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.content.pm.PackageManager import android.graphics.* import android.net.Uri @@ -32,11 +33,9 @@ import androidx.core.content.FileProvider import chat.simplex.app.* import chat.simplex.app.R import chat.simplex.app.model.json -import chat.simplex.app.views.chat.ComposeState import chat.simplex.app.views.chat.PickFromGallery import chat.simplex.app.views.newchat.ActionButton import kotlinx.serialization.builtins.* -import kotlinx.serialization.decodeFromString import java.io.ByteArrayOutputStream import java.io.File import kotlin.math.min @@ -177,6 +176,25 @@ fun rememberGetContentLauncher(cb: (Uri?) -> Unit): ManagedActivityResultLaunche fun rememberGetMultipleContentsLauncher(cb: (List) -> Unit): ManagedActivityResultLauncher> = rememberLauncherForActivityResult(contract = ActivityResultContracts.GetMultipleContents(), cb) +fun ManagedActivityResultLauncher.launchWithFallback() { + try { + launch(null) + } catch (e: ActivityNotFoundException) { + // No Activity found to handle Intent android.media.action.IMAGE_CAPTURE + // Means, no system camera app (Android 11+ requirement) + // https://developer.android.com/about/versions/11/behavior-changes-11#media-capture + Log.e(TAG, "Camera launcher: " + e.stackTraceToString()) + + try { + // Try to open any camera just to capture an image, will not be returned like with previous intent + SimplexApp.context.startActivity(Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA).also { it.addFlags(FLAG_ACTIVITY_NEW_TASK) }) + } catch (e: ActivityNotFoundException) { + // No camera apps available at all + Log.e(TAG, "Camera launcher2: " + e.stackTraceToString()) + } + } +} + @Composable fun GetImageBottomSheet( imageBitmap: MutableState, @@ -204,7 +222,7 @@ fun GetImageBottomSheet( } val permissionLauncher = rememberPermissionLauncher { isGranted: Boolean -> if (isGranted) { - cameraLauncher.launch(null) + cameraLauncher.launchWithFallback() hideBottomSheet() } else { Toast.makeText(context, generalGetString(R.string.toast_permission_denied), Toast.LENGTH_SHORT).show() @@ -228,7 +246,7 @@ fun GetImageBottomSheet( ActionButton(null, stringResource(R.string.use_camera_button), icon = Icons.Outlined.PhotoCamera) { when (PackageManager.PERMISSION_GRANTED) { ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) -> { - cameraLauncher.launch(null) + cameraLauncher.launchWithFallback() hideBottomSheet() } else -> {