1page.title=聯絡人供應程式 2@jd:body 3<div id="qv-wrapper"> 4<div id="qv"> 5<h2>快速檢視</h2> 6<ul> 7 <li>Android 關於人員資訊的存放庫。</li> 8 <li> 9 與網頁同步。 10 </li> 11 <li> 12 整合社交串流資料。 13 </li> 14</ul> 15<h2>本文件內容</h2> 16<ol> 17 <li> 18 <a href="#InformationTypes">聯絡人供應程式組織架構</a> 19 </li> 20 <li> 21 <a href="#RawContactBasics">原始聯絡人</a> 22 </li> 23 <li> 24 <a href="#DataBasics">資料</a> 25 </li> 26 <li> 27 <a href="#ContactBasics">聯絡人</a> 28 </li> 29 <li> 30 <a href="#Sources">來自同步配接器的資料</a> 31 </li> 32 <li> 33 <a href="#Permissions">必要權限</a> 34 </li> 35 <li> 36 <a href="#UserProfile">使用者設定檔</a> 37 </li> 38 <li> 39 <a href="#ContactsProviderMetadata">聯絡人供應程式中繼資料</a> 40 </li> 41 <li> 42 <a href="#Access">聯絡人供應程式存取</a> 43 <li> 44 </li> 45 <li> 46 <a href="#SyncAdapters">聯絡人供應程式同步配接器</a> 47 </li> 48 <li> 49 <a href="#SocialStream">社交串流資料</a> 50 </li> 51 <li> 52 <a href="#AdditionalFeatures">其他聯絡人供應程式功能</a> 53 </li> 54</ol> 55<h2>重要類別</h2> 56<ol> 57 <li>{@link android.provider.ContactsContract.Contacts}</li> 58 <li>{@link android.provider.ContactsContract.RawContacts}</li> 59 <li>{@link android.provider.ContactsContract.Data}</li> 60 <li>{@code android.provider.ContactsContract.StreamItems}</li> 61</ol> 62<h2>相關範例</h2> 63<ol> 64 <li> 65 <a href="{@docRoot}resources/samples/ContactManager/index.html">聯絡人管理員 66</a> 67 68 </li> 69 <li> 70 <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html"> 71範例同步配接器</a> 72 </li> 73</ol> 74<h2>另請參閱</h2> 75<ol> 76 <li> 77 <a href="{@docRoot}guide/topics/providers/content-provider-basics.html"> 78 內容供應程式基本概念 79 </a> 80 </li> 81</ol> 82</div> 83</div> 84<p> 85 聯絡人供應程式是強大且有彈性的 Android 元件,負責管理裝置上與人員相關的中央資料存放庫。 86聯絡人供應程式是裝置中聯絡人應用程式的資料來源,您也可以在自己的應用程式中存取其資料,並且在裝置和線上服務之間傳輸資料。 87 88供應程式內含範圍寬廣的資料來源,而且嘗試管理每個人愈來愈多的資料,組織架構因而變得很複雜。 89 90基於這個原因,供應程式的 API 包括豐富的合約類別和介面,可幫助資料的擷取和修改。 91 92 93</p> 94<p> 95 本指南描述以下各項: 96</p> 97 <ul> 98 <li> 99 基本的供應程式結構。 100 </li> 101 <li> 102 如何從供應程式擷取資料。 103 </li> 104 <li> 105 如何修改供應程式中的資料。 106 </li> 107 <li> 108 如何針對從伺服器到聯絡人供應程式的資料同步編寫同步配接器。 109 110 </li> 111 </ul> 112<p> 113 本指南假設您瞭解 Android 內容供應程式基本概念。如要更瞭解 Android 內容供應程式的詳細資訊,請閱讀<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">內容供應程式基本概念</a>指南。 114 115 116<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">範例同步配接器</a>範例應用程式是使用同步配接器在聯絡人供應程式和 Google 網路服務代管的範例應用程式之間傳輸資料的例子。 117 118 119 120</p> 121<h2 id="InformationTypes">聯絡人供應程式組織架構</h2> 122<p> 123 聯絡人供應程式是 Android 內容供應程式元件。負責維護三種與人有關的資料類型,每一種類型都會對應到供應程式所提供的表格,如圖 1 所示: 124 125 126</p> 127<img src="{@docRoot}images/providers/contacts_structure.png" alt="" height="364" id="figure1" /> 128<p class="img-caption"> 129 <strong>圖 1.</strong>聯絡人供應程式表格結構。 130</p> 131<p> 132 這三個表格通常會以其合約類別的名稱來稱呼。類別會定義內容 URI 的常數、欄名稱以及表格所使用的欄值: 133 134</p> 135<dl> 136 <dt> 137 {@link android.provider.ContactsContract.Contacts} 表格 138 </dt> 139 <dd> 140 根據原始聯絡人列的彙總,代表不同人員的列。 141 </dd> 142 <dt> 143 {@link android.provider.ContactsContract.RawContacts} 表格 144 </dt> 145 <dd> 146 內含人員資料摘要的列,針對使用者帳戶和類型。 147 </dd> 148 <dt> 149 {@link android.provider.ContactsContract.Data} 表格 150 </dt> 151 <dd> 152 內含原始聯絡人詳細資料的列,例如電子郵件地址或電話號碼。 153 </dd> 154</dl> 155<p> 156 合約類別在 {@link android.provider.ContactsContract} 中呈現的其他表格都是輔助表格。聯絡人供應程式使用輔助表格來管理其操作,或支援裝置中聯絡人或電話應用程式的特定功能。 157 158 159</p> 160<h2 id="RawContactBasics">原始聯絡人</h2> 161<p> 162 原始聯絡人是來自單一帳戶類型和帳戶名稱的人員資料。 163因為聯絡人供應程式允許一個人有多種線上服務做為資料來源,所以聯絡人供應程式可以讓同一個人有多個原始聯絡人。 164 165 多個原始聯絡人也可以讓使用者,將相同帳戶類型中多個帳戶的人員資料合併。 166 167</p> 168<p> 169 原始聯絡人的大部分資料不是儲存在 170{@link android.provider.ContactsContract.RawContacts} 表格,而是儲存在 {@link android.provider.ContactsContract.Data} 表格中的一或多個列。 171每個資料列都有一欄 172{@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID Data.RAW_CONTACT_ID},當中包含其上層資料列 {@link android.provider.ContactsContract.RawContacts} 的 {@code android.provider.BaseColumns#_ID RawContacts._ID} 值。 173 174 175</p> 176<h3 id="RawContactsColumns">重要的原始聯絡人欄</h3> 177<p> 178 {@link android.provider.ContactsContract.RawContacts} 表格中的重要欄列於表 1。 179請詳閱表格下方的注意事項: 180</p> 181<p class="table-caption" id="table1"> 182 <strong>表 1.</strong>重要的原始聯絡人欄。 183</p> 184<table> 185 <tr> 186 <th scope="col">欄名稱</th> 187 <th scope="col">用途</th> 188 <th scope="col">備註</th> 189 </tr> 190 <tr> 191 <td> 192 {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_NAME} 193 </td> 194 <td> 195 帳戶類型 (此原始聯絡人的來源) 的帳戶名稱。 196 例如,Google 帳戶的帳戶名稱是裝置擁有者的其中一個 Gmail 地址。 197請參閱下一個項目,進一步瞭解 198 {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE}。 199 200 </td> 201 <td> 202 不同的帳戶類型的名稱格式各不相同。帳戶名稱不一定是電子郵件地址。 203 204 </td> 205 </tr> 206 <tr> 207 <td> 208 {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE} 209 </td> 210 <td> 211 帳戶類型是此原始聯絡人的來源。例如,Google 帳戶的帳戶類型為 <code>com.google</code>。 212一定要將帳戶類型加上您所擁有或控制網域的網域識別碼。 213這樣可以確認您的帳戶類型是唯一的。 214 215 </td> 216 <td> 217 提供聯絡人資料的帳戶類型通常有關聯的同步配接器,可以與聯絡人供應程式同步。 218 219 </tr> 220 <tr> 221 <td> 222 {@link android.provider.ContactsContract.RawContactsColumns#DELETED} 223 </td> 224 <td> 225 原始聯絡人的「已刪除」旗標。 226 </td> 227 <td> 228 此旗標讓聯絡人供應程式可以在內部維護列,直到同步配接器從其伺服器刪除該列,最後從存放庫刪除該列。 229 230 231 </td> 232 </tr> 233</table> 234<h4>備註</h4> 235<p> 236 以下是有關 237 {@link android.provider.ContactsContract.RawContacts} 表格的注意事項: 238</p> 239<ul> 240 <li> 241 原始聯絡人的名稱不是儲存於本身在 242{@link android.provider.ContactsContract.RawContacts} 的列,而是儲存在 {@link android.provider.ContactsContract.Data} 表格的 243 {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} 列中。 244原始聯絡人在 {@link android.provider.ContactsContract.Data} 表格中只有一列這種類型。 245 246 </li> 247 <li> 248 <strong>注意:</strong>如要使用您在原始聯絡人列中自己的帳戶資料,必須先向 {@link android.accounts.AccountManager} 註冊。 249如要註冊,請提示使用者將帳戶類型及其帳戶名稱新增至帳戶清單。 250如果沒有這麼做,聯絡人供應程式將自動刪除您的原始聯絡人列。 251 252 <p> 253 例如,如果您希望應用程式維護網域為 {@code com.example.dataservice} 網頁式服務的聯絡人資料,此服務的使用者帳戶是 {@code becky.sharp@dataservice.example.com},這名使用者必須先新增帳戶「類型」({@code com.example.dataservice}) 和帳戶「名稱」 254({@code becky.smart@dataservice.example.com}),您的應用程式才能新增原始聯絡人列。 255 256 257 258 您可以在文件中向使用者說明此需求,或提示使用者同時新增類型和名稱。 259帳戶類型和帳戶名稱在下一節有更詳細的說明。 260 261 </li> 262</ul> 263<h3 id="RawContactsExample">原始聯絡人資料的來源</h3> 264<p> 265 如要瞭解原始聯絡人的運作方式,假設一位使用者 Emily Dickinson 在其裝置上定義了下列三個使用者帳戶: 266 267</p> 268<ul> 269 <li><code>emily.dickinson@gmail.com</code></li> 270 <li><code>emilyd@gmail.com</code></li> 271 <li>Twitter 帳戶「belle_of_amherst」</li> 272</ul> 273<p> 274 此使用者在「帳戶」<em></em>設定中為這三個帳戶啟用了「同步聯絡人」<em></em>。 275 276</p> 277<p> 278 假設 Emily Dickinson 開啟瀏覽器視窗,使用 279 <code>emily.dickinson@gmail.com</code>登入 Gmail,開啟[聯絡人] 並新增「Thomas Higginson」。 280接著,她使用 281 <code>emilyd@gmail.com</code>登入 Gmail,並寄送電子郵件給「Thomas Higginson」(系統已自動將他新增為聯絡人)。 282她也在 Twitter 上關注「colonel_tom」(Thomas Higginson 的 Twitter ID)。 283 284</p> 285<p> 286 聯絡人供應程式建立三個原始聯絡人的方式如下: 287</p> 288<ol> 289 <li> 290 「Thomas Higginson」的原始聯絡人與 <code>emily.dickinson@gmail.com</code> 相關聯。 291 該使用者帳戶類型為 Google。 292 </li> 293 <li> 294 「Thomas Higginson」的第二個原始聯絡人與 <code>emilyd@gmail.com</code> 相關聯。 295 該使用者帳戶類型也是 Google。儘管第二個原始聯絡人的名稱與前一個名稱完全相同,但此人是針對不同使用者帳戶所新增的。 296 297 298 </li> 299 <li> 300 「Thomas Higginson」的第三個原始聯絡人與「belle_of_amherst」相關聯。該使用者帳戶類型是 Twitter。 301 302 </li> 303</ol> 304<h2 id="DataBasics">資料</h2> 305<p> 306 如前所述,原始聯絡人的資料是儲存在 307 {@link android.provider.ContactsContract.Data} 列,而此列會連結到原始聯絡人的 308 <code>_ID</code> 值。這樣讓原始聯絡人的相同資料類型可以有多個執行個體,例如電子郵件地址或電話號碼。 309例如,如果{@code emilyd@gmail.com} 的 "Thomas Higginson" (Thomas Higginson 的原始聯絡人列,與 Google 帳戶 <code>emilyd@gmail.com</code> 關聯) 的住家電子郵件地址為 310 <code>thigg@gmail.com</code>,而工作電子郵件地址為 311 <code>thomas.higginson@gmail.com</code>,則聯絡人供應程式會儲存這兩個電子郵件地址列,並將兩者連結到原始聯絡人。 312 313 314 315</p> 316<p> 317 請注意,此單一表格中儲存了不同類型的資料。{@link android.provider.ContactsContract.Data} 表格中可以看到顯示名稱、電話號碼、電子郵件、郵寄地址、相片以及網站詳細資料等列。 318 319為了協助管理這些內容, 320{@link android.provider.ContactsContract.Data} 表格有一些欄附有描述性名稱,而其他欄則有一般名稱。 321描述性名稱欄的內容有相同的意義 (無論列中的資料類型為何),而一般名稱欄的內容則視資料的類型會有不同的意義。 322 323 324</p> 325<h3 id="DescriptiveColumns">描述性欄名稱</h3> 326<p> 327 以下提供幾個描述性欄名稱範例: 328</p> 329<dl> 330 <dt> 331 {@link android.provider.ContactsContract.Data#RAW_CONTACT_ID} 332 </dt> 333 <dd> 334 原始聯絡人 <code>_ID</code> 欄的資料值。 335 </dd> 336 <dt> 337 {@link android.provider.ContactsContract.Data#MIMETYPE} 338 </dt> 339 <dd> 340 儲存在此列中的資料類型,以自訂 MIME 類型表示。聯絡人供應程式會使用 341 {@link android.provider.ContactsContract.CommonDataKinds} 子類別中定義的MIME 類型。 342這些 MIME 類型屬開放原始碼,可以和聯絡人供應程式搭配的任何應用程式或同步配接器都可以加以使用。 343 344 </dd> 345 <dt> 346 {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} 347 </dt> 348 <dd> 349 如果原始聯絡人的此類型資料列出現多次,則 350 {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} 欄會在包含主要資料類型的資料列加上旗標。 351例如,使用者長按聯絡人的電話號碼並選取 [設為預設值]<strong></strong>,則包含該號碼的 {@link android.provider.ContactsContract.Data} 列就會將它的 {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} 欄設為零以外的值。 352 353 354 355 356 </dd> 357</dl> 358<h3 id="GenericColumns">一般欄名稱</h3> 359<p> 360 一般欄有 15 個 (名稱為 <code>DATA1</code> 到 361 <code>DATA15</code>),系統通常會提供這些欄。另外有 4 個一般欄(<code>SYNC1</code> 到 <code>SYNC4</code>) 只能透過同步配接器使用。 362 363不管列中的資料類型為何,一定可以使用一般欄名稱常數。 364 365</p> 366<p> 367 <code>DATA1</code> 欄會建立索引。聯絡人供應程式一律會使用此欄的資料,而且供應程式預期此欄為最常查詢的目標。 368例如,在電子郵件列中,此欄內含實際的電子郵件地址。 369 370</p> 371<p> 372 一般來說,<code>DATA15</code> 欄會保留用於儲存「二進位大型物件」(BLOB) 資料,例如相片縮圖。 373 374</p> 375<h3 id="TypeSpecificNames">類型特定的欄名稱</h3> 376<p> 377 為了要協助欄處理具有特定類型的列,聯絡人供應程式也提供類型特定的欄名稱常數。這些常數會在 378 {@link android.provider.ContactsContract.CommonDataKinds}的子類別中定義。 379常數只是為相同欄名稱指定不同的常數名稱,以協助您存取列中特定類型的資料。 380 381 382</p> 383<p> 384 例如,{@link android.provider.ContactsContract.CommonDataKinds.Email} 類別定義了 {@link android.provider.ContactsContract.Data} 列的類型特定欄名稱常數。此列內含 MIME 類型 {@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_ITEM_TYPE 385Email.CONTENT_ITEM_TYPE}。 386 387 388類別含有電子郵件地址欄的常數 389 {@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS}。 390 391 {@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS}的實際值是「data1」。此值與欄的一般名稱相同。 392 393</p> 394<p class="caution"> 395 <strong>注意:</strong>如果 396 {@link android.provider.ContactsContract.Data} 表格使用供應程式預先定義 MIME 類型的其中一種,請不要將您自訂的資料新增至此表格。 397假如將您自訂的資料新增至此表格,可能會遺失資料或讓供應程式發生故障。 398例如,您不應該將含有 MIME 類型 {@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_ITEM_TYPE 399Email.CONTENT_ITEM_TYPE} (內含使用者名稱,而不是電子郵件地址) 的列新增至 <code>DATA1</code> 欄。 400 401如果您的列使用自訂 MIME 類型,那麼您可以自行定義專屬的類型特定的欄名稱,並按照您的需求使用這些欄。 402 403</p> 404<p> 405 圖 2 顯示描述性欄和資料欄顯示在 406 {@link android.provider.ContactsContract.Data} 列的樣式,以及類型特定欄名稱與一般欄名稱的「重疊」方式。 407 408</p> 409<img src="{@docRoot}images/providers/data_columns.png" alt="How type-specific column names map to generic column names" height="311" id="figure2" /> 410<p class="img-caption"> 411 <strong>圖 2.</strong>特定類型欄名稱與一般欄名稱。 412</p> 413<h3 id="ColumnMaps">特定類型欄名稱類別</h3> 414<p> 415 表 2 列出最常用的特定類型欄名稱類別: 416</p> 417<p class="table-caption" id="table2"> 418 <strong>表 2.</strong>特定類型欄名稱類別</p> 419<table> 420 <tr> 421 <th scope="col">對應類別</th> 422 <th scope="col">資料類型</th> 423 <th scope="col">備註</th> 424 </tr> 425 <tr> 426 <td>{@link android.provider.ContactsContract.CommonDataKinds.StructuredName}</td> 427 <td>原始聯絡人 (與此資料列相關聯) 的名稱資料。</td> 428 <td>原始聯絡人只有一列此資料。</td> 429 </tr> 430 <tr> 431 <td>{@link android.provider.ContactsContract.CommonDataKinds.Photo}</td> 432 <td>原始聯絡人 (與此資料列相關聯) 的主要相片。</td> 433 <td>原始聯絡人只有一列此資料。</td> 434 </tr> 435 <tr> 436 <td>{@link android.provider.ContactsContract.CommonDataKinds.Email}</td> 437 <td>原始聯絡人 (與此資料列相關聯) 的電子郵件地址。</td> 438 <td>原始聯絡人可以有多個電子郵件地址。</td> 439 </tr> 440 <tr> 441 <td>{@link android.provider.ContactsContract.CommonDataKinds.StructuredPostal}</td> 442 <td>原始聯絡人 (與此資料列相關聯) 的郵寄地址。</td> 443 <td>原始聯絡人可以有多個郵寄地址。</td> 444 </tr> 445 <tr> 446 <td>{@link android.provider.ContactsContract.CommonDataKinds.GroupMembership}</td> 447 <td>將原始聯絡人連結至聯絡人供應程式內其中一個群組的識別碼。</td> 448 <td> 449 群組是帳戶類型和帳戶名稱的選用功能。如要進一步瞭解群組,請參閱<a href="#Groups">聯絡人群組</a>。 450 451 </td> 452 </tr> 453</table> 454<h3 id="ContactBasics">聯絡人</h3> 455<p> 456 聯絡人供應程式會合併所有帳戶類型和帳戶名稱的原始聯絡人,而成為「聯絡人」<strong></strong>。 457藉此協助使用者顯示及修改針對某個人所收集的所有資料。 458聯絡人供應程式負責建立新的聯絡人列,以及彙總原始聯絡人與現有的聯絡人列。 459應用程式或同步配接器都可以新增聯絡人,而聯絡人列中的某些欄屬於唯讀性質。 460 461</p> 462<p class="note"> 463 <strong>注意:</strong>如果您嘗試使用 464 {@link android.content.ContentResolver#insert(Uri,ContentValues) insert()} 將聯絡人新增至聯絡人供應程式,將會收到 {@link java.lang.UnsupportedOperationException} 例外狀況。 465如果您試著更新列為「唯讀」的欄,則會略過此更新作業。 466 467</p> 468<p> 469 如果新增的原始聯絡人與現有的聯絡人都不相符,聯絡人供應程式就會建立新的聯絡人。 470如果現有原始聯絡人的資料在變更後,不再與之前附加的聯絡人相符,則供應程式也會建立新的聯絡人。 471 472如果應用程式或同步配接器建立的新原始聯絡人「符合」<em></em>現有的聯絡人,則新的原始聯絡人會彙總為現有的聯絡人。 473 474 475</p> 476<p> 477 聯絡人供應程式使用 {@link android.provider.ContactsContract.Contacts Contacts} 表格中的聯絡人 478 <code>_ID</code> 欄,將聯絡人列連結到其原始聯絡人列。 479原始聯絡人表格 480 {@link android.provider.ContactsContract.RawContacts} 的 <code>CONTACT_ID</code> 欄,內含聯絡人列 (與每個原始聯絡人列相關聯) 的 <code>_ID</code> 值。 481 482</p> 483<p> 484 {@link android.provider.ContactsContract.Contacts} 表格也有 485{@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} 欄,此為聯絡人列的「永久」連結。 486因為聯絡人供應程式會自動維護聯絡人,它會變更聯絡人列的 {@code android.provider.BaseColumns#_ID} 值,以回應彙總或同步操作。 487 488即使發生這種情況,與聯絡人的 489{@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} 合併的內容 URI {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} 仍會指向聯絡人列,因此,您可以使用 490{@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} 491 來維護「常用聯絡人」等聯絡人的連結。 492 493此欄有自己的格式,與 {@code android.provider.BaseColumns#_ID} 欄的格式無關。 494 495</p> 496<p> 497 圖 3 說明這三個主要表格彼此之間的關係。 498</p> 499<img src="{@docRoot}images/providers/contacts_tables.png" alt="Contacts provider main tables" height="514" id="figure4" /> 500<p class="img-caption"> 501 <strong>圖 3.</strong>聯絡人、原始聯絡人以及詳細資料表格的關係。 502</p> 503<h2 id="Sources">來自同步配接器的資料</h2> 504<p> 505 使用者將聯絡人資料直接輸入裝置,但資料也會過「同步配接器」從網路服務流入聯絡人供應程式<strong></strong> (同步配接器會自動將資料在裝置和服務之間傳輸)。 506 507同步配接器受到系統的控制、在背景執行,並且會呼叫 {@link android.content.ContentResolver} 方法來管理資料。 508 509 510</p> 511<p> 512 在 Android 中,與同步配接器搭配運作的網路服務,是透過帳戶類型加以識別。 513 每個同步配接器會與一種帳戶類型搭配,但可以支援該類型的多個帳戶名稱。 514帳戶類型和帳戶名稱在<a href="#RawContactsExample">原始聯絡人資料的來源</a>中會有更詳細的說明。 515 下列定義提供更詳細的資訊,說明帳戶類型和名稱與同步配接器和服務之間的關係。 516 517</p> 518<dl> 519 <dt> 520 帳戶類型 521 </dt> 522 <dd> 523 識別使用者儲存資料的服務。在大部分情況下,使用者必須經過服務的驗證。 524例如,Google 聯絡人是一種帳戶類型,由程式碼 <code>google.com</code> 加以識別。 525此值會對應到 526 {@link android.accounts.AccountManager} 所使用的帳戶類型。 527 </dd> 528 <dt> 529 帳戶名稱 530 </dt> 531 <dd> 532 識別特定帳戶或帳戶類型的登入。Google 聯絡人帳戶與 Google 帳戶相同,都是使用電子郵件地址做為帳戶名稱。 533 534 其他服務可能是以單一文字使用者名稱或數值 ID 做為帳戶名稱。 535 </dd> 536</dl> 537<p> 538 帳戶類型不必是唯一的。使用者可以設定多個 Google 聯絡人帳戶,並將其資料下載至聯絡人供應程式;如果使用者有一組個人帳戶名稱的個人聯絡人,還有另一組工作用的聯絡人,就可能發生此情形。 539 540帳戶名稱通常是唯一的。 541兩者加起來,就可以識別聯絡人供應程式和外部服務之間的特定資料流程。 542 543</p> 544<p> 545 如果您要將服務的資料傳輸到聯絡人供應程式,則需要編寫您自己的同步配接器。 546如要進一步瞭解同步配接器,請參閱<a href="#SyncAdapters">聯絡人供應程式同步配接器</a>。 547 548</p> 549<p> 550 圖 4 顯示聯絡人供應程式在人員相關的資料流程中所扮演的角色。 551在標記為「同步配接器」的方塊中,每個配接器都以其帳戶類型做為標籤。 552</p> 553<img src="{@docRoot}images/providers/ContactsDataFlow.png" alt="Flow of data about people" height="252" id="figure5" /> 554<p class="img-caption"> 555 <strong>圖 4.</strong>聯絡人供應程式資料流程。 556</p> 557<h2 id="Permissions">必要權限</h2> 558<p> 559 要存取聯絡人供應程式的應用程式必須要求下列權限: 560 561</p> 562<dl> 563 <dt>一或多份表格的讀取權限</dt> 564 <dd> 565 {@link android.Manifest.permission#READ_CONTACTS},在 566 <code>AndroidManifest.xml</code> 的 567 <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"> 568 <uses-permission></a></code> 元素中,以 569 <code><uses-permission android:name="android.permission.READ_CONTACTS"></code> 指定。 570 </dd> 571 <dt>一或多份表格的寫入權限</dt> 572 <dd> 573 {@link android.Manifest.permission#WRITE_CONTACTS},在 574<code>AndroidManifest.xml</code> 的 575<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"> 576 <uses-permission></a></code> 元素中,以 577<code><uses-permission android:name="android.permission.WRITE_CONTACTS"></code> 指定。 578 </dd> 579</dl> 580<p> 581 這些權限不會延伸到使用者設定檔資料。如要瞭解使用者設定檔及其必要權限,請參閱<a href="#UserProfile">使用者設定檔</a>。 582 583 584</p> 585<p> 586 請記住,使用者的聯絡人資料是個人的敏感資訊。使用者很關心隱私權相關的問題,因此不希望應用程式收集使用者本身或其聯絡人的相關資訊。 587 588 如果沒有明確說明為何需要存取使用者的聯絡人資料,使用者可能會給您的應用程式低評分,或直接拒絕安裝。 589 590</p> 591<h2 id="UserProfile">使用者設定檔</h2> 592<p> 593 {@link android.provider.ContactsContract.Contacts} 表格中有一列內含裝置使用者的設定檔資料, 594此資料描述裝置的 <code>user</code>,而不是其中一位使用者的聯絡人。 595針對使用設定檔的每個系統,設定檔聯絡人列會連結到原始聯絡人列。 596 597 每個設定檔原始聯絡人列可以有多個資料列。{@link android.provider.ContactsContract.Profile} 類別中提供存取使用者設定檔的常數。 598 599</p> 600<p> 601 存取使用者設定檔需要特殊權限。除了 602{@link android.Manifest.permission#READ_CONTACTS} 和 603{@link android.Manifest.permission#WRITE_CONTACTS} 的讀取和寫入權限以外,存取使用者設定檔還分別需要 {@code android.Manifest.permission#READ_PROFILE} 讀取權限和 604{@code android.Manifest.permission#WRITE_PROFILE} 寫入權限。 605 606 607</p> 608<p> 609 請務必將使用者的設定檔視為敏感資訊。 610{@code android.Manifest.permission#READ_PROFILE}權限可以讓您存取裝置上使用者的身分識別資料。 611請務必在應用程式的簡介中告訴使用者,為何需要使用者設定檔存取權限。 612 613</p> 614<p> 615 如要擷取內含使用者的設定檔的聯絡人列,請呼叫 {@link android.content.ContentResolver#query(Uri,String[], String, String[], String) 616ContentResolver.query()}。 617將內容 URI 設為 618{@link android.provider.ContactsContract.Profile#CONTENT_URI},並且不要提供任何選取條件。 619您也可以使用此內容 URI 做為擷取原始聯絡人或設定檔資料的基礎 URI。 620例如,以下程式碼片段會擷取設定檔資料: 621</p> 622<pre> 623// Sets the columns to retrieve for the user profile 624mProjection = new String[] 625 { 626 Profile._ID, 627 Profile.DISPLAY_NAME_PRIMARY, 628 Profile.LOOKUP_KEY, 629 Profile.PHOTO_THUMBNAIL_URI 630 }; 631 632// Retrieves the profile from the Contacts Provider 633mProfileCursor = 634 getContentResolver().query( 635 Profile.CONTENT_URI, 636 mProjection , 637 null, 638 null, 639 null); 640</pre> 641<p class="note"> 642 <strong>注意:</strong>如果您擷取了多個聯絡人列,而想要判斷其中之一是否為使用者設定檔,請測試該列的 643{@link android.provider.ContactsContract.ContactsColumns#IS_USER_PROFILE} 欄。 644如果聯絡人為使用者設定檔,此欄會設為「1」。 645 646</p> 647<h2 id="ContactsProviderMetadata">聯絡人供應程式中繼資料</h2> 648<p> 649 聯絡人供應程式管理的資料可以追蹤存放庫中聯絡人資料的 650狀態。存放庫相關的中繼資料儲存在不同的位置,包括 651「原始聯絡人」、「資料」以及「聯絡人」表格列, 652{@link android.provider.ContactsContract.Settings} 表格以及 653{@link android.provider.ContactsContract.SyncState} 表格。以下表格說明 654這些中繼資料的作用: 655</p> 656<p class="table-caption" id="table3"> 657 <strong>表 3.</strong>聯絡人供應程式的中繼資料</p> 658<table> 659 <tr> 660 <th scope="col">表格</th> 661 <th scope="col">欄</th> 662 <th scope="col">值</th> 663 <th scope="col">意義</th> 664 </tr> 665 <tr> 666 <td rowspan="2">{@link android.provider.ContactsContract.RawContacts}</td> 667 <td rowspan="2">{@link android.provider.ContactsContract.SyncColumns#DIRTY}</td> 668 <td>「0」:上次同步後沒有變更。</td> 669 <td rowspan="2"> 670 標記裝置上經過變更,且必須同步回伺服器的原始聯絡人。 671Android 應用程式更新列時,聯絡人供應程式會自動設定此值。 672 673 <p> 674 修改原始聯絡人或資料表格的同步配接器一律會將字串{@link android.provider.ContactsContract#CALLER_IS_SYNCADAPTER} 附加到其使用的內容 URI, 675 676藉此防止供應程式將列標記為已變更 (dirty)。 677 否則,同步配接器修改會顯示為本機修改,因而傳送到伺服器,儘管伺服器才是修改的來源。 678 679 </p> 680 </td> 681 </tr> 682 <tr> 683 <td>「1」:上次同步後已變更,需要同步回伺服器。</td> 684 </tr> 685 <tr> 686 <td>{@link android.provider.ContactsContract.RawContacts}</td> 687 <td>{@link android.provider.ContactsContract.SyncColumns#VERSION}</td> 688 <td>此列的版本號碼。</td> 689 <td> 690 每當列或其相關資料變更時,聯絡人供應程式都會自動增加此值。 691 692 </td> 693 </tr> 694 <tr> 695 <td>{@link android.provider.ContactsContract.Data}</td> 696 <td>{@link android.provider.ContactsContract.DataColumns#DATA_VERSION}</td> 697 <td>此列的版本號碼。</td> 698 <td> 699 每當資料列變更時,聯絡人供應程式都會自動增加此值。 700 701 </td> 702 </tr> 703 <tr> 704 <td>{@link android.provider.ContactsContract.RawContacts}</td> 705 <td>{@link android.provider.ContactsContract.SyncColumns#SOURCE_ID}</td> 706 <td> 707 可唯一識別帳戶原始聯絡人的字串值(此帳戶是以此字串值所建立)。 708 709 </td> 710 <td> 711 同步配接器建立新的原始聯絡人時,此欄應設為原始聯絡人的伺服器唯一 ID。 712Android 應用程式建立新的原始聯絡人時,應用程式應將此欄保留空白。 713這樣會提供訊號給同步配接器,要在伺服器上建立新的原始聯絡人,然後取得 714{@link android.provider.ContactsContract.SyncColumns#SOURCE_ID} 值。 715 716 <p> 717 尤其是來源 ID 對於每個帳戶類型必須具備<strong>唯一性</strong>,在同步時應該很穩定: 718 719 </p> 720 <ul> 721 <li> 722 唯一:帳戶的每個原始聯絡人都必須有自己的來源 ID。如果沒有強制執行此條件,則聯絡人應用程式會發生問題。 723 724 請注意,同一個帳戶「類型」<em></em>的兩個原始聯絡人可能會有相同的來源 ID。 725例如,{@code emily.dickinson@gmail.com} 帳戶的原始聯絡人「Thomas Higginson」與 726 {@code emilyd@gmail.com} 帳戶的原始聯絡人「Thomas Higginson」的來源 ID相同。 727 728 729 </li> 730 <li> 731 穩定:來源 ID 是線上服務中原始聯絡人資料的永久部分。 732例如,如果使用者從應用程式設定中清除「聯絡人儲存空間」,然後重新同步,則還原的原始聯絡人的來源 ID 應該與先前相同。 733 734如果沒有強制執行此條件,捷徑將停止運作。 735 736 </li> 737 </ul> 738 </td> 739 </tr> 740 <tr> 741 <td rowspan="2">{@link android.provider.ContactsContract.Groups}</td> 742 <td rowspan="2">{@link android.provider.ContactsContract.GroupsColumns#GROUP_VISIBLE}</td> 743 <td>「0」:Android 應用程式 UI 中不應顯示此群組中的聯絡人。</td> 744 <td> 745 有些伺服器可以讓使用者隱藏某些群組中的聯絡人,此欄的設計提供了與這類伺服器的相容性。 746 747 </td> 748 </tr> 749 <tr> 750 <td>「1」:應用程式 UI 中會顯示此群組中的聯絡人。</td> 751 </tr> 752 <tr> 753 <td rowspan="2">{@link android.provider.ContactsContract.Settings}</td> 754 <td rowspan="2"> 755 {@link android.provider.ContactsContract.SettingsColumns#UNGROUPED_VISIBLE}</td> 756 <td> 757 「0」:針對此帳戶和帳戶類型,Android 應用程式 UI 中不會顯示不屬於群組的聯絡人。 758 759 </td> 760 <td rowspan="2"> 761 如果沒有任何原始聯絡人屬於某個群組,則聯絡人預設為不可見(原始聯絡人的群組成員資格是由{@link android.provider.ContactsContract.Data} 表格中的一或多個 762{@link android.provider.ContactsContract.CommonDataKinds.GroupMembership} 列所指出)。 763 764 765 在 {@link android.provider.ContactsContract.Settings} 表格列中為帳戶類型和帳戶設定此旗標,可以強制讓不屬於任何群組的聯絡人成為可見的。 766 767 此旗標的其中一個用途是,顯示伺服器中不屬於任何群組的聯絡人。 768 </td> 769 </tr> 770 <tr> 771 <td> 772 「1」:針對此帳戶和帳戶類型,應用程式 UI 中會顯示不屬於群組的聯絡人。 773 774 </td> 775 776 </tr> 777 <tr> 778 <td>{@link android.provider.ContactsContract.SyncState}</td> 779 <td>(全部)</td> 780 <td> 781 使用此表格儲存同步配接器的中繼資料。 782 </td> 783 <td> 784 使用此表格,您可以儲存同步狀態,以及其他與同步相關、會永久放在裝置上的資料。 785 786 </td> 787 </tr> 788</table> 789<h2 id="Access">聯絡人供應程式存取</h2> 790<p> 791 本節說明從聯絡人供應程式存取資料的指導方針,著重於以下各項: 792 793</p> 794<ul> 795 <li> 796 實體查詢。 797 </li> 798 <li> 799 批次修改。 800 </li> 801 <li> 802 使用意圖進行擷取及修改。 803 </li> 804 <li> 805 資料完整性。 806 </li> 807</ul> 808<p> 809 從同步配接器進行修改,在<a href="#SyncAdapters">聯絡人供應程式同步配接器</a>中也提供更詳細的資訊。 810 811</p> 812<h3 id="Entities">實體查詢</h3> 813<p> 814 因為聯絡人供應程式為階層式表格,擷取某一列及連結至此列的所有「子」列時非常實用。 815例如,如要顯示人員的所有資訊,您可能要擷取單一 816 {@link android.provider.ContactsContract.Contacts} 列的 817所有 {@link android.provider.ContactsContract.RawContacts} 列,或單一 818{@link android.provider.ContactsContract.RawContacts} 列的所有 819{@link android.provider.ContactsContract.CommonDataKinds.Email} 列。 820為了協助此操作,聯絡人供應程式提供<strong>實體</strong>建構,其運作方式就像是資料庫結合各個表格一樣。 821 822 823</p> 824<p> 825 實體就像是一份表格,由上層表格及其下層表格中的選取欄所組成。 826 查詢實體時,您會提供投影 (projection) 和搜尋條件根據該實體可用的欄。 827結果會是 {@link android.database.Cursor},擷取到的每個下層表格列在其中都會有一列。 828例如,如果您查詢 829{@link android.provider.ContactsContract.Contacts.Entity} 的聯絡人名稱,並且查詢所有 {@link android.provider.ContactsContract.CommonDataKinds.Email} 列中該名稱的所有原始聯絡人,則會取回 {@link android.database.Cursor},每個 {@link android.provider.ContactsContract.CommonDataKinds.Email} 列都會有一列。 830 831 832 833</p> 834<p> 835 實體簡化查詢。使用實體,您可以一次擷取聯絡人或原始聯絡人的所有聯絡人資料,而不用先查詢父項表格以取得 ID,再以此 ID 查詢子項表格。另外,聯絡人供應程式會在單一交易中處理針對實體的查詢,以確保所擷取的資料在內部的一致性。 836 837 838 839 840</p> 841<p class="note"> 842 <strong>注意:</strong>實體通常不會包含上層表格和下層表格的所有欄。 843如果您嘗試使用的欄名稱未列在實體的欄名稱常數中,將會收到 {@link java.lang.Exception}。 844 845</p> 846<p> 847 以下程式碼片段展示如何擷取一位聯絡人的所有原始聯絡人列。此程式碼片段屬於大型應用程式的一部分,此應用程式有兩個 Activity:「主要」和「詳細」。 848主要 Activity 會顯示聯絡人列的清單,當使用者選取其中一項時,此 Activity 會將其 ID 傳送給詳細 Activity。 849 850詳細 Activity 會使用 {@link android.provider.ContactsContract.Contacts.Entity},針對所選取的聯絡人,顯示與其關聯的所有原始聯絡人的所有資料列。 851 852 853</p> 854<p> 855 此程式碼片段是取自「詳細」Activity: 856</p> 857<pre> 858... 859 /* 860 * Appends the entity path to the URI. In the case of the Contacts Provider, the 861 * expected URI is content://com.google.contacts/#/entity (# is the ID value). 862 */ 863 mContactUri = Uri.withAppendedPath( 864 mContactUri, 865 ContactsContract.Contacts.Entity.CONTENT_DIRECTORY); 866 867 // Initializes the loader identified by LOADER_ID. 868 getLoaderManager().initLoader( 869 LOADER_ID, // The identifier of the loader to initialize 870 null, // Arguments for the loader (in this case, none) 871 this); // The context of the activity 872 873 // Creates a new cursor adapter to attach to the list view 874 mCursorAdapter = new SimpleCursorAdapter( 875 this, // the context of the activity 876 R.layout.detail_list_item, // the view item containing the detail widgets 877 mCursor, // the backing cursor 878 mFromColumns, // the columns in the cursor that provide the data 879 mToViews, // the views in the view item that display the data 880 0); // flags 881 882 // Sets the ListView's backing adapter. 883 mRawContactList.setAdapter(mCursorAdapter); 884... 885@Override 886public Loader<Cursor> onCreateLoader(int id, Bundle args) { 887 888 /* 889 * Sets the columns to retrieve. 890 * RAW_CONTACT_ID is included to identify the raw contact associated with the data row. 891 * DATA1 contains the first column in the data row (usually the most important one). 892 * MIMETYPE indicates the type of data in the data row. 893 */ 894 String[] projection = 895 { 896 ContactsContract.Contacts.Entity.RAW_CONTACT_ID, 897 ContactsContract.Contacts.Entity.DATA1, 898 ContactsContract.Contacts.Entity.MIMETYPE 899 }; 900 901 /* 902 * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw 903 * contact collated together. 904 */ 905 String sortOrder = 906 ContactsContract.Contacts.Entity.RAW_CONTACT_ID + 907 " ASC"; 908 909 /* 910 * Returns a new CursorLoader. The arguments are similar to 911 * ContentResolver.query(), except for the Context argument, which supplies the location of 912 * the ContentResolver to use. 913 */ 914 return new CursorLoader( 915 getApplicationContext(), // The activity's context 916 mContactUri, // The entity content URI for a single contact 917 projection, // The columns to retrieve 918 null, // Retrieve all the raw contacts and their data rows. 919 null, // 920 sortOrder); // Sort by the raw contact ID. 921} 922</pre> 923<p> 924 載入完成時,{@link android.app.LoaderManager} 會呼叫 {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished(Loader, D) 925 onLoadFinished()} 的回呼。 926此方法的其中一個傳入引數是內含查詢結果的 927 {@link android.database.Cursor}。在您的應用程式中,您可以從這個 {@link android.database.Cursor} 取得資料,然後加以顯示或進一步處理。 928 929</p> 930<h3 id="Transactions">批次修改</h3> 931<p> 932 您應該儘可能透過建立 933 {@link android.content.ContentProviderOperation} 物件的{@link java.util.ArrayList},然後呼叫 934 {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()},以「批次模式」在聯絡人供應程式中進行資料的插入、更新以及刪除。 935因為聯絡人供應程式會在單一交易中執行 936{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} 的所有操作,所以您所做的修改不會讓聯絡人存放庫處於不一致的狀態。 937 938 939批次修改同時也有助於插入原始聯絡人及其詳細資料。 940 941</p> 942<p class="note"> 943 <strong>注意:</strong>如要修改「單一」<em></em>原始聯絡人,請考慮將意圖傳送到裝置的聯絡人應用程式,而不要在您的應用程式中處理修改操作。這些動作在<a href="#Intents">使用意圖擷取和修改</a>中有更詳細的資料。 944 945 946 947</p> 948<h4>降伏點</h4> 949<p> 950 包含大量操作的批次修改可能會封鎖其他處理程序,導致整體的使用者體驗不良。 951如要將您想要執行的所有修改,儘可能安排在較少的清單中執行,同時要避免這些修改讓系統無法進行其他操作,則應該要為一或多個操作設定「降伏點」<strong></strong>。 952 953 954 降伏點是一個 {@link android.content.ContentProviderOperation} 物件,而且其 955{@link android.content.ContentProviderOperation#isYieldAllowed()} 值是設為 956<code>true</code>。當聯絡人供應程式遇到降伏點時,會暫停它的工作,以便讓其他處理程序執行,並關閉目前的交易。 957供應程式再次啟動時,會繼續 {@link java.util.ArrayList} 中的下一項操作,並啟動新的交易。 958 959 960</p> 961<p> 962 降伏點會讓每次呼叫 963{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} 產生一個以上的交易。基於這項原因,您必須將上次操作的降伏點設為一組相關的列。 964 965 例如,您應該為以下兩種上次操作設定降伏點:新增原始聯絡人列及其相關資料列的一組動作,或與單一聯絡人相關的一組列。 966 967 968</p> 969<p> 970 降伏點也是微型操作的單位。兩個降伏點之間的所有存取會以單一單元來看待為成功或失敗。 971如果沒有設定任何降伏點,則最小的微型操作就是整批操作。 972如果使用降伏點,您可以防止操作降低系統效能,同時確保操作的子集是微型操作。 973 974 975</p> 976<h4>修改反向參考</h4> 977<p> 978 以一組 979 {@link android.content.ContentProviderOperation} 物件插入新的原始聯絡人及其關聯的資料列時,您必須透過插入原始聯絡人的 980 {@code android.provider.BaseColumns#_ID} 值做為 981{@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID} 值,將資料列連結到原始聯絡人列。 982不過,此 983值在您為資料列建立 {@link android.content.ContentProviderOperation} 984時並不存在,這是因為您尚未替原始聯絡人列 985套用 {@link android.content.ContentProviderOperation}。為解決此狀況,{@link android.content.ContentProviderOperation.Builder} 類別提供了 986{@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()} 這個方法。 987 988 此方法可以讓您使用之前操作的結果來插入或修改欄。 989 990</p> 991<p> 992 {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()} 993方法有兩個引數: 994</p> 995 <dl> 996 <dt> 997 <code>key</code> 998 </dt> 999 <dd> 1000 鍵值對的鍵。此引數的值是您要修改表格中的欄名稱。 1001 1002 </dd> 1003 <dt> 1004 <code>previousResult</code> 1005 </dt> 1006 <dd> 1007 1008{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} 中的 1009{@link android.content.ContentProviderResult} 物件以 0 開始的陣列索引值。套用批次操作時,每次操作結果都會儲存在結果的中繼陣列。 1010 1011<code>previousResult</code> 值是這些結果的其中一個索引,這些結果是以 <code>key</code>值擷取並加以儲存。 1012 1013這樣可以讓您插入新的原始聯絡人記錄,並取得其 1014{@code android.provider.BaseColumns#_ID} 值,然後在您新增 {@link android.provider.ContactsContract.Data} 列時,做為此值的「反向參考」。 1015 1016 <p> 1017 您首次呼叫 1018 {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} 時會建立整個結果陣列,此陣列的大小等同於您所提供 1019 {@link android.content.ContentProviderOperation} 物件的{@link java.util.ArrayList} 大小。 1020不過,結果陣列中的所有元素會設為 <code>null</code>,如果您嘗試要針對尚未套用的操作結果製作反向參考, 1021{@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}則會擲回 {@link java.lang.Exception}。 1022 1023 1024 1025 1026 </p> 1027 </dd> 1028 </dl> 1029<p> 1030 以下程式碼片段展示如何插入大量新的原始聯絡人和資料。其中包括建立降伏點和使用反向參考的程式碼。 1031此程式碼片段是 <code>createContacEntry()</code> 方法的擴充版本。而這個方法是 1032 <code><a href="{@docRoot}resources/samples/ContactManager/index.html"> 1033 Contact Manager</a></code> 範例應用程式中 1034 <code>ContactAdder</code> 類別的一部分。 1035 1036</p> 1037<p> 1038 第一個程式碼片段會從 UI 擷取聯絡人資料。此時,使用者已經選好要加入的新原始聯絡人帳戶。 1039 1040</p> 1041<pre> 1042// Creates a contact entry from the current UI values, using the currently-selected account. 1043protected void createContactEntry() { 1044 /* 1045 * Gets values from the UI 1046 */ 1047 String name = mContactNameEditText.getText().toString(); 1048 String phone = mContactPhoneEditText.getText().toString(); 1049 String email = mContactEmailEditText.getText().toString(); 1050 1051 int phoneType = mContactPhoneTypes.get( 1052 mContactPhoneTypeSpinner.getSelectedItemPosition()); 1053 1054 int emailType = mContactEmailTypes.get( 1055 mContactEmailTypeSpinner.getSelectedItemPosition()); 1056</pre> 1057<p> 1058 下一個程式碼片段的操作會將原始聯絡人列插入 1059{@link android.provider.ContactsContract.RawContacts} 表格: 1060</p> 1061<pre> 1062 /* 1063 * Prepares the batch operation for inserting a new raw contact and its data. Even if 1064 * the Contacts Provider does not have any data for this person, you can't add a Contact, 1065 * only a raw contact. The Contacts Provider will then add a Contact automatically. 1066 */ 1067 1068 // Creates a new array of ContentProviderOperation objects. 1069 ArrayList<ContentProviderOperation> ops = 1070 new ArrayList<ContentProviderOperation>(); 1071 1072 /* 1073 * Creates a new raw contact with its account type (server type) and account name 1074 * (user's account). Remember that the display name is not stored in this row, but in a 1075 * StructuredName data row. No other data is required. 1076 */ 1077 ContentProviderOperation.Builder op = 1078 ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) 1079 .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType()) 1080 .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName()); 1081 1082 // Builds the operation and adds it to the array of operations 1083 ops.add(op.build()); 1084</pre> 1085<p> 1086 接著,程式碼會建立顯示名稱、電話以及電子郵件列的資料列。 1087</p> 1088<p> 1089 每項操作建立器物件會使用 1090{@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}來取得 1091{@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID}。 1092參照會指向第一項操作中的 {@link android.content.ContentProviderResult} 物件 (第一項操作會新增原始聯絡人列,並傳回其新的 {@code android.provider.BaseColumns#_ID} 值)。 1093 1094 1095因此,每個資料列會透過其 1096{@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID} 自動連結到它所屬的新 {@link android.provider.ContactsContract.RawContacts} 列。 1097 1098</p> 1099<p> 1100 新增電子郵件列的 {@link android.content.ContentProviderOperation.Builder} 物件會帶有 {@link android.content.ContentProviderOperation.Builder#withYieldAllowed(boolean) 1101 withYieldAllowed()} 旗標,而這會設定降伏點: 1102 1103</p> 1104<pre> 1105 // Creates the display name for the new raw contact, as a StructuredName data row. 1106 op = 1107 ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) 1108 /* 1109 * withValueBackReference sets the value of the first argument to the value of 1110 * the ContentProviderResult indexed by the second argument. In this particular 1111 * call, the raw contact ID column of the StructuredName data row is set to the 1112 * value of the result returned by the first operation, which is the one that 1113 * actually adds the raw contact row. 1114 */ 1115 .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) 1116 1117 // Sets the data row's MIME type to StructuredName 1118 .withValue(ContactsContract.Data.MIMETYPE, 1119 ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) 1120 1121 // Sets the data row's display name to the name in the UI. 1122 .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name); 1123 1124 // Builds the operation and adds it to the array of operations 1125 ops.add(op.build()); 1126 1127 // Inserts the specified phone number and type as a Phone data row 1128 op = 1129 ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) 1130 /* 1131 * Sets the value of the raw contact id column to the new raw contact ID returned 1132 * by the first operation in the batch. 1133 */ 1134 .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) 1135 1136 // Sets the data row's MIME type to Phone 1137 .withValue(ContactsContract.Data.MIMETYPE, 1138 ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) 1139 1140 // Sets the phone number and type 1141 .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) 1142 .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType); 1143 1144 // Builds the operation and adds it to the array of operations 1145 ops.add(op.build()); 1146 1147 // Inserts the specified email and type as a Phone data row 1148 op = 1149 ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) 1150 /* 1151 * Sets the value of the raw contact id column to the new raw contact ID returned 1152 * by the first operation in the batch. 1153 */ 1154 .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) 1155 1156 // Sets the data row's MIME type to Email 1157 .withValue(ContactsContract.Data.MIMETYPE, 1158 ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) 1159 1160 // Sets the email address and type 1161 .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email) 1162 .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType); 1163 1164 /* 1165 * Demonstrates a yield point. At the end of this insert, the batch operation's thread 1166 * will yield priority to other threads. Use after every set of operations that affect a 1167 * single contact, to avoid degrading performance. 1168 */ 1169 op.withYieldAllowed(true); 1170 1171 // Builds the operation and adds it to the array of operations 1172 ops.add(op.build()); 1173</pre> 1174<p> 1175 最後一個程式碼片段顯示 1176{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} 的呼叫,以插入新的原始聯絡人和資料列。 1177 1178</p> 1179<pre> 1180 // Ask the Contacts Provider to create a new contact 1181 Log.d(TAG,"Selected account: " + mSelectedAccount.getName() + " (" + 1182 mSelectedAccount.getType() + ")"); 1183 Log.d(TAG,"Creating contact: " + name); 1184 1185 /* 1186 * Applies the array of ContentProviderOperation objects in batch. The results are 1187 * discarded. 1188 */ 1189 try { 1190 1191 getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 1192 } catch (Exception e) { 1193 1194 // Display a warning 1195 Context ctx = getApplicationContext(); 1196 1197 CharSequence txt = getString(R.string.contactCreationFailure); 1198 int duration = Toast.LENGTH_SHORT; 1199 Toast toast = Toast.makeText(ctx, txt, duration); 1200 toast.show(); 1201 1202 // Log exception 1203 Log.e(TAG, "Exception encountered while inserting contact: " + e); 1204 } 1205} 1206</pre> 1207<p> 1208 批次操作也可以讓您實作<strong>開放式並行存取控制</strong>,此方法可以在套用修改交易時,不需要鎖定底層存放庫。 1209 1210 如要使用此方法,您要套用交易,然後檢查同時發生的其他修改操作。 1211如果您發現不一致的修改,請將交易復原並加以重試。 1212 1213</p> 1214<p> 1215 開放式並行存取控制很適合用在行動裝置,這是因為行動裝置一次只會有一位使用者,而且很少會發生同時存取資料存放庫的情形。 1216由於不會使用到鎖定,因此您不必花時間在設定鎖定,或等待其他交易釋放鎖定。 1217 1218</p> 1219<p> 1220 如要在更新單一 1221 {@link android.provider.ContactsContract.RawContacts} 列時使用開放式並行存取控制,請遵循以下步驟: 1222</p> 1223<ol> 1224 <li> 1225 隨著您要擷取的其他資料,一起擷取原始聯絡人的 {@link android.provider.ContactsContract.SyncColumns#VERSION} 欄。 1226 1227 </li> 1228 <li> 1229 使用 1230 {@link android.content.ContentProviderOperation#newAssertQuery(Uri)} 方法建立適合用於強制執行限制的{@link android.content.ContentProviderOperation.Builder} 物件。 1231如果是內容 URI,請使用 {@link android.provider.ContactsContract.RawContacts#CONTENT_URI 1232RawContacts.CONTENT_URI} 並附加原始聯絡人的 {@code android.provider.BaseColumns#_ID}。 1233 1234 1235 </li> 1236 <li> 1237 如果是 {@link android.content.ContentProviderOperation.Builder} 物件,請呼叫 {@link android.content.ContentProviderOperation.Builder#withValue(String, Object) 1238 withValue()},以比較 {@link android.provider.ContactsContract.SyncColumns#VERSION} 欄和您剛才擷取的版本號碼。 1239 1240 1241 </li> 1242 <li> 1243 如果是相同的 {@link android.content.ContentProviderOperation.Builder},請呼叫 {@link android.content.ContentProviderOperation.Builder#withExpectedCount(int) 1244withExpectedCount()} 以確保此判斷提示只測試一列。 1245 1246 </li> 1247 <li> 1248 呼叫 {@link android.content.ContentProviderOperation.Builder#build()} 以建立 1249{@link android.content.ContentProviderOperation} 物件,然後將此物件新增為您傳送到 1250 {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} 的第一個 {@link java.util.ArrayList} 物件。 1251 1252 </li> 1253 <li> 1254 套用批次交易。 1255 </li> 1256</ol> 1257<p> 1258 如果在您讀取原始聯絡人列和嘗試加以修改之間,有另一項操作要加以更新,則「判斷提示」{@link android.content.ContentProviderOperation} 將會失敗,而且整個批次的操作將會退出。 1259 1260您之後可以選擇重試此批次作業或採取其他動作。 1261 1262</p> 1263<p> 1264 以下程式碼片段展示如何在使用 {@link android.content.CursorLoader} 查詢單一原始聯絡人後,建立「判斷提示」 1265{@link android.content.ContentProviderOperation}: 1266 1267</p> 1268<pre> 1269/* 1270 * The application uses CursorLoader to query the raw contacts table. The system calls this method 1271 * when the load is finished. 1272 */ 1273public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 1274 1275 // Gets the raw contact's _ID and VERSION values 1276 mRawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)); 1277 mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION)); 1278} 1279 1280... 1281 1282// Sets up a Uri for the assert operation 1283Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, mRawContactID); 1284 1285// Creates a builder for the assert operation 1286ContentProviderOperation.Builder assertOp = ContentProviderOperation.netAssertQuery(rawContactUri); 1287 1288// Adds the assertions to the assert operation: checks the version and count of rows tested 1289assertOp.withValue(SyncColumns.VERSION, mVersion); 1290assertOp.withExpectedCount(1); 1291 1292// Creates an ArrayList to hold the ContentProviderOperation objects 1293ArrayList ops = new ArrayList<ContentProviderOperationg>; 1294 1295ops.add(assertOp.build()); 1296 1297// You would add the rest of your batch operations to "ops" here 1298 1299... 1300 1301// Applies the batch. If the assert fails, an Exception is thrown 1302try 1303 { 1304 ContentProviderResult[] results = 1305 getContentResolver().applyBatch(AUTHORITY, ops); 1306 1307 } catch (OperationApplicationException e) { 1308 1309 // Actions you want to take if the assert operation fails go here 1310 } 1311</pre> 1312<h3 id="Intents">使用意圖進行擷取及修改</h3> 1313<p> 1314 將意圖傳送給裝置的聯絡人應用程式,可讓您間接存取聯絡人供應程式。 1315意圖會啟動裝置的聯絡人應用程式 UI,使用者可以在此執行與聯絡人相關的工作。 1316透過此類型的存取方式,使用者可以: 1317 <ul> 1318 <li>從清單挑選聯絡人,並將它傳送給應用程式以進行其他操作。</li> 1319 <li>編輯現有的聯絡人資料。</li> 1320 <li>為使用者的任何帳戶插入新的原始聯絡人。</li> 1321 <li>刪除聯絡人或聯絡人資料。</li> 1322 </ul> 1323<p> 1324 如果使用者正在插入或更新資料,您可以先收集資料,然後讓它成為意圖的一部分加以傳送。 1325 1326</p> 1327<p> 1328 當您透過裝置的聯絡人應用程式使用意圖來存取聯絡人供應程式時,不需要自已撰寫存取供應程式的 UI 或程式碼。 1329您也不需要要求供應程式的讀取或寫入權限。 1330裝置的聯絡人應用程式可以將某個聯絡人的讀取權限委派給您,而且因為是透過另一個應用程式對供應程式進行修改,所以不需要具備寫入權限。 1331 1332 1333</p> 1334<p> 1335 傳送意圖以存取供應程式的一般流程在<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">內容供應程式基本概念</a>指南的「透過意圖存取資料」中有詳細的說明。 1336 1337表 4 摘要說明您可以在工作中使用的動作、MIME 類型以及資料值,而您可以和 1338 {@link android.content.Intent#putExtra(String, String) putExtra()} 搭配使用的額外值則列於 {@link android.provider.ContactsContract.Intents.Insert} 的參考文件: 1339 1340 1341 1342</p> 1343<p class="table-caption" id="table4"> 1344 <strong>表 4.</strong>聯絡人供應程式意圖。 1345</p> 1346<table style="width:75%"> 1347 <tr> 1348 <th scope="col" style="width:10%">工作</th> 1349 <th scope="col" style="width:5%">動作</th> 1350 <th scope="col" style="width:10%">資料</th> 1351 <th scope="col" style="width:10%">MIME 類型</th> 1352 <th scope="col" style="width:25%">備註</th> 1353 </tr> 1354 <tr> 1355 <td><strong>從清單挑選聯絡人</strong></td> 1356 <td>{@link android.content.Intent#ACTION_PICK}</td> 1357 <td> 1358 可以是以下其中一種: 1359 <ul> 1360 <li> 1361{@link android.provider.ContactsContract.Contacts#CONTENT_URI Contacts.CONTENT_URI},可顯示聯絡人的清單。 1362 1363 </li> 1364 <li> 1365{@link android.provider.ContactsContract.CommonDataKinds.Phone#CONTENT_URI Phone.CONTENT_URI},可顯示原始聯絡人的電話號碼清單。 1366 1367 </li> 1368 <li> 1369{@link android.provider.ContactsContract.CommonDataKinds.StructuredPostal#CONTENT_URI 1370StructuredPostal.CONTENT_URI},可顯示原始聯絡人的郵寄地址清單。 1371 1372 </li> 1373 <li> 1374{@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_URI Email.CONTENT_URI},可顯示原始聯絡人的電子郵件地址清單。 1375 1376 </li> 1377 </ul> 1378 </td> 1379 <td> 1380 未使用 1381 </td> 1382 <td> 1383 顯示原始聯絡人清單或原始聯絡人的資料清單,視您提供的內容 URI 類型而定。 1384 1385 <p> 1386 呼叫 1387{@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()}可傳回所選取列的內容 URI。 1388URI 的格式是表格的內容 URI 附加列的 <code>LOOKUP_ID</code>。 1389 1390 裝置的聯絡人應用程式會在 Activity 的生命週期內,將讀取和寫入權限委派給此內容 URI。 1391詳情請參閱<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">內容供應程式基本概念</a>指南。 1392 1393 1394 </p> 1395 </td> 1396 </tr> 1397 <tr> 1398 <td><strong>插入新的原始聯絡人</strong></td> 1399 <td>{@link android.provider.ContactsContract.Intents.Insert#ACTION Insert.ACTION}</td> 1400 <td>不適用</td> 1401 <td> 1402 {@link android.provider.ContactsContract.RawContacts#CONTENT_TYPE 1403RawContacts.CONTENT_TYPE},一組原始聯絡人的 MIME 類型。 1404 </td> 1405 <td> 1406 顯示裝置聯絡人應用程式中的「新增聯絡人」<strong></strong>畫面。會顯示您新增至意圖的額外值。 1407如果隨著 1408{@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()} 一起傳送,則新增的原始聯絡人內容 URI 會在 {@link android.content.Intent} 引數的 [資料] 欄位中傳回給 Activity 的 1409{@link android.app.Activity#onActivityResult(int, int, Intent) onActivityResult()}回呼方法。 1410 1411 1412如要取得此值,請呼叫 {@link android.content.Intent#getData()}。 1413 </td> 1414 </tr> 1415 <tr> 1416 <td><strong>編輯聯絡人</strong></td> 1417 <td>{@link android.content.Intent#ACTION_EDIT}</td> 1418 <td> 1419 聯絡人的 {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}。 1420編輯器 Activity 可讓使用者編輯與此聯絡人關聯的任何資料。 1421 1422 </td> 1423 <td> 1424 {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE 1425Contacts.CONTENT_ITEM_TYPE},單一聯絡人。</td> 1426 <td> 1427 顯示聯絡人應用程式中的「編輯聯絡人」畫面。顯示您新增至意圖的額外值。 1428使用者按一下 [完成]<strong></strong> 來儲存編輯內容時,您的 Activity 會回到前景。 1429 1430 </td> 1431 </tr> 1432 <tr> 1433 <td><strong>顯示也能夠新增資料的挑選器</strong></td> 1434 <td>{@link android.content.Intent#ACTION_INSERT_OR_EDIT}</td> 1435 <td> 1436 不適用 1437 </td> 1438 <td> 1439 {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE} 1440 </td> 1441 <td> 1442 此意圖一律會顯示聯絡人應用程式的挑選器畫面。使用者可以挑選要編輯的聯絡人,或新增聯絡人。 1443不論使用者選擇編輯或新增,所顯示的畫面中也會顯示您在意圖中傳送的額外資料。 1444 1445如果您的應用程式顯示電子郵件或電話號碼之類的聯絡人資料,使用此意圖會讓使用者將資料新增至現有聯絡人。 1446 1447 1448 <p class="note"> 1449 <strong>注意:</strong>不需要在意圖的額外值中傳送名稱值,這是因為使用者一定會挑選現有名稱或新增名稱。 1450再者,如果您傳送名稱,而使用者選擇編輯,則聯絡人應用程式會覆寫之前的值,以顯示您傳送的名稱。 1451 1452如果使用者沒有注意到此情形並儲存本次編輯,則會遺失舊的值。 1453 1454 </p> 1455 </td> 1456 </tr> 1457</table> 1458<p> 1459 裝置的聯絡人應用程式不會讓您刪除原始聯絡人或任何含有意圖的資料。 1460如要刪除原始聯絡人,請改用 1461{@link android.content.ContentResolver#delete(Uri, String, String[]) ContentResolver.delete()} 或 {@link android.content.ContentProviderOperation#newDelete(Uri) 1462ContentProviderOperation.newDelete()}。 1463 1464</p> 1465<p> 1466 以下程式碼片段展示如何建構及傳送可插入新原始聯絡人和資料,的意圖: 1467 1468</p> 1469<pre> 1470// Gets values from the UI 1471String name = mContactNameEditText.getText().toString(); 1472String phone = mContactPhoneEditText.getText().toString(); 1473String email = mContactEmailEditText.getText().toString(); 1474 1475String company = mCompanyName.getText().toString(); 1476String jobtitle = mJobTitle.getText().toString(); 1477 1478// Creates a new intent for sending to the device's contacts application 1479Intent insertIntent = new Intent(ContactsContract.Intents.Insert.ACTION); 1480 1481// Sets the MIME type to the one expected by the insertion activity 1482insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE); 1483 1484// Sets the new contact name 1485insertIntent.putExtra(ContactsContract.Intents.Insert.NAME, name); 1486 1487// Sets the new company and job title 1488insertIntent.putExtra(ContactsContract.Intents.Insert.COMPANY, company); 1489insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle); 1490 1491/* 1492 * Demonstrates adding data rows as an array list associated with the DATA key 1493 */ 1494 1495// Defines an array list to contain the ContentValues objects for each row 1496ArrayList<ContentValues> contactData = new ArrayList<ContentValues>(); 1497 1498 1499/* 1500 * Defines the raw contact row 1501 */ 1502 1503// Sets up the row as a ContentValues object 1504ContentValues rawContactRow = new ContentValues(); 1505 1506// Adds the account type and name to the row 1507rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType()); 1508rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName()); 1509 1510// Adds the row to the array 1511contactData.add(rawContactRow); 1512 1513/* 1514 * Sets up the phone number data row 1515 */ 1516 1517// Sets up the row as a ContentValues object 1518ContentValues phoneRow = new ContentValues(); 1519 1520// Specifies the MIME type for this data row (all data rows must be marked by their type) 1521phoneRow.put( 1522 ContactsContract.Data.MIMETYPE, 1523 ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE 1524); 1525 1526// Adds the phone number and its type to the row 1527phoneRow.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone); 1528 1529// Adds the row to the array 1530contactData.add(phoneRow); 1531 1532/* 1533 * Sets up the email data row 1534 */ 1535 1536// Sets up the row as a ContentValues object 1537ContentValues emailRow = new ContentValues(); 1538 1539// Specifies the MIME type for this data row (all data rows must be marked by their type) 1540emailRow.put( 1541 ContactsContract.Data.MIMETYPE, 1542 ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE 1543); 1544 1545// Adds the email address and its type to the row 1546emailRow.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email); 1547 1548// Adds the row to the array 1549contactData.add(emailRow); 1550 1551/* 1552 * Adds the array to the intent's extras. It must be a parcelable object in order to 1553 * travel between processes. The device's contacts app expects its key to be 1554 * Intents.Insert.DATA 1555 */ 1556insertIntent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData); 1557 1558// Send out the intent to start the device's contacts app in its add contact activity. 1559startActivity(insertIntent); 1560</pre> 1561<h3 id="DataIntegrity">資料完整性</h3> 1562<p> 1563 因為聯絡人存放庫內含重要的敏感資料,使用者會期待這些資料為正確且為最新狀態,聯絡人供應程式對於資料完整性有定義良好的規則。 1564因此,您在修改聯絡人資料時,必須符合這些規則。 1565以下列出重要規則: 1566 1567</p> 1568<dl> 1569 <dt> 1570 務必為您新增的每個 {@link android.provider.ContactsContract.RawContacts} 列新增 {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} 列。 1571 1572 </dt> 1573 <dd> 1574 {@link android.provider.ContactsContract.Data} 表格中不含 1575 {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} 列的 1576{@link android.provider.ContactsContract.RawContacts} 列,在彙總時會造成問題。 1577 1578 </dd> 1579 <dt> 1580 務必將 {@link android.provider.ContactsContract.Data} 列連結到其上層的 1581{@link android.provider.ContactsContract.RawContacts} 列。 1582 </dt> 1583 <dd> 1584 裝置的聯絡人應用程式中將看不到未連結到 1585 {@link android.provider.ContactsContract.RawContacts} 的 {@link android.provider.ContactsContract.Data} 列,而且與同步配接器搭配使用時可能會造成問題。 1586 1587 </dd> 1588 <dt> 1589 只針對您擁有的原始聯絡人變更資料。 1590 </dt> 1591 <dd> 1592 請記住,聯絡人供應程式通常用來管理來自不同帳戶類型或線上服務的資料。 1593您必須確認應用程式只會修改或刪除屬於您的資料列,並且確認應用程式插入的資料只含有您可控制的帳戶類型和名稱。 1594 1595 1596 </dd> 1597 <dt> 1598 務必使用 {@link android.provider.ContactsContract} 及其子類別中定義的常數,做為授權、內容 URI、URI 路徑、欄名稱、MIME 類型以及 1599{@link android.provider.ContactsContract.CommonDataKinds.CommonColumns#TYPE} 值。 1600 1601 </dt> 1602 <dd> 1603 使用這些常數可協助您避免發生錯誤。如果有任何常數已失效,則編譯器會發出通知。 1604 1605 </dd> 1606</dl> 1607<h3 id="CustomData">自訂資料列</h3> 1608<p> 1609 透過建立自訂的 MIME 類型,您可以插入、編輯、刪除以及擷取 {@link android.provider.ContactsContract.Data} 表格中您自己的資料列。 1610儘管您可以將自己的類型特定欄名稱對應到預設的欄名稱,您的列仍受限於使用 1611 {@link android.provider.ContactsContract.DataColumns} 中所定義的欄。 1612 1613在裝置的聯絡人應用程式中,可以顯示您的列中資料,但無法加以編輯或刪除,而且使用者無法新增其他資料。 1614 1615如要讓使用者修改您自訂的資料列,您必須在自己的應用程式中提供編輯器 Activity。 1616 1617</p> 1618<p> 1619 如要顯示自己的資料,請提供 <code>contacts.xml</code> 檔案,其中要包含 1620<code><ContactsAccountType></code> 元素以及一或多個其 1621<code><ContactsDataKind></code> 子元素。詳情請參閱 <a href="#SocialStreamDataKind"><code><ContactsDataKind> element</code></a>一節。 1622 1623</p> 1624<p> 1625 如要更瞭解自訂 MIME 類型的詳細資訊,請閱讀<a href="{@docRoot}guide/topics/providers/content-provider-creating.html">建立內容供應程式</a>指南。 1626 1627 1628</p> 1629<h2 id="SyncAdapters">聯絡人供應程式同步配接器</h2> 1630<p> 1631 聯絡人供應程式的設計是專門用來處理裝置和線上服務之間聯絡人資料的「同步作業」<strong></strong>。 1632以便讓使用者將現有資料下載到新裝置,以及將現有資料上傳到新帳戶。 1633 1634 同步作業也可以確保使用者手邊使用的是最新的資料,不論來源經過哪些新增和變更。 1635同步作業的另一個好處是,即使裝置沒有連上網路,使用者仍然可以存取聯絡人資料。 1636 1637</p> 1638<p> 1639 您可以用各種方式實作同步作業,不過 Android 系統提供的外掛程式同步架構可以將以下工作自動化: 1640 1641 <ul> 1642 1643 <li> 1644 檢查網路可用性。 1645 </li> 1646 <li> 1647 根據使用者偏好設定,安排並執行同步作業。 1648 </li> 1649 <li> 1650 重新啟動已停止的同步作業。 1651 </li> 1652 </ul> 1653<p> 1654 如要使用此架構,您要提供同步配接器外掛程式。每個同步配接器對於服務和內容供應程式來說是唯一的,但可以處理相同服務的多個帳戶名稱。 1655此架構也可以讓相同服務和供應程式使用多個同步配接器。 1656 1657</p> 1658<h3 id="SyncClassesFiles">同步配接器類別和檔案</h3> 1659<p> 1660 您將同步配接器實做為 {@link android.content.AbstractThreadedSyncAdapter} 的子類別,並以 Android 應用程式的一部分加以安裝。 1661 1662系統會從應用程式宣示說明中的元素,以及從宣示說明所指向的特殊 XML 檔案中瞭解同步配接器的相關資訊。 1663此 XML 檔案定義線上服務的帳戶類型,以及內容供應程式的授權,這兩者可用來唯一識別此配接器。 1664 1665同步配接器要在使用者新增同步配接器的帳戶類型, 1666並啟用要與同步配接器的內容供應程式同步後, 1667同步配接器才會變成使用中。此時,系統會開始管理配接器並視需要加以呼叫,以便在內容供應程式和伺服器之間進行同步。 1668 1669</p> 1670<p class="note"> 1671 <strong>注意:</strong>使用帳戶類型做為同步配接器識別的一部分,可以讓系統在偵測後,將存取不同服務、但來自相同組織的同步配接器群組在一起。 1672 1673例如,Google 線上服務的同步配接器都有相同的帳戶類型 <code>com.google</code>。 1674使用者將 Google 帳戶新增至其裝置後,所有已安裝的 Google 服務同步配接器會列在一起,每個列出的同步配接器會與裝置上不同的內容供應程式進行同步。 1675 1676 1677</p> 1678<p> 1679 由於大多數服務都需要在存取資料之前先驗證其身分,因此 Android 系統提供類似的驗證架構,而且通常會與同步配接器架構一起搭配使用。 1680 1681驗證架構使用外掛程式驗證器,這是 1682 {@link android.accounts.AbstractAccountAuthenticator} 的子類別。 1683驗證器會以下列步驟驗證使用者的身分: 1684 1685 <ol> 1686 <li> 1687 收集使用者的名稱、密碼或類似資訊 (使用者的<strong>憑證</strong>)。 1688 1689 </li> 1690 <li> 1691 將憑證傳送給服務 1692 </li> 1693 <li> 1694 檢驗服務的回覆。 1695 </li> 1696 </ol> 1697<p> 1698 如果服務接受此憑證,則驗證器可以儲存憑證供以後使用。 1699由於外掛程式驗證器架構的緣故, 1700{@link android.accounts.AccountManager} 可以存取驗證器支援且選擇顯示的任何 authtoken,例如 OAuth2 authtoken。 1701 1702</p> 1703<p> 1704 雖然驗證並非必要,大部分聯絡人服務仍會加以使用。 1705 不過,您不一定要使用 Android 驗證架構來進行驗證動作。 1706</p> 1707<h3 id="SyncAdapterImplementing">同步配接器實作</h3> 1708<p> 1709 如要實作聯絡人供應程式的同步配接器,要從建立內含以下各項的 Android 應用程式開始: 1710 1711</p> 1712 <dl> 1713 <dt> 1714 回應來自系統的要求,以繫結至同步配接器的 {@link android.app.Service} 元件。 1715 1716 </dt> 1717 <dd> 1718 系統要執行同步時,會呼叫服務的 1719 {@link android.app.Service#onBind(Intent) onBind()} 方法,以取得同步配接器的 1720 {@link android.os.IBinder}。這樣可以讓系統以跨處理程序的方式呼叫配接器的方法。 1721 1722 <p> 1723 在<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">範例同步配接器</a>範例應用程式中,此服務的名稱為 1724 <code>com.example.android.samplesync.syncadapter.SyncService</code>。 1725 1726 </p> 1727 </dd> 1728 <dt> 1729 實際的同步配接器是以 1730 {@link android.content.AbstractThreadedSyncAdapter} 的實體子類別加以實作。 1731 </dt> 1732 <dd> 1733 此類別會執行的工作包括:從伺服器下載資料、從裝置上傳資料以及解決衝突。 1734配接器的主要工作會使用 {@link android.content.AbstractThreadedSyncAdapter#onPerformSync( 1735Account, Bundle, String, ContentProviderClient, SyncResult) 1736onPerformSync()} 方法完成。 1737此類別必須以單一執行個體的方式加以具現化。 1738 <p> 1739 在<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">範例同步配接器</a>範例應用程式中,同步配接器定義在 1740<code>com.example.android.samplesync.syncadapter.SyncAdapter</code> 類別中。 1741 1742 </p> 1743 </dd> 1744 <dt> 1745 {@link android.app.Application} 的子類別。 1746 </dt> 1747 <dd> 1748 此類別就像是同步配接器單一執行個體的工廠。使用 1749{@link android.app.Application#onCreate()} 方法具現化同步配接器,並提供靜態的「getter」方法將單一執行個體傳回給同步配接器服務的 1750{@link android.app.Service#onBind(Intent) onBind()} 方法。 1751 1752 1753 </dd> 1754 <dt> 1755 <strong>選用:</strong>回應系統針對使用者發出的驗證要求的 {@link android.app.Service} 元件。 1756 1757 </dt> 1758 <dd> 1759 {@link android.accounts.AccountManager} 會啟動此服以開始驗證程序。 1760服務的 {@link android.app.Service#onCreate()} 方法會具現化為驗證器物件。 1761系統需驗證應用程式同步配接器的使用者帳戶時,會呼叫服務的 1762{@link android.app.Service#onBind(Intent) onBind()} 方法以取得驗證器的 1763 {@link android.os.IBinder}。 1764這樣可以讓系統以跨處理程序的方式呼叫驗證器的方法。 1765 1766 <p> 1767 在<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">範例同步配接器</a>範例應用程式中,此服務的類別名稱為 1768<code>com.example.android.samplesync.authenticator.AuthenticationService</code>。 1769 1770 </p> 1771 </dd> 1772 <dt> 1773 <strong>選用:</strong>處理驗證要求的 1774{@link android.accounts.AbstractAccountAuthenticator} 實體子類別。 1775 1776 </dt> 1777 <dd> 1778 {@link android.accounts.AccountManager} 會呼叫此類別提供的方法,透過伺服器驗證使用者的憑證。 1779驗證程序的詳細方式會根據所使用的伺服器技術,而有很大的差異。 1780建議您參閱伺服器軟體的說明文件,進一步瞭解驗證。 1781 1782 <p> 1783 在<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">範例同步配接器</a>範例應用程式中,驗證器是在 1784<code>com.example.android.samplesync.authenticator.Authenticator</code> 類別中完成定義。 1785 1786 </p> 1787 </dd> 1788 <dt> 1789 定義系統同步配接器和驗證器的 XML 檔案。 1790 </dt> 1791 <dd> 1792 應用程式宣示說明中的 1793 <code><<a href="{@docRoot}guide/topics/manifest/service-element.html">service</a>></code> 元素會定義之前說明的同步配接器和驗證器服務元件。 1794 1795這些元素包含的 1796<code><<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">meta-data</a>></code> 子元素可提供系統的特定資料: 1797 1798 1799 1800 <ul> 1801 <li> 1802 同步配接器服務的 1803 <code><<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">meta-data</a>></code> 元素,此元素會指向 XML 檔案 <code>res/xml/syncadapter.xml</code>。 1804 1805此檔案會按順序指出 1806將與聯絡人供應程式同步的網路服務 URI, 1807以及網路服務的帳戶類型。 1808 </li> 1809 <li> 1810 <strong>選用:</strong>驗證器服務的 1811 <code><<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">meta-data</a>></code> 元素,此元素會指向 XML 檔案 1812<code>res/xml/authenticator.xml</code>。 1813此檔案會按順序指出此驗證器支援的帳戶類型,以及驗證程序中會出現的 UI 資源。 1814 1815此元素中指定的帳戶類型必須與同步配接器中指定的帳戶類型相同。 1816 1817 1818 </li> 1819 </ul> 1820 </dd> 1821 </dl> 1822<h2 id="SocialStream">社交串流資料</h2> 1823<p> 1824 {@code android.provider.ContactsContract.StreamItems} 和 1825{@code android.provider.ContactsContract.StreamItemPhotos} 表格負責管理社交網路的傳入資料。 1826您可以編寫一個同步配接器,將來自您自己網路的串流資料 1827新增至這些表格,或是可以從這些表格讀取串流資料,然後 1828顯示於您自己的應用程式中,或同時具備這兩種功能。有了這些功能,您的社交網路服務和應用程式就可以整合到 Android 的社交網路體驗。 1829 1830</p> 1831<h3 id="StreamText">社交串流文字</h3> 1832<p> 1833 串流項目永遠會與原始聯絡人關聯。 1834{@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID} 會連結到原始聯絡人的 1835 <code>_ID</code> 值。原始聯絡人的帳戶類型和帳戶名稱也會儲存在串流項目列。 1836 1837</p> 1838<p> 1839 串流中的資料會儲存在下列各欄: 1840</p> 1841<dl> 1842 <dt> 1843 {@code android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE} 1844 </dt> 1845 <dd> 1846 <strong>必要。</strong>與此串流項目相關聯的原始聯絡人使用者帳戶類型。 1847請記得在插入串流項目時設定此值。 1848 </dd> 1849 <dt> 1850 {@code android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME} 1851 </dt> 1852 <dd> 1853 <strong>必要。</strong>與此串流項目相關聯的原始聯絡人使用者帳戶名稱。 1854請記得在插入串流項目時設定此值。 1855 </dd> 1856 <dt> 1857 識別碼欄 1858 </dt> 1859 <dd> 1860 <strong>必要。</strong>您必須在插入串流項目時插入以下識別碼欄: 1861 1862 <ul> 1863 <li> 1864 {@code android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID}:與此串流項目相關聯的聯絡人 1865{@code android.provider.BaseColumns#_ID} 值。 1866 1867 </li> 1868 <li> 1869 {@code android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY}:與此串流項目相關聯的聯絡人 1870{@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} 值。 1871 1872 </li> 1873 <li> 1874 {@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID}:與此串流項目相關聯的原始聯絡人 1875{@code android.provider.BaseColumns#_ID} 值。 1876 1877 </li> 1878 </ul> 1879 </dd> 1880 <dt> 1881 {@code android.provider.ContactsContract.StreamItemsColumns#COMMENTS} 1882 </dt> 1883 <dd> 1884 選用。儲存您可以在串流項目開頭顯示的摘要資訊。 1885 </dd> 1886 <dt> 1887 {@code android.provider.ContactsContract.StreamItemsColumns#TEXT} 1888 </dt> 1889 <dd> 1890 串流項目的文字,可能是項目來源張貼的內容,或者會產生串流項目動作的描述。 1891此欄可以包含 1892{@link android.text.Html#fromHtml(String) fromHtml()} 能夠轉譯的任何格式內嵌資源影像。 1893供應程式會截斷較長的內容,但會試著避免破壞標籤。 1894 1895 </dd> 1896 <dt> 1897 {@code android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP} 1898 </dt> 1899 <dd> 1900 內含插入或更新串流項目時間的文字字串, 1901,以「毫秒」<em></em>為單位。插入或更新串流項目的應用程式負責維護此欄,聯絡人供應程式不會自動加以維護。 1902 1903 1904 </dd> 1905</dl> 1906<p> 1907 如要顯示串流項目的識別資訊,請使用 1908{@code android.provider.ContactsContract.StreamItemsColumns#RES_ICON}、 1909{@code android.provider.ContactsContract.StreamItemsColumns#RES_LABEL} 以及 1910{@code android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE} 連結到應用程式中的資源。 1911 1912</p> 1913<p> 1914 {@code android.provider.ContactsContract.StreamItems} 表格也包含 1915{@code android.provider.ContactsContract.StreamItemsColumns#SYNC1} 到 1916{@code android.provider.ContactsContract.StreamItemsColumns#SYNC4} 欄,專門供同步配接器使用。 1917 1918</p> 1919<h3 id="StreamPhotos">社交串流相片</h3> 1920<p> 1921 {@code android.provider.ContactsContract.StreamItemPhotos} 表格會儲存與串流項目相關聯的相片。 1922表格的 1923{@code android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID} 欄會連結到 1924 {@code android.provider.ContactsContract.StreamItems} 表格中 {@code android.provider.BaseColumns#_ID} 欄的值。 1925相片參照會儲存在表格中的以下各欄: 1926 1927</p> 1928<dl> 1929 <dt> 1930 {@code android.provider.ContactsContract.StreamItemPhotos#PHOTO} 欄 (BLOB)。 1931 </dt> 1932 <dd> 1933 相片的二進位檔,由供應程式調整大小以進行儲存和顯示。 1934 此欄是要提供與使用舊版聯絡人供應程式儲存相片的向下相容性。 1935不過,在目前版本中,您不應使用此欄來儲存相片。 1936請改用 {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} 或 1937{@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI} (下文提供這兩者的相關說明) 在檔案中儲存相片。 1938 1939此欄現在包含相片的縮圖可供讀取。 1940 1941 </dd> 1942 <dt> 1943 {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} 1944 </dt> 1945 <dd> 1946 原始聯絡人相片的數字識別碼。將此值附加到常數 1947{@link android.provider.ContactsContract.DisplayPhoto#CONTENT_URI DisplayPhoto.CONTENT_URI} 可取得指向單一相片檔案的內容 URI,然後呼叫 {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) 1948openAssetFileDescriptor()} 可取得此相片檔案的控制代碼。 1949 1950 1951 </dd> 1952 <dt> 1953 {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI} 1954 </dt> 1955 <dd> 1956 直接指向此列所呈現相片的相片檔案內容 URI。 1957 使用此 URI 呼叫 {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) 1958openAssetFileDescriptor()} 可取得相片檔案的控制代碼。 1959 </dd> 1960</dl> 1961<h3 id="SocialStreamTables">使用社交串流表格</h3> 1962<p> 1963 這些表格的運作方式與聯絡人供應程式中的其他主要表格大致相同,以下各項除外: 1964</p> 1965 <ul> 1966 <li> 1967 這些表格需要額外的存取權限。如要從中讀取,您的應用程式必須具備 {@code android.Manifest.permission#READ_SOCIAL_STREAM} 權限。 1968如要加以修改,您的應用程式必須具備 1969{@code android.Manifest.permission#WRITE_SOCIAL_STREAM} 權限。 1970 1971 </li> 1972 <li> 1973 針對 {@code android.provider.ContactsContract.StreamItems} 表格,每個原始聯絡人的儲存列數是有限制的。 1974達到此限制後,聯絡人供應程式會自動刪除 1975{@code android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP} 最舊的列,為新的串流項目列騰出空間。 1976 1977如要取得此限制,請發出查詢給內容 URI 1978{@code android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI}。 1979您只要將內容 URI 設為 <code>null</code> 即可,其餘引數不需要處理。 1980此查詢會傳回內含單一列的 Cursor 與單一欄 1981{@code android.provider.ContactsContract.StreamItems#MAX_ITEMS}。 1982 1983 </li> 1984 </ul> 1985 1986<p> 1987 類別 {@code android.provider.ContactsContract.StreamItems.StreamItemPhotos} 定義了單一串流項目,且內含相片列的 {@code android.provider.ContactsContract.StreamItemPhotos} 子表格。 1988 1989 1990</p> 1991<h3 id="SocialStreamInteraction">社交串流互動</h3> 1992<p> 1993 社交串流資料受到聯絡人供應程式與裝置聯絡人應用程式的管理,提供強大的方式將您的社交網路系統與現有聯絡人連接起來。 1994 1995提供下列功能: 1996</p> 1997 <ul> 1998 <li> 1999 使用同步配接器將您的社交網路服務同步到聯絡人供應程式後,您可以擷取某位使用者的聯絡人最近 Activity,並將它儲存在 {@code android.provider.ContactsContract.StreamItems} 和 2000{@code android.provider.ContactsContract.StreamItemPhotos} 表格中,供後續使用。 2001 2002 2003 </li> 2004 <li> 2005 除了一般同步之外,您可以在使用者選取要檢視的聯絡人時,觸發您的同步配接器,以擷取其他資料。 2006此舉可讓您的同步配接器擷取聯絡人高解析度的相片,以及聯絡人最近的串流項目。 2007 2008 </li> 2009 <li> 2010 藉由向裝置的聯絡人應用程式和聯絡人供應程式註冊通知,您可以在檢視聯絡人時「收到」<em></em>意圖,並於此時更新您服務中的聯絡人狀態。 2011 2012相較於與同步配接器執行完整同步, 2013此方式較快速且使用的頻寬較少。 2014 </li> 2015 <li> 2016 使用者在裝置的聯絡人應用程式查看聯絡人時,可以將聯絡人新增至您的社交網路服務。 2017您可以透過「邀請聯絡人」啟用上述功能。「邀請聯絡人」會啟用一連串的 Activity,將現有聯絡人新增至您的網路和 XML 檔案。此檔案會將您應用程式的詳細資訊提供給裝置的聯絡人應用程式和聯絡人供應程式。 2018 2019 2020 2021 </li> 2022 </ul> 2023<p> 2024 串流項目與聯絡人供應程式的一般同步與其他同步相同。 2025如要進一步瞭解同步,請參閱<a href="#SyncAdapters">聯絡人供應程式同步配接器</a>。 2026以下兩節說明如何註冊通知和邀請聯絡人。 2027 2028</p> 2029<h4>註冊以處理社交網路檢視</h4> 2030<p> 2031 註冊您的同步配接器,使其在使用者查看由您的同步配接器所管理的聯絡人時收到通知: 2032 2033</p> 2034<ol> 2035 <li> 2036 在專案的 <code>res/xml/</code> 目錄中建立名稱為 <code>contacts.xml</code>的檔案。 2037如果已經有這個檔案,可略過此步驟。 2038 </li> 2039 <li> 2040 在此檔案中,新增 2041<code><ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"></code> 元素。 2042 如果這個元素已經存在,可略過此步驟。 2043 </li> 2044 <li> 2045 為了註冊服務,讓使用者在裝置的聯絡人應用程式中開啟聯絡人的詳細資訊頁面時收到通知,請將 2046 <code>viewContactNotifyService="<em>serviceclass</em>"</code> 屬性新增至此元素,其中 2047 <code><em>serviceclass</em></code> 是該服務的完整類別名稱,而此服務會收到來自裝置聯絡人應用程式的意圖。 2048 2049對於通知器服務而言,使用擴充 {@link android.app.IntentService} 的類別可以讓此服務接收意圖。 2050 2051傳入意圖的資料中含有使用者所點擊該名原始聯絡人的內容 URI。 2052您可以從通知器服務繫結,然後呼叫您的同步配接器,以更新原始聯絡人的資料。 2053 2054 </li> 2055</ol> 2056<p> 2057 如何註冊使用者點擊串流項目或相片 (或兩者) 時所呼叫的 Activity: 2058</p> 2059<ol> 2060 <li> 2061 在專案的 <code>res/xml/</code> 目錄中建立名稱為 <code>contacts.xml</code>的檔案。 2062如果已經有這個檔案,可略過此步驟。 2063 </li> 2064 <li> 2065 在此檔案中,新增 2066<code><ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"></code> 元素。 2067 如果這個元素已經存在,可略過此步驟。 2068 </li> 2069 <li> 2070 為了註冊其中一個 Activity,讓它處理使用者在裝置的聯絡人應用程式中點擊串流項目的 Activity,請將 2071 <code>viewStreamItemActivity="<em>activityclass</em>"</code> 屬性新增至此元素,其中 2072 <code><em>activityclass</em></code> 是該 Activity 的完整類別名稱,而此 Activity 會收到來自裝置聯絡人應用程式的意圖。 2073 2074 2075 </li> 2076 <li> 2077 為了註冊其中一個 Activity,讓它處理使用者在裝置的聯絡人應用程式中點擊串流相片的活動,請將 2078 <code>viewStreamItemPhotoActivity="<em>activityclass</em>"</code> 屬性新增至此元素,其中 2079 <code><em>activityclass</em></code> 是該 Activity 的完整類別名稱,而此 Activity 會收到來自裝置聯絡人應用程式的意圖。 2080 2081 2082 </li> 2083</ol> 2084<p> 2085 如要進一步瞭解 <code><ContactsAccountType></code> 元素,請參閱 <a href="#SocialStreamAcctType"><ContactsAccountType> 元素</a>。 2086 2087</p> 2088<p> 2089 傳入意圖的資料中含有使用者所按下項目或相片的內容 URI。 2090 如要針對文字項目和相片採取不同的 Activity,請在相同的檔案中同時使用兩個屬性。 2091</p> 2092<h4>與社交網路服務互動</h4> 2093<p> 2094 使用者不需要離開裝置的聯絡人應用程式,就可以邀請聯絡人到您的社交網路網站。 2095您可以改為讓裝置的聯絡人應用程式傳送意圖,以邀請聯絡人前往您的 Activity。 2096如要進行此設定: 2097</p> 2098<ol> 2099 <li> 2100 在專案的 <code>res/xml/</code> 目錄中建立名稱為 <code>contacts.xml</code>的檔案。 2101如果已經有這個檔案,可略過此步驟。 2102 </li> 2103 <li> 2104 在此檔案中,新增 <code><ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"></code> 元素。 2105 2106 如果這個元素已經存在,可略過此步驟。 2107 </li> 2108 <li> 2109 新增下列屬性: 2110 <ul> 2111 <li><code>inviteContactActivity="<em>activityclass</em>"</code></li> 2112 <li> 2113 <code>inviteContactActionLabel="@string/<em>invite_action_label</em>"</code> 2114 </li> 2115 </ul> 2116 <code><em>activityclass</em></code> 值是 Activity 的完整類別名稱,以此 Activity 接收意圖。 2117<code><em>invite_action_label</em></code> 值是顯示在裝置聯絡人應用程式內 [新增連線]<strong></strong> 選單中的文字字串。 2118 2119 2120 </li> 2121</ol> 2122<p class="note"> 2123 <strong>注意:</strong><code>ContactsSource</code> 是 2124 <code>ContactsAccountType</code> 已淘汰的標籤名稱。 2125</p> 2126<h3 id="ContactsFile">contacts.xml 參照</h3> 2127<p> 2128 <code>contacts.xml</code> 檔案包含的 XML 元素,可控制您的同步配接器與應用程式 (聯絡人應用程式和聯絡人供應程式) 之間的互動。 2129這些元素在以下各節有詳細的說明。 2130 2131</p> 2132<h4 id="SocialStreamAcctType"><ContactsAccountType> 元素</h4> 2133<p> 2134 <code><ContactsAccountType></code> 元素控制您的應用程式與聯絡人應用程式之間的互動。 2135此元素的語法如下: 2136</p> 2137<pre> 2138<ContactsAccountType 2139 xmlns:android="http://schemas.android.com/apk/res/android" 2140 inviteContactActivity="<em>activity_name</em>" 2141 inviteContactActionLabel="<em>invite_command_text</em>" 2142 viewContactNotifyService="<em>view_notify_service</em>" 2143 viewGroupActivity="<em>group_view_activity</em>" 2144 viewGroupActionLabel="<em>group_action_text</em>" 2145 viewStreamItemActivity="<em>viewstream_activity_name</em>" 2146 viewStreamItemPhotoActivity="<em>viewphotostream_activity_name</em>"> 2147</pre> 2148<p> 2149 <strong>包含於:</strong> 2150</p> 2151<p> 2152 <code>res/xml/contacts.xml</code> 2153</p> 2154<p> 2155 <strong>可以包含:</strong> 2156</p> 2157<p> 2158 <strong><code><ContactsDataKind></code></strong> 2159</p> 2160<p> 2161 <strong>描述:</strong> 2162</p> 2163<p> 2164 宣告 Android 元件和 UI 標籤,讓使用者可以邀請聯絡人加入社交網路、使用者的社交網路串流更新內容時通知使用者等等。 2165 2166 2167</p> 2168<p> 2169 請注意,<code><ContactsAccountType></code> 的屬性不需要使用屬性前置詞 <code>android:</code>。 2170 2171</p> 2172<p> 2173 <strong>屬性:</strong> 2174</p> 2175<dl> 2176 <dt>{@code inviteContactActivity}</dt> 2177 <dd> 2178 使用者從裝置的聯絡人應用程式選取[新增連線]<strong></strong>時,您希望在應用程式中啟動的 Activity 完整類別名稱。 2179 2180 2181 </dd> 2182 <dt>{@code inviteContactActionLabel}</dt> 2183 <dd> 2184 在 [新增連線]<strong></strong> 選單的 2185 {@code inviteContactActivity} 中所指定 Activity 的顯示文字字串。 2186 例如,您可以使用「關注我的網路活動」字串。此標籤可以使用字串資源識別碼。 2187 2188 </dd> 2189 <dt>{@code viewContactNotifyService}</dt> 2190 <dd> 2191 使用者檢視聯絡人時,要接收通知的應用程式中的服務完整類別名稱。 2192此通知是由裝置的聯絡人應用程式所傳送,這樣可以讓您的應用程式延後要處理大量資料的操作,需要時再加以處理。 2193 2194例如,您的應用程式可以藉由讀取並顯示聯絡人的高解析度相片,以及最近的社交串流項目,以回應此通知。 2195 2196如要進一步瞭解此功能,請參閱<a href="#SocialStreamInteraction">社交串流互動</a>。 2197您可以在 2198 <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">SampleSyncAdapter</a> 範例應用程式的 <code>NotifierService.java</code>中查看通知服務的範例。 2199 2200 2201 </dd> 2202 <dt>{@code viewGroupActivity}</dt> 2203 <dd> 2204 應用程式中可以顯示群組資訊的 Activity 完整類別名稱。 2205使用者在裝置的聯絡人應用程式中按一下群組標籤時,會顯示此 Activity 的 UI。 2206 2207 </dd> 2208 <dt>{@code viewGroupActionLabel}</dt> 2209 <dd> 2210 聯絡人應用程式顯示 UI 控制項的標籤,可以讓使用者在您的應用程式中查看群組。 2211 2212 <p> 2213 例如,如果您在裝置上安裝 Google+ 應用程式,而您將Google+ 與聯絡人應用程式進行同步,您會看到 Google+ 社交圈已列為聯絡人應用程式 [群組]<strong></strong> 標籤中的群組。 2214 2215如果按一下 Google+ 社交圈,您會看到該社交圈中的人員已列為「群組」。 2216系統會在畫面頂端顯示 Google+ 圖示,如果您按一下此圖示,則控制權會切換到 Google+ 應用程式。聯絡人應用程式使用 2217{@code viewGroupActivity} 執行此動作,並使用 Google+ 圖示做為 2218{@code viewGroupActionLabel} 的值。 2219 2220 2221 </p> 2222 <p> 2223 此屬性可以使用字串資源識別碼。 2224 </p> 2225 </dd> 2226 <dt>{@code viewStreamItemActivity}</dt> 2227 <dd> 2228 使用者按一下原始聯絡人的串流項目時,裝置的聯絡人應用程式所啟動應用程式中的 Activity 完整類別名稱。 2229 2230 </dd> 2231 <dt>{@code viewStreamItemPhotoActivity}</dt> 2232 <dd> 2233 使用者按一下原始聯絡人串流項目中的相片時,裝置的聯絡人應用程式所啟動應用程式中的 Activity 完整類別名稱。 2234 2235 2236 </dd> 2237</dl> 2238<h4 id="SocialStreamDataKind"><ContactsDataKind> 元素</h4> 2239<p> 2240 <code><ContactsDataKind></code> 元素控制聯絡人應用程式的 UI 中,您的應用程式自訂資料列所顯示的控制項。此元素的語法如下: 2241 2242</p> 2243<pre> 2244<ContactsDataKind 2245 android:mimeType="<em>MIMEtype</em>" 2246 android:icon="<em>icon_resources</em>" 2247 android:summaryColumn="<em>column_name</em>" 2248 android:detailColumn="<em>column_name</em>"> 2249</pre> 2250<p> 2251 <strong>包含於:</strong> 2252</p> 2253<code><ContactsAccountType></code> 2254<p> 2255 <strong>描述:</strong> 2256</p> 2257<p> 2258 使用此元素讓聯絡人應用程式,將自訂資料列的內容顯示為原始聯絡人詳細資訊的一部分。 2259<code><ContactsAccountType></code> 的每個 <code><ContactsDataKind></code> 子元素都代表同步配接器新增至 {@link android.provider.ContactsContract.Data} 表格的自訂資料列類型。 2260 2261針對您使用的每個自訂 MIME 類型,新增一個 2262 <code><ContactsDataKind></code> 元素。如果您不要顯示某個自訂資料列的資料,就不用為該列新增元素。 2263 2264</p> 2265<p> 2266 <strong>屬性:</strong> 2267</p> 2268<dl> 2269 <dt>{@code android:mimeType}</dt> 2270 <dd> 2271 您在 2272 {@link android.provider.ContactsContract.Data} 表格中已經為自訂資料列類型所定義的自訂 MIME 類型。例如, 2273<code>vnd.android.cursor.item/vnd.example.locationstatus</code> 值可能是 2274記錄聯絡人最後已知位置資料列的自訂 MIME 類型。 2275 </dd> 2276 <dt>{@code android:icon}</dt> 2277 <dd> 2278 聯絡人應用程式顯示在資料旁邊的 Android 2279<a href="{@docRoot}guide/topics/resources/drawable-resource.html">可繪資源</a>。 2280使用此項向使用者指出資料是來自您的服務。 2281 2282 </dd> 2283 <dt>{@code android:summaryColumn}</dt> 2284 <dd> 2285 從資料列擷取兩個值,其中第一個值的欄名稱。此資料列的值會顯示為該項目的第一行。 2286第一行的用意是做為資料的摘要使用,但為選用。 2287另請參閱 2288 <a href="#detailColumn">android:detailColumn</a>。 2289 </dd> 2290 <dt>{@code android:detailColumn}</dt> 2291 <dd> 2292 從資料列擷取兩個值,其中第二個值的欄名稱。此資料列的值會顯示為該項目的第二行。 2293另請參閱 2294{@code android:summaryColumn}。 2295 </dd> 2296</dl> 2297<h2 id="AdditionalFeatures">其他聯絡人供應程式功能</h2> 2298<p> 2299 除了上一節所描述的主要功能之外,聯絡人供應程式也提供以下實用功能來處理聯絡人資料: 2300 2301</p> 2302 <ul> 2303 <li>聯絡人群組</li> 2304 <li>相片功能</li> 2305 </ul> 2306<h3 id="Groups">聯絡人群組</h3> 2307<p> 2308 聯絡人供應程式可以選擇為群組<strong></strong>資料相關的聯絡人集合貼上標籤。 2309如果與使用者帳戶關聯的伺服器要維護群組,該帳戶的帳戶類型所屬的同步配接器,應該要在聯絡人供應程式和伺服器之間傳輸群組資料。 2310 2311使用者將新的聯絡人新增至伺服器,然後將此聯絡人放置於新群組時,同步配接器必須將新群組新增至 {@link android.provider.ContactsContract.Groups} 表格。 2312 2313原始聯絡人所屬的一或多個群組會使用 {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership} MIME 類型儲存在 {@link android.provider.ContactsContract.Data} 表格。 2314 2315 2316</p> 2317<p> 2318 如果您設計的同步配接器,會將原始聯絡人資料從伺服器新增至聯絡人供應程式,表示您並未使用群組,那麼您需要告訴供應程式讓您的資料變成可見的。 2319 2320在使用者將帳戶新增至裝置時,要執行的程式碼中,更新聯絡人供應程式為帳戶新增的 {@link android.provider.ContactsContract.Settings} 列。 2321 2322在此列中,將 {@link android.provider.ContactsContract.SettingsColumns#UNGROUPED_VISIBLE 2323Settings.UNGROUPED_VISIBLE} 欄的值設為 1。 2324這麼做之後,即使您沒有使用群組,聯絡人供應程式 2325一律會讓您的聯絡人資料成為可見的。 2326</p> 2327<h3 id="Photos">聯絡人相片</h3> 2328<p> 2329 {@link android.provider.ContactsContract.Data} 表格會使用 MIME 類型 {@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE 2330Photo.CONTENT_ITEM_TYPE} 在列中儲存相片。 2331列的 2332{@link android.provider.ContactsContract.RawContactsColumns#CONTACT_ID} 欄是連結到其所屬原始聯絡人的 2333 {@code android.provider.BaseColumns#_ID} 欄。 2334 類別 {@link android.provider.ContactsContract.Contacts.Photo} 定義了 2335 {@link android.provider.ContactsContract.Contacts} 的子表格,其中包含聯絡人主要相片的相片資訊,也就是聯絡人之主要原始聯絡人的主要相片。 2336同樣地, 2337類別 {@link android.provider.ContactsContract.RawContacts.DisplayPhoto} 定義了 {@link android.provider.ContactsContract.RawContacts} 的子表格,其中包含原始聯絡人之主要相片的相片資訊。 2338 2339 2340</p> 2341<p> 2342 {@link android.provider.ContactsContract.Contacts.Photo} 和 2343{@link android.provider.ContactsContract.RawContacts.DisplayPhoto} 的參考文件含有擷取相片資訊的範例。 2344擷取原始聯絡人的主要縮圖沒有方便使用的類別,不過您可以傳送查詢到 2345{@link android.provider.ContactsContract.Data} 表格,然後選取原始聯絡人的 2346{@code android.provider.BaseColumns#_ID}、{@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE 2347Photo.CONTENT_ITEM_TYPE} 以及 {@link android.provider.ContactsContract.Data#IS_PRIMARY} 欄,以尋找原始聯絡人的主要相片列。 2348 2349 2350 2351</p> 2352<p> 2353 人員的社交串流資料可能也包括相片。這些資訊都儲存在 2354{@code android.provider.ContactsContract.StreamItemPhotos} 表格。<a href="#StreamPhotos">社交串流相片</a>中針對此表格會有更詳細的說明。 2355 2356</p> 2357