Reputation: 5528
I am using 3rd party file manager to pick a file (PDF in my case) from the file system.
This is how I launch the activity:
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);
This is what I have in 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);
}
}
}
}
Code snippet is borrowed from Open Intents File Manager instructions available here:
http://www.openintents.org/en/node/829
The purpose of if-else
is backwards compatibility. I wonder if this is a best way to get the file name as I have found that other file managers return all kind of things.
For example, Documents ToGo return something like the following:
content://com.dataviz.dxtg.documentprovider/document/file%3A%2F%2F%2Fsdcard%2Fdropbox%2FTransfer%2Fconsent.pdf
on which getContentResolver().query()
returns null
.
To make things more interesting, unnamed file manager (I got this URI from client log) returned something like:
/./sdcard/downloads/.bin
Is there a preferred way of extracting the file name from URI or one should resort to string parsing?
Upvotes: 163
Views: 173156
Reputation: 573
Try this,
Intent data = result.getData();
// check condition
if (data != null) {
Uri sUri = data.getData();
@SuppressLint("Recycle")
Cursor returnCursor = getContentResolver().query(sUri, null, null, null, null);
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
String file_name = returnCursor.getString(nameIndex);
}
Upvotes: 2
Reputation: 2852
My answer would be an overkill, but here is how you can get filename from 4 different uri types in android.
[content://com.example.app/sample.png]
[file://data/user/0/com.example.app/cache/sample.png]
[android.resource://com.example.app/1234567890]
or [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("/")
}
}
}
Upvotes: 9
Reputation: 29
How about this?
Uri uri = result.getData().getClipData().getItemAt(i).getUri();
uri = Uri.parse(uri.getLastPathSegment());
System.out.println(uri.getLastPathSegment());
This prints the file name with extension
Upvotes: 2
Reputation: 3530
Here is my utils method to achieve this. You can copy/paste and use it from anywhere.
public class FileUtils {
/**
* Return file name from Uri given.
* @param context the context, cannot be null.
* @param uri uri request for file name, cannot be null
* @return the corresponding display name for file defined in uri or null if error occurs.
*/
public String getNameFromURI(@NonNull Context context, @NonNull Uri uri) {
String result = null;
Cursor c = null;
try {
c = context.getContentResolver().query(uri, null, null, null, null);
c.moveToFirst();
result = c.getString(c.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
catch (Exception e){
// error occurs
}
finally {
if(c != null){
c.close();
}
}
return result;
}
...
}
And usage.
String fileName = FileUtils.getNameFromContentUri(context, myuri);
if(fileName != null){
// do stuff
}
Regards.
Upvotes: 3
Reputation: 4321
If anyone is looking for a Kotlin
answer especially an extension
function, here is the way to go.
fun Uri.getOriginalFileName(context: Context): String? {
return context.contentResolver.query(this, null, null, null, null)?.use {
val nameColumnIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME)
it.moveToFirst()
it.getString(nameColumnIndex)
}
}
Upvotes: 3
Reputation: 2511
For Kotlin you can use something like this:
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()
Upvotes: 34
Reputation: 391
This will return the filename from Uri without file extension.
fun Uri.getFileName(): String? {
return this.path?.let { path -> File(path).name }
}
Here I described a way to get the filename with the extension.
Upvotes: 0
Reputation: 11
我从开发者官网找到一些信息
I got some information from the developer's website
取得游标
val cursor = context.contentResolver.query(fileUri, null, null, null, null)
接着就可以获取名称和文件大小
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
cursor.moveToFirst()
val fileName = cursor.getString(nameIndex)
val size = cursor.getLong(sizeIndex)
别忘记关闭资源
Don't forget to close resources
Upvotes: 0
Reputation: 13432
Here is what I have arrived at after a read of all the answers presented here as well what some Airgram has done in their SDKs - A utility that I have open sourced on Github:
https://github.com/mankum93/UriUtilsAndroid/tree/master/app/src/main/java/com/androiduriutils
As simple as calling, UriUtils.getDisplayNameSize()
. It provides both the name and size of the content.
Note: Only works with a content:// Uri
Here is a glimpse on the code:
/**
* References:
* - https://www.programcreek.com/java-api-examples/?code=MLNO/airgram/airgram-master/TMessagesProj/src/main/java/ir/hamzad/telegram/MediaController.java
* - https://stackoverflow.com/questions/5568874/how-to-extract-the-file-name-from-uri-returned-from-intent-action-get-content
*
* @author [email protected]/2HjxA0C
* Created on: 03-07-2020
*/
public final class UriUtils {
public static final int CONTENT_SIZE_INVALID = -1;
/**
* @param context context
* @param contentUri content Uri, i.e, of the scheme <code>content://</code>
* @return The Display name and size for content. In case of non-determination, display name
* would be null and content size would be {@link #CONTENT_SIZE_INVALID}
*/
@NonNull
public static DisplayNameAndSize getDisplayNameSize(@NonNull Context context, @NonNull Uri contentUri){
final String scheme = contentUri.getScheme();
if(scheme == null || !scheme.equals(ContentResolver.SCHEME_CONTENT)){
throw new RuntimeException("Only scheme content:// is accepted");
}
final DisplayNameAndSize displayNameAndSize = new DisplayNameAndSize();
displayNameAndSize.size = CONTENT_SIZE_INVALID;
String[] projection = new String[]{MediaStore.Images.Media.DATA, OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE};
Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
// Try extracting content size
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
if (sizeIndex != -1) {
displayNameAndSize.size = cursor.getLong(sizeIndex);
}
// Try extracting display name
String name = null;
// Strategy: The column name is NOT guaranteed to be indexed by DISPLAY_NAME
// so, we try two methods
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if (nameIndex != -1) {
name = cursor.getString(nameIndex);
}
if (nameIndex == -1 || name == null) {
nameIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
if (nameIndex != -1) {
name = cursor.getString(nameIndex);
}
}
displayNameAndSize.displayName = name;
}
}
finally {
if(cursor != null){
cursor.close();
}
}
// We tried querying the ContentResolver...didn't work out
// Try extracting the last path segment
if(displayNameAndSize.displayName == null){
displayNameAndSize.displayName = contentUri.getLastPathSegment();
}
return displayNameAndSize;
}
}
Upvotes: 1
Reputation: 181
The most condensed version:
public String getNameFromURI(Uri uri) {
Cursor c = getContentResolver().query(uri, null, null, null, null);
c.moveToFirst();
return c.getString(c.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
Upvotes: 16
Reputation: 21
Please try this :
private String displayName(Uri uri) {
Cursor mCursor =
getApplicationContext().getContentResolver().query(uri, null, null, null, null);
int indexedname = mCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
mCursor.moveToFirst();
String filename = mCursor.getString(indexedname);
mCursor.close();
return filename;
}
Upvotes: 2
Reputation: 2238
This actually worked for me:
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;
}
Upvotes: 2
Reputation: 465
If you want to have the filename with extension I use this function to get it. It also works with google drive file picks
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;
}
Upvotes: 9
Reputation: 5093
Stefan Haustein function for xamarin/c#:
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;
}
Upvotes: 1
Reputation: 1093
Easiest ways to get file name:
val fileName = File(uri.path).name
// or
val fileName = uri.pathSegments.last()
If they don't give you the right name you should use:
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
}
Upvotes: 35
Reputation: 9993
If you want it short this should work.
Uri uri= data.getData();
File file= new File(uri.getPath());
file.getName();
Upvotes: 17
Reputation: 6375
I use below code to get File Name & File Size from Uri in my project.
/**
* 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() {
}
}
Upvotes: 11
Reputation: 8277
Taken from Retrieving File information | Android developers
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;
}
Upvotes: 60
Reputation: 8588
First, you need to convert your URI
object to URL
object, and then use File
object to retrieve a file name:
try
{
URL videoUrl = uri.toURL();
File tempFile = new File(videoUrl.getFile());
String fileName = tempFile.getName();
}
catch (Exception e)
{
}
That's it, very easy.
Upvotes: 2
Reputation: 2092
My version of the answer is actually very similar to the @Stefan Haustein. I found the answer on Android Developer page Retrieving File Information; the information here is even more condensed on this specific topic than on Storage Access Framework guide site. In the result from the query the column index containing file name is OpenableColumns.DISPLAY_NAME
. None of other answers/solutions for column indexes worked for me. Below is the sample function:
/**
* @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
}
Upvotes: 1
Reputation: 19
String Fpath = getPath(this, uri) ;
File file = new File(Fpath);
String filename = file.getName();
Upvotes: 1
Reputation: 18793
developer.android.com has nice example code for this: https://developer.android.com/guide/topics/providers/document-provider.html
A condensed version to just extract the file name (assuming "this" is an 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;
}
Upvotes: 230
Reputation: 2111
I'm using something like this:
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();
}
}
Upvotes: 50
Reputation: 1576
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;
}
Upvotes: 4