ارائه دهنده مخاطبین

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

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

  • ساختار اصلی ارائه دهنده
  • نحوه بازیابی اطلاعات از ارائه دهنده
  • نحوه تغییر داده ها در ارائه دهنده
  • چگونه یک آداپتور همگام سازی برای همگام سازی داده ها از سرور خود با ارائه دهنده مخاطبین بنویسید.

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

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

ارائه دهنده مخاطبین یک مؤلفه ارائه دهنده محتوای Android است. سه نوع داده در مورد یک شخص نگهداری می کند که هر کدام مطابق با جدول ارائه شده توسط ارائه دهنده است، همانطور که در شکل 1 نشان داده شده است:

شکل 1. ساختار جدول ارائه دهنده مخاطبین.

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

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

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

مخاطبین خام

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

بیشتر داده های یک مخاطب خام در جدول ContactsContract.RawContacts ذخیره نمی شود. در عوض، در یک یا چند ردیف در جدول 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 است. همیشه نوع حساب خود را با یک شناسه دامنه برای دامنه ای که مالک یا تحت کنترل خود هستید، واجد شرایط کنید. این اطمینان حاصل می کند که نوع حساب شما منحصر به فرد است. نوع حسابی که داده‌های مخاطبین را ارائه می‌کند معمولاً یک آداپتور همگام‌سازی مرتبط دارد که با ارائه‌دهنده مخاطبین همگام‌سازی می‌شود.
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@gmail.com
  • emilyd@gmail.com
  • حساب توییتر "belle_of_amherst"

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

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

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

  1. یک مخاطب خام برای "توماس هیگینسون" مرتبط با emily.dickinson@gmail.com . نوع حساب کاربری گوگل است.
  2. دومین تماس خام برای "توماس هیگینسون" مرتبط با emilyd@gmail.com . نوع حساب کاربری نیز گوگل است. یک مخاطب خام دوم وجود دارد حتی اگر نام آن با نام قبلی یکسان است، زیرا آن شخص برای یک حساب کاربری دیگر اضافه شده است.
  3. سومین تماس خام برای "توماس هیگینسون" مرتبط با "belle_of_amherst". نوع حساب کاربری توییتر است.

داده ها

همانطور که قبلاً ذکر شد، داده‌های یک مخاطب خام در ردیف ContactsContract.Data که به مقدار _ID مخاطب خام مرتبط است، ذخیره می‌شود. این به یک مخاطب خام اجازه می دهد تا چندین نمونه از یک نوع داده مانند آدرس ایمیل یا شماره تلفن داشته باشد. برای مثال، اگر «توماس هیگینسون» برای emilyd@gmail.com (ردیف تماس خام برای توماس هیگینسون مرتبط با حساب Google emilyd@gmail.com ) یک آدرس ایمیل خانه thigg@gmail.com و یک آدرس ایمیل کاری از thomas.higginson@gmail.com ، Contacts Provider دو ردیف آدرس ایمیل را ذخیره می کند و هر دو را به مخاطب خام پیوند می دهد.

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

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

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

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

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

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

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

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

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

برای تسهیل کار با ستون‌ها برای نوع خاصی از سطر، Contacts Provider همچنین ثابت‌های نام ستون نوع خاصی را ارائه می‌کند که در زیر کلاس‌های 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 سفارشی خود برای ردیف استفاده می‌کنید، می‌توانید نام ستون‌های نوع خاص خود را تعریف کنید و از ستون‌ها هر طور که می‌خواهید استفاده کنید.

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

نحوه نگاشت نام ستون های خاص نوع به نام ستون های عمومی

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

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

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

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

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

مخاطبین

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

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

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

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

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

شکل 3 نحوه ارتباط سه جدول اصلی را با یکدیگر نشان می دهد.

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

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

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

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

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

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

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

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

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

داده از آداپتورهای همگام سازی

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

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

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

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

اگر می خواهید داده های سرویس خود را به ارائه دهنده مخاطبین انتقال دهید، باید آداپتور همگام سازی خود را بنویسید. این با جزئیات بیشتر در بخش آداپتورهای همگام ارائه دهنده مخاطبین توضیح داده شده است.

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

جریان داده ها در مورد افراد

شکل 4. جریان داده های ارائه دهنده مخاطبین.

مجوزهای مورد نیاز

برنامه هایی که می خواهند به Contacts Provider دسترسی داشته باشند باید مجوزهای زیر را درخواست کنند:

