Missing EXIF info in images selected from gallery using EXTERNAL_CONTENT_URI - android

I'm trying to gather EXIF info (date of picture taken, geotagging, orientation) from images selected from an EXTERNAL_CONTENT_URI intent, but it seems that if the pictures come from the internet (e.g. Google Photos) the EXIF data is somehow truncated.
For example if I download a picture from a web browser from photos.google.com on my PC, its size is 4.377.104 bytes, and all the EXIF data are there.
While if I download the same exact image using the command:
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
its size is 4.363.578 bytes (13526 bytes less than the original) and all the EXIF data are lost
Any idea on how to download the full original image?
PS: if I select a picture from the gallery which was taken from the phone and it is still resident on the phone's storage, the EXIF data are present

I finally found out a solution. after getting the source image Uri in the onActivityResult method using
Uri selectedImage = data.getData();
I use the following function to get the necessary data from the picture
public static ImageInfo getImageInfo(Context context, Uri photoUri) {
Cursor cursor = context.getContentResolver().query(photoUri,
new String[] {
MediaStore.Images.ImageColumns.ORIENTATION,
MediaStore.Images.ImageColumns.LATITUDE,
MediaStore.Images.ImageColumns.LONGITUDE,
MediaStore.Images.ImageColumns.DATE_TAKEN } , null, null, null);
if (cursor.getCount() != 1) {
return null;
}
cursor.moveToFirst();
ImageInfo i = new ImageInfo();
i.Orientation = cursor.getInt(0);
i.Lat = cursor.getDouble(1);
i.Lon = cursor.getDouble(2);
i.DateTakenUTC = cursor.getLong(3)/1000;
cursor.close();
return i;
}

Related

How to pick those photo stored in cloud from Google Photos?

I know how to pick photo from gallery and it always work.
The code to pick photo from gallery:
Intent intent = new Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, REQ_GALLERY);
And code to handle result in onActivityResult():
Uri uri = data.getData();
Cursor cursor = getContext().getContentResolver().query(uri, new String[] {
MediaStore.Images.Media.DATA,
}, null, null, null);
if (cursor == null) return false;
if (cursor.moveToFirst()) {
String path = cursor.getString(0);
if (path != null) {
startPhotoEdit(new File(path), output, requestCode);
cursor.close();
return true;
}
}
cursor.close();
This time I pick them from Google Photos and the photo is still stored in cloud and not downloaded to local yet. After I pick one and it starts downloading like that:
photo_downloading
When the download task finished and return to my application, the _data column in cursor which always contains photo path is null.
Can someone help me, please.
I finally find that when photo from cloud is picked, its Uri is different. Like this:
content://com.google.android.apps.photos.contentprovider/1/1/mediakey%3A%2Flocal%253A131b7978-cc48-4206-8561-d18f99421551/ORIGINAL/NONE/2134743478
It contains mediakey instead of content in normal Uri.
So, this might be helpful:
getContentResolver().openInputStream(uri);

Photo in gallery is not timestamped when created by Intent with MediaStore.ACTION_IMAGE_CAPTURE action

I figured this question would have been answered elsewhere already but I am having no luck finding an answer.
I am taking a photo through my application by generating an image URI and starting an activity with MediaStore.ACTION_IMAGE_CAPTURE as an action like so;
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
myActivity.this.startActivityForResult(t, MY_PHOTO_REQUEST_CODE);
After I have received the result I get the file path and look at the exif data like so;
Cursor cursor = activity.getContentResolver().query(mCapturedImageURI, projection, null, null, null);
if(cursor.moveToFirst())
{
int column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
//Get file path from last stored photo
capturedImageFilePath = new String(cursor.getString(column_index_data));
}
cursor.close();
ExifInterface e = new ExifInterface(capturedImageFilePath);
String dateTime = e.getAttribute(ExifInterface.TAG_DATETIME);
The exifData contains the correct dateTime however if I look at photo details in the gallery the photo's date is '01/01/1970 01:00'. I cannot understand why this is.
NOTE: For clarity I have left out exception handling and other code which I don't believe to be relevant. I have also made sure that no exceptions are thrown without my knowledge.
How do you store the image in a gallery? Would the following be of help?
http://developer.android.com/training/camera/photobasics.html#TaskGallery

