Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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
*/
Expand All @@ -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")
}
} 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 (activityResultLauncher != null) {
activityResultLauncher.launch(fileIntent)
} else {
activity.startActivityForResult(fileIntent, requestCode)
}
}

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
}

/**
Expand All @@ -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)
}

/**
Expand All @@ -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)
}

/**
Expand All @@ -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?) {
Expand All @@ -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) {
Expand All @@ -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)
}
}

Expand Down Expand Up @@ -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)
}
)
}

/**
Expand All @@ -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)
Expand Down
12 changes: 6 additions & 6 deletions vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ fun startNotificationChannelSettingsIntent(fragment: Fragment, channelID: String
}

fun startAddGoogleAccountIntent(context: Context, activityResultLauncher: ActivityResultLauncher<Intent>) {
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)
Expand All @@ -135,9 +135,9 @@ fun startAddGoogleAccountIntent(context: Context, activityResultLauncher: Activi

@RequiresApi(Build.VERSION_CODES.O)
fun startInstallFromSourceIntent(context: Context, activityResultLauncher: ActivityResultLauncher<Intent>) {
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
.setData(Uri.parse(String.format("package:%s", context.packageName)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: this was already here but it could be nice to avoid String.format in favour of a more kotlin idiomatic "package:${context.packageName}"

For this usecase it's not very relevant butString.format is also quite heavy relative to a StringBuilder https://cowtowncoder.medium.com/measuring-performance-of-java-string-format-or-lack-thereof-2e1c6a13362c

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Expand Down Expand Up @@ -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)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down