Reproduce Steps
Steps to reproduce the behavior:
- Open Chrome and a Flutter app with
desktop_drop side by side on Android tablet or emulator
- Drag an image from a web page loaded in Chrome to the Flutter app
- The returned file contains
content:// url as file.path and attempt to read data from the content:// url obtained from the DropDoneDetails.files..path (e.g. using the saf_stream package) is failing with "Permission Denial" error
Expected behavior
It should be possible to read the content data
Version (please complete the following information):
- Flutter Version: 3.47
- OS: Android
- plugin: desktop_drop 0.8.4
I/flutter ( 7970): Failed to copy content URI content://com.android.chrome.DropDataProvider/1789068043787: PlatformException(PluginError, Permission Denial: opening provider org.chromium.ui.dragdrop.DropDataContentProvider from ProcessRecord{ca7db50 7970:***/u0a212} (pid=7970, uid=10212) that is not exported from UID 10145, null, null)
I/flutter ( 7970): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:653:7)
I/flutter ( 7970): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:366:18)
I/flutter ( 7970): <asynchronous suspension>
I/flutter ( 7970): #2 MethodChannelSafStream.copyToLocalFile (package:saf_stream/saf_stream_method_channel.dart:58:5)
I/flutter ( 7970): <asynchronous suspension>
...
Why it fails:
- activity.requestDragAndDropPermissions(event) successfully obtains temporary read permissions for the content:// URI during the drop event.
- The plugin collects the URI strings (content://org.chromium.ui.dragdrop.DropDataContentProvider/...).
- Crucial Flaw: The plugin immediately calls permission.release() before sending the URIs over the MethodChannel to Flutter.
- By the time the Flutter Dart code receives the URI string via performOperation and attempts to read it (via SAF, ContentResolver, or SafStream), the drag-and-drop permission has already been revoked.
- Consequently, Android throws java.lang.SecurityException: Permission Denial when the app tries to open the input stream.
Required Changes in DesktopDropPlugin.kt
To allow reading from non-exported content:// providers across process boundaries:
- Copy content:// URIs to a local cache file while the permission is held: Before calling permission.release(), use contentResolver.openInputStream(uri) on the Android side to write the stream data into a temporary file in activity.cacheDir.
- Return the local file path to Flutter: Send the cached file path to Flutter instead of the raw content:// URI string.
- Release permission after copying: Call permission.release() inside a finally block once the file copy is complete.
Reproduce Steps
Steps to reproduce the behavior:
desktop_dropside by side on Android tablet or emulatorcontent://url as file.path and attempt to read data from thecontent://url obtained from theDropDoneDetails.files..path(e.g. using the saf_stream package) is failing with "Permission Denial" errorExpected behavior
It should be possible to read the content data
Version (please complete the following information):
Why it fails:
Required Changes in DesktopDropPlugin.kt
To allow reading from non-exported content:// providers across process boundaries: