Improved how presence is stored in native contact + fixed issue where write contacts permission was missing + ask for contacts permission in contacts settings
This commit is contained in:
parent
d79c8f09e6
commit
c15ecd54ac
5 changed files with 88 additions and 15 deletions
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.activities.main.settings.fragments
|
package org.linphone.activities.main.settings.fragments
|
||||||
|
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -27,11 +28,14 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
import org.linphone.activities.main.settings.viewmodels.ContactsSettingsViewModel
|
import org.linphone.activities.main.settings.viewmodels.ContactsSettingsViewModel
|
||||||
import org.linphone.compatibility.Compatibility
|
import org.linphone.compatibility.Compatibility
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.databinding.SettingsContactsFragmentBinding
|
import org.linphone.databinding.SettingsContactsFragmentBinding
|
||||||
|
import org.linphone.utils.PermissionHelper
|
||||||
|
|
||||||
class ContactsSettingsFragment : Fragment() {
|
class ContactsSettingsFragment : Fragment() {
|
||||||
private lateinit var binding: SettingsContactsFragmentBinding
|
private lateinit var binding: SettingsContactsFragmentBinding
|
||||||
|
@ -69,5 +73,52 @@ class ContactsSettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
viewModel.askWriteContactsPermissionForPresenceStorageEvent.observe(viewLifecycleOwner, Observer {
|
||||||
|
it.consume {
|
||||||
|
Log.i("[Contacts Settings] Asking for WRITE_CONTACTS permission to be able to store presence")
|
||||||
|
requestPermissions(arrayOf(android.Manifest.permission.WRITE_CONTACTS), 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!PermissionHelper.required(requireContext()).hasReadContactsPermission()) {
|
||||||
|
Log.i("[Contacts Settings] Asking for READ_CONTACTS permission")
|
||||||
|
requestPermissions(arrayOf(android.Manifest.permission.READ_CONTACTS), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(
|
||||||
|
requestCode: Int,
|
||||||
|
permissions: Array<out String>,
|
||||||
|
grantResults: IntArray
|
||||||
|
) {
|
||||||
|
when (requestCode) {
|
||||||
|
0 -> {
|
||||||
|
val granted = grantResults[0] == PackageManager.PERMISSION_GRANTED
|
||||||
|
if (granted) {
|
||||||
|
Log.i("[Contacts Settings] READ_CONTACTS permission granted")
|
||||||
|
viewModel.readContactsPermissionGranted.value = true
|
||||||
|
coreContext.contactsManager.fetchContactsAsync()
|
||||||
|
} else {
|
||||||
|
Log.w("[Contacts Settings] READ_CONTACTS permission denied")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
val granted = grantResults[0] == PackageManager.PERMISSION_GRANTED
|
||||||
|
if (granted) {
|
||||||
|
Log.i("[Contacts Settings] WRITE_CONTACTS permission granted")
|
||||||
|
corePreferences.storePresenceInNativeContact = true
|
||||||
|
|
||||||
|
if (coreContext.core.isFriendListSubscriptionEnabled) {
|
||||||
|
Log.i("[Contacts Settings] Updating subscription")
|
||||||
|
for (list in coreContext.core.friendsLists) {
|
||||||
|
list.updateSubscriptions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w("[Contacts Settings] WRITE_CONTACTS permission denied")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,15 @@ package org.linphone.activities.main.settings.viewmodels
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import org.linphone.activities.main.settings.SettingListenerStub
|
import org.linphone.activities.main.settings.SettingListenerStub
|
||||||
import org.linphone.utils.Event
|
import org.linphone.utils.Event
|
||||||
|
import org.linphone.utils.PermissionHelper
|
||||||
|
|
||||||
class ContactsSettingsViewModel : GenericSettingsViewModel() {
|
class ContactsSettingsViewModel : GenericSettingsViewModel() {
|
||||||
|
val askWriteContactsPermissionForPresenceStorageEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||||
|
MutableLiveData<Event<Boolean>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
val readContactsPermissionGranted = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val friendListSubscribeListener = object : SettingListenerStub() {
|
val friendListSubscribeListener = object : SettingListenerStub() {
|
||||||
override fun onBoolValueChanged(newValue: Boolean) {
|
override fun onBoolValueChanged(newValue: Boolean) {
|
||||||
core.enableFriendListSubscription(newValue)
|
core.enableFriendListSubscription(newValue)
|
||||||
|
@ -33,7 +40,15 @@ class ContactsSettingsViewModel : GenericSettingsViewModel() {
|
||||||
|
|
||||||
val nativePresenceListener = object : SettingListenerStub() {
|
val nativePresenceListener = object : SettingListenerStub() {
|
||||||
override fun onBoolValueChanged(newValue: Boolean) {
|
override fun onBoolValueChanged(newValue: Boolean) {
|
||||||
|
if (newValue) {
|
||||||
|
if (PermissionHelper.get().hasWriteContactsPermission()) {
|
||||||
prefs.storePresenceInNativeContact = newValue
|
prefs.storePresenceInNativeContact = newValue
|
||||||
|
} else {
|
||||||
|
askWriteContactsPermissionForPresenceStorageEvent.value = Event(true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
prefs.storePresenceInNativeContact = newValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val nativePresence = MutableLiveData<Boolean>()
|
val nativePresence = MutableLiveData<Boolean>()
|
||||||
|
@ -55,6 +70,8 @@ class ContactsSettingsViewModel : GenericSettingsViewModel() {
|
||||||
val launcherShortcutsEvent = MutableLiveData<Event<Boolean>>()
|
val launcherShortcutsEvent = MutableLiveData<Event<Boolean>>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
readContactsPermissionGranted.value = PermissionHelper.get().hasReadContactsPermission()
|
||||||
|
|
||||||
friendListSubscribe.value = core.isFriendListSubscriptionEnabled
|
friendListSubscribe.value = core.isFriendListSubscriptionEnabled
|
||||||
nativePresence.value = prefs.storePresenceInNativeContact
|
nativePresence.value = prefs.storePresenceInNativeContact
|
||||||
showOrganization.value = prefs.displayOrganization
|
showOrganization.value = prefs.displayOrganization
|
||||||
|
|
|
@ -287,7 +287,7 @@ class ContactsManager(private val context: Context) {
|
||||||
listener.onContactUpdated(contact)
|
listener.onContactUpdated(contact)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (corePreferences.storePresenceInNativeContact) {
|
if (corePreferences.storePresenceInNativeContact && PermissionHelper.get().hasWriteContactsPermission()) {
|
||||||
if (contact is NativeContact) {
|
if (contact is NativeContact) {
|
||||||
for (phoneNumber in contact.phoneNumbers) {
|
for (phoneNumber in contact.phoneNumbers) {
|
||||||
val sipAddress = contact.getContactForPhoneNumberOrAddress(phoneNumber)
|
val sipAddress = contact.getContactForPhoneNumberOrAddress(phoneNumber)
|
||||||
|
|
|
@ -235,10 +235,11 @@ class NativeContactEditor(
|
||||||
sipAddress.currentValue.isEmpty() -> {
|
sipAddress.currentValue.isEmpty() -> {
|
||||||
// New address to add
|
// New address to add
|
||||||
addCount++
|
addCount++
|
||||||
|
val address = sipAddress.newValue.value.orEmpty()
|
||||||
if (useLinphoneSyncAccount) {
|
if (useLinphoneSyncAccount) {
|
||||||
addAddress(sipAddress.newValue.value.orEmpty())
|
addAddress(address, address)
|
||||||
} else {
|
} else {
|
||||||
addSipAddress(sipAddress.newValue.value.orEmpty())
|
addSipAddress(address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sipAddress.toRemove.value == true -> {
|
sipAddress.toRemove.value == true -> {
|
||||||
|
@ -268,7 +269,7 @@ class NativeContactEditor(
|
||||||
Log.i("[Native Contact Editor] Trying to add presence information to contact as ${if (useLinphoneSyncAccount) "phone number" else "SIP address"}")
|
Log.i("[Native Contact Editor] Trying to add presence information to contact as ${if (useLinphoneSyncAccount) "phone number" else "SIP address"}")
|
||||||
|
|
||||||
if (useLinphoneSyncAccount) {
|
if (useLinphoneSyncAccount) {
|
||||||
setPresencePhoneNumber(phoneNumber)
|
setPresence(sipAddress, phoneNumber)
|
||||||
} else {
|
} else {
|
||||||
setPresenceSipAddress(sipAddress)
|
setPresenceSipAddress(sipAddress)
|
||||||
}
|
}
|
||||||
|
@ -359,7 +360,7 @@ class NativeContactEditor(
|
||||||
addChanges(delete)
|
addChanges(delete)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addAddress(address: String) {
|
private fun addAddress(address: String, detail: String) {
|
||||||
val insert = ContentProviderOperation.newInsert(contactUri)
|
val insert = ContentProviderOperation.newInsert(contactUri)
|
||||||
.withValue(ContactsContract.Data.RAW_CONTACT_ID, linphoneRawId)
|
.withValue(ContactsContract.Data.RAW_CONTACT_ID, linphoneRawId)
|
||||||
.withValue(
|
.withValue(
|
||||||
|
@ -368,7 +369,7 @@ class NativeContactEditor(
|
||||||
)
|
)
|
||||||
.withValue("data1", address) // value
|
.withValue("data1", address) // value
|
||||||
.withValue("data2", AppUtils.getString(R.string.app_name)) // summary
|
.withValue("data2", AppUtils.getString(R.string.app_name)) // summary
|
||||||
.withValue("data3", address) // detail
|
.withValue("data3", detail) // detail
|
||||||
.build()
|
.build()
|
||||||
addChanges(insert)
|
addChanges(insert)
|
||||||
}
|
}
|
||||||
|
@ -422,13 +423,13 @@ class NativeContactEditor(
|
||||||
addChanges(delete)
|
addChanges(delete)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setPresencePhoneNumber(phoneNumber: String) {
|
private fun setPresence(sipAddress: String, phoneNumber: String) {
|
||||||
val contentResolver = coreContext.context.contentResolver
|
val contentResolver = coreContext.context.contentResolver
|
||||||
val cursor = contentResolver.query(
|
val cursor = contentResolver.query(
|
||||||
ContactsContract.Data.CONTENT_URI,
|
ContactsContract.Data.CONTENT_URI,
|
||||||
arrayOf("data1"),
|
arrayOf("data1"),
|
||||||
"${ContactsContract.Data.RAW_CONTACT_ID} = ? AND ${ContactsContract.Data.MIMETYPE} = ? AND data1 = ?",
|
"${ContactsContract.Data.RAW_CONTACT_ID} = ? AND ${ContactsContract.Data.MIMETYPE} = ? AND data1 = ? AND data3 = ?",
|
||||||
arrayOf(linphoneRawId, AppUtils.getString(R.string.linphone_address_mime_type), phoneNumber),
|
arrayOf(linphoneRawId, AppUtils.getString(R.string.linphone_address_mime_type), sipAddress, phoneNumber),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
val count = cursor?.count ?: 0
|
val count = cursor?.count ?: 0
|
||||||
|
@ -436,7 +437,7 @@ class NativeContactEditor(
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
Log.i("[Native Contact Editor] No existing presence information found for this phone number, let's add it")
|
Log.i("[Native Contact Editor] No existing presence information found for this phone number, let's add it")
|
||||||
addAddress(phoneNumber)
|
addAddress(sipAddress, phoneNumber)
|
||||||
} else {
|
} else {
|
||||||
Log.i("[Native Contact Editor] There is already an entry for this, skipping")
|
Log.i("[Native Contact Editor] There is already an entry for this, skipping")
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,28 +69,32 @@
|
||||||
linphone:title="@{@string/contacts_settings_friendlist_subscribe_title}"
|
linphone:title="@{@string/contacts_settings_friendlist_subscribe_title}"
|
||||||
linphone:subtitle="@{@string/contacts_settings_friendlist_subscribe_summary}"
|
linphone:subtitle="@{@string/contacts_settings_friendlist_subscribe_summary}"
|
||||||
linphone:listener="@{viewModel.friendListSubscribeListener}"
|
linphone:listener="@{viewModel.friendListSubscribeListener}"
|
||||||
linphone:checked="@={viewModel.friendListSubscribe}"/>
|
linphone:checked="@={viewModel.friendListSubscribe}"
|
||||||
|
linphone:enabled="@{viewModel.readContactsPermissionGranted}"/>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
layout="@layout/settings_widget_switch"
|
layout="@layout/settings_widget_switch"
|
||||||
linphone:title="@{@string/contacts_settings_native_presence_title}"
|
linphone:title="@{@string/contacts_settings_native_presence_title}"
|
||||||
linphone:subtitle="@{@string/contacts_settings_native_presence_summary}"
|
linphone:subtitle="@{@string/contacts_settings_native_presence_summary}"
|
||||||
linphone:listener="@{viewModel.nativePresenceListener}"
|
linphone:listener="@{viewModel.nativePresenceListener}"
|
||||||
linphone:checked="@={viewModel.nativePresence}"/>
|
linphone:checked="@={viewModel.nativePresence}"
|
||||||
|
linphone:enabled="@{viewModel.readContactsPermissionGranted && viewModel.friendListSubscribe}"/>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
layout="@layout/settings_widget_switch"
|
layout="@layout/settings_widget_switch"
|
||||||
linphone:title="@{@string/contacts_settings_show_organization_title}"
|
linphone:title="@{@string/contacts_settings_show_organization_title}"
|
||||||
linphone:subtitle="@{@string/contacts_settings_show_organization_summary}"
|
linphone:subtitle="@{@string/contacts_settings_show_organization_summary}"
|
||||||
linphone:listener="@{viewModel.showOrganizationListener}"
|
linphone:listener="@{viewModel.showOrganizationListener}"
|
||||||
linphone:checked="@={viewModel.showOrganization}"/>
|
linphone:checked="@={viewModel.showOrganization}"
|
||||||
|
linphone:enabled="@{viewModel.readContactsPermissionGranted}"/>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
layout="@layout/settings_widget_switch"
|
layout="@layout/settings_widget_switch"
|
||||||
linphone:title="@{@string/contacts_settings_launcher_shortcuts_title}"
|
linphone:title="@{@string/contacts_settings_launcher_shortcuts_title}"
|
||||||
linphone:subtitle="@{@string/contacts_settings_launcher_shortcuts_summary}"
|
linphone:subtitle="@{@string/contacts_settings_launcher_shortcuts_summary}"
|
||||||
linphone:listener="@{viewModel.launcherShortcutsListener}"
|
linphone:listener="@{viewModel.launcherShortcutsListener}"
|
||||||
linphone:checked="@={viewModel.launcherShortcuts}"/>
|
linphone:checked="@={viewModel.launcherShortcuts}"
|
||||||
|
linphone:enabled="@{viewModel.readContactsPermissionGranted}"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue