Added a custom setting to allow fetching all device contacts + added debu logs

This commit is contained in:
Sylvain Berfini 2019-07-01 15:05:18 +02:00
parent 6ba56bb8f2
commit 35a2010488
16 changed files with 133 additions and 75 deletions

View file

@ -34,8 +34,6 @@ import java.io.Serializable;
import java.util.ArrayList;
import org.linphone.LinphoneService;
import org.linphone.R;
import org.linphone.core.PresenceBasicStatus;
import org.linphone.core.PresenceModel;
import org.linphone.core.tools.Log;
class AndroidContact implements Serializable {
@ -210,33 +208,16 @@ class AndroidContact implements Serializable {
}
}
public void updateNativeContactWithPresenceInfo(LinphoneContact contact) {
// creation of the raw contact with the presence information (tablet)
createRawLinphoneContactFromExistingAndroidContactIfNeeded();
for (LinphoneNumberOrAddress noa : contact.getNumbersOrAddresses()) {
String value = noa.getValue();
if (value == null || value.isEmpty()) {
return;
}
// Test presence of the value
PresenceModel pm = contact.getFriend().getPresenceModelForUriOrTel(value);
// If presence is not null
if (pm != null && pm.getBasicStatus().equals(PresenceBasicStatus.Open)) {
Boolean action = hasLinphoneAddressMimeType();
// do the action on the contact only once if it has not been done
if (action) {
if (!noa.isSIPAddress()) {
void updateNativeContactWithPresenceInfo(String value) {
if (!isLinphoneAddressMimeEntryAlreadyExisting(value)) {
Log.d("[Contact] Adding presence information " + value);
addChangesToCommit(
ContentProviderOperation.newInsert(Data.CONTENT_URI)
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, mAndroidRawId)
.withValue(
ContactsContract.Data.RAW_CONTACT_ID, mAndroidRawId)
.withValue(
Data.MIMETYPE,
ContactsContract.Data.MIMETYPE,
ContactsManager.getInstance()
.getString(
R.string
.linphone_address_mime_type))
.getString(R.string.linphone_address_mime_type))
.withValue("data1", value) // phone number
.withValue(
"data2",
@ -244,20 +225,19 @@ class AndroidContact implements Serializable {
.getString(R.string.app_name)) // Summary
.withValue("data3", value) // Detail
.build());
saveChangesCommited();
}
}
}
}
}
private Boolean hasLinphoneAddressMimeType() {
Boolean action = true;
private boolean isLinphoneAddressMimeEntryAlreadyExisting(String value) {
boolean result = false;
ContentResolver resolver = LinphoneService.instance().getContentResolver();
String[] projection = {"data1", "data3"};
String selection =
ContactsContract.Data.RAW_CONTACT_ID + "= ? AND " + Data.MIMETYPE + "= ?";
ContactsContract.Data.RAW_CONTACT_ID
+ " = ? AND "
+ Data.MIMETYPE
+ " = ? AND data1 = ?";
Cursor c =
resolver.query(
@ -267,16 +247,17 @@ class AndroidContact implements Serializable {
new String[] {
mAndroidRawId,
ContactsManager.getInstance()
.getString(R.string.linphone_address_mime_type)
.getString(R.string.linphone_address_mime_type),
value
},
null);
if (c != null) {
if (c.moveToFirst()) {
action = false;
result = true;
}
c.close();
}
return action;
return result;
}
void addNumberOrAddress(String value, String oldValueToReplace, boolean isSIP) {

View file

@ -1,13 +1,32 @@
package org.linphone.contacts;
/*
AsyncContactPresence.java
Copyright (C) 2019 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import android.os.AsyncTask;
public class AsyncContactPresence extends AsyncTask<Void, AndroidContact, Void> {
private LinphoneContact linphoneContact;
private LinphoneContact mLinphoneContact;
public AsyncContactPresence(LinphoneContact linphoneContact) {
this.linphoneContact = linphoneContact;
mLinphoneContact = linphoneContact;
}
@Override
@ -17,7 +36,7 @@ public class AsyncContactPresence extends AsyncTask<Void, AndroidContact, Void>
@Override
protected Void doInBackground(Void... voids) {
linphoneContact.updateNativeContactWithPresenceInfo(linphoneContact);
mLinphoneContact.updateNativeContactWithPresenceInfo();
return null;
}
}

View file

@ -78,12 +78,19 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
@Override
protected AsyncContactsData doInBackground(Void... params) {
Log.i("[Contacts Manager] Background synchronization started");
String selection = null;
if (mContext.getResources().getBoolean(R.bool.fetch_contacts_from_default_directory)) {
Log.i("[Contacts Manager] Only fetching contacts in default directory");
selection = ContactsContract.Data.IN_DEFAULT_DIRECTORY + " == 1";
}
Cursor c =
mContext.getContentResolver()
.query(
ContactsContract.Data.CONTENT_URI,
PROJECTION,
ContactsContract.Data.IN_DEFAULT_DIRECTORY + " == 1",
selection,
null,
null);
@ -141,6 +148,11 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
LinphoneContact contact = androidContactsCache.get(id);
if (contact == null) {
Log.d(
"[Contacts Manager] Creating LinphoneContact with native ID "
+ id
+ ", favorite flag is "
+ starred);
nativeIds.add(id);
contact = new LinphoneContact();
contact.setAndroidId(id);

View file

@ -358,11 +358,18 @@ public class ContactsManager extends ContentObserver implements FriendListListen
public synchronized LinphoneContact findContactFromAddress(Address address) {
if (address == null) return null;
Core core = LinphoneManager.getCore();
Friend lf = core.findFriend(address);
if (lf != null) {
return (LinphoneContact) lf.getUserData();
}
return findContactFromPhoneNumber(address.getUsername());
String username = address.getUsername();
if (android.util.Patterns.PHONE.matcher(username).matches()) {
return findContactFromPhoneNumber(username);
}
return null;
}
public synchronized LinphoneContact findContactFromPhoneNumber(String phoneNumber) {

View file

@ -37,6 +37,7 @@ import org.linphone.core.FriendList;
import org.linphone.core.PresenceBasicStatus;
import org.linphone.core.PresenceModel;
import org.linphone.core.SubscribePolicy;
import org.linphone.core.tools.Log;
public class LinphoneContact extends AndroidContact
implements Serializable, Comparable<LinphoneContact> {
@ -208,18 +209,18 @@ public class LinphoneContact extends AndroidContact
boolean found = false;
// Check for duplicated phone numbers but with different formats
for (LinphoneNumberOrAddress number : mAddresses) {
if (!number.isSIPAddress()) {
if ((!noa.isSIPAddress()
&& !number.isSIPAddress()
&& noa.getNormalizedPhone().equals(number.getNormalizedPhone()))
|| (noa.isSIPAddress()
&& !number.isSIPAddress()
&& noa.getValue().equals(number.getNormalizedPhone()))
|| (number.getValue().equals(noa.getNormalizedPhone())
|| !number.isSIPAddress())) {
|| (noa.getNormalizedPhone().equals(number.getValue()))) {
Log.d("[Linphone Contact] Duplicated entry detected: " + noa);
found = true;
break;
}
}
}
if (!found) {
if (noa.isSIPAddress()) {
@ -538,24 +539,57 @@ public class LinphoneContact extends AndroidContact
String data4 = c.getString(c.getColumnIndex("data4"));
if (getFullName() == null) {
Log.d("[Linphone Contact] Setting display name " + displayName);
setFullName(displayName);
}
if (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mime)) {
Log.d("[Linphone Contact] Found phone number " + data1 + " (" + data4 + ")");
addNumberOrAddress(new LinphoneNumberOrAddress(data1, data4));
} else if (ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE.equals(mime)
|| LinphoneService.instance()
.getString(R.string.linphone_address_mime_type)
.equals(mime)) {
Log.d("[Linphone Contact] Found SIP address " + data1);
addNumberOrAddress(new LinphoneNumberOrAddress(data1, true));
} else if (ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE.equals(mime)) {
Log.d("[Linphone Contact] Found organization " + data1);
setOrganization(data1, false);
} else if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals(mime)) {
Log.d("[Linphone Contact] Found first name " + data2 + " and last name " + data3);
setFirstNameAndLastName(data2, data3, false);
} else {
Log.w("[Linphone Contact] Unexpected MIME type " + mime);
}
}
public void updateNativeContactWithPresenceInfo() {
Log.d("[Contact] Trying to update native contact with presence information");
// Creation of the raw contact with the presence information (tablet)
createRawLinphoneContactFromExistingAndroidContactIfNeeded();
for (LinphoneNumberOrAddress noa : getNumbersOrAddresses()) {
if (noa.isSIPAddress()) {
// We are only interested in SIP addresses
continue;
}
String value = noa.getValue();
if (value == null || value.isEmpty()) {
return;
}
// Test presence of the value
PresenceModel pm = getFriend().getPresenceModelForUriOrTel(value);
// If presence is not null
if (pm != null && pm.getBasicStatus().equals(PresenceBasicStatus.Open)) {
Log.d("[Contact] Found presence information for phone number " + value);
// Do the action on the contact only once if it has not been done yet
updateNativeContactWithPresenceInfo(value);
}
}
saveChangesCommited();
}
public void save() {
saveChangesCommited();
syncValuesFromAndroidContact(LinphoneService.instance());

View file

@ -89,4 +89,8 @@ public class LinphoneNumberOrAddress implements Serializable, Comparable<Linphon
public String getNormalizedPhone() {
return mNormalizedPhone != null ? mNormalizedPhone : mValue;
}
public String toString() {
return (isSIPAddress() ? "sip:" : "tel:") + getNormalizedPhone();
}
}

View file

@ -110,6 +110,7 @@
<bool name="hide_invite_contact">false</bool>
<bool name="generate_text_avatar">true</bool>
<bool name="only_show_address_username_if_matches_default_domain">true</bool>
<bool name="fetch_contacts_from_default_directory">true</bool> <!-- Recommended -->
<!-- Side Menu -->
<bool name="hide_assistant_from_side_menu">false</bool>