Use newly added SDK API to merge friend list

This commit is contained in:
Sylvain Berfini 2025-07-31 10:27:04 +02:00
parent a5cee98a57
commit 98bf3daed8
7 changed files with 63 additions and 113 deletions

View file

@ -314,84 +314,17 @@ class ContactLoader : LoaderManager.LoaderCallbacks<Cursor> {
}
Log.i("$TAG Friends added")
} else {
val friendsArray = friends.values.toTypedArray()
Log.i(
"$TAG Friend list [$NATIVE_ADDRESS_BOOK_FRIEND_LIST] found, synchronizing existing friends with new ones"
)
for (localFriend in friendsList.friends) {
val newlyFetchedFriend = friends[localFriend.refKey]
if (newlyFetchedFriend != null) {
friends.remove(localFriend.refKey)
localFriend.nativeUri =
newlyFetchedFriend.nativeUri // Native URI isn't stored in linphone database, needs to be updated
if (newlyFetchedFriend.dumpVcard() == localFriend.dumpVcard()) continue
localFriend.edit()
// Update basic fields that may have changed
localFriend.name = newlyFetchedFriend.name
localFriend.organization = newlyFetchedFriend.organization
localFriend.jobTitle = newlyFetchedFriend.jobTitle
localFriend.photo = newlyFetchedFriend.photo
// Clear local friend phone numbers & add all newly fetched one ones
var atLeastAPhoneNumberWasRemoved = false
for (phoneNumber in localFriend.phoneNumbersWithLabel) {
val found = newlyFetchedFriend.phoneNumbers.find {
it == phoneNumber.phoneNumber
}
if (found == null) {
atLeastAPhoneNumberWasRemoved = true
}
localFriend.removePhoneNumberWithLabel(phoneNumber)
}
for (phoneNumber in newlyFetchedFriend.phoneNumbersWithLabel) {
localFriend.addPhoneNumberWithLabel(phoneNumber)
}
// If at least a phone number was removed, remove all SIP address from local friend before adding all from newly fetched one.
// If none was removed, simply add SIP addresses from fetched contact that aren't already in the local friend.
if (atLeastAPhoneNumberWasRemoved) {
Log.w(
"$TAG At least a phone number was removed from native contact [${localFriend.name}], clearing all SIP addresses from local friend before adding back the ones that still exists"
)
for (sipAddress in localFriend.addresses) {
localFriend.removeAddress(sipAddress)
}
}
// Adding only newly added SIP address(es) in native contact if any
for (sipAddress in newlyFetchedFriend.addresses) {
localFriend.addAddress(sipAddress)
}
localFriend.done()
val changes = friendsList.synchronizeFriendsWith(friendsArray)
if (changes) {
Log.i("$TAG Locally stored friends synchronized with native address book")
} else {
Log.i(
"$TAG Friend [${localFriend.name}] with ref key [${localFriend.refKey}] not found in newly fetched batch, removing it"
)
friendsList.removeFriend(localFriend)
Log.i("$TAG No changes detected between native address book and local friends storage")
}
}
// Check for newly created friends since last sync
val localFriends = friendsList.friends
for ((key, newFriend) in friends.entries) {
val found = localFriends.find {
it.refKey == key
}
if (found == null) {
if (newFriend.refKey == null) {
Log.w(
"$TAG Found friend [${newFriend.name}] with no refKey, using ID [$key]"
)
newFriend.refKey = key
}
Log.i(
"$TAG Friend [${newFriend.name}] with ref key [${newFriend.refKey}] not found in currently stored list, adding it"
)
friendsList.addLocalFriend(newFriend)
}
}
Log.i("$TAG Friends synchronized")
}
friends.clear()
friendsList.updateSubscriptions()

View file

@ -29,7 +29,6 @@ import org.linphone.BuildConfig
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.R
import org.linphone.contacts.ContactLoader.Companion.NATIVE_ADDRESS_BOOK_FRIEND_LIST
import org.linphone.core.Core
import org.linphone.core.CoreListenerStub
import org.linphone.core.VersionUpdateCheckResult
@ -251,20 +250,4 @@ class HelpViewModel
}
}
}
@UiThread
fun clearNativeFriendsDatabase() {
coreContext.postOnCoreThread { core ->
val list = core.getFriendListByName(NATIVE_ADDRESS_BOOK_FRIEND_LIST)
if (list != null) {
val friends = list.friends
Log.i("$TAG Friend list to remove found with [${friends.size}] friends")
for (friend in friends) {
list.removeFriend(friend)
}
core.removeFriendList(list)
Log.i("$TAG Friend list [$NATIVE_ADDRESS_BOOK_FRIEND_LIST] removed")
}
}
}
}

View file

