summaryrefslogtreecommitdiff
path: root/app/src/main/java/sh/lajo/buddy/ContactsObserver.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/sh/lajo/buddy/ContactsObserver.kt')
-rw-r--r--app/src/main/java/sh/lajo/buddy/ContactsObserver.kt186
1 files changed, 186 insertions, 0 deletions
diff --git a/app/src/main/java/sh/lajo/buddy/ContactsObserver.kt b/app/src/main/java/sh/lajo/buddy/ContactsObserver.kt
new file mode 100644
index 0000000..50b7a48
--- /dev/null
+++ b/app/src/main/java/sh/lajo/buddy/ContactsObserver.kt
@@ -0,0 +1,186 @@
+package sh.lajo.buddy
+
+import android.Manifest
+import android.content.ContentResolver
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.database.ContentObserver
+import android.net.Uri
+import android.os.Handler
+import android.os.Looper
+import android.provider.ContactsContract
+import android.util.Log
+import androidx.core.content.ContextCompat
+
+class ContactsObserver(
+ private val context: Context,
+ private val contentResolver: ContentResolver
+) : ContentObserver(Handler(Looper.getMainLooper())) {
+
+ companion object {
+ private const val TAG = "ContactsObserver"
+ }
+
+ private var lastContactCount = -1
+
+ init {
+ // Initialize the contact count
+ lastContactCount = getContactCount()
+ }
+
+ override fun onChange(selfChange: Boolean) {
+ onChange(selfChange, null)
+ }
+
+ override fun onChange(selfChange: Boolean, uri: Uri?) {
+
+ // Check if we have READ_CONTACTS permission
+ if (ContextCompat.checkSelfPermission(
+ context,
+ Manifest.permission.READ_CONTACTS
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ Log.w(TAG, "No READ_CONTACTS permission, skipping contact change")
+ return
+ }
+
+ Log.d(TAG, "Contact change detected, URI: $uri")
+
+ // Get current contact count
+ val currentCount = getContactCount()
+
+ // If count increased, a contact was likely added
+ if (lastContactCount >= 0 && currentCount > lastContactCount) {
+ Log.d(TAG, "Contact added detected (count: $lastContactCount -> $currentCount)")
+ // Find and send the new contact(s)
+ findAndSendNewContacts()
+ }
+
+ lastContactCount = currentCount
+ }
+
+ private fun getContactCount(): Int {
+ try {
+ val cursor = contentResolver.query(
+ ContactsContract.Contacts.CONTENT_URI,
+ arrayOf(ContactsContract.Contacts._ID),
+ null,
+ null,
+ null
+ )
+ cursor?.use {
+ return it.count
+ }
+ } catch (e: Exception) {
+ Log.e(TAG, "Error getting contact count", e)
+ }
+ return 0
+ }
+
+ private fun findAndSendNewContacts() {
+ try {
+ // Query the most recently added contacts
+ val cursor = contentResolver.query(
+ ContactsContract.Contacts.CONTENT_URI,
+ arrayOf(
+ ContactsContract.Contacts._ID,
+ ContactsContract.Contacts.DISPLAY_NAME
+ ),
+ null,
+ null,
+ "${ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP} DESC"
+ )
+
+ cursor?.use {
+ if (it.moveToFirst()) {
+ // Get the most recent contact
+ val contactId = it.getString(it.getColumnIndexOrThrow(ContactsContract.Contacts._ID))
+ val name = it.getString(it.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME))
+
+ val phoneNumbers = getPhoneNumbers(contactId)
+ val emails = getEmails(contactId)
+
+ // Send the contact info via WebSocket
+ sendContactAddedEvent(name, phoneNumbers, emails)
+ }
+ }
+ } catch (e: Exception) {
+ Log.e(TAG, "Error finding new contacts", e)
+ }
+ }
+
+ private fun getPhoneNumbers(contactId: String): List<String> {
+ val phoneNumbers = mutableListOf<String>()
+ try {
+ val cursor = contentResolver.query(
+ ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
+ arrayOf(ContactsContract.CommonDataKinds.Phone.NUMBER),
+ "${ContactsContract.CommonDataKinds.Phone.CONTACT_ID} = ?",
+ arrayOf(contactId),
+ null
+ )
+
+ cursor?.use {
+ while (it.moveToNext()) {
+ val number = it.getString(it.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER))
+ phoneNumbers.add(number)
+ }
+ }
+ } catch (e: Exception) {
+ Log.e(TAG, "Error getting phone numbers", e)
+ }
+ return phoneNumbers
+ }
+
+ private fun getEmails(contactId: String): List<String> {
+ val emails = mutableListOf<String>()
+ try {
+ val cursor = contentResolver.query(
+ ContactsContract.CommonDataKinds.Email.CONTENT_URI,
+ arrayOf(ContactsContract.CommonDataKinds.Email.ADDRESS),
+ "${ContactsContract.CommonDataKinds.Email.CONTACT_ID} = ?",
+ arrayOf(contactId),
+ null
+ )
+
+ cursor?.use {
+ while (it.moveToNext()) {
+ val email = it.getString(it.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Email.ADDRESS))
+ emails.add(email)
+ }
+ }
+ } catch (e: Exception) {
+ Log.e(TAG, "Error getting emails", e)
+ }
+ return emails
+ }
+
+ private fun sendContactAddedEvent(name: String, phoneNumbers: List<String>, emails: List<String>) {
+ Log.d(TAG, "Sending contact added event: $name, phones: $phoneNumbers, emails: $emails")
+
+ val intent = Intent(context, WebSocketService::class.java).apply {
+ action = WebSocketService.ACTION_SEND_CONTACT
+ putExtra(WebSocketService.EXTRA_CONTACT_NAME, name)
+ putExtra(WebSocketService.EXTRA_CONTACT_PHONES, phoneNumbers.toTypedArray())
+ putExtra(WebSocketService.EXTRA_CONTACT_EMAILS, emails.toTypedArray())
+ }
+
+ context.startForegroundService(intent)
+ }
+
+ fun register() {
+ contentResolver.registerContentObserver(
+ ContactsContract.Contacts.CONTENT_URI,
+ true,
+ this
+ )
+ Log.d(TAG, "ContactsObserver registered")
+ }
+
+ fun unregister() {
+ contentResolver.unregisterContentObserver(this)
+ Log.d(TAG, "ContactsObserver unregistered")
+ }
+}
+