Skip to content

[android] error reading image data dragged from Chrome browser #502

Description

@ekuleshov

Reproduce Steps

Steps to reproduce the behavior:

  1. Open Chrome and a Flutter app with desktop_drop side by side on Android tablet or emulator
  2. Drag an image from a web page loaded in Chrome to the Flutter app
  3. 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:

  1. activity.requestDragAndDropPermissions(event) successfully obtains temporary read permissions for the content:// URI during the drop event.
  2. The plugin collects the URI strings (content://org.chromium.ui.dragdrop.DropDataContentProvider/...).
  3. Crucial Flaw: The plugin immediately calls permission.release() before sending the URIs over the MethodChannel to Flutter.
  4. 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.
  5. 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:

  1. 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.
  2. Return the local file path to Flutter: Send the cached file path to Flutter instead of the raw content:// URI string.
  3. Release permission after copying: Call permission.release() inside a finally block once the file copy is complete.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions