在stackoverflow上有很多类似的问题,但我仍然找不到解决我的特定问题的方法:
我有一个带有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
确实如此。我也可以通过类似以下方式从SD卡获取File
文件的Uri
Uri uri = android.support.v4.content.FileProvider.getUriForFile(context, "com.cgogolin.library.fileprovider", file);
我可以从那个文件中读取内容,例如成功地启动一个 Intent.ACTION_VIEW
来在外部应用程序中打开该文件。
但是:尽管拥有写入权限,我无法向该文件写入内容。所有尝试使用以下任一方式打开 uri
的 OutputStream
或 ParcelFileDescriptor
均失败:
context.getContentResolver().openOutputStream(uri, "wa");
context.getContentResolver().openFileDescriptor(uri, "wa");
无论是直接从我的应用程序还是通过Intent
打开的应用程序,都会导致一个
java.io.FileNotFoundException: Permission denied
我的错误在哪里?我认为在checkSelfPermission()
告诉我我拥有WRITE_EXTERNAL_STORAGE
权限后,我应该能够实际执行操作。
Intent.ACTION_VIEW
的完全相同的应用程序打开它,则我可以覆盖该文件或将其保存到同一目录中的新文件中。如果我使用Intent.ACTION_OPEN_DOCUMENT
从后者应用程序打开sdcard上的文件,也是同样的情况。 - cgogolinFile file
的样本路径为/storage/0000-0000/dir/file1.pdf
。 - cgogolin