diff --git a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt index 06da70f391..99cd863141 100644 --- a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt +++ b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt @@ -80,11 +80,7 @@ fun openUrlInExternalBrowser(context: Context, uri: Uri?) { putExtra(Browser.EXTRA_CREATE_NEW_TAB, true) } - try { - context.startActivity(browserIntent) - } catch (activityNotFoundException: ActivityNotFoundException) { - context.toast(R.string.error_no_external_application_found) - } + context.safeStartActivity(browserIntent) } } @@ -123,22 +119,6 @@ fun openUrlInChromeCustomTab(context: Context, } } -/** - * Open sound recorder external application - */ -fun openSoundRecorder(activity: Activity, requestCode: Int) { - val recordSoundIntent = Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION) - - // Create chooser - val chooserIntent = Intent.createChooser(recordSoundIntent, activity.getString(R.string.go_on_with)) - - try { - activity.startActivityForResult(chooserIntent, requestCode) - } catch (activityNotFoundException: ActivityNotFoundException) { - activity.toast(R.string.error_no_external_application_found) - } -} - /** * Open file selection activity */ @@ -153,96 +133,14 @@ fun openFileSelection(activity: Activity, fileIntent.type = MimeTypes.Any try { - activityResultLauncher - ?.launch(fileIntent) - ?: run { - activity.startActivityForResult(fileIntent, requestCode) - } - } catch (activityNotFoundException: ActivityNotFoundException) { - activity.toast(R.string.error_no_external_application_found) - } -} - -/** - * Open external video recorder - */ -fun openVideoRecorder(activity: Activity, requestCode: Int) { - val captureIntent = Intent(MediaStore.ACTION_VIDEO_CAPTURE) - - // lowest quality - captureIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0) - - try { - activity.startActivityForResult(captureIntent, requestCode) - } catch (activityNotFoundException: ActivityNotFoundException) { - activity.toast(R.string.error_no_external_application_found) - } -} - -/** - * Open external camera - * @return the latest taken picture camera uri - */ -fun openCamera(activity: Activity, titlePrefix: String, requestCode: Int): String? { - val captureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) - - // the following is a fix for buggy 2.x devices - val date = Date() - val formatter = SimpleDateFormat("yyyyMMddHHmmss", Locale.US) - val values = ContentValues() - values.put(MediaStore.Images.Media.TITLE, titlePrefix + formatter.format(date)) - // The Galaxy S not only requires the name of the file to output the image to, but will also not - // set the mime type of the picture it just took (!!!). We assume that the Galaxy S takes image/jpegs - // so the attachment uploader doesn't freak out about there being no mimetype in the content database. - values.put(MediaStore.Images.Media.MIME_TYPE, MimeTypes.Jpeg) - var dummyUri: Uri? = null - try { - dummyUri = activity.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values) - - if (null == dummyUri) { - Timber.e("Cannot use the external storage media to save image") + if (activityResultLauncher != null) { + activityResultLauncher.launch(fileIntent) + } else { + activity.startActivityForResult(fileIntent, requestCode) } - } catch (uoe: UnsupportedOperationException) { - Timber.e(uoe, "Unable to insert camera URI into MediaStore.Images.Media.EXTERNAL_CONTENT_URI.") - Timber.e("no SD card? Attempting to insert into device storage.") - } catch (e: Exception) { - Timber.e(e, "Unable to insert camera URI into MediaStore.Images.Media.EXTERNAL_CONTENT_URI.") - } - - if (null == dummyUri) { - try { - dummyUri = activity.contentResolver.insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, values) - if (null == dummyUri) { - Timber.e("Cannot use the internal storage to save media to save image") - } - } catch (e: Exception) { - Timber.e(e, "Unable to insert camera URI into internal storage. Giving up.") - } - } - - if (dummyUri != null) { - captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, dummyUri) - Timber.v("trying to take a photo on $dummyUri") - } else { - Timber.v("trying to take a photo with no predefined uri") - } - - // Store the dummy URI which will be set to a placeholder location. When all is lost on Samsung devices, - // this will point to the data we're looking for. - // Because Activities tend to use a single MediaProvider for all their intents, this field will only be the - // *latest* TAKE_PICTURE Uri. This is deemed acceptable as the normal flow is to create the intent then immediately - // fire it, meaning onActivityResult/getUri will be the next thing called, not another createIntentFor. - val result = if (dummyUri == null) null else dummyUri.toString() - - try { - activity.startActivityForResult(captureIntent, requestCode) - - return result } catch (activityNotFoundException: ActivityNotFoundException) { activity.toast(R.string.error_no_external_application_found) } - - return null } /** @@ -254,11 +152,7 @@ fun sendMailTo(address: String, subject: String? = null, message: String? = null intent.putExtra(Intent.EXTRA_SUBJECT, subject) intent.putExtra(Intent.EXTRA_TEXT, message) - try { - activity.startActivity(intent) - } catch (activityNotFoundException: ActivityNotFoundException) { - activity.toast(R.string.error_no_external_application_found) - } + activity.safeStartActivity(intent) } /** @@ -267,11 +161,7 @@ fun sendMailTo(address: String, subject: String? = null, message: String? = null fun openUri(activity: Activity, uri: String) { val intent = Intent(Intent.ACTION_VIEW, Uri.parse(uri)) - try { - activity.startActivity(intent) - } catch (activityNotFoundException: ActivityNotFoundException) { - activity.toast(R.string.error_no_external_application_found) - } + activity.safeStartActivity(intent) } /** @@ -290,11 +180,7 @@ fun openMedia(activity: Activity, savedMediaPath: String, mimeType: String) { addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } - try { - activity.startActivity(intent) - } catch (activityNotFoundException: ActivityNotFoundException) { - activity.toast(R.string.error_no_external_application_found) - } + activity.safeStartActivity(intent) } fun shareMedia(context: Context, file: File, mediaMimeType: String?) { @@ -311,7 +197,7 @@ fun shareMedia(context: Context, file: File, mediaMimeType: String?) { .setChooserTitle(R.string.share) .createChooserIntent() - createChooser(context, chooserIntent) + context.safeStartActivity(chooserIntent) } fun shareText(context: Context, text: String) { @@ -321,14 +207,14 @@ fun shareText(context: Context, text: String) { .setChooserTitle(R.string.share) .createChooserIntent() - createChooser(context, chooserIntent) + context.safeStartActivity(chooserIntent) } -private fun createChooser(context: Context, intent: Intent) { +fun Context.safeStartActivity(intent: Intent) { try { - context.startActivity(intent) + startActivity(intent) } catch (activityNotFoundException: ActivityNotFoundException) { - context.toast(R.string.error_no_external_application_found) + toast(R.string.error_no_external_application_found) } } @@ -454,25 +340,18 @@ fun openPlayStore(activity: Activity, appId: String = BuildConfig.APPLICATION_ID try { activity.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=$appId"))) } catch (activityNotFoundException: ActivityNotFoundException) { - try { - activity.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=$appId"))) - } catch (activityNotFoundException: ActivityNotFoundException) { - activity.toast(R.string.error_no_external_application_found) - } + activity.safeStartActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=$appId"))) } } fun openAppSettingsPage(activity: Activity) { - try { - activity.startActivity( - Intent().apply { - action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - data = Uri.fromParts("package", activity.packageName, null) - }) - } catch (activityNotFoundException: ActivityNotFoundException) { - activity.toast(R.string.error_no_external_application_found) - } + activity.safeStartActivity( + Intent().apply { + action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + data = Uri.fromParts("package", activity.packageName, null) + } + ) } /** @@ -488,9 +367,8 @@ fun selectTxtFileToWrite( intent.addCategory(Intent.CATEGORY_OPENABLE) intent.type = "text/plain" intent.putExtra(Intent.EXTRA_TITLE, defaultFileName) - + val chooserIntent = Intent.createChooser(intent, chooserHint) try { - val chooserIntent = Intent.createChooser(intent, chooserHint) activityResultLauncher.launch(chooserIntent) } catch (activityNotFoundException: ActivityNotFoundException) { activity.toast(R.string.error_no_external_application_found) diff --git a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt index 966b38828e..1fa2b8151a 100644 --- a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt +++ b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt @@ -124,9 +124,9 @@ fun startNotificationChannelSettingsIntent(fragment: Fragment, channelID: String } fun startAddGoogleAccountIntent(context: Context, activityResultLauncher: ActivityResultLauncher) { + val intent = Intent(Settings.ACTION_ADD_ACCOUNT) + intent.putExtra(Settings.EXTRA_ACCOUNT_TYPES, arrayOf("com.google")) try { - val intent = Intent(Settings.ACTION_ADD_ACCOUNT) - intent.putExtra(Settings.EXTRA_ACCOUNT_TYPES, arrayOf("com.google")) activityResultLauncher.launch(intent) } catch (activityNotFoundException: ActivityNotFoundException) { context.toast(R.string.error_no_external_application_found) @@ -135,9 +135,9 @@ fun startAddGoogleAccountIntent(context: Context, activityResultLauncher: Activi @RequiresApi(Build.VERSION_CODES.O) fun startInstallFromSourceIntent(context: Context, activityResultLauncher: ActivityResultLauncher) { + val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES) + .setData(Uri.parse(String.format("package:%s", context.packageName))) try { - val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES) - .setData(Uri.parse(String.format("package:%s", context.packageName))) activityResultLauncher.launch(intent) } catch (activityNotFoundException: ActivityNotFoundException) { context.toast(R.string.error_no_external_application_found) @@ -177,9 +177,9 @@ fun startImportTextFromFileIntent(context: Context, activityResultLauncher: Acti val intent = Intent(Intent.ACTION_GET_CONTENT).apply { type = "text/plain" } - if (intent.resolveActivity(context.packageManager) != null) { + try { activityResultLauncher.launch(intent) - } else { + } catch (activityNotFoundException: ActivityNotFoundException) { context.toast(R.string.error_no_external_application_found) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index 35f33e4f75..91cae1230f 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -108,6 +108,7 @@ import im.vector.app.core.utils.onPermissionDeniedDialog import im.vector.app.core.utils.onPermissionDeniedSnackbar import im.vector.app.core.utils.openUrlInExternalBrowser import im.vector.app.core.utils.registerForPermissionsResult +import im.vector.app.core.utils.safeStartActivity import im.vector.app.core.utils.saveMedia import im.vector.app.core.utils.shareMedia import im.vector.app.core.utils.shareText @@ -782,11 +783,7 @@ class RoomDetailFragment @Inject constructor( addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - if (intent.resolveActivity(requireActivity().packageManager) != null) { - requireActivity().startActivity(intent) - } else { - requireActivity().toast(R.string.error_no_external_application_found) - } + requireActivity().safeStartActivity(intent) } private fun installApk(action: RoomDetailViewEvents.OpenFile) {