Monodroid setting imageview to image stored on sdcard

How do I take a photo and save it to a specific folder. I know it saves to the sdcard/DCIM/etc
But I don't want it there, I want it to be stored in a folder in /sdcard/Camera
I have made the directory with the following :
String destPath = Android.OS.Environment.ExternalStorageDirectory + "/Camera";
Then I launch the camera intent and try point the save file to the path I made.
Intent launchCamera = new Intent(Android.Provider.MediaStore.ActionImageCapture);
launchCamera.PutExtra(MediaStore.ExtraOutput, destPath);
This isn't working. Images still get saved to /sdcard/dcim/etc
Ideas?
From what I gathered when I developed an application using Monodroid is that the camera is very buggy and does not do what you want it to most of the time. This includes specifying the destination where images capture are to be saved.
To my knowledge these issues aren't specific to Monodroid and do occur with the java android sdk.
A work around to this issue that you may want to look at is capturing the image without specifying a destination, then in the OnActivityResult method retrieve the latest image saved to the gallery. Once you get the latest image you can then move it to your preferred destination.
Here is some example code from within OnActivityResult.
Retrieve the filename of the captured image
Android.Net.Uri targetUri = data.Data;
String origin = "";
String [] proj = { MediaStore.MediaColumns.Data.ToString (), BaseColumns.Id };
var qry = ManagedQuery (MediaStore.Images.Media.ExternalContentUri, proj, null, null, "date_added DESC");
qry.MoveToFirst ();
origin = qry.GetString (qry.GetColumnIndexOrThrow (MediaStore.MediaColumns.Data.ToString ()));
Move the image to your desired destination
System.IO.File.Move (origin, "yourdestinationfilenamehere");
I'd like to add to lanks's solution.
Let's say you use the following code to take a picture
var uri = ContentResolver.Insert(MediaStore.Images.Media.ExternalContentUri,
new ContentValues());
var intent = new Intent(MediaStore.ActionImageCapture);
intent.PutExtra(MediaStore.ExtraOutput, uri);
StartActivityForResult(intent, ACTIVITY_RESULT_PICTURE_TAKEN);
pictureUri = uri;
Where the ACTIVITY_RESULT_PICTURE_TAKEN is just a simple value you can use in the
OnActivityResult to check which activity was completed.
Your OnActivityResult could look something like this:
protected override void OnActivityResult(int requestCode,
Result resultCode, Intent data)
{
if (resultCode == Result.Ok && requestCode == ACTIVITY_RESULT_PICTURE_TAKEN)
{
string picturePath = GetRealPathFromURI(pictureUri);
//Do something with the file
}
}
The Uri you got earlier is something specific to android and needs to be translated.
It looks like "//content://media/external/media/11917" which is not a
valid path.
Which is exactly what the GetRealPathFromURI function does:
public string GetRealPathFromURI(Android.Net.Uri contentUri)
{
var mediaStoreImagesMediaData = "_data";
string[] projection = { mediaStoreImagesMediaData };
Android.Database.ICursor cursor = this.ManagedQuery(contentUri, projection,
null, null, null);
int columnIndex = cursor.GetColumnIndexOrThrow(mediaStoreImagesMediaData);
cursor.MoveToFirst();
return cursor.GetString(columnIndex);
}
Once you've got the real path, you can move it to wherever you want as lanks suggested.

Retrieve Picasa Image for Upload from Gallery