خواندن دسترسی به یک یا چند جدول
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() را فراخوانی کنید. URI محتوا را روی CONTENT_URI تنظیم کنید و هیچ معیار انتخابی ارائه نکنید. همچنین می توانید از این URI محتوا به عنوان 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 ردیف را آزمایش کنید. اگر مخاطب نمایه کاربر باشد، این ستون روی "1" تنظیم می شود.

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

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

جدول 3. فراداده در ارائه دهنده مخاطبین

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

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

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

به طور خاص، شناسه منبع باید برای هر نوع حساب منحصر به فرد باشد و باید در تمام همگام‌سازی‌ها پایدار باشد:

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

دسترسی به ارائه دهنده مخاطبین

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

  • پرس و جوهای موجودیت
  • اصلاح دسته ای
  • بازیابی و اصلاح با مقاصد.
  • یکپارچگی داده ها

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

موجودیت های پرس و جو

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

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

موجودیت ها پرس و جوها را ساده می کنند. با استفاده از یک موجودیت، می‌توانید تمام داده‌های مخاطبین یک مخاطب یا مخاطب خام را به‌طور هم‌زمان بازیابی کنید، به‌جای اینکه مجبور شوید ابتدا جدول والد را برای دریافت شناسه جستجو کنید و سپس مجبور باشید جدول فرزند را با آن شناسه جستجو کنید. همچنین، Contacts Provider یک پرس و جو علیه یک موجودیت را در یک تراکنش پردازش می کند، که تضمین می کند داده های بازیابی شده در داخل سازگار هستند.

توجه: یک موجودیت معمولاً شامل تمام ستون‌های جدول والد و فرزند نیست. اگر سعی کنید با نام ستونی کار کنید که در لیست ثابت‌های نام ستون برای موجودیت نیست، یک 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() داده‌ها را در Contacts Provider در حالت دسته‌ای وارد، به‌روزرسانی و حذف کنید. از آنجایی که Contacts Provider تمام عملیات موجود در applyBatch() را در یک تراکنش انجام می دهد، تغییرات شما هرگز مخزن مخاطبین را در حالت ناسازگار باقی نمی گذارد. یک اصلاح دسته ای همچنین درج یک تماس خام و داده های جزئیات آن را به طور همزمان تسهیل می کند.

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

امتیاز بازده

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

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

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

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

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

متد withValueBackReference() دو آرگومان دارد:

key
کلید یک جفت کلید-مقدار. مقدار این آرگومان باید نام ستونی در جدولی باشد که در حال تغییر آن هستید.
previousResult
شاخص مبتنی بر 0 یک مقدار در آرایه اشیاء 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 تماس RAW را به همراه سایر داده هایی که بازیابی می کنید بازیابی کنید.
  2. با استفاده از روش newAssertQuery(Uri) یک شیء ContentProviderOperation.Builder مناسب برای اجرای یک محدودیت ایجاد کنید. برای محتوای URI ، از RawContacts.CONTENT_URI با مخاطب خام _ID که به آن اضافه شده است ، استفاده کنید.
  3. برای ContentProviderOperation.Builder Object ، با withValue() تماس بگیرید تا ستون VERSION را با شماره نسخه ای که تازه بازیابی کرده اید مقایسه کنید.
  4. برای همان ContentProviderOperation.Builder ، withExpectedCount() تماس بگیرید تا اطمینان حاصل شود که فقط یک ردیف توسط این ادعا آزمایش می شود.
  5. برای ایجاد شیء ContentProviderOperation build() تماس بگیرید ، سپس این شی را به عنوان اولین شیء در ArrayList که برای applyBatch() منتقل می کنید اضافه کنید.
  6. معامله دسته ای را اعمال کنید.

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

قطعه زیر نشان می دهد که چگونه می توان پس از پرس و جو برای یک تماس خام منفرد با استفاده از یک ContentProviderOperation CursorLoader "ادعا" را ایجاد کرد:

کاتلین

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

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

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

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

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

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

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

جدول 4. اهداف ارائه دهنده مخاطبین.

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

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

