日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android官方文档—APP组件(Content Providers)(Contacts Provider)

發(fā)布時間:2023/12/14 Android 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android官方文档—APP组件(Content Providers)(Contacts Provider) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

通訊錄內(nèi)容提供者

Contacts Provider是一個功能強大且靈活的Android組件,用于管理設備的人員數(shù)據(jù)中??央存儲庫。聯(lián)系人提供程序是您在設備的聯(lián)系人應用程序中看到的數(shù)據(jù)源,您還可以在自己的應用程序中訪問其數(shù)據(jù),并在設備和在線服務之間傳輸數(shù)據(jù)。提供商可以容納各種數(shù)據(jù)源,并嘗試為每個人管理盡可能多的數(shù)據(jù),結果是組織結構復雜。因此,提供者的API包括一組廣泛的合同類和接口,便于數(shù)據(jù)檢索和修改。

本指南介紹以下內(nèi)容:

  • 基本的提供者結構。
  • 如何從提供程序檢索數(shù)據(jù)。
  • 如何修改提供程序中的數(shù)據(jù)。
  • 如何編寫同步適配器以將數(shù)據(jù)從服務器同步到Contacts Provider。

本指南假設您了解Android內(nèi)容提供商的基礎知識。要了解有關Android內(nèi)容提供商的更多信息,請閱讀內(nèi)容提供商基礎知識指南。 Sample Sync Adapter示例應用程序是使用同步適配器在Contacts Provider和Google Web Services托管的示例應用程序之間傳輸數(shù)據(jù)的示例。

通訊錄供應商架構


Contacts Provider是Android內(nèi)容提供商組件。它維護有關一個人的三種類型的數(shù)據(jù),每種數(shù)據(jù)對應于提供者提供的表,如圖1所示:

圖1. Contacts Provider表結構。

這三個表通常用其合同類的名稱來表示。這些類定義了表使用的內(nèi)容URI,列名和列值的常量:

ContactsContract.Contacts表

代表不同人的行,基于原始聯(lián)系行的聚合。

ContactsContract.RawContacts表

包含人員數(shù)據(jù)摘要的行,特定于用戶帳戶和類型。

ContactsContract.Data表

行包含原始聯(lián)系人的詳細信息,例如電子郵件地址或電話號碼。

ContactsContract中由合同類表示的其他表是Contacts Provider用于管理其操作或支持設備的聯(lián)系人或電話應用程序中的特定功能的輔助表。

原始聯(lián)系人


原始聯(lián)系人表示來自單個帳戶類型和帳戶名稱的人員數(shù)據(jù)。由于聯(lián)系人提供程序允許多個聯(lián)機服務作為人員的數(shù)據(jù)源,因此聯(lián)系人提供程序允許同一個人使用多個原始聯(lián)系人。多個原始聯(lián)系人還允許用戶組合來自同一帳戶類型的多個帳戶的人員數(shù)據(jù)。

原始聯(lián)系人的大多數(shù)數(shù)據(jù)不存儲在ContactsContract.RawContacts表中。相反,它存儲在ContactsContract.Data表中的一行或多行中。每個數(shù)據(jù)行都有一列Data.RAW_CONTACT_ID,其中包含其父ContactsContract.RawContacts行的RawContacts._ID值。

重要的原始數(shù)據(jù)列

ContactsContract.RawContacts表中的重要列列在表1中。請閱讀表后面的注釋:

表1.重要的原始接觸列。

列名用法備注
ACCOUNT_NAME作為此原始聯(lián)系人來源的帳戶類型的帳戶名稱。例如,Google帳戶的帳戶名稱是設備所有者的Gmail地址之一。有關詳細信息,請參閱ACCOUNT_TYPE的下一個條目。此名稱的格式特定于其帳戶類型。它不一定是電子郵件地址。
ACCOUNT_TYPE作為此原始聯(lián)系人來源的帳戶類型。例如,Google帳戶的帳戶類型是com.google。始終使用您擁有或控制的域的域標識符限定您的帳戶類型。這將確保您的帳戶類型是唯一的。提供聯(lián)系人數(shù)據(jù)的帳戶類型通常具有與聯(lián)系人提供程序同步的關聯(lián)同步適配器。
DELETED原始聯(lián)系人的“已刪除”標志。此標志允許聯(lián)系人提供程序在內(nèi)部維護該行,直到同步適配器能夠從其服務器中刪除該行,然后最終從存儲庫中刪除該行。

注意

以下是有關ContactsContract.RawContacts表的重要說明:

  • 原始聯(lián)系人的姓名未存儲在ContactsContract.RawContacts的行中。相反,它存儲在ContactsContract.CommonDataKinds.StructuredName行的ContactsContract.Data表中。原始聯(lián)系人在ContactsContract.Data表中只有一行此類型。
  • 警告:要在原始聯(lián)系人行中使用您自己的帳戶數(shù)據(jù),必須先在AccountManager中注冊。為此,請?zhí)崾居脩魧纛愋图捌鋷裘Q添加到帳戶列表中。如果您不這樣做,聯(lián)系人提供程序將自動刪除您的原始聯(lián)系人行。

例如,如果您希望自己的應用使用域com.example.dataservice維護基于Web的服務的聯(lián)系人數(shù)據(jù),并且用戶的服務帳戶是becky.sharp@dataservice.example.com,則用戶必須先添加在您的應用添加原始聯(lián)系人行之前,帳戶“type”(com.example.dataservice)和帳戶“name”(becky.smart@dataservice.example.com)。您可以在文檔中向用戶解釋此要求,也可以提示用戶添加類型和名稱,或兩者都添加。帳戶類型和帳戶名稱將在下一節(jié)中詳細介紹。

原始聯(lián)系人數(shù)據(jù)的來源

要了解原始聯(lián)系人的工作原理,請考慮在其設備上定義了以下三個用戶帳戶的用戶“Emily Dickinson”:

  • emily.dickinson@gmail.com
  • emilyd@gmail.com
  • Twitter account "belle_of_amherst"

此用戶已在“帳戶”設置中為所有這三個帳戶啟用了“同步聯(lián)系人”。

假設Emily Dickinson打開瀏覽器窗口,以emily.dickinson@gmail.com登錄Gmail,打開聯(lián)系人,并添加“Thomas Higginson”。稍后,她以emilyd@gmail.com身份登錄Gmail,并向“Thomas Higginson”發(fā)送電子郵件,自動將其添加為聯(lián)系人。她還在Twitter上關注“colonel_tom”(Thomas Higginson的Twitter ID)。

