Почему ContentResolver.openFileDescriptor выдает исключение IllegalArgumentException? Выход из положения?

У меня есть два вопроса, и чтобы прояснить мою проблему, вот короткий фрагмент кода:

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

В документации говорится, что последняя строка «Выдает исключение FileNotFoundException, если в URI нет файла или режим недействителен».

Но на самом деле я получаю java.lang.IllegalArgumentException.

(Вопрос 1) Это ошибка или нормально?

(Вопрос 2) openFileDescriptor(), очевидно, не является хорошим методом проверки существования документа. Каков "официальный" способ сделать это?

Изменить (добавлен журнал ошибок):

W/System.err: java.lang.IllegalArgumentException: не удалось определить, является ли 9016-4EF8:myFolder/file1.wav дочерним элементом 9016-4EF8:myFolder: java.io.FileNotFoundException: отсутствует файл для 9016-4EF8:myFolder/file1 .wav в /storage/extSdCard/myFolder/file1.wav

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

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

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

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

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

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

И:

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


person red symbol man    schedule 15.07.2016    source источник
comment
Но на самом деле я получаю java.lang.IllegalArgumentException - я рекомендую вам отредактировать свой вопрос и опубликовать всю трассировку стека Java вместе с заявлением о том, откуда вы взяли documentUri. Это баг или нормально? -- мы не можем сказать, не видя всей трассировки стека Java и не зная, откуда вы взяли documentUri. Каков «официальный» способ сделать это? -- Я бы использовал exists() на DocumentFile.   -  person CommonsWare    schedule 15.07.2016
comment
Если я смогу без проблем удалить документ, указанный documentUri, тогда характер фактического документа не должен иметь отношения к openFileDescriptor, не так ли? И по поводу DocumentFile: я успешно избежал этого и интересно, теперь я вынужден включать его только из-за exists()?   -  person red symbol man    schedule 15.07.2016


Ответы (1)


Это баг или нормально?

Я бы сказал, что это ошибка, поскольку она должна вызывать здесь FileNotFoundException.

openFileDescriptor(), очевидно, не является хорошим методом для проверки существования документа. Каков "официальный" способ сделать это?

Простое решение — использовать DocumentFile и его метод exists().

Если я могу без проблем удалить документ, идентифицированный documentUri, тогда характер фактического документа не должен иметь отношения к openFileDescriptor, не так ли?

Что ж, полезно знать, кто виноват. В данном случае проблема кроется в Google.

И что касается DocumentFile: я успешно избежал этого и задаюсь вопросом, вынужден ли я теперь включать его только из-за exists()?

Вы, конечно, можете клонировать его реализацию exists(), если хотите. Благодаря некоторой косвенности вы найдете его в 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);
    }
}
person CommonsWare    schedule 15.07.2016