3

There are many similar questions here on stackoverflow, but I still couldn't find a solution to my particular problem:

I have an app with the WRITE_EXTERNAL_STORAGE permission and a non-exported file provider

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.cgogolin.library"
      ...
      <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23" />
      ...
      <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.cgogolin.library.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
      </provider>
</application>

which is further specified in provider_paths.xml as

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
  <external-path name="external_files" path="."/>
  <root-path name="external_files2" path="/storage/"/>
</paths>

and which I want to use to serve files from the sdcard to other apps (My app acts more or less as a file browser in this case, but not quite...).

As I am using API level 23 I also dynamically request the permissions by calling

requestPermissions(new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_PERMISSION_REQUEST);

The dialog window is shown, and after I click "Allow" (and restart the app due to the bug described in Can't write to external storage unless app is restarted after granting permission) the App correctly obtains the permissions, which I can verified by testing whether

android.support.v4.content.ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED

and it is indeed true. I can also obtain a Uri to a File file from the sdcard with something like

Uri uri = android.support.v4.content.FileProvider.getUriForFile(context, "com.cgogolin.library.fileprovider", file);

I can read from that file and I can for example successfully start an Intent.ACTION_VIEW to open the file in an external App.

But: Despite having write permissions, I can not write to the file. All attempts to open an OutputStream or ParcelFileDescriptor to uri with either of the following

context.getContentResolver().openOutputStream(uri, "wa");
context.getContentResolver().openFileDescriptor(uri, "wa");

either directly from my App or from an App opened via Intent result in a

java.io.FileNotFoundException: Permission denied

Where is my mistake? I thought that after checkSelfPermission() tells me I have WRITE_EXTERNAL_STORAGE I should actually be able to do so.

Community
  • 1
  • 1
cgogolin
  • 960
  • 1
  • 10
  • 22
  • Everything seems correct. Please can you connect phone to computer and try to create a file to the folder you work. Write result here. – kodmanyagha Apr 11 '17 at 15:50
  • How exactly do you want me to create a file? From within my App? Via adb? – cgogolin Apr 11 '17 at 15:54
  • Not with adb. With file manager. – kodmanyagha Apr 11 '17 at 15:55
  • I can do that without problems. For example, if I chose a file on the sdcard with the default `Files` App and open it with the exact same app to which I send the `Intent.ACTION_VIEW` in the above example, I can overwrite the file or save to a new file in the same directory. The same is possible if I open a file on the sdcard from that latter App with a `Intent.ACTION_OPEN_DOCUMENT`. – cgogolin Apr 11 '17 at 16:01
  • As per your question, I want to use to serve files from the sdcard to other apps (My app acts more or less as a file browser in this case, but not quite...). if you are accessing other apps private directories than its not permuted by Android OS, because its follows Linux file system. – Lovekush Vishwakarma Apr 11 '17 at 16:02
  • The problem occurs for files in a generic directory called `dir` in the root of the scdard. – cgogolin Apr 11 '17 at 16:04
  • You cannot serve files from SD card using a FileProvider. But it is unclear to me if you really use files from SD card. Please tell full paths so we can check. – greenapps Apr 11 '17 at 16:10
  • A sample path of the `File file` in the above example would be `/storage/0000-0000/dir/file1.pdf`. – cgogolin Apr 11 '17 at 16:12
  • That looks like SD card. But 0000-0000? Strange. But anyhow FileProvider is useless. – greenapps Apr 11 '17 at 16:15

2 Answers2

0

and which I want to use to serve files from the sdcard to other apps

First, there is no documented root-path on FileProvider.

Second, you have no read or write access to removable storage, outside of very specific locations (e.g., 2nd and subsequent values returned by getExternalFilesDirs()). The external storage permissions have nothing to do with removable storage.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Well, I definitely have read access. I thought writing was solved with the new `WRITE_EXTERNAL_STORAGE` permission that has to be dynamically requested? There surely is a way to achieve this. With SolidExplorer I can, for example write to all directories on my sdcard. – cgogolin Apr 11 '17 at 16:10
  • Yes you will allways have read access. But the card is readonly nowadays. And you can write to all directories too if you use Storage Access Framework instead of File and FileOutputStream classes. – greenapps Apr 11 '17 at 16:11
  • Not to Apps like SolidExplorer, they can write even without root. So if not with the method above, how do such Apps achieve it? – cgogolin Apr 11 '17 at 16:13
0

The answer is to let the user give the App write permissions via a Intent.ACTION_OPEN_DOCUMENT_TREE for the whole sdcard (or the relevant subdirectory) as suggested also in this post Android SD Card Write Permission using SAF (Storage Access Framework).

Community
  • 1
  • 1
cgogolin
  • 960
  • 1
  • 10
  • 22