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)) {
if (LinphoneService.isReady()) {
mAddressToCall =
ContactsManager.getAddressOrNumberForAndroidContact(
getContentResolver(), intent.getData());
ContactsManager.getInstance()
.getAddressOrNumberForAndroidContact(
getContentResolver(), intent.getData());
} else {
mUriToResolve = intent.getData();
}
@ -143,8 +144,9 @@ public class LinphoneLauncherActivity extends Activity {
}
if (mUriToResolve != null) {
mAddressToCall =
ContactsManager.getAddressOrNumberForAndroidContact(
getContentResolver(), mUriToResolve);
ContactsManager.getInstance()
.getAddressOrNumberForAndroidContact(
getContentResolver(), mUriToResolve);
Log.i(
"LinphoneLauncher",
"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.utils.LinphoneUtils;
class AsyncContactsData {
final List<LinphoneContact> contacts;
final List<LinphoneContact> sipContacts;
AsyncContactsData() {
contacts = new ArrayList<>();
sipContacts = new ArrayList<>();
}
}
class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.AsyncContactsData> {
@SuppressLint("InlinedApi")
private static final String[] PROJECTION = {
ContactsContract.Data.CONTACT_ID,
@ -64,7 +54,6 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
};
private Context mContext;
private HashMap<String, LinphoneContact> mAndroidContactsCache;
public AsyncContactsLoader(Context context) {
mContext = context;
@ -72,8 +61,6 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
@Override
protected void onPreExecute() {
mAndroidContactsCache = new HashMap<>();
if (mContext == null) {
mContext = LinphoneService.instance().getApplicationContext();
}
@ -102,7 +89,10 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
ContactsContract.Data.IN_VISIBLE_GROUP + " == 1",
null,
null);
HashMap<String, LinphoneContact> androidContactsCache = new HashMap<>();
AsyncContactsData data = new AsyncContactsData();
List<String> nativeIds = new ArrayList<>();
Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (lc != null) {
@ -114,7 +104,8 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
if (contact != null) {
contact.clearAddresses();
if (contact.getAndroidId() != null) {
mAndroidContactsCache.put(contact.getAndroidId(), contact);
androidContactsCache.put(contact.getAndroidId(), contact);
nativeIds.add(contact.getAndroidId());
}
} else {
if (friend.getRefKey() != null) {
@ -135,7 +126,6 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
}
if (c != null) {
List<String> nativeIds = new ArrayList<>();
while (c.moveToNext()) {
if (isCancelled()) return data;
@ -150,15 +140,16 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
String lookupKey =
c.getString(c.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
LinphoneContact contact = mAndroidContactsCache.get(id);
LinphoneContact contact = androidContactsCache.get(id);
if (contact == null) {
nativeIds.add(id);
contact = new LinphoneContact();
contact.setAndroidId(id);
contact.setAndroidLookupKey(lookupKey);
contact.setFullName(displayName);
mAndroidContactsCache.put(id, contact);
androidContactsCache.put(id, contact);
}
if (contact.getFullName() == null && displayName != null) {
contact.setFullName(displayName);
}
@ -188,7 +179,7 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
String id = contact.getAndroidId();
if (id != null && !nativeIds.contains(id)) {
// 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();
}
for (LinphoneContact contact : mAndroidContactsCache.values()) {
for (LinphoneContact contact : androidContactsCache.values()) {
if (isCancelled()) return data;
boolean hideContactsWithoutPresence =
@ -233,7 +224,8 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
}
data.contacts.add(contact);
}
mAndroidContactsCache.clear();
androidContactsCache.clear();
Collections.sort(data.contacts);
Collections.sort(data.sipContacts);
@ -254,4 +246,14 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsData> {
ContactsManager.getInstance().setContacts(data.contacts);
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;
}
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
public void onChange(boolean selfChange) {
onChange(selfChange, null);
@ -178,6 +124,72 @@ public class ContactsManager extends ContentObserver implements FriendListListen
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) {
search = search.toLowerCase(Locale.getDefault());
List<LinphoneContact> searchContactsBegin = new ArrayList<>();
@ -216,11 +228,6 @@ public class ContactsManager extends ContentObserver implements FriendListListen
return searchContactsBegin;
}
private synchronized void addSipContact(LinphoneContact contact) {
mSipContacts.add(contact);
Collections.sort(mSipContacts);
}
public void enableContactsAccess() {
LinphonePreferences.instance().disableFriendsStorage();
}
@ -242,7 +249,9 @@ public class ContactsManager extends ContentObserver implements FriendListListen
public boolean isLinphoneContactsPrefered() {
ProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
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) {
@ -262,7 +271,9 @@ public class ContactsManager extends ContentObserver implements FriendListListen
if (accounts != null && accounts.length == 0) {
Account newAccount =
new Account(getString(R.string.sync_account_name), activity.getPackageName());
new Account(
mContext.getString(R.string.sync_account_name),
activity.getPackageName());
try {
accountManager.addAccountExplicitly(newAccount, null, null);
} catch (Exception e) {
@ -305,10 +316,41 @@ public class ContactsManager extends ContentObserver implements FriendListListen
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) {
LinphoneContact contact = (LinphoneContact) lf.getUserData();
if (contact != null && !getSIPContacts().contains(contact)) {
addSipContact(contact);
if (contact != null && !mSipContacts.contains(contact)) {
mSipContacts.add(contact);
Collections.sort(mSipContacts);
return true;
}
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;
}
public Uri getAndroidLookupUri() {
return ContactsContract.Contacts.getLookupUri(
Long.parseLong(getAndroidId()), getAndroidLookupKey());
}
public Friend getFriend() {
return mFriend;
}

View file

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