I have a method below:
private String getRealPathFromUriForVideos(Uri selectedVideoUri) {
String wholeID = DocumentsContract.getDocumentId(selectedVideoUri);
String id = wholeID.split(":")[1];
String[] column = { MediaStore.Video.Media.DATA };
String sel = MediaStore.Video.Media._ID + "=?";
Cursor cursor = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null);
String filePath = "";
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
return filePath;
}
This works just fine getting the file for videos that hte user selects. However, I want to allow users to also create new videos (from my app) and then get the URI and the file from there. The URI for newly created videos is: content://media/external/video/media/41. For selected videos is like content://com.android.providers.media.documents/document/video%3A42.
It works with the second one but not the first one. First one I get IllegalArgumentException because its not a document URI. How can I get the file from the first URI?
This works just fine getting the file for videos that hte user selects
It may work in a few situations. It will not work in general. A Uri that you get from something like ACTION_OPEN_DOCUMENT does not have to represent a file, let alone one that you can access via the filesystem, let alone one that this script-kiddie algorithm will let you access.
The URI for newly created videos is: content://media/external/video/media/41
Not necessarily. I suppose that there is a way that you get a Uri like that for a recorded video, though off the top of my head I cannot think of a recommended way that would give you such a Uri. If you are using MediaRecorder or ACTION_VIDEO_CAPTURE, you create your own file (and, for ACTION_VIDEO_CAPTURE, your own Uri for that file). And, if you are creating your own file, you know where that file is.
Need to be able to upload to my server
For the video, record to a file that you control, then use that file.
Use some library that lets you upload from a Uri or InputStream. Otherwise:
Use ContentResolver and openFileInput() to get an InputStream on the content represented by the Uri
Create a FileOutputStream on some file that you control (e.g., in getCacheDir())
Copy the content from the InputStream to the OutputStream
Use your copy for the upload
Delete your copy when the work is done
You treat a foreign Uri as if it were a URL to a Web server: stream the content.
Seems to get it from the second URI I need this:
private String getRealPathFromUriForImagesAndVideo(Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = {MediaStore.Images.Media.DATA};
cursor = getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} catch (Exception e) {
return contentUri.getPath();
} finally {
if (cursor != null) {
cursor.close();
}
}
}
Related
I am testing app on nexus 5 which has marshmallow version of android. I am looked into several method to get file path from uri but all the time it returns null. This method works for me on jelly bean and also on kitkat but not on marshmallow.
public String getPath(Uri uri) {
Log.d(TAG,"Uri GET PATH "+uri);
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
Log.d(TAG,"Cursor value "+cursor);
int Column_Index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
Log.d(TAG,"Column Index "+Column_Index);
cursor.moveToFirst();
String ImagePath = cursor.getString(Column_Index);
Log.d(TAG,"ImagePath of "+ImagePath);
cursor.close();
return ImagePath;
}
I also tried this this and also so many others but getting file path from uri is always null.
Uri return from Intent:content://com.android.providers.media.documents/document/image%3A2304`
I am looked into several method to get file path from uri but all the time it returns null
There is no file path. A Uri is not a file.
Use a ContentResolver and openInputStream() to get an InputStream on the content identified by the Uri. Either use that InputStream directly, or use it and a FileOutputStream on some file that you control (e.g., in getCacheDir()) to copy the content to the file, then use the resulting file.
I'm trying to get a video from the Android Gallery and get the full path, so I can upload the video in an app...
I'm displaying the gallery like this:
Intent intent = new Intent();
intent.setType("video/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
activity.startActivityForResult(Intent.createChooser(intent, context.getResources().getString(R.string.popup_menu_share_video_title)), Const.PICK_VIDEO_REQUEST);
I then extract the uri:
Uri selectedUri = data.getData();
String selectedPath = getRealPathFromURI(this, selectedUri);
And attempt to get the path:
public String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Video.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
But I can't seem the get the path...
I can see all the videos if I do this:
public static void dumpVideos(Context context ) {
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaStore.Video.Media.DATA };
Cursor c = context.getContentResolver().query(uri, projection, null, null, null);
int vidsCount = 0;
if (c != null) {
vidsCount = c.getCount();
while (c.moveToNext()) {
Log.d("VIDEO", c.getString(0));
}
c.close();
}
Log.d("VIDEO", "Total count of videos: " + vidsCount);
}
So I'm thinking there must be some real simple step, that I'm missing...
I'm trying to get a video from the Android Gallery
First, there is no "Android Gallery". There are many apps that might be considered "gallery" apps. There are thousands of device models, and they will ship with a wide variety of "gallery" apps, in addition to those that the user installs.
Second, ACTION_GET_CONTENT is not somehow magically limited to "gallery" apps. Any app can elect to support ACTION_GET_CONTENT for video/*.
and get the full path
That is impossible. You have no way of knowing what app the user chooses to handle your ACTION_GET_CONTENT request. You have no way of knowing what sort of Uri you will get back. You have no way of knowing where the content identified by that Uri will be stored, as it does not have to be a file on the filesystem that you can access.
so I can upload the video in an app
Use openInputStream() on ContentResolver to get an InputStream on the content identified by the Uri. Then, either:
Use that stream directly with your preferred HTTP client API to upload the content, or
Use that stream to make a local file copy of the content, then use that file with your preferred HTTP client
And attempt to get the path:
At best, that code will work in very limited circumstances:
The app that the user chooses to handle your ACTION_GET_CONTENT request happens to return a content Uri from the MediaStore
That content happens to be on external storage, not removable storage
Since that will not cover all of your scenarios, get rid of that code.
I can see all the videos if I do this
No, you can get paths for some videos:
Not every video accessible via ACTION_GET_CONTENT will be known to the MediaStore
Not every video in the MediaStore will be on external storage, where you might be able to access it via filesystem APIs
you can solve this issue by using ACTION_PICK instead of ACTION_GET_CONTENT. I believe unless you need the functionality of adding pictures/videos from Dropbox etc. it's not worth it.If all you need is to get stuff from the gallery use this code:
if (Build.VERSION.SDK_INT < 19) {
final Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/* video/*");
startActivityForResult(photoPickerIntent, PICK_PHOTO_ACTIVITY_REQUEST_CODE);
} else {
final Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("*/*");
photoPickerIntent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"image/*", "video/*"});
startActivityForResult(photoPickerIntent, PICK_PHOTO_ACTIVITY_REQUEST_CODE);
}
I just tried the code you posted with ACTION_PICK and it works perfectly!
I want to get file path from Uri for a video. The following method works fine when testing with a real device, however, it fails (returns null) when testing on emulator.
public String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = {MediaStore.Video.Media.DATA};
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
What is the correct way of getting file path from uri on emulator?
The following method works fine when testing with a real device
Only on the the device that you tried, and only for the app that you tried. Particularly on Android 4.4+, your approach will be unreliable. That is because a Uri is not a file. On older versions of Android, for a Uri from the MediaStore, your approach might work.
Nowadays, do not attempt to get a file for a Uri. Consume the Uri as you are supposed to, using methods on ContentResolver to get an InputStream, the MIME type, etc.
What is the correct way of getting file path from uri on emulator?
There is none. There does not have to be a file path associated with a Uri, let alone a path that your app is able to access using Java file I/O.
As CommonsWare mentioned, an Uri is NOT a File. The general way to deal with Uri is to use an inputstream and save the content as a file (assuming that's what you are looking for). What i typically do is
get the metadata associated with the Uri (to get title / type of data / size)
get the content via an input stream to save it on the device as a file.
Take a look at the "Examine document metadata" and "get an inputstream" on this page: https://developer.android.com/guide/topics/providers/document-provider.html
i am implementing the functionality to save file in my app which is being sent by some exteral application.
i have provided support for single and mulitple files. Provided handling for all kind of files.
But i am not able to handle the following scenario.
I view a file from an email client -> View it in QuickOffice -> Click on send -> Choose my app->Then click on save in my app.
In that i get the path in following wrapped in the exception
java.io.FileNotFoundException: /file:/data/data/com.qo.android.sp.oem/files/temp/Error.log: open failed: ENOENT (No such file or directory)
I have seen this post which is quite useful for handling uri which has content scheme
Get filename and path from URI from mediastore
Below is my code
Uri uri = (Uri) iterator.next();
if ("content".equals(uri.getScheme())) {
filePath = getFilePathFromContentUri(uri, hostAcitvity.getContentResolver());
}
else {
filePath = uri.getPath();
}
fileName = uri.getLastPathSegment();
fileSize = hostAcitvity.getContentResolver().openInputStream(uri).available();
Code for getFilePathFromContentUri
private String getFilePathFromContentUri(Uri selectedVideoUri, ContentResolver contentResolver)
{
String filePath;
String[] filePathColumn = { MediaColumns.DATA };
Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
cursor.close();
return filePath;
}
Then i wrap the path in a FileInputStream which is throwing the above exception
Not able to resolve the file path properly. Is this the correct way of finding the path ?
cheers,
Saurav
I have seen this post which is quite useful for handling uri which has content scheme
That never worked reliably and will work even less reliably in the future.
Is this the correct way of finding the path ?
No, because there is no requirement that every Uri map to a path on a filesystem that you can access.
Use getInputStream() on ContentResolver to get an InputStream on the Uri, and consume the data that way.
I am desperately trying to send a captured video to a server. The problem is that the URI that is given by the built-in camera application is not the real file path. It looks like this - /content:/media/external/video/media/19.
How can I access the real path or the data directly from this kind of URIs?
After reading the android documentation I saw that it looks like a content provider's notation, but I still don't have a clue how to reach the data that I need. Please help!!!
thanks in advance
How can I access the real path or the data directly from this kind of URIs?
You don't. It might not exist as a file. Or, it might not exist as a file that you can read except via the ContentProvider.
Instead, use a ContentResolver to open an InputStream on that Uri, and use that InputStream to transfer the data to a server.
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();
}
}
}
see following post for
Get filename and path from URI from mediastore