فراهم‌ساز مخاطبین

«ارائه‌کننده مخاطبین» مؤلفه قدرتمند و انعطاف‌پذیر Android است که مخزن مرکزی داده‌های مربوط به افراد را در دستگاه مدیریت می‌کند. «ارائه‌کننده مخاطبین» منبع داده‌هایی است که در برنامه مخاطبین دستگاه می‌بینید، و همچنین می‌توانید به داده‌های آن در برنامه خودتان دسترسی داشته باشید و داده‌ها را بین دستگاه و سرویس‌های آنلاین منتقل کنید. ارائه‌دهنده طیف گسترده‌ای از منابع داده را در خود جای می‌دهد و تلاش می‌کند تا حد امکان داده‌های بیشتری را برای هر فرد مدیریت کند، درنتیجه سازمان آن پیچیده است. به همین دلیل، میانای برنامه‌سازی کاربردی ارائه‌دهنده شامل مجموعه گسترده‌ای از کلاس‌ها و میاناهای قرارداد است که هم بازیابی و هم اصلاح داده‌ها را تسهیل می‌کند.

این راهنما موارد زیر را شرح می‌دهد:

  • ساختار ارائه‌دهنده پایه.
  • نحوه بازیابی داده‌ها از ارائه‌دهنده.
  • نحوه اصلاح داده‌ها در ارائه‌دهنده.
  • نحوه نوشتن وفق‌دهنده همگام‌سازی برای همگام‌سازی داده‌ها از سرور شما با «ارائه‌کننده مخاطبین».

این راهنما فرض می‌کند که شما با اصول اولیه ارائه‌دهندگان محتوای Android آشنا هستید. برای کسب اطلاعات بیشتر درباره ارائه‌دهندگان محتوای Android، راهنمای مبانی ارائه‌دهنده محتوا را بخوانید.

سازمان ارائه‌کننده مخاطبین

«ارائه‌کننده مخاطبین» یکی از مؤلفه‌های ارائه‌دهنده محتوای Android است. این API سه نوع داده درباره فرد را نگهداری می‌کند که هرکدام با جدولی که ارائه‌دهنده ارائه می‌دهد مطابقت دارد، همان‌طور که در شکل ۱ نشان داده شده است:

شکل ۱. ساختار جدول «ارائه‌کننده مخاطبین».

این سه جدول معمولاً با نام کلاس‌های قراردادشان شناخته می‌شوند. کلاس‌ها ثابت‌هایی را برای شناسه منبع یکسان محتوا، نام ستون‌ها، و مقادیر ستون‌های مورداستفاده جدول‌ها تعریف می‌کنند:

ContactsContract.Contacts جدول
ردیف‌هایی که افراد مختلف را براساس انبوهش ردیف‌های مخاطب خام نشان می‌دهند.
ContactsContract.RawContacts جدول
ردیف‌هایی که حاوی خلاصه‌ای از داده‌های شخص هستند، مختص نوع و حساب کاربری.
ContactsContract.Data جدول
ردیف‌هایی که حاوی جزئیات مخاطب خام هستند، مثل نشانی‌های ایمیل یا شماره تلفن‌ها.

جدول‌های دیگری که با کلاس‌های قرارداد در ContactsContract نشان داده می‌شوند جدول‌های کمکی هستند که «ارائه‌دهنده مخاطبین» از آن‌ها برای مدیریت عملیات خود یا پشتیبانی از عملکردهای خاص در مخاطبین دستگاه یا برنامه‌های تلفن استفاده می‌کند.

مخاطبین خام

مخاطب خام نشان‌دهنده داده‌های فردی است که از یک نوع حساب و نام حساب می‌آید. چون «ارائه‌کننده مخاطبین» اجازه می‌دهد بیش‌از یک سرویس آنلاین منبع داده‌های فرد باشد، «ارائه‌کننده مخاطبین» اجازه می‌دهد چندین مخاطب خام برای یک فرد وجود داشته باشد. چند مخاطب خام همچنین به کاربر اجازه می‌دهد داده‌های فرد را از بیش‌از یک حساب از همان نوع حساب ترکیب کند.

بیشتر داده‌های مخاطب خام در جدول ContactsContract.RawContacts ذخیره نمی‌شود. درعوض، در یک یا چند ردیف در جدول ContactsContract.Data ذخیره می‌شود. هر ردیف داده ستونی دارد Data.RAW_CONTACT_ID که حاوی مقدار RawContacts._ID ردیف ContactsContract.RawContacts اصلی آن است.

ستون‌های مهم مخاطب خام

ستون‌های مهم در جدول ContactsContract.RawContacts در جدول ۱ فهرست شده‌اند. لطفاً یادداشت‌های زیر جدول را بخوانید:

جدول ۱. ستون‌های مهم مخاطب خام.

نام ستون استفاده کردن یادداشت‌ها
ACCOUNT_NAME نام حساب برای نوع حسابی که منبع این مخاطب خام است. برای مثال، نام حساب «حساب Google» یکی از نشانی‌های Gmail مالک دستگاه است. برای اطلاعات بیشتر، ورودی بعدی را برای ACCOUNT_TYPE ببینید. قالب این نام مختص نوع حساب آن است. این نام کاربری لزوماً نشانی ایمیل نیست.
ACCOUNT_TYPE نوع حسابی که منبع این مخاطب خام است. برای مثال، نوع حساب «حساب Google» com.google است. همیشه نوع حسابتان را با شناسه دامنه‌ای که مالک آن هستید یا آن را کنترل می‌کنید واجدشرایط کنید. با این کار مطمئن می‌شوید که نوع حسابتان منحصربه‌فرد است. نوع حسابی که داده‌های مخاطبین را ارائه می‌دهد معمولاً وفق‌دهنده همگام‌سازی مرتبطی دارد که با «ارائه‌کننده مخاطبین» همگام‌سازی می‌شود.
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) را اضافه کند تا برنامه‌تان بتواند ردیف‌های مخاطب خام را اضافه کند. می‌توانید این الزام را در اسناد برای کاربر توضیح دهید، یا می‌توانید از کاربر بخواهید نوع و نام، یا هر دو را اضافه کند. انواع حساب و نام‌های حساب در بخش بعدی با جزئیات بیشتری شرح داده شده‌اند.

منابع داده‌های مخاطبین خام

برای درک نحوه عملکرد مخاطبین خام، کاربر «Emily Dickinson» را درنظر بگیرید که سه حساب کاربری زیر در دستگاهش تعریف شده است:

  • emily.dickinson@gmail.com
  • emilyd@gmail.com
  • حساب Twitter «belle_of_amherst»

این کاربر همگام‌سازی مخاطبین را برای هر سه حساب در تنظیمات حساب‌ها فعال کرده است.

فرض کنید امیلی دیکینسون پنجره مرورگری را باز می‌کند، به‌عنوان emily.dickinson@gmail.com به سیستم Gmail وارد می‌شود، «مخاطبین» را باز می‌کند، و «توماس هیگینسون» را اضافه می‌کند. بعداً، او به‌عنوان emilyd@gmail.com به سیستم Gmail وارد می‌شود و ایمیلی به «Thomas Higginson» ارسال می‌کند که به‌طور خودکار او را به‌عنوان مخاطب اضافه می‌کند. او همچنین «colonel_tom» (شناسه توییتر توماس هیگینسون) را در توییتر دنبال می‌کند.

«ارائه‌کننده مخاطبین» درنتیجه این کار سه مخاطب خام ایجاد می‌کند:

  1. مخاطب خام برای «Thomas Higginson» مرتبط با emily.dickinson@gmail.com. نوع حساب کاربری Google است.
  2. مخاطب خام دوم برای «Thomas Higginson» مرتبط با emilyd@gmail.com. نوع حساب کاربری نیز Google است. مخاطب خام دومی وجود دارد، هرچند نام آن با نام قبلی یکسان است، زیرا این فرد برای حساب کاربری دیگری اضافه شده است.
  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 داشته باشد، «ارائه‌دهنده مخاطبین» دو ردیف نشانی ایمیل را ذخیره می‌کند و هر دو را به مخاطب خام پیوند می‌دهد.

توجه کنید که انواع مختلف داده‌ها در این جدول واحد ذخیره شده است. ردیف‌های جزئیات نام نمایشی، شماره تلفن، ایمیل، نشانی پستی، عکس، و وب‌سایت همگی در جدول ContactsContract.Data قرار دارند. برای کمک به مدیریت این موضوع، جدول ContactsContract.Data چند ستون با نام‌های توصیفی و چند ستون با نام‌های عمومی دارد. محتوای ستون نام توصیفی، صرف‌نظر از نوع داده‌های موجود در ردیف، معنای یکسانی دارد، درحالی‌که محتوای ستون نام عمومی بسته به نوع داده‌ها معانی متفاوتی دارد.

نام‌های توصیفی ستون

چند نمونه از نام‌های توصیفی ستون عبارت‌اند از:

RAW_CONTACT_ID
مقدار ستون _ID مخاطب خام برای این داده‌ها.
MIMETYPE
نوع داده‌های ذخیره‌شده در این ردیف، که به‌صورت نوع MIME سفارشی بیان می‌شود. «ارائه‌دهنده مخاطبین» از انواع MIME تعریف‌شده در زیرکلاس‌های ContactsContract.CommonDataKinds استفاده می‌کند. این نوع‌های MIME متن‌باز هستند و هر برنامه یا وفق‌دهنده همگام‌سازی که با «ارائه‌کننده مخاطبین» کار می‌کند می‌تواند از آن‌ها استفاده کند.
IS_PRIMARY
اگر این نوع ردیف داده بتواند بیش‌از یک‌بار برای مخاطب خام رخ دهد، ستون IS_PRIMARY ردیف داده‌ای را که حاوی داده‌های اصلی برای آن نوع است پرچم‌گذاری می‌کند. برای مثال، اگر کاربر روی شماره تلفن مخاطبی فشار طولانی دهد و تنظیم پیش‌فرض را انتخاب کند، سپس ردیف ContactsContract.Data حاوی آن شماره ستون IS_PRIMARY آن روی مقدار غیرصفر تنظیم می‌شود.

نام‌های ستون عمومی

۱۵ ستون عمومی به‌نام DATA1 تا DATA15 وجود دارد که به‌طور کلی دردسترس هستند و چهار ستون عمومی دیگر SYNC1 تا SYNC4 که فقط باید توسط وفق‌دهنده‌های همگام‌سازی استفاده شوند. ثابت‌های نام ستون عمومی همیشه کار می‌کنند، صرف‌نظر از نوع داده‌ای که ردیف دارد.

ستون DATA1 نمایه‌سازی شده است. «ارائه‌کننده مخاطبین» همیشه از این ستون برای داده‌هایی استفاده می‌کند که ارائه‌کننده انتظار دارد بیشترین هدف پُرسمان باشد. برای مثال، در ردیف ایمیل، این ستون حاوی نشانی ایمیل واقعی است.

طبق قرارداد، ستون DATA15 برای ذخیره کردن داده‌های «شیء بزرگ دودویی» (BLOB) مثل ریزعکس‌ها رزرو شده است.

نام‌های ستون مختص نوع

برای تسهیل کار با ستون‌ها برای نوع خاصی از ردیف، «ارائه‌کننده مخاطبین» ثابت‌های نام ستون مختص نوع را نیز ارائه می‌دهد که در زیرکلاس‌های ContactsContract.CommonDataKinds تعریف شده‌اند. ثابت‌ها به‌سادگی نام ثابت متفاوتی به همان نام ستون می‌دهند که به شما کمک می‌کند به داده‌های موجود در ردیف نوع خاصی دسترسی پیدا کنید.

برای مثال، کلاس ContactsContract.CommonDataKinds.Email ثابت‌های نام ستون نوع‌ویژه را برای ردیف ContactsContract.Data که نوع MIME آن Email.CONTENT_ITEM_TYPE است تعریف می‌کند. کلاس حاوی ثابت ADDRESS برای ستون نشانی ایمیل است. مقدار واقعی ADDRESS «data1» است که با نام عمومی ستون یکسان است.

احتیاط: داده‌های سفارشی خودتان را بااستفاده از ردیفی که یکی از انواع MIME ازپیش تعریف‌شده ارائه‌دهنده را دارد به جدول ContactsContract.Data اضافه نکنید. اگر این کار را انجام دهید، ممکن است داده‌ها را ازدست بدهید یا باعث شوید ارائه‌دهنده دچار نقص عملکرد شود. برای مثال، نباید ردیفی با نوع MIME Email.CONTENT_ITEM_TYPE اضافه کنید که حاوی نام کاربری به‌جای نشانی ایمیل در ستون DATA1 باشد. اگر از نوع MIME سفارشی خودتان برای ردیف استفاده می‌کنید، می‌توانید نام‌های ستون مختص نوع خودتان را تعریف کنید و از ستون‌ها به هر نحوی که می‌خواهید استفاده کنید.

شکل ۲ نشان می‌دهد که ستون‌های توصیفی و ستون‌های داده چگونه در ردیف ContactsContract.Data ظاهر می‌شوند و نام‌های ستون خاص نوع چگونه روی نام‌های ستون عمومی «قرار می‌گیرند»

نحوه تخصیص نام‌های ستون نوع‌محور به نام‌های ستون عمومی

شکل ۲. نام‌های ستون خاص نوع و نام‌های ستون عمومی.

کلاس‌های نام ستون مختص نوع

جدول ۲ رایج‌ترین کلاس‌های نام ستون مختص نوع را فهرست می‌کند:

جدول ۲. کلاس‌های نام ستون خاص نوع

کلاس تخصیص نوع داده یادداشت‌ها
ContactsContract.CommonDataKinds.StructuredName داده‌های نام برای مخاطب خام مرتبط با این ردیف داده. مخاطب خام فقط یکی از این ردیف‌ها را دارد.
ContactsContract.CommonDataKinds.Photo عکس اصلی برای مخاطب خام مرتبط با این ردیف داده. مخاطب خام فقط یکی از این ردیف‌ها را دارد.
ContactsContract.CommonDataKinds.Email نشانی ایمیل برای مخاطب خام منسوب به این ردیف داده. مخاطب خام می‌تواند چندین نشانی ایمیل داشته باشد.
ContactsContract.CommonDataKinds.StructuredPostal نشانی پستی برای مخاطب خام منسوب به این ردیف داده. مخاطب خام می‌تواند چند نشانی پستی داشته باشد.
ContactsContract.CommonDataKinds.GroupMembership شناسه‌ای که مخاطب خام را به یکی از گروه‌ها در «ارائه‌دهنده مخاطبین» پیوند می‌دهد. گروه‌ها ویژگی اختیاری نوع حساب و نام حساب هستند. این موارد با جزئیات بیشتر در بخش گروه‌های مخاطب شرح داده شده‌اند.

مخاطبین

«ارائه‌کننده مخاطبین» ردیف‌های مخاطب خام را در همه انواع حساب و نام‌های حساب ترکیب می‌کند تا مخاطب را تشکیل دهد. این کار نمایش و اصلاح همه داده‌هایی را که کاربر برای فردی جمع‌آوری کرده است تسهیل می‌کند. «ارائه‌کننده مخاطبین» ایجاد ردیف‌های مخاطب جدید و ادغام مخاطبین خام با ردیف مخاطب موجود را مدیریت می‌کند. نه برنامه‌ها و نه وفق‌دهنده‌های همگام‌سازی مجاز به افزودن مخاطب نیستند، و برخی‌از ستون‌ها در ردیف مخاطب فقط خواندنی هستند.

توجه: اگر بخواهید مخاطبی را با insert() به «ارائه‌دهنده مخاطبین» اضافه کنید، استثنای UnsupportedOperationException دریافت خواهید کرد. اگر بخواهید ستونی را که به‌عنوان «فقط خواندنی» فهرست شده است به‌روز کنید، به‌روزرسانی نادیده گرفته می‌شود.

«ارائه‌کننده مخاطبین» در پاسخ به افزودن مخاطب خام جدیدی که با هیچ‌کدام از مخاطبین موجود مطابقت ندارد، مخاطب جدیدی ایجاد می‌کند. اگر داده‌های مخاطب خام موجود به‌گونه‌ای تغییر کند که دیگر با مخاطبی که قبلاً به آن پیوست شده بود مطابقت نداشته باشد، ارائه‌دهنده این کار را نیز انجام می‌دهد. اگر برنامه یا وفق‌دهنده همگام‌سازی مخاطب خام جدیدی ایجاد کند که با مخاطب موجود مطابقت داشته باشد، مخاطب خام جدید با مخاطب موجود ادغام می‌شود.

«ارائه‌کننده مخاطبین» ردیف مخاطب را با ستون _ID ردیف مخاطب در جدول Contacts به ردیف‌های مخاطب خام آن پیوند می‌دهد. ستون CONTACT_ID جدول مخاطبین خام ContactsContract.RawContacts حاوی مقادیر _ID برای ردیف مخاطبین مرتبط با هر ردیف مخاطبین خام است.

جدول ContactsContract.Contacts همچنین دارای ستون LOOKUP_KEY است که پیوندی «دائمی» به ردیف مخاطب است. چون «ارائه‌دهنده مخاطبین» مخاطبین را به‌طور خودکار نگهداری می‌کند، ممکن است مقدار _ID ردیف مخاطب را در پاسخ به تجمیع یا همگام‌سازی تغییر دهد. حتی اگر این اتفاق بیفتد، شناسه منبع یکسان محتوا CONTENT_LOOKUP_URI همراه با LOOKUP_KEY مخاطب همچنان به ردیف مخاطب اشاره خواهد کرد، بنابراین می‌توانید از LOOKUP_KEY برای حفظ پیوندها به مخاطبین «دلخواه» و غیره استفاده کنید. این ستون قالب خودش را دارد که به قالب ستون _ID مربوط نیست.

شکل ۳ نشان می‌دهد که سه جدول اصلی چگونه با یکدیگر مرتبط هستند.

جدول‌های اصلی ارائه‌کننده مخاطبین

شکل ۳. روابط جدول «مخاطبین»، «مخاطبین خام»، و «جزئیات».

احتیاط: اگر برنامه‌تان را در «فروشگاه Google Play» منتشر می‌کنید، یا اگر برنامه‌تان در دستگاهی با Android 10 (سطح میانای برنامه‌سازی کاربردی ۲۹) یا بالاتر اجرا می‌شود، به‌خاطر داشته باشید که مجموعه محدودی از فیلدها و روش‌های داده مخاطبین منسوخ شده‌اند.

تحت شرایط ذکرشده، سیستم به‌طور دوره‌ای هر مقداری را که در این فیلدهای داده نوشته شده است پاک می‌کند:

میاناهای برنامه‌سازی کاربردی که برای تنظیم فیلدهای داده بالا استفاده می‌شوند نیز منسوخ شده‌اند:

علاوه‌براین، فیلدهای زیر دیگر مخاطبین همیشگی را برنمی‌گردانند. توجه داشته باشید که برخی‌از این فیلدها تنها زمانی بر رتبه‌بندی مخاطبین تأثیر می‌گذارند که مخاطبین بخشی از یک نوع داده خاص باشند.

اگر برنامه‌هایتان به این فیلدها یا میاناهای برنامه‌سازی کاربردی دسترسی دارند یا آن‌ها را به‌روز می‌کنند، از روش‌های جایگزین استفاده کنید. برای مثال، می‌توانید بااستفاده از ارائه‌دهندگان محتوای خصوصی یا سایر داده‌های ذخیره‌شده در برنامه یا سیستم‌های پس‌زمینه‌تان، برخی‌از موارد استفاده را برآورده کنید.

برای تأیید اینکه عملکرد برنامه‌تان تحت تأثیر این تغییر قرار نمی‌گیرد، می‌توانید این فیلدهای داده را به‌صورت دستی پاک کنید. برای انجام این کار، فرمان ADB زیر را در دستگاهی که Android نسخه ۴.۱ (سطح میانای برنامه‌سازی کاربردی ۱۶) یا بالاتر دارد اجرا کنید:

adb shell content delete \
--uri content://com.android.contacts/contacts/delete_usage

داده‌ها از وفق‌دهنده‌های همگام‌سازی

کاربران داده‌های مخاطبین را مستقیماً در دستگاه وارد می‌کنند، اما داده‌ها ازطریق وفق‌دهنده‌های همگام‌سازی که انتقال داده‌ها بین دستگاه و سرویس‌ها را خودکار می‌کنند، از سرویس‌های وب به «ارائه‌کننده مخاطبین» نیز منتقل می‌شوند. وفق‌دهنده‌های همگام‌سازی در پس‌زمینه تحت کنترل سیستم اجرا می‌شوند و روش‌های ContentResolver را برای مدیریت داده‌ها فراخوانی می‌کنند.

در Android، سرویس وبی که وفق‌دهنده همگام‌سازی با آن کار می‌کند با نوع حساب شناسایی می‌شود. هر وفق‌دهنده همگام‌سازی با یک نوع حساب کار می‌کند، اما می‌تواند از چند نام حساب برای آن نوع پشتیبانی کند. انواع حساب و نام‌های حساب به‌طور خلاصه در بخش منابع داده‌های مخاطبین خام شرح داده شده‌اند. تعاریف زیر جزئیات بیشتری ارائه می‌دهند و نحوه ارتباط نوع و نام حساب با وفق‌دهنده‌ها و سرویس‌های همگام‌سازی را شرح می‌دهند.

