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 i
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;
}
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
}
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.
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;
}
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;
}
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 Manish@bit.ly/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;
}
}