Android: Get file path from Uri of file in SD card - android

We are trying to fetch the path of a file that is saved in SD Card, to pass on to a utility. However when we use the URI to open a cursor, only two columns are being fetched, the path (_data column) is missing. Please let me know how to fetch the path. The query works fine for any file that is in internal storage.
Scheme is "content".
Code snippet
cursor = context.getContentResolver().query(uri, null, null, null, null);
if (null != cursor && cursor.moveToFirst())
{
int testcolCount = cursor.getColumnCount();
for (int i = 0; i < testcolCount; i++)
{
String colName = cursor.getColumnName(i);
String colValue = cursor.getString(i);
System.out.println("" + i + ": " + colName + ":" + colValue + "\n");
}
//This prints only two columns, _display_name and _size
}

Don't try and get the path at all, with Android 10 and above file paths outside of your App's private directories are useless because you won't have permission to access them.
See https://developer.android.com/training/data-storage#scoped-storage
Use the contentResolver to get a FileDescriptor to pass on to the Utility
Note From https://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html#DATA
This constant was deprecated in API level 29.
Apps may not have filesystem permissions to directly access this path. Instead of trying to open this path directly, apps should use ContentResolver#openFileDescriptor(Uri, String) to gain access.

try this code i am using this function to get real path from uri:
private String getRealPathFromURI(Context mContext, Uri contentURI) {
String result = null;
Cursor cursor = null;
try {
String[] proj = {MediaStore.Video.Media.DATA};
ContentResolver mContentResolver = mContext.getContentResolver();
String mime = mContentResolver.getType(contentURI);
cursor = mContentResolver.query(contentURI, proj, null, null, null);
if (cursor == null) {
return null;
} else {
cursor.moveToFirst();
int column_index = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
if (column_index > -1)
result = cursor.getString(column_index);
cursor.close();
}
} catch (Exception e) {
return null;
} finally {
if (cursor != null)
cursor.close();
}
return result;
}
it will return a string which is real path of your file.
hope it will help you.

The default File manager was the one causing this problem - not returning "DATA" column and returning Authority as "com.lenovo.FileBrowser.FileProvider". When I used another file manager, the Authority was "media". Also got the path column using "DATA" while running the ContenResolver. Thanks to all for taking the effort to help out.

Related

Android get all folders that contain at least one media file like photo / video

I just need the path of folders that contain at least one file that ends with eg. .mp4 or .jpg . I already checked this thread: Android: how to get all folders with photos? but it's too slow for my use case. Is there a faster way to do that?
So I finally found a solution which is way faster than the mentioned above. I got all directories with images within ~100-150ms (around 3k files). In the example below all image files stored either on the internal or external storage gets checked and the parent directory is added to the array list. I excluded .gif and .giff files.
This method also works with videos therefore a few steps are required:
change queryUri to MediaStore.Video.Media.EXTERNAL_CONTENT_URI
change projection to MediaStore.Video.Media.DATA
change 'image/%' in includeImages to 'video/%'
delete + excludeGif from selection
public static ArrayList<String> getImageDirectories(Context mContext) {
ArrayList<String> directories = new ArrayList<>();
ContentResolver contentResolver = mContext.getContentResolver();
Uri queryUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = new String[]{
MediaStore.Images.Media.DATA
};
String includeImages = MediaStore.Images.Media.MIME_TYPE + " LIKE 'image/%' ";
String excludeGif = " AND " + MediaStore.Images.Media.MIME_TYPE + " != 'image/gif' " + " AND " + MediaStore.Images.Media.MIME_TYPE + " != 'image/giff' ";
String selection = includeImages + excludeGif;
Cursor cursor = contentResolver.query(queryUri, projection, selection, null, null);
if (cursor != null && cursor.moveToFirst()) {
do {
String photoUri = cursor.getString(cursor.getColumnIndex(projection[0]));
if(!directories.contains(new File(photoUri).getParent())){
directories.add(new File(photoUri).getParent());
}
} while (cursor.moveToNext());
}
return directories;
}

How to get Uri of file to Upload file to server?

I am getting audio files from specific folder and binding them on recyclerview. now i want Uri of each file so i can upload them one-by-one. i am using Cursor to get files. below is my code :
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Audio.AudioColumns.SIZE,MediaStore.Audio.AudioColumns.TITLE,android.provider.MediaStore.Audio.AudioColumns.DATA,
MediaStore.Audio.AudioColumns.DURATION,MediaStore.Audio.AudioColumns.TITLE};
Cursor c = context.getContentResolver().query(uri, projection, MediaStore.Audio.Media.DATA + " like ? ", new String[]{"%/storage/emulated/0/Call%"},null);
if (c != null ) {
for (int i = 0; i < 50 && c.moveToNext(); ++i) {
// Create a model object.
POJO audioModel = new POJO();
long id = c.getLong(4);
String SIZE = c.getString(0); // Retrieve path.
String NAME = c.getColumnName(1); // Retrieve name.
String PATH = c.getString(2); // Retrieve album name.
String DURATION = c.getString(3); // Retrieve artist name.
Uri contentUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,id);
audioModel.setSize(SIZE);
audioModel.setName(NAME);
audioModel.setPath(PATH);
audioModel.setDuration(DURATION);
audioModel.setUri(contentUri);
Log.d("#", String.valueOf(contentUri));
arrayListFile.add(audioModel);
}
c.close();
}
return arrayListFile;
in contentUri i am getting this ( content://media/external/audio/media/0 ) . and what i want is
content://com.android.providers.media.documents/document/xyz.mp3. how can i do ??
why do not use MediaStore.Files.FileColumns.DATA ? the path can be also used to upload to server.
Please consider using (MediaStore.Audio.Media.DATA must be part of your projection):
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
Uri yourFileUri = Uri.parse(cursor.getString(column_index));

GetRealPath for image Android10

I am trying to get real path for Picked image in Android 10 but it's not working Iam using the folowing code its work fine in android 9
public static String getRealPathFromURI(Context context, Android.Net.Uri contentUri)
{
ICursor cursor = context.ContentResolver.Query(contentUri, null, null, null, null);
cursor.MoveToFirst();
String document_id = cursor.GetString(0);
document_id = document_id.Substring(document_id.LastIndexOf(":") + 1);
cursor.Close();
cursor = context.ContentResolver.Query(
Android.Provider.MediaStore.Images.Media.ExternalContentUri,
null, MediaStore.Images.Media.InterfaceConsts.Id + " = ? ", new string[] { document_id }, null);
cursor.MoveToFirst();
String path = cursor.GetString(cursor.GetColumnIndex(MediaStore.Images.Media.InterfaceConsts.Data));
cursor.Close();
return path;
}
Option1
After SDK 29.0 ,DATA is deprecated . Apps may not have filesystem permissions to directly access this path. Instead of trying to open this path directly, apps should use ContentResolver#openFileDescriptor(Uri, String) to gain access.
Here is a similar thread which you can refer .
Option 2
You could install the plugin Xam.Plugin.Media from nuget .
Usage
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
return;
}
var file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
var path = file.Path;
For more details about the plugin you could check https://github.com/jamesmontemagno/MediaPlugin

How do I get the file name from an Android URI, not just the display name?

