Записать на SD-карту "java.io.FileNotFoundException: в доступе отказано"
Здесь много похожих вопросов о stackru, но я до сих пор не могу найти решение моей конкретной проблемы:
У меня есть приложение с WRITE_EXTERNAL_STORAGE
разрешение и не экспортируемый провайдер файлов
<?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>
что дополнительно указано в provider_paths.xml
как
<?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>
и который я хочу использовать для передачи файлов с SD-карты в другие приложения (в этом случае мое приложение действует более или менее как файловый браузер, но не совсем...).
Поскольку я использую уровень API 23, я также динамически запрашиваю разрешения, вызывая
requestPermissions(new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_PERMISSION_REQUEST);
Откроется диалоговое окно, и после того, как я нажму "Разрешить" (и перезапущу приложение из-за ошибки, описанной в " Невозможность записи во внешнее хранилище, если приложение не будет перезапущено после предоставления разрешения), приложение правильно получает разрешения, которые я могу проверить". проверяя,
android.support.v4.content.ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
и это действительно так. Я также могу получить Uri
к File
файл с SDCard с чем-то вроде
Uri uri = android.support.v4.content.FileProvider.getUriForFile(context, "com.cgogolin.library.fileprovider", file);
Я могу прочитать из этого файла, и я могу, например, успешно начать Intent.ACTION_VIEW
открыть файл во внешнем приложении.
Но: несмотря на наличие разрешений на запись, я не могу записать в файл. Все попытки открыть OutputStream
или же ParcelFileDescriptor
в uri
с любым из следующих
context.getContentResolver().openOutputStream(uri, "wa");
context.getContentResolver().openFileDescriptor(uri, "wa");
либо прямо из моего приложения, либо из приложения, открытого через Intent
привести к
java.io.FileNotFoundException: Permission denied
Где моя ошибка? Я думал что после checkSelfPermission()
говорит мне, что у меня есть WRITE_EXTERNAL_STORAGE
Я должен быть в состоянии сделать это.
2 ответа
Ответ заключается в том, чтобы позволить пользователю давать приложениям права на запись через Intent.ACTION_OPEN_DOCUMENT_TREE
для всей SDCard (или соответствующего подкаталога), как предлагается также в этом посте Разрешение на запись на SD-карту Android с использованием SAF (Storage Access Framework).
и который я хочу использовать для обслуживания файлов с SDCard для других приложений
Во-первых, нет документированных root-path
на FileProvider
,
Во-вторых, у вас нет доступа для чтения или записи к съемному хранилищу за пределами очень определенных мест (например, 2-е и последующие значения, возвращаемые getExternalFilesDirs()
). Разрешения внешнего хранилища не имеют ничего общего со съемным хранилищем.