Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why ContentResolver.openFileDescriptor throws IllegalArgumentException? Way out?

I have two questions, and to make my issue clear here a short code snippet:

ContentResolver resolver = context.getContentResolver();
DocumentsContract.deleteDocument(resolver, documentUri);
resolver.openFileDescriptor(documentUri, "rw");

The documentation sais that the last line "Throws FileNotFoundException if no file exists under the URI or the mode is invalid."

But actually I get java.lang.IllegalArgumentException.

(Question 1) Is this a bug or OK?

(Question 2) openFileDescriptor() is obviously not a good method to test if the document exists. What is the "official" method to do that?

Edit (added error log):

W/System.err: java.lang.IllegalArgumentException: Failed to determine if 9016-4EF8:myFolder/file1.wav is child of 9016-4EF8:myFolder: java.io.FileNotFoundException: Missing file for 9016-4EF8:myFolder/file1.wav at /storage/extSdCard/myFolder/file1.wav

W/System.err: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:167)

W/System.err: at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:148)

W/System.err: at android.content.ContentProviderProxy.openAssetFile(ContentProviderNative.java:618)

W/System.err: at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:945)

W/System.err: at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:784)

W/System.err: at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:739)

And:

documentUri="content://com.android.externalstorage.documents/tree/9016-4EF8%3AmyFolder/document/9016-4EF8%3AmyFolder%2Ffile1.wav"

like image 497
red symbol man Avatar asked Oct 31 '22 00:10

red symbol man


1 Answers

Is this a bug or OK?

I would argue that it's a bug, insofar as it should throw a FileNotFoundException here.

openFileDescriptor() is obviously not a good method to test if the document exists. What is the "official" method to do that?

The simple solution is to use DocumentFile and its exists() method.

If I'm able to remove the document identified by documentUri without any problem then the nature of the actual document shouldn't be relevant for openFileDescriptor, should it?

Well, it helps to know who to blame. In this case, the problem lies with Google.

And concerning DocumentFile: I successfully avoided it and wonder if I'm now forced to include it only because of exists()?

You are certainly welcome to clone its implementation of exists(), if you like. Courtesy of some indirection, you'll find it in DocumentsContractApi19:

public static boolean exists(Context context, Uri self) {
    final ContentResolver resolver = context.getContentResolver();

    Cursor c = null;
    try {
        c = resolver.query(self, new String[] {
                DocumentsContract.Document.COLUMN_DOCUMENT_ID }, null, null, null);
        return c.getCount() > 0;
    } catch (Exception e) {
        Log.w(TAG, "Failed query: " + e);
        return false;
    } finally {
        closeQuietly(c);
    }
}
like image 190
CommonsWare Avatar answered Nov 08 '22 12:11

CommonsWare