从科特林的Google通讯录中读取生日和姓名

问题描述 投票:0回答:1

我正在开发一个应用来存储有关事件(尤其是生日)的信息。一个有趣的功能是导入在Google通讯录中找到的每个生日,并立即显示它。该应用程序使用Room DB将联系人保留在事件对象中(基本上,事件由名称,姓氏(可选)和出生日期以及一些其他可选参数定义)

由于我对通讯录提供程序有些困惑(不是每个制造商都使用Google通讯录提供程序,对吗?),我发现的每个答案都已经很旧了,并且没有使用Kotlin,所以我想知道如何基本完成此功能(位于我的主要活动中,在这里我可以轻松访问viewmodel和其他所有内容)

  // Import the contacts from Google Contacts
    fun importContacts(): Boolean {
        // No permission. For now, just send an explanation toast
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, getString(R.string.missing_permission), Toast.LENGTH_SHORT).show()
            return false
        }

        // Phase 1: get every contact having at least a name and a birthday
        val contacts = getContacts()

        // Phase 2: convert the extracted data in an Event List, verify duplicates
        val events = mutableListOf<Event>()
        loop@ for (contact in contacts) {
            val splitterName = contact.key.split(",")
            var name: String
            var surname = ""
            var date = LocalDate.of(1970,1,1)
            when (splitterName.size) {
                // Not considering surname only contacts
                1 -> name = splitterName[0].trim()
                2 -> {
                    name = splitterName[1].trim()
                    surname = splitterName[0].trim()
                }
                else -> continue@loop
            }
            try { date = LocalDate.parse(contact.value) }
            catch (e: Exception) { continue }
            val event = Event(id = 0, name = name, surname = surname, originalDate = date)

            // Check if the event is duplicate with a query
            if (!homeViewModel.checkExisting(it.key, it.value) == 0) events.add(event)

        }

        // Phase 3: insert the remaining events in the db
        events.forEach {
            homeViewModel.insert(it)
        }

        return true
    }

    // Get the contacts and save them in a list
    private fun getContacts(): Map<String, String> {
        val nameBirth = mutableMapOf<String, String>()
        val resolver: ContentResolver = contentResolver;
        val cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null)

        if (cursor != null) {
            if (cursor.count > 0) {
                while (cursor.moveToNext()) {
                    val name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_ALTERNATIVE))
                    val birth = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.))
                    nameBirth[name] = "???"
                }
            }
        }
        cursor?.close()
        return nameBirth
    }

尽管我可以轻松地编写第2阶段和第3阶段,但我对处理第一个阶段的最佳方法感到困惑。您可以假设我已经授予了联系人许可权,而我想要的只是我可以用来创建对象的名称,姓氏和日期的列表。


EDIT:所以我根据自己的进度修改了上面的代码。现在,我可以取名字,在名字和姓氏中拆分名字,验证重复项并将联系人插入我的数据库中。剩下的唯一事情就是检索生日并管理可能未指定年份的事实。如您所见,我正在使用LocalDate对象保存日期。

android kotlin import contacts
1个回答
0
投票
// Import the contacts from Google Contacts
fun importContacts(): Boolean {
    // No permission. For now, just send an explanation toast
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        Toast.makeText(this, getString(R.string.missing_permission), Toast.LENGTH_SHORT).show()
        return false
    }

    // Phase 1: get every contact having at least a name and a birthday
    val contacts = getContacts()

    // Phase 2: convert the extracted data in an Event List, verify duplicates
    val events = mutableListOf<Event>()
    loop@ for (contact in contacts) {
        // Take the name and split it to separate name and surname
        val splitterName = contact.value[0].split(",")
        var name: String
        var surname = ""
        var date = LocalDate.of(1970,1,1)
        when (splitterName.size) {
            // Not considering surname only contacts, but considering name only
            1 -> name = splitterName[0].trim()
            2 -> {
                name = splitterName[1].trim()
                surname = splitterName[0].trim()
            }
            else -> continue@loop
        }

        try {
            // Missing year, put 2020 as a placeholder
            var parseDate = contact.value[1]
            if (contact.value[1].length < 8) parseDate = contact.value[1].replaceFirst("-", "2020")
            date = LocalDate.parse(parseDate)
        }
        catch (e: Exception) { continue }
        val event = Event(id = 0, name = name, surname = surname, originalDate = date)

        // The duplicate check is performed at entity level
        events.add(event)
    }

    // Phase 3: insert the remaining events in the db
    events.forEach {
        homeViewModel.insert(it)
    }

    return true
}

// Get the contacts and save them in a map
private fun getContacts(): Map<String, List<String>> {
    val nameBirth = mutableMapOf<String, List<String>>()

    // Retrieve name and id
    val resolver: ContentResolver = contentResolver
    val cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null)
    if (cursor != null) {
        if (cursor.count > 0) {
            while (cursor.moveToNext()) {
                val id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID))
                val name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_ALTERNATIVE))
                // Retrieve the birthday
                val bd = contentResolver
                val bdc: Cursor? = bd.query(ContactsContract.Data.CONTENT_URI, arrayOf(ContactsContract.CommonDataKinds.Event.DATA),
                    ContactsContract.Data.CONTACT_ID + " = " + id + " AND " + ContactsContract.Data.MIMETYPE + " = '" +
                            ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE + "' AND " + ContactsContract.CommonDataKinds.Event.TYPE +
                            " = " + ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY, null, ContactsContract.Data.DISPLAY_NAME
                )

                if (bdc != null) {
                    if (bdc.count > 0) {
                        while (bdc.moveToNext()) {
                            // Using a list as key will prevent collisions on same name
                            val birthday: String = bdc.getString(0)
                            val person = listOf<String>(name, birthday)
                            nameBirth[id] = person
                        }
                    }
                    bdc.close()
                }
            }
        }
    }
    cursor?.close()
    return nameBirth
}

所以这基本上就是我想要的功能。我敢肯定它可以做得更好,但是我在Kotlin中没有特别的参考。它需要联系人,检查其姓名和生日,并管理缺少年份的情况。另外,我只管理“仅名称”的情况,而不是“仅姓氏”的情况。

© www.soinside.com 2019 - 2024. All rights reserved.