Как извлечь имя файла из URI, возвращенного из Intent.ACTION_GET_CONTENT?
Я использую сторонний файловый менеджер, чтобы выбрать файл (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);
Это то, что у меня есть в 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);
}
}
}
}
Фрагмент кода заимствован из инструкций Open Intents File Manager, доступных здесь:
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
на котором getContentResolver().query()
возвращает null
.
Чтобы сделать что-то более интересным, неназванный файловый менеджер (я получил этот URI из журнала клиента), возвращал что-то вроде:
/./sdcard/downloads/.bin
Есть ли предпочтительный способ извлечения имени файла из URI или нужно использовать парсинг строк?
Ответы
Ответ 1
developer.android.com имеет хороший пример кода для этого:
https://developer.android.com/guide/topics/providers/document-provider.html
Конденсированная версия, чтобы просто извлечь имя файла (предполагается, что "this" - это действие):
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;
}
Ответ 2
Я использую что-то вроде этого:
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();
}
}
Ответ 3
Взято из Получение информации о файле | Разработчики Android
Получение имени файла.
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;
}
Ответ 4
Если вы хотите, чтобы это было коротко, это должно работать.
Uri uri= data.getData();
File file= new File(uri.getPath());
file.getName();
Ответ 5
Я использую ниже код, чтобы получить имя файла и размер файла из 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() {
}
}
Ответ 6
Самый простой способ получить имя файла:
val fileName = File(uri.path).name
// or
val fileName = uri.pathSegments.last()
Если они не дают вам правильное имя, вы должны использовать:
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
}
Ответ 7
public String getFilename()
{
/* Intent intent = getIntent();
String name = intent.getData().getLastPathSegment();
return name;*/
Uri uri=getIntent().getData();
String fileName = null;
Context context=getApplicationContext();
String scheme = uri.getScheme();
if (scheme.equals("file")) {
fileName = uri.getLastPathSegment();
}
else if (scheme.equals("content")) {
String[] proj = { MediaStore.Video.Media.TITLE };
Uri contentUri = null;
Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
if (cursor != null && cursor.getCount() != 0) {
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE);
cursor.moveToFirst();
fileName = cursor.getString(columnIndex);
}
}
return fileName;
}
Ответ 8
String Fpath = getPath(this, uri) ;
File file = new File(Fpath);
String filename = file.getName();
Ответ 9
Моя версия ответа на самом деле очень похожа на @Stefan Haustein. Я нашел ответ на странице разработчика Android Извлечение информации о файлах; информация здесь еще более сконцентрирована на этой конкретной теме, чем на Хранилище Access Framework. В результате запроса индекс столбца, содержащий имя файла, равен OpenableColumns.DISPLAY_NAME
. Ни один из других ответов/решений для индексов столбцов не работал у меня. Ниже приведен пример функции:
/**
* @param uri uri of file.
* @param contentResolver access to server app.
* @return the name of the file.
*/
def extractFileName(uri: Uri, contentResolver: ContentResolver): Option[String] = {
var fileName: Option[String] = None
if (uri.getScheme.equals("file")) {
fileName = Option(uri.getLastPathSegment)
} else if (uri.getScheme.equals("content")) {
var cursor: Cursor = null
try {
// Query the server app to get the file display name and size.
cursor = contentResolver.query(uri, null, null, null, null)
// Get the column indexes of the data in the Cursor,
// move to the first row in the Cursor, get the data.
if (cursor != null && cursor.moveToFirst()) {
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
fileName = Option(cursor.getString(nameIndex))
}
} finally {
if (cursor != null) {
cursor.close()
}
}
}
fileName
}
Ответ 10
Сначала вам нужно преобразовать объект URI
в объект URL
, а затем использовать объект File
для получения имени файла:
try
{
URL videoUrl = uri.toURL();
File tempFile = new File(videoUrl.getFile());
String fileName = tempFile.getName();
}
catch (Exception e)
{
}
Это очень легко.
Ответ 11
Функция Стефана Хаустейна для xamarin/С#:
public string GetFilenameFromURI(Android.Net.Uri uri)
{
string result = null;
if (uri.Scheme == "content")
{
using (var cursor = Application.Context.ContentResolver.Query(uri, null, null, null, null))
{
try
{
if (cursor != null && cursor.MoveToFirst())
{
result = cursor.GetString(cursor.GetColumnIndex(OpenableColumns.DisplayName));
}
}
finally
{
cursor.Close();
}
}
}
if (result == null)
{
result = uri.Path;
int cut = result.LastIndexOf('/');
if (cut != -1)
{
result = result.Substring(cut + 1);
}
}
return result;
}
Ответ 12
Если вы хотите иметь имя файла с расширением, я использую эту функцию, чтобы получить его. Он также работает с выбором файлов на диске Google
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;
}
Ответ 13
Это на самом деле работает для меня:
private String uri2filename() {
String ret;
String scheme = uri.getScheme();
if (scheme.equals("file")) {
ret = uri.getLastPathSegment();
}
else if (scheme.equals("content")) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
ret = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
}
return ret;
}
Ответ 14
Для Kotlin, вы можете использовать что-то вроде этого:
object FileUtils {
fun getFileName(context: Context, uri : Uri) : String {
var fileName = "Unknown"
when (uri.scheme) {
ContentResolver.SCHEME_FILE -> {
fileName = File(uri.path).name
}
ContentResolver.SCHEME_CONTENT -> {
try {
context.contentResolver.query(
uri,
null,
null,
null,
null
)?.apply {
if (moveToFirst()) {
fileName = getString(getColumnIndex(OpenableColumns.DISPLAY_NAME))
}
close()
}
} catch (e : Exception) {
return fileName
}
}
}
return fileName
}
}