From edb8447d2d59a303b85260cf1198b0dd13fe9b1e Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sat, 4 Nov 2023 16:06:02 -0400 Subject: [PATCH 1/4] FileShuttle: use try-with-resource for FileOutputStream --- .../net/typeblog/shelter/services/FileShuttleService.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/typeblog/shelter/services/FileShuttleService.java b/app/src/main/java/net/typeblog/shelter/services/FileShuttleService.java index 6eb419b..6120328 100644 --- a/app/src/main/java/net/typeblog/shelter/services/FileShuttleService.java +++ b/app/src/main/java/net/typeblog/shelter/services/FileShuttleService.java @@ -284,14 +284,13 @@ public class FileShuttleService extends Service { return null; } - FileOutputStream os = new FileOutputStream(pair[1].getFileDescriptor()); + // Send the bitmap into the pipe in another thread, so that we can return the // reading fd to the Documents UI before we finish sending the Bitmap. new Thread(() -> { - bmp.compress(Bitmap.CompressFormat.PNG, 100, os); - try { + try (FileOutputStream os = new FileOutputStream(pair[1].getFileDescriptor())) { + bmp.compress(Bitmap.CompressFormat.PNG, 100, os); os.flush(); - os.close(); } catch (IOException e) { // ... } From 20369aafd25f2daefa9c4d9efcd6802c23993dcd Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sat, 4 Nov 2023 18:14:12 -0400 Subject: [PATCH 2/4] gradle: Set versionCode of debug builds to current timestamp --- app/build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 35ce379..0f9c5d7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,6 +55,11 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + applicationVariants.all { variant -> + if (variant.name == "debug") { + variant.outputs.each { o -> o.versionCodeOverride = System.currentTimeSeconds() } + } + } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 From 584bd25aeb3bea74081d73f506dc80063c5b680e Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sat, 4 Nov 2023 18:24:10 -0400 Subject: [PATCH 3/4] FileShuttleService: trigger media scanner after writes as well Previously, we have been triggering the media scanner after calls to `createFile()`. This is not robust, though, as in many cases the writer is not able to finish writing (i.e. *actually* creating the file) before the scanner is scheduled, resulting in media copied into the work profile not showing up in galleries etc. Turns out, ParcelFileDescriptor supports a `listener` argument in its `open()` calls. This listener is triggered when the fd is actually closed by the (potentially remote) writer. To have robust media scanning, we simply re-trigger the scanner every time a writable ParcelFileDescriptor is closed. --- .../shelter/services/FileShuttleService.java | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/net/typeblog/shelter/services/FileShuttleService.java b/app/src/main/java/net/typeblog/shelter/services/FileShuttleService.java index 6120328..ff6355c 100644 --- a/app/src/main/java/net/typeblog/shelter/services/FileShuttleService.java +++ b/app/src/main/java/net/typeblog/shelter/services/FileShuttleService.java @@ -101,10 +101,24 @@ public class FileShuttleService extends Service { public ParcelFileDescriptor openFile(String path, String mode) { resetSuicideTask(); File f = new File(resolvePath(path)); + int numericMode = ParcelFileDescriptor.parseMode(mode); try { - return ParcelFileDescriptor.open(f, ParcelFileDescriptor.parseMode(mode)); - } catch (FileNotFoundException e) { + if ((numericMode & ParcelFileDescriptor.MODE_WRITE_ONLY) != 0) { + // When the file is opened in writable mode, and the file is of a media + // type, we need to notify the media scanner of the update. + // Even though this is done as part of file creation as well, that scan + // might have failed because it happened before the writer was able to + // finish writing. + return ParcelFileDescriptor.open(f, numericMode, mHandler, (e) -> { + String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension( + Utility.getFileExtension(f.getAbsolutePath())); + notifyMediaScannerIfNecessary(f, mime); + }); + } else { + return ParcelFileDescriptor.open(f, numericMode); + } + } catch (IOException e) { return null; } } @@ -138,8 +152,6 @@ public class FileShuttleService extends Service { DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType); boolean shouldAppendExtension = mimeType != null && !isDirectory && !mimeType.equals("application/octet-stream"); - boolean isMedia = - mimeType != null && (mimeType.startsWith("image/") || mimeType.startsWith("video/")); // Append extension for files if a MIME type is specified if (shouldAppendExtension) { @@ -159,13 +171,7 @@ public class FileShuttleService extends Service { return null; } - // Notify the media scanner to scan the file as needed - // This has to be done AFTER file creation - if (isMedia) { - Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - intent.setData(Uri.fromFile(f)); - sendBroadcast(intent); - } + notifyMediaScannerIfNecessary(f, mimeType); return f.getAbsolutePath(); } @@ -299,4 +305,14 @@ public class FileShuttleService extends Service { return pair[0]; } + + private void notifyMediaScannerIfNecessary(File f, String mimeType) { + // Notify the media scanner to scan the file as needed + // This has to be done AFTER file creation + if (mimeType != null && (mimeType.startsWith("image/") || mimeType.startsWith("video/"))) { + Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + intent.setData(Uri.fromFile(f)); + sendBroadcast(intent); + } + } } From 3593861e3950119ccee156e831d6091757fbdc8b Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sat, 4 Nov 2023 18:27:58 -0400 Subject: [PATCH 4/4] CHANGELOG: describe media scanning changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb91280..8284866 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Removed "Fake Camera" feature as it has not been supported since R. - Version displayed within the app has now been changed to also reflect the exact Git commit when the app is built. - File Shuttle no longer appends ".null" or ".bin" suffixes unnecessarily. This should make it work much better with file managers such as Material Files. +- File Shuttle now triggers media scanning much more robustly. Media files (pictures, videos, etc.) copied into the work profile should now show up much quicker in gallery apps. 1.8 ===