Acode icon indicating copy to clipboard operation
Acode copied to clipboard

Writable files are shown as read-only when shared by another App via FileProvider

Open zraktvor opened this issue 3 years ago • 1 comments

Issue

Files, that that were shared by other applications from their internal storage, are sometimes shown as read-only in ACode, even when they are not. This can happen, because androidx.documentfile.provider.SingleDocumentFile.canWrite, seems to be unreliable at determining writability. It is used here: https://github.com/deadlyjack/Acode/blob/0b70b3e4e3fd231064346fb55513a44d29ee8252/plugins/cordova-plugin-sdcard/src/android/SDcard.java#L279

How to reproduce

  1. Create an app-internal file (f.e. at /data/data/me.test.testapp/files/file.txt).
  2. Declare a <provider> of class androidx.core.content.FileProvider in the AndroidManifest.xml.
  3. The provider should export <files-path path="file.txt" name="file.txt" /> in the android.support.FILE_PROVIDER_PATHS meta-data.
  4. Create an Intent with action Intent.ACTION_VIEW or Intent.ACTION_EDIT, data = FileProvider.getUriForFile(this,"my.provider.authority", filepath) and flags = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION.
  5. When selecting ACode to handle the Intent, ACode will show the file as read-only, even though it could write it (I tested writability with another text-editor).

Related Issues

This issue may have the same cause as #181.

Proposed Solution

The writabiliy could be tested instead, by trying to create a writable FileDescriptor from the URI.

    public static boolean canWrite(Context context, Uri uri) {
        boolean canWrite = false;
        try {
            // if the file is not writable this throws a SecurityException
            var fd = context.getContentResolver().openFileDescriptor(uri, "w");
            if (fd != null)
                fd.close(); // we don't actually want to write anything, so we close immediately
            canWrite = true;
        } catch (SecurityException | IOException ignored) {
            // if we don't have write-permission or the file doesn't exist, canWrite can stay on false
        }
        return canWrite;
    }

I have tried this code in a minimal test application. It gives the correct result, where androidx.documentfile.provider.SingleDocumentFile.canWrite doesn't.

zraktvor avatar Jan 25 '22 16:01 zraktvor

Thank for the solution, I'll try to fix it.

deadlyjack avatar Jul 31 '22 22:07 deadlyjack

@zraktvor thanks for the suggestion, I've implemented it in v1.6.0 (204).

deadlyjack avatar Aug 18 '22 13:08 deadlyjack