Как извлечь имя файла из 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 или следует использовать синтаксический анализ строк?

Solutions Collecting From Web of "Как извлечь имя файла из URI, возвращенного из Intent.ACTION_GET_CONTENT?"

У разработчика.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; } 

Я использую что-то вроде этого:

 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(); } } 

Извлечение информации из файла | Разработчики 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; } 
 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; } 

Если вам это нужно, это должно сработать.

 Uri uri= data.getData(); File file= new File(uri.getPath()); file.getName(); 

Я использую ниже код, чтобы получить имя файла и размер файла из 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() { } } 
 String Fpath = getPath(this, uri) ; File file = new File(Fpath); String filename = file.getName(); 

Моя версия ответа на самом деле очень похожа на @Stefan Haustein. Я нашел ответ на странице разработчика Android. Извлечение информации о файле ; Информация здесь еще более сконцентрирована на этой конкретной теме, чем на веб-сайте Storage 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's 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 } 

Во-первых, вам нужно преобразовать свой объект URI объект URL , а затем использовать объект File для получения имени файла:

 try { URL videoUrl = uri.toURL(); File tempFile = new File(videoUrl.getFile()); String fileName = tempFile.getName(); } catch (Exception e) { } 

Вот и все, очень легко.