@ -29,6 +29,7 @@ import androidx.lifecycle.MutableLiveData
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.R
import org.linphone.contacts.ContactLoader.Companion.NATIVE_ADDRESS_BOOK_FRIEND_LIST
import org.linphone.core.AudioDevice
import org.linphone.core.Conference
import org.linphone.core.Core
@ -1181,4 +1182,21 @@ class SettingsViewModel
corePreferences.pushNotificationCompatibleDomains = newList
}
}
@UiThread
fun clearNativeFriendsDatabase() {
coreContext.postOnCoreThread { core ->
val list = core.getFriendListByName(NATIVE_ADDRESS_BOOK_FRIEND_LIST)
if (list != null) {
val friends = list.friends
Log.i("$TAG Friend list to remove found with [${friends.size}] friends")
for (friend in friends) {
list.removeFriend(friend)
}
core.removeFriendList(list)
Log.i("$TAG Friend list [$NATIVE_ADDRESS_BOOK_FRIEND_LIST] removed")
}
showGreenToast(R.string.settings_developer_cleared_native_friends_in_database_toast, R.drawable.trash_simple)
}
}
}

View file

@ -295,27 +295,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/firebase_project_subtitle"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:id="@+id/clear_friends_db"
android:onClick="@{() -> viewModel.clearNativeFriendsDatabase()}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="@dimen/screen_bottom_margin"
android:text="@string/help_troubleshooting_clear_native_friends_in_database"
android:maxLines="1"
android:ellipsize="end"
android:drawableEnd="@drawable/trash_simple"
android:drawableTint="?attr/color_main2_600"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/show_config_file"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View file

@ -270,6 +270,39 @@
app:layout_constraintStart_toStartOf="@id/push_compatible_domains_list_label"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:id="@+id/clear_friends_db_label"
android:onClick="@{() -> viewModel.clearNativeFriendsDatabase()}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="20dp"
android:text="@string/settings_developer_clear_native_friends_in_database_title"
android:maxLines="2"
android:ellipsize="end"
android:drawablePadding="5dp"
android:drawableEnd="@drawable/warning_circle"
android:drawableTint="?attr/color_main2_600"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/push_compatible_domains_list"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_subtitle_style"
android:id="@+id/clear_friends_db_subtitle"
android:onClick="@{() -> viewModel.clearNativeFriendsDatabase()}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="10dp"
android:maxLines="3"
android:text="@string/settings_developer_clear_native_friends_in_database_subtitle"
app:layout_constraintTop_toBottomOf="@id/clear_friends_db_label"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View file

@ -186,7 +186,6 @@
<string name="help_troubleshooting_debug_logs_cleaned_toast_message">Les journaux ont été nettoyés</string>
<string name="help_troubleshooting_debug_logs_upload_error_toast_message">Échec à l\'envoi des journaux</string>
<string name="help_troubleshooting_show_config_file">Afficher la configuration</string>
<string name="help_troubleshooting_clear_native_friends_in_database">Supprimer les contacts natifs importés</string>
<!-- App & SDK settings -->
<string name="settings_title">Paramètres</string>
@ -318,6 +317,9 @@
<string name="settings_developer_already_enabled_toast">Paramètres développeurs déjà activés</string>
<string name="settings_developer_enable_vu_meters_title">Activer l\'indicateur des volumes d\'enregistrement et de lecture</string>
<string name="settings_developer_push_compatible_domains_list_title">Liste des domaines qui supportent les notifications poussées (séparés par des virgules)</string>
<string name="settings_developer_clear_native_friends_in_database_title">Supprimer les contacts natifs importés</string>
<string name="settings_developer_clear_native_friends_in_database_subtitle">Ils seront synchronisés à nouveau au prochain démarrage de l\'application sauf si vous retirez la permission de lire les contacts</string>
<string name="settings_developer_cleared_native_friends_in_database_toast">Contacts importés supprimés</string>
<!-- Account profile & settings -->
<string name="manage_account_title">Mon compte</string>

View file

@ -228,7 +228,6 @@
<string name="help_troubleshooting_debug_logs_cleaned_toast_message">Debug logs have been cleaned</string>
<string name="help_troubleshooting_debug_logs_upload_error_toast_message">Failed to upload debug logs</string>
<string name="help_troubleshooting_show_config_file">Show configuration</string>
<string name="help_troubleshooting_clear_native_friends_in_database">Clear imported contacts from native address book</string>
<!-- App & SDK settings -->
<string name="settings_title">Settings</string>
@ -360,6 +359,9 @@
<string name="settings_developer_already_enabled_toast">Developer settings already enabled</string>
<string name="settings_developer_enable_vu_meters_title">Enable record/playback volume vu meters while in call</string>
<string name="settings_developer_push_compatible_domains_list_title">List of push notifications compatible domains (comma separated)</string>
<string name="settings_developer_clear_native_friends_in_database_title">Clear imported contacts from native address book</string>
<string name="settings_developer_clear_native_friends_in_database_subtitle">They will be imported again the next time the app starts unless you remove the contacts permission</string>
<string name="settings_developer_cleared_native_friends_in_database_toast">Imported contacts have been deleted</string>
<!-- Account profile & settings -->
<string name="manage_account_title">Manage account</string>