Extract file data when receiving ACTION_SEND in android - android

I can receive fileinfo in ACTION_VIEW like this:
String[] dataFileds = new String[]{
MediaStore.MediaColumns.DATA,
OpenableColumns.DISPLAY_NAME,
OpenableColumns.SIZE};
Cursor cursor = context.getContentResolver().query(uri, dataFileds, null, null, null);
cursor.moveToFirst();
fileLocation = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA));
title = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
size = cursor.getInt(cursor.getColumnIndex(OpenableColumns.SIZE));
cursor.close();
It has an URI that could look like this: content://downloads/all_downloads/387
My problem is when receiving a file through ACTION_SEND. Here I get an URI that look like this: file:///storage/emulated/0/Download/Arkitekturvalg.pdf
When I use the same code to get the file data, I get an null pointer error on cursor.
How will I be able to receive the file information when a user want to share a file to my app?
Note that bothe of the URIs is for the same file.

If the scheme of the Uri is file, then use getLastPathSegment() to get the "display name" (filename). Then, use new File(uri.getPath()).length() to get the length of the file.

Related

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

Convert content:// uri into a file path

I am having problems converting a uri to a path because of the content tag. So I am trying to select any file type from the Android storage, and I am able to select a file but when I grab the data and try to convert it to a string path my app crashes.
My code to convert the uri looks like
String path = data.getData().getPath();
I've looked around and some say to use a Content provider and content resolver, but I'm not sure how to use them. Any help would be great thanks.
Display it/ upload it to an s3 bucket. When I mean display it, I mean if it's a photo, or video to show it and if it's an audio file I'd like to be able to play it and the same with other files, like PDF and so on.
This method returns the Path as String
private String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(uri, projection, null, null,null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}

Apache FileUtils.MoveFile does not delete image after its been moved, device restart is required for the update to take place

I'm using org.apache.commons.io.FileUtils to move files from one directory to another, like so:
File source = new File("/my/image/directory/image.jpg";
File destination = new File("/new/image/directory/image.jpg");
FileUtils.moveFile(source, destination);
Note that the source directory is an external directory and destination is an internal directory.
After above code is executed, I query to get the files of my internal directory like so:
File vaultDir = ctx.getDir("dir_name", Context.MODE_PRIVATE);
String[] fileList = vaultDir.list();
//Iterate and print file names
This is working as intended. But when i query the MediaStore like so:
ArrayList<GridViewObject> objects = new ArrayList<>();
String[] mProjection = {MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATA};
ContentResolver cr = ctx.getContentResolver();
Cursor mCursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
mProjection,
null,
null,
MediaStore.Images.Media.DEFAULT_SORT_ORDER);
mCursor.moveToFirst();
while (!mCursor.isAfterLast()) {
GridViewObject tmpGridViewObject = new GridViewObject();
tmpGridViewObject.setTitle(mCursor.getString(0));
tmpGridViewObject.setUrl(mCursor.getString(1));
objects.add(tmpGridViewObject);
mCursor.moveToNext();
}
The image is still returned to me by the query. Also, when I open my camera gallery app, the image is still there, as if it was never deleted.
I noticed that if I restart the phone, the image disappears from my device camera gallery app as intended (and above query return correct result). So I think it might be an indexing problem.
What do I need to do to "update" the MediaStore to show the intended result?
I solved this by instead of deleting the file using FileUtils.delete(srcFile, destFile); i copied the the file using FileUtils.copy(srcFile, destFile); and then to refresh MediaStore i used the following code to delete the source entry:
String selection = MediaStore.Images.Media.DATA + "='" + source.getAbsolutePath() + "'";
ctx.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection, null);
Credit goes to Pascal's answer to this question.

Get file path from content URI

I had this working at a time, but now it fails every time I try to get the file path. I am receiving the file from Acrobat Reader and can receive the file name and size, but not the relative file path.
My code looks like this:
if(uri.getScheme().equals("content"))
{
String[] dataFields = new String[]{
MediaStore.MediaColumns.DATA,
OpenableColumns.DISPLAY_NAME,
OpenableColumns.SIZE};
Cursor cursor = context.getContentResolver().query(uri, dataFields, null, null, null);
cursor.moveToFirst();
fileLocation = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA));
title = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
size = cursor.getInt(cursor.getColumnIndex(OpenableColumns.SIZE));
cursor.close();
contentType = context.getContentResolver().getType(uri);
}
I get the following error in LogCat:
Failed to read row 0, column -1 from a CursorWindow which has 1 rows, 2 columns.
I understand it as it can't find the column. However, I don't understand how this can be?
A Uri is not a file. There is no requirement that the Uri be from MediaStore or otherwise have a MediaStore.MediaColumns.DATA column. If you want to access the content represented by the Uri, use openInputStream() on a ContentResolver.

MediaStore - Uri to query all types of files (media and non-media)

In the class MediaStore.Files class, its mentioned that,
Media provider table containing an index of all files in the media storage, including non-media files.
I'm interested in querying for non-media files like PDF.
I'm using CursorLoader to query the database. The second parameter for the constructor requires an Uri argument which is easy to get for the media types Audio, Images and Video as each of them have a EXTERNAL_CONTENT_URI and INTERNAL_CONTENT_URI constant defined for them.
For MediaStore.Files there is no such defined constant. I tried using the getContentUri() method but couldn't figure out the argument value for volumeName. I tried giving "/mnt/sdcard" and also the volume name that appears when I connect the device to my system but in vain.
I saw a similar question on Google Groups but that is not resolved.
EDIT: I also tried using Uri.fromFile(new File("/mnt/sdcard/")) and Uri.parse(new File("/mnt/sdcard").toString()) but that didn't work out either.
It is "external" or "internal" although internal (system files) is probably not useful here.
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);
If you want .pdf only you could check the mimetype
// only pdf
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + "=?";
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf");
String[] selectionArgsPdf = new String[]{ mimeType };
Cursor allPdfFiles = cr.query(uri, projection, selectionMimeType, selectionArgsPdf, sortOrder);

Categories

Resources