Fixed empty contacts issue after a contact has been edited/created/deleted

This commit is contained in:
Sylvain Berfini 2018-12-06 12:28:36 +01:00
parent 385e72ea9b
commit 54e7760fdd
5 changed files with 143 additions and 135 deletions

View file

@ -72,8 +72,9 @@ public class LinphoneLauncherActivity extends Activity {
} else if (Intent.ACTION_VIEW.equals(action)) { } else if (Intent.ACTION_VIEW.equals(action)) {
if (LinphoneService.isReady()) { if (LinphoneService.isReady()) {
mAddressToCall = mAddressToCall =
ContactsManager.getAddressOrNumberForAndroidContact( ContactsManager.getInstance()
getContentResolver(), intent.getData()); .getAddressOrNumberForAndroidContact(
getContentResolver(), intent.getData());
} else { } else {
mUriToResolve = intent.getData(); mUriToResolve = intent.getData();
} }
@ -143,8 +144,9 @@ public class LinphoneLauncherActivity extends Activity {
} }
if (mUriToResolve != null) { if (mUriToResolve != null) {
mAddressToCall = mAddressToCall =
ContactsManager.getAddressOrNumberForAndroidContact( ContactsManager.getInstance()
getContentResolver(), mUriToResolve); .getAddressOrNumberForAndroidContact(
getContentResolver(), mUriToResolve);
Log.i( Log.i(
"LinphoneLauncher", "LinphoneLauncher",
"Intent has uri to resolve : " + mUriToResolve.toString()); "Intent has uri to resolve : " + mUriToResolve.toString());

View file

@ -40,17 +40,7 @@ import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences; import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils; import org.linphone.utils.LinphoneUtils;
class AsyncContactsData { class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.AsyncContactsData> {
final List<LinphoneContact> contacts;
final List<LinphoneContact> sipContacts;
AsyncContactsData() {
contacts = new ArrayList<>();
sipContacts = new ArrayList<>();
}
}
class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
private static final String[] PROJECTION = { private static final String[] PROJECTION = {
ContactsContract.Data.CONTACT_ID, ContactsContract.Data.CONTACT_ID,
@ -64,7 +54,6 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
}; };
private Context mContext; private Context mContext;
private HashMap<String, LinphoneContact> mAndroidContactsCache;
public AsyncContactsLoader(Context context) { public AsyncContactsLoader(Context context) {
mContext = context; mContext = context;
@ -72,8 +61,6 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
@Override @Override
protected void onPreExecute() { protected void onPreExecute() {
mAndroidContactsCache = new HashMap<>();
if (mContext == null) { if (mContext == null) {
mContext = LinphoneService.instance().getApplicationContext(); mContext = LinphoneService.instance().getApplicationContext();
} }
@ -102,7 +89,10 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
ContactsContract.Data.IN_VISIBLE_GROUP + " == 1", ContactsContract.Data.IN_VISIBLE_GROUP + " == 1",
null, null,
null); null);
HashMap<String, LinphoneContact> androidContactsCache = new HashMap<>();
AsyncContactsData data = new AsyncContactsData(); AsyncContactsData data = new AsyncContactsData();
List<String> nativeIds = new ArrayList<>();
Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (lc != null) { if (lc != null) {
@ -114,7 +104,8 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
if (contact != null) { if (contact != null) {
contact.clearAddresses(); contact.clearAddresses();
if (contact.getAndroidId() != null) { if (contact.getAndroidId() != null) {
mAndroidContactsCache.put(contact.getAndroidId(), contact); androidContactsCache.put(contact.getAndroidId(), contact);
nativeIds.add(contact.getAndroidId());
} }
} else { } else {
if (friend.getRefKey() != null) { if (friend.getRefKey() != null) {
@ -135,7 +126,6 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
} }
if (c != null) { if (c != null) {
List<String> nativeIds = new ArrayList<>();
while (c.moveToNext()) { while (c.moveToNext()) {
if (isCancelled()) return data; if (isCancelled()) return data;
@ -150,15 +140,16 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
String lookupKey = String lookupKey =
c.getString(c.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); c.getString(c.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
LinphoneContact contact = mAndroidContactsCache.get(id); LinphoneContact contact = androidContactsCache.get(id);
if (contact == null) { if (contact == null) {
nativeIds.add(id); nativeIds.add(id);
contact = new LinphoneContact(); contact = new LinphoneContact();
contact.setAndroidId(id); contact.setAndroidId(id);
contact.setAndroidLookupKey(lookupKey); contact.setAndroidLookupKey(lookupKey);
contact.setFullName(displayName); contact.setFullName(displayName);
mAndroidContactsCache.put(id, contact); androidContactsCache.put(id, contact);
} }
if (contact.getFullName() == null && displayName != null) { if (contact.getFullName() == null && displayName != null) {
contact.setFullName(displayName); contact.setFullName(displayName);
} }
@ -188,7 +179,7 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
String id = contact.getAndroidId(); String id = contact.getAndroidId();
if (id != null && !nativeIds.contains(id)) { if (id != null && !nativeIds.contains(id)) {
// Has been removed since last fetch // Has been removed since last fetch
mAndroidContactsCache.remove(id); androidContactsCache.remove(id);
} }
} }
} }
@ -196,7 +187,7 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
nativeIds.clear(); nativeIds.clear();
} }
for (LinphoneContact contact : mAndroidContactsCache.values()) { for (LinphoneContact contact : androidContactsCache.values()) {
if (isCancelled()) return data; if (isCancelled()) return data;
boolean hideContactsWithoutPresence = boolean hideContactsWithoutPresence =
@ -233,7 +224,8 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
} }
data.contacts.add(contact); data.contacts.add(contact);
} }
mAndroidContactsCache.clear();
androidContactsCache.clear();
Collections.sort(data.contacts); Collections.sort(data.contacts);
Collections.sort(data.sipContacts); Collections.sort(data.sipContacts);
@ -254,4 +246,14 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
ContactsManager.getInstance().setContacts(data.contacts); ContactsManager.getInstance().setContacts(data.contacts);
ContactsManager.getInstance().setSipContacts(data.sipContacts); ContactsManager.getInstance().setSipContacts(data.sipContacts);
} }
class AsyncContactsData {
final List<LinphoneContact> contacts;
final List<LinphoneContact> sipContacts;
AsyncContactsData() {
contacts = new ArrayList<>();
sipContacts = new ArrayList<>();
}
}
} }

View file

@ -94,60 +94,6 @@ public class ContactsManager extends ContentObserver implements FriendListListen
return mContactsUpdatedListeners; return mContactsUpdatedListeners;
} }
public static String getAddressOrNumberForAndroidContact(
ContentResolver resolver, Uri contactUri) {
// Phone Numbers
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor c = resolver.query(contactUri, projection, null, null, null);
if (c != null) {
if (c.moveToNext()) {
int numberIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String number = c.getString(numberIndex);
c.close();
return number;
}
}
c.close();
// SIP addresses
projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
c = resolver.query(contactUri, projection, null, null, null);
if (c != null) {
if (c.moveToNext()) {
int numberIndex =
c.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
String address = c.getString(numberIndex);
c.close();
return address;
}
}
c.close();
return null;
}
public void destroy() {
Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (lc != null) {
for (FriendList list : lc.getFriendsLists()) {
list.setListener(null);
}
}
mDefaultAvatar.recycle();
sInstance = null;
}
public MagicSearch getMagicSearch() {
return mMagicSearch;
}
public boolean contactsFetchedOnce() {
return mContactsFetchedOnce;
}
public Bitmap getDefaultAvatarBitmap() {
return mDefaultAvatar;
}
@Override @Override
public void onChange(boolean selfChange) { public void onChange(boolean selfChange) {
onChange(selfChange, null); onChange(selfChange, null);
@ -178,6 +124,72 @@ public class ContactsManager extends ContentObserver implements FriendListListen
mSipContacts = c; mSipContacts = c;
} }
public void destroy() {
Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (lc != null) {
for (FriendList list : lc.getFriendsLists()) {
list.setListener(null);
}
}
mDefaultAvatar.recycle();
sInstance = null;
}
public void fetchContactsAsync() {
if (mLoadContactTask != null) {
mLoadContactTask.cancel(true);
}
mLoadContactTask = new AsyncContactsLoader(mContext);
mContactsFetchedOnce = true;
mLoadContactTask.executeOnExecutor(THREAD_POOL_EXECUTOR);
}
public void editContact(Context context, LinphoneContact contact, String valueToAdd) {
if (context.getResources().getBoolean(R.bool.use_native_contact_editor)) {
Intent intent = new Intent(Intent.ACTION_EDIT);
Uri contactUri = contact.getAndroidLookupUri();
intent.setDataAndType(contactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE);
intent.putExtra(
"finishActivityOnSaveCompleted", true); // So after save will go back here
if (valueToAdd != null) {
intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, valueToAdd);
}
context.startActivity(intent);
} else {
LinphoneActivity.instance().editContact(contact, valueToAdd);
}
}
public void createContact(Context context, String name, String valueToAdd) {
if (context.getResources().getBoolean(R.bool.use_native_contact_editor)) {
Intent intent = new Intent(ContactsContract.Intents.Insert.ACTION);
intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
intent.putExtra(
"finishActivityOnSaveCompleted", true); // So after save will go back here
if (name != null) {
intent.putExtra(ContactsContract.Intents.Insert.NAME, name);
}
if (valueToAdd != null) {
intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, valueToAdd);
}
context.startActivity(intent);
} else {
LinphoneActivity.instance().addContact(name, valueToAdd);
}
}
public MagicSearch getMagicSearch() {
return mMagicSearch;
}
public boolean contactsFetchedOnce() {
return mContactsFetchedOnce;
}
public Bitmap getDefaultAvatarBitmap() {
return mDefaultAvatar;
}
public List<LinphoneContact> getContacts(String search) { public List<LinphoneContact> getContacts(String search) {
search = search.toLowerCase(Locale.getDefault()); search = search.toLowerCase(Locale.getDefault());
List<LinphoneContact> searchContactsBegin = new ArrayList<>(); List<LinphoneContact> searchContactsBegin = new ArrayList<>();
@ -216,11 +228,6 @@ public class ContactsManager extends ContentObserver implements FriendListListen
return searchContactsBegin; return searchContactsBegin;
} }
private synchronized void addSipContact(LinphoneContact contact) {
mSipContacts.add(contact);
Collections.sort(mSipContacts);
}
public void enableContactsAccess() { public void enableContactsAccess() {
LinphonePreferences.instance().disableFriendsStorage(); LinphonePreferences.instance().disableFriendsStorage();
} }
@ -242,7 +249,9 @@ public class ContactsManager extends ContentObserver implements FriendListListen
public boolean isLinphoneContactsPrefered() { public boolean isLinphoneContactsPrefered() {
ProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig(); ProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
return lpc != null return lpc != null
&& lpc.getIdentityAddress().getDomain().equals(getString(R.string.default_domain)); && lpc.getIdentityAddress()
.getDomain()
.equals(mContext.getString(R.string.default_domain));
} }
public void initializeContactManager(Context context) { public void initializeContactManager(Context context) {
@ -262,7 +271,9 @@ public class ContactsManager extends ContentObserver implements FriendListListen
if (accounts != null && accounts.length == 0) { if (accounts != null && accounts.length == 0) {
Account newAccount = Account newAccount =
new Account(getString(R.string.sync_account_name), activity.getPackageName()); new Account(
mContext.getString(R.string.sync_account_name),
activity.getPackageName());
try { try {
accountManager.addAccountExplicitly(newAccount, null, null); accountManager.addAccountExplicitly(newAccount, null, null);
} catch (Exception e) { } catch (Exception e) {
@ -305,10 +316,41 @@ public class ContactsManager extends ContentObserver implements FriendListListen
return null; return null;
} }
public String getAddressOrNumberForAndroidContact(ContentResolver resolver, Uri contactUri) {
// Phone Numbers
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor c = resolver.query(contactUri, projection, null, null, null);
if (c != null) {
if (c.moveToNext()) {
int numberIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String number = c.getString(numberIndex);
c.close();
return number;
}
}
c.close();
// SIP addresses
projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
c = resolver.query(contactUri, projection, null, null, null);
if (c != null) {
if (c.moveToNext()) {
int numberIndex =
c.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
String address = c.getString(numberIndex);
c.close();
return address;
}
}
c.close();
return null;
}
private synchronized boolean refreshSipContact(Friend lf) { private synchronized boolean refreshSipContact(Friend lf) {
LinphoneContact contact = (LinphoneContact) lf.getUserData(); LinphoneContact contact = (LinphoneContact) lf.getUserData();
if (contact != null && !getSIPContacts().contains(contact)) { if (contact != null && !mSipContacts.contains(contact)) {
addSipContact(contact); mSipContacts.add(contact);
Collections.sort(mSipContacts);
return true; return true;
} }
return false; return false;
@ -367,49 +409,4 @@ public class ContactsManager extends ContentObserver implements FriendListListen
} }
} }
} }
public void fetchContactsAsync() {
if (mLoadContactTask != null) {
mLoadContactTask.cancel(true);
}
mLoadContactTask = new AsyncContactsLoader(mContext);
mContactsFetchedOnce = true;
mLoadContactTask.executeOnExecutor(THREAD_POOL_EXECUTOR);
}
public void editContact(Context context, LinphoneContact contact, String valueToAdd) {
if (context.getResources().getBoolean(R.bool.use_native_contact_editor)) {
Intent intent = new Intent(Intent.ACTION_EDIT);
Uri contactUri =
ContactsContract.Contacts.getLookupUri(
Long.parseLong(contact.getAndroidId()), contact.getAndroidLookupKey());
intent.setDataAndType(contactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE);
intent.putExtra(
"finishActivityOnSaveCompleted", true); // So after save will go back here
if (valueToAdd != null) {
intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, valueToAdd);
}
context.startActivity(intent);
} else {
LinphoneActivity.instance().editContact(contact, valueToAdd);
}
}
public void createContact(Context context, String name, String valueToAdd) {
if (context.getResources().getBoolean(R.bool.use_native_contact_editor)) {
Intent intent = new Intent(ContactsContract.Intents.Insert.ACTION);
intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
intent.putExtra(
"finishActivityOnSaveCompleted", true); // So after save will go back here
if (name != null) {
intent.putExtra(ContactsContract.Intents.Insert.NAME, name);
}
if (valueToAdd != null) {
intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, valueToAdd);
}
context.startActivity(intent);
} else {
LinphoneActivity.instance().addContact(name, valueToAdd);
}
}
} }

View file

@ -703,6 +703,11 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
mAndroidLookupKey = lookupKey; mAndroidLookupKey = lookupKey;
} }
public Uri getAndroidLookupUri() {
return ContactsContract.Contacts.getLookupUri(
Long.parseLong(getAndroidId()), getAndroidLookupKey());
}
public Friend getFriend() { public Friend getFriend() {
return mFriend; return mFriend;
} }

View file

@ -246,8 +246,10 @@ public class DialerFragment extends Fragment {
} else { } else {
Uri contactUri = intent.getData(); Uri contactUri = intent.getData();
String address = String address =
ContactsManager.getAddressOrNumberForAndroidContact( ContactsManager.getInstance()
LinphoneService.instance().getContentResolver(), contactUri); .getAddressOrNumberForAndroidContact(
LinphoneService.instance().getContentResolver(),
contactUri);
if (address != null) { if (address != null) {
mAddress.setText(address); mAddress.setText(address);
} else { } else {