mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-20 12:09:45 +01:00
fix "chat via"-links in phonebook (no multiple entries, fix deletion)
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
711afaccf5
commit
adc0a91dac
@ -9,11 +9,14 @@ Types of changes can be: Added/Changed/Deprecated/Removed/Fixed/Security
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- improve conversation list design wand dark/light theming
|
- improve conversation list design and dark/light theming
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- @ in username is allowed for phonebook sync
|
- @ in username is allowed for phonebook sync
|
||||||
- avoid sync when phonebook is empty
|
- avoid sync when phonebook is empty
|
||||||
|
- avoid creation of multiple "chat via"-links in phonebook
|
||||||
|
- delete "chat via"-link from phonebook if phone number was deleted on server
|
||||||
|
- remove all "chat via"-links from phonebook when sync is disabled
|
||||||
|
|
||||||
## [11.1.0] - 2021-03-12
|
## [11.1.0] - 2021-03-12
|
||||||
### Added
|
### Added
|
||||||
|
@ -176,7 +176,8 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
|||||||
if (userUtils.currentUser?.baseUrl?.endsWith(baseUrl) == true) {
|
if (userUtils.currentUser?.baseUrl?.endsWith(baseUrl) == true) {
|
||||||
startConversation(user)
|
startConversation(user)
|
||||||
} else {
|
} else {
|
||||||
Snackbar.make(container, "Account not found", Snackbar.LENGTH_LONG).show()
|
Snackbar.make(container, R.string.nc_phone_book_integration_account_not_found, Snackbar
|
||||||
|
.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ import android.content.pm.PackageManager
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.RemoteException
|
import android.os.RemoteException
|
||||||
import android.provider.ContactsContract
|
import android.provider.ContactsContract
|
||||||
import android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
@ -99,15 +98,14 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
Log.d(TAG, "Account already exists")
|
Log.d(TAG, "Account already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect all contacts with phone number
|
val deviceContactsWithNumbers = collectContactsWithPhoneNumbersFromDevice()
|
||||||
val contactsWithNumbers = collectPhoneNumbers()
|
|
||||||
|
|
||||||
if(contactsWithNumbers.isNotEmpty()){
|
if(deviceContactsWithNumbers.isNotEmpty()){
|
||||||
val currentLocale = ConfigurationCompat.getLocales(context.resources.configuration)[0].country
|
val currentLocale = ConfigurationCompat.getLocales(context.resources.configuration)[0].country
|
||||||
|
|
||||||
val map = mutableMapOf<String, Any>()
|
val map = mutableMapOf<String, Any>()
|
||||||
map["location"] = currentLocale
|
map["location"] = currentLocale
|
||||||
map["search"] = contactsWithNumbers
|
map["search"] = deviceContactsWithNumbers
|
||||||
|
|
||||||
val json = Gson().toJson(map)
|
val json = Gson().toJson(map)
|
||||||
|
|
||||||
@ -125,13 +123,14 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onNext(foundContacts: ContactsByNumberOverall) {
|
override fun onNext(foundContacts: ContactsByNumberOverall) {
|
||||||
up(foundContacts)
|
val contactsWithAssociatedPhoneNumbers = foundContacts.ocs.map
|
||||||
|
deleteLinkedAccounts(contactsWithAssociatedPhoneNumbers)
|
||||||
|
createLinkedAccounts(contactsWithAssociatedPhoneNumbers)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
Log.e(javaClass.simpleName, "Failed to searchContactsByPhoneNumber", e)
|
Log.e(javaClass.simpleName, "Failed to searchContactsByPhoneNumber", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,8 +140,8 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collectPhoneNumbers(): MutableMap<String, List<String>> {
|
private fun collectContactsWithPhoneNumbersFromDevice(): MutableMap<String, List<String>> {
|
||||||
val result: MutableMap<String, List<String>> = mutableMapOf()
|
val deviceContactsWithNumbers: MutableMap<String, List<String>> = mutableMapOf()
|
||||||
|
|
||||||
val contactCursor = context.contentResolver.query(
|
val contactCursor = context.contentResolver.query(
|
||||||
ContactsContract.Contacts.CONTENT_URI,
|
ContactsContract.Contacts.CONTENT_URI,
|
||||||
@ -156,42 +155,32 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
if (contactCursor.count > 0) {
|
if (contactCursor.count > 0) {
|
||||||
contactCursor.moveToFirst()
|
contactCursor.moveToFirst()
|
||||||
for (i in 0 until contactCursor.count) {
|
for (i in 0 until contactCursor.count) {
|
||||||
val numbers: MutableList<String> = mutableListOf()
|
|
||||||
|
|
||||||
val id = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID))
|
val id = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID))
|
||||||
val lookup = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY))
|
val lookup = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY))
|
||||||
|
deviceContactsWithNumbers[lookup] = getPhoneNumbersFromDeviceContact(id)
|
||||||
val phonesCursor = context.contentResolver.query(
|
|
||||||
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
|
||||||
null,
|
|
||||||
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id,
|
|
||||||
null,
|
|
||||||
null)
|
|
||||||
|
|
||||||
if (phonesCursor != null) {
|
|
||||||
while (phonesCursor.moveToNext()) {
|
|
||||||
numbers.add(phonesCursor.getString(phonesCursor.getColumnIndex(NUMBER)))
|
|
||||||
}
|
|
||||||
|
|
||||||
result[lookup] = numbers
|
|
||||||
|
|
||||||
phonesCursor.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
contactCursor.moveToNext()
|
contactCursor.moveToNext()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contactCursor.close()
|
contactCursor.close()
|
||||||
}
|
}
|
||||||
|
Log.d(TAG, "collected contacts with phonenumbers: " + deviceContactsWithNumbers.size)
|
||||||
return result
|
return deviceContactsWithNumbers
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun up(foundContacts: ContactsByNumberOverall) {
|
private fun deleteLinkedAccounts(contactsWithAssociatedPhoneNumbers: Map<String, String>?) {
|
||||||
val map = foundContacts.ocs.map
|
Log.d(TAG, "deleteLinkedAccount")
|
||||||
|
fun deleteLinkedAccount(id: String) {
|
||||||
|
val rawContactUri = ContactsContract.RawContacts.CONTENT_URI
|
||||||
|
.buildUpon()
|
||||||
|
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
||||||
|
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
||||||
|
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
||||||
|
.build()
|
||||||
|
val count = context.contentResolver.delete(rawContactUri, ContactsContract.RawContacts.CONTACT_ID + " " +
|
||||||
|
"LIKE \"" + id + "\"", null)
|
||||||
|
Log.d(TAG, "deleted $count linked accounts for id $id")
|
||||||
|
}
|
||||||
|
|
||||||
// Delete all old associations (those that are associated on phone, but not in server response)
|
|
||||||
val rawContactUri = ContactsContract.Data.CONTENT_URI
|
val rawContactUri = ContactsContract.Data.CONTENT_URI
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
||||||
@ -200,7 +189,6 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
.appendQueryParameter(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat")
|
.appendQueryParameter(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
// get all raw contacts
|
|
||||||
val rawContactsCursor = context.contentResolver.query(
|
val rawContactsCursor = context.contentResolver.query(
|
||||||
rawContactUri,
|
rawContactUri,
|
||||||
null,
|
null,
|
||||||
@ -212,35 +200,56 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
if (rawContactsCursor != null) {
|
if (rawContactsCursor != null) {
|
||||||
if (rawContactsCursor.count > 0) {
|
if (rawContactsCursor.count > 0) {
|
||||||
while (rawContactsCursor.moveToNext()) {
|
while (rawContactsCursor.moveToNext()) {
|
||||||
val id = rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.RawContacts._ID))
|
|
||||||
val sync1 = rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.Data.SYNC1))
|
|
||||||
val lookupKey = rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.Data.LOOKUP_KEY))
|
val lookupKey = rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.Data.LOOKUP_KEY))
|
||||||
Log.d("Contact", "Found associated: $id")
|
val contactId = rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID))
|
||||||
|
|
||||||
if (map == null || !map.containsKey(lookupKey)) {
|
if (contactsWithAssociatedPhoneNumbers == null || !contactsWithAssociatedPhoneNumbers.containsKey(lookupKey)) {
|
||||||
if (sync1 != null) {
|
deleteLinkedAccount(contactId)
|
||||||
deleteAssociation(sync1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "no contacts with linked Talk Accounts found. Nothing to delete...")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
rawContactsCursor.close()
|
rawContactsCursor.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// update / change found
|
|
||||||
if (map != null && map.isNotEmpty()) {
|
|
||||||
for (contact in foundContacts.ocs.map) {
|
|
||||||
val lookupKey = contact.key
|
|
||||||
val cloudId = contact.value
|
|
||||||
|
|
||||||
update(lookupKey, cloudId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun update(uniqueId: String, cloudId: String) {
|
private fun createLinkedAccounts(contactsWithAssociatedPhoneNumbers: Map<String, String>?) {
|
||||||
val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, uniqueId)
|
fun hasLinkedAccount(id: String) : Boolean {
|
||||||
|
var hasLinkedAccount = false
|
||||||
|
val where = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?"
|
||||||
|
val params = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id)
|
||||||
|
|
||||||
|
val rawContactUri = ContactsContract.Data.CONTENT_URI
|
||||||
|
.buildUpon()
|
||||||
|
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
||||||
|
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
||||||
|
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
||||||
|
.appendQueryParameter(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val rawContactsCursor = context.contentResolver.query(
|
||||||
|
rawContactUri,
|
||||||
|
null,
|
||||||
|
where,
|
||||||
|
params,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
|
if (rawContactsCursor != null) {
|
||||||
|
if (rawContactsCursor.count > 0) {
|
||||||
|
hasLinkedAccount = true
|
||||||
|
Log.d(TAG, "contact with id $id already has a linked account")
|
||||||
|
} else {
|
||||||
|
hasLinkedAccount = false
|
||||||
|
}
|
||||||
|
rawContactsCursor.close()
|
||||||
|
}
|
||||||
|
return hasLinkedAccount
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createLinkedAccount(lookupKey: String, cloudId: String) {
|
||||||
|
val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
|
||||||
val lookupContactUri = ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri)
|
val lookupContactUri = ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri)
|
||||||
val contactCursor = context.contentResolver.query(
|
val contactCursor = context.contentResolver.query(
|
||||||
lookupContactUri,
|
lookupContactUri,
|
||||||
@ -254,25 +263,78 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
contactCursor.moveToFirst()
|
contactCursor.moveToFirst()
|
||||||
|
|
||||||
val id = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID))
|
val id = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID))
|
||||||
|
if(hasLinkedAccount(id)){
|
||||||
val phonesCursor = context.contentResolver.query(
|
return
|
||||||
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
|
||||||
null,
|
|
||||||
ContactsContract.Data.CONTACT_ID + " = " + id,
|
|
||||||
null,
|
|
||||||
null)
|
|
||||||
|
|
||||||
val numbers = mutableListOf<String>()
|
|
||||||
if (phonesCursor != null) {
|
|
||||||
while (phonesCursor.moveToNext()) {
|
|
||||||
numbers.add(phonesCursor.getString(phonesCursor.getColumnIndex(NUMBER)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
phonesCursor.close()
|
val numbers = getPhoneNumbersFromDeviceContact(id)
|
||||||
|
val displayName = getDisplayNameFromDeviceContact(id)
|
||||||
|
|
||||||
|
if (displayName == null) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var displayName: String? = null
|
val ops = ArrayList<ContentProviderOperation>()
|
||||||
|
val rawContactsUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().build()
|
||||||
|
val dataUri = ContactsContract.Data.CONTENT_URI.buildUpon().build()
|
||||||
|
|
||||||
|
ops.add(ContentProviderOperation
|
||||||
|
.newInsert(rawContactsUri)
|
||||||
|
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
||||||
|
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
||||||
|
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE,
|
||||||
|
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
|
||||||
|
.withValue(ContactsContract.RawContacts.SYNC2, cloudId)
|
||||||
|
.build())
|
||||||
|
ops.add(ContentProviderOperation
|
||||||
|
.newInsert(dataUri)
|
||||||
|
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
||||||
|
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
|
||||||
|
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, numbers[0])
|
||||||
|
.build())
|
||||||
|
ops.add(ContentProviderOperation
|
||||||
|
.newInsert(dataUri)
|
||||||
|
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
||||||
|
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
||||||
|
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
|
||||||
|
.build())
|
||||||
|
ops.add(ContentProviderOperation
|
||||||
|
.newInsert(dataUri)
|
||||||
|
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
||||||
|
.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat")
|
||||||
|
.withValue(ContactsContract.Data.DATA1, cloudId)
|
||||||
|
.withValue(ContactsContract.Data.DATA2, String.format(context.resources.getString(R
|
||||||
|
.string.nc_phone_book_integration_chat_via), accountName))
|
||||||
|
.build())
|
||||||
|
|
||||||
|
try {
|
||||||
|
context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)
|
||||||
|
} catch (e: OperationApplicationException) {
|
||||||
|
Log.e(javaClass.simpleName, "", e)
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
Log.e(javaClass.simpleName, "", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "added new entry for contact $displayName (cloudId: $cloudId | lookupKey: $lookupKey" +
|
||||||
|
" | id: $id)")
|
||||||
|
}
|
||||||
|
contactCursor.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contactsWithAssociatedPhoneNumbers != null && contactsWithAssociatedPhoneNumbers.isNotEmpty()) {
|
||||||
|
for (contact in contactsWithAssociatedPhoneNumbers) {
|
||||||
|
val lookupKey = contact.key
|
||||||
|
val cloudId = contact.value
|
||||||
|
createLinkedAccount(lookupKey, cloudId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "no contacts with linked Talk Accounts found. No linked accounts created.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getDisplayNameFromDeviceContact(id: String?): String? {
|
||||||
|
var displayName:String? = null
|
||||||
val whereName = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?"
|
val whereName = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?"
|
||||||
val whereNameParams = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id)
|
val whereNameParams = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id)
|
||||||
val nameCursor = context.contentResolver.query(
|
val nameCursor = context.contentResolver.query(
|
||||||
@ -287,72 +349,28 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
}
|
}
|
||||||
nameCursor.close()
|
nameCursor.close()
|
||||||
}
|
}
|
||||||
|
return displayName
|
||||||
if (displayName == null) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update entries
|
private fun getPhoneNumbersFromDeviceContact(id: String?): MutableList<String> {
|
||||||
val ops = ArrayList<ContentProviderOperation>()
|
val numbers = mutableListOf<String>()
|
||||||
val rawContactsUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon()
|
val phonesNumbersCursor = context.contentResolver.query(
|
||||||
.build()
|
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
||||||
val dataUri = ContactsContract.Data.CONTENT_URI.buildUpon()
|
null,
|
||||||
.build()
|
ContactsContract.Data.CONTACT_ID + " = " + id,
|
||||||
|
null,
|
||||||
|
null)
|
||||||
|
|
||||||
ops.add(ContentProviderOperation
|
if (phonesNumbersCursor != null) {
|
||||||
.newInsert(rawContactsUri)
|
while (phonesNumbersCursor.moveToNext()) {
|
||||||
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
numbers.add(phonesNumbersCursor.getString(phonesNumbersCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)))
|
||||||
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
|
||||||
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE,
|
|
||||||
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
|
|
||||||
.withValue(ContactsContract.RawContacts.SYNC2, cloudId)
|
|
||||||
.build())
|
|
||||||
ops.add(ContentProviderOperation
|
|
||||||
.newInsert(dataUri)
|
|
||||||
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
|
||||||
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
|
|
||||||
.withValue(NUMBER, numbers[0])
|
|
||||||
.build())
|
|
||||||
ops.add(ContentProviderOperation
|
|
||||||
.newInsert(dataUri)
|
|
||||||
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
|
||||||
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
|
||||||
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
|
|
||||||
.build())
|
|
||||||
ops.add(ContentProviderOperation
|
|
||||||
.newInsert(dataUri)
|
|
||||||
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
|
||||||
.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat")
|
|
||||||
.withValue(ContactsContract.Data.DATA1, cloudId)
|
|
||||||
.withValue(ContactsContract.Data.DATA2, "Chat via " + context.resources.getString(R.string.nc_app_name))
|
|
||||||
.build())
|
|
||||||
|
|
||||||
try {
|
|
||||||
context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)
|
|
||||||
} catch (e: OperationApplicationException) {
|
|
||||||
Log.e(javaClass.simpleName, "", e)
|
|
||||||
} catch (e: RemoteException) {
|
|
||||||
Log.e(javaClass.simpleName, "", e)
|
|
||||||
}
|
}
|
||||||
|
phonesNumbersCursor.close()
|
||||||
}
|
}
|
||||||
|
if(numbers.size > 0){
|
||||||
contactCursor.close()
|
Log.d(TAG, "Found ${numbers.size} phone numbers for contact with id $id")
|
||||||
}
|
}
|
||||||
}
|
return numbers
|
||||||
|
|
||||||
private fun deleteAssociation(id: String) {
|
|
||||||
Log.d("Contact", "Delete associated: $id")
|
|
||||||
|
|
||||||
val rawContactUri = ContactsContract.RawContacts.CONTENT_URI
|
|
||||||
.buildUpon()
|
|
||||||
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
|
||||||
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
|
||||||
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
|
|
||||||
val count = context.contentResolver.delete(rawContactUri, ContactsContract.RawContacts.SYNC2 + " LIKE \"" + id + "\"", null)
|
|
||||||
Log.d("Contact", "deleted $count for id $id")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -354,6 +354,8 @@
|
|||||||
<string name="nc_settings_phone_book_integration_phone_number_dialog_invalid">Invalid phone number</string>
|
<string name="nc_settings_phone_book_integration_phone_number_dialog_invalid">Invalid phone number</string>
|
||||||
<string name="nc_settings_phone_book_integration_phone_number_dialog_success">Phone number set successfully</string>
|
<string name="nc_settings_phone_book_integration_phone_number_dialog_success">Phone number set successfully</string>
|
||||||
<string name="no_phone_book_integration_due_to_permissions">No phone book integration due to missing permissions</string>
|
<string name="no_phone_book_integration_due_to_permissions">No phone book integration due to missing permissions</string>
|
||||||
|
<string name="nc_phone_book_integration_chat_via">Chat via %s</string>
|
||||||
|
<string name="nc_phone_book_integration_account_not_found">Account not found</string>
|
||||||
|
|
||||||
<!-- Non-translatable strings -->
|
<!-- Non-translatable strings -->
|
||||||
<string name="path_password_strike_through" translatable="false"
|
<string name="path_password_strike_through" translatable="false"
|
||||||
|
Loading…
Reference in New Issue
Block a user