Image path from Android camera intent - android

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.

Related

is the Uri returned by Intent.ACTION_GET_CONTENT always somewhere on disk, or can it be anywhere?

Currently I have the following code that allows a user to choose an image.
int requestCode = 1337;
Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT);
chooserIntent.setType("image/*");
chooserIntent = Intent.createChooser(chooserIntent, "Please choose a picture");
chooserIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(chooserIntent, requestCode);
My question is:
does Android guarantee that the returned Uri is always pointing to a location on disk, or is it possible that it might be pointing to somewhere on the internet too?
P.S. although I am not sure about this, the Uri returned by this piece of code seems to always start with content:// - I am not sure whether or not this holds for all possible return values, I thought I would just add this here to help out any possible question answerers.
does Android guarantee that the returned Uri is always pointing to a
location on disk, or is it possible that it might be pointing to
somewhere on the internet too?
It is possible to have Uri other than local disk i.e. it can be remotely as well. You will get URL from remote then convert it to Uri and use it.
From official docs:
An ACTION_GET_CONTENT could allow the user to create the data as it
runs (for example taking a picture or recording a sound), let them
browse over the web and download the desired data, etc.
Convert Url to a Uri (Reference):
Uri uri = Uri.parse( "http://www.facebook.com" );

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

Android get image path after intent

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

Android - take picture - pass uri to camera app

I am trying to follow this tutorial to invoke the camera app and ask it to save a picture at the uri passed in the intent.
File image = File.createTempFile("testImage", ".jpg",
getExternalFilesDir(Environment.DIRECTORY_PICTURES));
Uri uri = Uri.fromFile(image);
Intent i = new Intent();
i.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, uri);
if (i.resolveActivity(getPackageManager()) != null) {
startActivityForResult(i, 1);
}
The path of the image is :
/storage/emulated/0/Android/data/com.android.test1.app/files/Pictures/testImage-516714791.jpg
I want to ask that how did the camera app have permission to write to this path ? I am testing on Android 4.4, so the path ExternalFilesDir is not publicly writable.
The reference says:
There is no security enforced with these files. For example, any application holding WRITE_EXTERNAL_STORAGE can write to these files.
Starting in KITKAT, no permissions are required to read or write to the returned path; it's always accessible to the calling app. This only applies to paths generated for package name of the calling application. To access paths belonging to other packages, WRITE_EXTERNAL_STORAGE and/or READ_EXTERNAL_STORAGE are required.
So, system Camera app, or any other app which is granted WRITE_EXTERNAL_STORAGE permission can write to /storage/emulated/0/Android/data/com.android.test1.app/files/Pictures/.

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

Categories

Resources