Fixed contact picture edition quality & rotation

This commit is contained in:
Sylvain Berfini 2019-12-03 15:57:54 +01:00
parent 7caff1175f
commit ac12b1a7ea
4 changed files with 107 additions and 37 deletions

View file

@ -23,6 +23,7 @@ import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
@ -30,6 +31,8 @@ import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import org.linphone.LinphoneContext;
@ -41,10 +44,12 @@ class AndroidContact implements Serializable {
private String mAndroidRawId;
private boolean isAndroidRawIdLinphone;
private final transient ArrayList<ContentProviderOperation> mChangesToCommit;
private byte[] mTempPicture;
AndroidContact() {
mChangesToCommit = new ArrayList<>();
isAndroidRawIdLinphone = false;
mTempPicture = null;
}
String getAndroidId() {
@ -78,6 +83,12 @@ class AndroidContact implements Serializable {
String rawId = String.valueOf(ContentUris.parseId(results[0].uri));
if (mAndroidId == null) {
Log.i("[Contact] Contact created with RAW ID " + rawId);
mAndroidRawId = rawId;
if (mTempPicture != null) {
Log.i(
"[Contact] Contact has been created, raw is is available, time to set the photo");
setPhoto(mTempPicture);
}
final String[] projection =
new String[] {ContactsContract.RawContacts.CONTACT_ID};
@ -551,33 +562,44 @@ class AndroidContact implements Serializable {
return;
}
if (mAndroidId == null) {
Log.i("[Contact] Setting picture to new contact.");
addChangesToCommit(
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo)
.build());
if (mAndroidRawId == null) {
Log.w("[Contact] Can't set picture for not already created contact, will do it later");
mTempPicture = photo;
} else {
Log.i(
"[Contact] Setting picture to existing contact "
+ mAndroidId
+ " ("
+ mAndroidRawId
+ ")");
addChangesToCommit(
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, mAndroidRawId)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo)
.withValue(ContactsContract.Data.IS_PRIMARY, 1)
.withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1)
.build());
"[Contact] Setting picture to an already created raw contact [",
mAndroidRawId,
"]");
try {
long rawId = Long.parseLong(mAndroidRawId);
Uri rawContactPhotoUri =
Uri.withAppendedPath(
ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawId),
RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
if (rawContactPhotoUri != null) {
ContentResolver resolver =
LinphoneContext.instance().getApplicationContext().getContentResolver();
AssetFileDescriptor fd =
resolver.openAssetFileDescriptor(rawContactPhotoUri, "rw");
OutputStream os = fd.createOutputStream();
os.write(photo);
os.close();
fd.close();
} else {
Log.e(
"[Contact] Failed to get raw contact photo URI for raw contact id [",
rawId,
"], aborting");
}
} catch (NumberFormatException nfe) {
Log.e("[Contact] Couldn't parse raw id [", mAndroidId, "], aborting");
} catch (IOException ioe) {
Log.e("[Contact] Couldn't set picture, IO error: ", ioe);
} catch (Exception e) {
Log.e("[Contact] Couldn't set picture, unknown error: ", e);
}
}
}

View file

@ -28,6 +28,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
@ -398,15 +399,18 @@ public class ContactEditorFragment extends Fragment {
editContactPicture(null, bm);
} else if (data != null && data.getData() != null) {
Uri selectedImageUri = data.getData();
try {
Bitmap selectedImage =
MediaStore.Images.Media.getBitmap(
getActivity().getContentResolver(), selectedImageUri);
selectedImage =
Bitmap.createScaledBitmap(selectedImage, PHOTO_SIZE, PHOTO_SIZE, false);
editContactPicture(null, selectedImage);
} catch (IOException e) {
Log.e(e);
String filePath = FileUtils.getRealPathFromURI(getActivity(), selectedImageUri);
if (filePath != null) {
editContactPicture(filePath, null);
} else {
try {
Bitmap selectedImage =
MediaStore.Images.Media.getBitmap(
getActivity().getContentResolver(), selectedImageUri);
editContactPicture(null, selectedImage);
} catch (IOException e) {
Log.e("[Contact Editor] IO error: ", e);
}
}
} else if (mPickedPhotoForContactUri != null) {
String filePath = mPickedPhotoForContactUri.getPath();
@ -478,23 +482,52 @@ public class ContactEditorFragment extends Fragment {
}
private void editContactPicture(String filePath, Bitmap image) {
int orientation = ExifInterface.ORIENTATION_NORMAL;
if (image == null) {
Log.i(
"[Contact Editor] Bitmap is null, trying to decode image from file [",
filePath,
"]");
image = BitmapFactory.decodeFile(filePath);
try {
ExifInterface ei = new ExifInterface(filePath);
orientation =
ei.getAttributeInt(
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
Log.i("[Contact Editor] Exif rotation is ", orientation);
} catch (IOException e) {
Log.e("[Contact Editor] Failed to get Exif rotation, error is ", e);
}
} else {
}
if (image == null) {
Log.e(
"[Contact Editor] Couldn't get bitmap from either filePath [",
filePath,
"] nor image [",
image,
"]");
"] nor image");
return;
}
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
image = ImageUtils.rotateImage(image, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
image = ImageUtils.rotateImage(image, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
image = ImageUtils.rotateImage(image, 270);
break;
case ExifInterface.ORIENTATION_NORMAL:
// Nothing to do
break;
default:
Log.w("[Contact Editor] Unexpected orientation ", orientation);
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, stream);
mPhotoToAdd = stream.toByteArray();

View file

@ -640,6 +640,10 @@ public class LinphoneContact extends AndroidContact
public void save() {
saveChangesCommited();
if (getAndroidId() != null) {
setThumbnailUri(getContactThumbnailPictureUri());
setPhotoUri(getContactPictureUri());
}
syncValuesFromAndroidContact(LinphoneContext.instance().getApplicationContext());
createOrUpdateFriend();
}

View file

@ -22,6 +22,7 @@ package org.linphone.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
@ -85,4 +86,14 @@ public class ImageUtils {
/ ((float) context.getResources().getDisplayMetrics().densityDpi
/ DisplayMetrics.DENSITY_DEFAULT);
}
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
Bitmap rotatedBitmap =
Bitmap.createBitmap(
source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
source.recycle();
return rotatedBitmap;
}
}