0

Imagine I'm openeing a file using the standard Intent.ACTION_OPEN_DOCUMENT like this

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("text/plain");
...
startActivityForResult(intent, READ_REQUEST_CODE);

which performs as expected.

In that files content, a file name is mentioned which I like to open without any user interaction (just exchange the file name of the intend result with the one read from the file). By doing this, I'll get an java.lang.SecurityException: Permission Denial: reading com.android.externalstorage.ExternalStorageProvider uri content://com.android.externalstorage.documents/document/primary%3ADownload%2Finc.txt from pid=..., uid=... requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission() by calling getContentResolver().openInputStream(manipulatedUri) which is weird as in the AndroidManifest.xml it is written as follows:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />

What it makes even more weird to me is the following: File A includes file name B. If I open it that way, it does not work. But, openening file B first (making it known to the systems ContentResolver instance?) and afterwards openening file A, the programatic load of file B works as expected even after app restart.

Does anybody knows the reason for such a behavior?


API Level 19 is used

micfra
  • 2,780
  • 1
  • 23
  • 34
  • At the end, I'm falling back to this solution http://stackoverflow.com/a/36714242/799562. After having the files real path, I'm just replacing the file name with the one found in the loaded file and open it via ordinary `FileInputStream`. – micfra Aug 09 '16 at 19:07

1 Answers1

0

In that file, a file name is mentioned

I am going to assume that you mean "a String representation of a Uri". A Uri is not a file.

which is weird as in the AndroidManifest.xml it is written as follows:

MANAGE_DOCUMENTS is a signature permission, meaning your app has to be signed by the same signing key as signed the firmware, in order to hold that permission. Most likely, this is not the case for your app.

What it makes even more weird is, that if I open the file to be loaded programatically as is first and afterwards loading it via inclusion, it works.

It is unclear what you mean by this.

A Uri is not a file. A Uri from a ContentProvider more closely resembles a URL to a Web site, where that URL requires authentication. Persisting that URL will not be useful, as while you might be able to access the content identified by that URL now (given that your user has done some authentication with the site), you might not be able to access the content identified by that URL tomorrow.

In the case of ACTION_OPEN_DOCUMENT, you only have access to the content identified by the Uri until your process terminates. The exception is if the storage provider offers persistable Uri permissions and you call takePersistableUriPermission() on ContentResolver once you first get the Uri via ACTION_OPEN_DOCUMENT. Even then, you might not have indefinite access (e.g., user deletes that file).

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Sorry for not being precise enough, but you are correct. In the file opened, a file name is stored. I do convert the Uri from the Intents result to a string, change the file name and convert it back to an Uri using `Uri.parse(changedPath)`. – micfra Aug 08 '16 at 19:30
  • @micfra: You will have to try `takePersistableUriPermission()`, then deal with the cases where the referenced content is no longer accessible, for whatever reason. – CommonsWare Aug 08 '16 at 19:32
  • Thanks for the hint. I'll try `final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION);` which changed nothing and using `final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);` leads to another exception `java.lang.IllegalArgumentException: Requested flags 0x41, but only 0x3 are allowed`. – micfra Aug 08 '16 at 19:52
  • @micra: I do not know what you are doing there. `int perms=Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; getContentResolver().takePersistableUriPermission(document, perms);`, where `document` is your `Uri`. – CommonsWare Aug 08 '16 at 20:02