Android ext sdcard 的 FileProvider
Android FileProvider for ext sdcard
例如,我正在使用 FileProvider 将我的内部文件公开给图库。为了使其更加统一,我还将我的外部文件放入提供程序(通过外部路径),但对于可移动 SD 卡中的文件,它不起作用。说那个文件夹没有授权。
任何帮助将不胜感激。
感谢
从 android 4.4 开始,普通应用程序不允许访问辅助外部存储设备,即 sd 卡,除了它们的包特定目录,即使您已请求 WRITE_EXTERNAL_STORAGE 权限。
The WRITE_EXTERNAL_STORAGE permission must only grant write access to
the primary external storage on a device. Apps must not be allowed to
write to secondary external storage devices, except in their
package-specific directories as allowed by synthesized permissions.
Restricting writes in this way ensures the system can clean up files
when applications are uninstalled.
我们来看看FileProvider
代码:
private static PathStrategy parsePathStrategy(Context context, String authority)
...
int type;
while ((type = in.next()) != END_DOCUMENT) {
if (type == START_TAG) {
final String tag = in.getName();
final String name = in.getAttributeValue(null, ATTR_NAME);
String path = in.getAttributeValue(null, ATTR_PATH);
File target = null;
if (TAG_ROOT_PATH.equals(tag)) {
target = buildPath(DEVICE_ROOT, path);
} else if (TAG_FILES_PATH.equals(tag)) {
target = buildPath(context.getFilesDir(), path);
} else if (TAG_CACHE_PATH.equals(tag)) {
target = buildPath(context.getCacheDir(), path);
} else if (TAG_EXTERNAL.equals(tag)) {
target = buildPath(Environment.getExternalStorageDirectory(), path);
}
if (target != null) {
strat.addRoot(name, target);
}
}
}
return strat;
}
FileProvider
在标记 root-path
(DEVICE_ROOT 常量)的帮助下接受目录的绝对路径。因此,只需将绝对路径添加到辅助外部磁盘中的文件文件夹,如下所示:
<root-path path="/storage/extSdCard/Android/data/com.edufii/files/image/" name="image-ext2" />
<root-path path="/storage/extSdCard/Android/data/com.edufii/files/video/" name="video-ext2" />
<root-path path="/storage/extSdCard/Android/data/com.edufii/files/datafile/" name="datafile-ext2" />
<root-path path="/storage/extSdCard/Android/data/com.edufii/files/audio/" name="audio-ext2" />
注意 official documentation 没有说明任何关于 <root-path>
的内容,因此将来可能会更改。
FileProvider
不支持辅助外部存储(如可移动 SD 卡)。这在 Android 7 及更高版本中更是一个问题 - 因为您不能再使用 file://
uris。
我已经发布了错误报告 here。
我在我的 XML 中按照@Gubatron 的建议添加了这个根路径并且它有效。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
<root-path name="external_files" path="/storage/" />
</paths>
要访问外部 SD 卡。
先调用uri.getEncodedPath()
得到编码后的路径
"
/external_files/3161-3330/WhatsApp/Media/WhatsApp%20Documents/All%20Currency.pdf
"
然后使用以下逻辑获取外部存储的文件路径
public String getFilePath(){
if (isKitKat && DocumentsContract.isDocumentUri(mContext, uri)) {
// ExternalStorageProvider
if (com.android.externalstorage.documents.equals(uri.getAuthority())) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
} else {
return "/storage" + "/" + split[0] + "/" + split[1];
}
}
}
}
getFilePath()
将给出:
/storage/emulated/0/3161-3330/WhatsApp/Media/WhatsApp Documents/All
Currency.pdf
uri 路径以
开头
/external_files/
文件路径以
开头
/storage/
因此,我们必须在下面添加行
<root-path name="external_files" path="/storage/" />
在
@xml/provider_paths.xml
例如,我正在使用 FileProvider 将我的内部文件公开给图库。为了使其更加统一,我还将我的外部文件放入提供程序(通过外部路径),但对于可移动 SD 卡中的文件,它不起作用。说那个文件夹没有授权。
任何帮助将不胜感激。
感谢
从 android 4.4 开始,普通应用程序不允许访问辅助外部存储设备,即 sd 卡,除了它们的包特定目录,即使您已请求 WRITE_EXTERNAL_STORAGE 权限。
The WRITE_EXTERNAL_STORAGE permission must only grant write access to the primary external storage on a device. Apps must not be allowed to write to secondary external storage devices, except in their package-specific directories as allowed by synthesized permissions. Restricting writes in this way ensures the system can clean up files when applications are uninstalled.
我们来看看FileProvider
代码:
private static PathStrategy parsePathStrategy(Context context, String authority)
...
int type;
while ((type = in.next()) != END_DOCUMENT) {
if (type == START_TAG) {
final String tag = in.getName();
final String name = in.getAttributeValue(null, ATTR_NAME);
String path = in.getAttributeValue(null, ATTR_PATH);
File target = null;
if (TAG_ROOT_PATH.equals(tag)) {
target = buildPath(DEVICE_ROOT, path);
} else if (TAG_FILES_PATH.equals(tag)) {
target = buildPath(context.getFilesDir(), path);
} else if (TAG_CACHE_PATH.equals(tag)) {
target = buildPath(context.getCacheDir(), path);
} else if (TAG_EXTERNAL.equals(tag)) {
target = buildPath(Environment.getExternalStorageDirectory(), path);
}
if (target != null) {
strat.addRoot(name, target);
}
}
}
return strat;
}
FileProvider
在标记 root-path
(DEVICE_ROOT 常量)的帮助下接受目录的绝对路径。因此,只需将绝对路径添加到辅助外部磁盘中的文件文件夹,如下所示:
<root-path path="/storage/extSdCard/Android/data/com.edufii/files/image/" name="image-ext2" />
<root-path path="/storage/extSdCard/Android/data/com.edufii/files/video/" name="video-ext2" />
<root-path path="/storage/extSdCard/Android/data/com.edufii/files/datafile/" name="datafile-ext2" />
<root-path path="/storage/extSdCard/Android/data/com.edufii/files/audio/" name="audio-ext2" />
注意 official documentation 没有说明任何关于 <root-path>
的内容,因此将来可能会更改。
FileProvider
不支持辅助外部存储(如可移动 SD 卡)。这在 Android 7 及更高版本中更是一个问题 - 因为您不能再使用 file://
uris。
我已经发布了错误报告 here。
我在我的 XML 中按照@Gubatron 的建议添加了这个根路径并且它有效。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
<root-path name="external_files" path="/storage/" />
</paths>
要访问外部 SD 卡。
先调用uri.getEncodedPath()
得到编码后的路径
" /external_files/3161-3330/WhatsApp/Media/WhatsApp%20Documents/All%20Currency.pdf "
然后使用以下逻辑获取外部存储的文件路径
public String getFilePath(){
if (isKitKat && DocumentsContract.isDocumentUri(mContext, uri)) {
// ExternalStorageProvider
if (com.android.externalstorage.documents.equals(uri.getAuthority())) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
} else {
return "/storage" + "/" + split[0] + "/" + split[1];
}
}
}
}
getFilePath()
将给出:
/storage/emulated/0/3161-3330/WhatsApp/Media/WhatsApp Documents/All Currency.pdf
uri 路径以
开头/external_files/
文件路径以
开头/storage/
因此,我们必须在下面添加行
<root-path name="external_files" path="/storage/" />
在
@xml/provider_paths.xml