یک تماس خام جدید وارد کنید Insert.ACTION N/A RawContacts.CONTENT_TYPE ، نوع mime برای مجموعه ای از مخاطبین خام. صفحه مخاطب برنامه مخاطبین دستگاه را نمایش می دهد. مقادیر اضافی که به قصد اضافه می کنید نمایش داده می شود. در صورت ارسال با startActivityForResult() ، محتوای URI تماس خام تازه اضافه شده به روش onActivityResult() فعالیت شما در آرگومان Intent ، در قسمت "داده" منتقل می شود. برای به دست آوردن مقدار ، با getData() تماس بگیرید.
یک تماس را ویرایش کنید ACTION_EDIT CONTENT_LOOKUP_URI برای مخاطب. فعالیت ویرایشگر به کاربر امکان می دهد هر یک از داده های مرتبط با این مخاطب را ویرایش کند. Contacts.CONTENT_ITEM_TYPE ، یک مخاطب واحد. صفحه تماس ویرایش را در برنامه مخاطبین نمایش می دهد. مقادیر اضافی که به قصد اضافه می کنید نمایش داده می شود. هنگامی که کاربر برای ذخیره ویرایش ها کلیک می کند ، فعالیت شما به پیش زمینه باز می گردد.
یک انتخاب کننده را نمایش دهید که می تواند داده ها را نیز اضافه کند. ACTION_INSERT_OR_EDIT N/A 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.CommonDataKinds.StructuredName برای هر ContactsContract.RawContacts اضافه کنید. ردیف rawcontacts که اضافه می کنید.
یک ردیف ContactsContract.RawContacts بدون ContactsContract.Data ContactsContract.CommonDataKinds.StructuredName .
همیشه ردیف های جدید ContactsContract.Data را به ردیف ContactsContract.RawContacts پدر و مادر خود پیوند دهید.
یک ردیف ContactsContract.Data که به یک ContactsContract.RawContacts در برنامه مخاطبین دستگاه قابل مشاهده نخواهد بود ، و ممکن است باعث ایجاد مشکل در آداپتورهای همگام سازی شود.
داده ها را فقط برای آن دسته از مخاطبین خام که در اختیار دارید تغییر دهید.
به یاد داشته باشید که ارائه دهنده مخاطبین معمولاً داده ها را از چندین نوع حساب/خدمات آنلاین مختلف مدیریت می کند. شما باید اطمینان حاصل کنید که برنامه شما فقط داده ها را برای ردیف هایی که متعلق به شما هستند اصلاح یا حذف می کند ، و این فقط داده ها را با نوع و نامی که کنترل می کنید درج می کند.
همیشه از ثابت های تعریف شده در ContactsContract و زیر کلاس های آن برای مقامات ، محتوای URIS ، مسیرهای URI ، نام ستون ، انواع تقلید و مقادیر TYPE استفاده کنید.
استفاده از این ثابت ها به شما کمک می کند تا از خطاها جلوگیری کنید. در صورت کاهش هر یک از ثابت ها ، با هشدارهای کامپایلر نیز به شما اطلاع داده می شود.

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

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

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

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

آداپتورهای همگام سازی ارائه دهنده مخاطبین

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

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

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

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

کلاس ها و پرونده های آداپتور همگام سازی

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

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

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

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

اگر این سرویس اعتبار را بپذیرد ، تأیید کننده می تواند اعتبار لازم را برای استفاده بعدی ذخیره کند. به دلیل چارچوب تأیید اعتبار ، AccountManager می تواند دسترسی به هرگونه AuthTokens را که یک تأیید کننده از آن پشتیبانی و انتخاب می کند ، مانند Authtokens OAuth2 پشتیبانی و انتخاب کند.

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

اجرای آداپتور همگام سازی

برای اجرای یک آداپتور همگام سازی برای ارائه دهنده مخاطبین ، شما با ایجاد یک برنامه Android که شامل موارد زیر است ، شروع می کنید:

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

داده های جریان اجتماعی

Android.Provider.ContactsContract.StreamItems و Android.Provider.ContactsContract.StreamItemphotos داده های ورودی را از شبکه های اجتماعی مدیریت می کنند. می توانید یک آداپتور همگام سازی بنویسید که داده های جریان را از شبکه خود به این جداول اضافه می کند ، یا می توانید داده های جریان را از این جداول بخوانید و آن را در برنامه شخصی خود یا هر دو نمایش دهید. با استفاده از این ویژگی ها ، خدمات و برنامه های شبکه های اجتماعی شما می توانند در تجربه شبکه های اجتماعی اندروید ادغام شوند.

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

موارد جریان همیشه با تماس خام همراه است. android.provider.contactscontract.streamitemscolumns#links raw_contact_id به مقدار _ID برای تماس خام. نوع حساب و نام حساب تماس RAW نیز در ردیف Stream Attment ذخیره می شود.

داده ها را از جریان خود در ستون های زیر ذخیره کنید:

Android.provider.ContactsContract.StreamItemscolumns#Account_Type
مورد نیاز. نوع حساب کاربر برای تماس خام مرتبط با این مورد جریان. به یاد داشته باشید وقتی یک مورد جریان را وارد می کنید ، این مقدار را تنظیم کنید.
android.provider.contactscontract.streamitemscolumns#حساب_Name
مورد نیاز. نام حساب کاربر برای تماس خام مرتبط با این مورد جریان. به یاد داشته باشید وقتی یک مورد جریان را وارد می کنید ، این مقدار را تنظیم کنید.
ستونهای شناسه
مورد نیاز. هنگام وارد کردن یک مورد جریان ، باید ستون های شناسه زیر را وارد کنید:
  • android.provider.contactscontract.streamitemscolumns#contact_id: android.provider.basecolumns#_id مقدار مخاطب که این مورد جریان با آن همراه است.
  • android.provider.contactscontract.streamitemscolumns#contact_lookup_key: android.provider.contactscontract.contactscolumns#مقدار جستجو_ کلید تماس با این مورد جریان با آن همراه است.
  • android.provider.contactscontract.streamitemscolumns#raw_contact_id: android.provider.basecolumns#_id مقدار تماس خام که این مورد جریان با آن همراه است.
android.provider.contactscontract.streamitemscolumns#نظرات
اختیاری. اطلاعات خلاصه ای را که می توانید در ابتدای یک مورد جریان نمایش دهید ، ذخیره کنید.
android.provider.contactscontract.streamitemscolumns#متن
متن مورد جریان ، یا محتوایی که توسط منبع مورد ارسال شده است ، یا توضیحی از برخی اقدامات که باعث ایجاد مورد جریان می شود. این ستون می تواند حاوی هر قالب بندی و تصاویر منبع تعبیه شده باشد که توسط fromHtml() ارائه می شود. ارائه دهنده ممکن است محتوای طولانی را کوتاه یا بیضی کند ، اما سعی خواهد کرد از شکستن برچسب ها جلوگیری کند.
android.provider.contactscontract.streamitemscolumns#timestamp
یک رشته متنی که شامل زمان درج یا به روزرسانی کالای جریان است ، در قالب میلی ثانیه از زمان EPOCH. برنامه هایی که موارد جریان را وارد یا به روز می کنند ، وظیفه حفظ این ستون را بر عهده دارند. به طور خودکار توسط ارائه دهنده مخاطبین نگهداری نمی شود.

برای نمایش اطلاعات برای موارد جریان خود ، از android.provider.contactscontract.streamitemscolumns#res_icon ، android.provider.contactscontract.streamitemscolumns#res_label و android.contactscontract.streamitetemscolumns#res_package به شما استفاده کنید.

جدول Android.Provider.ContactsContract.StreamItems همچنین شامل ستون های Android.provider.contactscontract.streamitemscolumns#sync1 از طریق Android.contactscontract.streamitemscolumns#sync4 برای استفاده منحصر به فرد از آداپتورهای همگام سازی است.

عکس های جریان اجتماعی

Android.Provider.ContactsContract.StreamItemphotos Table عکس های مرتبط با یک مورد جریان را ذخیره می کند. Android.provider.ContactsContract.StreamItemphotoscolumns#stream_item_id پیوند ستون به مقادیر موجود در ستون _ID android.provider.contactscontract.streamitems. منابع عکس در این ستون در جدول ذخیره می شوند:

android.provider.contactscontract.streamitemphotos#ستون عکس (یک حباب).
بازنمایی باینری از عکس ، که توسط ارائه دهنده برای ذخیره سازی و نمایش تغییر یافته است. این ستون برای سازگاری به عقب با نسخه های قبلی ارائه دهنده مخاطبین که از آن برای ذخیره عکس استفاده کرده است ، در دسترس است. با این حال ، در نسخه فعلی شما نباید از این ستون برای ذخیره عکس استفاده کنید. در عوض ، از android.provider.contactscontract.streamitemphotoscolumns#photo_file_id یا android.provider.contactscontract.streamitemphotoscolumns#photo_uri استفاده کنید (که هر دو در نقاط زیر توضیح داده شده است) برای ذخیره عکس ها در یک پرونده استفاده کنید. این ستون اکنون حاوی تصویر کوچک عکس است که برای خواندن در دسترس است.
android.provider.contactscontract.streamitemphotoscolumns#photo_file_id
شناسه عددی یک عکس برای تماس خام. این مقدار را به DisplayPhoto.CONTENT_URI ثابت اضافه کنید تا یک URI محتوا با اشاره به یک فایل عکس واحد دریافت کنید ، و سپس با openAssetFileDescriptor() تماس بگیرید تا یک دسته به پرونده عکس بگیرید.
android.provider.contactscontract.streamitemphotoscolumns#photo_uri
URI محتوا که مستقیماً به پرونده عکس برای عکس نشان داده شده توسط این ردیف اشاره می کند. با این URI با openAssetFileDescriptor() تماس بگیرید تا یک دسته از پرونده عکس بگیرید.

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

