Java tutorial
package org.linphone; /* ContactEditorFragment.java Copyright (C) 2012 Belledonne Communications, Grenoble, France This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.SyncFailedException; import java.util.ArrayList; import java.util.List; import org.linphone.compatibility.Compatibility; import org.linphone.core.LinphoneProxyConfig; import org.linphone.mediastream.Log; import org.linphone.mediastream.Version; import android.annotation.SuppressLint; import android.app.Activity; import android.app.Dialog; import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.Context; 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; import android.os.Parcelable; import android.provider.ContactsContract; import android.app.Fragment; import android.provider.MediaStore; import android.support.v4.content.CursorLoader; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; public class ContactEditorFragment extends Fragment { private View view; private ImageView cancel, deleteContact, ok; private ImageView addNumber, addSipAddress, contactPicture; private EditText firstName, lastName; private LayoutInflater inflater; private static final int ADD_PHOTO = 1337; private boolean isNewContact = true; private Contact contact; private int contactID; private List<NewOrUpdatedNumberOrAddress> numbersAndAddresses; private ArrayList<ContentProviderOperation> ops; private int firstSipAddressIndex = -1; private LinearLayout sipAddresses, numbers; private String newSipOrNumberToAdd; private ContactsManager contactsManager; private Uri imageToUploadUri; private String fileToUploadPath; private Bitmap imageToUpload; private Bitmap bitmapUnknown; byte[] photoToAdd; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { this.inflater = inflater; contact = null; if (getArguments() != null) { if (getArguments().getSerializable("Contact") != null) { contact = (Contact) getArguments().getSerializable("Contact"); isNewContact = false; contactID = Integer.parseInt(contact.getID()); contact.refresh(getActivity().getContentResolver()); if (getArguments().getString("NewSipAdress") != null) { newSipOrNumberToAdd = getArguments().getString("NewSipAdress"); } } else if (getArguments().getString("NewSipAdress") != null) { newSipOrNumberToAdd = getArguments().getString("NewSipAdress"); isNewContact = true; } } contactsManager = ContactsManager.getInstance(); view = inflater.inflate(R.layout.contact_edit, container, false); deleteContact = (ImageView) view.findViewById(R.id.delete_contact); cancel = (ImageView) view.findViewById(R.id.cancel); cancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { getFragmentManager().popBackStackImmediate(); } }); ok = (ImageView) view.findViewById(R.id.ok); ok.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (isNewContact) { boolean areAllFielsEmpty = true; for (NewOrUpdatedNumberOrAddress nounoa : numbersAndAddresses) { if (nounoa.newNumberOrAddress != null && !nounoa.newNumberOrAddress.equals("")) { areAllFielsEmpty = false; break; } } if (areAllFielsEmpty) { 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(); } for (NewOrUpdatedNumberOrAddress numberOrAddress : numbersAndAddresses) { numberOrAddress.save(); } try { getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); addLinphoneFriendIfNeeded(); removeLinphoneTagIfNeeded(); contactsManager.prepareContactsInBackground(); } catch (Exception e) { e.printStackTrace(); } getFragmentManager().popBackStackImmediate(); if (LinphoneActivity.instance().getResources().getBoolean(R.bool.isTablet)) ContactsListFragment.instance().invalidate(); } }); lastName = (EditText) view.findViewById(R.id.contactLastName); // Hack to display keyboard when touching focused edittext on Nexus One if (Version.sdkStrictlyBelow(Version.API11_HONEYCOMB_30)) { lastName.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { InputMethodManager imm = (InputMethodManager) LinphoneActivity.instance() .getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); } }); } lastName.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (lastName.getText().length() > 0 || firstName.getText().length() > 0) { ok.setEnabled(true); } else { ok.setEnabled(false); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); firstName = (EditText) view.findViewById(R.id.contactFirstName); firstName.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (firstName.getText().length() > 0 || lastName.getText().length() > 0) { ok.setEnabled(true); } else { ok.setEnabled(false); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); if (!isNewContact) { String fn = findContactFirstName(String.valueOf(contactID)); String ln = findContactLastName(String.valueOf(contactID)); if (fn != null || ln != null) { firstName.setText(fn); lastName.setText(ln); } else { lastName.setText(contact.getName()); firstName.setText(""); } deleteContact.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { final Dialog dialog = LinphoneActivity.instance() .displayDialog(getString(R.string.delete_text)); Button delete = (Button) dialog.findViewById(R.id.delete_button); Button cancel = (Button) dialog.findViewById(R.id.cancel); delete.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { deleteExistingContact(); ContactsManager.getInstance().removeContactFromLists(getActivity().getContentResolver(), contact); LinphoneActivity.instance().displayContacts(false); dialog.dismiss(); } }); cancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { dialog.dismiss(); } }); dialog.show(); } }); } else { deleteContact.setVisibility(View.INVISIBLE); } contactPicture = (ImageView) view.findViewById(R.id.contact_picture); if (contact != null && contact.getPhotoUri() != null) { InputStream input = Compatibility.getContactPictureInputStream(getActivity().getContentResolver(), contact.getID()); contactPicture.setImageBitmap(BitmapFactory.decodeStream(input)); } else { contactPicture.setImageResource(R.drawable.avatar); } contactPicture.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { pickImage(); } }); numbersAndAddresses = new ArrayList<NewOrUpdatedNumberOrAddress>(); sipAddresses = initSipAddressFields(contact); numbers = initNumbersFields(contact); addSipAddress = (ImageView) view.findViewById(R.id.add_address_field); addSipAddress.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { addEmptyRowToAllowNewNumberOrAddress(sipAddresses, true); } }); addNumber = (ImageView) view.findViewById(R.id.add_number_field); addNumber.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { addEmptyRowToAllowNewNumberOrAddress(numbers, false); } }); ops = new ArrayList<ContentProviderOperation>(); lastName.requestFocus(); return view; } @Override public void onResume() { super.onResume(); if (LinphoneActivity.isInstanciated()) { LinphoneActivity.instance().hideTabBar(false); } // Force hide keyboard getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); } private void pickImage() { imageToUploadUri = 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); captureIntent.putExtra("crop", "true"); captureIntent.putExtra("outputX", 256); captureIntent.putExtra("outputY", 256); captureIntent.putExtra("aspectX", 0); captureIntent.putExtra("aspectY", 0); captureIntent.putExtra("scale", true); captureIntent.putExtra("return-data", false); captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageToUploadUri); cameraIntents.add(captureIntent); final Intent galleryIntent = new Intent(); galleryIntent.setType("image/*"); galleryIntent.setAction(Intent.ACTION_GET_CONTENT); final Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.image_picker_title)); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[] {})); startActivityForResult(chooserIntent, ADD_PHOTO); } public String getRealPathFromURI(Uri contentUri) { String[] proj = { MediaStore.Images.Media.DATA }; CursorLoader loader = new CursorLoader(getActivity(), contentUri, proj, null, null, null); Cursor cursor = loader.loadInBackground(); if (cursor != null && cursor.moveToFirst()) { int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); String result = cursor.getString(column_index); cursor.close(); return result; } return null; } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { 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); } 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); } catch (IOException e) { e.printStackTrace(); } } else if (imageToUploadUri != null) { String filePath = imageToUploadUri.getPath(); showPopupMenuAskingImageSize(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); } } } else { super.onActivityResult(requestCode, resultCode, data); } } private void deleteExistingContact() { String select = ContactsContract.Data.CONTACT_ID + " = ?"; String[] args = new String[] { contact.getID() }; ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI) .withSelection(select, args).build()); try { getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); ContactsManager.getInstance().removeAllFriends(contact); } catch (Exception e) { Log.w(e.getMessage() + ":" + e.getStackTrace()); } } 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; } // 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.getID() + "' 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(); } } } } private LinearLayout initNumbersFields(final Contact contact) { LinearLayout controls = (LinearLayout) view.findViewById(R.id.controls_numbers); controls.removeAllViews(); if (contact != null) { for (String numberOrAddress : contact.getNumbersOrAddresses()) { boolean isSip = LinphoneUtils.isStrictSipAddress(numberOrAddress) || !LinphoneUtils.isNumberAddress(numberOrAddress); if (!isSip) { View view = displayNumberOrAddress(controls, numberOrAddress); if (view != null) controls.addView(view); } } } if (newSipOrNumberToAdd != null) { boolean isSip = LinphoneUtils.isStrictSipAddress(newSipOrNumberToAdd) || !LinphoneUtils.isNumberAddress(newSipOrNumberToAdd); if (!isSip) { View view = displayNumberOrAddress(controls, newSipOrNumberToAdd); if (view != null) controls.addView(view); } } if (controls.getChildCount() == 0) { addEmptyRowToAllowNewNumberOrAddress(controls, false); } return controls; } private LinearLayout initSipAddressFields(final Contact contact) { LinearLayout controls = (LinearLayout) view.findViewById(R.id.controls_sip_address); controls.removeAllViews(); if (contact != null) { for (String numberOrAddress : contact.getNumbersOrAddresses()) { boolean isSip = LinphoneUtils.isStrictSipAddress(numberOrAddress) || !LinphoneUtils.isNumberAddress(numberOrAddress); if (isSip) { View view = displayNumberOrAddress(controls, numberOrAddress); if (view != null) controls.addView(view); } } } if (newSipOrNumberToAdd != null) { boolean isSip = LinphoneUtils.isStrictSipAddress(newSipOrNumberToAdd) || !LinphoneUtils.isNumberAddress(newSipOrNumberToAdd); if (isSip) { View view = displayNumberOrAddress(controls, newSipOrNumberToAdd); if (view != null) controls.addView(view); } } if (controls.getChildCount() == 0) { addEmptyRowToAllowNewNumberOrAddress(controls, true); } return controls; } private View displayNumberOrAddress(final LinearLayout controls, String numberOrAddress) { return displayNumberOrAddress(controls, numberOrAddress, false); } @SuppressLint("InflateParams") private View displayNumberOrAddress(final LinearLayout controls, String numberOrAddress, boolean forceAddNumber) { boolean isSip = LinphoneUtils.isStrictSipAddress(numberOrAddress) || !LinphoneUtils.isNumberAddress(numberOrAddress); if (isSip) { if (firstSipAddressIndex == -1) { firstSipAddressIndex = controls.getChildCount(); } numberOrAddress = numberOrAddress.replace("sip:", ""); } if ((getResources().getBoolean(R.bool.hide_phone_numbers_in_editor) && !isSip) || (getResources().getBoolean(R.bool.hide_sip_addresses_in_editor) && isSip)) { if (forceAddNumber) isSip = !isSip; // If number can't be displayed because we hide a sort of number, change that category else return null; } NewOrUpdatedNumberOrAddress tempNounoa; if (forceAddNumber) { tempNounoa = new NewOrUpdatedNumberOrAddress(isSip); } else { if (isNewContact || newSipOrNumberToAdd != null) { tempNounoa = new NewOrUpdatedNumberOrAddress(isSip, numberOrAddress); } else { tempNounoa = new NewOrUpdatedNumberOrAddress(numberOrAddress, isSip); } } final NewOrUpdatedNumberOrAddress nounoa = tempNounoa; numbersAndAddresses.add(nounoa); final View view = inflater.inflate(R.layout.contact_edit_row, null); final EditText noa = (EditText) view.findViewById(R.id.numoraddr); noa.setInputType(isSip ? InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS : InputType.TYPE_CLASS_PHONE); noa.setText(numberOrAddress); noa.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { nounoa.setNewNumberOrAddress(noa.getText().toString()); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); if (forceAddNumber) { nounoa.setNewNumberOrAddress(noa.getText().toString()); } ImageView delete = (ImageView) view.findViewById(R.id.delete_field); delete.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { nounoa.delete(); numbersAndAddresses.remove(nounoa); view.setVisibility(View.GONE); } }); return view; } @SuppressLint("InflateParams") private void addEmptyRowToAllowNewNumberOrAddress(final LinearLayout controls, final boolean isSip) { final View view = inflater.inflate(R.layout.contact_edit_row, null); final NewOrUpdatedNumberOrAddress nounoa = new NewOrUpdatedNumberOrAddress(isSip); final EditText noa = (EditText) view.findViewById(R.id.numoraddr); numbersAndAddresses.add(nounoa); noa.setHint(isSip ? getString(R.string.sip_address) : getString(R.string.phone_number)); noa.setInputType(isSip ? InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS : InputType.TYPE_CLASS_PHONE); noa.requestFocus(); noa.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { nounoa.setNewNumberOrAddress(noa.getText().toString()); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); final ImageView delete = (ImageView) view.findViewById(R.id.delete_field); delete.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { nounoa.delete(); numbersAndAddresses.remove(nounoa); view.setVisibility(View.GONE); } }); controls.addView(view); } private String findContactFirstName(String contactID) { Cursor c = getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI, new String[] { ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME }, ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", new String[] { contactID, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE }, null); if (c != null) { String result = null; if (c.moveToFirst()) { result = c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)); } c.close(); return result; } return null; } private String findContactLastName(String contactID) { Cursor c = getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI, new String[] { ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME }, ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", new String[] { contactID, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE }, null); if (c != null) { String result = null; if (c.moveToFirst()) { result = c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME)); } c.close(); return result; } return null; } private void addLinphoneFriendIfNeeded() { for (NewOrUpdatedNumberOrAddress numberOrAddress : numbersAndAddresses) { if (numberOrAddress.newNumberOrAddress != null && numberOrAddress.isSipAddress) { if (isNewContact) { Contact c = contactsManager.findContactWithDisplayName(ContactsManager.getInstance() .getDisplayName(firstName.getText().toString(), lastName.getText().toString())); if (c != null && !contactsManager.isContactHasAddress(c, numberOrAddress.newNumberOrAddress)) { contactsManager.createNewFriend(c, numberOrAddress.newNumberOrAddress); } } else { if (!contactsManager.isContactHasAddress(contact, numberOrAddress.newNumberOrAddress)) { if (numberOrAddress.oldNumberOrAddress == null) { contactsManager.createNewFriend(contact, numberOrAddress.newNumberOrAddress); } else { if (contact.hasFriends()) contactsManager.updateFriend(numberOrAddress.oldNumberOrAddress, numberOrAddress.newNumberOrAddress); } } } } } } private void removeLinphoneTagIfNeeded() { if (!isNewContact) { boolean areAllSipFielsEmpty = true; for (NewOrUpdatedNumberOrAddress nounoa : numbersAndAddresses) { if (!nounoa.isSipAddress && (nounoa.oldNumberOrAddress != null && !nounoa.oldNumberOrAddress.equals("") || nounoa.newNumberOrAddress != null && !nounoa.newNumberOrAddress.equals(""))) { areAllSipFielsEmpty = false; break; } } if (areAllSipFielsEmpty && contactsManager.findRawLinphoneContactID(contact.getID()) != null) { contactsManager.removeLinphoneContactTag(contact); } } } class NewOrUpdatedNumberOrAddress { private String oldNumberOrAddress; private String newNumberOrAddress; private boolean isSipAddress; public NewOrUpdatedNumberOrAddress() { oldNumberOrAddress = null; newNumberOrAddress = null; isSipAddress = false; } public NewOrUpdatedNumberOrAddress(boolean isSip) { oldNumberOrAddress = null; newNumberOrAddress = null; isSipAddress = isSip; } public NewOrUpdatedNumberOrAddress(String old, boolean isSip) { oldNumberOrAddress = old; newNumberOrAddress = null; isSipAddress = isSip; } public NewOrUpdatedNumberOrAddress(boolean isSip, String newSip) { oldNumberOrAddress = null; newNumberOrAddress = newSip; isSipAddress = isSip; } public void setNewNumberOrAddress(String newN) { newNumberOrAddress = newN; } public void save() { if (newNumberOrAddress == null || newNumberOrAddress.equals(oldNumberOrAddress)) return; if (oldNumberOrAddress == null) { // New number to add addNewNumber(); } else { // Old number to update updateNumber(); } } public void delete() { if (contact != null) { if (isSipAddress) { if (contact.hasFriends()) { ContactsManager.getInstance().removeFriend(oldNumberOrAddress); } else { Compatibility.deleteSipAddressFromContact(ops, oldNumberOrAddress, String.valueOf(contactID)); } if (getResources().getBoolean(R.bool.use_linphone_tag)) { Compatibility.deleteLinphoneContactTag(ops, oldNumberOrAddress, contactsManager.findRawLinphoneContactID(String.valueOf(contactID))); } } else { String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' AND " + ContactsContract.CommonDataKinds.Phone.NUMBER + "=?"; String[] args = new String[] { String.valueOf(contactID), oldNumberOrAddress }; ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) .withSelection(select, args).build()); } } } private void addNewNumber() { if (newNumberOrAddress == null || newNumberOrAddress.length() == 0) { return; } if (isNewContact) { if (isSipAddress) { if (newNumberOrAddress.startsWith("sip:")) newNumberOrAddress = newNumberOrAddress.substring(4); if (!newNumberOrAddress.contains("@")) { //Use default proxy config domain if it exists LinphoneProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig(); if (lpc != null) { newNumberOrAddress = newNumberOrAddress + "@" + lpc.getDomain(); } else { newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain); } } Compatibility.addSipAddressToContact(getActivity(), ops, newNumberOrAddress); } else { ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, newNumberOrAddress) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM) .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, getString(R.string.addressbook_label)) .build()); } } else { String rawContactId = contactsManager.findRawContactID(getActivity().getContentResolver(), String.valueOf(contactID)); if (isSipAddress) { if (newNumberOrAddress.startsWith("sip:")) newNumberOrAddress = newNumberOrAddress.substring(4); if (!newNumberOrAddress.contains("@")) { //Use default proxy config domain if it exists LinphoneProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig(); if (lpc != null) { newNumberOrAddress = newNumberOrAddress + "@" + lpc.getDomain(); } else { newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain); } } Compatibility.addSipAddressToContact(getActivity(), ops, newNumberOrAddress, rawContactId); if (getResources().getBoolean(R.bool.use_linphone_tag)) { Compatibility.addLinphoneContactTag(getActivity(), ops, newNumberOrAddress, contactsManager.findRawLinphoneContactID(String.valueOf(contactID))); } } else { ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, newNumberOrAddress) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM) .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, getString(R.string.addressbook_label)) .build()); } } } private void updateNumber() { if (newNumberOrAddress == null || newNumberOrAddress.length() == 0) { return; } if (isSipAddress) { if (newNumberOrAddress.startsWith("sip:")) newNumberOrAddress = newNumberOrAddress.substring(4); if (!newNumberOrAddress.contains("@")) { //Use default proxy config domain if it exists LinphoneProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig(); if (lpc != null) { newNumberOrAddress = newNumberOrAddress + "@" + lpc.getDomain(); } else { newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain); } } Compatibility.updateSipAddressForContact(ops, oldNumberOrAddress, newNumberOrAddress, String.valueOf(contactID)); if (getResources().getBoolean(R.bool.use_linphone_tag)) { Compatibility.updateLinphoneContactTag(getActivity(), ops, newNumberOrAddress, oldNumberOrAddress, contactsManager.findRawLinphoneContactID(String.valueOf(contactID))); } } else { String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' AND " + ContactsContract.CommonDataKinds.Phone.NUMBER + "=?"; String[] args = new String[] { String.valueOf(contactID), oldNumberOrAddress }; ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) .withSelection(select, args) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, newNumberOrAddress).build()); } } } }