Added a custom setting to allow fetching all device contacts + added debu logs
This commit is contained in:
parent
6ba56bb8f2
commit
35a2010488
16 changed files with 133 additions and 75 deletions
|
@ -34,8 +34,6 @@ import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import org.linphone.LinphoneService;
|
import org.linphone.LinphoneService;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.core.PresenceBasicStatus;
|
|
||||||
import org.linphone.core.PresenceModel;
|
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
|
||||||
class AndroidContact implements Serializable {
|
class AndroidContact implements Serializable {
|
||||||
|
@ -210,33 +208,16 @@ class AndroidContact implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateNativeContactWithPresenceInfo(LinphoneContact contact) {
|
void updateNativeContactWithPresenceInfo(String value) {
|
||||||
// creation of the raw contact with the presence information (tablet)
|
if (!isLinphoneAddressMimeEntryAlreadyExisting(value)) {
|
||||||
createRawLinphoneContactFromExistingAndroidContactIfNeeded();
|
Log.d("[Contact] Adding presence information " + value);
|
||||||
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()) {
|
|
||||||
addChangesToCommit(
|
addChangesToCommit(
|
||||||
ContentProviderOperation.newInsert(Data.CONTENT_URI)
|
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
|
||||||
|
.withValue(ContactsContract.Data.RAW_CONTACT_ID, mAndroidRawId)
|
||||||
.withValue(
|
.withValue(
|
||||||
ContactsContract.Data.RAW_CONTACT_ID, mAndroidRawId)
|
ContactsContract.Data.MIMETYPE,
|
||||||
.withValue(
|
|
||||||
Data.MIMETYPE,
|
|
||||||
ContactsManager.getInstance()
|
ContactsManager.getInstance()
|
||||||
.getString(
|
.getString(R.string.linphone_address_mime_type))
|
||||||
R.string
|
|
||||||
.linphone_address_mime_type))
|
|
||||||
.withValue("data1", value) // phone number
|
.withValue("data1", value) // phone number
|
||||||
.withValue(
|
.withValue(
|
||||||
"data2",
|
"data2",
|
||||||
|
@ -244,20 +225,19 @@ class AndroidContact implements Serializable {
|
||||||
.getString(R.string.app_name)) // Summary
|
.getString(R.string.app_name)) // Summary
|
||||||
.withValue("data3", value) // Detail
|
.withValue("data3", value) // Detail
|
||||||
.build());
|
.build());
|
||||||
saveChangesCommited();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Boolean hasLinphoneAddressMimeType() {
|
private boolean isLinphoneAddressMimeEntryAlreadyExisting(String value) {
|
||||||
Boolean action = true;
|
boolean result = false;
|
||||||
|
|
||||||
ContentResolver resolver = LinphoneService.instance().getContentResolver();
|
ContentResolver resolver = LinphoneService.instance().getContentResolver();
|
||||||
String[] projection = {"data1", "data3"};
|
String[] projection = {"data1", "data3"};
|
||||||
String selection =
|
String selection =
|
||||||
ContactsContract.Data.RAW_CONTACT_ID + "= ? AND " + Data.MIMETYPE + "= ?";
|
ContactsContract.Data.RAW_CONTACT_ID
|
||||||
|
+ " = ? AND "
|
||||||
|
+ Data.MIMETYPE
|
||||||
|
+ " = ? AND data1 = ?";
|
||||||
|
|
||||||
Cursor c =
|
Cursor c =
|
||||||
resolver.query(
|
resolver.query(
|
||||||
|
@ -267,16 +247,17 @@ class AndroidContact implements Serializable {
|
||||||
new String[] {
|
new String[] {
|
||||||
mAndroidRawId,
|
mAndroidRawId,
|
||||||
ContactsManager.getInstance()
|
ContactsManager.getInstance()
|
||||||
.getString(R.string.linphone_address_mime_type)
|
.getString(R.string.linphone_address_mime_type),
|
||||||
|
value
|
||||||
},
|
},
|
||||||
null);
|
null);
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
if (c.moveToFirst()) {
|
if (c.moveToFirst()) {
|
||||||
action = false;
|
result = true;
|
||||||
}
|
}
|
||||||
c.close();
|
c.close();
|
||||||
}
|
}
|
||||||
return action;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addNumberOrAddress(String value, String oldValueToReplace, boolean isSIP) {
|
void addNumberOrAddress(String value, String oldValueToReplace, boolean isSIP) {
|
||||||
|
|
|
@ -1,13 +1,32 @@
|
||||||
package org.linphone.contacts;
|
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;
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
public class AsyncContactPresence extends AsyncTask<Void, AndroidContact, Void> {
|
public class AsyncContactPresence extends AsyncTask<Void, AndroidContact, Void> {
|
||||||
|
|
||||||
private LinphoneContact linphoneContact;
|
private LinphoneContact mLinphoneContact;
|
||||||
|
|
||||||
public AsyncContactPresence(LinphoneContact linphoneContact) {
|
public AsyncContactPresence(LinphoneContact linphoneContact) {
|
||||||
this.linphoneContact = linphoneContact;
|
mLinphoneContact = linphoneContact;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,7 +36,7 @@ public class AsyncContactPresence extends AsyncTask<Void, AndroidContact, Void>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... voids) {
|
protected Void doInBackground(Void... voids) {
|
||||||
linphoneContact.updateNativeContactWithPresenceInfo(linphoneContact);
|
mLinphoneContact.updateNativeContactWithPresenceInfo();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,12 +78,19 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
||||||
@Override
|
@Override
|
||||||
protected AsyncContactsData doInBackground(Void... params) {
|
protected AsyncContactsData doInBackground(Void... params) {
|
||||||
Log.i("[Contacts Manager] Background synchronization started");
|
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 =
|
Cursor c =
|
||||||
mContext.getContentResolver()
|
mContext.getContentResolver()
|
||||||
.query(
|
.query(
|
||||||
ContactsContract.Data.CONTENT_URI,
|
ContactsContract.Data.CONTENT_URI,
|
||||||
PROJECTION,
|
PROJECTION,
|
||||||
ContactsContract.Data.IN_DEFAULT_DIRECTORY + " == 1",
|
selection,
|
||||||
null,
|
null,
|
||||||
null);
|
null);
|
||||||
|
|
||||||
|
@ -141,6 +148,11 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
||||||
|
|
||||||
LinphoneContact contact = androidContactsCache.get(id);
|
LinphoneContact contact = androidContactsCache.get(id);
|
||||||
if (contact == null) {
|
if (contact == null) {
|
||||||
|
Log.d(
|
||||||
|
"[Contacts Manager] Creating LinphoneContact with native ID "
|
||||||
|
+ id
|
||||||
|
+ ", favorite flag is "
|
||||||
|
+ starred);
|
||||||
nativeIds.add(id);
|
nativeIds.add(id);
|
||||||
contact = new LinphoneContact();
|
contact = new LinphoneContact();
|
||||||
contact.setAndroidId(id);
|
contact.setAndroidId(id);
|
||||||
|
|
|
@ -358,11 +358,18 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
public synchronized LinphoneContact findContactFromAddress(Address address) {
|
public synchronized LinphoneContact findContactFromAddress(Address address) {
|
||||||
if (address == null) return null;
|
if (address == null) return null;
|
||||||
Core core = LinphoneManager.getCore();
|
Core core = LinphoneManager.getCore();
|
||||||
|
|
||||||
Friend lf = core.findFriend(address);
|
Friend lf = core.findFriend(address);
|
||||||
if (lf != null) {
|
if (lf != null) {
|
||||||
return (LinphoneContact) lf.getUserData();
|
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) {
|
public synchronized LinphoneContact findContactFromPhoneNumber(String phoneNumber) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.linphone.core.FriendList;
|
||||||
import org.linphone.core.PresenceBasicStatus;
|
import org.linphone.core.PresenceBasicStatus;
|
||||||
import org.linphone.core.PresenceModel;
|
import org.linphone.core.PresenceModel;
|
||||||
import org.linphone.core.SubscribePolicy;
|
import org.linphone.core.SubscribePolicy;
|
||||||
|
import org.linphone.core.tools.Log;
|
||||||
|
|
||||||
public class LinphoneContact extends AndroidContact
|
public class LinphoneContact extends AndroidContact
|
||||||
implements Serializable, Comparable<LinphoneContact> {
|
implements Serializable, Comparable<LinphoneContact> {
|
||||||
|
@ -208,18 +209,18 @@ public class LinphoneContact extends AndroidContact
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
// Check for duplicated phone numbers but with different formats
|
// Check for duplicated phone numbers but with different formats
|
||||||
for (LinphoneNumberOrAddress number : mAddresses) {
|
for (LinphoneNumberOrAddress number : mAddresses) {
|
||||||
|
if (!number.isSIPAddress()) {
|
||||||
if ((!noa.isSIPAddress()
|
if ((!noa.isSIPAddress()
|
||||||
&& !number.isSIPAddress()
|
|
||||||
&& noa.getNormalizedPhone().equals(number.getNormalizedPhone()))
|
&& noa.getNormalizedPhone().equals(number.getNormalizedPhone()))
|
||||||
|| (noa.isSIPAddress()
|
|| (noa.isSIPAddress()
|
||||||
&& !number.isSIPAddress()
|
|
||||||
&& noa.getValue().equals(number.getNormalizedPhone()))
|
&& noa.getValue().equals(number.getNormalizedPhone()))
|
||||||
|| (number.getValue().equals(noa.getNormalizedPhone())
|
|| (noa.getNormalizedPhone().equals(number.getValue()))) {
|
||||||
|| !number.isSIPAddress())) {
|
Log.d("[Linphone Contact] Duplicated entry detected: " + noa);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
if (noa.isSIPAddress()) {
|
if (noa.isSIPAddress()) {
|
||||||
|
@ -538,24 +539,57 @@ public class LinphoneContact extends AndroidContact
|
||||||
String data4 = c.getString(c.getColumnIndex("data4"));
|
String data4 = c.getString(c.getColumnIndex("data4"));
|
||||||
|
|
||||||
if (getFullName() == null) {
|
if (getFullName() == null) {
|
||||||
|
Log.d("[Linphone Contact] Setting display name " + displayName);
|
||||||
setFullName(displayName);
|
setFullName(displayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mime)) {
|
if (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mime)) {
|
||||||
|
Log.d("[Linphone Contact] Found phone number " + data1 + " (" + data4 + ")");
|
||||||
addNumberOrAddress(new LinphoneNumberOrAddress(data1, data4));
|
addNumberOrAddress(new LinphoneNumberOrAddress(data1, data4));
|
||||||
|
|
||||||
} else if (ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE.equals(mime)
|
} else if (ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE.equals(mime)
|
||||||
|| LinphoneService.instance()
|
|| LinphoneService.instance()
|
||||||
.getString(R.string.linphone_address_mime_type)
|
.getString(R.string.linphone_address_mime_type)
|
||||||
.equals(mime)) {
|
.equals(mime)) {
|
||||||
|
Log.d("[Linphone Contact] Found SIP address " + data1);
|
||||||
addNumberOrAddress(new LinphoneNumberOrAddress(data1, true));
|
addNumberOrAddress(new LinphoneNumberOrAddress(data1, true));
|
||||||
} else if (ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE.equals(mime)) {
|
} else if (ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE.equals(mime)) {
|
||||||
|
Log.d("[Linphone Contact] Found organization " + data1);
|
||||||
setOrganization(data1, false);
|
setOrganization(data1, false);
|
||||||
} else if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals(mime)) {
|
} 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);
|
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() {
|
public void save() {
|
||||||
saveChangesCommited();
|
saveChangesCommited();
|
||||||
syncValuesFromAndroidContact(LinphoneService.instance());
|
syncValuesFromAndroidContact(LinphoneService.instance());
|
||||||
|
|
|
@ -89,4 +89,8 @@ public class LinphoneNumberOrAddress implements Serializable, Comparable<Linphon
|
||||||
public String getNormalizedPhone() {
|
public String getNormalizedPhone() {
|
||||||
return mNormalizedPhone != null ? mNormalizedPhone : mValue;
|
return mNormalizedPhone != null ? mNormalizedPhone : mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return (isSIPAddress() ? "sip:" : "tel:") + getNormalizedPhone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,7 @@
|
||||||
<bool name="hide_invite_contact">false</bool>
|
<bool name="hide_invite_contact">false</bool>
|
||||||
<bool name="generate_text_avatar">true</bool>
|
<bool name="generate_text_avatar">true</bool>
|
||||||
<bool name="only_show_address_username_if_matches_default_domain">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 -->
|
<!-- Side Menu -->
|
||||||
<bool name="hide_assistant_from_side_menu">false</bool>
|
<bool name="hide_assistant_from_side_menu">false</bool>
|
||||||
|
|
Loading…
Reference in a new issue