diff --git a/src/org/linphone/ContactsManager.java b/src/org/linphone/ContactsManager.java index 8033dc8df..6e5ecbbdc 100644 --- a/src/org/linphone/ContactsManager.java +++ b/src/org/linphone/ContactsManager.java @@ -39,7 +39,7 @@ import java.util.List; public class ContactsManager { private static ContactsManager instance; private List contactList, sipContactList; - private Cursor contactCursor, sipContactCursor, friendContactCursor; + private Cursor contactCursor, sipContactCursor; private Account mAccount; private boolean preferLinphoneContacts = false, isContactPresenceDisabled = true; private ContentResolver contentResolver; @@ -65,10 +65,7 @@ public class ContactsManager { } public Cursor getSIPContactsCursor() { - if (sipContactCursor.getCount() > 0) - return sipContactCursor; - else - return friendContactCursor; + return sipContactCursor; } public void setLinphoneContactsPrefered(boolean isPrefered) { @@ -103,6 +100,7 @@ public class ContactsManager { return displayName; } + //Contacts public void createNewContact(ArrayList ops, String firstName, String lastName){ int contactID = 0; @@ -147,17 +145,20 @@ public class ContactsManager { } LinphoneFriend friend = LinphoneCoreFactory.instance().createLinphoneFriend(sipUri); - friend.edit(); - friend.setRefKey(contact.getID()); - friend.done(); - try { - LinphoneManager.getLc().addFriend(friend); - return true; - } catch (LinphoneCoreException e) { - e.printStackTrace(); + if(friend != null) { + friend.edit(); + friend.setRefKey(contact.getID()); + friend.done(); + try { + LinphoneManager.getLc().addFriend(friend); + return true; + } catch (LinphoneCoreException e) { + e.printStackTrace(); + return false; + } + } else { return false; } - } public void updateFriend(String oldSipUri, String newSipUri) { @@ -239,13 +240,42 @@ public class ContactsManager { } //End linphone Friend + public boolean removeContactTagIsNeeded(Contact contact){ + contact.refresh(contentResolver); + boolean onlyNumbers = true; + for(String address: contact.getNumbersOrAddresses()){ + if(LinphoneUtils.isSipAddress(address)){ + onlyNumbers = false; + } + } + + return onlyNumbers; + } + + public void removeLinphoneContactTag(Contact contact){ + ArrayList ops = new ArrayList(); + String select = ContactsContract.RawContacts._ID + " = ?"; + String[] args = new String[] { findRawLinphoneContactID(contact.getID()) }; + + + ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI) + .withSelection(select, args) + .build() + ); + + try { + contentResolver.applyBatch(ContactsContract.AUTHORITY, ops); + } catch (Exception e) { + Log.w(e.getMessage() + ":" + e.getStackTrace()); + } + } + public Contact findContactWithAddress(LinphoneAddress address){ for(Contact contact : contactList){ if(contact.getNumbersOrAddresses().contains(address.asStringUriOnly()) || contact.getNumbersOrAddresses().contains(address.getUserName())){ return contact; } } - return null; } @@ -270,7 +300,7 @@ public class ContactsManager { public boolean isContactHasAddress(Contact contact, String address){ if(contact != null) { contact.refresh(contentResolver); - if (contact.getNumbersOrAddresses().contains("sip:" + address)) { + if (contact.getNumbersOrAddresses().contains("sip:" + address)) { return true; } else { return false; @@ -279,6 +309,41 @@ public class ContactsManager { return false; } + public String findRawContactID(ContentResolver cr, String contactID) { + Cursor c = cr.query(ContactsContract.RawContacts.CONTENT_URI, + new String[]{ContactsContract.RawContacts._ID}, + ContactsContract.RawContacts.CONTACT_ID + "=?", + new String[]{contactID}, null); + if (c != null) { + String result = null; + if (c.moveToFirst()) { + result = c.getString(c.getColumnIndex(ContactsContract.RawContacts._ID)); + } + + c.close(); + return result; + } + return null; + } + + public String findRawLinphoneContactID(String contactID) { + String result = null; + String[] projection = { ContactsContract.RawContacts._ID }; + + String selection = ContactsContract.RawContacts.CONTACT_ID + "=? AND " + + ContactsContract.RawContacts.ACCOUNT_TYPE + "=? "; + + Cursor c = contentResolver.query(ContactsContract.RawContacts.CONTENT_URI, projection, + selection, new String[]{contactID, "org.linphone"}, null); + if (c != null) { + if (c.moveToFirst()) { + result = c.getString(c.getColumnIndex(ContactsContract.RawContacts._ID)); + } + } + c.close(); + return result; + } + //Migrate old IM contacts into SIP addresses or linphoneFriends public void migrateContacts() { Cursor oldContacts = Compatibility.getImContactsCursor(contentResolver); @@ -288,12 +353,13 @@ public class ContactsManager { for (int i = 0; i < oldContacts.getCount(); i++) { Contact contact = Compatibility.getContact(contentResolver, oldContacts, i); for (String address : Compatibility.extractContactImAddresses(contact.getID(), contentResolver)) { - if (LinphoneUtils.isSipAddress(address)) { if (address.startsWith("sip:")) { address = address.substring(4); } - Compatibility.addSipAddressToContact(context, ops, address, findRawContactID(contentResolver,contact.getID())); + + //Add new sip address + Compatibility.addSipAddressToContact(context, ops, address, findRawContactID(contentResolver, contact.getID())); try { contentResolver.applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { @@ -302,42 +368,39 @@ public class ContactsManager { ops.clear(); - if(isContactHasAddress(contact,address)){ + contact.refresh(contentResolver); + + //If address sip is correctly add, remove the im address + if(contact.getNumbersOrAddresses().contains(address)){ Compatibility.deleteImAddressFromContact(ops, address, contact.getID()); try { contentResolver.applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { e.printStackTrace(); } - ops.clear(); } else { - if (!address.startsWith("sip:")) { - address = "sip:" + address; + //Add linphone friend instead + if(createNewFriend(contact, address)) { + contact.refresh(contentResolver); + + //Remove IM address + Compatibility.deleteImAddressFromContact(ops, address, contact.getID()); + try { + contentResolver.applyBatch(ContactsContract.AUTHORITY, ops); + } catch (Exception e) { + e.printStackTrace(); + + } } - - createNewFriend(contact, address); - - contact.refresh(contentResolver); - - if (address.startsWith("sip:")) { - address = address.substring(4); - } - Compatibility.deleteImAddressFromContact(ops, address, contact.getID()); - try { - contentResolver.applyBatch(ContactsContract.AUTHORITY, ops); - } catch (Exception e) { - e.printStackTrace(); - - } - ops.clear(); } } + ops.clear(); } - ops.clear(); - contact.refresh(contentResolver); } + oldContacts.close(); } + } public synchronized void prepareContactsInBackground() { @@ -377,6 +440,11 @@ public class ContactsManager { if (contact == null) continue; + //Remove linphone contact tag if the contact has no sip address + if(removeContactTagIsNeeded(contact) && isContactHasLinphoneTag(contact,contentResolver)){ + removeLinphoneContactTag(contact); + } + for (Contact c : sipContactList) { if (c != null && c.getID().equals(contact.getID())) { contact = c; @@ -444,21 +512,4 @@ public class ContactsManager { return false; } - public String findRawContactID(ContentResolver cr, String contactID) { - Cursor c = cr.query(ContactsContract.RawContacts.CONTENT_URI, - new String[]{ContactsContract.RawContacts._ID}, - ContactsContract.RawContacts.CONTACT_ID + "=?", - new String[]{contactID}, null); - if (c != null) { - String result = null; - if (c.moveToFirst()) { - result = c.getString(c.getColumnIndex(ContactsContract.RawContacts._ID)); - } - - c.close(); - return result; - } - return null; - } - } diff --git a/src/org/linphone/EditContactFragment.java b/src/org/linphone/EditContactFragment.java index 0889b3b2a..edb2bb77e 100644 --- a/src/org/linphone/EditContactFragment.java +++ b/src/org/linphone/EditContactFragment.java @@ -5,7 +5,6 @@ import java.util.ArrayList; import java.util.List; import org.linphone.compatibility.Compatibility; import org.linphone.mediastream.Version; -import org.linphone.mediastream.Log; import org.linphone.ui.AvatarWithShadow; import android.annotation.SuppressLint; import android.content.ContentProviderOperation; @@ -14,7 +13,6 @@ import android.database.Cursor; import android.graphics.BitmapFactory; import android.os.Bundle; import android.provider.ContactsContract; -import android.provider.ContactsContract.RawContacts; import android.support.v4.app.Fragment; import android.text.Editable; import android.text.InputType; @@ -102,7 +100,7 @@ public class EditContactFragment extends Fragment { try { getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); - checkSipAddress(); + addLinphoneFriendIfNeeded(); contactsManager.prepareContactsInBackground(); } catch (Exception e) { e.printStackTrace(); @@ -360,39 +358,6 @@ public class EditContactFragment extends Fragment { } } - private String findRawContactID(String contactID) { - Cursor c = getActivity().getContentResolver().query(RawContacts.CONTENT_URI, - new String[]{RawContacts._ID},RawContacts.CONTACT_ID + "=?", - new String[]{contactID}, null); - if (c != null) { - String result = null; - if (c.moveToFirst()) { - result = c.getString(c.getColumnIndex(RawContacts._ID)); - } - c.close(); - return result; - } - return null; - } - - private String findRawLinphoneContactID(String contactID) { - String result = null; - String[] projection = { RawContacts._ID }; - - String selection = RawContacts.CONTACT_ID + "=? AND " - + RawContacts.ACCOUNT_TYPE + "=? "; - - Cursor c = getActivity().getContentResolver().query(RawContacts.CONTENT_URI, projection, - selection, new String[]{contactID, getString(R.string.sync_account_type)}, null); - if (c != null) { - if (c.moveToFirst()) { - result = c.getString(c.getColumnIndex(ContactsContract.RawContacts._ID)); - } - } - c.close(); - return result; - } - private String findContactFirstName(String contactID) { Cursor c = getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI, new String[]{ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME}, @@ -425,35 +390,24 @@ public class EditContactFragment extends Fragment { return null; } - private boolean checkSipAddress(){ - boolean check = true; + private void addLinphoneFriendIfNeeded(){ for (NewOrUpdatedNumberOrAddress numberOrAddress : numbersAndAddresses) { - if(numberOrAddress.newNumberOrAddress != null){ - if(numberOrAddress.isSipAddress) { - if(isNewContact){ - Contact c = ContactsManager.getInstance().findContactWithDisplayName(ContactsManager.getInstance().getDisplayName(firstName.getText().toString(), lastName.getText().toString())); - if (!ContactsManager.getInstance().isContactHasAddress(c, numberOrAddress.newNumberOrAddress)) { - if (c != null) { - ContactsManager.getInstance().createNewFriend(c, numberOrAddress.newNumberOrAddress); - } - } + if(numberOrAddress.newNumberOrAddress != null && numberOrAddress.isSipAddress && !contactsManager.isContactHasAddress(contact, numberOrAddress.newNumberOrAddress)) { + if(isNewContact){ + Contact c = contactsManager.findContactWithDisplayName(ContactsManager.getInstance().getDisplayName(firstName.getText().toString(), lastName.getText().toString())); + if (c != null) { + contactsManager.createNewFriend(c, numberOrAddress.newNumberOrAddress); + } + } else { + if (numberOrAddress.oldNumberOrAddress == null) { + contactsManager.createNewFriend(contact, numberOrAddress.newNumberOrAddress); } else { - if (!ContactsManager.getInstance().isContactHasAddress(contact, numberOrAddress.newNumberOrAddress)) { - check = false; - if (numberOrAddress.oldNumberOrAddress == null) { - ContactsManager.getInstance().createNewFriend(contact, numberOrAddress.newNumberOrAddress); - } else { - if(contact.hasFriends()) - ContactsManager.getInstance().updateFriend(numberOrAddress.oldNumberOrAddress, numberOrAddress.newNumberOrAddress); - } - - } + if(contact.hasFriends()) + contactsManager.updateFriend(numberOrAddress.oldNumberOrAddress, numberOrAddress.newNumberOrAddress); } } } } - - return check; } class NewOrUpdatedNumberOrAddress { @@ -509,7 +463,7 @@ public class EditContactFragment extends Fragment { } else { Compatibility.deleteSipAddressFromContact(ops, oldNumberOrAddress, String.valueOf(contactID)); } - Compatibility.deleteLinphoneContactTag(ops, oldNumberOrAddress, findRawLinphoneContactID(String.valueOf(contactID))); + 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 " @@ -546,7 +500,7 @@ public class EditContactFragment extends Fragment { ); } } else { - String rawContactId = findRawContactID(String.valueOf(contactID)); + String rawContactId = contactsManager.findRawContactID(getActivity().getContentResolver(),String.valueOf(contactID)); if (isSipAddress) { if (newNumberOrAddress.startsWith("sip:")) newNumberOrAddress = newNumberOrAddress.substring(4); @@ -554,7 +508,7 @@ public class EditContactFragment extends Fragment { newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain); Compatibility.addSipAddressToContact(getActivity(), ops, newNumberOrAddress, rawContactId); - Compatibility.addLinphoneContactTag(getActivity(), ops, newNumberOrAddress, findRawLinphoneContactID(String.valueOf(contactID))); + 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) @@ -579,7 +533,7 @@ public class EditContactFragment extends Fragment { if(!newNumberOrAddress.contains("@")) newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain); Compatibility.updateSipAddressForContact(ops, oldNumberOrAddress, newNumberOrAddress, String.valueOf(contactID)); - Compatibility.updateLinphoneContactTag(getActivity(), ops, newNumberOrAddress, oldNumberOrAddress, findRawLinphoneContactID(String.valueOf(contactID))); + 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 " diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java index 3bf32df7c..271e435b7 100644 --- a/src/org/linphone/LinphoneActivity.java +++ b/src/org/linphone/LinphoneActivity.java @@ -152,8 +152,8 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene ContactsManager.getInstance().initializeSyncAccount(getApplicationContext(), getContentResolver()); if(!LinphonePreferences.instance().isContactsMigrationDone()){ - //ContactsManager.getInstance().migrateContacts(); - //LinphonePreferences.instance().contactsMigrationDone(); + ContactsManager.getInstance().migrateContacts(); + LinphonePreferences.instance().contactsMigrationDone(); } setContentView(R.layout.main); diff --git a/src/org/linphone/LinphoneService.java b/src/org/linphone/LinphoneService.java index 034867c38..f88dae86d 100644 --- a/src/org/linphone/LinphoneService.java +++ b/src/org/linphone/LinphoneService.java @@ -45,6 +45,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; +import android.database.ContentObserver; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; @@ -52,6 +53,7 @@ import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.SystemClock; +import android.provider.ContactsContract; import android.provider.MediaStore; /** @@ -235,10 +237,12 @@ public final class LinphoneService extends Service { mStartForeground = getClass().getMethod("startForeground", mStartFgSign); mStopForeground = getClass().getMethod("stopForeground", mStopFgSign); } catch (NoSuchMethodException e) { - Log.e(e, "Couldn't find startGoreground or stopForeground"); + Log.e(e, "Couldn't find startForeground or stopForeground"); } } + this.getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, mObserver); + startForegroundCompat(NOTIF_ID, mNotif); if (!mTestDelayElapsed) { @@ -259,6 +263,15 @@ public final class LinphoneService extends Service { , mkeepAlivePendingIntent); } + private ContentObserver mObserver = new ContentObserver(new Handler()) { + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + } + + }; + private enum IncallIconState {INCALL, PAUSE, VIDEO, IDLE} private IncallIconState mCurrentIncallIconState = IncallIconState.IDLE; private synchronized void setIncallIcon(IncallIconState state) { @@ -299,7 +312,8 @@ public final class LinphoneService extends Service { LinphoneAddress address = LinphoneCoreFactory.instance().createLinphoneAddress(userName,domain,null); address.setDisplayName(displayName); - Uri pictureUri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, getContentResolver()); + Contact contact = ContactsManager.getInstance().findContactWithAddress(address); + Uri pictureUri = contact != null ? contact.getPhotoUri() : null; Bitmap bm = null; try { bm = MediaStore.Images.Media.getBitmap(getContentResolver(), pictureUri); @@ -376,7 +390,8 @@ public final class LinphoneService extends Service { Uri pictureUri; try { - pictureUri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(LinphoneCoreFactory.instance().createLinphoneAddress(fromSipUri), getContentResolver()); + Contact contact = ContactsManager.getInstance().findContactWithAddress(LinphoneCoreFactory.instance().createLinphoneAddress(fromSipUri)); + pictureUri = contact.getPhotoUri(); } catch (LinphoneCoreException e1) { Log.e("Cannot parse from address",e1); pictureUri=null; @@ -548,6 +563,7 @@ public final class LinphoneService extends Service { mNM.cancel(MESSAGE_NOTIF_ID); ((AlarmManager) this.getSystemService(Context.ALARM_SERVICE)).cancel(mkeepAlivePendingIntent); + getContentResolver().unregisterContentObserver(mObserver); super.onDestroy(); } diff --git a/src/org/linphone/compatibility/Compatibility.java b/src/org/linphone/compatibility/Compatibility.java index c5e6500e3..226ee1f9e 100644 --- a/src/org/linphone/compatibility/Compatibility.java +++ b/src/org/linphone/compatibility/Compatibility.java @@ -81,7 +81,11 @@ public class Compatibility { } public static List extractContactImAddresses(String id, ContentResolver cr) { - return ApiFivePlus.extractContactNumbersAndAddresses(id, cr); + if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) { + return ApiFivePlus.extractContactNumbersAndAddresses(id, cr); + } else { + return null; + } } public static Cursor getContactsCursor(ContentResolver cr, List contactsId) { diff --git a/submodules/linphone b/submodules/linphone index 04abb5760..ef7677a88 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit 04abb57606e7f322a10e60288291889843feaa70 +Subproject commit ef7677a88d7aaef4168f884eeaca85af2994ecd9