日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

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

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

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

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

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

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

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

通訊錄供應(yīng)商架構(gòu)


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

圖1. Contacts Provider表結(jié)構(gòu)。

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

ContactsContract.Contacts表

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

ContactsContract.RawContacts表

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

ContactsContract.Data表

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

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

原始聯(lián)系人


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

注意

以下是有關(guān)ContactsContract.RawContacts表的重要說明:

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

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

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

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

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

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

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

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

  • “Thomas Higginson”的原始聯(lián)系人與emily.dickinson@gmail.com相關(guān)聯(lián)。用戶帳戶類型為Google。
  • “Thomas Higginson”的第二個原始聯(lián)系人與emilyd@gmail.com相關(guān)聯(lián)。用戶帳戶類型也是Google。即使名稱與以前的名稱相同,也存在第二個原始聯(lián)系人,因為該人員是為其他用戶帳戶添加的。
  • ?與“belle_of_amherst”相關(guān)的“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相關(guān)聯(lián))的家庭電子郵件地址為thigg@gmail.com,工作電子郵件地址為thomas.higginson@gmail.com,Contacts Provider存儲兩個電子郵件地址行,并將它們鏈接到原始聯(lián)系人。

    請注意,此單個表中存儲了不同類型的數(shù)據(jù)。顯示名稱,電話號碼,電子郵件,郵政地址,照片和網(wǎng)站詳細(xì)信息行均可在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一起使用的應(yīng)用程序或同步適配器使用。

    IS_PRIMARY

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

    通用列名稱

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

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

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

    特定于類型的列名稱

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

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

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

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

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

    特定于類型的列名稱類

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

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

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

    通訊錄

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

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

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

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

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

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

    圖3. Contacts,Raw Contacts和Details表關(guān)系。

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


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

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

    帳戶類型

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

    用戶名

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

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

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

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

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

    必需的權(quán)限


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

    對一個或多個表的讀訪問權(quán)限

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

    對一個或多個表的寫訪問權(quán)

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

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

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

    用戶檔案


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

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

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

    要檢索包含用戶配置文件的聯(lián)系人行,請調(diào)用ContentResolver.query()。將內(nèi)容URI設(shè)置為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)系人是用戶配置文件,則此列設(shè)置為“1”。

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


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

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

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

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

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

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

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


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

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

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

    查詢實體

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

    實體就像一個由父表及其子表中的選定列組成的表。查詢實體時,您將根據(jù)實體中可用的列提供投影和搜索條件。結(jié)果是包含的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)系人提供程序在單個事務(wù)中處理針對實體的查詢,這確保檢索到的數(shù)據(jù)在內(nèi)部是一致的。

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

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

    此代碼段取自“詳細(xì)信息”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ù)是帶有查詢結(jié)果的Cursor。在您自己的應(yīng)用程序中,您可以從此Cursor獲取數(shù)據(jù)以顯示它或進(jìn)一步使用它。

    批量修改

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

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

    屈服點

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

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

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

    修改后引用

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

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

    key

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

    previousResult

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

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

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

    第一個代碼段從UI檢索聯(lián)系人數(shù)據(jù)。此時,用戶已經(jīng)選擇了應(yī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ù)行。

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

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

    // 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ā)控制,這是一種應(yīng)用修改事務(wù)而無需鎖定底層存儲庫的方法。要使用此方法,請應(yīng)用事務(wù),然后檢查可能同時進(jìn)行的其他修改。如果發(fā)現(xiàn)發(fā)生了不一致的修改,則回滾事務(wù)并重試。

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

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

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

    使用意圖進(jìn)行檢索和修改

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

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

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

    當(dāng)您使用意圖通過設(shè)備的聯(lián)系人應(yīng)用程序訪問聯(lián)系人提供程序時,您不必編寫自己的UI或代碼來訪問提供程序。您也不必請求讀取或?qū)懭胩峁┏绦虻臋?quán)限。設(shè)備的聯(lián)系人應(yīng)用程序可以將聯(lián)系人的讀取權(quán)限委派給您,并且由于您通過其他應(yīng)用程序?qū)μ峁┏绦蜻M(jìn)行了修改,因此您不必具有寫入權(quán)限。

    發(fā)送訪問提供程序的意圖的一般過程在“內(nèi)容提供程序基礎(chǔ)知識”指南的“通過意圖進(jìn)行數(shù)據(jù)訪問”一節(jié)中有詳細(xì)介紹。表4總結(jié)了用于可用任務(wù)的操作,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。設(shè)備的聯(lián)系人應(yīng)用程序在活動期間委托對此內(nèi)容URI的讀寫權(quán)限。有關(guān)更多詳細(xì)信息,請參閱Content Provider Basics指南。
    插入新的原始聯(lián)系人Insert.ACTIONN/ARawContacts.CONTENT_TYPE,一組原始聯(lián)系人的MIME類型。顯示設(shè)備的聯(lián)系人應(yīng)用程序的“添加聯(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)系人關(guān)聯(lián)的任何數(shù)據(jù)。Contacts.CONTENT_ITEM_TYPE,單個聯(lián)系人。顯示聯(lián)系人應(yīng)用程序中的編輯聯(lián)系人屏幕。將顯示您添加到意圖中的額外值。當(dāng)用戶單擊“完成”以保存編輯時,您的活動將返回到前臺。
    顯示也可以添加數(shù)據(jù)的選擇器。ACTION_INSERT_OR_EDITN/ACONTENT_ITEM_TYPE

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

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

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

    以下代碼段顯示了如何構(gòu)造和發(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ù)時,您有責(zé)任遵守這些規(guī)則。這里列出了重要的規(guī)則:

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

    同步適配器類和文件

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

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

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

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

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

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

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

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

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

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

    在Sample Sync Adapter示例應(yīng)用程序中,此服務(wù)的類名是com.example.android.samplesync.syncadapter.SyncService。

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

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

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

    Application的子類。

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

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

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

    在Sample Sync Adapter示例應(yīng)用程序中,此服務(wù)的類名是com.example.android.samplesync.authenticator.AuthenticationService。

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

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

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

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

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

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

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


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

    社交流文本

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

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

    android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE

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

    android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME

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

    標(biāo)識符列

    必要:插入流項時,必須插入以下標(biāo)識符列:

    • android.provider.ContactsContract.StreamItemsColumns #CONTACT_ID:與此流項關(guān)聯(lián)的聯(lián)系人的android.provider.BaseColumns#_ID值。
    • android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY:此流項目與之關(guān)聯(lián)的聯(lián)系人的android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY值。
    • android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID:與此流項關(guān)聯(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)容,但會盡量避免破壞標(biāo)記。

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

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

    社交流照片

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

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

    照片的二進(jìn)制表示,由提供程序調(diào)整大小以進(jìn)行存儲和顯示。此列可用于向后兼容用于存儲照片的以前版本的Contacts Provider。但是,在當(dāng)前版本中,您不應(yīng)使用此列來存儲照片。相反,使用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ù)字標(biāo)識符。將此值附加到常量DisplayPhoto.CONTENT_URI以獲取指向單個照片文件的內(nèi)容URI,然后調(diào)用openAssetFileDescriptor()以獲取照片文件的句柄。

    android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI

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

    使用社交流表

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

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

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

    社交流互動

    聯(lián)系人提供商管理的社交流數(shù)據(jù)與設(shè)備的聯(lián)系人應(yīng)用程序一起,提供了一種將社交網(wǎng)絡(luò)系統(tǒng)與現(xiàn)有聯(lián)系人連接的強(qiáng)大方式??梢允褂靡韵鹿δ?#xff1a;

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

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

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

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

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

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

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

    與您的社交網(wǎng)絡(luò)服務(wù)進(jìn)行交互

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

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

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

    注意:ContactsSource是ContactsAccountType的已棄用標(biāo)記名稱。

    contacts.xml參考

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

    <ContactsAccountType>元素

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

    <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標(biāo)簽,允許用戶邀請其中一個聯(lián)系人加入社交網(wǎng)絡(luò),在其中一個社交網(wǎng)絡(luò)流更新時通知用戶,等等。

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

    屬性:

    inviteContactActivity

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

    inviteContactActionLabel

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

    viewContactNotifyService

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

    viewGroupActivity

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

    viewGroupActionLabel

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

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

    此屬性允許使用字符串資源標(biāo)識符。

    viewStreamItemActivity

    應(yīng)用程序中活動的完全限定類名,當(dāng)用戶單擊原始聯(lián)系人的流項時,設(shè)備的聯(lián)系人應(yīng)用程序?qū)釉摶顒印?/p>

    viewStreamItemPhotoActivity

    應(yīng)用程序中活動的完全限定類名,當(dāng)用戶單擊原始聯(lián)系人的流項目中的照片時,設(shè)備的聯(lián)系人應(yīng)用程序?qū)釉摶顒印?/p>

    <ContactsDataKind>元素

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

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

    包含在:

    <ContactsAccountType>

    描述:

    使用此元素可使聯(lián)系人應(yīng)用程序顯示自定義數(shù)據(jù)行的內(nèi)容,作為原始聯(lián)系人詳細(xì)信息的一部分。 <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)系人應(yīng)用程序在您的數(shù)據(jù)旁邊顯示的Android可繪制資源。使用此選項可向用戶表明數(shù)據(jù)來自您的服務(wù)。

    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ù)標(biāo)記相關(guān)聯(lián)系人的集合。如果與用戶帳戶關(guān)聯(lián)的服務(wù)器要維護(hù)組,則帳戶的帳戶類型的同步適配器應(yīng)在聯(lián)系人提供程序和服務(wù)器之間傳輸組數(shù)據(jù)。當(dāng)用戶將新聯(lián)系人添加到服務(wù)器,然后將此聯(lián)系人放入新組時,同步適配器必須將新組添加到ContactsContract.Groups表。原始聯(lián)系人所屬的組或組使用ContactsContract.CommonDataKinds.GroupMembership MIME類型存儲在ContactsContract.Data表中。

    如果您正在設(shè)計將原始聯(lián)系人數(shù)據(jù)從服務(wù)器添加到聯(lián)系人提供程序的同步適配器,并且您沒有使用組,則需要告知提供程序使您的數(shù)據(jù)可見。在用戶向設(shè)備添加帳戶時執(zhí)行的代碼中,更新Contacts Provider為該帳戶添加的ContactsContract.Settings行。在此行中,將Settings.UNGROUPED_VISIBLE列的值設(shè)置為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é)中有更詳細(xì)的描述。

    總結(jié)

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

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

    国产亚洲精品久久久久久电影 | 97天堂网 | 探花视频网站 | 天天干中文字幕 | 色五月色开心色婷婷色丁香 | 亚洲视频一区二区三区在线观看 | 99色免费视频 | 亚洲性xxxx | 天天干天天摸天天操 | 久久久久久久久久久久久久av | 97国产精品亚洲精品 | 国产 色 | 91麻豆精品国产91久久久久久 | 欧美成人性网 | 香蕉视频国产在线观看 | 国产精品99久久久精品 | 91看片网址| 五月开心婷婷 | 欧美激情视频一区 | av综合网址| 日韩欧美91 | 亚洲国产精品久久久久 | 啪啪免费观看网站 | 日韩欧美视频一区二区 | 亚洲成a人片在线www | 美女久久一区 | 热久久这里只有精品 | 91九色网址| 在线观看v片 | av高清影院 | 在线激情av电影 | 最近中文字幕免费观看 | 日韩三区在线 | 国产成人a亚洲精品 | 亚洲三级精品 | 99久久99久久精品国产片 | 日本色小说视频 | 日韩av片在线 | 日日夜夜天天射 | 欧美 日韩 国产 成人 在线 | 亚洲女人天堂成人av在线 | 五月婷网 | 91久久丝袜国产露脸动漫 | 国产男女爽爽爽免费视频 | 中文字幕亚洲综合久久五月天色无吗'' | 久久视频免费 | 久久国产精品久久精品 | 天天色综合三 | 日韩有码网站 | 日韩av电影免费观看 | 日韩欧美大片免费观看 | 黄色av免费 | 欧美日韩久久久 | 免费成人av网站 | 麻豆果冻剧传媒在线播放 | 国产高清中文字幕 | 国产精品九九九九九 | 国产精品99久久久精品免费观看 | 在线观看免费版高清版 | 欧美日韩亚洲在线观看 | 亚洲免费色| 亚洲免费色 | av黄色在线观看 | 激情久久小说 | 亚洲综合视频在线 | 友田真希av| 亚洲一片黄 | 天堂av在线免费 | 在线观看视频中文字幕 | 成年人在线免费看 | 欧美日韩国产一区二 | 激情av在线播放 | 国产色视频网站 | 一区二区三区免费网站 | 亚洲毛片一区二区三区 | 天天激情站 | 久久久免费看视频 | 91av视频在线播放 | 黄色小网站在线观看 | 麻花豆传媒mv在线观看 | 337p西西人体大胆瓣开下部 | 黄色亚洲大片免费在线观看 | 久久精品国产一区二区三 | 成人在线你懂得 | av电影在线免费 | 很黄很色很污的网站 | 九九视频免费在线观看 | 综合色爱| 天天色天天射综合网 | 午夜久久久精品 | 国产午夜精品一区二区三区欧美 | 久久亚洲婷婷 | 日韩毛片一区 | 亚洲国产精品500在线观看 | 91九色蝌蚪视频 | 亚洲视频,欧洲视频 | 久久色亚洲 | 日韩视频一区二区三区在线播放免费观看 | 欧美aaa视频 | 在线99| 日韩a在线播放 | 天天干干| 久久手机在线视频 | 国产成人一区二区啪在线观看 | 欧美一级电影免费观看 | 精品日韩av | 91av资源在线| 午夜精品久久久久久久久久 | 91亚洲国产成人 | 色婷婷97 | 日韩在线观看电影 | 香蕉久久久久久av成人 | 成人av电影网址 | 人人干狠狠干 | 色综合久久综合网 | 成人黄视频 | 欧美a级免费视频 | 国产手机免费视频 | 天天五月天色 | 国产原厂视频在线观看 | 亚洲午夜精品久久久久久久久久久久 | 免费看国产曰批40分钟 | 精品国产免费人成在线观看 | 一二三区在线 | 99热在线网站| 黄色大全视频 | 天天艹天天爽 | 欧美aaa一级 | 国产精品久久人 | 一区二区不卡在线观看 | 日韩一级片观看 | 免费在线观看毛片网站 | 欧美黄色成人 | 日韩欧美综合 | 天天天干天天射天天天操 | 日韩在线不卡视频 | 日韩区在线观看 | 日韩女同一区二区三区在线观看 | 久久久五月婷婷 | 国产精品久久人 | 久久久久97国产 | 久久天天拍 | 欧美性生活免费看 | a级国产乱理论片在线观看 伊人宗合网 | 2023亚洲精品国偷拍自产在线 | 日日日操操 | 成人9ⅰ免费影视网站 | 8x成人免费视频 | 亚洲精品福利在线观看 | 麻豆激情电影 | av黄网站 | 日本护士撒尿xxxx18 | 欧美在线久久 | 色婷婷www| 精品久久一区二区三区 | 国产精品嫩草影院9 | 黄色aaa级片| 亚洲精品国产自产拍在线观看 | 国产在线91在线电影 | 国产18精品乱码免费看 | 制服丝袜一区二区 | 国产在线不卡精品 | 国产在线v | 91精品国产欧美一区二区 | 久久人人爽人人爽人人片 | 国产在线久草 | 国产99自拍 | 久久精品屋 | 狠狠狠狠狠狠狠狠干 | 伊人狠狠色丁香婷婷综合 | 国产成人精品一区二区在线观看 | www.婷婷色 | 五月天九九 | 精品美女视频 | 99免费在线视频观看 | 久久人人97超碰com | av字幕在线 | 国产精品1024 | 天天爽天天搞 | 福利网址在线观看 | 国产成人精品在线 | 9草在线| 国产一区二区高清 | 国产精品美女免费看 | 国产女人40精品一区毛片视频 | 天堂av在线免费观看 | 在线影视 一区 二区 三区 | 97超碰站 | 国产婷婷vvvv激情久 | 国产不卡免费视频 | 久久五月情影视 | 久久国产精品99久久久久久老狼 | 五月天亚洲激情 | 久久精品欧美一区二区三区麻豆 | 久久免费视频99 | 午夜精品影院 | 黄色免费视频在线观看 | 欧美 日韩 久久 | 国产精品久久久久久久久费观看 | 欧美一级视频免费看 | 粉嫩高清一区二区三区 | 国产一级大片免费看 | 最新影院 | 国产精品免费一区二区三区在线观看 | 国产精品青草综合久久久久99 | 九九久久国产 | 久久久91精品国产一区二区三区 | 国产小视频在线免费观看 | 国产日韩欧美精品在线观看 | 97视频入口免费观看 | 亚洲一级电影在线观看 | 日韩免费av在线 | 欧美人zozo | 婷婷六月在线 | 91污在线 | 天堂网中文在线 | 国产日韩欧美在线看 | 国产破处在线播放 | 91mv.cool在线观看 | 激情图片久久 | 中文字幕一区二区三区在线观看 | 麻豆高清免费国产一区 | 精品99久久 | 99国产视频在线 | 三级黄色免费片 | 亚洲综合网 | 午夜精品久久久久久中宇69 | 中文字幕中文字幕在线中文字幕三区 | 国产黄在线观看 | 国产一卡二卡在线 | 人人舔人人舔 | 伊人六月 | 色婷婷国产精品一区在线观看 | 成人国产精品久久久久久亚洲 | 国产一区免费视频 | 国产在线第三页 | 日韩精品免费专区 | 少妇超碰在线 | 欧美一级视频免费看 | 97av视频在线观看 | 有码一区二区三区 | 国产美女黄网站免费 | 在线观看视频一区二区 | 日韩免费久久 | 免费在线色视频 | 国产黄色精品视频 | 久久久免费在线观看 | 国产精品免费观看视频 | 激情婷婷久久 | 国产 日韩 欧美 自拍 | 人人爽人人爽人人 | 日日夜夜亚洲 | 天天干天天操人体 | 久久久99国产精品免费 | 亚洲成av人影片在线观看 | 麻豆久久 | 97视频一区 | 大胆欧美gogo免费视频一二区 | 欧美日本不卡视频 | 成年人免费av网站 | 美女搞黄国产视频网站 | 亚洲国产成人精品久久 | 久久国产精品免费 | av不卡中文 | 热re99久久精品国产66热 | 国产黄色免费看 | 日韩在线视频一区二区三区 | 韩日成人av | 国产综合精品久久 | 91片黄在线观 | www.色婷婷.com | 99免费看片 | 久久免费试看 | 狂野欧美激情性xxxx | 日韩在线中文字幕 | 国产精品区二区三区日本 | 中文字幕在线播放一区二区 | 最新日韩视频在线观看 | 免费在线观看av不卡 | 国产黄在线免费观看 | 五月激情五月激情 | 久久视频网址 | www.久久色 | www.五月婷婷 | 欧美精品做受xxx性少妇 | 免费av网址在线观看 | 精品夜夜嗨av一区二区三区 | 在线观看视频一区二区三区 | 91亚洲精品久久久蜜桃借种 | 亚洲精品理论片 | 国产 日韩 中文字幕 | 看v片 | 国产精品一区二区在线看 | 97国产超碰| 日韩亚洲欧美中文字幕 | av中文天堂在线 | 在线国产观看 | 国产剧情一区二区 | 久久精品精品电影网 | 在线视频欧美亚洲 | 久久久国产电影 | 最近最新最好看中文视频 | 天天干天天操天天拍 | 天天综合入口 | 国产精品18久久久久vr手机版特色 | 国产精品美女久久久久久久久 | 久久国产高清 | 久久99精品久久久久久久久久久久 | 成人黄色在线视频 | 亚洲欧美少妇 | 99国产精品一区 | 黄色大片日本免费大片 | 欧美日韩伦理一区 | 青青河边草免费直播 | 国产精品麻豆视频 | 97成人精品 | 麻豆视频免费看 | 国产一区在线免费观看 | 国产成人黄色网址 | 97碰碰精品嫩模在线播放 | 国产精品18毛片一区二区 | 人人添人人 | 国产午夜麻豆影院在线观看 | 亚洲成人精品 | 免费成人黄色 | 亚洲综合视频在线观看 | 91麻豆看国产在线紧急地址 | 欧美天堂久久 | 91网址在线观看 | 国产精品欧美一区二区三区不卡 | 成人午夜av电影 | 日韩精品一区二区三区丰满 | 永久免费在线 | 成人午夜影院 | 国产久草在线 | 首页av在线| 国内精品国产三级国产aⅴ久 | 国产一级黄色免费看 | 久久久久在线视频 | 国产69精品久久99不卡的观看体验 | 日韩免费高清在线 | 成人欧美一区二区三区在线观看 | 欧美大片在线看免费观看 | 中文字幕一区在线观看视频 | 亚洲天天在线日亚洲洲精 | 色婷婷综合视频在线观看 | 天天干天天玩天天操 | 精品视频中文字幕 | 超碰在线观看97 | 午夜在线资源 | 国产人成看黄久久久久久久久 | 毛片网在线播放 | 狠狠色丁香婷婷综合久久片 | 美女视频黄免费网站 | 777久久久 | 97精品国产97久久久久久久久久久久 | 久久久久 免费视频 | 麻豆系列在线观看 | 欧美日韩中文在线观看 | 高清不卡毛片 | 91在线九色| 黄色三级免费网址 | 又黄又爽的免费高潮视频 | 开心丁香婷婷深爱五月 | 亚洲午夜久久久综合37日本 | 99精品久久精品一区二区 | 日韩视频一区二区三区在线播放免费观看 | 精油按摩av | 婷婷丁香自拍 | 高清色免费 | 国产精品一区二区62 | 波多野结衣精品视频 | 亚洲做受高潮欧美裸体 | 麻豆国产露脸在线观看 | 日韩高清www | 日韩高清精品免费观看 | 人人爽人人爽人人片av免 | 色狠狠综合 | 天天爱天天 | 91久久国产自产拍夜夜嗨 | 欧美精品一区二区三区四区在线 | 777视频在线观看 | 91插插插免费视频 | 天天干夜夜想 | 青青草国产精品 | 九色视频自拍 | 久久97视频| 亚洲精品国产精品国自产 | 国产女教师精品久久av | av免费观看在线 | 中文字幕精品一区久久久久 | 亚洲激精日韩激精欧美精品 | 亚洲综合色网站 | 一区三区在线欧 | 国产精品21区 | 久久精品精品电影网 | 在线观看免费黄色 | 久久不卡av | 国产一级高清 | 综合精品在线 | 夜色资源站国产www在线视频 | 黄网站免费看 | 日本特黄一级片 | 国产精品成人a免费观看 | 国产精品久久久久久一区二区三区 | 久久毛片视频 | 中文字幕高清有码 | 天天插综合| 国产黄色精品在线观看 | 精品久久网 | 国产精品刺激对白麻豆99 | 成人在线观看免费 | 91九色网站 | 日韩午夜av| 91系列在线 | 中文字幕色播 | 夜夜躁日日躁狠狠久久av | 国产精品久久久精品 | 天天插天天干天天操 | 99在线视频播放 | 在线看一区 | 国产原创中文在线 | 成人黄大片视频在线观看 | 狠狠操欧美 | 国产成人精品一区二区三区在线 | 色婷婷九月| 色综合狠狠干 | 国产精品永久 | 91香蕉久久 | 黄色网址国产 | a'aaa级片在线观看 | 久久久99精品免费观看乱色 | 91视频免费视频 | 国产精品福利久久久 | 蜜臀久久99静品久久久久久 | 亚洲少妇久久 | 深爱婷婷激情 | 伊人永久 | 九九精品无码 | 手机看片中文字幕 | 黄色精品一区二区 | 日韩精品你懂的 | 一区二区三区电影 | 深爱激情亚洲 | 麻豆免费视频观看 | 免费福利片2019潦草影视午夜 | 国产香蕉在线 | 尤物一区二区三区 | 精品国内自产拍在线观看视频 | 激情五月婷婷综合 | 国产精品美女久久久久aⅴ 干干夜夜 | 国产成人精品999在线观看 | 97免费中文视频在线观看 | 国产婷婷vvvv激情久 | 在线视频 你懂得 | 久操免费视频 | 日韩免费av网址 | 91污视频在线观看 | 日韩成人高清在线 | 色天堂在线视频 | 91精品黄色 | 91天堂在线观看 | 狠狠色噜噜狠狠狠合久 | 黄色三级视频片 | 亚洲精品理论 | 久久激情五月婷婷 | 久久国语露脸国产精品电影 | 国产精品伦一区二区三区视频 | 98精品国产自产在线观看 | 久精品视频在线 | 国产亚洲高清视频 | 久久久久久久综合色一本 | 美女av免费| 狠狠狠色丁香综合久久天下网 | 国产系列精品av | 免费日韩一区 | 天天色天| 九九热只有这里有精品 | 国产亚洲精品久久19p | 国产精品视频内 | 狠狠色伊人亚洲综合网站野外 | 九九亚洲视频 | 最近2019中文免费高清视频观看www99 | 精品国产人成亚洲区 | 在线你懂的视频 | 男女精品久久 | www.天天操.com | 国产资源精品在线观看 | 夜夜操网| 国产一区二区三区午夜 | 四虎影视精品 | 日韩一级片网址 | 99精品小视频 | 狠狠狠色丁香婷婷综合久久五月 | 日韩一区二区久久 | 久久免费中文视频 | 五月天狠狠操 | 免费视频在线观看网站 | 91中文字幕视频 | 在线黄色av电影 | 国内精品久久久久 | 免费在线观看成人小视频 | 不卡日韩av | 欧美视频日韩视频 | 成人久久久电影 | 日韩精品中文字幕有码 | 日韩丝袜视频 | 97精品国产97久久久久久粉红 | 欧美-第1页-屁屁影院 | 最近免费在线观看 | 国产精品自在欧美一区 | 午夜久久久久久久久 | 久久尤物电影视频在线观看 | 久久综合福利 | 国产视频2| 日韩欧美综合精品 | 国产精品久久久777 成人手机在线视频 | 中文字幕超清在线免费 | 99国产一区 | 久久精品99视频 | 久久精品资源 | 在线www色| 日韩在线观看a | 成人在线观看资源 | 免费情趣视频 | 亚洲精品福利在线 | 国产破处在线视频 | 男女拍拍免费视频 | 久热超碰| 夜夜操天天操 | 日韩成人免费观看 | 久久久久久精 | 日韩免费久久 | 日韩欧美高清免费 | 97精产国品一二三产区在线 | 欧美日韩首页 | www日韩| 丁香激情视频 | 欧美巨乳网 | 五月天中文在线 | 黄色中文字幕在线 | 免费涩涩网站 | 国产精品毛片一区视频播不卡 | 91一区一区三区 | 91精品一区二区三区蜜臀 | 国产中文a| 91黄色小视频| 91av蜜桃| 四虎在线免费 | 日本高清久久久 | 国产91精品欧美 | av高清不卡 | 国产精品久久久久久爽爽爽 | 久99久久 | 日韩精品极品视频 | 婷婷久久精品 | 新版资源中文在线观看 | 成年人av在线播放 | 九九热视频在线 | 中文字幕乱码日本亚洲一区二区 | 91cn国产在线 | 久久国产精品99久久久久久丝袜 | 99久热在线精品视频 | 中文字幕二区在线观看 | 精品国产区在线 | 亚洲一区二区麻豆 | 一区二区三区精品在线视频 | 在线观看日本高清mv视频 | 午夜性生活片 | 国产精品久久久久久久久费观看 | 91久久国产综合精品女同国语 | 黄色一级影院 | 国际av在线 | 91福利视频免费观看 | 日韩欧美视频一区二区 | 国产一区二区影院 | 在线观看完整版免费 | 日韩av午夜在线观看 | 天天综合天天综合 | 久久久久女人精品毛片 | 欧美日韩视频一区二区 | 午夜狠狠干 | 亚洲在线视频网站 | 日本久草电影 | 狠狠久久伊人 | 亚洲老妇xxxxxx | 最近免费中文视频 | 成人h电影在线观看 | 国产黄色av| 人人添人人澡人人澡人人人爽 | 9999激情 | 久香蕉| 日韩高清av | 精品国产一区二区三区噜噜噜 | 成人黄色电影在线观看 | 中文字幕在线影院 | 中文字幕欧美日韩va免费视频 | 2019中文字幕网站 | 黄色网免费| 操操操日日 | 国产精品久久久免费 | 国产成人精品一区二区在线 | 成人app在线播放 | 日韩视频免费看 | 欧美男男tv网站 | 一区二区三区av在线 | 久草在线国产 | 日日干美女 | 婷婷成人亚洲综合国产xv88 | 天天玩天天干天天操 | 国产激情电影综合在线看 | 国内久久看 | 免费看片日韩 | 精品久久久久久国产91 | 中文字幕你懂的 | 视频福利在线观看 | 在线观看视频97 | 天天鲁天天干天天射 | 玖玖在线视频观看 | 欧美一级xxxx| 一区在线观看视频 | 99久久夜色精品国产亚洲 | 91精品国产91久久久久福利 | 亚洲欧美国产精品18p | 国产精品第二页 | 欧美一级电影在线观看 | 免费日韩高清 | 国产视频一区二区在线 | 久久久久久久久毛片 | 日韩91在线| 国产精品夜夜夜一区二区三区尤 | 中文字幕一区2区3区 | 国产精品99久久久久的智能播放 | 欧美孕妇视频 | 国产精品久久久久久久免费 | 久草电影在线 | 国产在线观看,日本 | 日日干夜夜干 | 亚洲狠狠丁香婷婷综合久久久 | 亚洲国产丝袜在线观看 | 日本特黄一级 | 国产一区欧美二区 | 亚洲精品小区久久久久久 | 天天色图 | 999久久久久久久久6666 | 成人av资源网站 | 18岁免费看片| av激情五月 | 91麻豆精品91久久久久同性 | 麻豆 free xxxx movies hd | 日韩激情网 | 在线免费观看国产视频 | 久草在线视频资源 | www.av小说 | 久久国产精品99久久久久 | 伊人小视频 | 欧美日韩国产高清视频 | 伊人色综合网 | 国产精品99久久99久久久二8 | 久久久久久久久久影院 | 黄色大全在线观看 | 丝袜+亚洲+另类+欧美+变态 | 91九色在线| 在线 国产 日韩 | 久久成人国产 | 日韩sese| 国产亚洲精品综合一区91 | 欧美日韩精品二区第二页 | 香蕉视频网址 | www激情久久 | 91资源在线播放 | 国产精品久久久久影院日本 | 国产精品美女久久久网av | 久久理论电影 | 日韩精品中文字幕在线 | 特级西西444www大精品视频免费看 | 天天摸日日摸人人看 | 免费观看全黄做爰大片国产 | 国产视频精品免费 | 99久久婷婷国产综合精品 | 免费av网站在线 | 国产黄色视 | 亚洲国产欧美在线人成大黄瓜 | 久草视频网 | 福利二区视频 | 九九视频免费在线观看 | 深夜视频久久 | 午夜视频在线观看欧美 | 国产精品入口麻豆www | 国产婷婷在线观看 | 正在播放国产精品 | www.com久久久 | 美女免费视频网站 | 一区二区三区四区五区六区 | 人人插人人插 | 午夜影院一级片 | 日批视频在线观看免费 | 天天操综合 | 欧美日韩国产一区 | 中文永久免费观看 | www.日本色 | 91精品夜夜| 精品国偷自产在线 | 久久综合久久综合这里只有精品 | 福利视频第一页 | 国产成人一区二区三区在线观看 | 日韩在线视频免费看 | 91精品在线播放 | 亚洲人av免费网站 | 久久久久久久综合色一本 | 国产亚洲久一区二区 | 69国产精品成人在线播放 | 五月婷香蕉久色在线看 | 免费在线观看国产黄 | 综合网欧美 | 精品美女在线观看 | 91精品一区二区三区蜜桃 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 亚洲午夜久久久久 | 国产精品久久久一区二区 | 午夜久久成人 | 久久视频99 | 九九热av| 午夜电影久久 | 久久久www| 中文字幕在线视频免费播放 | 日日夜夜精品免费 | 成人天堂网 | 国产乱对白刺激视频不卡 | 久久久久久久久久网 | 亚洲高清在线精品 | 中文字幕av在线免费 | 91精品国产91久久久久久三级 | 国产高清视频免费最新在线 | 久久精品网址 | 久久久精品国产一区二区三区 | 亚州精品在线视频 | 99色视频 | 午夜视频在线观看网站 | 国产精品21区 | 黄色网免费 | 狠狠干综合网 | 成人av片在线观看 | 成人久久久久久久久 | 视频一区二区视频 | 日产中文字幕 | 天堂av在线免费观看 | 亚洲永久精品在线 | 免费观看不卡av | 伊人天天狠天天添日日拍 | 亚洲午夜激情网 | 97超级碰碰碰碰久久久久 | 91最新国产| 毛片网在线 | 亚洲自拍偷拍色图 | 超碰在线日本 | 91黄色免费网站 | 婷婷伊人五月天 | 激情小说久久 | 日韩精品第1页 | 日本中文字幕一二区观 | 香蕉看片| 97精品国产 | 欧美精品在线观看一区 | 91传媒免费在线观看 | 一区二区视频电影在线观看 | 午夜精品久久一牛影视 | 高清精品视频 | 日韩在线色| 中文字幕一区二区三区四区久久 | 日韩资源在线播放 | 最近日本韩国中文字幕 | 国产成人一区二区在线观看 | www.香蕉视频在线观看 | www亚洲国产| 日韩免费一区二区在线观看 | 精品福利在线观看 | 久久,天天综合 | 九九久久久久99精品 | 国产精品成人久久久 | 欧美日韩高清一区 | 日本精品二区 | 亚洲第一av在线播放 | 爱射综合 | 欧美视频www| 99 色| 日韩欧美国产激情在线播放 | 色a网 | 久久综合久久综合这里只有精品 | 亚洲国产久 | 国产一级二级视频 | 国产三级av在线 | 国产精品s色 | 国产精品无av码在线观看 | 激情欧美xxxx | a色视频 | 午夜精品久久久久久久爽 | 五月天婷婷免费视频 | 丰满少妇久久久 | 18国产精品福利片久久婷 | 日韩av免费一区二区 | 久久午夜鲁丝片 | 日韩精品免费在线 | 国产视频1区2区 | 日日干美女 | 天天干天天操av | 久草视频中文 | 国产一区二区免费看 | 久久久久久久久综合 | 久久精品爱视频 | 欧美日韩国产综合一区二区 | 亚洲激情网站免费观看 | 日韩一级电影网站 | 色婷婷综合久久久久中文字幕1 | 国产对白av | 精品久久一区二区 | 国产香蕉av| 在线 成人 | 一区二区激情 | 久草视频免费看 | 亚洲国产中文字幕在线 | 五月天综合激情 | 超碰97成人 | 欧美大荫蒂xxx | 中文字幕视频播放 | av免费电影在线观看 | 欧美日韩一区二区在线观看 | 主播av在线 | 中文字幕国语官网在线视频 | 久草网站在线 | 精品国产理论片 | 午夜av电影院 | 免费看一级 | 色香com. | 在线99视频| 又黄又爽又湿又无遮挡的在线视频 | 色综合五月 | 欧美永久视频 | 日日爽天天爽 | 高清不卡一区二区三区 | 亚洲精品免费观看视频 | 99久久精品免费一区 | 国产在线播放观看 | 精品久久久久久国产 | 最新日本中文字幕 | 亚洲高清精品在线 | 在线观看中文字幕一区二区 | 91久久爱热色涩涩 | 日韩丝袜在线观看 | 69国产盗摄一区二区三区五区 | 久久综合色一综合色88 | 一区二区三区日韩精品 | 久草视频观看 | 99九九99九九九视频精品 | 日韩精品三区四区 | 欧美日韩一级在线 | 五月天,com| 最新极品jizzhd欧美 | 玖玖爱免费视频 | 在线看成人| 国产精品第二页 | 一级黄色片毛片 | 综合五月婷婷 | 中文av一区二区 | 国产精品久久久久久久免费 | 三级av网 | 在线免费av电影 | 久久成人一区二区 | 97成人免费视频 | 国产99久久九九精品 | 久久九九九九 | 亚洲专区在线播放 | 国产免费午夜 | 成人午夜影视 | 国产高清绿奴videos | 中文av影院 | 天天天干天天天操 | 欧美日韩国产精品一区二区三区 | 天天射网| 波多野结衣视频一区二区三区 | 亚洲一区二区观看 | 日本特黄一级 | 色婷婷色| 日产av在线播放 | 狠狠躁夜夜av| 91看片在线 | 亚洲91在线| 中文字幕欲求不满 | 亚洲精品国产综合99久久夜夜嗨 | 中文字幕精品一区久久久久 | 中文字幕一区av | av短片在线观看 | 久久96| 狠狠狠色丁香婷婷综合久久88 | 在线 视频 一区二区 | 国产乱对白刺激视频在线观看女王 | 婷婷色在线| 国产成人资源 | 日韩一级电影在线观看 | 五月开心色 | 国产在线色 | 色播六月天 | 天天干天天综合 | www.com久久久 | 六月色丁 | 亚洲色图色 | 国产在线无 | 波多野结衣精品视频 | 日韩成人黄色av | 国内精品久久久久影院日本资源 | 日韩免费不卡av | 又色又爽又黄高潮的免费视频 | 国产小视频在线观看免费 | 精品一区二三区 | 亚洲在线视频播放 | aaa黄色毛片| 四虎最新入口 | 国产不卡视频在线播放 | 国产人在线成免费视频 | 免费看国产一级片 | 久久成人在线视频 | 久久丁香| 伊人五月 | 91精品国产高清自在线观看 | 狠狠88综合久久久久综合网 | 久久久免费精品视频 | 国产在线国产 | 嫩草91影院 | 亚洲视屏 | 国内精品一区二区 | 欧美精品一区二区三区一线天视频 | 欧美日韩精品在线播放 | 人人玩人人添人人澡97 | 久久久久久久av | 99精品久久久久久久 | 97成人在线| 黄色aaa级片 | 九九热免费观看 | 91久色蝌蚪 | 国产大片免费久久 | 久久高清片 | 国产在线 一区二区三区 | 国内丰满少妇猛烈精品播 | 麻豆视频www | 69国产盗摄一区二区三区五区 | 久热免费在线观看 | 成人免费 在线播放 | 国产精品永久在线 | 成人中文字幕+乱码+中文字幕 | 久久艹国产视频 | 99视频精品免费视频 | 欧美一区二区视频97 | 国产一级视频在线免费观看 | 99视频播放 | 美女视频黄是免费的 | 免费日韩一区二区三区 | 97色视频在线 | 免费观看国产精品视频 | 欧洲精品一区二区 | 国产精品不卡一区 | 亚洲精品美女 | 99久久99视频 | 五月天com| 欧美日韩国产一二三区 | 成人污视频在线观看 | a级国产乱理论片在线观看 伊人宗合网 | 久久婷婷一区二区三区 | 91中文字幕在线 | 中文字幕一区av | 国产在线v| 婷婷色综 | 日韩在线免费看 | 人人要人人澡人人爽人人dvd | 精品播放| 欧美一二三四在线 | 五月在线视频 | 狠狠的干狠狠的操 | 免费成人av网站 | 国产视频丨精品|在线观看 国产精品久久久久久久久久久久午夜 | 久草视频播放 | 日韩性xxx| 久久一级电影 | 欧美日韩在线播放一区 | 久久福利剧场 | 国产精品永久在线观看 | 91尤物在线播放 | 黄色精品国产 | 日韩手机视频 | 亚州精品在线视频 | 久久久久久高潮国产精品视 | 99精品国产免费久久久久久下载 | 国产精品久久久久久久久久三级 | 不卡的av片 | 免费av看片 | 免费视频三区 | 亚洲人成影院在线 | 亚洲综合一区二区精品导航 | 狠狠色伊人亚洲综合网站色 |