نوع حساب
سرویسی را که کاربر در آن داده ذخیره کرده است شناسایی می‌کند. در بیشتر مواقع، کاربر باید با سرویس اصالت‌سنجی کند. برای مثال، «مخاطبین Google» نوعی حساب است که با کد google.com شناسایی می‌شود. این مقدار با نوع حساب استفاده‌شده توسط AccountManager مطابقت دارد.
نام حساب
حساب یا ورود به سیستم خاصی را برای نوع حساب شناسایی می‌کند. حساب‌های «مخاطبین Google» همان «حساب‌های Google» هستند که نشانی ایمیل را به‌عنوان نام حساب دارند. سرویس‌های دیگر ممکن است از نام کاربری تک‌کلمه‌ای یا شناسه عددی استفاده کنند.

انواع حساب لازم نیست منحصربه‌فرد باشند. کاربر می‌تواند چندین حساب «مخاطبین Google» را پیکربندی کند و داده‌های آن‌ها را در «ارائه‌دهنده مخاطبین» بارگیری کند؛ این اتفاق ممکن است زمانی رخ دهد که کاربر یک مجموعه مخاطب شخصی برای نام حساب شخصی و مجموعه دیگری برای کار داشته باشد. نام‌های حساب معمولاً یکتا هستند. این دو باهم جریان داده خاصی را بین «ارائه‌دهنده مخاطبین» و سرویس خارجی شناسایی می‌کنند.

اگر می‌خواهید داده‌های سرویس خود را به «ارائه‌کننده مخاطبین» منتقل کنید، باید وفق‌دهنده همگام‌سازی خودتان را بنویسید. این موضوع با جزئیات بیشتر در بخش وفق‌دهنده‌های همگام‌سازی ارائه‌کننده مخاطبین توضیح داده شده است.

شکل ۴ نشان می‌دهد که «ارائه‌کننده مخاطبین» چگونه در جریان داده‌های مربوط به افراد قرار می‌گیرد. در چارگوشی که «وفق‌دهنده‌های همگام‌سازی» علامت‌گذاری شده است، هر وفق‌دهنده با نوع حسابش برچسب‌گذاری شده است.

جریان داده‌های مربوط به افراد

شکل ۴. جریان داده‌های «ارائه‌کننده مخاطبین».

مجوزهای لازم

برنامه‌هایی که می‌خواهند به «ارائه‌دهنده مخاطبین» دسترسی داشته باشند باید اجازه‌های زیر را درخواست کنند:

دسترسی خواندن به یک یا چند جدول
READ_CONTACTS، مشخص‌شده در AndroidManifest.xml با عنصر <uses-permission> به‌عنوان <uses-permission android:name="android.permission.READ_CONTACTS">.
دسترسی نوشتن به یک یا چند جدول
WRITE_CONTACTS، مشخص‌شده در AndroidManifest.xml با عنصر <uses-permission> به‌عنوان <uses-permission android:name="android.permission.WRITE_CONTACTS">.

این اجازه‌ها به داده‌های نمایه کاربر تعمیم داده نمی‌شود. نمایه کاربر و اجازه‌های لازم آن در بخش زیر، نمایه کاربر، توضیح داده شده است.

به‌یاد داشته باشید که داده‌های مخاطبین کاربر شخصی و حساس است. کاربران نگران حریم خصوصی‌شان هستند، بنابراین نمی‌خواهند برنامه‌ها داده‌های مربوط به آن‌ها یا مخاطبینشان را جمع‌آوری کنند. اگر مشخص نباشد که چرا به اجازه دسترسی به داده‌های مخاطبین نیاز دارید، ممکن است رتبه‌بندی پایینی به برنامه‌تان بدهند یا به‌سادگی از نصب آن خودداری کنند.

نمایه کاربر

جدول 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() را فراخوانی کنید. شناسه منبع یکسان محتوا را روی CONTENT_URI تنظیم کنید و هیچ معیار انتخابی ارائه نکنید. همچنین می‌توانید از این شناسه منبع یکسان محتوا به‌عنوان شناسه منبع یکسان پایه برای بازیابی مخاطبین خام یا داده‌های نمایه استفاده کنید. برای مثال، این قطعه کد داده‌های نمایه را بازیابی می‌کند:

کاتلین

// 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
)

جاوا

// 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 ردیف را آزمایش کنید. اگر مخاطب نمایه کاربر باشد، این ستون روی «۱» تنظیم می‌شود.

فراداده ارائه‌کننده مخاطبین

«ارائه‌کننده مخاطبین» داده‌هایی را مدیریت می‌کند که وضعیت داده‌های مخاطبین را در مخزن ردیابی می‌کند. این فراداده درباره مخزن در مکان‌های مختلفی ذخیره می‌شود، ازجمله ردیف‌های جدول «مخاطبین خام»، «داده‌ها»، و «مخاطبین»، جدول ContactsContract.Settings، و جدول ContactsContract.SyncState. جدول زیر تأثیر هریک از این فراداده‌ها را نشان می‌دهد:

جدول ۳. فراداده در «ارائه‌کننده مخاطبین»

میز ستون مقدار معنی
ContactsContract.RawContacts DIRTY «0» - از آخرین همگام‌سازی تغییر نکرده است. مخاطبین خامی را که در دستگاه تغییر کرده‌اند و باید دوباره با سرور همگام‌سازی شوند علامت‌گذاری می‌کند. وقتی برنامه‌های Android ردیفی را به‌روز می‌کنند، این مقدار به‌طور خودکار توسط «ارائه‌دهنده مخاطبین» تنظیم می‌شود.

وفق‌دهنده‌های همگام‌سازی که مخاطب خام یا جدول‌های داده را اصلاح می‌کنند باید همیشه رشته CALLER_IS_SYNCADAPTER را به شناسه منبع یکسان محتوایی که استفاده می‌کنند اضافه کنند. این کار مانع از این می‌شود که ارائه‌دهنده ردیف‌ها را به‌عنوان کثیف علامت‌گذاری کند. درغیراین‌صورت، اصلاحات وفق‌دهنده همگام‌سازی به‌عنوان اصلاحات محلی نشان داده می‌شود و به سرور ارسال می‌شود، حتی اگر سرور منبع اصلاحات باشد.

«۱» - از آخرین همگام‌سازی تغییر کرده است، باید دوباره با سرور همگام‌سازی شود.
ContactsContract.RawContacts VERSION شماره نسخه این ردیف. «ارائه‌کننده مخاطبین» هرگاه ردیف یا داده‌های مرتبط با آن تغییر کند، این مقدار را به‌طور خودکار افزایش می‌دهد.
ContactsContract.Data DATA_VERSION شماره نسخه این ردیف. «ارائه‌کننده مخاطبین» هرگاه ردیف داده تغییر کند، این مقدار را به‌طور خودکار افزایش می‌دهد.
ContactsContract.RawContacts SOURCE_ID مقدار رشته‌ای که این مخاطب خام را به‌طور منحصربه‌فرد برای حسابی که در آن ایجاد شده است شناسایی می‌کند. وقتی وفق‌دهنده همگام‌سازی مخاطب خام جدیدی ایجاد می‌کند، این ستون باید روی شناسه یکتای سرور برای مخاطب خام تنظیم شود. وقتی برنامه Android مخاطب خام جدیدی ایجاد می‌کند، برنامه باید این ستون را خالی بگذارد. این کار به وفق‌دهنده همگام‌سازی علامت می‌دهد که باید مخاطب خام جدیدی در سرور ایجاد کند و مقداری برای SOURCE_ID دریافت کند.

به‌ویژه، شناسه منبع باید برای هر نوع حساب یکتا باشد و در همگام‌سازی‌ها ثابت بماند:

  • یکتا: هر مخاطب خام برای یک حساب باید شناسه منبع خودش را داشته باشد. اگر این کار را انجام ندهید، در برنامه مخاطبین مشکل ایجاد خواهید کرد. توجه داشته باشید که دو مخاطب خام برای یک نوع حساب ممکن است شناسه منبع یکسانی داشته باشند. برای مثال، مخاطب خام «Thomas Higginson» برای حساب emily.dickinson@gmail.com می‌تواند شناسه منبع یکسانی با مخاطب خام «Thomas Higginson» برای حساب emilyd@gmail.com داشته باشد.
  • پایدار: شناسه‌های منبع بخشی دائمی از داده‌های سرویس آنلاین برای مخاطب خام است. برای مثال، اگر کاربر «فضای ذخیره‌سازی مخاطبین» را از تنظیمات «برنامه‌ها» پاک کند و دوباره همگام‌سازی کند، مخاطبین خام بازیابی‌شده باید همان شناسه‌های منبع قبلی را داشته باشند. اگر این را اعمال نکنید، میان‌برها دیگر کار نخواهند کرد.
ContactsContract.Groups GROUP_VISIBLE «0» - مخاطبین این گروه نباید در واسط‌های کاربر برنامه Android نمایان باشند. این ستون برای سازگاری با سرورهایی است که به کاربر اجازه می‌دهند مخاطبین را در گروه‌های خاصی پنهان کند.
«۱» - مخاطبین این گروه می‌توانند در واسط‌های کاربر برنامه نمایان باشند.
ContactsContract.Settings UNGROUPED_VISIBLE «0» - برای این حساب و نوع حساب، مخاطبینی که به گروهی تعلق ندارند برای واسط‌های کاربر برنامه Android نامرئی هستند. به‌طور پیش‌فرض، اگر هیچ‌کدام از مخاطبین خام به گروهی تعلق نداشته باشند، مخاطبین نامرئی هستند (عضویت گروه برای مخاطب خام با یک یا چند ContactsContract.CommonDataKinds.GroupMembership ردیف در جدول ContactsContract.Data نشان داده می‌شود). با تنظیم این پرچم در ردیف جدول ContactsContract.Settings برای نوع حساب و حساب، می‌توانید مخاطبین بدون گروه را مجبور کنید که قابل‌مشاهده باشند. یکی از کاربردهای این پرچم نشان دادن مخاطبین از سرورهایی است که از گروه‌ها استفاده نمی‌کنند.
«۱» - برای این حساب و نوع حساب، مخاطبینی که به گروهی تعلق ندارند برای واسط‌های کاربر برنامه قابل‌مشاهده هستند.
ContactsContract.SyncState (همه) از این جدول برای ذخیره فراداده برای وفق‌دهنده همگام‌سازی‌تان استفاده کنید. با این جدول می‌توانید وضعیت همگام‌سازی و سایر داده‌های مرتبط با همگام‌سازی را به‌طور مداوم در دستگاه ذخیره کنید.

دسترسی به «ارائه‌کننده مخاطبین»