由于這項工作,Contacts Provider會創(chuàng)建三個原始聯(lián)系人:

  • “Thomas Higginson”的原始聯(lián)系人與emily.dickinson@gmail.com相關聯(lián)。用戶帳戶類型為Google。
  • “Thomas Higginson”的第二個原始聯(lián)系人與emilyd@gmail.com相關聯(lián)。用戶帳戶類型也是Google。即使名稱與以前的名稱相同,也存在第二個原始聯(lián)系人,因為該人員是為其他用戶帳戶添加的。
  • ?與“belle_of_amherst”相關的“Thomas Higginson”的第三個原始聯(lián)系人。用戶帳戶類型是Twitter。
  • 數(shù)據(jù)


    如前所述,原始聯(lián)系人的數(shù)據(jù)存儲在ContactsContract.Data行中,該行鏈接到原始聯(lián)系人的_ID值。這允許單個原始聯(lián)系人具有相同類型數(shù)據(jù)的多個實例,例如電子郵件地址或電話號碼。例如,如果emilyd@gmail.com的“Thomas Higginson”(Thomas Higginson的原始聯(lián)系人行與Google帳戶emilyd@gmail.com相關聯(lián))的家庭電子郵件地址為thigg@gmail.com,工作電子郵件地址為thomas.higginson@gmail.com,Contacts Provider存儲兩個電子郵件地址行,并將它們鏈接到原始聯(lián)系人。

    請注意,此單個表中存儲了不同類型的數(shù)據(jù)。顯示名稱,電話號碼,電子郵件,郵政地址,照片和網(wǎng)站詳細信息行均可在ContactsContract.Data表中找到。為了幫助管理它,ContactsContract.Data表包含一些具有描述性名稱的列,以及具有通用名稱的其他列。無論行中的數(shù)據(jù)類型如何,描述性名稱列的內(nèi)容都具有相同的含義,而通用名稱列的內(nèi)容根據(jù)數(shù)據(jù)類型具有不同的含義。

    描述性列名

    描述性列名的一些示例是:

    RAW_CONTACT_ID

    此數(shù)據(jù)的原始聯(lián)系人的_ID列的值。

    MIMETYPE

    存儲在此行中的數(shù)據(jù)類型,表示為自定義MIME類型。 Contacts Provider使用ContactsContract.CommonDataKinds子類中定義的MIME類型。這些MIME類型是開源的,可以與任何與Contacts Provider一起使用的應用程序或同步適配器使用。

    IS_PRIMARY

    如果原始聯(lián)系人可以多次出現(xiàn)此類數(shù)據(jù)行,則IS_PRIMARY列會標記包含該類型主數(shù)據(jù)的數(shù)據(jù)行。例如,如果用戶長按聯(lián)系人的電話號碼并選擇“設置默認值”,則包含該號碼的ContactsContract.Data行將其IS_PRIMARY列設置為非零值。

    通用列名稱

    有15個名為DATA1到DATA15的通用列通常可用,還有另外四個通用列SYNC1到SYNC4,它們只能由同步適配器使用。無論行包含哪種數(shù)據(jù)類型,通用列名常量始終有效。

    DATA1列已編制索引。聯(lián)系人提供程序始終將此列用于提供程序期望的數(shù)據(jù),該數(shù)據(jù)將是查詢的最常見目標。例如,在電子郵件行中,此列包含實際的電子郵件地址。

    按照慣例,列DATA15被保留用于存儲二進制大對象(BLOB)數(shù)據(jù),例如照片縮略圖。

    特定于類型的列名稱

    為了便于使用特定類型行的列,Contacts Provider還提供了在ContactsContract.CommonDataKinds的子類中定義的特定于類型的列名常量。常量只是為同一列名提供不同的常量名稱,這有助于您訪問特定類型的行中的數(shù)據(jù)。

    例如,ContactsContract.CommonDataKinds.Email類為ContactsContract.Data行定義類型特定的列名常量,該行具有MIME類型Email.CONTENT_ITEM_TYPE。該類包含電子郵件地址列的常量ADDRESS。 ADDRESS的實際值是“data1”,它與列的通用名稱相同。

    警告:不要使用具有提供程序的預定義MIME類型之一的行將自己的自定義數(shù)據(jù)添加到ContactsContract.Data表。如果這樣做,您可能會丟失數(shù)據(jù)或導致提供商出現(xiàn)故障。例如,您不應在DATA1列中添加包含用戶名而不是電子郵件地址的MIME類型Email.CONTENT_ITEM_TYPE的行。如果您對該行使用自己的自定義MIME類型,則可以自由定義自己的特定于類型的列名稱,并根據(jù)需要使用列。

    圖2顯示了描述性列和數(shù)據(jù)列在ContactsContract.Data行中的顯示方式,以及特定于類型的列名稱如何“覆蓋”通用列名稱。

    圖2.特定于類型的列名和通用列名。

    特定于類型的列名稱類

    表2列出了最常用的特定于類型的列名類:

    表2.特定于類型的列名類

    映射類數(shù)據(jù)類型備注
    ContactsContract.CommonDataKinds.StructuredName與此數(shù)據(jù)行關聯(lián)的原始聯(lián)系人的名稱數(shù)據(jù)。原始聯(lián)系人只有這些行中的一行。
    ContactsContract.CommonDataKinds.Photo與此數(shù)據(jù)行關聯(lián)的原始聯(lián)系人的主照片。原始聯(lián)系人只有這些行中的一行。
    ContactsContract.CommonDataKinds.Email與此數(shù)據(jù)行關聯(lián)的原始聯(lián)系人的電子郵件地址。原始聯(lián)系人可以有多個電子郵件地址。
    ContactsContract.CommonDataKinds.StructuredPostal與此數(shù)據(jù)行關聯(lián)的原始聯(lián)系人的郵政地址。原始聯(lián)系人可以有多個郵政地址。
    ContactsContract.CommonDataKinds.GroupMembership將原始聯(lián)系人鏈接到“聯(lián)系人”提供程序中的一個組的標識符。組是帳戶類型和帳戶名稱的可選功能。它們在聯(lián)系人組部分中有更詳細的描述。

    通訊錄

    聯(lián)系人提供商將所有帳戶類型和帳戶名稱中的原始聯(lián)系人行組合在一起以形成聯(lián)系人。這有助于顯示和修改用戶為人收集的所有數(shù)據(jù)。聯(lián)系人提供程序管理新聯(lián)系人行的創(chuàng)建,以及原始聯(lián)系人與現(xiàn)有聯(lián)系人行的聚合。應用程序和同步適配器都不允許添加聯(lián)系人,聯(lián)系行中的某些列是只讀的。

    注意:如果您嘗試使用insert()將聯(lián)系人添加到Contacts Provider,則會收到UnsupportedOperationException異常。如果您嘗試更新列為“只讀”的列,則忽略更新。

    聯(lián)系人提供商創(chuàng)建新聯(lián)系人以響應添加與任何現(xiàn)有聯(lián)系人不匹配的新原始聯(lián)系人。如果現(xiàn)有原始聯(lián)系人的數(shù)據(jù)以不再與之前附加的聯(lián)系人匹配的方式更改,則提供程序也會執(zhí)行此操作。如果應用程序或同步適配器創(chuàng)建與現(xiàn)有聯(lián)系人匹配的新原始聯(lián)系人,則新的原始聯(lián)系人將聚合到現(xiàn)有聯(lián)系人。

    “聯(lián)系人”提供程序將聯(lián)系人行與其原始聯(lián)系人行鏈接,并在“聯(lián)系人”表中將聯(lián)系人行的_ID列鏈接。原始聯(lián)系人表ContactsContract.RawContacts的CONTACT_ID列包含與每個原始聯(lián)系人行關聯(lián)的聯(lián)系人行的_ID值。

    ContactsContract.Contacts表還有LOOKUP_KEY列,它是聯(lián)系行的“永久”鏈接。由于聯(lián)系人提供程序會自動維護聯(lián)系人,因此可能會更改聯(lián)系人行的_ID值以響應聚合或同步。即使發(fā)生這種情況,內(nèi)容URI CONTENT_LOOKUP_URI結合聯(lián)系人的LOOKUP_KEY仍將指向聯(lián)系人行,因此您可以使用LOOKUP_KEY維護指向“最喜歡”聯(lián)系人的鏈接,依此類推。此列具有自己的格式,與_ID列的格式無關。

    圖3顯示了三個主要表格如何相互關聯(lián)。

    圖3. Contacts,Raw Contacts和Details表關系。

    來自同步適配器的數(shù)據(jù)


    用戶將聯(lián)系人數(shù)據(jù)直接輸入設備,但數(shù)據(jù)也通過同步適配器從Web服務流入聯(lián)系人提供程序,這樣可以自動在設備和服務之間傳輸數(shù)據(jù)。同步適配器在系統(tǒng)的控制下在后臺運行,并且它們調(diào)用ContentResolver方法來管理數(shù)據(jù)。

    在Android中,同步適配器使用的Web服務由帳戶類型標識。每個同步適配器使用一種帳戶類型,但它可以支持該類型的多個帳戶名稱。帳戶類型和帳戶名稱在原始聯(lián)系人數(shù)據(jù)源中簡要描述。以下定義提供了更多詳細信息,并描述了帳戶類型和名稱與同步適配器和服務的關系。

    帳戶類型

    標識用戶已存儲數(shù)據(jù)的服務。大多數(shù)情況下,用戶必須使用該服務進行身份驗證。例如,Google通訊錄是一種帳戶類型,由代碼google.com標識。此值對應于AccountManager使用的帳戶類型。

    用戶名

    標識帳戶類型的特定帳戶或登錄。 Google通訊錄帳戶與Google帳戶相同,后者的電子郵件地址為帳戶名稱。其他服務可能使用單字用戶名或數(shù)字ID。

    帳戶類型不必是唯一的。用戶可以配置多個Google通訊錄帳戶并將其數(shù)據(jù)下載到聯(lián)系人提供商;如果用戶有一組個人帳戶名稱的個人聯(lián)系人,另一組用于工作,則可能發(fā)生這種情況。帳戶名稱通常是唯一的。它們共同確定了聯(lián)系人提供者和外部服務之間的特定數(shù)據(jù)流。

    如果要將服務的數(shù)據(jù)傳輸?shù)紺ontacts Provider,則需要編寫自己的同步適配器。 “聯(lián)系人提供程序同步適配器”一節(jié)中對此進行了更詳細的描述。

    圖4顯示了Contacts Provider如何適應人員數(shù)據(jù)流。在標有“同步適配器”的框中,每個適配器都標有其帳戶類型。

    圖4. Contacts Provider數(shù)據(jù)流。

    必需的權限


    想要訪問聯(lián)系人提供程序的應用程序必須請求以下權限:

    對一個或多個表的讀訪問權限

    READ_CONTACTS,在AndroidManifest.xml中指定,<uses-permission>元素為<uses-permission android:name =“android.permission.READ_CONTACTS”>。

    對一個或多個表的寫訪問權

    WRITE_CONTACTS,在AndroidManifest.xml中指定,<uses-permission>元素為<uses-permission android:name =“android.permission.WRITE_CONTACTS”>。

    這些權限不會擴展到用戶配置文件數(shù)據(jù)。用戶配置文件及其所需權限將在下一節(jié)“用戶配置文件”中討論。

    請記住,用戶的聯(lián)系人數(shù)據(jù)是個人且敏感的。用戶擔心他們的隱私,因此他們不希望應用程序收集有關他們或他們的聯(lián)系人的數(shù)據(jù)。如果您需要獲得訪問其聯(lián)系人數(shù)據(jù)的權限并不明顯,則可能會使您的應用程序評級較低,或者只是拒絕安裝它。

    用戶檔案


    ContactsContract.Contacts表有一行包含設備用戶的配置文件數(shù)據(jù)。此數(shù)據(jù)描述設備的用戶而不是用戶的一個聯(lián)系人。配置文件聯(lián)系人行鏈接到使用配置文件的每個系統(tǒng)的原始聯(lián)系人行。每個配置文件原始聯(lián)系人行可以有多個數(shù)據(jù)行。 ContactsContract.Profile類中提供了用于訪問用戶配置文件的常量。

    訪問用戶配置文件需要特殊權限。除了讀取和寫入所需的READ_CONTACTS和WRITE_CONTACTS權限之外,訪問用戶配置文件還需要分別使用android.Manifest.permission#READ_PROFILE和android.Manifest.permission#WRITE_PROFILE權限進行讀寫訪問。

    請記住,您應該認為用戶的個人資料是敏感的。權限android.Manifest.permission#READ_PROFILE允許您訪問設備用戶的個人識別數(shù)據(jù)。請務必告訴用戶您在應用程序說明中需要用戶配置文件訪問權限的原因。

    要檢索包含用戶配置文件的聯(lián)系人行,請調(diào)用ContentResolver.query()。將內(nèi)容URI設置為CONTENT_URI,不提供任何選擇條件。您還可以使用此內(nèi)容URI作為基本URI,以檢索配置文件的原始聯(lián)系人或數(shù)據(jù)。例如,此代碼段檢索配置文件的數(shù)據(jù):

    // Sets the columns to retrieve for the user profile mProjection = new String[]{Profile._ID,Profile.DISPLAY_NAME_PRIMARY,Profile.LOOKUP_KEY,Profile.PHOTO_THUMBNAIL_URI};// Retrieves the profile from the Contacts Provider mProfileCursor =getContentResolver().query(Profile.CONTENT_URI,mProjection ,null,null,null);

    注意:如果檢索多個聯(lián)系行,并且要確定其中一個是否為用戶配置文件,請測試該行的IS_USER_PROFILE列。如果聯(lián)系人是用戶配置文件,則此列設置為“1”。

    聯(lián)系人提供商元數(shù)據(jù)


    聯(lián)系人提供程序管理跟蹤存儲庫中聯(lián)系人數(shù)據(jù)狀態(tài)的數(shù)據(jù)。有關存儲庫的此元數(shù)據(jù)存儲在各種位置,包括Raw Contacts,Data和Contacts表行,ContactsContract.Settings表和ContactsContract.SyncState表。下表顯示了每個元數(shù)據(jù)的效果:

    表3. Contacts Provider中的元數(shù)據(jù)

    意義
    ContactsContract.RawContactsDIRTY“0” - 自上次同步后未更改。標記在設備上更改的原始聯(lián)系人,并且必須同步回服務器。當Android應用程序更新行時,聯(lián)系人提供程序會自動設置該值。
    “1” - 自上次同步后更改,需要同步回服務器。修改原始聯(lián)系人或數(shù)據(jù)表的同步適配器應始終將字符串CALLER_IS_SYNCADAPTER附加到他們使用的內(nèi)容URI。這可以防止提供程序將行標記為臟。否則,同步適配器修改似乎是本地修改并發(fā)送到服務器,即使服務器是修改的源。
    ContactsContract.RawContactsVERSION此行的版本號。每當行或其相關數(shù)據(jù)發(fā)生更改時,Contacts Provider會自動遞增此值。
    ContactsContract.DataDATA_VERSION此行的版本號。每當更改數(shù)據(jù)行時,Contacts Provider都會自動遞增此值。
    ContactsContract.RawContactsSOURCE_ID一個字符串值,用于唯一標識與創(chuàng)建該聯(lián)系人的帳戶的原始聯(lián)系人。

    當同步適配器創(chuàng)建新的原始聯(lián)系人時,應將此列設置為服務器的原始聯(lián)系人的唯一ID。當Android應用程序創(chuàng)建新的原始聯(lián)系人時,應用程序應將此列留空。這表示同步適配器應在服務器上創(chuàng)建新的原始聯(lián)系人,并獲取SOURCE_ID的值。

    特別是,每個帳戶類型的源ID必須是唯一的,并且應該在同步中保持穩(wěn)定:

    • 唯一:帳戶的每個原始聯(lián)系人都必須擁有自己的源ID。如果您不強制執(zhí)行此操作,則會導致聯(lián)系人應用程序出現(xiàn)問題。請注意,同一帳戶類型的兩個原始聯(lián)系人可能具有相同的源ID。例如,帳戶emily.dickinson@gmail.com的原始聯(lián)系人“Thomas Higginson”被允許與帳戶emilyd@gmail.com的原始聯(lián)系人“Thomas Higginson”具有相同的源ID。
    • 穩(wěn)定:源ID是原始聯(lián)系人在線服務數(shù)據(jù)的永久部分。例如,如果用戶從“應用程序”設置中清除“聯(lián)系人存儲”并重新同步,則還原的原始聯(lián)系人應具有與以前相同的源ID。如果您不強制執(zhí)行此操作,快捷方式將停止工作。
    ContactsContract.GroupsGROUP_VISIBLE“0” - 此組中的聯(lián)系人不應在Android應用程序UI中可見。此列用于與允許用戶隱藏特定組中的聯(lián)系人的服務器兼容。
    “1” - 允許在應用程序UI中顯示該組中的聯(lián)系人。?
    ContactsContract.SettingsUNGROUPED_VISIBLE“0” - 對于此帳戶和帳戶類型,不屬于某個組的聯(lián)系人對Android應用程序UI不可見。默認情況下,如果聯(lián)系人的原始聯(lián)系人都不屬于某個組,則聯(lián)系人不可見(原始聯(lián)系人的組成員身份由ContactsContract.Data表中的一個或多個ContactsContract.CommonDataKinds.GroupMembership行指示)。通過在ContactsContract.Settings表行中為帳戶類型和帳戶設置此標志,可以強制不顯示組的聯(lián)系人。此標志的一個用途是顯示不使用組的服務器的聯(lián)系人。
    “1” - 對于此帳戶和帳戶類型,應用程序UI可以看到不屬于某個組的聯(lián)系人。?
    ContactsContract.SyncState(all)使用此表存儲同步適配器的元數(shù)據(jù)。使用此表,您可以在設備上持久存儲同步狀態(tài)和其他與同步相關的數(shù)據(jù)。

    聯(lián)系提供者訪問


    本節(jié)介紹從“聯(lián)系人提供程序”訪問數(shù)據(jù)的準則,重點介紹以下內(nèi)容:

    • 實體查詢。
    • 批量修改。
    • 使用意圖進行檢索和修改。
    • 數(shù)據(jù)的完整性。

    “聯(lián)系人提供程序同步適配器”一節(jié)中還詳細介紹了如何從同步適配器進行修改。

    查詢實體

    由于Contacts Provider表是按層次結構組織的,因此檢索行和鏈接到它的所有“子”行通常很有用。例如,要顯示人員的所有信息,您可能需要檢索單個ContactsContract.Contacts行的所有ContactsContract.RawContacts行,或單個ContactsContract.RawContacts行的所有ContactsContract.CommonDataKinds.Email行。為此,Contacts Provider提供實體構造,其作用類似于表之間的數(shù)據(jù)庫連接。

    實體就像一個由父表及其子表中的選定列組成的表。查詢實體時,您將根據(jù)實體中可用的列提供投影和搜索條件。結果是包含的Cursor包含檢索到的每個子表行的一行。例如,如果查詢ContactsContract.Contacts.Entity以獲取該名稱的所有原始聯(lián)系人的聯(lián)系人姓名和所有ContactsContract.CommonDataKinds.Email行,則會返回一個Cursor,其中包含每行ContactsContract.CommonDataKinds.Email行的一行。

    實體簡化了查詢。使用實體,您可以立即檢索聯(lián)系人或原始聯(lián)系人的所有聯(lián)系人數(shù)據(jù),而不必首先查詢父表以獲取ID,然后必須使用該ID查詢子表。此外,聯(lián)系人提供程序在單個事務中處理針對實體的查詢,這確保檢索到的數(shù)據(jù)在內(nèi)部是一致的。

    注意:實體通常不包含父表和子表的所有列。如果您嘗試使用不在實體的列名常量列表中的列名,您將獲得異常。

    以下代碼段顯示了如何檢索聯(lián)系人的所有原始聯(lián)系人行。該代碼段是一個較大的應用程序的一部分,它有兩個活動,“主要”和“細節(jié)”。主要活動顯示聯(lián)系人行列表;當用戶選擇一個時,活動將其ID發(fā)送到詳細活動。詳細信息活動使用ContactsContract.Contacts.Entity顯示與所選聯(lián)系人關聯(lián)的所有原始聯(lián)系人的所有數(shù)據(jù)行。

    此代碼段取自“詳細信息”activity:

    .../** Appends the entity path to the URI. In the case of the Contacts Provider, the* expected URI is content://com.google.contacts/#/entity (# is the ID value).*/mContactUri = Uri.withAppendedPath(mContactUri,ContactsContract.Contacts.Entity.CONTENT_DIRECTORY);// Initializes the loader identified by LOADER_ID.getLoaderManager().initLoader(LOADER_ID, // The identifier of the loader to initializenull, // Arguments for the loader (in this case, none)this); // The context of the activity// Creates a new cursor adapter to attach to the list viewmCursorAdapter = new SimpleCursorAdapter(this, // the context of the activityR.layout.detail_list_item, // the view item containing the detail widgetsmCursor, // the backing cursormFromColumns, // the columns in the cursor that provide the datamToViews, // the views in the view item that display the data0); // flags// Sets the ListView's backing adapter.mRawContactList.setAdapter(mCursorAdapter); ... @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) {/** Sets the columns to retrieve.* RAW_CONTACT_ID is included to identify the raw contact associated with the data row.* DATA1 contains the first column in the data row (usually the most important one).* MIMETYPE indicates the type of data in the data row.*/String[] projection ={ContactsContract.Contacts.Entity.RAW_CONTACT_ID,ContactsContract.Contacts.Entity.DATA1,ContactsContract.Contacts.Entity.MIMETYPE};/** Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw* contact collated together.*/String sortOrder =ContactsContract.Contacts.Entity.RAW_CONTACT_ID +" ASC";/** Returns a new CursorLoader. The arguments are similar to* ContentResolver.query(), except for the Context argument, which supplies the location of* the ContentResolver to use.*/return new CursorLoader(getApplicationContext(), // The activity's contextmContactUri, // The entity content URI for a single contactprojection, // The columns to retrievenull, // Retrieve all the raw contacts and their data rows.null, //sortOrder); // Sort by the raw contact ID. }

    加載完成后,LoaderManager調(diào)用onLoadFinished()的回調(diào)。此方法的一個傳入?yún)?shù)是帶有查詢結果的Cursor。在您自己的應用程序中,您可以從此Cursor獲取數(shù)據(jù)以顯示它或進一步使用它。

    批量修改

    只要有可能,您應該通過創(chuàng)建ContentProviderOperation對象的ArrayList并調(diào)用applyBatch(),以“批處理模式”在Contacts Provider中插入,更新和刪除數(shù)據(jù)。由于Contacts Provider在單個事務中執(zhí)行applyBatch()中的所有操作,因此您的修改永遠不會使聯(lián)系人存儲庫處于不一致狀態(tài)。批量修改還有助于同時插入原始聯(lián)系人及其詳細數(shù)據(jù)。

    注意:要修改單個原始聯(lián)系人,請考慮向設備的聯(lián)系人應用程序發(fā)送意圖,而不是在應用程序中處理修改。在使用意圖檢索和修改一節(jié)中更詳細地描述了這樣做。

    屈服點

    包含大量操作的批量修改可能會阻止其他進程,從而導致整體用戶體驗不佳。要在盡可能少的單獨列表中組織要執(zhí)行的所有修改,同時防止它們阻止系統(tǒng),您應該為一個或多個操作設置屈服點。屈服點是ContentProviderOperation對象,其isYieldAllowed()值設置為true。當聯(lián)系人提供程序遇到屈服點時,它會暫停其工作以讓其他進程運行并關閉當前事務。當提供程序再次啟動時,它將繼續(xù)執(zhí)行ArrayList中的下一個操作并啟動新事務。

    服點確實會導致每次調(diào)用applyBatch()時有多個事務。因此,您應為一組相關行的最后一個操作設置屈服點。例如,您應該為添加原始聯(lián)系人行及其關聯(lián)數(shù)據(jù)行的集合中的最后一個操作設置屈服點,或者為與單個聯(lián)系人相關的一組行設置最后一個操作。

    屈服點也是原子操作的單位。兩個屈服點之間的所有訪問將作為單個單元成功或失敗。如果未設置任何屈服點,則最小的原子操作是整批操作。如果使用屈服點,則可以防止操作降低系統(tǒng)性能,同時確保操作子集是原子的。

    修改后引用

    當您將新的原始聯(lián)系人行及其關聯(lián)的數(shù)據(jù)行作為一組ContentProviderOperation對象插入時,必須通過將原始聯(lián)系人的_ID值作為RAW_CONTACT_ID值插入,將數(shù)據(jù)行鏈接到原始聯(lián)系人行。但是,當您為數(shù)據(jù)行創(chuàng)建ContentProviderOperation時,此值不可用,因為您尚未為原始聯(lián)系人行應用ContentProviderOperation。要解決此問題,ContentProviderOperation.Builder類具有withValueBackReference()方法。此方法允許您插入或修改具有上一操作結果的列。

    withValueBackReference()方法有兩個參數(shù):

    key

    鍵值對的關鍵。此參數(shù)的值應該是您正在修改的表中列的名稱。

    previousResult

    來自applyBatch()的ContentProviderResult對象數(shù)組中的值的從0開始的索引。在應用批處理操作時,每個操作的結果都存儲在一個中間結果數(shù)組中。 previousResult值是這些結果之一的索引,使用鍵值檢索和存儲。這允許您插入新的原始聯(lián)系人記錄并獲取其_ID值,然后在添加ContactsContract.Data行時對該值進行“后向引用”。

    第一次調(diào)用applyBatch()時會創(chuàng)建整個結果數(shù)組,其大小等于您提供的ContentProviderOperation對象的ArrayList的大小。但是,結果數(shù)組中的所有元素都設置為null,如果嘗試對尚未應用的操作的結果進行反向引用,則withValueBackReference()會拋出異常。

    以下代碼段顯示了如何批量插入新的原始聯(lián)系人和數(shù)據(jù)。它們包括建立屈服點并使用反向引用的代碼。這些片段是createContacEntry()方法的擴展版本,該方法是Contact Manager示例應用程序中ContactAdder類的一部分。

    第一個代碼段從UI檢索聯(lián)系人數(shù)據(jù)。此時,用戶已經(jīng)選擇了應添加新原始聯(lián)系人的帳戶。

    // Creates a contact entry from the current UI values, using the currently-selected account. protected void createContactEntry() {/** Gets values from the UI*/String name = mContactNameEditText.getText().toString();String phone = mContactPhoneEditText.getText().toString();String email = mContactEmailEditText.getText().toString();int phoneType = mContactPhoneTypes.get(mContactPhoneTypeSpinner.getSelectedItemPosition());int emailType = mContactEmailTypes.get(mContactEmailTypeSpinner.getSelectedItemPosition());

    下一個代碼段創(chuàng)建一個操作,將原始聯(lián)系人行插入ContactsContract.RawContacts表:

    /** Prepares the batch operation for inserting a new raw contact and its data. Even if* the Contacts Provider does not have any data for this person, you can't add a Contact,* only a raw contact. The Contacts Provider will then add a Contact automatically.*/// Creates a new array of ContentProviderOperation objects.ArrayList<ContentProviderOperation> ops =new ArrayList<ContentProviderOperation>();/** Creates a new raw contact with its account type (server type) and account name* (user's account). Remember that the display name is not stored in this row, but in a* StructuredName data row. No other data is required.*/ContentProviderOperation.Builder op =ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI).withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType()).withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName());// Builds the operation and adds it to the array of operationsops.add(op.build());

    接下來,代碼為顯示名稱,電話和電子郵件行創(chuàng)建數(shù)據(jù)行。

    每個操作構建器對象使用withValueBackReference()來獲取RAW_CONTACT_ID。引用指向第一個操作的ContentProviderResult對象,該操作添加原始聯(lián)系人行并返回其新的_ID值。因此,每個數(shù)據(jù)行都會通過其RAW_CONTACT_ID自動鏈接到它所屬的新ContactsContract.RawContacts行。

    添加電子郵件行的ContentProviderOperation.Builder對象標記為withYieldAllowed(),該對象設置屈服點:

    // Creates the display name for the new raw contact, as a StructuredName data row.op =ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)/** withValueBackReference sets the value of the first argument to the value of* the ContentProviderResult indexed by the second argument. In this particular* call, the raw contact ID column of the StructuredName data row is set to the* value of the result returned by the first operation, which is the one that* actually adds the raw contact row.*/.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)// Sets the data row's MIME type to StructuredName.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)// Sets the data row's display name to the name in the UI..withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);// Builds the operation and adds it to the array of operationsops.add(op.build());// Inserts the specified phone number and type as a Phone data rowop =ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)/** Sets the value of the raw contact id column to the new raw contact ID returned* by the first operation in the batch.*/.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)// Sets the data row's MIME type to Phone.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)// Sets the phone number and type.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone).withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType);// Builds the operation and adds it to the array of operationsops.add(op.build());// Inserts the specified email and type as a Phone data rowop =ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)/** Sets the value of the raw contact id column to the new raw contact ID returned* by the first operation in the batch.*/.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)// Sets the data row's MIME type to Email.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)// Sets the email address and type.withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email).withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType);/** Demonstrates a yield point. At the end of this insert, the batch operation's thread* will yield priority to other threads. Use after every set of operations that affect a* single contact, to avoid degrading performance.*/op.withYieldAllowed(true);// Builds the operation and adds it to the array of operationsops.add(op.build());

    最后一個片段顯示了對applyBatch()的調(diào)用,該調(diào)用插入了新的原始聯(lián)系人和數(shù)據(jù)行。

    // Ask the Contacts Provider to create a new contactLog.d(TAG,"Selected account: " + mSelectedAccount.getName() + " (" +mSelectedAccount.getType() + ")");Log.d(TAG,"Creating contact: " + name);/** Applies the array of ContentProviderOperation objects in batch. The results are* discarded.*/try {getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);} catch (Exception e) {// Display a warningContext ctx = getApplicationContext();CharSequence txt = getString(R.string.contactCreationFailure);int duration = Toast.LENGTH_SHORT;Toast toast = Toast.makeText(ctx, txt, duration);toast.show();// Log exceptionLog.e(TAG, "Exception encountered while inserting contact: " + e);} }

    批處理操作還允許您實現(xiàn)樂觀并發(fā)控制,這是一種應用修改事務而無需鎖定底層存儲庫的方法。要使用此方法,請應用事務,然后檢查可能同時進行的其他修改。如果發(fā)現(xiàn)發(fā)生了不一致的修改,則回滾事務并重試。

    樂觀并發(fā)控制對于移動設備非常有用,其中一次只有一個用戶,并且很少同時訪問數(shù)據(jù)存儲庫。由于未使用鎖定,因此不會浪費時間設置鎖定或等待其他事務釋放其鎖定。

    要在更新單個ContactsContract.RawContacts行時使用樂觀并發(fā)控制,請按照下列步驟操作:

  • 檢索原始聯(lián)系人的VERSION列以及您檢索的其他數(shù)據(jù)。
  • 使用newAssertQuery(Uri)方法創(chuàng)建適合強制執(zhí)行約束的ContentProviderOperation.Builder對象。對于內(nèi)容URI,使用RawContacts.CONTENT_URI并附加原始聯(lián)系人的_ID。
  • 對于ContentProviderOperation.Builder對象,調(diào)用withValue()將VERSION列與剛剛檢索的版本號進行比較。
  • 對于相同的ContentProviderOperation.Builder,調(diào)用withExpectedCount()以確保此斷言僅測試一行。
  • 調(diào)用build()來創(chuàng)建ContentProviderOperation對象,然后將此對象添加為您傳遞給applyBatch()的ArrayList中的第一個對象。
  • 應用批處理事務。
  • 如果在您讀取行的時間和嘗試修改行的時間之間通過另一個操作更新原始聯(lián)系行,則“斷言”ContentProviderOperation將失敗,并且將撤消整批操作。然后,您可以選擇重試批處理或執(zhí)行其他操作。

    以下代碼段演示了如何在使用CursorLoader查詢單個原始聯(lián)系人后創(chuàng)建“斷言”ContentProviderOperation:

    /** The application uses CursorLoader to query the raw contacts table. The system calls this method* when the load is finished.*/ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {// Gets the raw contact's _ID and VERSION valuesmRawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID));mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION)); }...// Sets up a Uri for the assert operation Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, mRawContactID);// Creates a builder for the assert operation ContentProviderOperation.Builder assertOp = ContentProviderOperation.netAssertQuery(rawContactUri);// Adds the assertions to the assert operation: checks the version and count of rows tested assertOp.withValue(SyncColumns.VERSION, mVersion); assertOp.withExpectedCount(1);// Creates an ArrayList to hold the ContentProviderOperation objects ArrayList ops = new ArrayList<ContentProviderOperationg>;ops.add(assertOp.build());// You would add the rest of your batch operations to "ops" here...// Applies the batch. If the assert fails, an Exception is thrown try{ContentProviderResult[] results =getContentResolver().applyBatch(AUTHORITY, ops);} catch (OperationApplicationException e) {// Actions you want to take if the assert operation fails go here}

    使用意圖進行檢索和修改

    向設備的聯(lián)系人應用程序發(fā)送意圖允許您間接訪問聯(lián)系人提供程序。意圖啟動設備的聯(lián)系人應用程序UI,用戶可以在其中執(zhí)行與聯(lián)系人相關的工作。通過這種類型的訪問,用戶可以:

    • 從列表中選擇一個聯(lián)系人,并將其返回到您的應用程序以進行進一步的工作。
    • 編輯現(xiàn)有聯(lián)系人的數(shù)據(jù)。
    • 為他們的任何帳戶插入新的原始聯(lián)系人。
    • 刪除聯(lián)系人或聯(lián)系人數(shù)據(jù)。

    如果用戶正在插入或更新數(shù)據(jù),您可以先收集數(shù)據(jù)并將其作為意圖的一部分發(fā)送。

    當您使用意圖通過設備的聯(lián)系人應用程序訪問聯(lián)系人提供程序時,您不必編寫自己的UI或代碼來訪問提供程序。您也不必請求讀取或寫入提供程序的權限。設備的聯(lián)系人應用程序可以將聯(lián)系人的讀取權限委派給您,并且由于您通過其他應用程序對提供程序進行了修改,因此您不必具有寫入權限。

    發(fā)送訪問提供程序的意圖的一般過程在“內(nèi)容提供程序基礎知識”指南的“通過意圖進行數(shù)據(jù)訪問”一節(jié)中有詳細介紹。表4總結了用于可用任務的操作,MIME類型和數(shù)據(jù)值,而可以與putExtra()一起使用的extras值列在ContactsContract.Intents.Insert的參考文檔中:

    表4.聯(lián)系人提供者意圖。

    TaskActionDataMIME typeNotes
    從列表中選擇一個聯(lián)系人ACTION_PICK

    以下之一:

    • Contacts.CONTENT_URI,顯示聯(lián)系人列表。
    • Phone.CONTENT_URI,顯示原始聯(lián)系人的電話號碼列表。
    • StructuredPostal.CONTENT_URI,顯示原始聯(lián)系人的郵政地址列表。
    • Email.CONTENT_URI,顯示原始聯(lián)系人的電子郵件地址列表。
    Not used顯示原始聯(lián)系人列表或原始聯(lián)系人的數(shù)據(jù)列表,具體取決于您提供的內(nèi)容URI類型。

    調(diào)用startActivityForResult(),它返回所選行的內(nèi)容URI。 URI的形式是表的內(nèi)容URI,其中附加了行的LOOKUP_ID。設備的聯(lián)系人應用程序在活動期間委托對此內(nèi)容URI的讀寫權限。有關更多詳細信息,請參閱Content Provider Basics指南。
    插入新的原始聯(lián)系人Insert.ACTIONN/ARawContacts.CONTENT_TYPE,一組原始聯(lián)系人的MIME類型。顯示設備的聯(lián)系人應用程序的“添加聯(lián)系人”屏幕。將顯示您添加到意圖中的額外值。如果使用startActivityForResult()發(fā)送,則新添加的原始聯(lián)系人的內(nèi)容URI將在“數(shù)據(jù)”字段中的Intent參數(shù)中傳遞回活動的onActivityResult()回調(diào)方法。要獲取該值,請調(diào)用getData()。
    編輯聯(lián)系人ACTION_EDITCONTENT_LOOKUP_URI為聯(lián)系人。編輯器活動將允許用戶編輯與此聯(lián)系人關聯(lián)的任何數(shù)據(jù)。Contacts.CONTENT_ITEM_TYPE,單個聯(lián)系人。顯示聯(lián)系人應用程序中的編輯聯(lián)系人屏幕。將顯示您添加到意圖中的額外值。當用戶單擊“完成”以保存編輯時,您的活動將返回到前臺。
    顯示也可以添加數(shù)據(jù)的選擇器。ACTION_INSERT_OR_EDITN/ACONTENT_ITEM_TYPE

    此意圖始終顯示聯(lián)系人應用程序的選擇器屏幕。用戶可以選擇要編輯的聯(lián)系人,也可以添加新聯(lián)系人。根據(jù)用戶的選擇,將顯示編輯或添加屏幕,并顯示您在意圖中傳遞的額外數(shù)據(jù)。如果您的應用顯示聯(lián)系人數(shù)據(jù)(如電子郵件或電話號碼),請使用此意圖允許用戶將數(shù)據(jù)添加到現(xiàn)有聯(lián)系人。

    注意:無需在此intent的附加內(nèi)容中發(fā)送名稱值,因為用戶始終選擇現(xiàn)有名稱或添加新名稱。此外,如果您發(fā)送名稱,并且用戶選擇進行編輯,則聯(lián)系人應用程序將顯示您發(fā)送的名稱,覆蓋以前的值。如果用戶沒有注意到并保存編輯,則舊值將丟失。

    設備的聯(lián)系人應用程序不允許您刪除原始聯(lián)系人或其任何數(shù)據(jù)。相反,要刪除原始聯(lián)系人,請使用ContentResolver.delete()或ContentProviderOperation.newDelete()。

    以下代碼段顯示了如何構造和發(fā)送插入新原始聯(lián)系人和數(shù)據(jù)的intent:

    // Gets values from the UI String name = mContactNameEditText.getText().toString(); String phone = mContactPhoneEditText.getText().toString(); String email = mContactEmailEditText.getText().toString();String company = mCompanyName.getText().toString(); String jobtitle = mJobTitle.getText().toString();// Creates a new intent for sending to the device's contacts application Intent insertIntent = new Intent(ContactsContract.Intents.Insert.ACTION);// Sets the MIME type to the one expected by the insertion activity insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE);// Sets the new contact name insertIntent.putExtra(ContactsContract.Intents.Insert.NAME, name);// Sets the new company and job title insertIntent.putExtra(ContactsContract.Intents.Insert.COMPANY, company); insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle);/** Demonstrates adding data rows as an array list associated with the DATA key*/// Defines an array list to contain the ContentValues objects for each row ArrayList<ContentValues> contactData = new ArrayList<ContentValues>();/** Defines the raw contact row*/// Sets up the row as a ContentValues object ContentValues rawContactRow = new ContentValues();// Adds the account type and name to the row rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType()); rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName());// Adds the row to the array contactData.add(rawContactRow);/** Sets up the phone number data row*/// Sets up the row as a ContentValues object ContentValues phoneRow = new ContentValues();// Specifies the MIME type for this data row (all data rows must be marked by their type) phoneRow.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE );// Adds the phone number and its type to the row phoneRow.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone);// Adds the row to the array contactData.add(phoneRow);/** Sets up the email data row*/// Sets up the row as a ContentValues object ContentValues emailRow = new ContentValues();// Specifies the MIME type for this data row (all data rows must be marked by their type) emailRow.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE );// Adds the email address and its type to the row emailRow.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email);// Adds the row to the array contactData.add(emailRow);/** Adds the array to the intent's extras. It must be a parcelable object in order to* travel between processes. The device's contacts app expects its key to be* Intents.Insert.DATA*/ insertIntent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData);// Send out the intent to start the device's contacts app in its add contact activity. startActivity(insertIntent);

    數(shù)據(jù)的完整性

    由于聯(lián)系人存儲庫包含用戶期望正確且最新的重要且敏感的數(shù)據(jù),因此聯(lián)系人提供程序具有明確定義的數(shù)據(jù)完整性規(guī)則。修改聯(lián)系人數(shù)據(jù)時,您有責任遵守這些規(guī)則。這里列出了重要的規(guī)則:

    始終為您添加的每個ContactsContract.RawContacts行添加ContactsContract.CommonDataKinds.StructuredName行。

    在ContactsContract.Data表中沒有ContactsContract.CommonDataKinds.StructuredName行的ContactsContract.RawContacts行可能會在聚合期間導致問題。

    始終將新的ContactsContract.Data行鏈接到其父ContactsContract.RawContacts行。

    未鏈接到ContactsContract.RawContacts的ContactsContract.Data行將在設備的聯(lián)系人應用程序中不可見,并且可能會導致同步適配器出現(xiàn)問題。

    僅為您擁有的原始聯(lián)系人更改數(shù)據(jù)。

    請記住,聯(lián)系人提供商通常管理來自多種不同帳戶類型/在線服務的數(shù)據(jù)。您需要確保應用程序僅修改或刪除屬于您的行的數(shù)據(jù),并且僅插入具有您控制的帳戶類型和名稱的數(shù)據(jù)。

    始終使用ContactsContract及其子類中定義的常量來獲取權限,內(nèi)容URI,URI路徑,列名,MIME類型和TYPE值。

    使用這些常量可以幫助您避免錯誤。如果不推薦任何常量,也會收到編譯器警告通知。

    自定義數(shù)據(jù)行

    通過創(chuàng)建和使用自己的自定義MIME類型,您可以在ContactsContract.Data表中插入,編輯,刪除和檢索自己的數(shù)據(jù)行。您的行僅限于使用ContactsContract.DataColumns中定義的列,但您可以將自己的特定于類型的列名稱映射到默認列名稱。在設備的聯(lián)系人應用程序中,將顯示行的數(shù)據(jù),但無法編輯或刪除,用戶無法添加其他數(shù)據(jù)。要允許用戶修改自定義數(shù)據(jù)行,您必須在自己的應用程序中提供編輯器活動。

    顯示自定義數(shù)據(jù),請?zhí)峁┌?lt;ContactsAccountType>元素及其一個或多個<ContactsDataKind>子元素的contacts.xml文件。這在<ContactsDataKind>元素部分中有更詳細的描述。

    要了解有關自定義MIME類型的更多信息,請閱讀“創(chuàng)建內(nèi)容提供商”指南。

    聯(lián)系人提供商同步適配器


    聯(lián)系人提供程序專門用于處理設備和在線服務之間的聯(lián)系人數(shù)據(jù)同步。這允許用戶將現(xiàn)有數(shù)據(jù)下載到新設備并將現(xiàn)有數(shù)據(jù)上載到新帳戶。無論添加和更改的來源如何,同步還可確保用戶掌握最新數(shù)據(jù)。同步的另一個優(yōu)點是,即使設備未連接到網(wǎng)絡,它也可以使聯(lián)系人數(shù)據(jù)可用。

    雖然您可以通過多種方式實現(xiàn)同??步,但Android系統(tǒng)提供了一個插件同步框架,可自動執(zhí)行以下任務:

    • 檢查網(wǎng)絡可用性。
    • 根據(jù)用戶首選項調(diào)度和執(zhí)行同步。
    • 重新啟動已停止的同步。

    要使用此框架,請?zhí)峁┩竭m配器插件。每個同步適配器對于服務和內(nèi)容提供商都是唯一的,但可以處理同一服務的多個帳戶名。該框架還允許同一服務和提供者使用多個同步適配器。

    同步適配器類和文件

    您將同步適配器實現(xiàn)為AbstractThreadedSyncAdapter的子類,并將其安裝為Android應用程序的一部分。系統(tǒng)從應用程序清單中的元素以及清單指向的特殊XML文件中了解同步適配器。 XML文件定義在線服務的帳戶類型和內(nèi)容提供者的權限,它們一起唯一地標識適配器。在用戶為同步適配器的帳戶類型添加帳戶并為同步適配器同步的內(nèi)容提供程序啟用同步之前,同步適配器不會變?yōu)榛顒訝顟B(tài)。此時,系統(tǒng)開始管理適配器,根據(jù)需要調(diào)用它以在內(nèi)容提供者和服務器之間進行同步。

    注意:使用帳戶類型作為同步適配器標識的一部分,系統(tǒng)可以檢測同一組合的同步適配器并將其組合在一起。例如,Google在線服務的同步適配器都具有相同的帳戶類型com.google。當用戶將Google帳戶添加到他們的設備時,所有已安裝的Google服務同步適配器都會列在一起;列出的每個同步適配器與設備上的其他內(nèi)容提供程序同步。

    由于大多數(shù)服務要求用戶在訪問數(shù)據(jù)之前驗證其身份,因此Android系統(tǒng)提供的身份驗證框架與同步適配器框架類似,并且通常與其同時使用。身份驗證框架使用插件身份驗證器,它是AbstractAccountAuthenticator的子類。驗證者通過以下步驟驗證用戶的身份:

    • 收集用戶的名稱,密碼或類似信息(用戶的憑據(jù))。
    • 將憑據(jù)發(fā)送到服務
    • 檢查服務的回復。

    如果服務接受憑據(jù),則身份驗證器可以存儲憑據(jù)以供以后使用。由于插件驗證器框架,AccountManager可以提供對驗證者支持并選擇公開的任何驗證的訪問權限,例如OAuth2 authtokens。

    雖然不需要身份驗證,但大多數(shù)聯(lián)系人服務都使用它。但是,您不需要使用Android身份驗證框架進行身份驗證。

    同步適配器實現(xiàn)

    要為Contacts Provider實現(xiàn)同步適配器,首先要創(chuàng)建一個包含以下內(nèi)容的Android應用程序:

    一個服務組件,響應來自系統(tǒng)的請求綁定到同步適配器。

    當系統(tǒng)想要運行同步時,它會調(diào)用服務的onBind()方法來獲取同步適配器的IBinder。這允許系統(tǒng)對適配器的方法執(zhí)行跨進程調(diào)用。

    在Sample Sync Adapter示例應用程序中,此服務的類名是com.example.android.samplesync.syncadapter.SyncService。

    實際的同步適配器,實現(xiàn)為AbstractThreadedSyncAdapter的具體子類。

    此類負責從服務器下載數(shù)據(jù),從設備上傳數(shù)據(jù)以及解決沖突。適配器的主要工作是在onPerformSync()方法中完成的。必須將此類實例化為單例。

    在Sample Sync Adapter示例應用程序中,同步適配器在com.example.android.samplesync.syncadapter.SyncAdapter類中定義。

    Application的子類。

    此類充當同步適配器單例的工廠。使用onCreate()方法實例化同步適配器,并提供靜態(tài)“getter”方法以將單例返回到同步適配器服務的onBind()方法。

    可選:響應來自系統(tǒng)的用戶身份驗證請求的服務組件。

    AccountManager啟動此服務以開始身份驗證過程。服務的onCreate()方法實例化一個authenticator對象。當系統(tǒng)想要為應用程序的同步適配器驗證用戶帳戶時,它會調(diào)用服務的onBind()方法來獲取驗證者的IBinder。這允許系統(tǒng)對認證者的方法進行跨進程調(diào)用。

    在Sample Sync Adapter示例應用程序中,此服務的類名是com.example.android.samplesync.authenticator.AuthenticationService。

    可選:AbstractAccountAuthenticator的一個具體子類,用于處理身份驗證請求。

    此類提供AccountManager調(diào)用的方法,以便使用服務器驗證用戶的憑據(jù)。根據(jù)使用的服務器技術,身份驗證過程的細節(jié)差異很大。您應參閱服務器軟件的文檔以了解有關身份驗證的更多信息。

    在Sample Sync Adapter示例應用程序中,驗證程序在com.example.android.samplesync.authenticator.Authenticator類中定義。

    定義系統(tǒng)同步適配器和身份驗證器的XML文件。

    前面描述的同步適配器和身份驗證器服務組件在應用程序清單中的<service>元素中定義。這些元素包含<meta-data>子元素,它們?yōu)橄到y(tǒng)提供特定數(shù)據(jù):

    • 步適配器服務的<meta-data>元素指向XML文件res / xml / syncadapter.xml。反過來,此文件指定將與聯(lián)系人提供程序同步的Web服務的URI,以及Web服務的帳戶類型。
    • 可選:驗證者的<meta-data>元素指向XML文件res / xml / authenticator.xml。反過來,此文件指定此身份驗證器支持的帳戶類型,以及在身份驗證過程中顯示的UI資源。此元素中指定的帳戶類型必須與為同步適配器指定的帳戶類型相同。

    社交流數(shù)據(jù)


    android.provider.ContactsContract.StreamItems和android.provider.ContactsContract.StreamItemPhotos表管理來自社交網(wǎng)絡的傳入數(shù)據(jù)。您可以編寫一個同步適配器,將來自您自己網(wǎng)絡的流數(shù)據(jù)添加到這些表中,或者您可以從這些表中讀取流數(shù)據(jù)并將其顯示在您自己的應用程序中,或兩者都顯示。借助這些功能,您的社交網(wǎng)絡服務和應用程序可以集成到Android的社交網(wǎng)絡體驗中。

    社交流文本

    流項目始終與原始聯(lián)系人關聯(lián)。 android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID鏈接到原始聯(lián)系人的_ID值。原始聯(lián)系人的帳戶類型和帳戶名稱也存儲在流項目行中。

    將流中的數(shù)據(jù)存儲在以下列中:

    android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE

    必要:用戶與此流項關聯(lián)的原始聯(lián)系人的帳戶類型。請記住在插入流項目時設置此值。

    android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME

    必要:用戶與此流項目關聯(lián)的原始聯(lián)系人的帳戶名稱。請記住在插入流項目時設置此值。

    標識符列

    必要:插入流項時,必須插入以下標識符列:

    • android.provider.ContactsContract.StreamItemsColumns #CONTACT_ID:與此流項關聯(lián)的聯(lián)系人的android.provider.BaseColumns#_ID值。
    • android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY:此流項目與之關聯(lián)的聯(lián)系人的android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY值。
    • android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID:與此流項關聯(lián)的原始聯(lián)系人的android.provider.BaseColumns#_ID值。

    android.provider.ContactsContract.StreamItemsColumns#COMMENTS

    可選的。存儲可以在流項目開頭顯示的摘要信息。

    android.provider.ContactsContract.StreamItemsColumns#TEXT

    流項目的文本,即項目源發(fā)布的內(nèi)容,或生成流項目的某些操作的描述。此列可以包含可以由fromHtml()呈現(xiàn)的任何格式和嵌入式資源圖像。提供程序可能會截斷或刪除長內(nèi)容,但會盡量避免破壞標記。

    要顯示流項目的標識信息,請使用android.provider.ContactsContract.StreamItemsColumns#RES_ICON,android.provider.ContactsContract.StreamItemsColumns#RES_LABEL和android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE鏈接到應用程序中的資源。

    android.provider.ContactsContract.StreamItems表還包含列android.provider.ContactsContract.StreamItemsColumns#SYNC1到android.provider.ContactsContract.StreamItemsColumns#SYNC4,用于獨占使用同步適配器。

    社交流照片

    android.provider.ContactsContract.StreamItemPhotos表存儲與流項關聯(lián)的照片。表的android.provider.ContactsContract.StreamItemPhotosColumns #STREAM_ITEM_ID列鏈接到android.provider.ContactsContract.StreamItems表的_ID列中的值。照片參考存儲在這些列的表中:

    android.provider.ContactsContract.StreamItemPhotos #PHOTO列(BLOB)。

    照片的二進制表示,由提供程序調(diào)整大小以進行存儲和顯示。此列可用于向后兼容用于存儲照片的以前版本的Contacts Provider。但是,在當前版本中,您不應使用此列來存儲照片。相反,使用android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID或android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI(兩者都在以下幾點中描述)將照片存儲在文件中。此列現(xiàn)在包含照片的縮略圖,可供閱讀。

    android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID

    原始聯(lián)系人照片的數(shù)字標識符。將此值附加到常量DisplayPhoto.CONTENT_URI以獲取指向單個照片文件的內(nèi)容URI,然后調(diào)用openAssetFileDescriptor()以獲取照片文件的句柄。

    android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI

    內(nèi)容URI直接指向此行所代表的照片的照片文件。使用此URI調(diào)用openAssetFileDescriptor()以獲取照片文件的句柄。

    使用社交流表

    這些表的工作方式與Contacts Provider中的其他主表相同,不同之處在于:

    • 這些表需要其他訪問權限。要從中讀取,您的應用程序必須具有android.Manifest.permission#READ_SOCIAL_STREAM權限。要修改它們,您的應用程序必須具有android.Manifest.permission#WRITE_SOCIAL_STREAM權限。
    • 對于android.provider.ContactsContract.StreamItems表,為每個原始聯(lián)系人存儲的行數(shù)是有限的。達到此限制后,Contacts Provider會自動刪除具有最舊android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP的行,從而為新的流項目行騰出空間。要獲得限制,請向內(nèi)容URI發(fā)出查詢android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI。您可以將除內(nèi)容URI之外的所有參數(shù)設置為null。該查詢返回一個包含單行的Cursor,其中包含單個列android.provider.ContactsContract.StreamItems #MAX_ITEMS。

    android.provider.ContactsContract.StreamItems.StreamItemPhotos類定義了包含單個流項目的照片行的android.provider.ContactsContract.StreamItemPhotos的子表。

    社交流互動

    聯(lián)系人提供商管理的社交流數(shù)據(jù)與設備的聯(lián)系人應用程序一起,提供了一種將社交網(wǎng)絡系統(tǒng)與現(xiàn)有聯(lián)系人連接的強大方式。可以使用以下功能:

    • 通過使用同步適配器將您的社交網(wǎng)絡服務同步到Contacts Provider,您可以檢索用戶聯(lián)系人的最近活動,并將其存儲在android.provider.ContactsContract.StreamItems和android.provider.ContactsContract.StreamItemPhotos表中供以后使用。
    • 除了常規(guī)同步之外,您還可以在用戶選擇要查看的聯(lián)系人時觸發(fā)同步適配器以檢索其他數(shù)據(jù)。這允許您的同步適配器檢索高分辨率照片和聯(lián)系人的最新流項目。
    • 通過向設備的聯(lián)系人應用程序和聯(lián)系人提供程序注冊通知,您可以在查看聯(lián)系人時收到意圖,并在此時更新服務中的聯(lián)系人狀態(tài)。與使用同步適配器進行完全同步相比,此方法可能更快并且使用更少的帶寬。
    • 用戶可以在查看設備聯(lián)系人應用程序中的聯(lián)系人時為您的社交網(wǎng)絡服務添加聯(lián)系人。您可以使用“邀請聯(lián)系人”功能啟用此功能,該功能通過將現(xiàn)有聯(lián)系人添加到網(wǎng)絡的活動和提供設備聯(lián)系人應用程序的XML文件以及提供應用程序詳細信息的聯(lián)系人提供程序的組合啟用。

    流項目與Contacts Provider的定期同步與其他同步相同。有關同步的詳細信息,請參閱“聯(lián)系人提供程序同步適配器”一節(jié)。接下來的兩節(jié)將介紹注冊通知和邀請聯(lián)系人。

    注冊以處理社交網(wǎng)絡視圖

    注冊同步適配器以在用戶查看由同步適配器管理的聯(lián)系人時接收通知:

  • 在項目的res / xml /目錄中創(chuàng)建名為contacts.xml的文件。如果您已有此文件,則可以跳過此步驟。
  • 在此文件中,添加元素<ContactsAccountType xmlns:android =“http://schemas.android.com/apk/res/android”>。如果此元素已存在,則可以跳過此步驟。
  • 要注冊當用戶在設備的聯(lián)系人應用程序中打開聯(lián)系人詳細信息頁面時收到通知的服務,請將屬性viewContactNotifyService =“serviceclass”添加到該元素,其中serviceclass是應接收意圖的服務的完全限定類名。設備的聯(lián)系人應用程序。對于通知程序服務,請使用擴展IntentService的類,以允許服務接收意圖。傳入意圖中的數(shù)據(jù)包含用戶單擊的原始聯(lián)系人的內(nèi)容URI。從通知程序服務,您可以綁定到然后調(diào)用同步適配器以更新原始聯(lián)系人的數(shù)據(jù)。
  • 要注冊當用戶單擊流項目或照片或兩者時要調(diào)用的活動:

  • 在項目的res / xml /目錄中創(chuàng)建名為contacts.xml的文件。如果您已有此文件,則可以跳過此步驟。
  • 要注冊您的某個活動以處理用戶單擊設備的聯(lián)系人應用程序中的流項目,請將屬性viewStreamItemActivity =“activityclass”添加到元素,其中activityclass是應從其接收意圖的活動的完全限定類名。設備的聯(lián)系人應用程序。
  • 要注冊您的某個活動以處理用戶單擊設備的聯(lián)系人應用程序中的流項目,請將屬性viewStreamItemActivity =“activityclass”添加到元素,其中activityclass是應從其接收意圖的活動的完全限定類名。設備的聯(lián)系人應用程序。
  • 要注冊您的某個活動以處理用戶在設備的聯(lián)系人應用程序中單擊流照片,請將屬性viewStreamItemPhotoActivity =“activityclass”添加到該元素,其中activityclass是應接收意圖的活動的完全限定類名。設備的聯(lián)系人應用程序。
  • <ContactsAccountType>元素在<ContactsAccountType>元素中有更詳細的描述。

    傳入的意圖包含用戶單擊的項目或照片的內(nèi)容URI。要為文本項和照片分別進行活動,請在同一文件中使用這兩個屬性。

    與您的社交網(wǎng)絡服務進行交互

    用戶無需離開設備的聯(lián)系人應用程序即可邀請聯(lián)系人加入您的社交網(wǎng)站。相反,您可以讓設備的聯(lián)系人應用程序發(fā)送邀請聯(lián)系人參與您的某項活動的意圖。要設置它:

  • 在項目的res / xml /目錄中創(chuàng)建名為contacts.xml的文件。如果您已有此文件,則可以跳過此步驟。
  • 在此文件中,添加元素<ContactsAccountType xmlns:android =“http://schemas.android.com/apk/res/android”>。如果此元素已存在,則可以跳過此步驟。
  • 添加以下屬性:
    • inviteContactActivity="activityclass"
    • inviteContactActionLabel="@string/invite_action_label"

    activityclass值是應該接收intent的活動的完全限定類名。 invite_action_label值是一個文本字符串,顯示在設備的聯(lián)系人應用程序的“添加連接”菜單中。

    注意:ContactsSource是ContactsAccountType的已棄用標記名稱。

    contacts.xml參考

    文件的contacts.xml包含控制同步適配器和應用程序與聯(lián)系人應用程序和聯(lián)系人提供程序的交互的XML元素。以下各節(jié)介紹了這些元素。

    <ContactsAccountType>元素

    <ContactsAccountType>元素控制應用程序與聯(lián)系人應用程序的交互。它具有以下語法:

    <ContactsAccountTypexmlns:android="http://schemas.android.com/apk/res/android"inviteContactActivity="activity_name"inviteContactActionLabel="invite_command_text"viewContactNotifyService="view_notify_service"viewGroupActivity="group_view_activity"viewGroupActionLabel="group_action_text"viewStreamItemActivity="viewstream_activity_name"viewStreamItemPhotoActivity="viewphotostream_activity_name">

    包含在:

    res/xml/contacts.xml

    可以包含:

    <ContactsDataKind>

    描述:

    聲明Android組件和UI標簽,允許用戶邀請其中一個聯(lián)系人加入社交網(wǎng)絡,在其中一個社交網(wǎng)絡流更新時通知用戶,等等。

    請注意,<ContactsAccountType>的屬性不需要屬性前綴android:。

    屬性:

    inviteContactActivity

    當用戶從設備的聯(lián)系人應用程序中選擇添加連接時,要激活的應用程序中活動的完全限定類名。

    inviteContactActionLabel

    在“添加連接”菜單中為inviteContactActivity中指定的活動顯示的文本字符串。例如,您可以使用字符串“Follow in my network”。您可以為此標簽使用字符串資源標識符。

    viewContactNotifyService

    應用程序中服務的完全限定類名,應在用戶查看聯(lián)系人時接收通知。此通知由設備的聯(lián)系人應用程序發(fā)送;它允許您的應用程序推遲數(shù)據(jù)密集型操作,直到需要它們?yōu)橹埂@?#xff0c;您的應用程序可以通過讀入并顯示聯(lián)系人的高分辨率照片和最新的社交流項目來響應此通知。社交流交互部分中更詳細地描述了此功能。您可以在SampleSyncAdapter示例應用程序的NotifierService.java文件中看到通知服務的示例。

    viewGroupActivity

    應用程序中可顯示組信息的活動的完全限定類名。當用戶單擊設備的聯(lián)系人應用程序中的組標簽時,將顯示此活動的UI。

    viewGroupActionLabel

    聯(lián)系人應用程序為UI控件顯示的標簽,允許用戶查看應用程序中的組。

    例如,如果您在自己的設備上安裝Google+應用程序并將Google+與聯(lián)系人應用程序同步,則會在聯(lián)系人應用程序的“組”標簽中看到Google+圈子列為群組。如果您點擊Google+圈子,您會看到該圈子中的人員被列為“群組”。在屏幕頂部,您會看到Google+圖標;如果您點擊它,控制權切換到Google+應用。聯(lián)系人應用程序使用Google+圖標作為viewGroupActionLabel的值,使用viewGroupActivity執(zhí)行此操作。

    此屬性允許使用字符串資源標識符。

    viewStreamItemActivity

    應用程序中活動的完全限定類名,當用戶單擊原始聯(lián)系人的流項時,設備的聯(lián)系人應用程序將啟動該活動。

    viewStreamItemPhotoActivity

    應用程序中活動的完全限定類名,當用戶單擊原始聯(lián)系人的流項目中的照片時,設備的聯(lián)系人應用程序將啟動該活動。

    <ContactsDataKind>元素

    <ContactsDataKind>元素控制聯(lián)系人應用程序UI中應用程序的自定義數(shù)據(jù)行的顯示。它具有以下語法:

    <ContactsDataKindandroid:mimeType="MIMEtype"android:icon="icon_resources"android:summaryColumn="column_name"android:detailColumn="column_name">

    包含在:

    <ContactsAccountType>

    描述:

    使用此元素可使聯(lián)系人應用程序顯示自定義數(shù)據(jù)行的內(nèi)容,作為原始聯(lián)系人詳細信息的一部分。 <ContactsAccountType>的每個<ContactsDataKind>子元素表示同步適配器添加到ContactsContract.Data表的一種自定義數(shù)據(jù)行。為您使用的每個自定義MIME類型添加一個<ContactsDataKind>元素。如果您有一個不想顯示數(shù)據(jù)的自定義數(shù)據(jù)行,則不必添加該元素。

    屬性:

    android:mimeType

    您為ContactsContract.Data表中的某個自定義數(shù)據(jù)行類型定義的自定義MIME類型。例如,值vnd.android.cursor.item / vnd.example.locationstatus可以是記錄聯(lián)系人上次已知位置的數(shù)據(jù)行的自定義MIME類型。

    android:icon

    聯(lián)系人應用程序在您的數(shù)據(jù)旁邊顯示的Android可繪制資源。使用此選項可向用戶表明數(shù)據(jù)來自您的服務。

    android:summaryColumn

    從數(shù)據(jù)行檢索的兩個值中的第一個的列名稱。該值顯示為此數(shù)據(jù)行的條目的第一行。第一行旨在用作數(shù)據(jù)摘要,但這是可選的。另見android:detailColumn。

    android:detailColumn

    從數(shù)據(jù)行檢索的兩個值中的第二個的列名稱。該值顯示為此數(shù)據(jù)行的條目的第二行。另見android:summaryColumn。

    其他聯(lián)系人提供商功能

    除了前面部分中描述的主要功能外,Contacts Provider還提供了這些用于處理聯(lián)系人數(shù)據(jù)的有用功能:

    • 聯(lián)系小組
    • 照片功能

    聯(lián)系小組

    聯(lián)系人提供者可以選擇使用組數(shù)據(jù)標記相關聯(lián)系人的集合。如果與用戶帳戶關聯(lián)的服務器要維護組,則帳戶的帳戶類型的同步適配器應在聯(lián)系人提供程序和服務器之間傳輸組數(shù)據(jù)。當用戶將新聯(lián)系人添加到服務器,然后將此聯(lián)系人放入新組時,同步適配器必須將新組添加到ContactsContract.Groups表。原始聯(lián)系人所屬的組或組使用ContactsContract.CommonDataKinds.GroupMembership MIME類型存儲在ContactsContract.Data表中。

    如果您正在設計將原始聯(lián)系人數(shù)據(jù)從服務器添加到聯(lián)系人提供程序的同步適配器,并且您沒有使用組,則需要告知提供程序使您的數(shù)據(jù)可見。在用戶向設備添加帳戶時執(zhí)行的代碼中,更新Contacts Provider為該帳戶添加的ContactsContract.Settings行。在此行中,將Settings.UNGROUPED_VISIBLE列的值設置為1.執(zhí)行此操作時,即使您不使用組,聯(lián)系人提供程序也始終使您的聯(lián)系人數(shù)據(jù)可見。

    聯(lián)系照片

    ContactsContract.Data表將照片存儲為MIME類型為Photo.CONTENT_ITEM_TYPE的行。行的CONTACT_ID列鏈接到它所屬的原始聯(lián)系人的_ID列。 ContactsContract.Contacts.Photo類定義ContactsContract.Contacts的子表,其中包含聯(lián)系人主要照片的照片信息,該照片是聯(lián)系人主要原始聯(lián)系人的主要照片。類似地,類ContactsContract.RawContacts.DisplayPhoto定義ContactsContract.RawContacts的子表,其中包含原始聯(lián)系人的主要照片的照片信息。

    ContactsContract.Contacts.Photo和ContactsContract.RawContacts.DisplayPhoto的參考文檔包含檢索照片信息的示例。檢索原始聯(lián)系人的主縮略圖沒有便利類,但您可以向ContactsContract.Data表發(fā)送查詢,選擇原始聯(lián)系人的_ID,Photo.CONTENT_ITEM_TYPE和IS_PRIMARY列以查找原始聯(lián)系人的主要聯(lián)系人照片排。

    人的社交流數(shù)據(jù)還可以包括照片。它們存儲在android.provider.ContactsContract.StreamItemPhotos表中,在社交流照片一節(jié)中有更詳細的描述。

    總結

    以上是生活随笔為你收集整理的Android官方文档—APP组件(Content Providers)(Contacts Provider)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。