i am facing an issue of taking picture from android camera and then showing it to next activity. process works fine but out of 10 pictures 1 picture is missed.
steps: activity a where i invoke camera and take picture then i pass to activity b of its URI to display in image view , repeating this cycle 10 times 1-2 times picture got missed and delay is observed of 2 sec when picture is taken and displayed into image view on next screen in the form of blank screen.
kindly check the code and guide me what mistake am i doing here?
Activity A
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==CAMERA_IMAGE_CAPTURE && resultCode==Activity.RESULT_OK){
String[] projection = {
MediaStore.Images.Thumbnails._ID, // The columns we want
MediaStore.Images.Thumbnails.IMAGE_ID,
MediaStore.Images.Thumbnails.KIND,
MediaStore.Images.Thumbnails.DATA};
String selection = MediaStore.Images.Thumbnails.KIND + "=" + // Select only mini's
MediaStore.Images.Thumbnails.MINI_KIND;
String sort = MediaStore.Images.Thumbnails._ID + " DESC";
//At the moment, this is a bit of a hack, as I'm returning ALL images, and just taking the latest one. There is a better way to narrow this down I think with a WHERE clause which is currently the selection variable
Cursor myCursor = this.getContentResolver().query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection, selection, null, sort);
long imageId = 0l;
long thumbnailImageId = 0l;
String thumbnailPath = "";
try{
myCursor.moveToFirst();
imageId = myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID));
thumbnailImageId = myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID));
thumbnailPath = myCursor.getString(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
}
finally{myCursor.close();}
//Create new Cursor to obtain the file Path for the large image
String[] largeFileProjection = {
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA
};
String largeFileSort = MediaStore.Images.ImageColumns._ID + " DESC";
myCursor = this.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, largeFileProjection, null, null, largeFileSort);
String largeImagePath = "";
try{
myCursor.moveToFirst();
//This will actually give you the file path location of the image.
largeImagePath = myCursor.getString(myCursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
}
finally{myCursor.close();}
// These are the two URI's you'll be interested in. They give you a handle to the actual images
Uri uriLargeImage = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, String.valueOf(imageId));
Uri uriThumbnailImage = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, String.valueOf(thumbnailImageId));
Intent next= new Intent(this,AddListing.class);
next.putExtra("imageUriThumb", uriThumbnailImage.toString());
next.putExtra("imageUriFull", uriLargeImage.toString());
startActivity(next);
}
}
Activity B
String uri = bundle.getString("imageUriThumb");
Uri myThumbUri = Uri.parse(uri);
try {
tempBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),myThumbUri);
imgThumbnail.setImageBitmap(tempBitmap);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
tempBitmap.compress(Bitmap.CompressFormat.PNG, 90, bao);
byte [] ba = bao.toByteArray();
imageBytesString = Base64.encodeToString(ba, 0);
} catch (Exception e) {
}
I ended up this problem with following points:
i have searched this issue on internet already actually these phones dont get images using intent.get("data") and that's why i used above mentioned technique. i have tried this using Samsung ace phone , Samsung Galaxy and same problem is there. i guess whole Samsung dont work perfectly and delayed response is there when you have requirement of taking pictures again and again :( rest of phones like htc works perfect.
Related
I'm using an image picker intent, to allow users to choose an image from their gallery, I get it's path, and pass it then to a 3rd library.
It's working fine for most of the cases, but if I picked up an image from Google Photos (an image that is stored online) I get a null path, though that I get valid URI for both of the working and not working images.
Here is my Intent call:
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RESULT_LOAD_IMAGE);
and here is onActivityResult:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri uri = data.getData();
Log.e(getClass().getName(),"file uri = " + uri);
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = getActivity().getContentResolver().query(uri, projection,
null, null, null);
if(cursor == null) return;
Log.e(getClass().getName(),"file cursor = " + cursor);
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
Log.e(getClass().getName(),"file columnIndex = " + columnIndex);
cursor.moveToFirst();
// The crash happens here
String photoPath = cursor.getString(columnIndex);
Log.e(getClass().getName(),"file photo path = " + photoPath);
cursor.close();
cropImage(photoPath);
}
And here are the logs for working and not-working image:
Working image:
file uri = content://com.google.android.apps.photos.contentprovider/0/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F105681/ORIGINAL/NONE/187859359
file cursor =
android.content.ContentResolver$CursorWrapperInner#8953964
file columnIndex = 0
file photo path = /storage/emulated/0/DCIM/Camera/IMG_20190523_184830.jpg
Not working image:
file uri =
content://com.google.android.apps.photos.contentprovider/0/1/mediakey%3A%2Flocal%253A4574915c-b4ac-40af-bc08-b1004670cab2/ORIGINAL/NONE/477302338
file cursor =
android.content.ContentResolver$CursorWrapperInner#59448a4
file columnIndex = 0
file photo path = null
If there isn't way to avoid that error, is there a way instead to hide photos that are stored online and only show local ones?
The technique in your question has (at least) three problems:
Not every MediaStore entry has a value for DATA, as you're seeing
Not every non-null DATA value represents a filesystem path that you can access, as the MediaStore can get to content that you can't
The DATA column is not available on Android Q and higher
In your case, the uCrop library accepts a Uri. Well-written Android libraries know how to handle a Uri, so you can just hand the Uri over to the library and it will take it from there.
Background
I want to change the photo of specific contacts in the address book.
The problem
I do some query of the contacts, as such:
final Cursor phonesCursor = context.getContentResolver()
.query(ContactsContract.Data.CONTENT_URI,null,null,null,null);
and then, inside the loop that goes over the cursor, I tried to update the first contact's photo :
if (phonesCursor != null) {
while (phonesCursor.moveToNext()) {
final int rawContactId = phonesCursor.getInt(phonesCursor
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID));
final String phoneNumber = phonesCursor.getString(phonesCursor
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String name = phonesCursor.getString(phonesCursor.getColumnIndex(Phone.DISPLAY_NAME));
phonesMap.put(rawContactId, phoneNumber);
Log.d("AppLog", "trying to set image for " + name);
int photoRow = phonesCursor.getInt(phonesCursor.getColumnIndex(Phone._ID));
phonesCursor.close();
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
ByteArrayOutputStream streamy = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0, streamy);
byte[] photo = streamy.toByteArray();
final ContentValues values = new ContentValues();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, photo);
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
final int update = context.getContentResolver().update(ContactsContract.Data.CONTENT_URI, values, ContactsContract.Data._ID + " = " + photoRow, null);
Log.d("AppLog", "update result:" + update);
break;
}
}
Thing is, the result is that "update" returns "1", so it is supposed to be successful, but when I get to the contacts, I don't see this photo.
What I tried
I tried to use a batch instead (using ArrayList and getContentResolver().applyBatch ), but it also didn't work .
I also tried to change the update call, to identify the item I wish to change in a different way (using RAW_CONTACT_ID instead). It also didn't work.
The questions
How come it occurs? What should I do to fix this?
What's the best way to update multiple contacts with new photos?
Is it possible to also get the photo of the contact using the query that I had, without an extra query ? I wish to do it in order to see for myself that the contact was different before.
OK, the correct field to use is "LOOKUP_KEY" :
int lookupKeyIdx = phonesCursor.getColumnIndex(Phone.LOOKUP_KEY);
final String lookupKey = phonesCursor.getString(lookupKeyIdx);
...
final int update = context.getContentResolver().update(ContactsContract.Data.CONTENT_URI, values, Phone.LOOKUP_KEY + " = " + lookupKey , null);
I am working on one sample application just to insert, update and delete the native android contact. I am able to successfully insert, update and delete the contact. But the problem in updating the contact photo. Below images are the observation where the same contact having two different issue.
After updating the contact, first image is still displaying the old image. But where as when i view the full details i am able to view the newly updated contact image as shown in the second image. Below is the code for updating the contact image.
mBitmap =getAllowedPhotoBitmap(photo);
mBitmap = ThumbnailUtils.extractThumbnail(mBitmap, THUMBNAIL_SIZE, THUMBNAIL_SIZE);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
if(mBitmap!=null){ // If an image is selected successfully
mBitmap.compress(Bitmap.CompressFormat.PNG ,100, stream);
op = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
op.withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND " + ContactsContract.Data.MIMETYPE + "=?", new String[{String.valueOf(native_contactid), ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE});
op.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, stream.toByteArray());
ops.add(op.build());
}
What is the problem and where i am going wrong?
Here is a open source app that does that: https://github.com/heinrisch/Contact-Picture-Sync/blob/master/src/heinrisch/contact/picture/sync/ContactHandler.java
this file will help you set Image for contact with Contact ID
https://github.com/heinrisch/Contact-Picture-Sync/blob/master/src/heinrisch/contact/picture/sync/ContactHandler.java
void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
// Check for the request code, we might be usign multiple
if (requestCode == PICK_CONTACT_REQUEST) {
Uri contactUri = data.getData();
String[] projection = {Phone.CONTACT_ID,Phone.NUMBER,ContactsContract.Data.RAW_CONTACT_ID,ContactsContract.Data._ID };
Cursor cursor = getContentResolver().query(contactUri, projection, null, null, null);
cursor.moveToFirst();
int columcontactID = cursor.getColumnIndex(Phone.CONTACT_ID);
String contactID = cursor.getString(columcontactID);
Bitmap item = (imgBg.getVisibleRectangleBitmap());
setContactPicture(AtWallpaperDetails.this, contactID, item);
}
}
}
The following is my code for obtaining a thumbnail of a given image.
As of now, the exception that I'm getting is 'Cursor out of bounds'
I think that may be because I am not appending the image URL anywhere. I'm a little confused as to where to do that.
So 2 questions:
1. Where do I use the image URL of which I want to obtain a thumbnail
2. The for loop which is supposed to print column names prints nothing except the first statement 'COLUMN NAMES'
//get the corresponding thumbnail
String lastImageTakenPath = MyActivity.this.savedInstanceStateVariable.getString("lastImageTaken");
System.out.println("previous image is "+ lastImageTakenPath);
ContentResolver cr = getContentResolver();
if(cr != null){
String[] projection = { MediaStore.Images.Media._ID };
Cursor cursor = managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,projection,null,null,null);
//Cursor cursor = cr.query(lastImageTakenURI, null, null, null, null);
//Activity.startManagingCursor(cursor);
if(cursor != null){
String[] columnNames = cursor.getColumnNames();
System.out.println("COLUMN NAMES");
for(int i=0;i<columnNames.length; i++){
System.out.println(columnNames[i]);
}
/* 1. get the id of the image
* 2. use this id in the call, getThumbnails on MediaStore.Images.Thumbnails to obtain the
thumbnail
3.set the imageview's src to this thumbnail */
int imageID = cursor.getInt( cursor.getColumnIndex(MediaStore.Images.Media._ID) );
Uri uri = Uri.withAppendedPath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Integer.toString(imageID) );
// Get original image ID
String url = uri.toString();
int originalImageId = Integer.parseInt(url.substring(url.lastIndexOf("/") + 1, url.length()));
// Get (or create upon demand) the micro thumbnail for the original image.
thumbnailLastImage = MediaStore.Images.Thumbnails.getThumbnail(cr, originalImageId, MediaStore.Images.Thumbnails.MICRO_KIND,null);
thumbnailImage.setImageBitmap(thumbnailLastImage);
}
else{
System.out.println("Cursor is NULL");
}
}
else{
Log.d(TAG,"ContentResolver is NULL");
}
I believe your test of if(cursor != null) is incorrect or at least insufficient. If the result of the query returns no thumbnails then you will still get a cursor where cursor.getCount() == 0 you may want to use that as your test.
Here is the code I am using to write a contact PHOTO. It works. If I am quick enough after writing it to the address book and go back and read the contact, I get my picture back.
But, after 10 seconds or so, in the debugger you can see an alarm fire and a thread startup and after that goes away if I go read the same contact back, the PHOTO was scaled down from roughly 400x400 down to 96x96.
It looks like there is a trigger firing on the backend to scale the PHOTO after it is written. Does anyone know a way to get around this or control it? Or is there a better way of writing a PHOTO that will not cause this scaling trigger?
I am doing this in Android 2.1 on Droid.
In trying to determine if I was writing the PHOTO correctly, I saw that there was a
ContactsContract.ContactsColumns interface with PHOTO_URI and PHOTO_THUMB_URI members, but I cannot find any way to get at it as the interface is protected and I cannot find any of the joins returning them. Does anyone how to use them?
Uri uri = ContactsContract.RawContacts.CONTENT_URI;
String[] projection = new String[] { BaseColumns._ID };
String selection = ContactsContract.RawContacts.CONTACT_ID + "=?";
String[] arguments = new String[] { "" + lContactID };
Cursor cursor = resolver.query(uri, projection, selection, arguments, null);
if (cursor != null && cursor.getCount() > 0)
{
while (cursor.moveToNext())
{
long rawContactId = cursor.getLong(0);
int row = -1;
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = new String[] { ContactsContract.Data._ID };
String selection = ContactsContract.Data.RAW_CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
String[] params = new String[] { "" + rawContactId };
Cursor cursor = resolver.query(uri, projection, selection, params, null);
if (cursor != null && cursor.getCount() > 0)
{
if (cursor.moveToFirst())
{
row = cursor.getInt(0);
}
cursor.close();
}
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, pic);
values.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
if (row >= 0)
{
resolver.update(ContactsContract.Data.CONTENT_URI, values, ContactsContract.Data._ID + " = " + photoRow, null);
}
else
{
resolver.insert(ContactsContract.Data.CONTENT_URI, values);
}
}
cursor.close();
cursor = null;
}
It turns out that it is the gmail.com sync adapter that is scaling the photo.
if I turn off
Settings->Accounts&Syncs->gmail.com->“Sync Contacts” the problem goes away.
Why does the sync adapter need to do this on a PHOTO it did not put there?
If that were not enough, it is not even very consistent with how it does it:
If the gmail.com contact does not previously have a picture on the server, when I write the PHOTO to the address book it is not scaled. The picture shows up on the server.
However, if the gmail.com contact previously had a picture on the server, when I write the contact to the address book the picture I just wrote is scaled to 96x96. Once again the picture shows up on the server.
So, either the sync adapter has a bug with processing the original picture, or has a bug with the update of a picture, because it does not always scale the photo. Either way, it should not be scaling the picture :(