این بخش دستورالعمل‌های دسترسی به داده‌ها از «ارائه‌دهنده مخاطبین» را شرح می‌دهد و بر موارد زیر تمرکز دارد:

  • پُرسمان‌های نهاد.
  • اصلاح گروهی.
  • بازیابی و اصلاح با قصدها.
  • تمامیت داده‌ها.

ایجاد تغییرات ازطریق وفق‌دهنده همگام‌سازی نیز با جزئیات بیشتر در بخش وفق‌دهنده‌های همگام‌سازی ارائه‌کننده مخاطبین پوشش داده شده است.

درحال پُرسمان نهادها

چون جدول‌های «ارائه‌دهنده مخاطبین» به‌صورت سلسله‌مراتبی سازمان‌دهی شده‌اند، اغلب مفید است که یک ردیف و همه ردیف‌های «فرزند» پیوندشده به آن را بازیابی کنید. برای مثال، برای نمایش همه اطلاعات یک فرد، ممکن است بخواهید همه ردیف‌های ContactsContract.RawContacts را برای یک ردیف ContactsContract.Contacts، یا همه ردیف‌های ContactsContract.CommonDataKinds.Email را برای یک ردیف ContactsContract.RawContacts بازیابی کنید. برای تسهیل این امر، «ارائه‌دهنده مخاطبین» ساختارهای نهاد را ارائه می‌دهد که مانند پیوندهای پایگاه داده بین جدول‌ها عمل می‌کنند.

نهاد مانند جدولی است که از ستون‌های انتخاب‌شده از جدول اصلی و جدول فرعی آن تشکیل شده است. وقتی نهادی را پُرسمان می‌کنید، طرح‌ریزی و معیارهای جستجو را براساس ستون‌های موجود از نهاد ارائه می‌دهید. نتیجه یک Cursor است که شامل یک ردیف برای هر ردیف جدول فرزند بازیابی‌شده است. برای مثال، اگر ContactsContract.Contacts.Entity را برای نام مخاطب و همه ردیف‌های ContactsContract.CommonDataKinds.Email را برای همه مخاطبین خام آن نام پُرسمان کنید، یک Cursor دریافت می‌کنید که حاوی یک ردیف برای هر ردیف ContactsContract.CommonDataKinds.Email است.

نهادها پُرسمان‌ها را ساده می‌کنند. بااستفاده از یک موجودیت، می‌توانید همه داده‌های مخاطبین را برای یک مخاطب یا مخاطب خام به‌طور هم‌زمان بازیابی کنید، به‌جای اینکه ابتدا مجبور باشید جدول اصلی را برای دریافت شناسه جستجو کنید و سپس جدول فرعی را با آن شناسه جستجو کنید. همچنین، «ارائه‌کننده مخاطبین» پرسمان را دربرابر یک نهاد در یک تراکنش پردازش می‌کند که این امر اطمینان می‌دهد داده‌های بازیابی‌شده ازنظر داخلی سازگار هستند.

توجه: معمولاً یک نهاد شامل همه ستون‌های جدول اصلی و فرعی نیست. اگر بخواهید با نام ستونی کار کنید که در فهرست ثابت‌های نام ستون برای نهاد نیست، Exception دریافت خواهید کرد.

تکه‌کد زیر نحوه بازیابی همه ردیف‌های مخاطب خام را برای یک مخاطب نشان می‌دهد. این قطعه کد بخشی از یک برنامه بزرگ‌تر است که دو فعالیت دارد: «اصلی» و «جزئیات». فعالیت اصلی فهرستی از ردیف‌های مخاطب را نشان می‌دهد؛ وقتی کاربر یکی را انتخاب می‌کند، فعالیت شناسه آن را به فعالیت جزئیات ارسال می‌کند. فعالیت جزئیات از ContactsContract.Contacts.Entity برای نمایش همه ردیف‌های داده از همه مخاطبین خام مرتبط با مخاطب انتخاب‌شده استفاده می‌کند.

این قطعه از فعالیت «جزئیات» گرفته شده است:

کاتلین

...
    /*
     * 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.
    )
}

جاوا

...
    /*
     * 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() در یک تراکنش انجام می‌دهد، اصلاحات شما هرگز مخزن مخاطبین را در وضعیت ناسازگار رها نمی‌کند. اصلاح دسته‌ای همچنین درج مخاطب خام و داده‌های جزئیات آن را به‌طور هم‌زمان تسهیل می‌کند.

توجه: برای اصلاح یک مخاطب خام، به‌جای انجام اصلاح در برنامه‌تان، ارسال هدف به برنامه مخاطبین دستگاه را درنظر بگیرید. این کار با جزئیات بیشتر در بخش بازیابی و اصلاح با هدف‌ها شرح داده شده است.

امتیازهای بازده

اصلاح دسته‌ای حاوی تعداد زیادی عملیات می‌تواند فرایندهای دیگر را مسدود کند، که منجر به تجربه کاربری کلی بدی می‌شود. برای سازمان‌دهی همه تغییراتی که می‌خواهید در کمترین فهرست‌های جداگانه ممکن انجام دهید و درعین‌حال از مسدود شدن سیستم توسط آن‌ها جلوگیری کنید، باید برای یک یا چند عملیات نقطه تسلیم تنظیم کنید. نقطه تسلیم شیء ContentProviderOperation است که مقدار isYieldAllowed() آن روی true تنظیم شده است. وقتی «ارائه‌کننده مخاطبین» با نقطه تسلیم مواجه می‌شود، کارش را موقتاً متوقف می‌کند تا به دیگر فرایندها اجازه اجرا دهد و تراکنش فعلی را می‌بندد. وقتی ارائه‌دهنده دوباره شروع می‌شود، با عملیات بعدی در ArrayList ادامه می‌دهد و تراکنش جدیدی را شروع می‌کند.

نقاط تسلیم منجر به بیش‌از یک تراکنش در هر تماس با applyBatch() می‌شود. به‌همین دلیل، باید نقطه تسلیمی برای آخرین عملیات برای مجموعه‌ای از ردیف‌های مرتبط تنظیم کنید. برای مثال، باید برای آخرین عملیات در مجموعه‌ای که ردیف‌های مخاطب خام و ردیف‌های داده مرتبط با آن را اضافه می‌کند، یا آخرین عملیات برای مجموعه‌ای از ردیف‌های مرتبط با یک مخاطب، نقطه تسلیم تنظیم کنید.

نقطه تسلیم همچنین واحدی از عملیات اتمی است. همه دسترسی‌های بین دو نقطه تسلیم به‌صورت یک واحد تکی موفق یا ناموفق خواهند بود. اگر هیچ نقطه تسلیمی تنظیم نکنید، کوچک‌ترین عملیات اتمی کل دسته عملیات خواهد بود. اگر از نقاط تسلیم استفاده کنید، از کاهش عملکرد سیستم توسط عملیات جلوگیری می‌کنید و درعین‌حال اطمینان حاصل می‌کنید که زیرمجموعه‌ای از عملیات اتمی است.

مرجع‌های برگشتی اصلاح

وقتی ردیف مخاطب خام جدید و ردیف‌های داده مرتبط با آن را به‌عنوان مجموعه‌ای از اشیاء ContentProviderOperation درج می‌کنید، باید ردیف‌های داده را با درج کردن مقدار _ID مخاطب خام به‌عنوان مقدار RAW_CONTACT_ID به ردیف مخاطب خام پیوند دهید. بااین‌حال، این مقدار هنگام ایجاد ContentProviderOperation برای ردیف داده دردسترس نیست، زیرا هنوز ContentProviderOperation را برای ردیف مخاطب خام اعمال نکرده‌اید. برای حل این مشکل، کلاس ContentProviderOperation.Builder دارای روش withValueBackReference() است. این روش به شما امکان می‌دهد ستونی را با نتیجه عملیات قبلی درج یا اصلاح کنید.

روش withValueBackReference() دو متغیر مستقل دارد:

key
کلید جفت کلید-مقدار. مقدار این آرگومان باید نام ستونی در جدولی باشد که درحال اصلاح آن هستید.
previousResult
نمایه مبتنی بر ۰ مقداری در آرایه اشیای ContentProviderResult از applyBatch(). با اعمال عملیات دسته‌ای، نتیجه هر عملیات در آرایه واسطه‌ای از نتایج ذخیره می‌شود. مقدار previousResult نمایه یکی از این نتایج است که با مقدار key بازیابی و ذخیره می‌شود. این کار به شما امکان می‌دهد تا یک رکورد مخاطب خام جدید درج کنید و مقدار _ID آن را برگردانید، سپس هنگام افزودن ردیف ContactsContract.Data، یک «ارجاع برگشتی» به مقدار ایجاد کنید.

وقتی برای اولین‌بار applyBatch() را فراخوانی می‌کنید، کل آرایه نتیجه ایجاد می‌شود و اندازه آن برابر با اندازه ArrayList اشیای ContentProviderOperation است که ارائه می‌دهید. بااین‌حال، همه عناصر موجود در آرایه نتیجه روی null تنظیم شده‌اند و اگر بخواهید به نتیجه عملیاتی که هنوز اعمال نشده است ارجاع دهید، withValueBackReference() Exception را برمی‌گرداند.

قطعه‌های زیر نحوه درج مخاطب خام و داده‌های جدید را به‌صورت دسته‌ای نشان می‌دهد. این الگوها شامل کدی هستند که نقطه تسلیم ایجاد می‌کند و از ارجاع برگشتی استفاده می‌کند.

قطعه کد اول داده‌های مخاطب را از میانای کاربر بازیابی می‌کند. در این مرحله، کاربر ازقبل حسابی را که مخاطب خام جدید باید به آن اضافه شود انتخاب کرده است.

کاتلین

// 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]

جاوا

// 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 ایجاد می‌کند:

کاتلین

    /*
     * 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())

جاوا

    /*
     * 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() پرچم‌گذاری شده است که نقطه تسلیم را تنظیم می‌کند:

کاتلین

    // 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())

جاوا

    // 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() را نشان می‌دهد که مخاطب خام و ردیف‌های داده جدید را درج می‌کند.

کاتلین

    // 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")
    }
}

جاوا

    // 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 ردیف، این مراحل را دنبال کنید:

  1. ستون VERSION مخاطب خام را به‌همراه داده‌های دیگری که بازیابی می‌کنید بازیابی کنید.
  2. بااستفاده از روش newAssertQuery(Uri)، شیء ContentProviderOperation.Builder مناسبی برای اعمال محدودیت ایجاد کنید. برای شناسه منبع یکسان محتوا، از RawContacts.CONTENT_URI با _ID مخاطب خام پیوست‌شده به آن استفاده کنید.
  3. برای شیء ContentProviderOperation.Builder، withValue() را فراخوانی کنید تا ستون VERSION را با شماره نسخه‌ای که به‌تازگی بازیابی کرده‌اید مقایسه کنید.
  4. برای همان ContentProviderOperation.Builder، withExpectedCount() را فراخوانی کنید تا مطمئن شوید فقط یک ردیف توسط این ادعا آزمایش می‌شود.
  5. برای ایجاد شیء ContentProviderOperation، build() را فراخوانی کنید، سپس این شیء را به‌عنوان اولین شیء در ArrayList که به applyBatch() ارسال می‌کنید اضافه کنید.
  6. تراکنش دسته‌ای را اعمال کنید.

اگر ردیف مخاطب خام با عملیات دیگری بین زمانی که ردیف را می‌خوانید و زمانی که برای اصلاح آن تلاش می‌کنید به‌روز شود، «assert» ContentProviderOperation ناموفق خواهد بود و کل دسته عملیات لغو خواهد شد. سپس می‌توانید انتخاب کنید که دسته را دوباره امتحان کنید یا اقدام دیگری انجام دهید.

قطعه زیر نشان می‌دهد که چگونه پس‌از پُرسمان برای یک مخاطب خام بااستفاده از CursorLoader، یک «assert» ContentProviderOperation ایجاد کنید:

کاتلین

/*
 * 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
}

جاوا

/*
 * 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
    }

بازیابی و اصلاح با قصدها

ارسال هدف به برنامه مخاطبین دستگاه به شما امکان می‌دهد به‌طور غیرمستقیم به «ارائه‌دهنده مخاطبین» دسترسی پیدا کنید. هدف، واسط کاربر برنامه مخاطبین دستگاه را راه‌اندازی می‌کند که در آن کاربران می‌توانند کارهای مربوط به مخاطبین را انجام دهند. با این نوع دسترسی، کاربران می‌توانند:

  • مخاطبی را از فهرست انتخاب کنید و آن را برای کار بیشتر به برنامه‌تان برگردانید.
  • داده‌های مخاطب موجود را ویرایش کنید.
  • مخاطب خام جدیدی را برای هرکدام از حساب‌هایشان درج کنید.
  • داده‌های یک یا چند مخاطب را حذف کنید.

اگر کاربر درحال درج یا به‌روزرسانی داده‌ها است، می‌توانید ابتدا داده‌ها را جمع‌آوری کنید و آن را به‌عنوان بخشی از قصد ارسال کنید.

وقتی از هدف‌ها برای دسترسی به «ارائه‌کننده مخاطبین» ازطریق برنامه مخاطبین دستگاه استفاده می‌کنید، لازم نیست واسط کاربر یا کد خودتان را برای دسترسی به ارائه‌کننده بنویسید. همچنین لازم نیست برای خواندن یا نوشتن در ارائه‌دهنده، درخواست اجازه کنید. برنامه مخاطبین دستگاه می‌تواند اجازه خواندن مخاطب را به شما واگذار کند، و چون شما ازطریق برنامه دیگری درحال اعمال تغییرات در ارائه‌دهنده هستید، لازم نیست اجازه‌های نوشتن داشته باشید.

روند کلی ارسال هدف برای دسترسی به ارائه‌دهنده به‌طور دقیق در راهنمای مبانی ارائه‌دهنده محتوا در بخش «دسترسی به داده‌ها ازطریق اهداف» شرح داده شده است. کنش، نوع MIME، و مقادیر داده‌ای که برای تکالیف دردسترس استفاده می‌کنید در جدول ۴ خلاصه شده است، درحالی‌که مقادیر اضافی که می‌توانید با putExtra() استفاده کنید در اسناد مرجع برای ContactsContract.Intents.Insert فهرست شده است:

جدول ۴. قصدهای ارائه‌کننده مخاطبین.

تکلیف کنش داده نوع MIME یادداشت‌ها
انتخاب مخاطب از فهرست ACTION_PICK یکی از:
  • Contacts.CONTENT_URI، که فهرستی از مخاطبین را نمایش می‌دهد.
  • Phone.CONTENT_URI، که فهرستی از شماره تلفن‌های مخاطب خام را نمایش می‌دهد.
  • StructuredPostal.CONTENT_URI، که فهرستی از نشانی‌های پستی را برای مخاطب خام نمایش می‌دهد.
  • Email.CONTENT_URI، که فهرستی از نشانی‌های ایمیل را برای مخاطب خام نمایش می‌دهد.
استفاده نمی‌شود بسته به نوع شناسه منبع یکسان محتوایی که ارائه می‌دهید، فهرستی از مخاطبین خام یا فهرستی از داده‌های مخاطب خام را نمایش می‌دهد.

فراخوانی startActivityForResult()، که شناسه منبع یکسان محتوای ردیف انتخاب‌شده را برمی‌گرداند. قالب URI همان URI محتوای جدول است که LOOKUP_ID ردیف به آن پیوست شده است. برنامه مخاطبین دستگاه اجازه‌های خواندن و نوشتن را به این شناسه منبع یکسان محتوا برای طول عمر فعالیت شما واگذار می‌کند. برای جزئیات بیشتر، راهنمای مبانی ارائه‌دهنده محتوا را ببینید.

درج مخاطب خام جدید Insert.ACTION موجود نیست ‫RawContacts.CONTENT_TYPE، نوع MIME برای مجموعه‌ای از مخاطبین خام. صفحه افزودن مخاطب برنامه مخاطبین دستگاه را نمایش می‌دهد. مقادیر اضافه‌ای که به قصد اضافه می‌کنید نمایش داده می‌شود. اگر با startActivityForResult() ارسال شود، شناسه منبع یکسان محتوای مخاطب خام جدیداً اضافه‌شده به روش بازخوان onActivityResult() فعالیت شما در شناسه Intent، در فیلد «داده» برگردانده می‌شود. برای دریافت مقدار، getData() را فراخوانی کنید.
ویرایش مخاطب ACTION_EDIT CONTENT_LOOKUP_URI برای مخاطب. فعالیت ویرایشگر به کاربر اجازه می‌دهد هرکدام از داده‌های مرتبط با این مخاطب را ویرایش کند. Contacts.CONTENT_ITEM_TYPE، یک مخاطب. صفحه «ویرایش مخاطب» را در برنامه مخاطبین نمایش می‌دهد. مقادیر اضافی که به قصد اضافه می‌کنید نمایش داده می‌شود. وقتی کاربر برای ذخیره کردن ویرایش‌ها روی تمام کلیک می‌کند، فعالیت شما به پیش‌زمینه برمی‌گردد.
انتخاب‌گری را نمایش دهید که بتواند داده هم اضافه کند. ACTION_INSERT_OR_EDIT موجود نیست CONTENT_ITEM_TYPE این هدف همیشه صفحه انتخابگر برنامه مخاطبین را نمایش می‌دهد. کاربر می‌تواند مخاطبی را برای ویرایش انتخاب کند یا مخاطب جدیدی اضافه کند. بسته به انتخاب کاربر، صفحه ویرایش یا افزودن ظاهر می‌شود و داده‌های اضافی که در هدف ارسال می‌کنید نمایش داده می‌شود. اگر برنامه‌تان داده‌های مخاطب مثل ایمیل یا شماره تلفن را نمایش می‌دهد، از این هدف استفاده کنید تا به کاربر اجازه دهید داده‌ها را به مخاطب موجود اضافه کند. تماس،

توجه: نیازی به ارسال مقدار نام در موارد اضافی این هدف نیست، زیرا کاربر همیشه نام موجودی را انتخاب می‌کند یا نام جدیدی اضافه می‌کند. علاوه‌براین، اگر نامی ارسال کنید و کاربر تصمیم بگیرد آن را ویرایش کند، برنامه مخاطبین نامی را که ارسال کرده‌اید نمایش می‌دهد و مقدار قبلی را رونویسی می‌کند. اگر کاربر متوجه این موضوع نشود و ویرایش را ذخیره کند، مقدار قدیمی ازبین می‌رود.

برنامه مخاطبین دستگاه به شما اجازه نمی‌دهد مخاطب خام یا هرکدام از داده‌های آن را با هدف حذف کنید. درعوض، برای حذف مخاطب خام، از ContentResolver.delete() یا ContentProviderOperation.newDelete() استفاده کنید.

قطعه زیر نشان می‌دهد که چگونه قصدی را بسازید و ارسال کنید که مخاطب خام و داده جدیدی را درج می‌کند:

کاتلین

// 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)

جاوا

// 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.RawContacts که اضافه می‌کنید، یک ردیف ContactsContract.CommonDataKinds.StructuredName اضافه کنید.
ردیف ContactsContract.RawContacts بدون ردیف ContactsContract.CommonDataKinds.StructuredName در جدول ContactsContract.Data ممکن است درطول انبوهش مشکل ایجاد کند.
همیشه ردیف‌های جدید ContactsContract.Data را به ردیف اصلی ContactsContract.RawContacts پیوند دهید.
ردیف ContactsContract.Data که به ContactsContract.RawContacts پیوند داده نشده باشد در برنامه مخاطبین دستگاه نمایان نخواهد بود و ممکن است باعث بروز مشکلاتی در وفق‌دهنده‌های همگام‌سازی شود.
داده‌ها را فقط برای مخاطبین خامی که متعلق به شما است تغییر دهید.
به‌یاد داشته باشید که «ارائه‌دهنده مخاطبین» معمولاً داده‌های چندین نوع حساب/سرویس آنلاین مختلف را مدیریت می‌کند. باید مطمئن شوید که برنامه‌تان فقط داده‌های ردیف‌هایی را که متعلق به شما است اصلاح یا حذف می‌کند، و فقط داده‌هایی را با نوع و نام حسابی که شما کنترل می‌کنید درج می‌کند.
همیشه از ثابت‌های تعریف‌شده در ContactsContract و زیرکلاس‌های آن برای مراجع، شناسه منبع یکسان محتوا، مسیرهای شناسه منبع یکسان، نام ستون‌ها، نوع رسانه، و مقادیر TYPE استفاده کنید.
استفاده از این ثابت‌ها به شما کمک می‌کند از خطاها جلوگیری کنید. همچنین اگر هرکدام از ثابت‌ها منسوخ شده باشد، با هشدارهای کامپایلر مطلع خواهید شد.

ردیف‌های داده سفارشی

با ایجاد و استفاده از انواع MIME سفارشی خودتان، می‌توانید ردیف‌های داده خودتان را در جدول ContactsContract.Data درج، ویرایش، حذف، و بازیابی کنید. ردیف‌های شما محدود به استفاده از ستون تعریف‌شده در ContactsContract.DataColumns هستند، اگرچه می‌توانید نام‌های ستون خاص نوع خودتان را به نام‌های ستون پیش‌فرض نگاشت کنید. در برنامه مخاطبین دستگاه، داده‌های ردیف‌های شما نمایش داده می‌شود اما نمی‌توان آن‌ها را ویرایش یا حذف کرد، و کاربران نمی‌توانند داده‌های بیشتری اضافه کنند. برای اینکه به کاربران اجازه دهید ردیف‌های داده‌های سفارشی شما را اصلاح کنند، باید فعالیت ویرایشگر را در برنامه خودتان ارائه دهید.

برای نمایش داده‌های سفارشی‌تان، فایل contacts.xml حاوی عنصر <ContactsAccountType> و یک یا چند عنصر فرزند <ContactsDataKind> آن را ارائه دهید. این موضوع با جزئیات بیشتر در بخش <ContactsDataKind> element توضیح داده شده است.

برای کسب اطلاعات بیشتر درباره انواع MIME سفارشی، راهنمای ایجاد ارائه‌دهنده محتوا را بخوانید.

وفق‌دهنده‌های همگام‌سازی «ارائه‌کننده مخاطبین»

«ارائه‌کننده مخاطبین» به‌طور خاص برای مدیریت همگام‌سازی داده‌های مخاطبین بین دستگاه و سرویس آنلاین طراحی شده است. این کار به کاربران اجازه می‌دهد داده‌های موجود را در دستگاه جدیدی بارگیری کنند و داده‌های موجود را در حساب جدیدی بارگذاری کنند. همگام‌سازی همچنین تضمین می‌کند که کاربران جدیدترین داده‌ها را دراختیار داشته باشند، صرف‌نظر از اینکه منبع افزوده‌ها و تغییرات چه باشد. مزیت دیگر همگام‌سازی این است که باعث می‌شود داده‌های مخاطبین حتی زمانی که دستگاه به شبکه متصل نیست دردسترس باشد.

اگرچه می‌توانید همگام‌سازی را به روش‌های مختلفی پیاده‌سازی کنید، سیستم Android یک چارچوب همگام‌سازی افزونه ارائه می‌دهد که کارهای زیر را خودکار می‌کند:

  • درحال بررسی دردسترس بودن شبکه.
  • زمان‌بندی و اجرای همگام‌سازی براساس اولویت‌های کاربر.
  • درحال بازراه‌اندازی همگام‌سازی‌هایی که متوقف شده‌اند.

برای استفاده از این چارچوب، باید افزایه وفق‌دهنده همگام‌سازی ارائه دهید. هر وفق‌دهنده همگام‌سازی برای یک سرویس و ارائه‌دهنده محتوا منحصربه‌فرد است، اما می‌تواند چندین نام حساب را برای یک سرویس مدیریت کند. این چارچوب همچنین امکان استفاده از چندین وفق‌دهنده همگام‌سازی را برای یک سرویس و ارائه‌دهنده فراهم می‌کند.

کلاس‌ها و فایل‌های وفق‌دهنده همگام‌سازی

وفق‌دهنده همگام‌سازی را به‌عنوان زیرکلاس AbstractThreadedSyncAdapter پیاده‌سازی می‌کنید و آن را به‌عنوان بخشی از برنامه Android نصب می‌کنید. سیستم از عناصر موجود در مانیفست برنامه شما و از فایل XML ویژه‌ای که مانیفست به آن اشاره می‌کند، درباره وفق‌دهنده همگام‌سازی اطلاعات کسب می‌کند. فایل XML نوع حساب را برای سرویس آنلاین و مرجع را برای ارائه‌دهنده محتوا تعریف می‌کند که باهم آداپتور را به‌طور منحصربه‌فرد شناسایی می‌کنند. وفق‌دهنده همگام‌سازی تا زمانی که کاربر حسابی برای نوع حساب وفق‌دهنده همگام‌سازی اضافه نکند و همگام‌سازی را برای ارائه‌دهنده محتوایی که وفق‌دهنده همگام‌سازی با آن همگام‌سازی می‌کند فعال نکند، فعال نمی‌شود. در این مرحله، سیستم شروع به مدیریت آداپتور می‌کند و آن را درصورت لزوم برای همگام‌سازی بین ارائه‌دهنده محتوا و سرور فراخوانی می‌کند.

توجه: استفاده از نوع حساب به‌عنوان بخشی از شناسایی وفق‌دهنده همگام‌سازی به سیستم اجازه می‌دهد وفق‌دهنده‌های همگام‌سازی را که به سرویس‌های مختلف از یک سازمان دسترسی دارند شناسایی و گروه‌بندی کند. برای مثال، وفق‌دهنده‌های همگام‌سازی برای سرویس‌های آنلاین Google همگی نوع حساب یکسانی دارند: com.google. وقتی کاربران «حساب Google» به دستگاه‌هایشان اضافه می‌کنند، همه وفق‌دهنده‌های همگام‌سازی نصب‌شده برای سرویس‌های Google باهم فهرست می‌شوند؛ هر وفق‌دهنده همگام‌سازی فهرست‌شده با ارائه‌دهنده محتوای متفاوتی در دستگاه همگام‌سازی می‌شود.

ازآنجایی‌که اکثر سرویس‌ها کاربران را ملزم می‌کنند قبل‌از دسترسی به داده‌ها هویتشان را به‌تأیید برسانند، سیستم Android چارچوب اصالت‌سنجی‌ای ارائه می‌دهد که مشابه چارچوب وفق‌دهنده همگام‌سازی است و اغلب همراه با آن استفاده می‌شود. چارچوب اصالت‌سنجی از اصالت‌سنج‌های افزونه‌ای استفاده می‌کند که زیرکلاس‌های AbstractAccountAuthenticator هستند. اصالت‌سنج هویت کاربر را در مراحل زیر تأیید می‌کند:

  1. نام، گذرواژه، یا اطلاعات مشابه کاربر (اعتبارنامه‌های کاربر) را جمع‌آوری می‌کند.
  2. اعتبارنامه را به سرویس ارسال می‌کند
  3. پاسخ سرویس را بررسی می‌کند.

اگر سرویس اعتبارنامه را بپذیرد، اصالت‌سنج می‌تواند اعتبارنامه را برای استفاده بعدی ذخیره کند. به‌دلیل چارچوب اصالت‌سنجی افزونه، AccountManager می‌تواند به هر توکن اصالت‌سنجی که اصالت‌سنج پشتیبانی می‌کند و انتخاب می‌کند که نمایش دهد، مانند توکن‌های اصالت‌سنجی OAuth2، دسترسی فراهم کند.

اگرچه اصالت‌سنجی الزامی نیست، اکثر سرویس‌های مخاطبین از آن استفاده می‌کنند. بااین‌حال، برای انجام اصالت‌سنجی ملزم به استفاده از چارچوب اصالت‌سنجی Android نیستید.

پیاده‌سازی وفق‌دهنده همگام‌سازی

برای پیاده‌سازی وفق‌دهنده همگام‌سازی برای «ارائه‌کننده مخاطبین»، ابتدا یک برنامه Android ایجاد می‌کنید که حاوی موارد زیر است:

یک مؤلفه Service که به درخواست‌های سیستم برای اتصال به وفق‌دهنده همگام‌سازی پاسخ می‌دهد.
وقتی سیستم می‌خواهد همگام‌سازی را اجرا کند، روش onBind() سرویس را فراخوانی می‌کند تا IBinder را برای وفق‌دهنده همگام‌سازی دریافت کند. این کار به سیستم اجازه می‌دهد فراخوانی‌های بین‌فرایندی به روش‌های آداپتور انجام دهد.
وفق‌دهنده همگام‌سازی واقعی، که به‌عنوان زیرکلاس واقعی AbstractThreadedSyncAdapter پیاده‌سازی شده است.
این کلاس کار بارگیری داده‌ها از سرور، بارگذاری داده‌ها از دستگاه، و حل تعارض‌ها را انجام می‌دهد. کار اصلی آداپتور در روش onPerformSync() انجام می‌شود. این کلاس باید به‌عنوان یک تک‌قلو نمونه‌سازی شود.
زیرکلاسی از Application.
این کلاس به‌عنوان کارخانه‌ای برای وفق‌دهنده همگام‌سازی تک‌عضوی عمل می‌کند. از روش onCreate() برای نمونه‌سازی وفق‌دهنده همگام‌سازی استفاده کنید و یک روش «گیرنده» ایستا برای برگرداندن تک‌نمونه به روش onBind() سرویس وفق‌دهنده همگام‌سازی ارائه دهید.
اختیاری: مؤلفه Service که به درخواست‌های سیستم برای اصالت‌سنجی کاربر پاسخ می‌دهد.
AccountManager این سرویس را برای شروع فرایند اصالت‌سنجی آغاز می‌کند. روش onCreate() سرویس، یک شیء اصالت‌سنجی را نمونه‌سازی می‌کند. وقتی سیستم می‌خواهد حساب کاربری را برای وفق‌دهنده همگام‌سازی برنامه اصالت‌سنجی کند، روش onBind() سرویس را فراخوانی می‌کند تا IBinder را برای اصالت‌سنج دریافت کند. این به سیستم اجازه می‌دهد فراخوانی‌های بین‌فرایندی به روش‌های اصالت‌سنج انجام دهد..
اختیاری: زیرکلاس واقعی AbstractAccountAuthenticator که درخواست‌های اصالت‌سنجی را مدیریت می‌کند.
این کلاس روش‌هایی را ارائه می‌دهد که AccountManager برای اصالت‌سنجی اطلاعات کاربری کاربر با سرور فراخوانی می‌کند. جزئیات فرایند اصالت‌سنجی براساس فناوری سرور مورداستفاده بسیار متفاوت است. برای کسب اطلاعات بیشتر درباره اصالت‌سنجی، باید به اسناد نرم‌افزار سرورتان مراجعه کنید.
فایل‌های XML که وفق‌دهنده همگام‌سازی و اصالت‌سنج را برای سیستم تعریف می‌کنند.
مؤلفه‌های سرویس اصالت‌سنج و وفق‌دهنده همگام‌سازی که قبلاً شرح داده شد در <service> عناصر مانیفست برنامه تعریف شده‌اند. این عناصر حاوی <meta-data> عناصر فرزندی هستند که داده‌های خاصی را به سیستم ارائه می‌دهند:
  • عنصر <meta-data> برای سرویس وفق‌دهنده همگام‌سازی به فایل XML res/xml/syncadapter.xml اشاره می‌کند. به‌نوبه خود، این فایل یک URI برای سرویس وب مشخص می‌کند که با «ارائه‌کننده مخاطبین» همگام‌سازی خواهد شد، و یک نوع حساب برای سرویس وب.
  • اختیاری: عنصر <meta-data> برای اصالت‌سنج به فایل XML res/xml/authenticator.xml اشاره می‌کند. به‌نوبه خود، این فایل نوع حسابی را که این اصالت‌سنج پشتیبانی می‌کند، و همچنین منابع واسط کاربری را که درطول فرایند اصالت‌سنجی ظاهر می‌شوند مشخص می‌کند. نوع حساب مشخص‌شده در این عنصر باید با نوع حساب مشخص‌شده برای وفق‌دهنده همگام‌سازی یکسان باشد.

داده‌های جاری‌سازی اجتماعی

جدول‌های android.provider.ContactsContract.StreamItems و android.provider.ContactsContract.StreamItemPhotos داده‌های ورودی از شبکه‌های اجتماعی را مدیریت می‌کنند. می‌توانید وفق‌دهنده همگام‌سازی‌ای بنویسید که داده‌های جاری را از شبکه خودتان به این جدول‌ها اضافه کند، یا می‌توانید داده‌های جاری را از این جدول‌ها بخوانید و آن را در برنامه خودتان نمایش دهید، یا هر دو کار را انجام دهید. با این ویژگی‌ها، سرویس‌ها و برنامه‌های شبکه‌های اجتماعی شما می‌توانند در تجربه شبکه‌های اجتماعی 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
رشته نوشتاری حاوی زمان درج یا به‌روزرسانی مورد جاری‌سازی، به‌شکل میلی‌ثانیه از مبدأ تاریخ. برنامه‌هایی که موارد جاری را درج یا به‌روز می‌کنند مسئول نگهداری این ستون هستند؛ این ستون به‌طور خودکار توسط «ارائه‌دهنده مخاطبین» نگهداری نمی‌شود.

برای نمایش اطلاعات شناساننده برای موارد جاری‌سازی، از 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 برای استفاده انحصاری وفق‌دهنده‌های همگام‌سازی است.

عکس‌های Social stream

جدول android.provider.ContactsContract.StreamItemPhotos عکس‌های مرتبط با یک مورد جاری‌سازی را ذخیره می‌کند. ستون android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID جدول به مقادیر ستون _ID جدول android.provider.ContactsContract.StreamItems پیوند می‌دهد. ارجاع‌های عکس در جدول در این ستون‌ها ذخیره می‌شود:

ستون android.provider.ContactsContract.StreamItemPhotos#PHOTO (یک BLOB).
نمایش دودویی عکس، که ارائه‌دهنده برای ذخیره‌سازی و نمایش اندازه آن را تغییر داده است. این ستون برای سازگاری با نسخه‌های قدیمی‌تر «ارائه‌دهنده مخاطبین» که از آن برای ذخیره کردن عکس‌ها استفاده می‌کردند دردسترس است. اما در نسخه فعلی نباید از این ستون برای ذخیره عکس استفاده کنید. درعوض، از android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID یا android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI (که هر دو در نکات زیر شرح داده شده‌اند) برای ذخیره عکس‌ها در فایل استفاده کنید. این ستون اکنون حاوی ریزعکس است که برای خواندن دردسترس است.
android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID
شناسه عددی عکس برای مخاطب خام. این مقدار را به ثابت DisplayPhoto.CONTENT_URI اضافه کنید تا شناسه منبع یکسان محتوایی را که به یک فایل عکس اشاره می‌کند دریافت کنید، سپس openAssetFileDescriptor() را فراخوانی کنید تا دستگیره‌ای برای فایل عکس دریافت کنید.
android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI
شناسه منبع یکسان محتوایی که مستقیماً به فایل عکس مربوط به عکس نشان‌داده‌شده در این ردیف اشاره می‌کند. با این URI با openAssetFileDescriptor() تماس بگیرید تا دستگیره‌ای برای فایل عکس دریافت کنید.

استفاده از جدول‌های جریان اجتماعی

این جدول‌ها مانند سایر جدول‌های اصلی در «ارائه‌دهنده مخاطبین» کار می‌کنند، با این تفاوت که:

  • این جدول‌ها به اجازه‌های دسترسی بیشتری نیاز دارند. برای خواندن از آن‌ها، برنامه شما باید اجازه android.Manifest.permission#READ_SOCIAL_STREAM را داشته باشد. برای اصلاح آن‌ها، برنامه شما باید اجازه android.Manifest.permission#WRITE_SOCIAL_STREAM را داشته باشد.
  • برای جدول android.provider.ContactsContract.StreamItems، تعداد ردیف‌های ذخیره‌شده برای هر مخاطب خام محدود است. وقتی به این حد برسید، «ارائه‌دهنده مخاطبین» با حذف خودکار ردیف‌هایی که قدیمی‌ترین android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP را دارند، برای ردیف‌های جدید مورد جاری فضا ایجاد می‌کند. برای دریافت حد، پُرسمانی برای شناسه منبع یکسان محتوا android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI صادر کنید. می‌توانید همه آرگومان‌ها به‌جز شناسه منبع یکسان محتوا را روی null تنظیم کنید. این پُرسمان یک «نشانگر» حاوی یک ردیف را با یک ستون android.provider.ContactsContract.StreamItems#MAX_ITEMS برمی‌گرداند.

کلاس android.provider.ContactsContract.StreamItems.StreamItemPhotos یک زیرجدول از android.provider.ContactsContract.StreamItemPhotos تعریف می‌کند که حاوی ردیف‌های عکس برای یک مورد جاری‌سازی است.

تعاملات جریان اجتماعی

داده‌های جریان اجتماعی که توسط «ارائه‌دهنده مخاطبین» مدیریت می‌شود، در ترکیب با برنامه مخاطبین دستگاه، روشی قدرتمند برای اتصال سیستم شبکه‌های اجتماعی شما با مخاطبین موجود ارائه می‌دهد. ویژگی‌های زیر دردسترس است:

  • با همگام‌سازی سرویس شبکه اجتماعی‌تان با «ارائه‌کننده مخاطبین» ازطریق وفق‌دهنده همگام‌سازی، می‌توانید فعالیت اخیر مخاطبین کاربر را بازیابی کنید و آن را در جدول‌های android.provider.ContactsContract.StreamItems و android.provider.ContactsContract.StreamItemPhotos برای استفاده‌های بعدی ذخیره کنید.
  • علاوه‌بر همگام‌سازی معمولی، می‌توانید وفق‌دهنده همگام‌سازی را برای بازیابی داده‌های بیشتر هنگامی که کاربر مخاطبی را برای مشاهده انتخاب می‌کند، راه‌اندازی کنید. این به وفق‌دهنده همگام‌سازی شما اجازه می‌دهد عکس‌های با وضوح بالا و جدیدترین موارد جاری را برای مخاطب بازیابی کند.
  • با ثبت اعلان با برنامه مخاطبین دستگاه و ارائه‌دهنده مخاطبین، می‌توانید هنگام مشاهده مخاطب، قصدی را دریافت کنید و در آن نقطه، وضعیت مخاطب را از سرویس خود به‌روز کنید. این رویکرد ممکن است سریع‌تر باشد و پهنای باند کمتری نسبت به همگام‌سازی کامل با وفق‌دهنده همگام‌سازی مصرف کند.
  • کاربران می‌توانند هنگام مشاهده مخاطب در برنامه مخاطبین دستگاه، مخاطب را به سرویس شبکه اجتماعی شما اضافه کنند. این کار را با ویژگی «دعوت از مخاطب» فعال می‌کنید، که آن را با ترکیبی از فعالیتی که مخاطب موجود را به شبکه‌تان اضافه می‌کند، و فایل XML که برنامه مخاطبین دستگاه و «ارائه‌دهنده مخاطبین» را با جزئیات برنامه‌تان ارائه می‌دهد، فعال می‌کنید.

همگام‌سازی منظم موارد جاری با «ارائه‌دهنده مخاطبین» مانند سایر همگام‌سازی‌ها است. برای کسب اطلاعات بیشتر درباره همگام‌سازی، بخش وفق‌دهنده‌های همگام‌سازی ارائه‌کننده مخاطبین را ببینید. ثبت اعلان‌ها و دعوت از مخاطبین در دو بخش بعدی پوشش داده شده است.

درحال ثبت برای رسیدگی به نماهای شبکه‌سازی اجتماعی

برای ثبت وفق‌دهنده همگام‌سازی‌تان جهت دریافت اعلان وقتی کاربر مخاطبی را که توسط وفق‌دهنده همگام‌سازی‌تان مدیریت می‌شود مشاهده می‌کند:

  1. فایلی با نام contacts.xml در فهرست راهنمای res/xml/ پروژه‌تان ایجاد کنید. اگر ازقبل این فایل را دارید، می‌توانید این مرحله را رد کنید.
  2. در این فایل، عنصر <ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"> را اضافه کنید. اگر این عنصر ازقبل وجود دارد، می‌توانید این مرحله را رد کنید.
  3. برای ثبت سرویسی که وقتی کاربر صفحه جزئیات مخاطبی را در برنامه مخاطبین دستگاه باز می‌کند مطلع می‌شود، مشخصه viewContactNotifyService="serviceclass" را به عنصر اضافه کنید، که در آن serviceclass نام کلاس کاملاً واجدشرایط سرویسی است که باید هدف را از برنامه مخاطبین دستگاه دریافت کند. برای سرویس اعلام‌کننده، از کلاسی استفاده کنید که IntentService را گسترش می‌دهد تا به سرویس اجازه دهد هدف‌ها را دریافت کند. داده‌های موجود در هدف ورودی حاوی شناسه منبع یکسان محتوای مخاطب خامی است که کاربر روی آن کلیک کرده است. از سرویس اطلاع‌رسان، می‌توانید به وفق‌دهنده همگام‌سازی‌تان متصل شوید و سپس آن را فراخوانی کنید تا داده‌های مخاطب خام را به‌روز کند.

برای ثبت فعالیتی که وقتی کاربر روی مورد جاری‌سازی یا عکس یا هر دو کلیک می‌کند فراخوانده شود:

  1. فایلی با نام contacts.xml در فهرست راهنمای res/xml/ پروژه‌تان ایجاد کنید. اگر ازقبل این فایل را دارید، می‌توانید این مرحله را رد کنید.
  2. در این فایل، عنصر <ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"> را اضافه کنید. اگر این عنصر ازقبل وجود دارد، می‌توانید این مرحله را رد کنید.
  3. برای ثبت یکی از فعالیت‌هایتان برای رسیدگی به کلیک کاربر روی مورد جاری‌سازی در برنامه مخاطبین دستگاه، ویژگی viewStreamItemActivity="activityclass" را به عنصر اضافه کنید، که در آن activityclass نام کلاس کاملاً واجدشرایط فعالیتی است که باید هدف را از برنامه مخاطبین دستگاه دریافت کند.
  4. برای ثبت یکی از فعالیت‌هایتان برای رسیدگی به کلیک کاربر روی عکس جاری در برنامه مخاطبین دستگاه، مشخصه viewStreamItemPhotoActivity="activityclass" را به عنصر اضافه کنید، که در آن activityclass نام کلاس کاملاً واجدشرایط فعالیتی است که باید هدف را از برنامه مخاطبین دستگاه دریافت کند.

عنصر <ContactsAccountType> با جزئیات بیشتر در بخش عنصر<ContactsAccountType> توضیح داده شده است.

هدف ورودی حاوی شناسه منبع یکسان محتوای مورد یا عکسی است که کاربر روی آن کلیک کرده است. برای داشتن فعالیت‌های جداگانه برای موارد نوشتاری و عکس‌ها، از هر دو مشخصه در یک فایل استفاده کنید.

تعامل با سرویس شبکه‌های اجتماعی شما

کاربران برای دعوت کردن مخاطب به سایت شبکه‌سازی اجتماعی شما، لازم نیست برنامه مخاطبین دستگاه را ترک کنند. درعوض، می‌توانید از برنامه مخاطبین دستگاه بخواهید قصدی برای دعوت کردن مخاطب به یکی از فعالیت‌هایتان ارسال کند. برای راه‌اندازی کردن این مورد:

  1. فایلی با نام contacts.xml در فهرست راهنمای res/xml/ پروژه‌تان ایجاد کنید. اگر ازقبل این فایل را دارید، می‌توانید این مرحله را رد کنید.
  2. در این فایل، عنصر <ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"> را اضافه کنید. اگر این عنصر ازقبل وجود دارد، می‌توانید این مرحله را رد کنید.
  3. مشخصه‌های زیر را اضافه کنید:
    • inviteContactActivity="activityclass"
    • inviteContactActionLabel="@string/invite_action_label"
    مقدار activityclass نام کلاس کاملاً واجدشرایط فعالیتی است که باید هدف را دریافت کند. مقدار invite_action_label رشته نوشتاری است که در منو افزودن اتصال در برنامه مخاطبین دستگاه نمایش داده می‌شود.

توجه: ContactsSource نام برچسب منسوخ‌شده‌ای برای ContactsAccountType است.

مرجع contacts.xml

فایل contacts.xml حاوی عناصر XML است که تعامل وفق‌دهنده همگام‌سازی و برنامه شما را با برنامه مخاطبین و «ارائه‌کننده مخاطبین» کنترل می‌کند. این عناصر در بخش‌های زیر شرح داده شده‌اند.

عنصر <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>

توضیح:

عناصر Android و برچسب‌های میانای کاربری را اعلام می‌کند که به کاربران اجازه می‌دهد یکی از مخاطبین خود را به شبکه اجتماعی دعوت کنند، وقتی یکی از جاری‌سازی‌های شبکه اجتماعی آن‌ها به‌روز می‌شود به کاربران اطلاع می‌دهد، و غیره.

توجه داشته باشید که پیشوند مشخصه android: برای مشخصه‌های <ContactsAccountType> ضروری نیست.

مشخصه‌ها:

inviteContactActivity
نام کلاس کاملاً واجدشرایط فعالیت در برنامه شما که می‌خواهید وقتی کاربر افزودن اتصال را از برنامه مخاطبین دستگاه انتخاب می‌کند، فعال شود.
inviteContactActionLabel
رشته نوشتاری که برای فعالیت مشخص‌شده در inviteContactActivity، در منو افزودن اتصال نمایش داده می‌شود. برای مثال، می‌توانید از رشته «دنبال کردن در شبکه من» استفاده کنید. می‌توانید از شناسه منبع رشته‌ای برای این برچسب استفاده کنید.
viewContactNotifyService
نام کلاس کاملاً واجدشرایط سرویسی در برنامه‌تان که باید وقتی کاربر مخاطبی را مشاهده می‌کند، اعلان دریافت کند. این اعلان توسط برنامه مخاطبین دستگاه ارسال می‌شود؛ این اعلان به برنامه شما اجازه می‌دهد عملیات‌های با حجم داده بالا را تا زمانی که نیاز باشد به‌تعویق بیندازد. برای مثال، برنامه شما می‌تواند با خواندن و نمایش عکس با وضوح بالای مخاطب و جدیدترین موارد جریان اجتماعی به این اعلان پاسخ دهد. این ویژگی با جزئیات بیشتر در بخش تعاملات جریان اجتماعی توضیح داده شده است.
viewGroupActivity
نام کلاس کاملاً واجدشرایط فعالیتی در برنامه شما که می‌تواند اطلاعات گروه را نمایش دهد. وقتی کاربر روی برچسب گروه در برنامه مخاطبین دستگاه کلیک می‌کند، واسط کاربر برای این فعالیت نمایش داده می‌شود.
viewGroupActionLabel
برچسبی که برنامه مخاطبین برای کنترل میانای کاربر نمایش می‌دهد که به کاربر اجازه می‌دهد گروه‌ها را در برنامه شما ببیند.

شناسه منبع رشته‌ای برای این مشخصه مجاز است.

viewStreamItemActivity
نام کلاس کاملاً واجدشرایط فعالیتی در برنامه شما که برنامه مخاطبین دستگاه وقتی کاربر روی مورد جاری برای مخاطب خام کلیک می‌کند، آن را راه‌اندازی می‌کند.
viewStreamItemPhotoActivity
نام کلاس کاملاً واجدشرایط فعالیتی در برنامه شما که برنامه مخاطبین دستگاه هنگام کلیک کردن کاربر روی عکسی در مورد جاری‌سازی برای مخاطب خام راه‌اندازی می‌کند.

عنصر <ContactsDataKind>

عنصر <ContactsDataKind> نمایش ردیف‌های داده سفارشی برنامه‌تان را در میانای کاربر برنامه مخاطبین کنترل می‌کند. نحو آن به‌صورت زیر است:

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

موجود در:

<ContactsAccountType>

توضیح:

از این عنصر استفاده کنید تا برنامه مخاطبین محتوای ردیف داده سفارشی را به‌عنوان بخشی از جزئیات مخاطب خام نمایش دهد. هر عنصر فرزند <ContactsDataKind> از <ContactsAccountType> نشان‌دهنده نوعی ردیف داده سفارشی است که وفق‌دهنده همگام‌سازی شما به جدول ContactsContract.Data اضافه می‌کند. برای هر نوع MIME سفارشی که استفاده می‌کنید، یک عنصر <ContactsDataKind> اضافه کنید. اگر ردیف داده سفارشی‌ای دارید که نمی‌خواهید داده‌های آن نمایش داده شود، لازم نیست عنصر را اضافه کنید.

مشخصه‌ها:

android:mimeType
نوع MIME سفارشی که برای یکی از انواع ردیف داده سفارشی‌تان در جدول ContactsContract.Data تعریف کرده‌اید. برای مثال، مقدار vnd.android.cursor.item/vnd.example.locationstatus می‌تواند نوع MIME سفارشی برای ردیف داده‌ای باشد که آخرین مکان شناخته‌شده مخاطب را ثبت می‌کند.
android:icon
منبع ترسیم‌شدنی Android که برنامه مخاطبین در کنار داده‌های شما نمایش می‌دهد. از این برای نشان دادن به کاربر استفاده کنید که داده‌ها از سرویس شما می‌آید.
android:summaryColumn
نام ستون برای اولین مقدار از دو مقدار بازیابی‌شده از ردیف داده. این مقدار به‌عنوان اولین خط ورودی برای این ردیف داده نمایش داده می‌شود. خط اول به‌عنوان خلاصه داده‌ها درنظر گرفته شده است، اما این اختیاری است. همچنین android:detailColumn را ببینید.
android:detailColumn
نام ستون برای دومین مقدار از دو مقدار بازیابی‌شده از ردیف داده. این مقدار به‌عنوان خط دوم ورودی برای این ردیف داده نمایش داده می‌شود. همچنین ببینید android:summaryColumn.

ویژگی‌های اضافی «ارائه‌کننده مخاطبین»

علاوه‌بر ویژگی‌های اصلی شرح‌داده‌شده در بخش‌های قبلی، «ارائه‌کننده مخاطبین» این ویژگی‌های مفید را برای کار با داده‌های مخاطبین ارائه می‌دهد:

  • گروه‌های مخاطبین
  • ویژگی‌های عکس

گروه‌های مخاطبین

«ارائه‌دهنده مخاطبین» می‌تواند به‌طور اختیاری مجموعه‌های مخاطبین مرتبط را با داده‌های گروه برچسب‌گذاری کند. اگر سرور مرتبط با حساب کاربری بخواهد گروه‌ها را حفظ کند، وفق‌دهنده همگام‌سازی برای نوع حساب آن حساب باید داده‌های گروه‌ها را بین «ارائه‌دهنده مخاطبین» و سرور منتقل کند. وقتی کاربران مخاطب جدیدی به سرور اضافه می‌کنند و سپس این مخاطب را در گروه جدیدی قرار می‌دهند، وفق‌دهنده همگام‌سازی باید گروه جدید را به جدول ContactsContract.Groups اضافه کند. گروه یا گروه‌هایی که مخاطب خام به آن‌ها تعلق دارد در جدول ContactsContract.Data بااستفاده از نوع MIME‏ ContactsContract.CommonDataKinds.GroupMembership ذخیره می‌شوند.

اگر درحال طراحی وفق‌دهنده همگام‌سازی هستید که داده‌های مخاطب خام را از سرور به «ارائه‌کننده مخاطبین» اضافه می‌کند و از گروه‌ها استفاده نمی‌کنید، باید به «ارائه‌کننده» بگویید داده‌هایتان را نمایان کند. در کدی که هنگام افزودن حساب به دستگاه توسط کاربر اجرا می‌شود، ردیف ContactsContract.Settings را که «ارائه‌دهنده مخاطبین» برای حساب اضافه می‌کند به‌روز کنید. در این ردیف، مقدار ستون Settings.UNGROUPED_VISIBLE را روی ۱ تنظیم کنید. وقتی این کار را انجام دهید، «ارائه‌دهنده مخاطبین» همیشه داده‌های مخاطبینتان را نمایان می‌کند، حتی اگر از گروه‌ها استفاده نکنید.

عکس‌های مخاطب

جدول 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 حاوی نمونه‌هایی از بازیابی اطلاعات عکس است. There is no convenience class for retrieving the primary thumbnail for a raw contact, but you can send a query to the ContactsContract.Data table, selecting on the raw contact's _ID, the Photo.CONTENT_ITEM_TYPE, and the IS_PRIMARY column to find the raw contact's primary photo row.

داده‌های جریان اجتماعی برای یک فرد ممکن است شامل عکس‌ها نیز باشد. این عکس‌ها در جدول android.provider.ContactsContract.StreamItemPhotos ذخیره می‌شوند که در بخش عکس‌های جریان اجتماعی با جزئیات بیشتری شرح داده شده است.