I'm using Intent.ACTION_GET_CONTENT which opens recent files. Selecting items from the recent files gives a bad URI but selecting the same file from the file manager gives a right URI which can be handled by my code.
public static String getRealPathFromURI(Context context, Uri uri) {
String path;
if ("content".equals(uri.getScheme())) {
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
path = cursor.getString(idx);
cursor.close();
} else {
path = uri.getPath();
}
return path;
}
Note: The uri.getPath() output when I select a PDF from the recent files is /document/... but selecting the same file from the file manager is, .../emulated/....
Note: the error while selecting the file from the recent files is
Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
The problem was my code doesn't handle the new Layout Storage URIs of Android. If you face this problem too, please refer to this link because the writer is wrote a fantastic method to get real path of every URIs.
Related
I have image uri like this :"content://com.iceburgapp.provider/external_files/.pkgName/File1.jpg"
Now whenever I get path it give me : "/external_files/.pkgName/File1.jpg"
I want to get RealPathFrom content Uri.
I got solution from stackoverflow and I tried below code but not working for me :
public String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
AnyOne know How to do this? I got below error for using above code.
java.lang.IllegalArgumentException: column '_data' does not exist. Available columns: []
It's only not working in the Nought and oreo device because of contentUri using file provider.
Use a ContentResolver and openInputStream() to get an InputStream on the content identified by the Uri. Ideally, just use that stream directly, for whatever it is that you are trying to do. Or, use that InputStream and some FileOutputStream on a file that you control to make a copy of the content, then use that file.
This is working properly in devices before Android N
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);
}
I use MediaStore to get all Images from Android device. Then after I delete some of the Images from File Manager. Followed I use MediaStore again to get Images, and I get all deleted files which is problem.
Why MediaStore returns files that are no longer are on the device(Deleted from device) ?
Code which I am using to retrieve image from MediaStore.
Uri uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
Cursor cursor = activity.getContentResolver().query(uri, projection, null, null, MediaStore.MediaColumns.DATE_ADDED + " DESC");
String ImagePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA));
Help to resolve this issue.
Why MediaStore returns files that are no longer are on the device(Deleted from device) ?
Because whatever file manager you used did not do anything to inform the MediaStore about the deletion of the files. MediaStore will find out eventually, but it may be several hours.
You can rescan Media using below code
MediaScannerConnection.scanFile(context, new String[]{imagePath}, null, new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
//something that you want to do
}
});
So far, we have solved Cursor == null when retrieved via ContentResolver by using separate logic for SDKs <11, 11-18, >=19. Something like
public static Cursor getRealPathFromURI_API19(Context context, Uri uri) {
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(uri, filePathColumn, null, null, null);
return cursor;
}
public static Cursor getRealPathFromURI_API11to18(Context context, Uri contentUri) {
String[] proj = {MediaStore.Images.Media.DATA};
String result = null;
CursorLoader cursorLoader = new CursorLoader(context, contentUri, proj, null, null, null);
Cursor cursor = cursorLoader.loadInBackground();
return cursor;
}
public static Cursor getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
return cursor;
}
However, on Galaxy S5, when we save an image to its own directory in the internal public memory (not private data/data), we get cursor==null. On other devices, we DON't get null cursor.
The flow of the app is like this:
Take image with Camera
Save it into file in its own directory (public directory in internal memory)
Access file via ContentResolver and return Cursor
Steps 1 and 2 are properly done. Verified! I can see the image I take via Camera inside the specified directory.
I also checked if the Bitmap is accessible via
InputStream input;
Bitmap bmp;
try {
input = getContentResolver().openInputStream(uri);
bmp = BitmapFactory.decodeStream(input);
} catch (FileNotFoundException e1) {
Log.e("tafg", "error");
}
and I never get an exception.
However, in spite of all this, Cursor remains null on some devices. Anyone can guess why and what is the ultimate way never to get null cursor?
PS. is there any 3rd party library that handles this part properly?
PPS. We are using Retrofit to get up to 10 images saved via Camera and upload to the remote server. Using and working with Bitmap is not possible in this case as we get OOM on the 5th or 6th image. So Retrofit logic must use ContentResolver to get hold of the image(s) that need(s) to be uploaded.
So far, we have solved Cursor == null when retrieved via ContentResolver by using separate logic for SDKs <11, 11-18, >=19.
I strongly recommend that you delete all that code and use a Uri properly.
The flow of the app is like this:
Your step #3 is pointless. You know where the file is, because you put it there in step #2. And, by getting rid of step #3, you can also get rid of all of the bogus "real path" code.
Anyone can guess why
Perhaps MediaStore does not know about the image, because it has not been indexed yet. See MediaScannerConnection and its scanFile() method.
Also note that you are not actually setting cursor to a value in getRealPathFromURI_API19(). I would expect that code to not compile, so I am assuming that it is a copy/paste problem in your question.
what is the ultimate way never to get null cursor?
Stop querying for it in the first place.
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.