diff --git a/src/org/linphone/ContactEditorFragment.java b/src/org/linphone/ContactEditorFragment.java index f036bf0af..1dc0e45d1 100644 --- a/src/org/linphone/ContactEditorFragment.java +++ b/src/org/linphone/ContactEditorFragment.java @@ -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 cameraIntents = new ArrayList(); 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) { diff --git a/src/org/linphone/ContactsManager.java b/src/org/linphone/ContactsManager.java index 23102556a..c6a7415b4 100644 --- a/src/org/linphone/ContactsManager.java +++ b/src/org/linphone/ContactsManager.java @@ -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; diff --git a/src/org/linphone/LinphoneContact.java b/src/org/linphone/LinphoneContact.java index 1c621208b..a225381fa 100644 --- a/src/org/linphone/LinphoneContact.java +++ b/src/org/linphone/LinphoneContact.java @@ -44,27 +44,44 @@ public class LinphoneContact implements Serializable { private String fullName, firstName, lastName, androidId; private transient Uri photoUri, thumbnailUri; private List addresses; + private transient ArrayList changesToCommit; public LinphoneContact() { addresses = new ArrayList(); androidId = null; thumbnailUri = null; photoUri = null; + changesToCommit = new ArrayList(); } 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(); + } + } + } 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 getAddressesAndNumbersForAndroidContact(String id) { List result = new ArrayList(); ContentResolver resolver = ContactsManager.getInstance().getContentResolver();