From 57a3385a7cd3bf8ca9c497acecfa2adb8aed0b4c Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sat, 1 Apr 2023 20:03:30 +0200 Subject: [PATCH] fixed crash when trying to create file while system file picker is missing --- .../streams/ActivityResultStreamHandler.kt | 42 +++++++++++-------- .../action_mixins/permission_aware.dart | 26 +++++++----- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt index c2e9d364d..c5f319dd2 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt @@ -101,7 +101,17 @@ class ActivityResultStreamHandler(private val activity: Activity, arguments: Any endOfStream() } - private fun createFile() { + private suspend fun safeStartActivityForResult(intent: Intent, requestCode: Int, onGranted: (uri: Uri) -> Unit, onDenied: () -> Unit) { + if (intent.resolveActivity(activity.packageManager) != null) { + MainActivity.pendingStorageAccessResultHandlers[requestCode] = PendingStorageAccessResultHandler(null, onGranted, onDenied) + activity.startActivityForResult(intent, requestCode) + } else { + MainActivity.notifyError("failed to resolve activity for intent=$intent extras=${intent.extras}") + onDenied() + } + } + + private suspend fun createFile() { @SuppressLint("ObsoleteSdkInt") if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { error("createFile-sdk", "unsupported SDK version=${Build.VERSION.SDK_INT}", null) @@ -116,12 +126,7 @@ class ActivityResultStreamHandler(private val activity: Activity, arguments: Any return } - val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - type = mimeType - putExtra(Intent.EXTRA_TITLE, name) - } - MainActivity.pendingStorageAccessResultHandlers[MainActivity.CREATE_FILE_REQUEST] = PendingStorageAccessResultHandler(null, { uri -> + fun onGranted(uri: Uri) { ioScope.launch { try { // truncate is necessary when overwriting a longer file @@ -134,13 +139,20 @@ class ActivityResultStreamHandler(private val activity: Activity, arguments: Any } endOfStream() } - }, { + } + + fun onDenied() { success(null) endOfStream() - }) - activity.startActivityForResult(intent, MainActivity.CREATE_FILE_REQUEST) - } + } + val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { + addCategory(Intent.CATEGORY_OPENABLE) + type = mimeType + putExtra(Intent.EXTRA_TITLE, name) + } + safeStartActivityForResult(intent, MainActivity.CREATE_FILE_REQUEST, ::onGranted, ::onDenied) + } private suspend fun openFile() { @SuppressLint("ObsoleteSdkInt") @@ -178,13 +190,7 @@ class ActivityResultStreamHandler(private val activity: Activity, arguments: Any addCategory(Intent.CATEGORY_OPENABLE) setTypeAndNormalize(mimeType ?: MimeTypes.ANY) } - if (intent.resolveActivity(activity.packageManager) != null) { - MainActivity.pendingStorageAccessResultHandlers[MainActivity.OPEN_FILE_REQUEST] = PendingStorageAccessResultHandler(null, ::onGranted, ::onDenied) - activity.startActivityForResult(intent, MainActivity.OPEN_FILE_REQUEST) - } else { - MainActivity.notifyError("failed to resolve activity for intent=$intent extras=${intent.extras}") - onDenied() - } + safeStartActivityForResult(intent, MainActivity.OPEN_FILE_REQUEST, ::onGranted, ::onDenied) } private fun pickCollectionFilters() { diff --git a/lib/widgets/common/action_mixins/permission_aware.dart b/lib/widgets/common/action_mixins/permission_aware.dart index 4709909de..680bf013f 100644 --- a/lib/widgets/common/action_mixins/permission_aware.dart +++ b/lib/widgets/common/action_mixins/permission_aware.dart @@ -71,17 +71,7 @@ mixin PermissionAwareMixin { // abort if the user cancels in Flutter if (confirmed == null || !confirmed) return false; - if (!await deviceService.isSystemFilePickerEnabled()) { - await showDialog( - context: context, - builder: (context) => AvesDialog( - content: Text(context.l10n.missingSystemFilePickerDialogMessage), - actions: const [OkButton()], - ), - routeSettings: const RouteSettings(name: AvesDialog.warningRouteName), - ); - return false; - } + if (!await _checkSystemFilePickerEnabled(context)) return false; final granted = await storageService.requestDirectoryAccess(dir.dirPath); if (!granted) { @@ -105,4 +95,18 @@ mixin PermissionAwareMixin { routeSettings: const RouteSettings(name: AvesDialog.warningRouteName), ); } + + Future _checkSystemFilePickerEnabled(BuildContext context) async { + if (await deviceService.isSystemFilePickerEnabled()) return true; + + await showDialog( + context: context, + builder: (context) => AvesDialog( + content: Text(context.l10n.missingSystemFilePickerDialogMessage), + actions: const [OkButton()], + ), + routeSettings: const RouteSettings(name: AvesDialog.warningRouteName), + ); + return false; + } }