Contact editor allows name and photo changes

This commit is contained in:
Sylvain Berfini 2016-03-18 17:02:03 +01:00 committed by Jehan Monnier
parent 2a4a003780
commit 8eadbbb52d
3 changed files with 142 additions and 160 deletions

View file

@ -36,12 +36,6 @@ import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
@ -69,7 +63,9 @@ public class ContactEditorFragment extends Fragment {
private LinearLayout phoneNumbersSection, sipAddressesSection;
private EditText firstName, lastName;
private LayoutInflater inflater;
private static final int ADD_PHOTO = 1337;
private static final int PHOTO_SIZE = 128;
private boolean isNewContact = true;
private LinphoneContact contact;
@ -77,9 +73,7 @@ public class ContactEditorFragment extends Fragment {
private int firstSipAddressIndex = -1;
private LinearLayout sipAddresses, numbers;
private String newSipOrNumberToAdd;
private Uri imageToUploadUri;
private String fileToUploadPath;
private Bitmap imageToUpload;
private Uri pickedPhotoForContactUri;
private byte[] photoToAdd;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -140,27 +134,27 @@ public class ContactEditorFragment extends Fragment {
getFragmentManager().popBackStackImmediate();
return;
}
//contactsManager.createNewContact(ops, firstName.getText().toString(), lastName.getText().toString());
setContactPhoto();
} else {
//contactsManager.updateExistingContact(ops, contact, firstName.getText().toString(), lastName.getText().toString());
setContactPhoto();
}
if (photoToAdd != null) {
contact.setPhoto(photoToAdd);
}
contact.setFirstNameAndLastName(firstName.getText().toString(), lastName.getText().toString());
for (NewOrUpdatedNumberOrAddress numberOrAddress : numbersAndAddresses) {
/*for (NewOrUpdatedNumberOrAddress numberOrAddress : numbersAndAddresses) {
numberOrAddress.save();
}
}*/
contact.save();
/*try {
getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
addLinphoneFriendIfNeeded();
removeLinphoneTagIfNeeded();
contactsManager.prepareContactsInBackground();
} catch (Exception e) {
e.printStackTrace();
}*/
if(!isNewContact) {
if (!isNewContact) {
if (LinphoneActivity.instance().getResources().getBoolean(R.bool.isTablet)) {
if(ContactsListFragment.isInstanciated()) {
ContactsListFragment.instance().invalidate();
@ -231,6 +225,7 @@ public class ContactEditorFragment extends Fragment {
lastName.setText(contact.getFullName());
firstName.setText("");
}
deleteContact.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@ -321,19 +316,19 @@ public class ContactEditorFragment extends Fragment {
}
private void pickImage() {
imageToUploadUri = null;
pickedPhotoForContactUri = null;
final List<Intent> cameraIntents = new ArrayList<Intent>();
final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(Environment.getExternalStorageDirectory(), getString(R.string.temp_photo_name));
imageToUploadUri = Uri.fromFile(file);
pickedPhotoForContactUri = Uri.fromFile(file);
captureIntent.putExtra("crop", "true");
captureIntent.putExtra("outputX",256);
captureIntent.putExtra("outputY", 256);
captureIntent.putExtra("outputX", PHOTO_SIZE);
captureIntent.putExtra("outputY", PHOTO_SIZE);
captureIntent.putExtra("aspectX", 0);
captureIntent.putExtra("aspectY", 0);
captureIntent.putExtra("scale", true);
captureIntent.putExtra("return-data", false);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageToUploadUri);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, pickedPhotoForContactUri);
cameraIntents.add(captureIntent);
final Intent galleryIntent = new Intent();
@ -364,26 +359,26 @@ public class ContactEditorFragment extends Fragment {
if (requestCode == ADD_PHOTO && resultCode == Activity.RESULT_OK) {
if (data != null && data.getExtras() != null && data.getExtras().get("data") != null) {
Bitmap bm = (Bitmap) data.getExtras().get("data");
showPopupMenuAskingImageSize(null, bm);
editContactPicture(null, bm);
}
else if (data != null && data.getData() != null) {
Uri selectedImageUri = data.getData();
try {
Bitmap selectedImage = MediaStore.Images.Media.getBitmap(LinphoneManager.getInstance().getContext().getContentResolver(), selectedImageUri);
selectedImage = Bitmap.createScaledBitmap(selectedImage, 256, 256, false);
showPopupMenuAskingImageSize(null, selectedImage);
selectedImage = Bitmap.createScaledBitmap(selectedImage, PHOTO_SIZE, PHOTO_SIZE, false);
editContactPicture(null, selectedImage);
} catch (IOException e) { e.printStackTrace(); }
}
else if (imageToUploadUri != null) {
String filePath = imageToUploadUri.getPath();
showPopupMenuAskingImageSize(filePath, null);
else if (pickedPhotoForContactUri != null) {
String filePath = pickedPhotoForContactUri.getPath();
editContactPicture(filePath, null);
}
else {
File file = new File(Environment.getExternalStorageDirectory(), getString(R.string.temp_photo_name));
if (file.exists()) {
imageToUploadUri = Uri.fromFile(file);
String filePath = imageToUploadUri.getPath();
showPopupMenuAskingImageSize(filePath, null);
pickedPhotoForContactUri = Uri.fromFile(file);
String filePath = pickedPhotoForContactUri.getPath();
editContactPicture(filePath, null);
}
}
} else {
@ -391,121 +386,15 @@ public class ContactEditorFragment extends Fragment {
}
}
private void showPopupMenuAskingImageSize(final String filePath, final Bitmap image) {
fileToUploadPath = filePath;
imageToUpload = image;
editContactPicture(fileToUploadPath,imageToUpload);
}
private void editContactPicture(final String filePath, final Bitmap image) {
int SIZE_SMALL = 256;
int COMPRESSOR_QUALITY = 100;
Bitmap bitmapUnknown = BitmapFactory.decodeResource(getResources(), R.drawable.avatar);
Bitmap bm = null;
if(filePath != null){
int pixelsMax = SIZE_SMALL;
//Resize image
bm = BitmapFactory.decodeFile(filePath);
if (bm != null) {
if (bm.getWidth() > bm.getHeight() && bm.getWidth() > pixelsMax) {
bm = Bitmap.createScaledBitmap(bm, 256, 256, false);
}
}
} else if (image != null) {
bm = image;
private void editContactPicture(String filePath, Bitmap image) {
if (image == null) {
image = BitmapFactory.decodeFile(filePath);
}
// Rotate the bitmap if possible/needed, using EXIF data
try {
if (imageToUploadUri != null && filePath != null) {
ExifInterface exif = new ExifInterface(filePath);
int pictureOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
Matrix matrix = new Matrix();
if (pictureOrientation == 6) {
matrix.postRotate(90);
} else if (pictureOrientation == 3) {
matrix.postRotate(180);
} else if (pictureOrientation == 8) {
matrix.postRotate(270);
}
bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
}
} catch (Exception e) {
e.printStackTrace();
}
Bitmap bitmapRounded;
if(bm != null)
{
bitmapRounded = Bitmap.createScaledBitmap(bm,bitmapUnknown.getWidth(), bitmapUnknown.getWidth(), false);
Canvas canvas = new Canvas(bitmapRounded);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(bitmapRounded, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
canvas.drawCircle(bitmapRounded.getWidth() / 2+0.7f, bitmapRounded.getHeight() / 2+0.7f,bitmapRounded.getWidth() / 2+0.1f, paint);
contactPicture.setImageBitmap(bitmapRounded);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG,COMPRESSOR_QUALITY, outStream);
photoToAdd = outStream.toByteArray();
}
}
private void setContactPhoto() {
/*ContentResolver cr = getActivity().getContentResolver();
Uri updateUri = ContactsContract.Data.CONTENT_URI;
if(photoToAdd != null){
//New contact
if(isNewContact){
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, contactID)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photoToAdd)
.build()
);
} else { //update contact picture
String w = ContactsContract.Data.CONTACT_ID + "='"
+ contact.getAndroidId() + "' AND "
+ ContactsContract.Data.MIMETYPE + " = '"
+ ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
Cursor queryCursor = cr.query(updateUri,new String[] { ContactsContract.Data._ID}, w, null, null);
if (queryCursor == null) {
try {
throw new SyncFailedException("EE");
} catch (SyncFailedException e) {
e.printStackTrace();
}
} else {
if(contact.getPhoto() == null) {
String rawContactId = ContactsManager.getInstance().findRawContactID(cr,String.valueOf(contactID));
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photoToAdd)
.build()
);
}
if (queryCursor.moveToFirst()) { // otherwise no photo
int colIdx = queryCursor.getColumnIndex(ContactsContract.Data._ID);
long id = queryCursor.getLong(colIdx);
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(ContactsContract.Data._ID + "= ?",new String[] { String.valueOf(id) })
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photoToAdd)
.build());
}
queryCursor.close();
}
}
}*/
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG , 75, stream);
photoToAdd = stream.toByteArray();
contactPicture.setImageBitmap(image);
}
private LinearLayout initNumbersFields(final LinphoneContact contact) {

View file

@ -120,6 +120,10 @@ public class ContactsManager extends ContentObserver {
public void enableContactsAccess() {
hasContactAccess = true;
}
public boolean hasContactsAccess() {
return hasContactAccess;
}
public void setLinphoneContactsPrefered(boolean isPrefered) {
preferLinphoneContacts = isPrefered;

View file

@ -44,27 +44,44 @@ public class LinphoneContact implements Serializable {
private String fullName, firstName, lastName, androidId;
private transient Uri photoUri, thumbnailUri;
private List<LinphoneNumberOrAddress> addresses;
private transient ArrayList<ContentProviderOperation> changesToCommit;
public LinphoneContact() {
addresses = new ArrayList<LinphoneNumberOrAddress>();
androidId = null;
thumbnailUri = null;
photoUri = null;
changesToCommit = new ArrayList<ContentProviderOperation>();
}
public void setFullName(String name) {
if (name == null) return;
fullName = name;
if (friend != null) {
friend.setName(name);
}
}
public String getFullName() {
return fullName;
}
public void setFirstNameAndLastName(String fn, String ln) {
if (fn.length() == 0 && ln.length() == 0) return;
if (isAndroidContact() && (!firstName.equals(fn) || !lastName.equals(ln))) {
String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'";
String[] args = new String[]{ getAndroidId() };
changesToCommit.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(select, args)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, fn)
.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, ln)
.build()
);
}
firstName = fn;
lastName = ln;
fullName = firstName + " " + lastName;
}
public String getFirstName() {
return firstName;
}
@ -92,6 +109,28 @@ public class LinphoneContact implements Serializable {
public Uri getThumbnailUri() {
return thumbnailUri;
}
public void setPhoto(byte[] photo) {
if (isAndroidContact() && photo != null) {
if (!hasPhoto()) {
String rawContactId = findRawContactID(getAndroidId());
if (rawContactId != null) {
changesToCommit.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withSelection(ContactsContract.Data.RAW_CONTACT_ID + "= ?", new String[] { rawContactId })
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo)
.build());
}
} else {
String id = findDataId(getAndroidId());
changesToCommit.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(ContactsContract.Data._ID + "= ?", new String[] { id })
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo)
.build());
}
}
}
public void addNumberOrAddress(LinphoneNumberOrAddress noa) {
if (noa == null) return;
@ -130,6 +169,25 @@ public class LinphoneContact implements Serializable {
public String getAndroidId() {
return androidId;
}
public void save() {
if (ContactsManager.getInstance().hasContactsAccess()) {
if (isAndroidContact()) {
try {
ContactsManager.getInstance().getContentResolver().applyBatch(ContactsContract.AUTHORITY, changesToCommit);
} catch (Exception e) {
Log.e(e);
} finally {
changesToCommit = new ArrayList<ContentProviderOperation>();
}
}
} else {
if (friend == null) {
friend = LinphoneCoreFactory.instance().createLinphoneFriend();
}
friend.setName(fullName);
}
}
public void delete() {
if (isAndroidContact()) {
@ -170,11 +228,11 @@ public class LinphoneContact implements Serializable {
photoUri = null;
} else {
String id = getAndroidId();
setFullName(getName(id));
setThumbnailUri(getContactPictureUri(id));
setPhotoUri(getContactPhotoUri(id));
fullName = getName(id);
lastName = getContactLastName(id);
firstName = getContactFirstName(id);
setThumbnailUri(getContactPictureUri(id));
setPhotoUri(getContactPhotoUri(id));
for (LinphoneNumberOrAddress noa : getAddressesAndNumbersForAndroidContact(id)) {
addresses.add(noa);
}
@ -243,17 +301,48 @@ public class LinphoneContact implements Serializable {
private String getName(String id) {
ContentResolver resolver = ContactsManager.getInstance().getContentResolver();
Cursor cursor = resolver.query(getContactUri(id), null, null, null, null);
Cursor c = resolver.query(getContactUri(id), null, null, null, null);
String name = null;
if (cursor != null) {
if (cursor.moveToFirst()) {
name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (c != null) {
if (c.moveToFirst()) {
name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
}
cursor.close();
c.close();
}
return name;
}
private String findRawContactID(String id) {
ContentResolver resolver = ContactsManager.getInstance().getContentResolver();
String result = null;
String[] projection = { ContactsContract.Data.RAW_CONTACT_ID };
String selection = ContactsContract.RawContacts.CONTACT_ID + "=?";
Cursor c = resolver.query(ContactsContract.Data.CONTENT_URI, projection, selection, new String[]{ id }, null);
if (c != null) {
if (c.moveToFirst()) {
result = c.getString(c.getColumnIndex(ContactsContract.Data.RAW_CONTACT_ID));
}
c.close();
}
return result;
}
private String findDataId(String id) {
ContentResolver resolver = ContactsManager.getInstance().getContentResolver();
String result = null;
String[] projection = { ContactsContract.Data._ID };
String selection = ContactsContract.Data.CONTACT_ID + "='" + id + "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
Cursor c = resolver.query(ContactsContract.Data.CONTENT_URI, projection, selection, null, null);
if (c != null) {
if (c.moveToFirst()) {
result = String.valueOf(c.getLong(c.getColumnIndex(ContactsContract.Data._ID)));
}
c.close();
}
return result;
}
private List<LinphoneNumberOrAddress> getAddressesAndNumbersForAndroidContact(String id) {
List<LinphoneNumberOrAddress> result = new ArrayList<LinphoneNumberOrAddress>();
ContentResolver resolver = ContactsManager.getInstance().getContentResolver();