mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Make sure to always search contacts using a cleaned SIP address + improved Android DB search for SIP address + delay loading contacts to after an account was successfully registered
This commit is contained in:
parent
aa36235ab1
commit
82d6d37fd7
6 changed files with 83 additions and 41 deletions
|
|
@ -26,6 +26,7 @@ import android.database.Cursor
|
|||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.provider.ContactsContract
|
||||
import androidx.annotation.MainThread
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.app.ActivityCompat
|
||||
|
|
@ -120,7 +121,7 @@ class ContactsManager @UiThread constructor() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@MainThread
|
||||
fun loadContacts(activity: MainActivity) {
|
||||
val manager = LoaderManager.getInstance(activity)
|
||||
manager.restartLoader(0, null, ContactLoader())
|
||||
|
|
@ -236,15 +237,25 @@ class ContactsManager @UiThread constructor() {
|
|||
|
||||
@WorkerThread
|
||||
fun findContactByAddress(address: Address): Friend? {
|
||||
val sipUri = address.asStringUriOnly()
|
||||
val sipUri = LinphoneUtils.getAddressAsCleanStringUriOnly(address)
|
||||
Log.d("$TAG Looking for friend with SIP URI [$sipUri]")
|
||||
|
||||
val username = address.username
|
||||
val found = coreContext.core.findFriend(address)
|
||||
return if (found != null) {
|
||||
if (found != null) {
|
||||
Log.d("$TAG Friend [${found.name}] was found using SIP URI [$sipUri]")
|
||||
found
|
||||
} else if (!username.isNullOrEmpty() && username.startsWith("+")) {
|
||||
return found
|
||||
}
|
||||
|
||||
val sipAddress = if (sipUri.startsWith("sip:")) {
|
||||
sipUri.substring("sip:".length)
|
||||
} else if (sipUri.startsWith("sips:")) {
|
||||
sipUri.substring("sips:".length)
|
||||
} else {
|
||||
sipUri
|
||||
}
|
||||
|
||||
return if (!username.isNullOrEmpty() && username.startsWith("+")) {
|
||||
Log.d("$TAG Looking for friend with phone number [$username]")
|
||||
val foundUsingPhoneNumber = coreContext.core.findFriendByPhoneNumber(username)
|
||||
if (foundUsingPhoneNumber != null) {
|
||||
|
|
@ -256,13 +267,13 @@ class ContactsManager @UiThread constructor() {
|
|||
Log.d(
|
||||
"$TAG Friend wasn't found using phone number [$username], looking in native address book directly"
|
||||
)
|
||||
findNativeContact(sipUri, true, username)
|
||||
findNativeContact(sipAddress, username, true)
|
||||
}
|
||||
} else {
|
||||
Log.d(
|
||||
"$TAG Friend wasn't found using SIP URI [$sipUri] and username [$username] isn't a phone number, looking in native address book directly"
|
||||
"$TAG Friend wasn't found using SIP address [$sipAddress] and username [$username] isn't a phone number, looking in native address book directly"
|
||||
)
|
||||
findNativeContact(sipUri, false)
|
||||
findNativeContact(sipAddress, username.orEmpty(), false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -339,10 +350,7 @@ class ContactsManager @UiThread constructor() {
|
|||
"$TAG Looking for avatar model for friend [${friend.name}] using SIP URI [${address.asStringUriOnly()}]"
|
||||
)
|
||||
|
||||
val clone = address.clone()
|
||||
clone.clean()
|
||||
val key = clone.asStringUriOnly()
|
||||
|
||||
val key = LinphoneUtils.getAddressAsCleanStringUriOnly(address)
|
||||
val foundInMap = getAvatarModelFromCache(key)
|
||||
if (foundInMap != null) {
|
||||
Log.d("$TAG Found avatar model in map using SIP URI [$key]")
|
||||
|
|
@ -402,7 +410,7 @@ class ContactsManager @UiThread constructor() {
|
|||
}
|
||||
|
||||
@WorkerThread
|
||||
fun findNativeContact(address: String, searchAsPhoneNumber: Boolean, number: String = ""): Friend? {
|
||||
fun findNativeContact(address: String, username: String, searchAsPhoneNumber: Boolean): Friend? {
|
||||
if (nativeContactsLoaded) {
|
||||
Log.d(
|
||||
"$TAG Native contacts already loaded, no need to search further, no native contact matches address [$address]"
|
||||
|
|
@ -417,19 +425,19 @@ class ContactsManager @UiThread constructor() {
|
|||
) == PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
Log.d(
|
||||
"$TAG Looking for native contact with address [$address] ${if (searchAsPhoneNumber) "or phone number [$number]" else ""}"
|
||||
"$TAG Looking for native contact with address [$address] ${if (searchAsPhoneNumber) "or phone number [$username]" else ""}"
|
||||
)
|
||||
|
||||
try {
|
||||
val selection = if (searchAsPhoneNumber) {
|
||||
"${ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER} LIKE ? OR ${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ?"
|
||||
"${ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER} LIKE ? OR ${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ? OR ${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ? OR ${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ?"
|
||||
} else {
|
||||
"${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ?"
|
||||
"${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ? OR ${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ? OR ${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ?"
|
||||
}
|
||||
val selectionParams = if (searchAsPhoneNumber) {
|
||||
arrayOf(number, address)
|
||||
arrayOf(username, address, "sip:$address", username)
|
||||
} else {
|
||||
arrayOf(address)
|
||||
arrayOf(address, "sip:$address", username)
|
||||
}
|
||||
val cursor: Cursor? = context.contentResolver.query(
|
||||
ContactsContract.Data.CONTENT_URI,
|
||||
|
|
|
|||
|
|
@ -810,25 +810,22 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
isPausedByRemote.postValue(call.state == Call.State.PausedByRemote)
|
||||
canBePaused.postValue(canCallBePaused())
|
||||
|
||||
val address = call.remoteAddress.clone()
|
||||
address.clean()
|
||||
val address = call.remoteAddress
|
||||
displayedAddress.postValue(address.asStringUriOnly())
|
||||
|
||||
val conferenceInfo = coreContext.core.findConferenceInformationFromUri(
|
||||
call.remoteAddress
|
||||
)
|
||||
val conferenceInfo = coreContext.core.findConferenceInformationFromUri(address)
|
||||
val model = if (conferenceInfo != null) {
|
||||
coreContext.contactsManager.getContactAvatarModelForConferenceInfo(conferenceInfo)
|
||||
} else {
|
||||
// Do not use contact avatar model from ContactsManager
|
||||
// coreContext.contactsManager.getContactAvatarModelForAddress(call.remoteAddress)
|
||||
val friend = coreContext.contactsManager.findContactByAddress(call.remoteAddress)
|
||||
// coreContext.contactsManager.getContactAvatarModelForAddress(address)
|
||||
val friend = coreContext.contactsManager.findContactByAddress(address)
|
||||
if (friend != null) {
|
||||
ContactAvatarModel(friend)
|
||||
} else {
|
||||
val fakeFriend = coreContext.core.createFriend()
|
||||
fakeFriend.name = LinphoneUtils.getDisplayName(address)
|
||||
fakeFriend.address = call.remoteAddress
|
||||
fakeFriend.address = address
|
||||
ContactAvatarModel(fakeFriend)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,10 +96,6 @@ class MainActivity : GenericActivity() {
|
|||
Thread.sleep(50)
|
||||
}
|
||||
|
||||
if (checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
|
||||
loadContacts()
|
||||
}
|
||||
|
||||
viewModel = run {
|
||||
ViewModelProvider(this)[MainViewModel::class.java]
|
||||
}
|
||||
|
|
@ -160,6 +156,14 @@ class MainActivity : GenericActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
viewModel.startLoadingContactsEvent.observe(this) {
|
||||
it.consume {
|
||||
if (checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
|
||||
loadContacts()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.root.doOnAttach {
|
||||
Log.i("$TAG Report UI has been fully drawn (TTFD)")
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@ class ConversationInfoViewModel @UiThread constructor() : AbstractConversationVi
|
|||
val firstParticipant = chatRoom.participants.firstOrNull()
|
||||
if (firstParticipant != null) {
|
||||
val address = firstParticipant.address
|
||||
sipUri.postValue(address.asStringUriOnly())
|
||||
sipUri.postValue(LinphoneUtils.getAddressAsCleanStringUriOnly(address))
|
||||
val friend = coreContext.contactsManager.findContactByAddress(address)
|
||||
oneToOneParticipantRefKey.postValue(friend?.refKey ?: "")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,10 @@ class MainViewModel @UiThread constructor() : ViewModel() {
|
|||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
val startLoadingContactsEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
var accountsFound = -1
|
||||
|
||||
var mainIntentHandled = false
|
||||
|
|
@ -94,6 +98,8 @@ class MainViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
private var alertJob: Job? = null
|
||||
|
||||
private var firstAccountRegistered: Boolean = false
|
||||
|
||||
private val coreListener = object : CoreListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onLastCallEnded(core: Core) {
|
||||
|
|
@ -164,10 +170,20 @@ class MainViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
}
|
||||
RegistrationState.Ok -> {
|
||||
if (account == core.defaultAccount && defaultAccountRegistrationFailed) {
|
||||
Log.i("$TAG Default account is now registered")
|
||||
defaultAccountRegistrationFailed = false
|
||||
defaultAccountRegistrationErrorEvent.postValue(Event(false))
|
||||
if (!firstAccountRegistered) {
|
||||
Log.i(
|
||||
"$TAG First account registered, start loading contacts if permission has been granted"
|
||||
)
|
||||
firstAccountRegistered = true
|
||||
startLoadingContactsEvent.postValue(Event(true))
|
||||
}
|
||||
|
||||
if (account == core.defaultAccount) {
|
||||
if (defaultAccountRegistrationFailed) {
|
||||
Log.i("$TAG Default account is now registered")
|
||||
defaultAccountRegistrationFailed = false
|
||||
defaultAccountRegistrationErrorEvent.postValue(Event(false))
|
||||
}
|
||||
} else {
|
||||
// If no call and no account is in Failed state, hide top bar
|
||||
val found = core.accountList.find {
|
||||
|
|
@ -240,6 +256,14 @@ class MainViewModel @UiThread constructor() : ViewModel() {
|
|||
updateCallAlert()
|
||||
}
|
||||
atLeastOneCall.postValue(core.callsNb > 0)
|
||||
|
||||
if (core.defaultAccount?.state == RegistrationState.Ok && !firstAccountRegistered) {
|
||||
Log.i(
|
||||
"$TAG First account registered, start loading contacts if permission has been granted"
|
||||
)
|
||||
firstAccountRegistered = true
|
||||
startLoadingContactsEvent.postValue(Event(true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -293,17 +317,16 @@ class MainViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
val currentCall = core.currentCall ?: core.calls.firstOrNull()
|
||||
if (currentCall != null) {
|
||||
val contact = coreContext.contactsManager.findContactByAddress(
|
||||
currentCall.remoteAddress
|
||||
)
|
||||
val address = currentCall.remoteAddress
|
||||
val contact = coreContext.contactsManager.findContactByAddress(address)
|
||||
val label = if (contact != null) {
|
||||
contact.name ?: LinphoneUtils.getDisplayName(currentCall.remoteAddress)
|
||||
contact.name ?: LinphoneUtils.getDisplayName(address)
|
||||
} else {
|
||||
val conferenceInfo = coreContext.core.findConferenceInformationFromUri(
|
||||
currentCall.remoteAddress
|
||||
address
|
||||
)
|
||||
conferenceInfo?.subject ?: LinphoneUtils.getDisplayName(
|
||||
currentCall.remoteAddress
|
||||
address
|
||||
)
|
||||
}
|
||||
addAlert(SINGLE_CALL, label)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,16 @@ class LinphoneUtils {
|
|||
return coreContext.core.defaultAccount ?: coreContext.core.accountList.firstOrNull()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getAddressAsCleanStringUriOnly(address: Address): String {
|
||||
val scheme = address.scheme ?: "sip"
|
||||
val username = address.username
|
||||
if (username.orEmpty().isEmpty()) {
|
||||
return "$scheme:${address.domain}"
|
||||
}
|
||||
return "$scheme:$username@${address.domain}"
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getDisplayName(address: Address?): String {
|
||||
if (address == null) return "[null]"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue