fix(settings): resolve transient URI permission revocation and file picker crash on custom ROMs#42
Merged
Merged
Conversation
…ostics UX - Fix transient URI permission revocation when launching background import coroutines by opening input streams synchronously on the main thread during the activity callback. - Implement `openStreamWithFallback` and `getPathFromUri` to resolve local documents and media provider URIs directly to file system paths, allowing direct file reading via `FileInputStream` under the `MANAGE_EXTERNAL_STORAGE` permission (bypasses buggy system-level `ExternalStorageProvider` SecurityExceptions on custom Android ROMs). - Upgrade import UI to collect success/failure status by file name and display an aggregated `AlertDialog` report containing formatted checkmark/cross lists. - Update JNI bridge (`hoshidicts_jni.cpp`) to pass the raw C++ error message in the `title` field on JNI import failure so Kotlin can display detailed native errors.
Owner
|
lgtm |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
This PR fixes a bug where users could not import Yomichan/Yomitan dictionaries on certain devices (specifically custom Android ROMs like Xiaomi HyperOS/MIUI devices) due to transient URI permission revocations and system-level
SecurityExceptioncrashes.Problem Description
rememberLauncherForActivityResultwithOpenMultipleDocuments, the returned URIs are granted transient read permissions. Deferring the stream opening (openInputStream) entirely inside a background thread coroutine (scope.launch) causes the callback thread to exit immediately, prompting Android to revoke the read permission before the background thread can open the file.SecurityException: Permission Denial: com.android.externalstorage has no access to content://media/because of system-level provider bugs, rendering standardContentResolver.openInputStreamunusable.Solution Implemented
importLauncher, we now synchronously callopenStreamWithFallbackon the main thread during the activity result callback to grab and secure the file descriptor immediately before Android can revoke the transient permissions.getPathFromUri) that parsescom.android.externalstorage.documentsandcom.android.providers.downloads.documentsURIs to their absolute storage paths (e.g.,/storage/emulated/0/...). When the systemopenInputStreamfails, it falls back to direct file reading usingFileInputStreamunder the existingMANAGE_EXTERNAL_STORAGEpermission.AlertDialog. The new dialog compiles a clean, user-friendly import report for single/multiple file selections, mapping success states with checkmarks (✓) and failure states with cross marks (✗). It filters out raw developer diagnostics (such as long URIs, absolute file paths, and internal variables) to prevent UI clutter. Furthermore, it dynamically displays a "Grant Permission" button if a storage permission failure is detected, allowing users to navigate directly to settings to grant the required access.hoshidicts_jni.cpp) to pass raw C++ exception messages (such asempty dictionaryor JSON parsing failures) in thetitlefield of theImportResulton failure, allowing the UI to display the exact root cause.Screenshots