Android,联系人合同:存储和检索自定义数据



为了了解androids ContacsContact是如何工作的,我尝试向联系人添加一个自定义条目。经过一整天的阅读文档、教程和观看youtube视频,我在完成这项任务方面仍然没有取得任何进展。

我得到的最接近的是这份文件https://developer.android.com/reference/kotlin/android/provider/ContactsContract.Data正在设置

例如,如果为";最喜欢的歌曲">到谷歌帐户拥有的原始联系人,它将不会同步到服务器,因为谷歌同步适配器不知道如何处理这种数据。因此,新的数据类型通常与新的帐户类型一起引入,即新的同步适配器。

他们写了我正在尝试的内容,但不幸的是,没有提供如何实现这项任务的解决方案。如果有人能提供一个简单的例子,将最喜欢的歌曲的数据行添加到联系人中,并通过代码检索,那将是非常好的。

__

我自己得到的:

一种获取基本联系信息的方法:

import android.content.ContentResolver
import android.database.Cursor
import android.provider.ContactsContract
fun fetchContacts(resolver: ContentResolver) : MutableList<ItemContact> {
var cols = listOf<String>(
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone._ID,
).toTypedArray()
var cursor : Cursor? = resolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
cols, null, null,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
)
var contactsList : MutableList<ItemContact> 
= emptyList<ItemContact>().toMutableList()
if (cursor != null && cursor.count > 0) {
while(cursor.moveToNext()){
contactsList.add(ItemContact(
name = cursor.getString(0),
number = cursor.getString(1),
contact_id = cursor.getString(2),
))
}
}
return contactsList
}

及其对应的数据类

data class ItemContact (
val name: String,
val number: String,
val contact_id: String,
)

根据我目前的理解,我需要向给定的联系人添加一个新的RawContact,代表我的应用程序,并在创建时将最喜欢的歌曲添加为单个数据条目。该RawContact应该能够使用检索到的Contact_id连接到联系人。然后我需要检查,如果联系人存在代表我的应用程序的RawContact,如果存在,我将能够检索存储的歌曲,否则我会在UI中留下占位符文本,仍然需要选择歌曲。不知怎么的,这涉及到一个自定义Mimetype,但我仍然不确定这是什么以及如何创建一个。

首先,让我们回顾一下ContactsContract DB的组织方式:

  1. 联系人表-每个联系人包含一行,但几乎没有任何信息
  2. RawContacts表-可以有多行,每行都分配给一个联系人ID(来自上一个表(,包含一个由多个数据行组成的逻辑组,通常用于单个SyncProvider(如Google(
  3. 数据表-包含RawContact的实际数据,每行都有一个MIMETYPE列,该列说明该行的数据类型(电话、电子邮件、姓名等(+15个数据列来保存信息本身

还有一些伪表,例如您在代码中查询的ContactsContract.CommonDataKinds.Phone,它基本上是在Data表上查询的,但具有特定的MIMETYPE值,例如Phone.CONTENT_ITEM_TYPE

如果您想实现自己的SyncProvider,通常会创建自己的RawContact行,将其添加到现有的Contact_ID中,并使用新的RAW_Contact_ID添加Data行。

然后,当设备上的人员/联系人应用程序想要呈现某个联系人的数据时,他们将获得该联系人的所有RawContacts列表(包括您的联系人(,然后获得所有RawContact的所有数据。

如果你只想向现有联系人添加一小段自定义数据;最喜欢的歌曲";对于联系人,您不必为此创建新的RawContact,相反,您可以创建一个新的Data行,并使用自定义MIMETYPE将其附加到现有的RawContacts,但请记住,您的项目不会同步到谷歌的服务器,但它仍然可以在本地设备上使用。

我想你正在考虑第二个选项,所以这里有一个示例代码(未测试(:

// you need to get a RawContact ID of the contact you want to add info to
fun addFavoriteSong(context: Context, rawContactId: Long) {
val resolver = context.contentResolver
val ops = ArrayList<ContentProviderOperation>()

ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI, true)
.withValue(Data.RAW_CONTACT_ID, rawContactId)
.withValue(Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.example.favorite_song")
.withValue(Data.DATA1, "Paranoid Android")
.withValue(Data.DATA2, "Radiohead")
.withValue(Data.DATA3, "OK Computer")
.build())
try {
val results = resolver.applyBatch(ContactsContract.AUTHORITY, ops)
if (results.isEmpty())
return
} catch (e: Exception) {
e.printStackTrace()
}
Log.i("Songs Added", "success!");
}

然后查询该信息,以及姓名和电话等其他信息:

fun fetchContacts(resolver: ContentResolver) : MutableCollection<ItemContact> {
var cols = arrayOf(
Data.CONTACT_ID,
Data.MIMETYPE,
Data.DISPLAY_NAME,
Phone.NUMBER,
Data.DATA1,
Data.DATA2,
Data.DATA3,
)

// get only rows of MIMETYPE phone and your new custom MIMETYPE
var selection = Data.MIMETYPE + " IN (" + Phone.CONTENT_ITEM_TYPE + ", " + "vnd.android.cursor.item/vnd.com.example.favorite_song" + ")"
var cursor : Cursor? = resolver.query(Data.CONTENT_URI, cols, null, null, Data.CONTACT_ID)
val map = hashMapOf<Long, ItemContact>()

while(cursor != null && cursor.moveToNext()) {
val contactId = cursor.getLong(0)
val mimetype = cursor.getString(1)
// gets the existing ItemContact from the map or if not found, puts an empty one in the map
val contact = map.getOrPut(contactId) { ItemContact() }
with(contact) {
if (mimetype == Phone.CONTENT_ITEM_TYPE) {
contact_id = contactId
name = cursor.getString(2)
number = cursor.getString(3)
} else {
contact_id = contactId
song = cursor.getString(4)
band = cursor.getString(5)
album = cursor.getString(6)
}
}
}
return map.values
}

最新更新