我正在使用第三方文件管理器从文件系统中选择一个文件(在我的情况下为PDF).
这是我启动活动的方式:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(getString(R.string.app_pdf_mime_type));
intent.addCategory(Intent.CATEGORY_OPENABLE);
String chooserName = getString(R.string.Browse);
Intent chooser = Intent.createChooser(intent, chooserName);
startActivityForResult(chooser, ActivityRequests.BROWSE);
Run Code Online (Sandbox Code Playgroud)
这就是我所拥有的onActivityResult
:
Uri uri = data.getData();
if (uri != null) {
if (uri.toString().startsWith("file:")) {
fileName = uri.getPath();
} else { // uri.startsWith("content:")
Cursor c = getContentResolver().query(uri, null, null, null, null);
if (c != null && c.moveToFirst()) {
int id = c.getColumnIndex(Images.Media.DATA);
if (id != -1) {
fileName = c.getString(id);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
代码片段来自Open Intents文件管理器说明,网址为:http:
//www.openintents.org/en/node/829
目的if-else
是向后兼容.我想知道这是否是获取文件名的最佳方式,因为我发现其他文件管理器会返回所有类型的东西.
例如,Documents ToGo返回如下内容:
content://com.dataviz.dxtg.documentprovider/document/file%3A%2F%2F%2Fsdcard%2Fdropbox%2FTransfer%2Fconsent.pdf
Run Code Online (Sandbox Code Playgroud)
上getContentResolver().query()
返回null
.
为了使事情变得更有趣,未命名的文件管理器(我从客户端日志中获取此URI)返回类似于:
/./sdcard/downloads/.bin
Run Code Online (Sandbox Code Playgroud)
是否有从URI中提取文件名的首选方法,或者应该求助于字符串解析?
Ste*_*ein 125
developer.android.com有很好的示例代码:https: //developer.android.com/guide/topics/providers/document-provider.html
一个简化版本,只提取文件名(假设"this"是一个Activity):
public String getFileName(Uri uri) {
String result = null;
if (uri.getScheme().equals("content")) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
cursor.close();
}
}
if (result == null) {
result = uri.getPath();
int cut = result.lastIndexOf('/');
if (cut != -1) {
result = result.substring(cut + 1);
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
Ken*_*ing 42
我正在使用这样的东西:
String scheme = uri.getScheme();
if (scheme.equals("file")) {
fileName = uri.getLastPathSegment();
}
else if (scheme.equals("content")) {
String[] proj = { MediaStore.Images.Media.TITLE };
Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
if (cursor != null && cursor.getCount() != 0) {
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.TITLE);
cursor.moveToFirst();
fileName = cursor.getString(columnIndex);
}
if (cursor != null) {
cursor.close();
}
}
Run Code Online (Sandbox Code Playgroud)
Bha*_*gav 29
private String queryName(ContentResolver resolver, Uri uri) {
Cursor returnCursor =
resolver.query(uri, null, null, null, null);
assert returnCursor != null;
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
String name = returnCursor.getString(nameIndex);
returnCursor.close();
return name;
}
Run Code Online (Sandbox Code Playgroud)
Tam*_*afi 13
对于 Kotlin,您可以使用以下内容:
fun Context.getFileName(uri: Uri): String? = when(uri.scheme) {
ContentResolver.SCHEME_CONTENT -> getContentFileName(uri)
else -> uri.path?.let(::File)?.name
}
private fun Context.getContentFileName(uri: Uri): String? = runCatching {
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
cursor.moveToFirst()
return@use cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME).let(cursor::getString)
}
}.getOrNull()
Run Code Online (Sandbox Code Playgroud)
Sam*_*uel 12
如果你想要它简短,这应该工作.
Uri uri= data.getData();
File file= new File(uri.getPath());
file.getName();
Run Code Online (Sandbox Code Playgroud)
Met*_*etu 11
获取文件名的最简单方法:
val fileName = File(uri.path).name
// or
val fileName = uri.pathSegments.last()
Run Code Online (Sandbox Code Playgroud)
如果他们给您的名字不正确,则应使用:
fun Uri.getName(context: Context): String {
val returnCursor = context.contentResolver.query(this, null, null, null, null)
val nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
returnCursor.moveToFirst()
val fileName = returnCursor.getString(nameIndex)
returnCursor.close()
return fileName
}
Run Code Online (Sandbox Code Playgroud)
小智 9
最精简的版本:
public String getNameFromURI(Uri uri) {
Cursor c = getContentResolver().query(uri, null, null, null, null);
c.moveToFirst();
return c.getString(c.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
Run Code Online (Sandbox Code Playgroud)
我使用下面的代码从我的项目中获取Uri的文件名和文件大小.
/**
* Used to get file detail from uri.
* <p>
* 1. Used to get file detail (name & size) from uri.
* 2. Getting file details from uri is different for different uri scheme,
* 2.a. For "File Uri Scheme" - We will get file from uri & then get its details.
* 2.b. For "Content Uri Scheme" - We will get the file details by querying content resolver.
*
* @param uri Uri.
* @return file detail.
*/
public static FileDetail getFileDetailFromUri(final Context context, final Uri uri) {
FileDetail fileDetail = null;
if (uri != null) {
fileDetail = new FileDetail();
// File Scheme.
if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
File file = new File(uri.getPath());
fileDetail.fileName = file.getName();
fileDetail.fileSize = file.length();
}
// Content Scheme.
else if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Cursor returnCursor =
context.getContentResolver().query(uri, null, null, null, null);
if (returnCursor != null && returnCursor.moveToFirst()) {
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
fileDetail.fileName = returnCursor.getString(nameIndex);
fileDetail.fileSize = returnCursor.getLong(sizeIndex);
returnCursor.close();
}
}
}
return fileDetail;
}
/**
* File Detail.
* <p>
* 1. Model used to hold file details.
*/
public static class FileDetail {
// fileSize.
public String fileName;
// fileSize in bytes.
public long fileSize;
/**
* Constructor.
*/
public FileDetail() {
}
}
Run Code Online (Sandbox Code Playgroud)
如果你想拥有带扩展名的文件名,我使用这个函数来获取它。它也适用于谷歌驱动器文件选择
public static String getFileName(Uri uri) {
String result;
//if uri is content
if (uri.getScheme() != null && uri.getScheme().equals("content")) {
Cursor cursor = global.getInstance().context.getContentResolver().query(uri, null, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
//local filesystem
int index = cursor.getColumnIndex("_data");
if(index == -1)
//google drive
index = cursor.getColumnIndex("_display_name");
result = cursor.getString(index);
if(result != null)
uri = Uri.parse(result);
else
return null;
}
} finally {
cursor.close();
}
}
result = uri.getPath();
//get filename + ext of path
int cut = result.lastIndexOf('/');
if (cut != -1)
result = result.substring(cut + 1);
return result;
}
Run Code Online (Sandbox Code Playgroud)
我的回答有点过分了,但这里是如何从 android 中的 4 种不同的 uri 类型获取文件名。
[content://com.example.app/sample.png]
[file://data/user/0/com.example.app/cache/sample.png]
[android.resource://com.example.app/1234567890]
或[android.resource://com.example.app/raw/sample]
[https://example.com/sample.png]
fun Uri.name(context: Context): String {
when (scheme) {
ContentResolver.SCHEME_FILE -> {
return toFile().nameWithoutExtension
}
ContentResolver.SCHEME_CONTENT -> {
val cursor = context.contentResolver.query(
this,
arrayOf(OpenableColumns.DISPLAY_NAME),
null,
null,
null
) ?: throw Exception("Failed to obtain cursor from the content resolver")
cursor.moveToFirst()
if (cursor.count == 0) {
throw Exception("The given Uri doesn't represent any file")
}
val displayNameColumnIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
val displayName = cursor.getString(displayNameColumnIndex)
cursor.close()
return displayName.substringBeforeLast(".")
}
ContentResolver.SCHEME_ANDROID_RESOURCE -> {
// for uris like [android.resource://com.example.app/1234567890]
var resourceId = lastPathSegment?.toIntOrNull()
if (resourceId != null) {
return context.resources.getResourceName(resourceId)
}
// for uris like [android.resource://com.example.app/raw/sample]
val packageName = authority
val resourceType = if (pathSegments.size >= 1) {
pathSegments[0]
} else {
throw Exception("Resource type could not be found")
}
val resourceEntryName = if (pathSegments.size >= 2) {
pathSegments[1]
} else {
throw Exception("Resource entry name could not be found")
}
resourceId = context.resources.getIdentifier(
resourceEntryName,
resourceType,
packageName
)
return context.resources.getResourceName(resourceId)
}
else -> {
// probably a http uri
return toString().substringBeforeLast(".").substringAfterLast("/")
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
80933 次 |
最近记录: |