Android get image path after intent - android

I made an app. It has 2 options for uploading photo:
1) by taking a photo using camera
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 1);
2) by picking from gallery
Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 2);
My problem is getting file path after these intents in onActivityResult.
Is there any methods to get those paths for new File(path) , that also takes care of sdk level changes? For example till KitKat is 1 type of file system , after KitKat is other type.

My problem is getting file path after these intents in onActivityResult.
There will be no file path for the ACTION_IMAGE_CAPTURE approach, because you did not provide EXTRA_OUTPUT. If you do provide EXTRA_OUTPUT, then you already know what the file path is.
There is no file path for ACTION_PICK, insofar as there is no requirement that what the user picks be in a file that you have access to. For example, it could be an image on removable storage. Use a ContentResolver and methods like openInputStream() to get the content represented by the Uri that you are given.

If you can able to get path from camera then for Intent.ACTION_PICK you can directly get uri of image using data.getData() and then you can get file path using this method(as suggested in the link provided by Gennadii Saprykin
public String getRealPathFromURI(Uri uri) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx); }

Related

Photo intent, don't understand the path

When I launch a Photo Capture intent, the photo path that is gave to me in return is : content://media/external/images/media/40209 but when I look in my device, the photo path should have been something like [..]/pictures/1456164469539.jpg
Do you know how to get the second path from the first ?
note I use the method described there Android ACTION_IMAGE_CAPTURE Intent by yanokwa.
Thanks,
-------------------- EDIT
I launch my intent like so :
private void launchPhotoIntent() {
Uri photoUri = getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new ContentValues());
Log.i("renaud","photoUri : "+mPhotoUri.toString());
SharedPreferences sharedPreferences = getActivity().getSharedPreferences(AppConstants.SP,Context.MODE_PRIVATE);
sharedPreferences.edit().putString("test",photoUri.toString()).commit();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
getActivity().startActivityForResult(intent, ACTION_TAKE_PHOTO);
}
and In my Callback :
else if(requestCode == PostMessageWindowFragment.ACTION_TAKE_PHOTO && resultCode == Activity.RESULT_OK){
Uri uri = Uri.parse(sharedPreferences.getString("test",null)); // data.getData();
File file = new File(event.uri.getPath());
Log.i("PICTEST",""+file.length());
}
It logs "0"
When I launch a Photo Capture intent, the photo path that is gave to me in return is : content://media/external/images/media/40209
That is not a path. That is a Uri, pointing to content.
the photo path should have been something like [..]/pictures/1456164469539.jpg
Not necessarily.
First, there are thousands of Android device models and thousands of camera apps (both pre-installed and installed by users), some of which implement ACTION_IMAGE_CAPTURE. What one camera app does will not necessarily match what another camera app does.
Second, if you read the documentation for ACTION_IMAGE_CAPTURE, you will notice that there is no "photo path that is gave to me in return". If you supply EXTRA_OUTPUT, your photo should be in that location. If you do not, use getExtra("data") on the Intent passed to onActivityResult() to get a thumbnail bitmap. You appear to be assuming that the Intent will have a Uri, and few camera apps do that.
Do you know how to get the second path from the first ?
That is not possible in general, as a Uri does not have to point to a file, let alone a file that you can access. Use ContentResovler to work with Uri values, such as openInputStream() to read in the content pointed to by a Uri.
The path you get is the file URI. Try with converting it to path using this Convert file: Uri to File in Android

Image path from Android camera intent

I am trying to figure out the right way to get a file path from the camera after a picture is taken:
Launch the camera intent. Since I am telling the camera to write to internal storage give it the uri and read permission:
File file = new File(context.getFilesDir(), "picture.jpg");
Uri uri = FileProvider.getUriForFile(getApplicationContext(), "my.app.package.fileprovider", file);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(intent, ACTION_IMAGE_CAPTURE_REQUEST_CODE);
Listen for the camera intent result:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}
switch (requestCode) {
case ACTION_IMAGE_CAPTURE_REQUEST_CODE:
// How do I get the local path to the file here?
break;
}
}
What is the best way to get the file path on camera intent return. Sure I can save off the file path to a member variable before launching the intent, but that seems bad, seems I should get the path from the onActivityResult.
I have tried this (Get Image path from camera intent):
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(MediaStore.Images.Media.INTERNAL_CONTENT_URI,projection, null, null, null);
int column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToLast();
String imagePath = cursor.getString(column_index_data);
Only difference being that I am using INTERNAL_CONTENT_URI as I am trying to store the pic internally. If I do this I get an exception:
Error getting data column
java.lang.IllegalArgumentException: column '_data' does not exist
Am I going about this wrong. I want to take a pic and store that pic in internal storage.
EDIT:
One more thought. Should I be storing pics internally? I am right not because of the new android M permissions. I already have to ask the user for Camera permission, if I store pic to external storage, I have to ask the user for permission to write to to external. Lastly if I store the image externally, it is readable by all applications on the device that can read from external storage. This may be a privacy issue for my app.
What is the best way to get the file path on camera intent return
You specified the file path in EXTRA_OUTPUT. Either the camera put the photo there, or it didn't. If it did, then you already know the file path: new File(context.getFilesDir(), "picture.jpg"). That should be the case the vast majority of the time.
Some camera apps are buggy and will ignore EXTRA_OUTPUT. In those cases:
You can see if the camera app returned a Uri in the Intent passed to onActivityResult(), then use ContentResolver and openInputStream() to begin the process of copying the image to your desired location, or
You can see if the "data" extra exists, in which case that's a Bitmap thumbnail that you can save to your desired location.
In all of these cases, the file path is what you specified; it is merely a question of whether or not it takes additional work for you to get the image there.
Sure I can save off the file path to a member variable before launching the intent, but that seems bad
I have no idea why you would think that.
seems I should get the path from the onActivityResult
You are welcome to believe whatever you want. Camera app developers are hopefully reading the documentation for ACTION_IMAGE_CAPTURE. That documentation does not state that the camera app has to return anything if you provide EXTRA_OUTPUT. Hence, many camera apps will not return anything.
UPDATE based on edit:
Should I be storing pics internally?
Um, you already are.
if I store pic to external storage, I have to ask the user for permission to write to to external
That depends on where you are writing. getExternalFilesDir(), getExternalCacheDir(), and kin from Context do not require a permission on Android 4.4+. The methods you call on Environment for external storage locations (e.g., getExternalStoragePublicDirectory()) do require WRITE_EXTERNAL_STORAGE, which is a dangerous permission and would need to be requested at runtime.

