From 455d329fff7a04ee5b13d8190543e209c5f490ce Mon Sep 17 00:00:00 2001 From: Markus Fisch Date: Fri, 7 May 2021 22:15:38 +0200 Subject: [PATCH] Remove resolveActivity() for opening content Because on Android 11+ resolveActivity() can no longer be used to query if there's an app that can handle the intent for privacy reasons. --- .../actions/search/OpenOrSearchAction.kt | 34 ++++++------------- .../android/binaryeye/content/Share.kt | 15 +++++--- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/app/src/main/kotlin/de/markusfisch/android/binaryeye/actions/search/OpenOrSearchAction.kt b/app/src/main/kotlin/de/markusfisch/android/binaryeye/actions/search/OpenOrSearchAction.kt index bb3b170e..441331e8 100644 --- a/app/src/main/kotlin/de/markusfisch/android/binaryeye/actions/search/OpenOrSearchAction.kt +++ b/app/src/main/kotlin/de/markusfisch/android/binaryeye/actions/search/OpenOrSearchAction.kt @@ -8,6 +8,7 @@ import de.markusfisch.android.binaryeye.app.alertDialog import de.markusfisch.android.binaryeye.app.parseAndNormalizeUri import de.markusfisch.android.binaryeye.app.prefs import de.markusfisch.android.binaryeye.content.execShareIntent +import de.markusfisch.android.binaryeye.content.startIntent import de.markusfisch.android.binaryeye.widget.toast import java.net.URLEncoder @@ -15,33 +16,20 @@ object OpenOrSearchAction : IAction { override val iconResId: Int = R.drawable.ic_action_search override val titleResId: Int = R.string.search_web - override fun canExecuteOn(data: ByteArray): Boolean = false + override fun canExecuteOn(bytes: ByteArray): Boolean = false - override suspend fun execute(context: Context, data: ByteArray) { - val intent = openUri(context, String(data)) ?: return - context.execShareIntent(intent) + override suspend fun execute(context: Context, bytes: ByteArray) { + view(context, String(bytes), true) } - private suspend fun openUri( - context: Context, - data: String, - search: Boolean = true - ): Intent? { - val uri = parseAndNormalizeUri(data) - val intent = Intent(Intent.ACTION_VIEW, uri) - return when { - // It's okay to use `resolveActivity()` at API level 30+ here - // because ACTION_VIEW is defined in `` in the Manifest. - intent.resolveActivity(context.packageManager) != null -> intent - search -> getSearchIntent(context, data) - else -> { - context.toast(R.string.cannot_resolve_action) - null - } + private suspend fun view(context: Context, s: String, search: Boolean) { + val intent = Intent(Intent.ACTION_VIEW, parseAndNormalizeUri(s)) + if (!context.startIntent(intent) && search) { + openSearch(context, s) } } - private suspend fun getSearchIntent(context: Context, query: String): Intent? { + private suspend fun openSearch(context: Context, query: String) { val names = context.resources.getStringArray( R.array.search_engines_names ).toMutableList() @@ -57,7 +45,7 @@ object OpenOrSearchAction : IAction { setItems(names.toTypedArray()) { _, which -> resume(urls[which] + URLEncoder.encode(query, "utf-8")) } - } ?: return null - return openUri(context, queryUri, false) + } ?: return + view(context, queryUri, false) } } diff --git a/app/src/main/kotlin/de/markusfisch/android/binaryeye/content/Share.kt b/app/src/main/kotlin/de/markusfisch/android/binaryeye/content/Share.kt index 03cd5c5b..af252633 100644 --- a/app/src/main/kotlin/de/markusfisch/android/binaryeye/content/Share.kt +++ b/app/src/main/kotlin/de/markusfisch/android/binaryeye/content/Share.kt @@ -12,6 +12,12 @@ import de.markusfisch.android.binaryeye.widget.toast import java.io.File fun Context.execShareIntent(intent: Intent) { + if (!startIntent(intent)) { + toast(R.string.cannot_resolve_action) + } +} + +fun Context.startIntent(intent: Intent) = try { // Avoid using `intent.resolveActivity()` at API level 30+ due // to the new package visibility restrictions. In order for // `resolveActivity()` to "see" another package, we would need @@ -20,11 +26,10 @@ fun Context.execShareIntent(intent: Intent) { // an exception if the Intent cannot be resolved, it's much easier // and more robust to just try and catch that exception if // necessary. - try { - startActivity(intent) - } catch (e: ActivityNotFoundException) { - toast(R.string.cannot_resolve_action) - } + startActivity(intent) + true +} catch (e: ActivityNotFoundException) { + false } fun shareText(context: Context, text: String, type: String = "text/plain") {