有没有一种直接的方法可以从文件 Uri 中获取父目录的 Uri?
Posted
技术标签:
【中文标题】有没有一种直接的方法可以从文件 Uri 中获取父目录的 Uri?【英文标题】:Is there a straightforward way to get the parent directory's Uri from a file Uri? 【发布时间】:2018-08-01 14:05:00 【问题描述】:假设一个 Uri 可以是以下任意一种:
来自存储访问框架的 DocumentFile 的 Uri(即 DocumentFile.getUri())。 来自常规文件的 Uri(即 Uri.fromFile(File))在这两种情况下都是指目录下的文件。
有没有一种直接的方法来获取其父目录的 Uri,而无需尝试两者中的每一个来查看哪个有效?
[编辑]: 以下是 SAF 的示例:
URI:
content://com.android.externalstorage.documents/tree/0000-0000%3Atest/document/0000-0000%3Atest%2Ffoo%2FMovies%2FRR%20parking%20lot%20a%202018_02_22_075101.mp4
getPath():
/tree/0000-0000:test/document/0000-0000:test/foo/Movies/RR 停车场 2018_02_22_075101.mp4
getPathSegments():
0 = "tree"
1 = "0000-0000:test"
2 = "document"
3 = "0000-0000:test/foo/Movies/RR parking lot a 2018_02_22_075101.mp4"
父文件夹应该是 test/foo/Movies。
以下是常规文件的示例:
URI:
file:///storage/emulated/0/foo/Movies/RR%20parking%20lot%20a%202018_02_22_081351.mp4
getPath():
/storage/emulated/0/foo/Movies/RR 停车场a 2018_02_22_081351.mp4
getPathSegments():
0 = "storage"
1 = "emulated"
2 = "0"
3 = "foo"
4 = "Movies"
5 = "RR parking lot a 2018_02_22_081351.mp4"
【问题讨论】:
您假设 Android Uri 必须与某种父目录相关联,这不是真的。 Uri 不需要父级,甚至不需要与文件关联。存储访问框架的 Uri 可以引用存储在 SQLite 数据库中的 blob。在这种情况下,没有父“目录”可言,该 Uri 将直接与该 DocumentsProvider 的“存储根”相关联。此外,非文档 Uris(来自旧的 ContentProvider 基础设施的 Uris)甚至没有层次结构的概念它们只是不透明的字符串,可能引用一些字节流 感谢您的解释。我明白了。很抱歉模棱两可。我编辑了这个问题,以明确它在两种情况下都指的是目录下的文件。 @Hong 你试过什么?鉴于您正在使用已知的 nfile URI,我认为getPath()
或 getPathSegments() 将是一个好的开始。
@AndrewHenle 根据您的要求,我在问题中添加了一个示例,因为不可能在评论中这样做。您是否建议通过解析文件 Uri 来获取父 Uri?如果是这样,这在所有 Android 版本中是否可靠?
@Hong 根据您发布的内容,您将不得不对您得到的内容进行一些解析。 这在所有版本的 Android 中都可靠吗? 我不确定是否有人可以回答这个问题。 “最后一个 '/'
字符左侧的所有内容”可能是您能做的最好的事情。
【参考方案1】:
晚了 3 年,我遇到了类似的问题。我已经使用 Android 26 API DocumentsContract.findDocumentPath 解决了这个问题。这对我来说没问题,因为我在项目的早期 Android 版本上使用了 File API。
基本上,我使用 findDocumentPath 找到文档的路径并从中删除最后一段(即找到父目录的路径)。然后,为了改造 SAF Uri,我在 Uri 中找到最后一个 / 或 : 字符,并将下一部分替换为父目录的路径。
public static String GetParentDirectory( ContentResolver resolver, String rawUri )
if( !rawUri.contains( "://" ) )
// This is a raw filepath, not a SAF path
return new File( rawUri ).getParent();
// Calculate the URI's path using findDocumentPath, omit the last path segment from it and then replace the rawUri's path component entirely
DocumentsContract.Path rawUriPath = DocumentsContract.findDocumentPath( resolver, Uri.parse( rawUri ) );
if( rawUriPath != null )
List<String> pathSegments = rawUriPath.getPath();
if( pathSegments != null && pathSegments.size() > 0 )
String rawUriParentPath;
if( pathSegments.size() > 1 )
rawUriParentPath = Uri.encode( pathSegments.get( pathSegments.size() - 2 ) );
else
String fullPath = pathSegments.get( 0 );
int separatorIndex = Math.max( fullPath.lastIndexOf( '/' ), fullPath.lastIndexOf( ':' ) + 1 );
rawUriParentPath = separatorIndex > 0 ? Uri.encode( fullPath.substring( 0, separatorIndex ) ) : null;
if( rawUriParentPath != null && rawUriParentPath.length() > 0 )
int rawUriLastPathSegmentIndex = rawUri.lastIndexOf( '/' ) + 1;
if( rawUriLastPathSegmentIndex > 0 )
String rawUriParent = rawUri.substring( 0, rawUriLastPathSegmentIndex ) + rawUriParentPath;
if( !rawUriParent.equals( rawUri ) )
return rawUriParent;
return null;
【讨论】:
以上是关于有没有一种直接的方法可以从文件 Uri 中获取父目录的 Uri?的主要内容,如果未能解决你的问题,请参考以下文章
有没有一种方便的方法可以将文件 uri 映射到 os.path?