ผู้ให้บริการรายชื่อติดต่อเป็นคอมโพเนนต์ Android ที่มีประสิทธิภาพและยืดหยุ่นซึ่งจัดการที่เก็บข้อมูลส่วนกลางของอุปกรณ์เกี่ยวกับผู้คน ผู้ให้บริการรายชื่อติดต่อคือแหล่งข้อมูล ที่คุณเห็นในแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ และคุณยังเข้าถึงข้อมูลใน แอปพลิเคชันของคุณเองและโอนข้อมูลระหว่างอุปกรณ์กับบริการออนไลน์ได้ด้วย ผู้ให้บริการรองรับ แหล่งข้อมูลที่หลากหลายและพยายามจัดการข้อมูลให้ได้มากที่สุดสำหรับแต่ละบุคคล ซึ่งส่งผลให้องค์กรมีความซับซ้อน ด้วยเหตุนี้ API ของผู้ให้บริการจึงมีชุดคลาสและอินเทอร์เฟซของสัญญาที่ครอบคลุม ซึ่งช่วยให้ทั้งการดึงข้อมูลและการแก้ไขข้อมูลเป็นไปได้
คู่มือนี้อธิบายสิ่งต่อไปนี้
- โครงสร้างพื้นฐานของผู้ให้บริการ
- วิธีกู้คืนข้อมูลจากผู้ให้บริการ
- วิธีแก้ไขข้อมูลในผู้ให้บริการ
- วิธีเขียน Sync Adapter สำหรับซิงค์ข้อมูลจากเซิร์ฟเวอร์ไปยัง ผู้ให้บริการรายชื่อติดต่อ
คู่มือนี้ถือว่าคุณทราบข้อมูลพื้นฐานเกี่ยวกับผู้ให้บริการเนื้อหาของ Android ดูข้อมูลเพิ่มเติม เกี่ยวกับผู้ให้บริการเนื้อหาของ Android ได้ที่คู่มือ พื้นฐานของผู้ให้บริการเนื้อหา
องค์กร Contacts Provider
Contacts Provider เป็นคอมโพเนนต์ผู้ให้บริการเนื้อหาของ Android โดยจะเก็บข้อมูล 3 ประเภทเกี่ยวกับบุคคล ซึ่งแต่ละประเภทจะสอดคล้องกับตารางที่ผู้ให้บริการเสนอ ดังที่แสดงในรูปที่ 1

รูปที่ 1 โครงสร้างตาราง Contacts Provider
โดยทั่วไปแล้วตารางทั้ง 3 ตารางนี้จะอ้างอิงตามชื่อของคลาสสัญญา คลาส กำหนดค่าคงที่สำหรับ URI ของเนื้อหา ชื่อคอลัมน์ และค่าคอลัมน์ที่ใช้โดยตารางต่อไปนี้
-
ContactsContract.Contacts
ตาราง - แถวที่แสดงบุคคลต่างๆ โดยอิงตามการรวบรวมแถวรายชื่อติดต่อดิบ
-
ContactsContract.RawContacts
ตาราง - แถวที่มีข้อมูลสรุปของบุคคลหนึ่งๆ ซึ่งเฉพาะเจาะจงสำหรับบัญชีผู้ใช้และประเภท
-
ContactsContract.Data
ตาราง - แถวที่มีรายละเอียดสำหรับรายชื่อติดต่อดิบ เช่น อีเมลหรือหมายเลขโทรศัพท์
ตารางอื่นๆ ที่แสดงโดยคลาสสัญญาใน ContactsContract
คือตารางเสริมที่ผู้ให้บริการรายชื่อติดต่อใช้เพื่อจัดการการดำเนินการหรือรองรับ
ฟังก์ชันเฉพาะในแอปพลิเคชันรายชื่อติดต่อหรือโทรศัพท์ของอุปกรณ์
ข้อมูลติดต่อดิบ
รายชื่อติดต่อดิบแสดงข้อมูลของบุคคลที่มาจากบัญชีประเภทเดียวและชื่อบัญชี เนื่องจากผู้ให้บริการรายชื่อติดต่ออนุญาตให้ใช้บริการออนไลน์มากกว่า 1 รายการเป็นแหล่งข้อมูลของบุคคลหนึ่งๆ ผู้ให้บริการรายชื่อติดต่อจึงอนุญาตให้ใช้รายชื่อติดต่อดิบหลายรายการสำหรับบุคคลเดียวกัน นอกจากนี้ รายชื่อติดต่อดิบหลายรายการยังช่วยให้ผู้ใช้รวมข้อมูลของบุคคลจากบัญชีมากกว่า 1 บัญชี จากบัญชีประเภทเดียวกันได้ด้วย
ระบบจะไม่จัดเก็บข้อมูลส่วนใหญ่ของรายชื่อติดต่อดิบในตาราง ContactsContract.RawContacts
แต่จะจัดเก็บไว้ในแถวอย่างน้อย 1 แถวในตาราง ContactsContract.Data
แถวข้อมูลแต่ละแถวมีคอลัมน์
Data.RAW_CONTACT_ID
ที่
มีค่า RawContacts._ID
ของ
แถว ContactsContract.RawContacts
หลัก
คอลัมน์รายชื่อติดต่อดิบที่สำคัญ
คอลัมน์ที่สำคัญในตาราง ContactsContract.RawContacts
แสดงอยู่ในตารางที่ 1 โปรดอ่านหมายเหตุที่อยู่หลังตาราง
ตารางที่ 1 คอลัมน์รายชื่อติดต่อดิบที่สำคัญ
ชื่อคอลัมน์ | ใช้ | หมายเหตุ |
---|---|---|
ACCOUNT_NAME
|
ชื่อบัญชีสำหรับประเภทบัญชีที่เป็นแหล่งที่มาของรายชื่อติดต่อดิบนี้
เช่น ชื่อบัญชีของบัญชี Google คืออีเมล Gmail ของเจ้าของอุปกรณ์
ดูข้อมูลเพิ่มเติมได้ที่รายการถัดไปสำหรับ
ACCOUNT_TYPE
|
รูปแบบของชื่อนี้จะขึ้นอยู่กับประเภทบัญชี ซึ่งไม่จำเป็นต้องเป็นอีเมล |
ACCOUNT_TYPE
|
ประเภทบัญชีที่เป็นแหล่งที่มาของรายชื่อติดต่อดิบนี้ เช่น ประเภทบัญชีของบัญชี Google คือ com.google ระบุประเภทบัญชีของคุณเสมอ
ด้วยตัวระบุโดเมนสำหรับโดเมนที่คุณเป็นเจ้าของหรือควบคุม ซึ่งจะช่วยให้มั่นใจได้ว่าประเภทบัญชีของคุณจะไม่ซ้ำกับใคร
|
บัญชีประเภทที่มีข้อมูลรายชื่อติดต่อมักจะมี Sync Adapter ที่เชื่อมโยงกันซึ่งจะ ซิงค์กับผู้ให้บริการรายชื่อติดต่อ |
DELETED
|
แฟล็ก "deleted" สำหรับรายชื่อติดต่อดิบ | โดยฟีเจอร์นี้จะช่วยให้ผู้ให้บริการรายชื่อติดต่อสามารถเก็บแถวไว้ภายในจนกว่าอะแดปเตอร์การซิงค์ จะลบแถวออกจากเซิร์ฟเวอร์ของตนได้ แล้วจึงลบแถวออกจากที่เก็บ ในที่สุด |
หมายเหตุ
หมายเหตุสำคัญเกี่ยวกับตาราง
ContactsContract.RawContacts
มีดังนี้
-
ระบบจะไม่จัดเก็บชื่อของรายชื่อติดต่อดิบในแถวของรายชื่อติดต่อดิบใน
ContactsContract.RawContacts
แต่จะจัดเก็บไว้ใน ตารางContactsContract.Data
ใน แถวContactsContract.CommonDataKinds.StructuredName
รายชื่อติดต่อดิบ มีแถวประเภทนี้เพียงแถวเดียวในตารางContactsContract.Data
-
ข้อควรระวัง: หากต้องการใช้ข้อมูลบัญชีของคุณเองในแถวรายชื่อติดต่อดิบ คุณต้อง
ลงทะเบียนกับ
AccountManager
ก่อน โดยให้แจ้ง ให้ผู้ใช้เพิ่มประเภทบัญชีและชื่อบัญชีของตนลงในรายการบัญชี หากคุณไม่ ดำเนินการนี้ ผู้ให้บริการรายชื่อติดต่อจะลบแถวรายชื่อติดต่อดิบโดยอัตโนมัติเช่น หากต้องการให้แอปเก็บรักษาข้อมูลรายชื่อติดต่อสำหรับบริการบนเว็บที่มีโดเมน
com.example.dataservice
และบัญชีของผู้ใช้สำหรับบริการของคุณคือbecky.sharp@dataservice.example.com
ผู้ใช้ต้องเพิ่ม "ประเภท" บัญชี (com.example.dataservice
) และ "ชื่อ" บัญชี (becky.smart@dataservice.example.com
) ก่อนแอปจะเพิ่มแถวรายชื่อติดต่อดิบได้ คุณสามารถอธิบายข้อกำหนดนี้แก่ผู้ใช้ในเอกสารประกอบ หรือแจ้งให้ผู้ใช้เพิ่มประเภทและชื่อ หรือทั้ง 2 อย่าง ประเภทบัญชีและชื่อบัญชี มีการอธิบายอย่างละเอียดในส่วนถัดไป
แหล่งที่มาของข้อมูลรายชื่อติดต่อดิบ
หากต้องการทำความเข้าใจวิธีการทำงานของรายชื่อติดต่อดิบ ให้พิจารณาผู้ใช้ "Emily Dickinson" ซึ่งมีบัญชีผู้ใช้ 3 บัญชีต่อไปนี้ในอุปกรณ์
emily.dickinson@gmail.com
emilyd@gmail.com
- บัญชี Twitter "belle_of_amherst"
ผู้ใช้รายนี้ได้เปิดใช้ซิงค์รายชื่อติดต่อสำหรับบัญชีทั้ง 3 บัญชีนี้ในการตั้งค่าบัญชี
สมมติว่าเอมิลี ดิกคินสันเปิดหน้าต่างเบราว์เซอร์ ลงชื่อเข้าใช้ Gmail ในชื่อ
emily.dickinson@gmail.com
เปิด
รายชื่อติดต่อ และเพิ่ม "Thomas Higginson" ต่อมาเธอเข้าสู่ระบบ Gmail ในชื่อ
emilyd@gmail.com
และส่งอีเมลถึง "Thomas Higginson" ซึ่งระบบจะเพิ่ม
เขาเป็นรายชื่อติดต่อโดยอัตโนมัติ นอกจากนี้ เธอยังติดตาม "colonel_tom" (รหัส Twitter ของ Thomas Higginson) บน
Twitter ด้วย
Contacts Provider จะสร้างรายชื่อติดต่อดิบ 3 รายการอันเป็นผลมาจากการดำเนินการนี้
-
ข้อมูลติดต่อดิบสำหรับ "Thomas Higginson" ที่เชื่อมโยงกับ
emily.dickinson@gmail.com
ประเภทบัญชีผู้ใช้คือ Google -
ข้อมูลติดต่อดิบที่ 2 สำหรับ "Thomas Higginson" ที่เชื่อมโยงกับ
emilyd@gmail.com
ประเภทบัญชีผู้ใช้คือ Google มีรายชื่อติดต่อดิบรายการที่ 2 แม้ว่าชื่อจะเหมือนกับชื่อก่อนหน้าก็ตาม เนื่องจากมีการเพิ่มบุคคลดังกล่าวสำหรับบัญชีผู้ใช้ที่แตกต่างกัน - รายชื่อติดต่อดิบที่ 3 สำหรับ "Thomas Higginson" ที่เชื่อมโยงกับ "belle_of_amherst" ประเภทบัญชีผู้ใช้คือ Twitter
ข้อมูล
ดังที่ได้กล่าวไว้ก่อนหน้านี้ ข้อมูลสำหรับรายชื่อติดต่อดิบจะจัดเก็บไว้ในแถว ContactsContract.Data
ที่ลิงก์กับค่า _ID
ของรายชื่อติดต่อดิบ ซึ่งช่วยให้ผู้ติดต่อแบบดิบรายเดียวมีข้อมูลประเภทเดียวกันได้หลายอินสแตนซ์ เช่น อีเมลหรือหมายเลขโทรศัพท์ ตัวอย่างเช่น หาก
"Thomas Higginson" สำหรับ emilyd@gmail.com
(แถวรายชื่อติดต่อดิบสำหรับ Thomas Higginson
ที่เชื่อมโยงกับบัญชี Google emilyd@gmail.com
) มีอีเมลส่วนตัวเป็น
thigg@gmail.com
และอีเมลที่ทำงานเป็น
thomas.higginson@gmail.com
ผู้ให้บริการรายชื่อติดต่อจะจัดเก็บแถวอีเมล 2 รายการ
และลิงก์ทั้ง 2 รายการกับรายชื่อติดต่อดิบ
โปรดทราบว่าระบบจะจัดเก็บข้อมูลประเภทต่างๆ ไว้ในตารางเดียวนี้ แถวชื่อที่แสดง
หมายเลขโทรศัพท์ อีเมล ที่อยู่ทางไปรษณีย์ รูปภาพ และรายละเอียดเว็บไซต์ทั้งหมดจะอยู่ในตาราง
ContactsContract.Data
ตาราง
ContactsContract.Data
มีคอลัมน์บางรายการที่มีชื่อสื่อความหมาย
และคอลัมน์อื่นๆ ที่มีชื่อทั่วไป เพื่อช่วยในการจัดการ เนื้อหาของคอลัมน์ชื่อที่สื่อความหมายจะมี
ความหมายเดียวกันไม่ว่าจะเป็นข้อมูลประเภทใดในแถว ส่วนเนื้อหาของคอลัมน์ชื่อทั่วไปจะมี
ความหมายแตกต่างกันไปตามประเภทของข้อมูล
ชื่อคอลัมน์ที่สื่อความหมาย
ตัวอย่างชื่อคอลัมน์ที่สื่อความหมายมีดังนี้
-
RAW_CONTACT_ID
-
ค่าของคอลัมน์
_ID
ของรายชื่อติดต่อดิบสำหรับข้อมูลนี้ -
MIMETYPE
-
ประเภทของข้อมูลที่จัดเก็บในแถวนี้ ซึ่งแสดงเป็นประเภท MIME ที่กำหนดเอง Contacts Provider
ใช้ประเภท MIME ที่กำหนดไว้ในคลาสย่อยของ
ContactsContract.CommonDataKinds
MIME ประเภทเหล่านี้เป็นโอเพนซอร์ส และแอปพลิเคชันหรืออะแดปเตอร์การซิงค์ใดก็ได้ที่ใช้ได้กับผู้ให้บริการรายชื่อติดต่อจะใช้ MIME ประเภทเหล่านี้ได้ -
IS_PRIMARY
-
หากแถวข้อมูลประเภทนี้เกิดขึ้นได้มากกว่า 1 ครั้งสำหรับรายชื่อติดต่อดิบ คอลัมน์
IS_PRIMARY
จะติด แฟล็กแถวข้อมูลที่มีข้อมูลหลักสำหรับประเภทนั้น เช่น หาก ผู้ใช้กดหมายเลขโทรศัพท์ของรายชื่อติดต่อค้างไว้แล้วเลือกตั้งค่าเริ่มต้น แถวContactsContract.Data
ที่มีหมายเลขนั้น จะมีคอลัมน์IS_PRIMARY
ตั้งค่าเป็น ค่าที่ไม่ใช่ 0
ชื่อคอลัมน์ทั่วไป
มีคอลัมน์ทั่วไป 15 รายการชื่อ DATA1
ถึง
DATA15
ซึ่งพร้อมให้บริการโดยทั่วไป และคอลัมน์ทั่วไปอีก 4 รายการ
ชื่อ SYNC1
ถึง SYNC4
ซึ่งควรใช้โดยอะแดปเตอร์การซิงค์เท่านั้น
ค่าคงที่ชื่อคอลัมน์ทั่วไปจะใช้งานได้เสมอ ไม่ว่าแถวจะมีข้อมูลประเภทใดก็ตาม
คอลัมน์ DATA1
มีการจัดทำดัชนี ผู้ให้บริการรายชื่อติดต่อจะใช้คอลัมน์นี้เสมอสำหรับ
ข้อมูลที่ผู้ให้บริการคาดว่าจะเป็นเป้าหมายของการค้นหาที่พบบ่อยที่สุด เช่น
ในแถวอีเมล คอลัมน์นี้จะมีอีเมลจริง
ตามธรรมเนียมแล้ว คอลัมน์ DATA15
จะสงวนไว้สำหรับจัดเก็บข้อมูล Binary Large Object
(BLOB) เช่น รูปขนาดย่อของรูปภาพ
ชื่อคอลัมน์เฉพาะประเภท
เพื่ออำนวยความสะดวกในการทำงานกับคอลัมน์สำหรับแถวประเภทใดประเภทหนึ่ง ผู้ให้บริการรายชื่อติดต่อ
ยังมีค่าคงที่ชื่อคอลัมน์เฉพาะประเภท ซึ่งกำหนดไว้ในคลาสย่อยของ
ContactsContract.CommonDataKinds
ค่าคงที่จะกำหนดชื่อค่าคงที่ที่แตกต่างกันให้กับชื่อคอลัมน์เดียวกัน ซึ่งจะช่วยให้คุณเข้าถึงข้อมูลในแถวของประเภทที่เฉพาะเจาะจงได้
เช่น คลาส ContactsContract.CommonDataKinds.Email
จะกำหนด
ค่าคงที่ของชื่อคอลัมน์ที่เฉพาะเจาะจงประเภทสำหรับแถว ContactsContract.Data
ที่มีประเภท MIME
Email.CONTENT_ITEM_TYPE
คลาสมีค่าคงที่
ADDRESS
สำหรับคอลัมน์
อีเมล ค่าจริงของ
ADDRESS
คือ "data1" ซึ่งเป็น
ชื่อทั่วไปของคอลัมน์
ข้อควรระวัง: อย่าเพิ่มข้อมูลที่กำหนดเองลงในตาราง
ContactsContract.Data
โดยใช้แถวที่มีประเภท MIME ที่กำหนดไว้ล่วงหน้าของผู้ให้บริการ หากทำเช่นนั้น ข้อมูลอาจสูญหายหรือทำให้ผู้ให้บริการทำงานผิดปกติ
ได้ เช่น คุณไม่ควรเพิ่มแถวที่มี MIME ประเภท
Email.CONTENT_ITEM_TYPE
ซึ่งมีชื่อผู้ใช้แทนอีเมลในคอลัมน์
DATA1
หากคุณใช้ประเภท MIME ที่กำหนดเองสำหรับแถว คุณก็สามารถ
กำหนดชื่อคอลัมน์เฉพาะประเภทของคุณเองและใช้คอลัมน์ได้ตามต้องการ
รูปที่ 2 แสดงลักษณะของคอลัมน์อธิบายและคอลัมน์ข้อมูลใน
ContactsContract.Data
แถว และวิธีที่ชื่อคอลัมน์เฉพาะประเภท "ซ้อนทับ"
ชื่อคอลัมน์ทั่วไป

รูปที่ 2 ชื่อคอลัมน์เฉพาะประเภทและชื่อคอลัมน์ทั่วไป
คลาสชื่อคอลัมน์เฉพาะประเภท
ตารางที่ 2 แสดงรายการคลาสชื่อคอลัมน์เฉพาะประเภทที่ใช้กันมากที่สุด
ตารางที่ 2 คลาสชื่อคอลัมน์เฉพาะประเภท
ชั้นเรียนการแมป | ประเภทของข้อมูล | หมายเหตุ |
---|---|---|
ContactsContract.CommonDataKinds.StructuredName |
ข้อมูลชื่อสำหรับรายชื่อติดต่อดิบที่เชื่อมโยงกับแถวข้อมูลนี้ | รายชื่อติดต่อดิบจะมีแถวเหล่านี้เพียงแถวเดียว |
ContactsContract.CommonDataKinds.Photo |
รูปภาพหลักสำหรับรายชื่อติดต่อดิบที่เชื่อมโยงกับแถวข้อมูลนี้ | รายชื่อติดต่อดิบจะมีแถวเหล่านี้เพียงแถวเดียว |
ContactsContract.CommonDataKinds.Email |
อีเมลสำหรับผู้ติดต่อดิบที่เชื่อมโยงกับแถวข้อมูลนี้ | รายชื่อติดต่อดิบมีอีเมลได้หลายรายการ |
ContactsContract.CommonDataKinds.StructuredPostal |
ที่อยู่ไปรษณีย์ของผู้ติดต่อดิบที่เชื่อมโยงกับแถวข้อมูลนี้ | รายชื่อติดต่อดิบมีที่อยู่ไปรษณีย์ได้หลายรายการ |
ContactsContract.CommonDataKinds.GroupMembership |
ตัวระบุที่ลิงก์รายชื่อติดต่อดิบกับกลุ่มใดกลุ่มหนึ่งในผู้ให้บริการรายชื่อติดต่อ | กลุ่มเป็นฟีเจอร์ที่ไม่บังคับของประเภทบัญชีและชื่อบัญชี ซึ่งจะอธิบายอย่างละเอียดในส่วนกลุ่มรายชื่อติดต่อ |
รายชื่อติดต่อ
Contacts Provider จะรวมแถวข้อมูลติดต่อดิบในบัญชีทุกประเภทและชื่อบัญชี เพื่อสร้างรายชื่อติดต่อ ซึ่งช่วยให้แสดงและแก้ไขข้อมูลทั้งหมดที่ผู้ใช้รวบรวมไว้สำหรับบุคคลหนึ่งๆ ได้ง่ายขึ้น ผู้ให้บริการรายชื่อติดต่อจะจัดการการสร้างแถวรายชื่อติดต่อใหม่ และการรวบรวมรายชื่อติดต่อดิบกับแถวรายชื่อติดต่อที่มีอยู่ ทั้งแอปพลิเคชันและ ตัวปรับการซิงค์ไม่ได้รับอนุญาตให้เพิ่มรายชื่อติดต่อ และคอลัมน์บางคอลัมน์ในแถวรายชื่อติดต่อเป็นแบบอ่านอย่างเดียว
หมายเหตุ: หากพยายามเพิ่มรายชื่อติดต่อลงในผู้ให้บริการรายชื่อติดต่อด้วย
insert()
คุณจะได้รับข้อยกเว้น UnsupportedOperationException
หากคุณพยายามอัปเดตคอลัมน์
ที่แสดงเป็น "อ่านอย่างเดียว" ระบบจะไม่สนใจการอัปเดต
ผู้ให้บริการรายชื่อติดต่อจะสร้างรายชื่อติดต่อใหม่เพื่อตอบสนองต่อการเพิ่มรายชื่อติดต่อดิบใหม่ ซึ่งไม่ตรงกับรายชื่อติดต่อที่มีอยู่ ผู้ให้บริการจะดำเนินการนี้ด้วยหากข้อมูลของรายชื่อติดต่อเดิมมีการเปลี่ยนแปลงในลักษณะที่ข้อมูลไม่ตรงกับรายชื่อติดต่อที่เคยแนบไว้ หากแอปพลิเคชันหรือตัวปรับการซิงค์สร้างรายชื่อติดต่อดิบใหม่ที่ ตรงกันกับรายชื่อติดต่อที่มีอยู่ ระบบจะรวมรายชื่อติดต่อดิบใหม่เข้ากับรายชื่อติดต่อที่มีอยู่
ผู้ให้บริการรายชื่อติดต่อจะลิงก์แถวรายชื่อติดต่อกับแถวรายชื่อติดต่อดิบด้วยคอลัมน์ _ID
ของแถวรายชื่อติดต่อในตาราง Contacts
คอลัมน์ CONTACT_ID
ของตารางรายชื่อติดต่อดิบ
ContactsContract.RawContacts
มีค่า _ID
สำหรับ
แถวรายชื่อติดต่อที่เชื่อมโยงกับแถวรายชื่อติดต่อดิบแต่ละแถว
ContactsContract.Contacts
ตารางยังมีคอลัมน์
LOOKUP_KEY
ซึ่งเป็นลิงก์ "ถาวร" ไปยังแถวของรายชื่อติดต่อ เนื่องจากผู้ให้บริการรายชื่อติดต่อจะดูแลรายชื่อติดต่อโดยอัตโนมัติ จึงอาจเปลี่ยนค่า _ID
ของแถวรายชื่อติดต่อ
เพื่อตอบสนองต่อการรวมหรือการซิงค์ แม้จะเกิดกรณีนี้ขึ้น URI ของเนื้อหา
CONTENT_LOOKUP_URI
เมื่อรวมกับ
LOOKUP_KEY
ของรายชื่อติดต่อจะยังคง
ชี้ไปยังแถวของรายชื่อติดต่อ คุณจึงใช้
LOOKUP_KEY
เพื่อรักษาลิงก์ไปยังรายชื่อติดต่อ "รายการโปรด" และอื่นๆ ได้ คอลัมน์นี้มีรูปแบบของตัวเองซึ่ง
ไม่เกี่ยวข้องกับรูปแบบของคอลัมน์ _ID
รูปที่ 3 แสดงความสัมพันธ์ของตารางหลัก 3 ตาราง

รูปที่ 3 ความสัมพันธ์ของตารางรายชื่อติดต่อ รายชื่อติดต่อดิบ และรายละเอียด
ข้อควรระวัง: หากคุณเผยแพร่แอปไปยัง Google Play Store หรือหากแอปของคุณ อยู่ในอุปกรณ์ที่ใช้ Android 10 (API ระดับ 29) ขึ้นไป โปรดทราบว่า ฟิลด์ข้อมูลและวิธีการของรายชื่อติดต่อบางรายการจะเลิกใช้งานแล้ว
ภายใต้เงื่อนไขที่กล่าวถึง ระบบจะล้างค่าที่เขียนลงในช่องข้อมูลต่อไปนี้เป็นระยะๆ
-
ContactsContract.ContactOptionsColumns.LAST_TIME_CONTACTED
-
ContactsContract.ContactOptionsColumns.TIMES_CONTACTED
-
ContactsContract.DataUsageStatColumns.LAST_TIME_USED
-
ContactsContract.DataUsageStatColumns.TIMES_USED
API ที่ใช้ในการตั้งค่าฟิลด์ข้อมูลข้างต้นจะเลิกใช้งานด้วยเช่นกัน
นอกจากนี้ ฟิลด์ต่อไปนี้จะไม่แสดงรายชื่อติดต่อที่ติดต่อบ่อยอีกต่อไป โปรดทราบ ว่าฟิลด์บางรายการเหล่านี้จะมีผลต่อการจัดอันดับรายชื่อติดต่อก็ต่อเมื่อรายชื่อติดต่อ เป็นส่วนหนึ่งของประเภทข้อมูลที่เฉพาะเจาะจง เท่านั้น
-
ContactsContract.Contacts.CONTENT_FREQUENT_URI
-
ContactsContract.Contacts.CONTENT_STREQUENT_URI
-
ContactsContract.Contacts.CONTENT_STREQUENT_FILTER_URI
-
CONTENT_FILTER_URI
(มีผลเฉพาะ อีเมล โทรศัพท์ โทรได้ และ ติดต่อได้ ) -
ENTERPRISE_CONTENT_FILTER_URI
(มีผลเฉพาะ อีเมล โทรศัพท์ และ ข้อมูลที่โทรได้ )
หากแอปของคุณเข้าถึงหรืออัปเดตฟิลด์หรือ API เหล่านี้ ให้ใช้วิธีอื่น ตัวอย่างเช่น คุณสามารถตอบสนอง Use Case บางอย่างได้โดยใช้ ผู้ให้บริการเนื้อหาส่วนตัวหรือข้อมูลอื่นๆ ที่จัดเก็บไว้ในแอปหรือระบบแบ็กเอนด์ ของคุณ
หากต้องการยืนยันว่าฟังก์ชันการทำงานของแอปไม่ได้รับผลกระทบจากการเปลี่ยนแปลงนี้ คุณ สามารถล้างช่องข้อมูลเหล่านี้ด้วยตนเองได้ โดยให้เรียกใช้คำสั่ง ADB ต่อไปนี้ในอุปกรณ์ที่ใช้ Android 4.1 (API ระดับ 16) ขึ้นไป
adb shell content delete \ --uri content://com.android.contacts/contacts/delete_usage
ข้อมูลจากอะแดปเตอร์การซิงค์
ผู้ใช้จะป้อนข้อมูลรายชื่อติดต่อลงในอุปกรณ์โดยตรง แต่ข้อมูลจะไหลเข้าสู่ Contacts
Provider จากบริการบนเว็บผ่านตัวปรับการซิงค์ ซึ่งจะทำให้การโอนข้อมูลระหว่างอุปกรณ์กับบริการเป็นไปโดยอัตโนมัติ
Sync Adapters ทำงานในเบื้องหลัง
ภายใต้การควบคุมของระบบ และเรียกใช้ContentResolver
เมธอด
เพื่อจัดการข้อมูล
ใน Android บริการเว็บที่ Sync Adapter ทำงานด้วยจะระบุโดยประเภทบัญชี Sync Adapter แต่ละตัวจะทำงานกับบัญชีประเภทเดียว แต่รองรับชื่อบัญชีหลายชื่อสำหรับประเภทนั้นได้ ประเภทบัญชีและชื่อบัญชีอธิบายไว้สั้นๆ ในส่วน แหล่งที่มาของข้อมูลรายชื่อติดต่อดิบ คำจำกัดความต่อไปนี้จะให้รายละเอียดเพิ่มเติม และอธิบายว่าประเภทและชื่อบัญชีเกี่ยวข้องกับตัวดัดแปลงและบริการการซิงค์อย่างไร
- ประเภทบัญชี
-
ระบุบริการที่ผู้ใช้จัดเก็บข้อมูลไว้ โดยส่วนใหญ่แล้ว ผู้ใช้จะต้อง
ตรวจสอบสิทธิ์กับบริการ เช่น Google Contacts เป็นประเภทบัญชีที่ระบุด้วยรหัส
google.com
ค่านี้สอดคล้องกับประเภทบัญชีที่ใช้โดยAccountManager
- ชื่อบัญชี
- ระบุบัญชีหรือการเข้าสู่ระบบสำหรับประเภทบัญชีที่เฉพาะเจาะจง บัญชี Google Contacts เหมือนกับบัญชี Google ซึ่งมีอีเมลเป็นชื่อบัญชี บริการอื่นๆ อาจใช้ชื่อผู้ใช้แบบคำเดียวหรือรหัสตัวเลข
ประเภทบัญชีไม่จำเป็นต้องไม่ซ้ำกัน ผู้ใช้สามารถกำหนดค่าบัญชี Google Contacts หลายบัญชี และดาวน์โหลดข้อมูลไปยังผู้ให้บริการ Contacts ได้ ซึ่งอาจเกิดขึ้นหากผู้ใช้มีรายชื่อติดต่อส่วนตัวชุดหนึ่ง สำหรับชื่อบัญชีส่วนตัว และอีกชุดหนึ่งสำหรับงาน ชื่อบัญชีมักจะไม่ซ้ำกัน โดยทั้ง 2 อย่างนี้จะระบุการไหลของข้อมูลที่เฉพาะเจาะจงระหว่างผู้ให้บริการรายชื่อติดต่อกับ บริการภายนอก
หากต้องการโอนข้อมูลของบริการไปยังผู้ให้บริการรายชื่อติดต่อ คุณต้องเขียน Sync Adapter ของคุณเอง ซึ่งอธิบายไว้อย่างละเอียดในส่วนอะแดปเตอร์การซิงค์ของผู้ให้บริการรายชื่อติดต่อ
รูปที่ 4 แสดงให้เห็นว่าผู้ให้บริการรายชื่อติดต่ออยู่ในขั้นตอนการไหลของข้อมูล เกี่ยวกับผู้คนอย่างไร ในช่องที่ทำเครื่องหมายว่า "อะแดปเตอร์การซิงค์" อะแดปเตอร์แต่ละตัวจะมีป้ายกำกับตามประเภทบัญชี

รูปที่ 4 โฟลว์ข้อมูลของ Contacts Provider
สิทธิ์ที่จำเป็น
แอปพลิเคชันที่ต้องการเข้าถึงผู้ให้บริการรายชื่อติดต่อต้องขอสิทธิ์ต่อไปนี้
- สิทธิ์การอ่านตารางอย่างน้อย 1 รายการ
-
READ_CONTACTS
ที่ระบุในAndroidManifest.xml
ด้วยองค์ประกอบ<uses-permission>
เป็น<uses-permission android:name="android.permission.READ_CONTACTS">
- สิทธิ์การเขียนสำหรับตารางอย่างน้อย 1 รายการ
-
WRITE_CONTACTS
ที่ระบุในAndroidManifest.xml
ด้วยองค์ประกอบ<uses-permission>
เป็น<uses-permission android:name="android.permission.WRITE_CONTACTS">
สิทธิ์เหล่านี้ไม่มีผลกับข้อมูลโปรไฟล์ผู้ใช้ โปรไฟล์ผู้ใช้และสิทธิ์ที่จำเป็นจะอธิบายไว้ในส่วนถัดไป โปรไฟล์ผู้ใช้
โปรดทราบว่าข้อมูลรายชื่อติดต่อของผู้ใช้เป็นข้อมูลส่วนบุคคลและข้อมูลที่ละเอียดอ่อน ผู้ใช้กังวลเกี่ยวกับ ความเป็นส่วนตัว จึงไม่ต้องการให้แอปพลิเคชันเก็บรวบรวมข้อมูลเกี่ยวกับตนเองหรือรายชื่อติดต่อ หากผู้ใช้ไม่ทราบเหตุผลที่คุณต้องมีสิทธิ์เข้าถึงข้อมูลรายชื่อติดต่อของผู้ใช้ ผู้ใช้อาจให้คะแนนแอปพลิเคชันของคุณต่ำหรือปฏิเสธที่จะติดตั้งแอป
โปรไฟล์ผู้ใช้
ContactsContract.Contacts
ตารางมีแถวเดียวซึ่งมี
ข้อมูลโปรไฟล์สําหรับผู้ใช้อุปกรณ์ ข้อมูลนี้อธิบายถึง user
ของอุปกรณ์
แทนที่จะเป็นรายชื่อติดต่อของผู้ใช้ แถวรายชื่อติดต่อของโปรไฟล์จะลิงก์กับแถวรายชื่อติดต่อดิบ
สำหรับแต่ละระบบที่ใช้โปรไฟล์
แถวรายชื่อติดต่อดิบของแต่ละโปรไฟล์มีแถวข้อมูลได้หลายแถว ค่าคงที่สำหรับการเข้าถึงโปรไฟล์ผู้ใช้
มีอยู่ในคลาส ContactsContract.Profile
การเข้าถึงโปรไฟล์ผู้ใช้ต้องมีสิทธิ์พิเศษ นอกเหนือจากสิทธิ์ READ_CONTACTS
และ WRITE_CONTACTS
ที่จำเป็นสำหรับการอ่านและเขียนแล้ว การเข้าถึงโปรไฟล์ผู้ใช้ยังต้องมีสิทธิ์ android.Manifest.permission#READ_PROFILE และ android.Manifest.permission#WRITE_PROFILE สำหรับการเข้าถึงแบบอ่านและเขียนตามลำดับ
โปรดทราบว่าคุณควรพิจารณาว่าโปรไฟล์ของผู้ใช้เป็นข้อมูลที่ละเอียดอ่อน สิทธิ์ android.Manifest.permission#READ_PROFILE ช่วยให้คุณเข้าถึง ข้อมูลที่ระบุตัวบุคคลได้ของผู้ใช้อุปกรณ์ โปรดแจ้งให้ผู้ใช้ทราบเหตุผลที่คุณต้องการสิทธิ์เข้าถึงโปรไฟล์ผู้ใช้ในคำอธิบายของแอปพลิเคชัน
หากต้องการดึงแถวรายชื่อติดต่อที่มีโปรไฟล์ของผู้ใช้ ให้
เรียกใช้ ContentResolver.query()
ตั้งค่า URI ของเนื้อหาเป็น
CONTENT_URI
และไม่ต้องระบุเกณฑ์การเลือก
ใดๆ นอกจากนี้ คุณยังใช้ URI เนื้อหานี้เป็น URI ฐานสําหรับการดึงข้อมูล
รายชื่อติดต่อหรือข้อมูลดิบสําหรับโปรไฟล์ได้ด้วย เช่น ข้อมูลโค้ดนี้จะดึงข้อมูลสำหรับโปรไฟล์
Kotlin
// Sets the columns to retrieve for the user profile projection = arrayOf( ContactsContract.Profile._ID, ContactsContract.Profile.DISPLAY_NAME_PRIMARY, ContactsContract.Profile.LOOKUP_KEY, ContactsContract.Profile.PHOTO_THUMBNAIL_URI ) // Retrieves the profile from the Contacts Provider profileCursor = contentResolver.query( ContactsContract.Profile.CONTENT_URI, projection, null, null, null )
Java
// Sets the columns to retrieve for the user profile projection = new String[] { Profile._ID, Profile.DISPLAY_NAME_PRIMARY, Profile.LOOKUP_KEY, Profile.PHOTO_THUMBNAIL_URI }; // Retrieves the profile from the Contacts Provider profileCursor = getContentResolver().query( Profile.CONTENT_URI, projection , null, null, null);
หมายเหตุ: หากดึงข้อมูลแถวของรายชื่อติดต่อหลายแถวและต้องการพิจารณาว่าแถวใดแถวหนึ่งเป็นโปรไฟล์ผู้ใช้ ให้ทดสอบคอลัมน์ IS_USER_PROFILE
ของแถวนั้น คอลัมน์นี้
จะตั้งค่าเป็น "1" หากรายชื่อติดต่อเป็นโปรไฟล์ผู้ใช้
ข้อมูลเมตาของผู้ให้บริการรายชื่อติดต่อ
Contacts Provider จัดการข้อมูลที่ติดตามสถานะของข้อมูลรายชื่อติดต่อใน
ที่เก็บ ระบบจะจัดเก็บข้อมูลเมตานี้เกี่ยวกับที่เก็บไว้ในที่ต่างๆ ซึ่งรวมถึงแถวของตาราง
Raw Contacts, Data และ Contacts, ตาราง
ContactsContract.Settings
และตาราง
ContactsContract.SyncState
ตารางต่อไปนี้แสดงผลของข้อมูลเมตาแต่ละรายการ
ตารางที่ 3 ข้อมูลเมตาใน Contacts Provider
ตาราง | คอลัมน์ | ค่า | ความหมาย |
---|---|---|---|
ContactsContract.RawContacts |
DIRTY |
"0" - ไม่มีการเปลี่ยนแปลงนับตั้งแต่ซิงค์ครั้งล่าสุด |
ทำเครื่องหมายรายชื่อติดต่อดิบที่มีการเปลี่ยนแปลงในอุปกรณ์และต้องซิงค์กลับไปยังเซิร์ฟเวอร์ ผู้ให้บริการรายชื่อติดต่อจะตั้งค่าโดยอัตโนมัติเมื่อแอปพลิเคชัน Android
อัปเดตแถว
Sync Adapter ที่แก้ไขตารางข้อมูลหรือรายชื่อติดต่อดิบควรต่อท้ายสตริง |
"1" - มีการเปลี่ยนแปลงตั้งแต่การซิงค์ครั้งล่าสุด ต้องซิงค์กลับไปยังเซิร์ฟเวอร์ | |||
ContactsContract.RawContacts |
VERSION |
หมายเลขเวอร์ชันของแถวนี้ | ผู้ให้บริการรายชื่อติดต่อจะเพิ่มค่านี้โดยอัตโนมัติเมื่อใดก็ตามที่แถวหรือ ข้อมูลที่เกี่ยวข้องมีการเปลี่ยนแปลง |
ContactsContract.Data |
DATA_VERSION |
หมายเลขเวอร์ชันของแถวนี้ | ผู้ให้บริการรายชื่อติดต่อจะเพิ่มค่านี้โดยอัตโนมัติทุกครั้งที่มีการเปลี่ยนแปลงแถวข้อมูล |
ContactsContract.RawContacts |
SOURCE_ID |
ค่าสตริงที่ระบุรายชื่อติดต่อดิบนี้ในบัญชีที่สร้างขึ้นอย่างไม่ซ้ำกัน |
เมื่อตัวปรับการซิงค์สร้างรายชื่อติดต่อดิบใหม่ คอลัมน์นี้ควรตั้งค่าเป็นรหัสที่ไม่ซ้ำกันของเซิร์ฟเวอร์สำหรับรายชื่อติดต่อดิบ เมื่อแอปพลิเคชัน Android สร้าง
รายชื่อติดต่อดิบใหม่ แอปพลิเคชันควรปล่อยให้คอลัมน์นี้ว่างไว้ ซึ่งจะส่งสัญญาณไปยังอะแดปเตอร์การซิงค์
ว่าควรสร้างรายชื่อติดต่อดิบใหม่ในเซิร์ฟเวอร์ และรับค่าสำหรับ SOURCE_ID
โดยเฉพาะอย่างยิ่ง รหัสแหล่งที่มาต้องไม่ซ้ำกันสำหรับบัญชีแต่ละประเภท และควรคงที่ตลอดการซิงค์
|
ContactsContract.Groups |
GROUP_VISIBLE |
"0" - รายชื่อติดต่อในกลุ่มนี้ไม่ควรปรากฏใน UI ของแอปพลิเคชัน Android | คอลัมน์นี้ใช้เพื่อความเข้ากันได้กับเซิร์ฟเวอร์ที่อนุญาตให้ผู้ใช้ซ่อนรายชื่อติดต่อใน บางกลุ่ม |
"1" - อนุญาตให้รายชื่อติดต่อในกลุ่มนี้ปรากฏใน UI ของแอปพลิเคชัน | |||
ContactsContract.Settings |
UNGROUPED_VISIBLE |
"0" - สำหรับบัญชีและประเภทบัญชีนี้ รายชื่อติดต่อที่ไม่ได้อยู่ในกลุ่มจะ ไม่ปรากฏใน UI ของแอปพลิเคชัน Android |
โดยค่าเริ่มต้น รายชื่อติดต่อจะมองไม่เห็นหากไม่มีรายชื่อติดต่อดิบอยู่ในกลุ่ม
(การเป็นสมาชิกกลุ่มสำหรับรายชื่อติดต่อดิบจะระบุด้วยแถวอย่างน้อย 1 แถว
ContactsContract.CommonDataKinds.GroupMembership
ในตาราง ContactsContract.Data )
การตั้งค่าสถานะนี้ในContactsContract.Settings แถวตาราง
สำหรับประเภทบัญชีและบัญชีจะทำให้รายชื่อติดต่อที่ไม่มีกลุ่มแสดงได้
การใช้แฟล็กนี้อย่างหนึ่งคือการแสดงรายชื่อติดต่อจากเซิร์ฟเวอร์ที่ไม่ได้ใช้กลุ่ม
|
"1" - สำหรับบัญชีและประเภทบัญชีนี้ รายชื่อติดต่อที่ไม่ได้อยู่ในกลุ่มจะ มองเห็นได้ใน UI ของแอปพลิเคชัน | |||
ContactsContract.SyncState |
(ทั้งหมด) | ใช้ตารางนี้เพื่อจัดเก็บข้อมูลเมตาสำหรับตัวปรับการซิงค์ | ตารางนี้ช่วยให้คุณจัดเก็บสถานะการซิงค์และข้อมูลอื่นๆ ที่เกี่ยวข้องกับการซิงค์อย่างถาวรในอุปกรณ์ได้ |
การเข้าถึง Contacts Provider
ส่วนนี้จะอธิบายหลักเกณฑ์ในการเข้าถึงข้อมูลจากผู้ให้บริการรายชื่อติดต่อ โดยเน้นที่ หัวข้อต่อไปนี้
- คำค้นหาเอนทิตี
- การแก้ไขเป็นกลุ่ม
- การดึงข้อมูลและการแก้ไขด้วย Intent
- ความสมบูรณ์ของข้อมูล
การแก้ไขจาก Sync Adapter จะอธิบายรายละเอียดเพิ่มเติมในส่วน Sync Adapter ของ Contacts Provider
การค้นหาเอนทิตี
เนื่องจากตารางของ Contacts Provider จัดระเบียบเป็นลำดับชั้น จึงมักมีประโยชน์ที่จะ
เรียกข้อมูลแถวและแถว "ย่อย" ทั้งหมดที่ลิงก์กับแถวนั้น เช่น หากต้องการแสดง
ข้อมูลทั้งหมดของบุคคล คุณอาจต้องดึงข้อมูลContactsContract.RawContacts
แถวทั้งหมดสำหรับContactsContract.Contacts
แถวเดียว หรือContactsContract.CommonDataKinds.Email
แถวทั้งหมดสำหรับContactsContract.RawContacts
แถวเดียว เพื่ออำนวยความสะดวกในเรื่องนี้ ผู้ให้บริการรายชื่อติดต่อ
จึงมีโครงสร้างเอนทิตี ซึ่งทำหน้าที่เหมือนการรวมฐานข้อมูลระหว่าง
ตาราง
เอนทิตีก็เหมือนตารางที่ประกอบด้วยคอลัมน์ที่เลือกจากตารางหลักและตารางย่อย
เมื่อค้นหาเอนทิตี คุณจะระบุการฉายภาพและเกณฑ์การค้นหาตามคอลัมน์
ที่ใช้ได้จากเอนทิตี ผลลัพธ์คือ Cursor
ที่มี
แถว 1 แถวสำหรับแถวของตารางย่อยแต่ละแถวที่ดึงข้อมูลมา ตัวอย่างเช่น หากคุณค้นหา
ContactsContract.Contacts.Entity
สำหรับชื่อรายชื่อติดต่อ
และแถว ContactsContract.CommonDataKinds.Email
ทั้งหมดสำหรับ
รายชื่อติดต่อดิบทั้งหมดสำหรับชื่อนั้น คุณจะได้รับ Cursor
ที่มีแถว 1 แถว
สำหรับแถว ContactsContract.CommonDataKinds.Email
แต่ละแถว
เอนทิตีช่วยให้การค้นหาง่ายขึ้น การใช้เอนทิตีช่วยให้คุณดึงข้อมูลรายชื่อติดต่อทั้งหมดสำหรับ รายชื่อติดต่อหรือรายชื่อติดต่อดิบได้ในครั้งเดียว แทนที่จะต้องค้นหาตารางหลักก่อนเพื่อรับรหัส แล้วจึงต้องค้นหาตารางย่อยด้วยรหัสนั้น นอกจากนี้ ผู้ให้บริการรายชื่อติดต่อยังประมวลผล การค้นหาเทียบกับเอนทิตีในธุรกรรมเดียว ซึ่งช่วยให้มั่นใจว่าข้อมูลที่เรียกคืนมาจะ สอดคล้องกันภายใน
หมายเหตุ: โดยปกติแล้วเอนทิตีจะไม่มีคอลัมน์ทั้งหมดของตารางหลักและตารางย่อย หากพยายามใช้ชื่อคอลัมน์ที่ไม่ได้อยู่ในรายการค่าคงที่ของชื่อคอลัมน์
สำหรับเอนทิตี คุณจะได้รับ Exception
ข้อมูลโค้ดต่อไปนี้แสดงวิธีดึงข้อมูลแถวรายชื่อติดต่อดิบทั้งหมดสำหรับรายชื่อติดต่อ ข้อมูลโค้ด
เป็นส่วนหนึ่งของแอปพลิเคชันขนาดใหญ่ที่มี 2 กิจกรรม ได้แก่ "main" และ "detail" กิจกรรมหลัก
แสดงรายการแถวของรายชื่อติดต่อ เมื่อผู้ใช้เลือกแถวใดแถวหนึ่ง กิจกรรมจะส่งรหัสไปยังกิจกรรมรายละเอียด
กิจกรรมแบบละเอียดใช้ ContactsContract.Contacts.Entity
เพื่อแสดงแถวข้อมูลทั้งหมดจากรายชื่อติดต่อดิบทั้งหมดที่เชื่อมโยงกับรายชื่อติดต่อที่เลือก
ข้อมูลโค้ดนี้มาจากกิจกรรม "รายละเอียด"
Kotlin
... /* * 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). */ contactUri = Uri.withAppendedPath( contactUri, ContactsContract.Contacts.Entity.CONTENT_DIRECTORY ) // Initializes the loader identified by LOADER_ID. loaderManager.initLoader( LOADER_ID, // The identifier of the loader to initialize null, // Arguments for the loader (in this case, none) this // The context of the activity ) // Creates a new cursor adapter to attach to the list view cursorAdapter = SimpleCursorAdapter( this, // the context of the activity R.layout.detail_list_item, // the view item containing the detail widgets mCursor, // the backing cursor fromColumns, // the columns in the cursor that provide the data toViews, // the views in the view item that display the data 0) // flags // Sets the ListView's backing adapter. rawContactList.adapter = cursorAdapter ... override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> { /* * 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. */ val projection: Array<String> = arrayOf( 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. */ val 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 CursorLoader( applicationContext, // The activity's context contactUri, // The entity content URI for a single contact projection, // The columns to retrieve null, // Retrieve all the raw contacts and their data rows. null, // sortOrder // Sort by the raw contact ID. ) }
Java
... /* * 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). */ contactUri = Uri.withAppendedPath( contactUri, ContactsContract.Contacts.Entity.CONTENT_DIRECTORY); // Initializes the loader identified by LOADER_ID. getLoaderManager().initLoader( LOADER_ID, // The identifier of the loader to initialize null, // Arguments for the loader (in this case, none) this); // The context of the activity // Creates a new cursor adapter to attach to the list view cursorAdapter = new SimpleCursorAdapter( this, // the context of the activity R.layout.detail_list_item, // the view item containing the detail widgets mCursor, // the backing cursor fromColumns, // the columns in the cursor that provide the data toViews, // the views in the view item that display the data 0); // flags // Sets the ListView's backing adapter. rawContactList.setAdapter(cursorAdapter); ... @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 context contactUri, // The entity content URI for a single contact projection, // The columns to retrieve null, // Retrieve all the raw contacts and their data rows. null, // sortOrder); // Sort by the raw contact ID. }
เมื่อโหลดเสร็จแล้ว LoaderManager
จะเรียกใช้การเรียกกลับไปยัง
onLoadFinished()
อาร์กิวเมนต์ขาเข้าอย่างหนึ่งของเมธอดนี้คือ
Cursor
ที่มีผลลัพธ์ของคำค้นหา ในแอปของคุณเอง คุณสามารถรับ
ข้อมูลจาก Cursor
นี้เพื่อแสดงหรือทำงานกับข้อมูลเพิ่มเติมได้
การแก้ไขแบบเป็นกลุ่ม
คุณควรแทรก อัปเดต และลบข้อมูลในผู้ให้บริการรายชื่อติดต่อใน "โหมดกลุ่ม" ทุกครั้งที่ทำได้ โดยการสร้างออบเจ็กต์ ArrayList
ของออบเจ็กต์ ContentProviderOperation
และเรียกใช้ applyBatch()
เนื่องจาก
ผู้ให้บริการรายชื่อติดต่อจะดำเนินการทั้งหมดใน
applyBatch()
ในธุรกรรมเดียว
การแก้ไขของคุณจึงจะไม่ทำให้ที่เก็บรายชื่อติดต่ออยู่ในสถานะที่ไม่สอดคล้องกัน
การแก้ไขแบบเป็นกลุ่มยังช่วยให้แทรกรายชื่อติดต่อดิบและข้อมูลรายละเอียดได้พร้อมกันด้วย
หมายเหตุ: หากต้องการแก้ไขรายชื่อติดต่อดิบรายการเดียว ให้ลองส่ง Intent ไปยัง แอปพลิเคชันรายชื่อติดต่อของอุปกรณ์แทนที่จะจัดการการแก้ไขในแอป คุณสามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับวิธีนี้ได้ในส่วน การดึงข้อมูลและการแก้ไขด้วย Intent
จุดหยุดชั่วคราว
การแก้ไขแบบเป็นชุดที่มีการดำเนินการจำนวนมากอาจบล็อกกระบวนการอื่นๆ
ซึ่งส่งผลให้ผู้ใช้ได้รับประสบการณ์การใช้งานโดยรวมที่ไม่ดี หากต้องการจัดระเบียบการแก้ไขทั้งหมดที่คุณต้องการ
ดำเนินการในรายการที่แยกกันให้น้อยที่สุด และในขณะเดียวกันก็ป้องกันไม่ให้
การแก้ไขเหล่านั้นบล็อกระบบ คุณควรตั้งค่าจุดผลตอบแทนสำหรับการดำเนินการอย่างน้อย 1 รายการ
จุดที่ให้ผลตอบแทนคือออบเจ็กต์ ContentProviderOperation
ที่มีค่า
isYieldAllowed()
ตั้งค่าเป็น
true
เมื่อผู้ให้บริการรายชื่อติดต่อพบจุดที่ต้องหยุดชั่วคราว ผู้ให้บริการจะหยุดการทำงานชั่วคราวเพื่อ
ให้กระบวนการอื่นๆ ทำงานและปิดธุรกรรมปัจจุบัน เมื่อผู้ให้บริการเริ่มทำงานอีกครั้ง ผู้ให้บริการจะ
ดำเนินการต่อด้วยการดำเนินการถัดไปใน ArrayList
และเริ่มธุรกรรมใหม่
คะแนนผลตอบแทนจะทำให้เกิดธุรกรรมมากกว่า 1 รายการต่อการเรียกใช้
applyBatch()
ด้วยเหตุนี้ คุณจึงควรตั้งค่าจุดหยุดชั่วคราวสำหรับการดำเนินการสุดท้ายของชุดแถวที่เกี่ยวข้อง
เช่น คุณควรตั้งค่าจุดผลตอบแทนสำหรับการดำเนินการสุดท้ายในชุดที่เพิ่ม
แถวรายชื่อติดต่อดิบและแถวข้อมูลที่เชื่อมโยง หรือการดำเนินการสุดท้ายสำหรับชุดแถวที่เกี่ยวข้อง
กับรายชื่อติดต่อเดียว
นอกจากนี้ จุดผลตอบแทนยังเป็นหน่วยของการดำเนินการแบบอะตอมมิกด้วย การเข้าถึงทั้งหมดระหว่างจุดให้ผลตอบแทน 2 จุดจะ สำเร็จหรือล้มเหลวเป็นหน่วยเดียว หากไม่ได้ตั้งค่าจุดให้ผล การดำเนินการย่อยที่เล็กที่สุด คือชุดการดำเนินการทั้งหมด หากใช้จุดผลตอบแทน คุณจะป้องกันไม่ให้ การดำเนินการทำให้ประสิทธิภาพของระบบลดลง ในขณะเดียวกันก็มั่นใจได้ว่าการดำเนินการย่อยของ การดำเนินการจะเป็นแบบอะตอม
การอ้างอิงย้อนกลับของการแก้ไข
เมื่อแทรกแถวรายชื่อติดต่อดิบใหม่และแถวข้อมูลที่เชื่อมโยงเป็นชุดของออบเจ็กต์ ContentProviderOperation
คุณต้องลิงก์แถวข้อมูลกับแถวรายชื่อติดต่อดิบโดยแทรกค่า _ID
ของรายชื่อติดต่อดิบเป็นค่า RAW_CONTACT_ID
อย่างไรก็ตาม ค่านี้จะไม่พร้อมใช้งานเมื่อคุณสร้าง ContentProviderOperation
สำหรับแถวข้อมูล เนื่องจากคุณยังไม่ได้ใช้ ContentProviderOperation
สำหรับแถวรายชื่อติดต่อดิบ หากต้องการหลีกเลี่ยงปัญหานี้
คลาส ContentProviderOperation.Builder
มีเมธอด
withValueBackReference()
วิธีนี้ช่วยให้คุณแทรกหรือแก้ไขคอลัมน์ที่มี
ผลลัพธ์ของการดำเนินการก่อนหน้าได้
เมธอด withValueBackReference()
มีอาร์กิวเมนต์ 2 รายการ ดังนี้
-
key
- คีย์ของคู่คีย์-ค่า ค่าของอาร์กิวเมนต์นี้ควรเป็นชื่อของคอลัมน์ ในตารางที่คุณกำลังแก้ไข
-
previousResult
-
ดัชนีแบบ 0 ของค่าในอาร์เรย์ของออบเจ็กต์
ContentProviderResult
จากapplyBatch()
เมื่อ ใช้การดำเนินการแบบกลุ่ม ระบบจะจัดเก็บผลลัพธ์ของการดำเนินการแต่ละรายการไว้ใน อาร์เรย์ผลลัพธ์ชั่วคราว ค่าpreviousResult
คือดัชนี ของผลลัพธ์อย่างใดอย่างหนึ่งต่อไปนี้ ซึ่งจะเรียกและจัดเก็บพร้อมกับค่าkey
ซึ่งจะช่วยให้คุณแทรกระเบียนรายชื่อติดต่อดิบใหม่และรับค่า_ID
กลับมา จากนั้นสร้าง "การอ้างอิงย้อนกลับ" ไปยังค่าเมื่อเพิ่มแถวContactsContract.Data
ระบบจะสร้างอาร์เรย์ผลลัพธ์ทั้งหมดเมื่อคุณเรียกใช้
applyBatch()
, เป็นครั้งแรก โดยมีขนาดเท่ากับขนาดของArrayList
ของออบเจ็กต์ContentProviderOperation
ที่คุณระบุ อย่างไรก็ตาม ระบบจะตั้งค่าองค์ประกอบทั้งหมดในอาร์เรย์ผลลัพธ์เป็นnull
และหากคุณพยายาม อ้างอิงย้อนกลับไปยังผลลัพธ์สำหรับการดำเนินการที่ยังไม่ได้ใช้withValueBackReference()
ระบบจะแสดงException
ข้อมูลโค้ดต่อไปนี้แสดงวิธีแทรกรายชื่อติดต่อดิบและข้อมูลใหม่เป็นกลุ่ม โดยมีโค้ดที่กำหนดจุดที่ได้ผลตอบแทนและใช้การอ้างอิงย้อนกลับ
ข้อมูลโค้ดแรกจะดึงข้อมูลรายชื่อติดต่อจาก UI ในขั้นตอนนี้ ผู้ใช้ได้เลือกบัญชีที่จะเพิ่มรายชื่อติดต่อดิบใหม่แล้ว
Kotlin
// Creates a contact entry from the current UI values, using the currently-selected account. private fun createContactEntry() { /* * Gets values from the UI */ val name = contactNameEditText.text.toString() val phone = contactPhoneEditText.text.toString() val email = contactEmailEditText.text.toString() val phoneType: String = contactPhoneTypes[mContactPhoneTypeSpinner.selectedItemPosition] val emailType: String = contactEmailTypes[mContactEmailTypeSpinner.selectedItemPosition]
Java
// Creates a contact entry from the current UI values, using the currently-selected account. protected void createContactEntry() { /* * Gets values from the UI */ String name = contactNameEditText.getText().toString(); String phone = contactPhoneEditText.getText().toString(); String email = contactEmailEditText.getText().toString(); int phoneType = contactPhoneTypes.get( contactPhoneTypeSpinner.getSelectedItemPosition()); int emailType = contactEmailTypes.get( contactEmailTypeSpinner.getSelectedItemPosition());
ข้อมูลโค้ดถัดไปจะสร้างการดำเนินการเพื่อแทรกแถวรายชื่อติดต่อดิบลงในตาราง
ContactsContract.RawContacts
Kotlin
/* * 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. val ops = arrayListOf<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. */ var op: ContentProviderOperation.Builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.name) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.type) // Builds the operation and adds it to the array of operations ops.add(op.build())
Java
/* * 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, selectedAccount.getType()) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.getName()); // Builds the operation and adds it to the array of operations ops.add(op.build());
จากนั้นโค้ดจะสร้างแถวข้อมูลสำหรับแถวชื่อที่แสดง โทรศัพท์ และอีเมล
ออบเจ็กต์เครื่องมือสร้างการดำเนินการแต่ละรายการใช้
withValueBackReference()
เพื่อรับ
RAW_CONTACT_ID
จุดอ้างอิง
กลับไปยังออบเจ็กต์ ContentProviderResult
จากการดำเนินการแรก
ซึ่งจะเพิ่มแถวรายชื่อติดต่อดิบและแสดงผลค่า _ID
ใหม่ ด้วยเหตุนี้ ระบบจึงลิงก์แถวข้อมูลแต่ละแถวโดยอัตโนมัติด้วย
RAW_CONTACT_ID
ไปยังแถว ContactsContract.RawContacts
ใหม่ที่แถวนั้นเป็นของ
ออบเจ็กต์ ContentProviderOperation.Builder
ที่เพิ่มแถวอีเมลจะ
มีการแจ้งว่า withYieldAllowed()
ซึ่งจะตั้งค่าจุดที่ให้ผลตอบแทน
Kotlin
// 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 operations ops.add(op.build()) // Inserts the specified phone number and type as a Phone data row op = 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 operations ops.add(op.build()) // Inserts the specified email and type as a Phone data row op = 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 operations ops.add(op.build())
Java
// 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 operations ops.add(op.build()); // Inserts the specified phone number and type as a Phone data row op = 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 operations ops.add(op.build()); // Inserts the specified email and type as a Phone data row op = 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 operations ops.add(op.build());
ข้อมูลโค้ดสุดท้ายแสดงการเรียกใช้
applyBatch()
ที่
แทรกรายชื่อติดต่อและแถวข้อมูลใหม่
Kotlin
// Ask the Contacts Provider to create a new contact Log.d(TAG, "Selected account: ${mSelectedAccount.name} (${mSelectedAccount.type})") Log.d(TAG, "Creating contact: $name") /* * Applies the array of ContentProviderOperation objects in batch. The results are * discarded. */ try { contentResolver.applyBatch(ContactsContract.AUTHORITY, ops) } catch (e: Exception) { // Display a warning val txt: String = getString(R.string.contactCreationFailure) Toast.makeText(applicationContext, txt, Toast.LENGTH_SHORT).show() // Log exception Log.e(TAG, "Exception encountered while inserting contact: $e") } }
Java
// Ask the Contacts Provider to create a new contact Log.d(TAG,"Selected account: " + selectedAccount.getName() + " (" + selectedAccount.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 warning Context ctx = getApplicationContext(); CharSequence txt = getString(R.string.contactCreationFailure); int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(ctx, txt, duration); toast.show(); // Log exception Log.e(TAG, "Exception encountered while inserting contact: " + e); } }
การดำเนินการแบบกลุ่มยังช่วยให้คุณใช้การควบคุมการทำงานพร้อมกันแบบมองโลกในแง่ดีได้ด้วย ซึ่งเป็นวิธีการใช้ธุรกรรมการแก้ไขโดยไม่ต้องล็อกที่เก็บข้อมูลพื้นฐาน หากต้องการใช้วิธีนี้ ให้ใช้ธุรกรรม แล้วตรวจสอบการแก้ไขอื่นๆ ที่อาจเกิดขึ้นพร้อมกัน หากพบว่ามีการแก้ไขที่ไม่สอดคล้องกันเกิดขึ้น คุณ สามารถย้อนกลับธุรกรรมและลองอีกครั้ง
การควบคุมการทำงานพร้อมกันแบบมองโลกในแง่ดีมีประโยชน์สำหรับอุปกรณ์เคลื่อนที่ ซึ่งมีผู้ใช้เพียงคนเดียวในแต่ละครั้ง และการเข้าถึงที่เก็บข้อมูลพร้อมกันนั้นเกิดขึ้นได้ยาก เนื่องจากไม่ได้ใช้การล็อก จึงไม่ต้องเสียเวลาในการตั้งค่าการล็อกหรือรอให้ธุรกรรมอื่นๆ ปลดล็อก
หากต้องการใช้การควบคุมการทำงานพร้อมกันแบบมองโลกในแง่ดีขณะอัปเดตแถวเดียว
ContactsContract.RawContacts
ให้ทำตามขั้นตอนต่อไปนี้
-
เรียกข้อมูลคอลัมน์
VERSION
ของรายชื่อติดต่อดิบพร้อมกับข้อมูลอื่นๆ ที่คุณเรียก -
สร้างออบเจ็กต์
ContentProviderOperation.Builder
ที่เหมาะสำหรับ การบังคับใช้ข้อจำกัดโดยใช้วิธีการnewAssertQuery(Uri)
สำหรับ URI ของเนื้อหา ให้ใช้RawContacts.CONTENT_URI
โดยต่อท้ายด้วย_ID
ของรายชื่อติดต่อดิบ -
สำหรับออบเจ็กต์
ContentProviderOperation.Builder
ให้เรียกใช้withValue()
เพื่อเปรียบเทียบคอลัมน์VERSION
กับหมายเลขเวอร์ชันที่คุณเพิ่งดึงข้อมูลมา -
สำหรับ
ContentProviderOperation.Builder
เดียวกัน ให้เรียกใช้withExpectedCount()
เพื่อให้แน่ใจว่าการยืนยันนี้จะทดสอบเพียงแถวเดียว -
เรียกใช้
build()
เพื่อสร้างออบเจ็กต์ContentProviderOperation
จากนั้นเพิ่มออบเจ็กต์นี้เป็นออบเจ็กต์แรกในArrayList
ที่คุณส่งไปยังapplyBatch()
- ใช้ธุรกรรมแบบกลุ่ม
หากมีการอัปเดตแถวของข้อมูลติดต่อดิบโดยการดำเนินการอื่นระหว่างเวลาที่คุณอ่านแถวกับ
เวลาที่คุณพยายามแก้ไข "ยืนยัน" ContentProviderOperation
จะล้มเหลว และระบบจะยกเลิกการดำเนินการทั้งหมดในกลุ่ม จากนั้นคุณสามารถเลือกที่จะลองส่ง
กลุ่มอีกครั้งหรือดำเนินการอื่นๆ
ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้าง "assert"
ContentProviderOperation
หลังจากค้นหารายชื่อติดต่อดิบรายการเดียวโดยใช้
CursorLoader
Kotlin
/* * The application uses CursorLoader to query the raw contacts table. The system calls this method * when the load is finished. */ override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor) { // Gets the raw contact's _ID and VERSION values rawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)) mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION)) } ... // Sets up a Uri for the assert operation val rawContactUri: Uri = ContentUris.withAppendedId( ContactsContract.RawContacts.CONTENT_URI, rawContactID ) // Creates a builder for the assert operation val assertOp: ContentProviderOperation.Builder = ContentProviderOperation.newAssertQuery(rawContactUri).apply { // Adds the assertions to the assert operation: checks the version withValue(SyncColumns.VERSION, mVersion) // and count of rows tested withExpectedCount(1) } // Creates an ArrayList to hold the ContentProviderOperation objects val ops = arrayListOf<ContentProviderOperation>() 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 { val results: Array<ContentProviderResult> = contentResolver.applyBatch(AUTHORITY, ops) } catch (e: OperationApplicationException) { // Actions you want to take if the assert operation fails go here }
Java
/* * 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 values rawContactID = 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, rawContactID); // Creates a builder for the assert operation ContentProviderOperation.Builder assertOp = ContentProviderOperation.newAssertQuery(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<ContentProviderOperation>; 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 }
การดึงข้อมูลและการแก้ไขด้วย Intent
การส่ง Intent ไปยังแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์จะช่วยให้คุณเข้าถึง Contacts Provider โดยอ้อมได้ Intent จะเริ่ม UI ของแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ ซึ่งผู้ใช้สามารถ ทำงานที่เกี่ยวข้องกับรายชื่อติดต่อได้ เมื่อมีสิทธิ์เข้าถึงประเภทนี้ ผู้ใช้จะทำสิ่งต่อไปนี้ได้
- เลือกรายชื่อติดต่อจากรายการและส่งกลับไปยังแอปของคุณเพื่อดำเนินการต่อ
- แก้ไขข้อมูลของผู้ติดต่อที่มีอยู่
- แทรกรายชื่อติดต่อดิบใหม่สำหรับบัญชีใดก็ได้
- ลบรายชื่อติดต่อหรือข้อมูลรายชื่อติดต่อ
หากผู้ใช้แทรกหรืออัปเดตข้อมูล คุณสามารถรวบรวมข้อมูลก่อนแล้วส่งเป็น ส่วนหนึ่งของ Intent ได้
เมื่อใช้ Intent เพื่อเข้าถึงผู้ให้บริการรายชื่อติดต่อผ่านแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ คุณ ไม่จำเป็นต้องเขียน UI หรือโค้ดของคุณเองเพื่อเข้าถึงผู้ให้บริการ นอกจากนี้ คุณยังไม่จำเป็นต้อง ขอสิทธิ์อ่านหรือเขียนไปยังผู้ให้บริการ แอปพลิเคชันรายชื่อติดต่อของอุปกรณ์สามารถ มอบสิทธิ์อ่านรายชื่อติดต่อให้คุณได้ และเนื่องจากคุณทำการแก้ไขผู้ให้บริการผ่านแอปพลิเคชันอื่น คุณจึงไม่จำเป็นต้องมีสิทธิ์เขียน
กระบวนการทั่วไปในการส่ง Intent เพื่อเข้าถึงผู้ให้บริการอธิบายไว้โดยละเอียดใน
คู่มือข้อมูลเบื้องต้นเกี่ยวกับผู้ให้บริการเนื้อหาในส่วน "การเข้าถึงข้อมูลผ่าน Intent" การดำเนินการ
ประเภท MIME และค่าข้อมูลที่คุณใช้สำหรับงานที่พร้อมใช้งานจะสรุปไว้ในตารางที่ 4 ส่วนค่า
extras ที่คุณใช้กับ
putExtra()
จะแสดงอยู่ใน
เอกสารอ้างอิงสำหรับ ContactsContract.Intents.Insert
ตารางที่ 4 เจตนาของ Contacts Provider
งาน | การทำงาน | ข้อมูล | ประเภท MIME | หมายเหตุ |
---|---|---|---|---|
เลือกรายชื่อติดต่อจากรายการ | ACTION_PICK |
ค่าใดค่าหนึ่งต่อไปนี้
|
ไม่ใช้ |
แสดงรายการรายชื่อติดต่อดิบหรือรายการข้อมูลจากรายชื่อติดต่อดิบ ทั้งนี้ขึ้นอยู่กับ
ประเภท URI ของเนื้อหาที่คุณระบุ
Call
|
แทรกรายชื่อติดต่อดิบใหม่ | Insert.ACTION |
ไม่มี |
RawContacts.CONTENT_TYPE ประเภท MIME สำหรับชุดรายชื่อติดต่อดิบ
|
แสดงหน้าจอเพิ่มรายชื่อติดต่อของแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ ค่า
extras ที่คุณเพิ่มลงใน Intent จะแสดงขึ้น หากส่งพร้อมกับ
startActivityForResult()
ระบบจะส่ง URI ของเนื้อหาของรายชื่อติดต่อดิบที่เพิ่มใหม่กลับไปยังเมธอดเรียกกลับ onActivityResult()
ของกิจกรรมในอาร์กิวเมนต์ Intent ในฟิลด์ "data"
หากต้องการทราบค่าดังกล่าว โปรดโทรหา getData()
|
แก้ไขรายชื่อติดต่อ | ACTION_EDIT |
CONTENT_LOOKUP_URI สำหรับ
รายชื่อติดต่อ กิจกรรมของเอดิเตอร์จะช่วยให้ผู้ใช้แก้ไขข้อมูลที่เชื่อมโยงกับรายชื่อติดต่อนี้ได้
|
Contacts.CONTENT_ITEM_TYPE รายชื่อติดต่อเดียว |
แสดงหน้าจอแก้ไขรายชื่อติดต่อในแอปพลิเคชันรายชื่อติดต่อ ค่าพิเศษที่คุณเพิ่ม ลงใน Intent จะแสดงขึ้น เมื่อผู้ใช้คลิกเสร็จสิ้นเพื่อบันทึก การแก้ไข กิจกรรมของคุณจะกลับมาอยู่เบื้องหน้า |
แสดงเครื่องมือเลือกที่เพิ่มข้อมูลได้ด้วย | ACTION_INSERT_OR_EDIT |
ไม่มี |
CONTENT_ITEM_TYPE
|
ความตั้งใจนี้จะแสดงหน้าจอเครื่องมือเลือกของแอปรายชื่อติดต่อเสมอ ผู้ใช้สามารถ
เลือกรายชื่อติดต่อที่จะแก้ไข หรือเพิ่มรายชื่อติดต่อใหม่ หน้าจอแก้ไขหรือหน้าจอเพิ่มจะปรากฏขึ้น ทั้งนี้ขึ้นอยู่กับตัวเลือกของผู้ใช้ และระบบจะแสดงข้อมูลเพิ่มเติมที่คุณส่งใน Intent
หากแอปแสดงข้อมูลติดต่อ เช่น อีเมลหรือหมายเลขโทรศัพท์ ให้ใช้
Intent นี้เพื่อให้ผู้ใช้เพิ่มข้อมูลลงในรายชื่อติดต่อที่มีอยู่
รายชื่อติดต่อ
หมายเหตุ: ไม่จำเป็นต้องส่งค่าชื่อในส่วนพิเศษของ Intent นี้ เนื่องจากผู้ใช้จะเลือกชื่อที่มีอยู่หรือเพิ่มชื่อใหม่เสมอ นอกจากนี้ หากคุณส่งชื่อและผู้ใช้เลือกที่จะแก้ไข แอปรายชื่อติดต่อจะ แสดงชื่อที่คุณส่งและเขียนทับค่าก่อนหน้า หากผู้ใช้ไม่สังเกตเห็นข้อความนี้และบันทึกการแก้ไข ค่าเก่าจะหายไป |
แอปรายชื่อติดต่อของอุปกรณ์ไม่อนุญาตให้คุณลบรายชื่อติดต่อดิบหรือข้อมูลใดๆ ของรายชื่อติดต่อดังกล่าวด้วย
Intent แต่หากต้องการลบรายชื่อติดต่อดิบ ให้ใช้
ContentResolver.delete()
หรือ ContentProviderOperation.newDelete()
ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้างและส่ง Intent ที่แทรกรายชื่อติดต่อและข้อมูลใหม่
Kotlin
// Gets values from the UI val name = contactNameEditText.text.toString() val phone = contactPhoneEditText.text.toString() val email = contactEmailEditText.text.toString() val company = companyName.text.toString() val jobtitle = jobTitle.text.toString() /* * 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 val contactData = arrayListOf<ContentValues>() /* * Defines the raw contact row */ // Sets up the row as a ContentValues object val rawContactRow = ContentValues().apply { // Adds the account type and name to the row put(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.type) put(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.name) } // Adds the row to the array contactData.add(rawContactRow) /* * Sets up the phone number data row */ // Sets up the row as a ContentValues object val phoneRow = ContentValues().apply { // Specifies the MIME type for this data row (all data rows must be marked by their type) put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) // Adds the phone number and its type to the row 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 val emailRow = ContentValues().apply { // Specifies the MIME type for this data row (all data rows must be marked by their type) put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) // Adds the email address and its type to the row put(ContactsContract.CommonDataKinds.Email.ADDRESS, email) } // Adds the row to the array contactData.add(emailRow) // Creates a new intent for sending to the device's contacts application val insertIntent = Intent(ContactsContract.Intents.Insert.ACTION).apply { // Sets the MIME type to the one expected by the insertion activity type = ContactsContract.RawContacts.CONTENT_TYPE // Sets the new contact name putExtra(ContactsContract.Intents.Insert.NAME, name) // Sets the new company and job title putExtra(ContactsContract.Intents.Insert.COMPANY, company) putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle) /* * 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 */ putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData) } // Send out the intent to start the device's contacts app in its add contact activity. startActivity(insertIntent)
Java
// Gets values from the UI String name = contactNameEditText.getText().toString(); String phone = contactPhoneEditText.getText().toString(); String email = contactEmailEditText.getText().toString(); String company = companyName.getText().toString(); String jobtitle = jobTitle.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, selectedAccount.getType()); rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.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);
ความสมบูรณ์ของข้อมูล
เนื่องจากที่เก็บรายชื่อติดต่อมีข้อมูลที่สำคัญและละเอียดอ่อนซึ่งผู้ใช้คาดหวังว่าข้อมูลดังกล่าวจะถูกต้องและเป็นปัจจุบัน ผู้ให้บริการรายชื่อติดต่อจึงมีกฎที่กำหนดไว้อย่างชัดเจนสำหรับความสมบูรณ์ของข้อมูล คุณมีหน้าที่รับผิดชอบในการปฏิบัติตามกฎเหล่านี้เมื่อแก้ไขข้อมูลรายชื่อติดต่อ กฎที่สำคัญ มีดังนี้
-
เพิ่ม
ContactsContract.CommonDataKinds.StructuredName
แถว สําหรับContactsContract.RawContacts
แถวทุกแถวที่คุณเพิ่มเสมอ -
แถว
ContactsContract.RawContacts
ที่ไม่มีแถวContactsContract.CommonDataKinds.StructuredName
ในตารางContactsContract.Data
อาจทำให้เกิดปัญหาในระหว่างการ รวม -
ลิงก์แถวใหม่ของ
ContactsContract.Data
กับแถวหลักContactsContract.RawContacts
เสมอ -
แถว
ContactsContract.Data
ที่ไม่ได้ลิงก์กับContactsContract.RawContacts
จะไม่ปรากฏในแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ และอาจทำให้เกิดปัญหากับตัวดัดแปลงการซิงค์ - เปลี่ยนข้อมูลเฉพาะสำหรับรายชื่อติดต่อดิบที่คุณเป็นเจ้าของเท่านั้น
- โปรดทราบว่าโดยปกติแล้วผู้ให้บริการรายชื่อติดต่อจะจัดการข้อมูลจากบัญชีประเภทต่างๆ และบริการออนไลน์หลายรายการ คุณต้องตรวจสอบว่าแอปพลิเคชันของคุณแก้ไข หรือลบข้อมูลสำหรับแถวที่เป็นของคุณเท่านั้น และแทรกข้อมูลที่มี ประเภทบัญชีและชื่อที่คุณควบคุมเท่านั้น
-
ใช้ค่าคงที่ที่กำหนดไว้ใน
ContactsContract
และคลาสย่อย ของค่าคงที่นั้นเสมอสำหรับค่าคงที่ของหน่วยงาน, URI ของเนื้อหา, เส้นทาง URI, ชื่อคอลัมน์, ประเภท MIME และค่าTYPE
- การใช้ค่าคงที่เหล่านี้จะช่วยให้คุณหลีกเลี่ยงข้อผิดพลาดได้ นอกจากนี้ คุณจะได้รับการแจ้งเตือนพร้อมคำเตือนของคอมไพเลอร์ หากค่าคงที่ใดค่าหนึ่งเลิกใช้งานแล้ว
แถวข้อมูลที่กำหนดเอง
การสร้างและใช้ประเภท MIME ที่กำหนดเองจะช่วยให้คุณแทรก แก้ไข ลบ และเรียกข้อมูลแถวข้อมูลของคุณเองในตาราง ContactsContract.Data
ได้ แถวของคุณ
จะใช้ได้เฉพาะคอลัมน์ที่กำหนดไว้ใน
ContactsContract.DataColumns
แม้ว่าคุณจะแมปชื่อคอลัมน์เฉพาะประเภทของคุณเอง
กับชื่อคอลัมน์เริ่มต้นได้ก็ตาม ในแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์
ระบบจะแสดงข้อมูลสำหรับแถวของคุณ แต่จะแก้ไขหรือลบไม่ได้ และผู้ใช้จะเพิ่ม
ข้อมูลเพิ่มเติมไม่ได้ หากต้องการอนุญาตให้ผู้ใช้แก้ไขแถวข้อมูลที่กำหนดเอง คุณต้องระบุกิจกรรมของเอดิเตอร์
ในแอปพลิเคชันของคุณเอง
หากต้องการแสดงข้อมูลที่กำหนดเอง ให้ระบุcontacts.xml
ไฟล์ที่มีองค์ประกอบ <ContactsAccountType>
และองค์ประกอบย่อย <ContactsDataKind>
อย่างน้อย 1 รายการ ซึ่งอธิบายไว้อย่างละเอียดในส่วน<ContactsDataKind> element
ดูข้อมูลเพิ่มเติมเกี่ยวกับประเภท MIME ที่กำหนดเองได้ในคู่มือ สร้าง Content Provider
อะแดปเตอร์การซิงค์ Contacts Provider
ผู้ให้บริการรายชื่อติดต่อออกแบบมาเพื่อจัดการการซิงค์ ข้อมูลรายชื่อติดต่อระหว่างอุปกรณ์และบริการออนไลน์โดยเฉพาะ ซึ่งจะช่วยให้ผู้ใช้ดาวน์โหลด ข้อมูลที่มีอยู่ไปยังอุปกรณ์ใหม่และอัปโหลดข้อมูลที่มีอยู่ไปยังบัญชีใหม่ได้ การซิงค์ยังช่วยให้ผู้ใช้มีข้อมูลล่าสุดพร้อมใช้งานเสมอ ไม่ว่า แหล่งที่มาของการเพิ่มและการเปลี่ยนแปลงจะเป็นอะไรก็ตาม ข้อดีอีกอย่างของการซิงค์คือการทำให้ข้อมูลรายชื่อติดต่อพร้อมใช้งานแม้ว่าอุปกรณ์จะไม่ได้เชื่อมต่อกับเครือข่ายก็ตาม
แม้ว่าคุณจะใช้การซิงค์ได้หลายวิธี แต่ระบบ Android มี เฟรมเวิร์กการซิงค์แบบปลั๊กอินที่ทำให้งานต่อไปนี้เป็นไปโดยอัตโนมัติ
- กำลังตรวจสอบความพร้อมใช้งานของเครือข่าย
- การกำหนดเวลาและดำเนินการซิงค์ตามค่ากำหนดของผู้ใช้
- การรีสตาร์ทการซิงโครไนซ์ที่หยุดไป
หากต้องการใช้เฟรมเวิร์กนี้ คุณต้องจัดหาปลั๊กอิน Sync Adapter Sync Adapter แต่ละตัวจะเฉพาะเจาะจงสำหรับผู้ให้บริการและผู้ให้บริการเนื้อหา แต่สามารถจัดการชื่อบัญชีหลายชื่อสำหรับบริการเดียวกันได้ เฟรมเวิร์กยังอนุญาตให้มี Sync Adapter หลายรายการสำหรับบริการและผู้ให้บริการเดียวกันด้วย
คลาสและไฟล์ของอะแดปเตอร์การซิงค์
คุณใช้ตัวปรับการซิงค์เป็นคลาสย่อยของ
AbstractThreadedSyncAdapter
และติดตั้งเป็นส่วนหนึ่งของแอปพลิเคชัน Android
ระบบจะเรียนรู้เกี่ยวกับ Sync Adapter จากองค์ประกอบในไฟล์ Manifest ของแอปพลิเคชัน
และจากไฟล์ XML พิเศษที่ไฟล์ Manifest ชี้ไป ไฟล์ XML จะกำหนด
ประเภทบัญชีสำหรับบริการออนไลน์และสิทธิ์สำหรับผู้ให้บริการเนื้อหา ซึ่งเมื่อรวมกันแล้ว
จะระบุอะแดปเตอร์ได้อย่างไม่ซ้ำกัน ตัวปรับการซิงค์จะไม่ทำงานจนกว่าผู้ใช้จะเพิ่มบัญชีสำหรับประเภทบัญชีของตัวปรับการซิงค์และเปิดใช้การซิงค์สำหรับผู้ให้บริการเนื้อหาที่ตัวปรับการซิงค์ซิงค์ด้วย ในตอนนี้ ระบบจะเริ่มจัดการอแดปเตอร์
โดยเรียกใช้อแดปเตอร์ตามความจำเป็นเพื่อซิงค์ระหว่างผู้ให้บริการเนื้อหากับเซิร์ฟเวอร์
หมายเหตุ: การใช้ประเภทบัญชีเป็นส่วนหนึ่งของการระบุตัวตนของ Sync Adapter จะช่วยให้ระบบตรวจหาและจัดกลุ่ม Sync Adapter ที่เข้าถึงบริการต่างๆ จากองค์กรเดียวกันได้ เช่น อะแดปเตอร์การซิงค์สำหรับบริการออนไลน์ของ Google ทั้งหมดมี
ประเภทบัญชีcom.google
เดียวกัน เมื่อผู้ใช้เพิ่มบัญชี Google ลงในอุปกรณ์ ระบบจะแสดงตัวปรับการซิงค์ที่ติดตั้งไว้ทั้งหมดสำหรับบริการของ Google ไว้ด้วยกัน โดยตัวปรับการซิงค์แต่ละรายการที่แสดงจะซิงค์กับผู้ให้บริการเนื้อหาที่แตกต่างกันในอุปกรณ์
เนื่องจากบริการส่วนใหญ่กำหนดให้ผู้ใช้ยืนยันตัวตนก่อนจึงจะเข้าถึงข้อมูลได้ ระบบ Android จึงมีเฟรมเวิร์กการตรวจสอบสิทธิ์ที่คล้ายกับเฟรมเวิร์กอะแดปเตอร์การซิงค์ และมักใช้ร่วมกับเฟรมเวิร์กอะแดปเตอร์การซิงค์ เฟรมเวิร์กการตรวจสอบสิทธิ์ใช้
เครื่องมือตรวจสอบสิทธิ์แบบปลั๊กอินซึ่งเป็นคลาสย่อยของ
AbstractAccountAuthenticator
เครื่องมือตรวจสอบสิทธิ์จะยืนยัน
ตัวตนของผู้ใช้ในขั้นตอนต่อไปนี้
- รวบรวมชื่อ รหัสผ่าน หรือข้อมูลที่คล้ายกันของผู้ใช้ (ข้อมูลเข้าสู่ระบบของผู้ใช้ )
- ส่งข้อมูลเข้าสู่ระบบไปยังบริการ
- ตรวจสอบการตอบกลับของบริการ
หากบริการยอมรับข้อมูลเข้าสู่ระบบ โปรแกรมตรวจสอบสิทธิ์จะ
จัดเก็บข้อมูลเข้าสู่ระบบไว้ใช้ในภายหลังได้ เนื่องจากเฟรมเวิร์กของโปรแกรมตรวจสอบสิทธิ์แบบปลั๊กอิน
AccountManager
จึงสามารถให้สิทธิ์เข้าถึงโทเค็นการตรวจสอบสิทธิ์ที่โปรแกรมตรวจสอบสิทธิ์
รองรับและเลือกที่จะเปิดเผย เช่น โทเค็นการตรวจสอบสิทธิ์ OAuth2
แม้ว่าจะไม่จำเป็นต้องมีการตรวจสอบสิทธิ์ แต่บริการรายชื่อติดต่อส่วนใหญ่ก็ใช้การตรวจสอบสิทธิ์ อย่างไรก็ตาม คุณไม่จำเป็นต้องใช้เฟรมเวิร์กการตรวจสอบสิทธิ์ของ Android เพื่อทำการตรวจสอบสิทธิ์
การติดตั้งใช้งานอะแดปเตอร์การซิงค์
หากต้องการใช้ตัวดัดแปลงการซิงค์สำหรับผู้ให้บริการรายชื่อติดต่อ คุณต้องเริ่มต้นด้วยการสร้างแอปพลิเคชัน Android ที่มีสิ่งต่อไปนี้
-
คอมโพเนนต์
Service
ที่ตอบสนองต่อคำขอจากระบบเพื่อ เชื่อมโยงกับ Sync Adapter -
เมื่อระบบต้องการเรียกใช้การซิงค์ ระบบจะเรียกใช้เมธอด
onBind()
ของบริการเพื่อรับIBinder
สำหรับ Sync Adapter ซึ่งช่วยให้ระบบ โทรข้ามกระบวนการไปยังเมธอดของอแดปเตอร์ได้ -
อะแดปเตอร์การซิงค์จริงที่ใช้เป็นคลาสย่อยที่เฉพาะเจาะจงของ
AbstractThreadedSyncAdapter
-
คลาสนี้จะทำหน้าที่ดาวน์โหลดข้อมูลจากเซิร์ฟเวอร์ อัปโหลดข้อมูลจาก
อุปกรณ์ และแก้ไขข้อขัดแย้ง การทำงานหลักของอแดปเตอร์จะ
ดำเนินการในเมธอด
onPerformSync()
ต้องสร้างอินสแตนซ์ของคลาสนี้เป็น Singleton -
คลาสย่อยของ
Application
-
คลาสนี้ทำหน้าที่เป็นโรงงานสำหรับซิงค์อะแดปเตอร์แบบ Singleton ใช้วิธี
onCreate()
เพื่อสร้างอินสแตนซ์ของ SyncAdapter และ ระบุเมธอด "getter" แบบคงที่เพื่อส่งคืน Singleton ไปยัง เมธอดonBind()
ของบริการ SyncAdapter -
ไม่บังคับ:
Service
คอมโพเนนต์ที่ตอบกลับ คำขอจากระบบสำหรับการตรวจสอบสิทธิ์ผู้ใช้ -
AccountManager
เริ่มบริการนี้เพื่อเริ่มกระบวนการ ตรวจสอบสิทธิ์ เมธอดonCreate()
ของบริการจะสร้างออบเจ็กต์ เครื่องมือตรวจสอบสิทธิ์ เมื่อระบบต้องการตรวจสอบสิทธิ์บัญชีผู้ใช้สำหรับ Sync Adapter ของแอปพลิเคชัน ระบบจะเรียกใช้เมธอดonBind()
ของบริการเพื่อรับIBinder
สำหรับเครื่องมือตรวจสอบสิทธิ์ ซึ่งจะช่วยให้ระบบ โทรข้ามกระบวนการไปยังเมธอดของเครื่องมือตรวจสอบสิทธิ์ได้ -
ไม่บังคับ: คลาสย่อยที่เฉพาะเจาะจงของ
AbstractAccountAuthenticator
ซึ่งจัดการคำขอสำหรับ การตรวจสอบสิทธิ์ -
คลาสนี้มีเมธอดที่
AccountManager
เรียกใช้ เพื่อตรวจสอบสิทธิ์ข้อมูลเข้าสู่ระบบของผู้ใช้กับเซิร์ฟเวอร์ รายละเอียดของ กระบวนการตรวจสอบสิทธิ์จะแตกต่างกันไปตามเทคโนโลยีเซิร์ฟเวอร์ที่ใช้ คุณควร ดูเอกสารประกอบสำหรับซอฟต์แวร์เซิร์ฟเวอร์เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับการตรวจสอบสิทธิ์ - ไฟล์ XML ที่กำหนด Sync Adapter และเครื่องมือตรวจสอบสิทธิ์ให้กับระบบ
-
คอมโพเนนต์บริการตัวตรวจสอบสิทธิ์และตัวปรับการซิงค์ที่อธิบายไว้ก่อนหน้านี้จะ
กำหนดไว้ใน
<service>
ในไฟล์ Manifest ของแอปพลิเคชัน องค์ประกอบเหล่านี้ มีองค์ประกอบย่อย<meta-data>
ซึ่งให้ข้อมูลที่เฉพาะเจาะจงแก่ระบบ-
องค์ประกอบ
<meta-data>
สำหรับบริการอะแดปเตอร์การซิงค์จะชี้ไปยัง ไฟล์ XMLres/xml/syncadapter.xml
ในทางกลับกัน ไฟล์นี้จะระบุ URI สำหรับเว็บเซอร์วิสที่จะซิงค์กับผู้ให้บริการรายชื่อติดต่อ และประเภทบัญชีสำหรับเว็บเซอร์วิส -
ไม่บังคับ: องค์ประกอบ
<meta-data>
สำหรับโปรแกรมตรวจสอบสิทธิ์จะชี้ไปยังไฟล์ XMLres/xml/authenticator.xml
ในทางกลับกัน ไฟล์นี้จะระบุ ประเภทบัญชีที่เครื่องมือตรวจสอบสิทธิ์นี้รองรับ รวมถึงทรัพยากร UI ที่ ปรากฏในระหว่างกระบวนการตรวจสอบสิทธิ์ ประเภทบัญชีที่ระบุในองค์ประกอบนี้ต้องเหมือนกับประเภทบัญชีที่ระบุสำหรับอะแดปเตอร์การซิงค์
-
องค์ประกอบ
ข้อมูลสตรีมโซเชียล
ตาราง android.provider.ContactsContract.StreamItems และ android.provider.ContactsContract.StreamItemPhotos จัดการข้อมูลขาเข้าจากโซเชียลเน็ตเวิร์ก คุณเขียนตัวดัดแปลงการซิงค์ที่เพิ่มข้อมูลสตรีม จากเครือข่ายของคุณเองลงในตารางเหล่านี้ หรือจะอ่านข้อมูลสตรีมจากตารางเหล่านี้และ แสดงในแอปพลิเคชันของคุณเอง หรือทั้ง 2 อย่างก็ได้ ฟีเจอร์เหล่านี้ช่วยให้คุณผสานรวมบริการและแอปพลิเคชันเครือข่ายสังคม เข้ากับประสบการณ์การใช้งานเครือข่ายสังคมของ Android ได้
ข้อความสตรีมโซเชียล
รายการสตรีมจะเชื่อมโยงกับรายชื่อติดต่อดิบเสมอ
android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID ลิงก์ไปยัง
_ID
ค่าสำหรับรายชื่อติดต่อดิบ ระบบจะจัดเก็บประเภทบัญชีและชื่อบัญชีของรายชื่อติดต่อดิบ
ไว้ในแถวของรายการสตรีมด้วย
จัดเก็บข้อมูลจากสตรีมในคอลัมน์ต่อไปนี้
- android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE
- ต้องระบุ ประเภทบัญชีของผู้ใช้สำหรับรายชื่อติดต่อดิบที่เชื่อมโยงกับรายการสตรีมนี้ อย่าลืมตั้งค่านี้เมื่อแทรกรายการสตรีม
- android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME
- ต้องระบุ ชื่อบัญชีของผู้ใช้สำหรับรายชื่อติดต่อดิบที่เชื่อมโยงกับรายการสตรีมนี้ อย่าลืมตั้งค่านี้เมื่อแทรกรายการสตรีม
- คอลัมน์ตัวระบุ
-
ต้องระบุ คุณต้องแทรกคอลัมน์ตัวระบุต่อไปนี้เมื่อ
แทรกรายการสตรีม
- android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID: ค่า android.provider.BaseColumns#_ID ของรายชื่อติดต่อที่รายการสตรีมนี้ เชื่อมโยงอยู่
- android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY: ค่า android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY ของ รายชื่อติดต่อที่เชื่อมโยงกับรายการสตรีมนี้
- android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID: ค่า android.provider.BaseColumns#_ID ของรายชื่อติดต่อดิบที่รายการสตรีมนี้ เชื่อมโยงอยู่
- android.provider.ContactsContract.StreamItemsColumns#COMMENTS
- ไม่บังคับ สรุปข้อมูลร้านค้าที่คุณแสดงได้ที่จุดเริ่มต้นของรายการสตรีม
- android.provider.ContactsContract.StreamItemsColumns#TEXT
-
ข้อความของรายการสตรีม ไม่ว่าจะเป็นเนื้อหาที่แหล่งที่มาของรายการโพสต์
หรือคำอธิบายของการดำเนินการบางอย่างที่สร้างรายการสตรีม คอลัมน์นี้อาจมี
การจัดรูปแบบและรูปภาพทรัพยากรที่ฝังใดๆ ที่
fromHtml()
แสดงได้ ผู้ให้บริการอาจตัดทอนหรือ ละเนื้อหาที่ยาว แต่จะพยายามไม่ให้แท็กขาด - android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP
- สตริงข้อความที่มีเวลาที่แทรกหรืออัปเดตรายการสตรีมในรูปแบบมิลลิวินาทีตั้งแต่ Epoch แอปพลิเคชันที่แทรกหรืออัปเดตรายการสตรีมมี หน้าที่ดูแลคอลัมน์นี้ โดย Contacts Provider จะไม่ดูแลคอลัมน์นี้โดยอัตโนมัติ
หากต้องการแสดงข้อมูลระบุสำหรับรายการสตรีม ให้ใช้ android.provider.ContactsContract.StreamItemsColumns#RES_ICON, android.provider.ContactsContract.StreamItemsColumns#RES_LABEL และ android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE เพื่อลิงก์ไปยังทรัพยากร ในแอปพลิเคชัน
ตาราง android.provider.ContactsContract.StreamItems ยังมีคอลัมน์ android.provider.ContactsContract.StreamItemsColumns#SYNC1 ถึง android.provider.ContactsContract.StreamItemsColumns#SYNC4 สำหรับใช้กับ Sync Adapter เท่านั้น
รูปภาพในสตรีมโซเชียล
ตาราง android.provider.ContactsContract.StreamItemPhotos จะจัดเก็บรูปภาพที่เชื่อมโยง
กับรายการสตรีม คอลัมน์ android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID ของตาราง
ลิงก์ไปยังค่าในคอลัมน์ _ID
ของ
ตาราง android.provider.ContactsContract.StreamItems ระบบจะจัดเก็บข้อมูลอ้างอิงรูปภาพไว้ในตาราง
ในคอลัมน์ต่อไปนี้
- คอลัมน์ android.provider.ContactsContract.StreamItemPhotos#PHOTO (BLOB)
- การแสดงรูปภาพในรูปแบบไบนารี ซึ่งผู้ให้บริการปรับขนาดเพื่อจัดเก็บและแสดง คอลัมน์นี้พร้อมใช้งานเพื่อให้เข้ากันได้แบบย้อนหลังกับ Contacts Provider เวอร์ชันก่อนหน้าซึ่งใช้คอลัมน์นี้ในการจัดเก็บรูปภาพ อย่างไรก็ตาม ในเวอร์ชันปัจจุบัน คุณไม่ควรใช้คอลัมน์นี้เพื่อจัดเก็บรูปภาพ แต่ให้ใช้ android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID หรือ android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI (ทั้ง 2 รายการ อธิบายไว้ในจุดต่อไปนี้) เพื่อจัดเก็บรูปภาพในไฟล์แทน ตอนนี้คอลัมน์นี้ มีภาพขนาดย่อของรูปภาพซึ่งพร้อมให้อ่านแล้ว
- android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID
-
ตัวระบุตัวเลขของรูปภาพสำหรับรายชื่อติดต่อดิบ ผนวกค่านี้เข้ากับค่าคงที่
DisplayPhoto.CONTENT_URI
เพื่อรับ URI เนื้อหาที่ชี้ไปยังไฟล์รูปภาพเดียว แล้วเรียกใช้openAssetFileDescriptor()
เพื่อรับแฮนเดิลไปยังไฟล์รูปภาพ - android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI
-
URI ของเนื้อหาที่ชี้ไปยังไฟล์รูปภาพโดยตรงสำหรับรูปภาพที่แถวนี้แสดง
โทรหา
openAssetFileDescriptor()
ด้วย URI นี้เพื่อรับแฮนเดิลไปยังไฟล์รูปภาพ
การใช้ตารางสตรีมโซเชียล
ตารางเหล่านี้ทำงานเหมือนกับตารางหลักอื่นๆ ใน Contacts Provider ยกเว้นว่า
- ตารางเหล่านี้ต้องมีสิทธิ์เข้าถึงเพิ่มเติม หากต้องการอ่านข้อมูลจากสตรีมเหล่านั้น แอปพลิเคชันของคุณ ต้องมีสิทธิ์ android.Manifest.permission#READ_SOCIAL_STREAM หากต้องการ แก้ไขแอตทริบิวต์เหล่านี้ แอปพลิเคชันของคุณต้องมีสิทธิ์ android.Manifest.permission#WRITE_SOCIAL_STREAM
-
สำหรับตาราง android.provider.ContactsContract.StreamItems ระบบจะจำกัดจำนวนแถว
ที่จัดเก็บไว้สำหรับรายชื่อติดต่อดิบแต่ละรายการ เมื่อถึงขีดจำกัดนี้แล้ว
ผู้ให้บริการรายชื่อติดต่อจะเพิ่มพื้นที่สำหรับแถวรายการสตรีมใหม่โดยการลบแถวที่มี
android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP ที่เก่าที่สุดโดยอัตโนมัติ หากต้องการดูขีดจำกัด ให้ส่งคำค้นหาไปยัง URI เนื้อหา
android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI คุณปล่อยให้
อาร์กิวเมนต์อื่นๆ ทั้งหมดนอกเหนือจาก URI ของเนื้อหาตั้งค่าเป็น
null
ได้ การค้นหา จะแสดงผลเคอร์เซอร์ที่มีแถวเดียว โดยมีคอลัมน์เดียว android.provider.ContactsContract.StreamItems#MAX_ITEMS
คลาส android.provider.ContactsContract.StreamItems.StreamItemPhotos จะกำหนดตารางย่อยของ android.provider.ContactsContract.StreamItemPhotos ซึ่งมีแถวรูปภาพสำหรับรายการสตรีมรายการเดียว
การโต้ตอบในสตรีมโซเชียล
ข้อมูลสตรีมโซเชียลที่จัดการโดยผู้ให้บริการรายชื่อติดต่อร่วมกับแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์เป็นวิธีที่มีประสิทธิภาพในการเชื่อมต่อระบบเครือข่ายโซเชียลกับรายชื่อติดต่อที่มีอยู่ ฟีเจอร์ต่อไปนี้พร้อมใช้งาน
- การซิงค์บริการเครือข่ายสังคมกับผู้ให้บริการรายชื่อติดต่อด้วยอะแดปเตอร์ sync จะช่วยให้คุณดึงกิจกรรมล่าสุดของรายชื่อติดต่อของผู้ใช้และจัดเก็บไว้ในตาราง android.provider.ContactsContract.StreamItems และ android.provider.ContactsContract.StreamItemPhotos เพื่อใช้ในภายหลังได้
- นอกจากการซิงค์ปกติแล้ว คุณยังเรียกใช้ตัวดัดแปลงการซิงค์เพื่อดึงข้อมูลเพิ่มเติมได้เมื่อผู้ใช้เลือกรายชื่อติดต่อเพื่อดู ซึ่งจะช่วยให้ตัวดัดแปลงการซิงค์ ดึงรูปภาพความละเอียดสูงและรายการสตรีมล่าสุดสำหรับรายชื่อติดต่อได้
- การลงทะเบียนการแจ้งเตือนกับแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์และ Contacts Provider จะช่วยให้คุณรับ Intent เมื่อมีการดูรายชื่อติดต่อ และอัปเดตสถานะของรายชื่อติดต่อจากบริการของคุณได้ในเวลานั้น วิธีนี้อาจเร็วกว่าและใช้แบนด์วิดท์น้อยกว่าการซิงค์แบบเต็มด้วยอะแดปเตอร์การซิงค์
- ผู้ใช้สามารถเพิ่มรายชื่อติดต่อลงในบริการเครือข่ายสังคมออนไลน์ขณะดูรายชื่อติดต่อ ในแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ คุณเปิดใช้ฟีเจอร์นี้ได้ด้วยฟีเจอร์ "เชิญรายชื่อติดต่อ" ซึ่งคุณเปิดใช้ได้ด้วยการรวมกิจกรรมที่เพิ่มรายชื่อติดต่อที่มีอยู่ลงใน เครือข่ายของคุณ และไฟล์ XML ที่ให้รายละเอียดแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์และ ผู้ให้บริการรายชื่อติดต่อพร้อมรายละเอียดของแอปพลิเคชันของคุณ
การซิงค์รายการในสตรีมกับผู้ให้บริการรายชื่อติดต่อเป็นประจำจะเหมือนกับการซิงค์อื่นๆ ดูข้อมูลเพิ่มเติมเกี่ยวกับการซิงค์ได้ที่ส่วน อะแดปเตอร์การซิงค์ของผู้ให้บริการรายชื่อติดต่อ การลงทะเบียนการแจ้งเตือนและ การเชิญผู้ติดต่อจะกล่าวถึงใน 2 ส่วนถัดไป
การลงทะเบียนเพื่อจัดการมุมมองของโซเชียลเน็ตเวิร์ก
หากต้องการลงทะเบียน Sync Adapter เพื่อรับการแจ้งเตือนเมื่อผู้ใช้ดูรายชื่อติดต่อที่ Sync Adapter ของคุณจัดการ ให้ทำดังนี้
-
สร้างไฟล์ชื่อ
contacts.xml
ในไดเรกทอรีres/xml/
ของโปรเจ็กต์ หากมีไฟล์นี้อยู่แล้ว ให้ข้ามขั้นตอนนี้ -
ในไฟล์นี้ ให้เพิ่มองค์ประกอบ
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">
หากมีองค์ประกอบนี้อยู่แล้ว ให้ข้ามขั้นตอนนี้ -
หากต้องการลงทะเบียนบริการที่จะได้รับการแจ้งเตือนเมื่อผู้ใช้เปิดหน้ารายละเอียดของรายชื่อติดต่อใน
แอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ ให้เพิ่มแอตทริบิวต์
viewContactNotifyService="serviceclass"
ลงในองค์ประกอบ โดยที่serviceclass
คือชื่อคลาสที่มีคุณสมบัติครบถ้วนของบริการ ที่ควรได้รับ Intent จากแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ สำหรับบริการแจ้งเตือน ให้ใช้คลาสที่ขยายIntentService
เพื่อให้บริการรับ Intent ได้ ข้อมูลใน Intent ขาเข้ามี URI เนื้อหาของรายชื่อติดต่อดิบที่ผู้ใช้คลิก จากบริการแจ้งเตือน คุณสามารถเชื่อมโยงและเรียกใช้ Sync Adapter เพื่ออัปเดตข้อมูลสำหรับรายชื่อติดต่อดิบ
หากต้องการลงทะเบียนกิจกรรมที่จะเรียกใช้เมื่อผู้ใช้คลิกรายการในสตรีม รูปภาพ หรือทั้ง 2 อย่าง ให้ทำดังนี้
-
สร้างไฟล์ชื่อ
contacts.xml
ในไดเรกทอรีres/xml/
ของโปรเจ็กต์ หากมีไฟล์นี้อยู่แล้ว ให้ข้ามขั้นตอนนี้ -
ในไฟล์นี้ ให้เพิ่มองค์ประกอบ
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">
หากมีองค์ประกอบนี้อยู่แล้ว ให้ข้ามขั้นตอนนี้ -
หากต้องการลงทะเบียนกิจกรรมอย่างใดอย่างหนึ่งเพื่อจัดการเมื่อผู้ใช้คลิกรายการในสตรีมในแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ ให้เพิ่มแอตทริบิวต์
viewStreamItemActivity="activityclass"
ลงในองค์ประกอบ โดยที่activityclass
คือชื่อคลาสแบบเต็มของกิจกรรม ที่ควรรับ Intent จากแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ -
หากต้องการลงทะเบียนกิจกรรมอย่างใดอย่างหนึ่งเพื่อจัดการเมื่อผู้ใช้คลิกรูปภาพในสตรีมในแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ ให้เพิ่มแอตทริบิวต์
viewStreamItemPhotoActivity="activityclass"
ลงในองค์ประกอบ โดยที่activityclass
คือชื่อคลาสแบบเต็มของกิจกรรม ที่ควรรับ Intent จากแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์
องค์ประกอบ <ContactsAccountType>
มีคำอธิบายโดยละเอียดในส่วนองค์ประกอบ<ContactsAccountType>
Intent ขาเข้ามี URI เนื้อหาของรายการหรือรูปภาพที่ผู้ใช้คลิก หากต้องการมีกิจกรรมแยกกันสำหรับรายการข้อความและรูปภาพ ให้ใช้ทั้ง 2 แอตทริบิวต์ในไฟล์เดียวกัน
การโต้ตอบกับบริการโซเชียลเน็ตเวิร์ก
ผู้ใช้ไม่จำเป็นต้องออกจากแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์เพื่อเชิญรายชื่อติดต่อไปยังเว็บไซต์เครือข่ายสังคม ของคุณ แต่คุณสามารถให้แอปรายชื่อติดต่อของอุปกรณ์ส่ง Intent เพื่อเชิญ รายชื่อติดต่อเข้าร่วมกิจกรรมใดกิจกรรมหนึ่งของคุณได้ โดยมีวิธีการตั้งค่าดังนี้
-
สร้างไฟล์ชื่อ
contacts.xml
ในไดเรกทอรีres/xml/
ของโปรเจ็กต์ หากมีไฟล์นี้อยู่แล้ว ให้ข้ามขั้นตอนนี้ -
ในไฟล์นี้ ให้เพิ่มองค์ประกอบ
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">
หากมีองค์ประกอบนี้อยู่แล้ว ให้ข้ามขั้นตอนนี้ -
เพิ่มแอตทริบิวต์ต่อไปนี้
inviteContactActivity="activityclass"
-
inviteContactActionLabel="@string/invite_action_label"
activityclass
คือชื่อคลาสแบบเต็มของ กิจกรรมที่ควรได้รับ Intentinvite_action_label
ค่าคือสตริงข้อความที่แสดงในเมนูเพิ่มการเชื่อมต่อในแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์
หมายเหตุ: ContactsSource
เป็นชื่อแท็กที่เลิกใช้งานแล้วสำหรับ
ContactsAccountType
การอ้างอิง contacts.xml
ไฟล์ contacts.xml
มีองค์ประกอบ XML ที่ควบคุมการโต้ตอบของ
Sync Adapter และแอปพลิเคชันกับแอปพลิเคชันรายชื่อติดต่อและผู้ให้บริการรายชื่อติดต่อ องค์ประกอบเหล่านี้มีคำอธิบายในส่วนต่อไปนี้
องค์ประกอบ <ContactsAccountType>
องค์ประกอบ <ContactsAccountType>
จะควบคุมการโต้ตอบของแอปพลิเคชันกับแอปพลิเคชันรายชื่อติดต่อ
โดยมีไวยากรณ์ดังนี้
<ContactsAccountType xmlns: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>
Description:
ประกาศคอมโพเนนต์ Android และป้ายกำกับ UI ที่อนุญาตให้ผู้ใช้เชิญรายชื่อติดต่อรายใดรายหนึ่งไปยัง โซเชียลเน็ตเวิร์ก แจ้งเตือนผู้ใช้เมื่อสตรีมโซเชียลเน็ตเวิร์กรายการใดรายการหนึ่งมีการอัปเดต และ อื่นๆ
โปรดทราบว่าไม่จำเป็นต้องมีคำนำหน้าแอตทริบิวต์ android:
สำหรับแอตทริบิวต์
ของ <ContactsAccountType>
แอตทริบิวต์
inviteContactActivity
- ชื่อคลาสแบบเต็มของกิจกรรมในแอปพลิเคชันที่คุณต้องการ เปิดใช้งานเมื่อผู้ใช้เลือกเพิ่มการเชื่อมต่อจาก แอปพลิเคชันรายชื่อติดต่อของอุปกรณ์
inviteContactActionLabel
-
สตริงข้อความที่แสดงสำหรับกิจกรรมที่ระบุใน
inviteContactActivity
ในเมนูเพิ่มการเชื่อมต่อ เช่น คุณสามารถใช้สตริง "ติดตามในเครือข่ายของฉัน" คุณใช้ตัวระบุทรัพยากรสตริง สำหรับป้ายกำกับนี้ได้ viewContactNotifyService
- ชื่อคลาสที่มีคุณสมบัติครบถ้วนของบริการในแอปพลิเคชันของคุณซึ่งควรได้รับการแจ้งเตือน เมื่อผู้ใช้ดูรายชื่อติดต่อ การแจ้งเตือนนี้ส่งโดยแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ ซึ่งจะช่วยให้แอปพลิเคชันของคุณเลื่อนการดำเนินการที่ใช้ข้อมูลจำนวนมากออกไปจนกว่าจะจำเป็นได้ ตัวอย่างเช่น แอปพลิเคชันของคุณสามารถตอบสนองต่อการแจ้งเตือนนี้ โดยการอ่านและแสดงรูปภาพความละเอียดสูงของรายชื่อติดต่อและรายการสตรีมโซเชียลล่าสุด ฟีเจอร์นี้อธิบายไว้โดยละเอียดในส่วนการโต้ตอบในสตรีมโซเชียล
viewGroupActivity
- ชื่อคลาสแบบเต็มของกิจกรรมในแอปพลิเคชันที่แสดงข้อมูลกลุ่มได้ เมื่อผู้ใช้คลิกป้ายกำกับกลุ่มในแอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ ระบบจะแสดง UI สำหรับกิจกรรมนี้
viewGroupActionLabel
-
ป้ายกำกับที่แอปพลิเคชันรายชื่อติดต่อแสดงสำหรับตัวควบคุม UI ที่อนุญาต
ให้ผู้ใช้ดูกลุ่มในแอปพลิเคชันของคุณ
แอตทริบิวต์นี้อนุญาตให้ใช้ตัวระบุทรัพยากรสตริง
viewStreamItemActivity
- ชื่อคลาสแบบเต็มของกิจกรรมในแอปพลิเคชันที่แอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ จะเปิดขึ้นเมื่อผู้ใช้คลิกรายการสตรีมสำหรับรายชื่อติดต่อดิบ
viewStreamItemPhotoActivity
- ชื่อคลาสแบบเต็มของกิจกรรมในแอปพลิเคชันที่แอปพลิเคชันรายชื่อติดต่อของอุปกรณ์ จะเปิดขึ้นเมื่อผู้ใช้คลิกรูปภาพในรายการสตรีมสำหรับรายชื่อติดต่อดิบ
องค์ประกอบ <ContactsDataKind>
องค์ประกอบ <ContactsDataKind>
ควบคุมการแสดงแถวข้อมูลที่กำหนดเองของแอปพลิเคชันใน UI ของแอปพลิเคชันรายชื่อติดต่อ โดยมีไวยากรณ์ดังนี้
<ContactsDataKind android:mimeType="MIMEtype" android:icon="icon_resources" android:summaryColumn="column_name" android:detailColumn="column_name">
มีอยู่ใน:
<ContactsAccountType>
Description:
ใช้องค์ประกอบนี้เพื่อให้แอปพลิเคชันรายชื่อติดต่อแสดงเนื้อหาของแถวข้อมูลที่กำหนดเองเป็น
ส่วนหนึ่งของรายละเอียดของรายชื่อติดต่อดิบ <ContactsDataKind>
องค์ประกอบย่อยแต่ละรายการ
ของ <ContactsAccountType>
แสดงถึงประเภทของแถวข้อมูลที่กำหนดเองซึ่งอะแดปเตอร์การซิงค์
จะเพิ่มลงในตาราง ContactsContract.Data
เพิ่มองค์ประกอบ
<ContactsDataKind>
สำหรับประเภท MIME ที่กำหนดเองแต่ละประเภทที่คุณใช้ คุณไม่จำเป็นต้องเพิ่มองค์ประกอบหากมีแถวข้อมูลที่กำหนดเองซึ่งคุณไม่ต้องการแสดงข้อมูล
แอตทริบิวต์
android:mimeType
-
ประเภท MIME ที่กำหนดเองที่คุณกำหนดไว้สำหรับประเภทแถวข้อมูลที่กำหนดเองประเภทใดประเภทหนึ่งในตาราง
ContactsContract.Data
เช่น ค่าvnd.android.cursor.item/vnd.example.locationstatus
อาจเป็น ประเภท MIME ที่กำหนดเองสำหรับแถวข้อมูลที่บันทึกตำแหน่งล่าสุดที่ทราบของรายชื่อติดต่อ android:icon
- ทรัพยากร drawable ของ Android ที่แอปพลิเคชันรายชื่อติดต่อแสดงข้างข้อมูลของคุณ ใช้เพื่อระบุให้ผู้ใช้ทราบว่าข้อมูลมาจากบริการของคุณ
android:summaryColumn
- ชื่อคอลัมน์สำหรับค่าแรกจาก 2 ค่าที่ดึงมาจากแถวข้อมูล ค่า จะแสดงเป็นบรรทัดแรกของรายการสำหรับแถวข้อมูลนี้ บรรทัดแรกมีไว้ เพื่อใช้เป็นข้อมูลสรุป แต่จะใช้หรือไม่ก็ได้ ดูเพิ่มเติม android:detailColumn
android:detailColumn
-
ชื่อคอลัมน์สำหรับค่าที่ 2 จาก 2 ค่าที่ดึงมาจากแถวข้อมูล ค่าจะ
แสดงเป็นบรรทัดที่ 2 ของรายการสำหรับแถวข้อมูลนี้ ดูเพิ่มเติม
android:summaryColumn
ฟีเจอร์เพิ่มเติมของ Contacts Provider
นอกเหนือจากฟีเจอร์หลักที่อธิบายไว้ในส่วนก่อนหน้าแล้ว ผู้ให้บริการรายชื่อติดต่อยังมีฟีเจอร์ที่มีประโยชน์ต่อไปนี้สำหรับการทำงานกับข้อมูลรายชื่อติดต่อ
- กลุ่มรายชื่อติดต่อ
- ฟีเจอร์รูปภาพ
กลุ่มรายชื่อติดต่อ
ผู้ให้บริการรายชื่อติดต่อจะติดป้ายกำกับคอลเล็กชันของรายชื่อติดต่อที่เกี่ยวข้องด้วยข้อมูลกลุ่มหรือไม่ก็ได้ หากเซิร์ฟเวอร์ที่เชื่อมโยงกับบัญชีผู้ใช้ต้องการดูแลรักษากลุ่ม อะแดปเตอร์การซิงค์สำหรับประเภทบัญชีของบัญชีควรโอนข้อมูลกลุ่มระหว่างผู้ให้บริการรายชื่อติดต่อกับเซิร์ฟเวอร์ เมื่อผู้ใช้เพิ่มรายชื่อติดต่อใหม่ลงในเซิร์ฟเวอร์
แล้วใส่รายชื่อติดต่อนี้ในกลุ่มใหม่ ตัวดัดแปลงการซิงค์จะต้องเพิ่มกลุ่มใหม่
ลงในตาราง ContactsContract.Groups
ระบบจะจัดเก็บกลุ่มที่รายชื่อติดต่อดิบ
เป็นสมาชิกไว้ในตาราง ContactsContract.Data
โดยใช้
ประเภท MIME ของ ContactsContract.CommonDataKinds.GroupMembership
หากคุณกำลังออกแบบ Sync Adapter ที่จะเพิ่มข้อมูลรายชื่อติดต่อดิบจากเซิร์ฟเวอร์ไปยังผู้ให้บริการรายชื่อติดต่อ และไม่ได้ใช้กลุ่ม คุณจะต้องบอกให้ผู้ให้บริการแสดงข้อมูลของคุณ ในโค้ดที่เรียกใช้เมื่อผู้ใช้เพิ่มบัญชี
ลงในอุปกรณ์ ให้อัปเดตแถว ContactsContract.Settings
ที่ผู้ให้บริการรายชื่อติดต่อเพิ่มสำหรับบัญชี ในแถวนี้ ให้ตั้งค่าของคอลัมน์
Settings.UNGROUPED_VISIBLE
เป็น 1 เมื่อทำเช่นนี้ ผู้ให้บริการรายชื่อติดต่อจะทำให้ข้อมูลรายชื่อติดต่อของคุณแสดงอยู่เสมอ แม้ว่าคุณจะไม่ได้ใช้กลุ่มก็ตาม
รูปภาพรายชื่อติดต่อ
ตาราง ContactsContract.Data
จะจัดเก็บรูปภาพเป็นแถวที่มีประเภท MIME
Photo.CONTENT_ITEM_TYPE
คอลัมน์ CONTACT_ID
ของแถวจะลิงก์กับคอลัมน์ _ID
ของรายชื่อติดต่อดิบที่แถวเป็นของ
คลาส ContactsContract.Contacts.Photo
จะกำหนดตารางย่อยของ
ContactsContract.Contacts
ที่มีข้อมูลรูปภาพสำหรับรูปภาพหลักของรายชื่อติดต่อ
ซึ่งเป็นรูปภาพหลักของรายชื่อติดต่อดิบหลักของรายชื่อติดต่อ ในทำนองเดียวกัน
คลาส ContactsContract.RawContacts.DisplayPhoto
จะกำหนดตารางย่อย
ของ ContactsContract.RawContacts
ที่มีข้อมูลรูปภาพสำหรับ
รูปภาพหลักของรายชื่อติดต่อดิบ
เอกสารอ้างอิงสำหรับ ContactsContract.Contacts.Photo
และ
ContactsContract.RawContacts.DisplayPhoto
มีตัวอย่างการดึงข้อมูลรูปภาพ ไม่มีคลาสอำนวยความสะดวกสำหรับการดึงข้อมูลรูปขนาดย่อหลักสำหรับรายชื่อติดต่อดิบ แต่คุณสามารถส่งคำค้นหาไปยังตาราง ContactsContract.Data
โดยเลือกใน _ID
ของรายชื่อติดต่อดิบ, Photo.CONTENT_ITEM_TYPE
และคอลัมน์ IS_PRIMARY
เพื่อค้นหารายการรูปภาพหลักของรายชื่อติดต่อดิบ
ข้อมูลสตรีมโซเชียลของบุคคลอาจรวมถึงรูปภาพด้วย โดยจะจัดเก็บไว้ในตาราง android.provider.ContactsContract.StreamItemPhotos ซึ่งมีคำอธิบายโดยละเอียดในส่วนรูปภาพในสตรีมโซเชียล