so I'm pretty new to Android development. I'm trying to have the user select a song from their SD card or internal storage using a file manager and upload the file to a server. Right now, I'm just trying to access the name of the file that the user selected so that I can use it to access the contents of the file later and upload those contents.
I've looked at other posts concerning this and most of them tell you to query the content resolver and then use the cursor to grab the display name, but that does not always return the display name (this is mentioned in Google's guide to the SAF). It has not been returning the full file name, just part of it (the title of the song).
Here's my code that starts the intent:
Intent chooseIntent = new Intent(Intent.ACTION_GET_CONTENT);
chooseIntent.addCategory(Intent.CATEGORY_OPENABLE);
chooseIntent.setType("audio/*");
startActivityForResult(chooseIntent, SELECT_SONG_FILE_REQUEST_CODE);
How I'm getting the display name now:
String fileName = null;
if (uri.getScheme().equals("content")) {
try (Cursor cursor = getContentResolver().query(uri, null, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
fileName = cursor.getString(
cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME));
Log.i(TAG, "Filename: " + fileName);
cursor.close();
}
}
}
How can I get the full file name rather than just the display name?
You also can use TITLE in Cursor as URI parameter to get the full name of file
use below code it
Cursor cursor = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,MediaStore.Audio.Media.TITLE, null, null, null);
Or You can use DATA to get Path of the file
Cursor cursor = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,MediaStore.Audio.Media.DATA, null, null, null);
All You have to do is let the user choose the music and after selecting with the use of DATA you have full path of song and with TITLE you have full name of file .
Next just upload it.
There are several things that you can do to improve the performance of the query
You are getting all the columns which can be painfully slow.
You can write code like the one below and then check what field you want to use. You will get all the data for all the audio files installed in the device. You can walk through this code in the debugger to see the data that you need.
{
Uri objUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
ContentResolver cr = context.getContentResolver();
String[] entityColumns = {MediaStore.Audio.AudioColumns.DATA,
MediaStore.Audio.AudioColumns.DISPLAY_NAME,
MediaStore.Audio.AudioColumns.TITLE};
cursor = cr.query(
objUri,
entityColumns,
null,
null,
null);
if (cursor != null && cursor.moveToFirst()) {
do {
String filePath = cursor.getString(cursor.getColumnIndex(entityCoumns[0]));
String fileName = cursor.getString(cursor.getColumnIndex(entityColumns[1]));
String fileTitle =
cursor.getString(cursor.getColumnIndex(entityColumns[2]));
} while (cursor.moveToNext());
cursor.close();
}
}

Best way to get all documents from mobile?

I want to get all types of documents pdf,xml,doc except video and image and audio files.
And display list with name, size, date, and location.
ContentResolver cr = context.getContentResolver();
Uri uri = MediaStore.Files.getContentUri("external");
// every column, although that is huge waste, you probably need
// BaseColumns.DATA (the path) only.
String[] projection = null;
// exclude media files, they would be here also.
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_NONE;
String[] selectionArgs = null; // there is no ? in selection so null here
String sortOrder = null; // unordered
Cursor allNonMediaFiles = cr.query(uri, projection, selection, selectionArgs, sortOrder);
I am using this code for getting documents from mobile is it work? And how to get the document details like uri, date, and name. thanks advance.
Try this one:
File path;
ArrayList<String> pdf_paths=new ArrayList<String>();
ArrayList<String> pdf_names=new ArrayList<String>();
path = new File(Environment.getExternalStorageDirectory() + "");
searchFolderRecursive1(path);
private static void searchFolderRecursive1(File folder)
{
if (file.isFile())
{
//.pdf files
if(file.getName().contains(".pdf"))
{
file.getPath();
pdf_names.add(file.getName());
pdf_paths.add(file.getPath());
Log.e("pdf_paths", ""+pdf_names);
}
else if(file.getName().contains(".doc"))
{
file.getPath();
pdf_names.add(file.getName());
pdf_paths.add(file.getPath());
}
}
}
String ext =FilenameUtils.getExtension(mediSore.getString(mediSore.getColumnIndex(MediaStore.Files.FileColumns.DATA)));
if(ext.equals("pdf") || ext.equals("txt")|| ext.equals("docx") ||
ext.equals("xlsx") ||
ext.equals("csv")||
ext.equals("ods")||
ext.equals("odt")
) {
Array.add(
mediSore.getString(mediSore.getColumnIndex(MediaStore.Files.FileColumns.DATA)) + " -- " +
mediSore.getString(mediSore.getColumnIndex(MediaStore.Files.FileColumns.TITLE)) + "---" +
mediSore.getString(mediSore.getColumnIndex(MediaStore.Files.FileColumns.DISPLAY_NAME))
);
Heading

Categories

Resources