Is there a ContentResolver to obtain a File instead of a FileDescriptor?

I am using an intent to invoke a file chooser that is external to my app. Some of the file chooser applications return an Uri of scheme "content".
I need to obtain the last modified date of the chosen object. How do I do that when the scheme is "content"? I didn't find an appropriate API.
There is some API that returns a FileDescriptor. But I don't get the last modified date from a FileDescriptor. Any help appreciate.
Best Regards
In general you can't do what you want - there is no API to get a File for an item described by a "content" URI because a content URI does not have to correspond with a file anyway.
In practice it is possible to get a File path for some content URIs:
as you describe, sometimes you can get lucky, and manipulate the content uri by changing the content scheme to a file scheme
If the content URI came from the Media store, then you can do a query to get the file path
public static String getPathnameFromMediaUri(Activity activity, Uri contentUri)
{
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = activity.managedQuery(contentUri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
There are a whole host of other questions asking pretty much the same thing that provide further ideas (or slightly different working of the same ideas)
Android file chooser
How to extract the file name from URI returned from Intent.ACTION_GET_CONTENT?
URI from Intent.ACTION_GET_CONTENT into File

How to retrieve the current app folder where my android app has access?

I am starting a cam intent in my app and want that the picture will be stored inside my app folder in a images folder. To achieve this I am starting the cam intent like this
public void startCamAction(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, this.getApplicationContext().getDir("images", MODE_PRIVATE));
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE), TAKE_PICTURE);
}
In the next Activity I want to do something with this picuture but I guess its not working because my app has no access to this folder. The folder where the picture has been stored is
content:://media/external/images/media/20
This is not the desired path, how do I have to configure it so that the picture will be stored inside my app folder?
Thanks
Actually content:://media/external/images/media/20 is a Uri not a real file path..
So If you want to get real path from this Uri then you have to do something like,
Uri uri = content:://media/external/images/media/20
String imageFile = getRealPathFromURI(uri);
and the method getRealPathFromURI() is
private String getRealPathFromURI(Uri contentURI) {
Cursor cursor = getContentResolver()
.query(contentURI, null, null, null, null);
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}
Update:
Also from your code line,
intent.putExtra(MediaStore.EXTRA_OUTPUT, this.getApplicationContext().getDir("images", MODE_PRIVATE));
Your captured images are stored in your application's internal storage. So you can access this directory within your application in any activity.
To retrieve a files from this directory you can use the simple file operation.
Like,
File directory = this.getApplicationContext().getDir("images", MODE_PRIVATE);
Use
Context.getExternalCacheDir()
Context.getExternalFilesDir(String type)
You will get the directory on the SD card where your app has access. It will look something like
/sdcard/Android/your.app.package.name/
And don't forget to add this to your manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
I doubt the camera can save to the directory of an app. Mainly because of rights issues.
Best is to store it to external store (as you have done, judging from the URI: content://media/external/images/media/20 )
You can always copy the file using this URI and save it in your app data directory, and then remove it from the external directory.
Other solution is to specify a own ContentProvider. In this ContentProvider you can save the file.
http://dharmendra4android.blogspot.be/2012/04/save-captured-image-to-applications.html

Getting Images From Gallery - Not All "Exist"?

I am simply trying to get the path of an image that the user selects and then convert it into a bitmap. The problem is, only some of the images in the gallery work when selected (by "work" I mean they are found to be a file that exists), while the others claim the file does not exist (even though the image is showing up in the gallery?). Even more strange is that this doesn't seem to be consistent, an image that was at one point considered to "exist" now claims to be nonexistent. My code is below:
-----The Intent-----
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, GALLERY_ACTIVITY);
-----onActivityForResult-----
Uri uri = intent.getData();
String [] proj={MediaStore.Images.Media.DATA};
Cursor cursor = managedQuery(uri,proj,null,null,null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
BitmapFactory.Options opts = new BitmapFactory.Options();<br/>
opts.inSampleSize = 2;<br/>
Bitmap b = BitmapFactory.decodeFile(cursor.getString(column_index),opts);
Any ideas on this will be greatly appreciated, thank you!
Matt.
Some images in gallery were loaded from external sources (such as Picasa), thus were not stored locally, causing local filepath reading failure. You can distinguish them by reading your uri value. I could not find a fix for this, perhaps this bug http://code.google.com/p/android/issues/detail?id=21234 can lure out a solution soon.

Categories

Resources