I am working on an activity and associated tasks that allow users to select an image to use as their profile picture from the Gallery. Once the selection is made the image is uploaded to a web server via its API. I have this working regular images from the gallery. However, if the image selected is from a Picasa Web Album nothing is returned.
I have done a lot of debugging and narrowed the problem down to this method.
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
//cursor is null for picasa images
if(cursor!=null)
{
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
else return null;
}
Picasa images return a null cursor. MediaStore.Images.Media.DATA is not null for them, however. It only returns an #id, so I am guessing that there is no actual bitmap data at the address. Are Picasa images stored locally on the device at all?
I also noticed from the documentation that MediaStore.Images.ImageColumns.PICASA_ID exists. This value exists for selected picasa images but not other gallery images. I was thinking I could use this value to get a URL for the image if it is not store locally but I can not find any information about it anywhere.
I have faced the exact same problem,
Finally the solution I found, was to launch an ACTION_GET_CONTENT intent instead of an ACTION_PICK, then make sure you provide a MediaStore.EXTRA_OUTPUT extra with an uri to a temporary file.
Here is the code to start the intent :
public class YourActivity extends Activity {
File mTempFile;
int REQUEST_CODE_CHOOSE_PICTURE = 1;
(...)
public showImagePicker() {
mTempFile = getFileStreamPath("yourTempFile");
mTempFile.getParentFile().mkdirs();
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile));
intent.putExtra("outputFormat",Bitmap.CompressFormat.PNG.name());
startActivityForResult(intent,REQUEST_CODE_CHOOSE_PICTURE);
}
(...)
}
You might need to mTempFile.createFile()
Then in onActivityResult, you will be able to get the image this way
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
case REQUEST_CODE_CHOOSE_PICTURE:
Uri imageUri = data.getData();
if (imageUri == null || imageUri.toString().length() == 0) {
imageUri = Uri.fromFile(mTempFile);
file = mTempFile;
}
if (file == null) {
//use your current method here, for compatibility as some other picture chooser might not handle extra_output
}
}
Hope this helps
Then you should delete your temporary file on finish (it is in internal storage as is, but you can use external storage, I guess it would be better).
Why are you using the managedQuery() method? That method is deprecated.
If you want to convert a Uri to a Bitmap object try this code:
public Bitmap getBitmap(Uri uri) {
Bitmap orgImage = null;
try {
orgImage = BitmapFactory.decodeStream(getApplicationContext().getContentResolver().openInputStream(uri));
} catch (FileNotFoundException e) {
// do something if you want
}
return orgImage;
}

Getting full-sized image from the camera does not work on Galaxy S

I am having a problem capturing an image from the built-in camera app on the Samsung Galaxy S.
I have a button on my app that when pressed launches the camera:
ContentValues values = new ContentValues();
values.put(Images.Media.MIME_TYPE, "image/jpeg");
mPicUri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mPicUri.getPath());
startActivityForResult(intent, REQ_CODE_TAKE_PIC);
From what I read on the interwebz, I can get the full-sized just-taken picture using the URI I passed to the intent. And so I have this on my onActivityResult:
Uri selectedImage = mPicUri;
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
And then using the variable filePath, I set the image in an ImageView. I am getting no image, and when I stepped through the code, I found out that BitmapFactory.decodeFile() is returning null.
Bitmap chosenPic = BitmapFactory.decodeFile(filePath);
So I tried a little more debugging. I found out that mPicUri returns a seemingly valid URI, such as: content://media/external/images/media/90. After the picture is taken and the user chooses to save the picture, the cursor resolves to the following filePath: /sdcard/DCIM/Camera/1285601413961.jpg. No bitmap is decoded though, BUT when I looked through the gallery, the picture I just took is there. So I tried to take a look at the URI of that picture, and this is what I got:
URI is: content://media/external/images/media/91
File path is: /sdcard/DCIM/Camera/2010-09-27 23.30.30.jpg
And so, it looks like the value I got from mPicUri is not the final URI that will be used.
Am I missing a step here? All I really want to do is retrieve the file of the just-taken picture.
Thanks in advance,
Zarah.
Did you try to specify File in both cases before taking picture and the same after?
public static File getTempFile() {
//it will return /sdcard/image.jpg
final File path = new File(Environment.getExternalStorageDirectory(), "MyApp");
if (!path.exists()) {
path.mkdir();
}
return new File(path, "image.jpg");
}
I'm using this function to get and set file path.

Categories

Resources