این جداول مانند سایر جداول اصلی در ارائه دهنده مخاطبین کار می کنند ، به جز این:

  • این جداول نیاز به مجوزهای دسترسی اضافی دارند. برای خواندن از آنها ، برنامه شما باید دارای مجوز 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 حاوی ردیف های عکس برای یک مورد واحد را تعریف می کند.

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

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

  • با همگام سازی سرویس شبکه های اجتماعی خود با ارائه دهنده مخاطبین با یک آداپتور همگام سازی ، می توانید فعالیت های اخیر را برای مخاطبین کاربر بازیابی کرده و آن را در 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 نام کلاس کاملاً واجد شرایط از سرویس است که باید از این طریق دریافت کند. برنامه مخاطبین دستگاه. برای سرویس Notifier ، از کلاس استفاده کنید که IntentService گسترش می دهد ، برای دریافت خدمات به این سرویس اجازه دهید. داده های موجود در هدف ورودی شامل محتوای URI از تماس خام است که کاربر کلیک کرده است. از سرویس Notifier ، می توانید به آداپتور همگام سازی خود متصل شوید و با آداپتور همگام سازی خود تماس بگیرید تا داده ها را برای تماس خام به روز کنید.

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

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

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

هدف ورودی حاوی محتوای URI مورد یا عکسی است که کاربر روی آن کلیک کرده است. برای داشتن فعالیت های جداگانه برای موارد متنی و برای عکس ، از هر دو ویژگی در یک پرونده استفاده کنید.

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

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

  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 مرجع

file 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>

توضیحات:

مؤلفه های اندرویدی و برچسب های UI را اعلام می کند که به کاربران امکان می دهد یکی از مخاطبین خود را به یک شبکه اجتماعی دعوت کنند ، هنگامی که یکی از جریان های شبکه های اجتماعی آنها به روز می شود و غیره ، به کاربران اطلاع می دهد.

توجه داشته باشید که پیشوند ویژگی android: برای ویژگی های <ContactsAccountType> ضروری نیست.

ویژگی ها:

inviteContactActivity
نام کلاس کاملاً واجد شرایط فعالیت در برنامه شما که می خواهید هنگام انتخاب کاربر ، اتصال ADD را از برنامه مخاطبین دستگاه انتخاب کنید.
inviteContactActionLabel
یک رشته متنی که برای فعالیت مشخص شده در inviteContactActivity ، در منوی Add Connection نمایش داده می شود. به عنوان مثال ، می توانید از رشته "دنبال در شبکه من" استفاده کنید. برای این برچسب می توانید از یک شناسه منبع رشته استفاده کنید.
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>

توضیحات:

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

ویژگی ها:

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

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

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

  • گروه های تماس
  • ویژگی های عکس

گروه های تماس

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

If you're designing a sync adapter that will add raw contact data from server to the Contacts Provider, and you aren't using groups, then you need to tell the Provider to make your data visible. In the code that is executed when a user adds an account to the device, update the ContactsContract.Settings row that the Contacts Provider adds for the account. In this row, set the value of the Settings.UNGROUPED_VISIBLE column to 1. When you do this, the Contacts Provider will always make your contacts data visible, even if you don't use groups.

Contact photos

The ContactsContract.Data table stores photos as rows with MIME type Photo.CONTENT_ITEM_TYPE . The row's CONTACT_ID column is linked to the _ID column of the raw contact to which it belongs. The class ContactsContract.Contacts.Photo defines a sub-table of ContactsContract.Contacts containing photo information for a contact's primary photo, which is the primary photo of the contact's primary raw contact. Similarly, the class ContactsContract.RawContacts.DisplayPhoto defines a sub-table of ContactsContract.RawContacts containing photo information for a raw contact's primary photo.

The reference documentation for ContactsContract.Contacts.Photo and ContactsContract.RawContacts.DisplayPhoto contain examples of retrieving photo information. 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.

Social stream data for a person may also include photos. These are stored in the android.provider.ContactsContract.StreamItemPhotos table, which is described in more detail in the section Social stream photos .