مقدم جهات الاتصال هو مكون Android قوي ومرن يدير هو المستودع المركزي للبيانات حول الأشخاص. موفِّر جهات الاتصال هو مصدر البيانات التي تظهر في تطبيق جهات الاتصال في الجهاز، كما يمكنك أيضًا الدخول إلى بياناته في التطبيق ونقل البيانات بين الجهاز والخدمات على الإنترنت. يتعامل مقدّم الخدمة مع مجموعة كبيرة من مصادر البيانات ويحاول إدارة أكبر قدر ممكن من البيانات لكل شخص، مما يؤدي بدوره إلى كون تنظيمه معقدًا. ولهذا السبب، تتضمن واجهة برمجة التطبيقات الخاصة بالموفر مجموعة واسعة من فئات وواجهات العقود التي تسهل كل من استرجاع البيانات التعديل.
يوضّح هذا الدليل ما يلي:
- بنية مقدّم الخدمة الأساسية
- كيفية استرداد البيانات من مقدّم الخدمة
- كيفية تعديل البيانات في مقدّم الخدمة
- كيفية كتابة محول مزامنة لمزامنة البيانات من الخادم إلى جهات الاتصال
يفترض هذا الدليل أنّك على دراية بأساسيات موفّري محتوى Android. لمزيد من المعلومات عن موفّري محتوى Android، يُرجى الاطّلاع على دليل أساسيات موفّري المحتوى.
مؤسسة مقدّم جهات الاتصال
"موفِّر جهات الاتصال" هو مكوّن لموفِّر محتوى Android. وهي تحافظ على ثلاثة أنواع من بيانات حول شخص ما، يتوافق كل منها مع جدول يقدمه المزود، حيث كما هو موضح في الشكل 1:

الشكل 1. بنية جدول "مزوِّد جهات الاتصال"
يُشار إلى الجداول الثلاثة عادةً بأسماء فئات العقود. الصفوف تحديد الثوابت لمعرّفات الموارد المنتظمة (URI) للمحتوى وأسماء الأعمدة وقيم الأعمدة التي تستخدمها الجداول:
-
جدول
ContactsContract.Contacts
- صفوف تمثل أشخاصًا مختلفين استنادًا إلى تجميعات صفوف جهات الاتصال الأولية.
-
جدول
ContactsContract.RawContacts
- الصفوف التي تحتوي على ملخّص لبيانات شخص معيّن، خاصة بحساب مستخدم ونوعه
-
جدول
ContactsContract.Data
- الصفوف التي تحتوي على تفاصيل جهة الاتصال الأوّلية، مثل عناوين البريد الإلكتروني أو أرقام الهواتف
أما الجداول الأخرى التي تمثّلها فئات العقود في ContactsContract
فهي جداول مساعدة يستخدمها مقدّم جهات الاتصال لإدارة عملياته أو إتاحة
وظائف معيّنة في تطبيقات جهات الاتصال أو تطبيقات الاتصال الهاتفي على الجهاز.
جهات الاتصال الأولية
تمثل جهة الاتصال الأولية بيانات شخص واردة من نوع حساب واحد وحساب واحد. الاسم. بما أنّ "مزوّد جهات الاتصال" يسمح بأكثر من خدمة واحدة على الإنترنت كمصدر لبيانات المستخدم، يسمح "مزوّد جهات الاتصال" بعدة جهات اتصال أولية للمستخدم نفسه. تسمح جهات الاتصال الأوّلية المتعددة للمستخدم أيضًا بدمج بيانات شخص من أكثر من حساب واحد من نوع الحساب نفسه.
لا يتم تخزين معظم بيانات جهة الاتصال الأوّلية في جدول
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
- حساب Twitter "belle_of_amherst"
فعّل هذا المستخدم مزامنة جهات الاتصال لجميع هذه الحسابات الثلاثة في الحسابات.
لنفترض أن إميلي ديكنسون فتحت نافذة متصفح، وسجلت الدخول إلى Gmail
emily.dickinson@gmail.com
، يفتح
جهات الاتصال، وإضافة "توماس هيغينسون". في وقت لاحق، سجّلت مها الدخول إلى Gmail باستخدام حساب
emilyd@gmail.com
وأرسلت رسالة إلكترونية إلى "توماس هيغينز"، ما أدّى إلى
إضافته تلقائيًا كجهة اتصال. وتتابع أيضًا "colonel_tom" (معرّف Thomas Higginson على Twitter) على
Twitter.
ويقوم موفر جهات الاتصال بإنشاء ثلاث جهات اتصال أولية كنتيجة لهذا العمل:
-
جهة اتصال أولية لـ "توماس هيغينزون" مرتبطة بـ
emily.dickinson@gmail.com
إنّ نوع حساب المستخدم هو Google. -
جهة اتصال أساسية ثانية لـ "توماس هيغينزون" مرتبطة بـ
emilyd@gmail.com
ونوع حساب المستخدم هو أيضًا Google. هناك جهة اتصال أولية ثانية حتى على الرغم من أن الاسم مطابق للاسم السابق، لأنه تمت إضافة هذا الشخص حساب مستخدم مختلف. - جهة اتصال أوّلية ثالثة للمغنّي "توماس هيغنسون" المرتبطة بـ "belle_of_amherst". المستخدِم هو Twitter.
البيانات
كما أشرنا سابقًا، يتم تخزين البيانات لجهة اتصال أولية في
صف ContactsContract.Data
المرتبط بجهة الاتصال الأولية
_ID
. يسمح هذا الإجراء لجهة اتصال أولية واحدة بالحصول على مثيلات متعددة من نفس
نوع البيانات مثل عناوين البريد الإلكتروني أو أرقام الهواتف. على سبيل المثال، إذا
"توماس هيجينسون" لـ emilyd@gmail.com
(صف جهة الاتصال الأولية لتوماس هيغنسون
المرتبط بحساب 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
على قيمة غير صفرية.
أسماء الأعمدة العامة
هناك 15 عمودًا عامًا يحمل أسماء DATA1
إلى
DATA15
وهي متاحة بشكل عام، وأربعة أعمدة إضافية
عامة من SYNC1
إلى SYNC4
لا يُفترض أن تستخدمها سوى محولات
المزامنة. تعمل ثوابت أسماء العمود العامة دائمًا، بغض النظر عن نوع
البيانات التي يحتوي عليها الصف.
تم فهرسة عمود DATA1
. يستخدم موفر جهات الاتصال هذا العمود دائمًا
البيانات التي يتوقعها المزود ستكون الهدف الأكثر تكرارًا لأي طلب. على سبيل المثال:
في صف بريد إلكتروني، يحتوي هذا العمود على عنوان البريد الإلكتروني الفعلي.
وفقًا للعرف، يتم حجز العمود DATA15
لتخزين بيانات Binary Large Object
(BLOB) مثل الصور المصغّرة.
أسماء الأعمدة الخاصة بالنوع
لتسهيل العمل على الأعمدة الخاصة بنوع معين من الصفوف، يستخدم مقدم جهات الاتصال
كما توفر ثوابت أسماء الأعمدة الخاصة بنوع محدّد، ويتم تحديدها في الفئات الفرعية
ContactsContract.CommonDataKinds
تعطي الثوابت ببساطة
اسم ثابت مختلف إلى نفس اسم العمود، مما يساعدك في الوصول إلى البيانات في صف من
لنوع معين.
على سبيل المثال، تُحدّد الفئة ContactsContract.CommonDataKinds.Email
ثوابت أسماء الأعمدة الخاصة بالنوع للصف ContactsContract.Data
لديه نوع MIME
Email.CONTENT_ITEM_TYPE
تحتوي الفئة على الثابت
ADDRESS
لعنوان البريد الإلكتروني
. تُعد القيمة الفعلية
ADDRESS
هي "data1"،
نفس الاسم العام للعمود.
تنبيه: يجب عدم إضافة بياناتك المخصّصة إلى
ContactsContract.Data
باستخدام صف يحتوي على أحد
أنواع MIME المحدّدة مسبقًا لموفّر الخدمة. وفي هذه الحالة، قد تفقد البيانات أو تتسبّب في تعطُّل مقدّم الخدمة. على سبيل المثال، يجب عدم إضافة صفّ بنوع MIME
Email.CONTENT_ITEM_TYPE
يحتوي على اسم مستخدم بدلاً من عنوان بريد إلكتروني في عمود
DATA1
. إذا كنت تستخدم نوع MIME مخصصًا للصف، لا يمكنك اتخاذ هذا الإجراء
لتحديد أسماء الأعمدة الخاصة بالنوع واستخدام الأعمدة بالطريقة التي تريدها.
يوضح الشكل 2 كيف تظهر الأعمدة الوصفية وأعمدة البيانات في
ContactsContract.Data
، وكيف تتم "تراكب" أسماء الأعمدة الخاصة بنوع محدّد
أسماء الأعمدة العامة

الشكل 2. أسماء الأعمدة الخاصة بالنوع وأسماء الأعمدة العامة
فئات أسماء الأعمدة الخاصة بالنوع
يسرد الجدول 2 فئات أسماء الأعمدة الأكثر استخدامًا حسب النوع:
الجدول 2. فئات أسماء الأعمدة الخاصة بالنوع
فئة الربط | نوع البيانات | ملاحظات |
---|---|---|
ContactsContract.CommonDataKinds.StructuredName |
بيانات الاسم لجهة الاتصال الأولية المرتبطة بصف البيانات هذا. | تحتوي جهة الاتصال الأوّلية على صف واحد فقط من هذه الصفوف. |
ContactsContract.CommonDataKinds.Photo |
الصورة الرئيسية لجهة الاتصال الأوّلية المرتبطة بهذا صف البيانات. | تحتوي جهة الاتصال الأولية على صف واحد فقط من هذه الصفوف. |
ContactsContract.CommonDataKinds.Email |
عنوان البريد الإلكتروني لجهة الاتصال الأولية المرتبطة بصف البيانات هذا. | يمكن أن تحتوي جهة الاتصال الأولية على عناوين بريد إلكتروني متعددة. |
ContactsContract.CommonDataKinds.StructuredPostal |
عنوان بريدي لجهة الاتصال الأولية المرتبطة بصف البيانات هذا. | يمكن أن تحتوي جهة الاتصال الأولية على عناوين بريدية متعددة. |
ContactsContract.CommonDataKinds.GroupMembership |
معرّف يربط جهة الاتصال الأوّلية بإحدى المجموعات في موفِّر جهات الاتصال | "المجموعات" هي ميزة اختيارية لنوع الحساب واسمه. ويمكنك الاطّلاع على مزيد من التفاصيل في القسم مجموعات جهات الاتصال. |
جهات الاتصال
يدمج "مقدِّم جهات الاتصال" صفوف جهات الاتصال الأولية على مستوى جميع أنواع الحسابات وأسماء الحسابات. لإنشاء جهة اتصال. ويسهل هذا عرض وتعديل جميع البيانات جمعها المستخدم لشخص ما. يدير مقدّم جهات الاتصال إنشاء صفوف جهات اتصال جديدة وتجميع جهات الاتصال الأوّلية مع صف جهة اتصال حالي. لا تطبيقات ولا يُسمح لمحوّلات المزامنة بإضافة جهات اتصال، كما أنّ بعض الأعمدة في صف جهة الاتصال تكون للقراءة فقط.
ملاحظة: إذا حاولت إضافة جهة اتصال إلى موفِّر جهات الاتصال باستخدام
insert()
، ستتلقّى
UnsupportedOperationException
استثناءً. إذا حاولت تعديل عمود
مدرَج على أنّه "للقراءة فقط"، سيتم تجاهل التعديل.
ينشئ موفِّر جهات الاتصال جهة اتصال جديدة استجابةً لإضافة جهة اتصال أولية جديدة لا يطابق أي جهات اتصال حالية. وينفّذ مقدّم الخدمة ذلك أيضًا إذا تغيّرت بيانات جهة اتصال أساسية حالية بطريقة تجعلها لا تتطابق مع جهة الاتصال التي كانت مرتبطة بها في السابق. إذا أنشأ تطبيق أو محوّل مزامنة بيانات جهة اتصال أولية جديدة تتطابق مع جهة اتصال حالية، فسيتم تجميع جهة الاتصال الأولية الجديدة مع جهة الاتصال الحالية جهة اتصال.
يربط مقدّم جهات الاتصال صف جهة اتصال بصفوف جهات الاتصال الأوّلية باستخدام عمود
_ID
في صف جهة الاتصال في جدول Contacts
. يحتوي عمود CONTACT_ID
في جدول ContactsContract.RawContacts
للجهات الاتّصال الأوّلية على قيم _ID
لصف ContactsContract.RawContacts
المرتبط بكل صف من صفوف ContactsContract.RawContacts
الأوّلية.
يحتوي جدول ContactsContract.Contacts
أيضًا على العمود
LOOKUP_KEY
الذي يمثّل
رابطًا "دائمًا" بصف جهة الاتصال. لأنّ "مقدِّم جهات الاتصال" يحافظ على جهات الاتصال
تلقائيًا، قد يغيّر قيمة _ID
لصف جهة اتصال
استجابةً لعملية تجميع أو مزامنة. حتى في حال حدوث ذلك، سيظلّ عنوان URL للمحتوى
CONTENT_LOOKUP_URI
مع
LOOKUP_KEY
جهة الاتصال يشيران
إلى صف جهة الاتصال، لذا يمكنك استخدام
LOOKUP_KEY
للاحتفاظ بالروابط التي تؤدي إلى جهات الاتصال "المفضّلة" وما إلى ذلك. يحتوي هذا العمود على تنسيق خاص به
لا علاقة له بتنسيق عمود _ID
.
يوضّح الشكل 3 كيفية ارتباط الجداول الرئيسية الثلاثة ببعضها.

الشكل 3: علاقات جدول جهات الاتصال وجهات الاتصال الأولية والتفاصيل.
تنبيه: إذا نشرت تطبيقك على "متجر Google Play" أو إذا كان التطبيق على جهاز يعمل بنظام التشغيل Android 10 (المستوى 29 من واجهة برمجة التطبيقات) أو إصدار أحدث، يُرجى ملاحظة: أن مجموعة محدودة من حقول وطرق بيانات جهات الاتصال أصبحت قديمة.
وفقًا للشروط المذكورة، يمحو النظام أي قيم بشكل دوري. كتابتها في حقول البيانات هذه:
-
ContactsContract.ContactOptionsColumns.LAST_TIME_CONTACTED
-
ContactsContract.ContactOptionsColumns.TIMES_CONTACTED
-
ContactsContract.DataUsageStatColumns.LAST_TIME_USED
-
ContactsContract.DataUsageStatColumns.TIMES_USED
واجهات برمجة التطبيقات المستخدمة لضبط حقول البيانات أعلاه قديمة أيضًا:
بالإضافة إلى ذلك، لن تعرض الحقول التالية جهات الاتصال المتكررة. ملاحظة أن بعض هذه الحقول لا تؤثر إلا في ترتيب جهات الاتصال جهات الاتصال هي جزء من عملية البيانات النوع.
-
ContactsContract.Contacts.CONTENT_FREQUENT_URI
-
ContactsContract.Contacts.CONTENT_STREQUENT_URI
-
ContactsContract.Contacts.CONTENT_STREQUENT_FILTER_URI
-
CONTENT_FILTER_URI
(يؤثر فقط البريد الإلكتروني، هاتف، قابل للاتصال، أو معلومات التواصل أنواع البيانات) -
ENTERPRISE_CONTENT_FILTER_URI
(يؤثر فقط البريد الإلكتروني، هاتف، أو قابل للاتصال أنواع البيانات)
إذا كانت تطبيقاتك تحصل على هذه الحقول أو واجهات برمجة التطبيقات أو تعدّلها، استخدِم methodsبديلة. على سبيل المثال، يمكنك استيفاء بعض حالات الاستخدام باستخدام خاصة موفّرو المحتوى أو البيانات الأخرى المخزّنة داخل تطبيقك أو الخلفية والأنظمة المختلفة.
للتأكّد من أنّ وظيفة تطبيقك لم تتأثّر بهذا التغيير، يمكنك محو حقول البيانات هذه يدويًا. لتنفيذ ذلك، شغِّل الأمر التالي لـ ADB على جهاز يعمل بالإصدار 4.1 من نظام التشغيل Android (المستوى 16 من واجهة برمجة التطبيقات) أو إصدار أحدث:
adb shell content delete \ --uri content://com.android.contacts/contacts/delete_usage
البيانات من محوِّلات المزامنة
يُدخل المستخدمون بيانات جهات الاتصال مباشرةً في الجهاز، ولكن تتدفق البيانات أيضًا إلى جهات الاتصال
مزوّد من خدمات الويب عبر محوّلات المزامنة، التي تعمل تلقائيًا
لنقل البيانات بين الجهاز والخدمات. يتم تشغيل محولات المزامنة في الخلفية
تحت سيطرة النظام، وهي تستدعي طرق ContentResolver
لإدارة البيانات.
في Android، يتم تحديد خدمة الويب التي يعمل معها محوِّل المزامنة حسب نوع الحساب. يعمل كل محوِّل مزامنة مع نوع حساب واحد، ولكن يمكن أن يتيح أسماء حسابات متعددة لهذا النوع. يتم وصف أنواع الحسابات وأسماء الحسابات بشكل مختصر في القسم مصادر بيانات جهات الاتصال الأوّلية. تقدم التعريفات التالية على مزيد من التفاصيل، ووصف كيفية ارتباط نوع الحساب واسمه بمحوّلات وخدمات المزامنة.
- نوع الحساب
-
يحدِّد الخدمة التي تخزّن بيانات المستخدم. في معظم الأحيان، على المستخدم
المصادقة مع الخدمة. على سبيل المثال، جهات اتصال Google هي نوع حساب، يتم تحديده
بواسطة الرمز
google.com
. تتوافق هذه القيمة مع نوع الحساب الذي يستخدمهAccountManager
- اسم الحساب
- يحدّد حسابًا معيّنًا أو معلومات تسجيل الدخول لنوع حساب معيّن. حسابات "جهات اتصال Google" تتشابه مع حسابات Google، والتي يكون لها عنوان بريد إلكتروني كاسم للحساب. قد تستخدم الخدمات الأخرى اسم مستخدم مكوّنًا من كلمة واحدة أو معرّفًا رقميًا.
ولا يُشترط أن تكون أنواع الحسابات فريدة. يمكن للمستخدم ضبط حسابات متعدّدة في "جهات اتصال Google" وتنزيل بياناتهم إلى "مقدِّم جهات الاتصال" وقد يحدث هذا إذا كان المستخدم لديه مجموعة واحدة من جهات الاتصال الشخصية لاسم حساب شخصي، ومجموعة أخرى للعمل. تكون أسماء الحسابات عادةً فريدة. وتحدد معًا تدفق بيانات معينًا بين مقدم جهات الاتصال أو خدمة خارجية.
إذا أردت نقل بيانات خدمتك إلى "مقدِّم جهات الاتصال"، عليك كتابة محوّل المزامنة الخاص. ويتم وصف ذلك بمزيد من التفصيل في القسم محوِّلات مزامنة موفّري جهات الاتصال.
يوضّح الشكل 4 كيفية ملاءمة "مقدِّم جهات الاتصال" لتدفق البيانات في الأشخاص. في المربّع الذي يحمل العنوان "محوِّلات المزامنة"، يتم تصنيف كل محوِّل حسب نوع حسابه.

الشكل 4. تدفّق البيانات في "مقدّم جهات الاتصال"
الأذونات المطلوبة
على التطبيقات التي تريد الوصول إلى موفِّر جهات الاتصال طلب الأذونات التالية:
- إذن بالقراءة إلى جدول واحد أو أكثر
-
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
ولا تقدِّم أي
معيار اختيار. يمكنك أيضًا استخدام معرّف الموارد المنتظم للمحتوى هذا كمعرّف الموارد المنتظم الأساسي لاسترداد ملف التعريف أو بياناته
الأوّلية. على سبيل المثال، يسترجع هذا المقتطف بيانات الملف الشخصي:
Kotlin
// Sets the columns to retrieve for the user profile projection = arrayOf( ContactsContract.Profile._ID, ContactsContract.Profile.DISPLAY_NAME_PRIMARY, ContactsContract.Profile.LOOKUP_KEY, ContactsContract.Profile.PHOTO_THUMBNAIL_URI ) // Retrieves the profile from the Contacts Provider profileCursor = contentResolver.query( ContactsContract.Profile.CONTENT_URI, projection, null, null, null )
Java
// Sets the columns to retrieve for the user profile projection = new String[] { Profile._ID, Profile.DISPLAY_NAME_PRIMARY, Profile.LOOKUP_KEY, Profile.PHOTO_THUMBNAIL_URI }; // Retrieves the profile from the Contacts Provider profileCursor = getContentResolver().query( Profile.CONTENT_URI, projection , null, null, null);
ملاحظة: في حال استرداد صفوف متعدّدة لجهات الاتصال، وأردت تحديد ما إذا كان أحدها
هو ملف تعريف المستخدم، فاختبر الصف
عمود "IS_USER_PROFILE
". هذا العمود
تم الضبط على "1" إذا كانت جهة الاتصال هي الملف الشخصي للمستخدم
البيانات الوصفية لموفِّر جهات الاتصال
يدير مقدّم جهات الاتصال البيانات التي تتتبّع حالة بيانات جهات الاتصال في
مستودع البيانات. يتم تخزين هذه البيانات الوصفية عن المستودع في أماكن مختلفة، بما في ذلك صفوف جدولَي "جهات الاتصال الأوّلية" و"البيانات" و"جهات الاتصال"، وجدول
ContactsContract.Settings
، وجدول
ContactsContract.SyncState
. يوضّح الجدول التالي أثر كلّ قطعة من هذه البيانات الوصفية:
الجدول 3. البيانات الوصفية في مقدِّم جهات الاتصال
جدول | العمود | القيم | المعنى |
---|---|---|---|
ContactsContract.RawContacts |
DIRTY |
"0" - لم يتم تغييره منذ آخر مزامنة. |
وضع علامة على جهات الاتصال الأولية التي تم تغييرها على الجهاز والتي يجب مزامنتها مرة أخرى
الخادم. يضبط موفِّر جهات الاتصال القيمة تلقائيًا عندما تعدِّل تطبيقات Android
صفًا.
يجب أن تُلحق محولات المزامنة التي تعدِّل جهة الاتصال الأولية أو جداول البيانات السمة
السلسلة |
"1" - تم تغييره منذ آخر مزامنة، ويجب مزامنته مرة أخرى مع الخادم. | |||
ContactsContract.RawContacts |
VERSION |
رقم الإصدار لهذا الصف. | يزيد مقدّم جهات الاتصال هذه القيمة تلقائيًا كلما تغيّر الصف أو البيانات المرتبطة به. |
ContactsContract.Data |
DATA_VERSION |
رقم إصدار هذا الصف. | يزيد "مقدِّم جهات الاتصال" هذه القيمة تلقائيًا كلما كان صف البيانات التغييرات. |
ContactsContract.RawContacts |
SOURCE_ID |
قيمة سلسلة تُحدِّد بشكلٍ فريد جهة الاتصال الأوّلية هذه للحساب الذي تم إنشاؤها فيه. |
عندما ينشئ مُعِدِّم المزامنة جهة اتصال جديدة غير معالجة، يجب ضبط هذا العمود على
رقم التعريف الفريد للخادم لجهة الاتصال غير المعالجة. عند إنشاء تطبيق Android جديد
جهة اتصال أولية، يجب أن يترك التطبيق هذا العمود فارغًا. يشير ذلك إلى محوِّل
مزامنة البيانات بأنّه يجب إنشاء جهة اتصال جديدة غير معالجة على الخادم، والحصول على قيمة
لـ SOURCE_ID .
على وجه التحديد، يجب أن يكون معرّف المصدر فريدًا لكل نوع حساب ومستقرًا في جميع عمليات المزامنة:
|
ContactsContract.Groups |
GROUP_VISIBLE |
"0" - يجب ألا تكون جهات الاتصال في هذه المجموعة مرئية في واجهات مستخدم تطبيقات Android. | هذا العمود مخصّص للتوافق مع الخوادم التي تسمح للمستخدم بإخفاء جهات الاتصال في مجموعات معيّنة. |
"1" - يُسمح لجهات الاتصال في هذه المجموعة بالظهور في واجهات مستخدم التطبيقات. | |||
ContactsContract.Settings |
UNGROUPED_VISIBLE |
"0" - بالنسبة إلى هذا الحساب ونوع الحساب، يتم حذف جهات الاتصال التي لا تنتمي إلى مجموعة غير مرئية لواجهات مستخدم تطبيقات Android. |
بشكل افتراضي، تكون جهات الاتصال غير مرئية إذا لم تنتمي أي من جهات الاتصال الأولية إلى مجموعة
(يشار إلى عضوية المجموعة لجهة اتصال أولية بعلامة واحدة أو أكثر
ContactsContract.CommonDataKinds.GroupMembership صف
في جدول ContactsContract.Data ).
من خلال ضبط هذا العلامة في صف الجدول ContactsContract.Settings
لنوع الحساب والحساب، يمكنك فرض ظهور جهات الاتصال التي لا تنتمي إلى مجموعات.
ومن بين استخدامات هذه العلامة عرض جهات الاتصال من الخوادم التي لا تستخدم المجموعات.
|
"1" - بالنسبة إلى هذا الحساب ونوع الحساب، يتم حذف جهات الاتصال التي لا تنتمي إلى مجموعة مرئية لواجهات مستخدم التطبيق. | |||
ContactsContract.SyncState |
(all) | استخدم هذا الجدول لتخزين البيانات الوصفية لمحوّل المزامنة. | باستخدام هذا الجدول، يمكنك تخزين حالة المزامنة والبيانات الأخرى ذات الصلة بالمزامنة باستمرار على جهازك. |
وصول مقدِّم جهات الاتصال
يصف هذا القسم إرشادات الوصول إلى البيانات من مزود جهات الاتصال، مع التركيز على ما يلي:
- طلبات البحث عن الكيانات
- تعديل مجمّع
- الاسترجاع والتعديل باستخدام النوايا
- سلامة البيانات
يتم أيضًا تناول إجراء تعديلات من محوّل المزامنة بمزيد من التفاصيل في هذا القسم محوّلات مزامنة موفّر جهات الاتصال
كيانات الاستعلام
بما أنّ جداول مقدّم جهات الاتصال منظَّمة بشكل هرمي، غالبًا ما يكون من المفيد
استرداد صف وجميع الصفوف "الفرعية" المرتبطة به. على سبيل المثال، لعرض
كل المعلومات الخاصة بشخص معيّن، قد تحتاج إلى استرداد كل صفوف
ContactsContract.RawContacts
لصف واحد
ContactsContract.Contacts
، أو كل صفوف
ContactsContract.CommonDataKinds.Email
لصف واحد
ContactsContract.RawContacts
. لتسهيل ذلك، تعمل جهات الاتصال
يوفّر الموفِّر بُنى entity التي تعمل مثل عمليات ضم قاعدة البيانات بين
الجداول.
الكيان يشبه جدولاً مكونًا من أعمدة محددة من جدول رئيسي وجدوله الفرعي.
عند طلب معلومات عن عنصر، عليك تقديم عرض ومعايير بحث استنادًا إلى الأعمدة
المتاحة من العنصر. النتيجة هي Cursor
تحتوي على
صف واحد لكل صف جدول فرعي تم استرداده. على سبيل المثال، إذا قمت بطلب
ContactsContract.Contacts.Entity
لاسم جهة اتصال
وجميع الصفوف الـ ContactsContract.CommonDataKinds.Email
لجميع
جهات الاتصال الأولية لهذا الاسم، ستحصل على Cursor
يتضمن صفًا واحدًا
لكل صف ContactsContract.CommonDataKinds.Email
.
تعمل الكيانات على تبسيط الاستعلامات. باستخدام عنصر، يمكنك استرداد جميع بيانات جهات الاتصال الخاصة بجهة اتصال أو جهة اتصال أولية دفعة واحدة، بدلاً من الحاجة إلى إجراء طلب بحث في الجدول الرئيسي أولاً للحصول على رقم تعريف، ثم إجراء طلب بحث في الجدول الفرعي باستخدام رقم التعريف هذا. يعالج مقدّم جهات الاتصال أيضًا طلب بحث عن كيان في معاملة واحدة، ما يضمن أن تكون البيانات التي يتم استرجاعها متسقة داخليًا.
ملاحظة: لا يحتوي الكيان عادةً على جميع الأعمدة في العنصر الرئيسي
جدول فرعي. إذا حاولت استخدام اسم عمود غير مُدرَج في قائمة ثوابت اسم عمود
الكيان، ستظهر لك رسالة الخطأ Exception
.
يوضح المقتطف التالي كيفية استرداد جميع صفوف جهات الاتصال الأولية لجهة اتصال. المقتطف
هو جزء من تطبيق أكبر يحتوي على نشاطين "الرئيسي" و"التفاصيل". يعرِض النشاط الرئيسي
قائمة بصفوف جهات الاتصال. عندما يختار المستخدم صفًا، يُرسِل النشاط رقم تعريفه إلى النشاط التفصيلي
. يستخدم النشاط التفصيلي ContactsContract.Contacts.Entity
لعرض جميع صفوف البيانات من جميع جهات الاتصال الأولية المرتبطة
جهة اتصال.
تم أخذ هذا المقتطف من نشاط "التفاصيل":
Kotlin
... /* * Appends the entity path to the URI. In the case of the Contacts Provider, the * expected URI is content://com.google.contacts/#/entity (# is the ID value). */ contactUri = Uri.withAppendedPath( contactUri, ContactsContract.Contacts.Entity.CONTENT_DIRECTORY ) // Initializes the loader identified by LOADER_ID. loaderManager.initLoader( LOADER_ID, // The identifier of the loader to initialize null, // Arguments for the loader (in this case, none) this // The context of the activity ) // Creates a new cursor adapter to attach to the list view cursorAdapter = SimpleCursorAdapter( this, // the context of the activity R.layout.detail_list_item, // the view item containing the detail widgets mCursor, // the backing cursor fromColumns, // the columns in the cursor that provide the data toViews, // the views in the view item that display the data 0) // flags // Sets the ListView's backing adapter. rawContactList.adapter = cursorAdapter ... override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> { /* * Sets the columns to retrieve. * RAW_CONTACT_ID is included to identify the raw contact associated with the data row. * DATA1 contains the first column in the data row (usually the most important one). * MIMETYPE indicates the type of data in the data row. */ val projection: Array<String> = arrayOf( ContactsContract.Contacts.Entity.RAW_CONTACT_ID, ContactsContract.Contacts.Entity.DATA1, ContactsContract.Contacts.Entity.MIMETYPE ) /* * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw * contact collated together. */ val sortOrder = "${ContactsContract.Contacts.Entity.RAW_CONTACT_ID} ASC" /* * Returns a new CursorLoader. The arguments are similar to * ContentResolver.query(), except for the Context argument, which supplies the location of * the ContentResolver to use. */ return CursorLoader( applicationContext, // The activity's context contactUri, // The entity content URI for a single contact projection, // The columns to retrieve null, // Retrieve all the raw contacts and their data rows. null, // sortOrder // Sort by the raw contact ID. ) }
Java
... /* * Appends the entity path to the URI. In the case of the Contacts Provider, the * expected URI is content://com.google.contacts/#/entity (# is the ID value). */ contactUri = Uri.withAppendedPath( contactUri, ContactsContract.Contacts.Entity.CONTENT_DIRECTORY); // Initializes the loader identified by LOADER_ID. getLoaderManager().initLoader( LOADER_ID, // The identifier of the loader to initialize null, // Arguments for the loader (in this case, none) this); // The context of the activity // Creates a new cursor adapter to attach to the list view cursorAdapter = new SimpleCursorAdapter( this, // the context of the activity R.layout.detail_list_item, // the view item containing the detail widgets mCursor, // the backing cursor fromColumns, // the columns in the cursor that provide the data toViews, // the views in the view item that display the data 0); // flags // Sets the ListView's backing adapter. rawContactList.setAdapter(cursorAdapter); ... @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { /* * Sets the columns to retrieve. * RAW_CONTACT_ID is included to identify the raw contact associated with the data row. * DATA1 contains the first column in the data row (usually the most important one). * MIMETYPE indicates the type of data in the data row. */ String[] projection = { ContactsContract.Contacts.Entity.RAW_CONTACT_ID, ContactsContract.Contacts.Entity.DATA1, ContactsContract.Contacts.Entity.MIMETYPE }; /* * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw * contact collated together. */ String sortOrder = ContactsContract.Contacts.Entity.RAW_CONTACT_ID + " ASC"; /* * Returns a new CursorLoader. The arguments are similar to * ContentResolver.query(), except for the Context argument, which supplies the location of * the ContentResolver to use. */ return new CursorLoader( getApplicationContext(), // The activity's context contactUri, // The entity content URI for a single contact projection, // The columns to retrieve null, // Retrieve all the raw contacts and their data rows. null, // sortOrder); // Sort by the raw contact ID. }
عند انتهاء التحميل، يستدعي LoaderManager
معاودة الاتصال
onLoadFinished()
إحدى الوسيطات الواردة إلى هذه الطريقة هي
Cursor
التي تتضمّن نتائج طلب البحث. في تطبيقك، يمكنك الحصول على
بيانات من هذا Cursor
لعرضها أو إجراء المزيد من الإجراءات عليها.
تعديل مجمّع
يجب إدراج البيانات وتعديلها وحذفها في "موفِّر جهات الاتصال" في
"وضع الحِزم" كلما أمكن ذلك، وذلك عن طريق إنشاء ArrayList
من
عناصر ContentProviderOperation
واستدعاء
applyBatch()
. لأنّ
يجري موفّر جهات الاتصال جميع العمليات في
applyBatch()
في أغنية واحدة
معاملة، فلن تترك التعديلات التي تجريها مستودع جهات الاتصال في حالة
الولاية. يسهّل تعديل الحِزم أيضًا إدراج جهة اتصال أولية وبياناتها التفصيلية في
الوقت نفسه.
ملاحظة: لتعديل جهة اتصال أولية واحدة، يمكنك إرسال intent إلى تطبيق جهات الاتصال في الجهاز بدلاً من معالجة التعديل في تطبيقك. وقد تم توضيح إجراء ذلك بشكل أكثر تفصيلاً في القسم الاسترجاع والتعديل بأغراض:
نقاط الكمية الناتجة
يمكن أن يؤدي التعديل المجمّع الذي يحتوي على عدد كبير من العمليات إلى حظر عمليات أخرى،
ما يؤدي إلى تجربة سيئة للمستخدم بشكل عام. لتنظيم كل التعديلات التي تريد
إجراؤها في أقل عدد ممكن من القوائم المنفصلة، وفي الوقت نفسه منع
حظر النظام، عليك ضبط نقاط العائد لعملية واحدة أو أكثر.
نقطة الإنتاج هي كائن ContentProviderOperation
له
تم ضبط قيمة isYieldAllowed()
على
true
عندما يواجه موفِّر جهات الاتصال نقطة إنتاجية، فإنه يوقف عمله مؤقتًا
السماح بتشغيل العمليات الأخرى وإغلاق المعاملة الحالية. وعندما يبدأ مزود الخدمة مرة أخرى،
مواصلة العملية التالية في 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
.
توضِّح المقتطفات التالية كيفية إدراج بيانات وجهات اتصال جديدة غير معالجة بشكل مجمّع. وتشمل رمزًا يحدّد نقطة استراحة ويستخدم مرجعًا خلفيًا.
يسترد المقتطف الأول بيانات جهة الاتصال من واجهة المستخدم. في هذه المرحلة، سبق للمستخدم اختيار الحساب الذي يجب إضافة جهة الاتصال الأوّلية الجديدة إليه.
Kotlin
// Creates a contact entry from the current UI values, using the currently-selected account. private fun createContactEntry() { /* * Gets values from the UI */ val name = contactNameEditText.text.toString() val phone = contactPhoneEditText.text.toString() val email = contactEmailEditText.text.toString() val phoneType: String = contactPhoneTypes[mContactPhoneTypeSpinner.selectedItemPosition] val emailType: String = contactEmailTypes[mContactEmailTypeSpinner.selectedItemPosition]
Java
// Creates a contact entry from the current UI values, using the currently-selected account. protected void createContactEntry() { /* * Gets values from the UI */ String name = contactNameEditText.getText().toString(); String phone = contactPhoneEditText.getText().toString(); String email = contactEmailEditText.getText().toString(); int phoneType = contactPhoneTypes.get( contactPhoneTypeSpinner.getSelectedItemPosition()); int emailType = contactEmailTypes.get( contactEmailTypeSpinner.getSelectedItemPosition());
ينشئ المقتطف التالي عملية لإدراج صف جهة الاتصال الأولية في
جدول ContactsContract.RawContacts
:
Kotlin
/* * Prepares the batch operation for inserting a new raw contact and its data. Even if * the Contacts Provider does not have any data for this person, you can't add a Contact, * only a raw contact. The Contacts Provider will then add a Contact automatically. */ // Creates a new array of ContentProviderOperation objects. val ops = arrayListOf<ContentProviderOperation>() /* * Creates a new raw contact with its account type (server type) and account name * (user's account). Remember that the display name is not stored in this row, but in a * StructuredName data row. No other data is required. */ var op: ContentProviderOperation.Builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.name) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.type) // Builds the operation and adds it to the array of operations ops.add(op.build())
Java
/* * Prepares the batch operation for inserting a new raw contact and its data. Even if * the Contacts Provider does not have any data for this person, you can't add a Contact, * only a raw contact. The Contacts Provider will then add a Contact automatically. */ // Creates a new array of ContentProviderOperation objects. ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); /* * Creates a new raw contact with its account type (server type) and account name * (user's account). Remember that the display name is not stored in this row, but in a * StructuredName data row. No other data is required. */ ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.getType()) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.getName()); // Builds the operation and adds it to the array of operations ops.add(op.build());
بعد ذلك، يُنشئ الرمز صفوف بيانات لصفوف الاسم المعروض والهاتف والبريد الإلكتروني.
يستخدم كل كائن أداة إنشاء عمليات
withValueBackReference()
للحصول على
RAW_CONTACT_ID
النقاط المرجعية
الرجوع إلى الكائن ContentProviderResult
من العملية الأولى،
التي تضيف صف جهة الاتصال الأولية وتعرض _ID
الجديدة
نتيجةً لذلك، يتم ربط كل صف بيانات تلقائيًا باستخدام
RAW_CONTACT_ID
بالصف ContactsContract.RawContacts
الجديد الذي ينتمي إليه.
عنصر ContentProviderOperation.Builder
الذي يضيف صف البريد الإلكتروني هو
محددة باستخدام withYieldAllowed()
، التي تحدد نقطة عائد:
Kotlin
// Creates the display name for the new raw contact, as a StructuredName data row. op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * withValueBackReference sets the value of the first argument to the value of * the ContentProviderResult indexed by the second argument. In this particular * call, the raw contact ID column of the StructuredName data row is set to the * value of the result returned by the first operation, which is the one that * actually adds the raw contact row. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to StructuredName .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) // Sets the data row's display name to the name in the UI. .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name) // Builds the operation and adds it to the array of operations ops.add(op.build()) // Inserts the specified phone number and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Phone .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) // Sets the phone number and type .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType) // Builds the operation and adds it to the array of operations ops.add(op.build()) // Inserts the specified email and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Email .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) // Sets the email address and type .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email) .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType) /* * Demonstrates a yield point. At the end of this insert, the batch operation's thread * will yield priority to other threads. Use after every set of operations that affect a * single contact, to avoid degrading performance. */ op.withYieldAllowed(true) // Builds the operation and adds it to the array of operations ops.add(op.build())
Java
// Creates the display name for the new raw contact, as a StructuredName data row. op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * withValueBackReference sets the value of the first argument to the value of * the ContentProviderResult indexed by the second argument. In this particular * call, the raw contact ID column of the StructuredName data row is set to the * value of the result returned by the first operation, which is the one that * actually adds the raw contact row. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to StructuredName .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) // Sets the data row's display name to the name in the UI. .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name); // Builds the operation and adds it to the array of operations ops.add(op.build()); // Inserts the specified phone number and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Phone .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) // Sets the phone number and type .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType); // Builds the operation and adds it to the array of operations ops.add(op.build()); // Inserts the specified email and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Email .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) // Sets the email address and type .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email) .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType); /* * Demonstrates a yield point. At the end of this insert, the batch operation's thread * will yield priority to other threads. Use after every set of operations that affect a * single contact, to avoid degrading performance. */ op.withYieldAllowed(true); // Builds the operation and adds it to the array of operations ops.add(op.build());
يعرض المقتطف الأخير طلبًا إلى دالة
applyBatch()
التي تُدخِل صفوف البيانات وجهات الاتصال الأوّلية الجديدة.
Kotlin
// Ask the Contacts Provider to create a new contact Log.d(TAG, "Selected account: ${mSelectedAccount.name} (${mSelectedAccount.type})") Log.d(TAG, "Creating contact: $name") /* * Applies the array of ContentProviderOperation objects in batch. The results are * discarded. */ try { contentResolver.applyBatch(ContactsContract.AUTHORITY, ops) } catch (e: Exception) { // Display a warning val txt: String = getString(R.string.contactCreationFailure) Toast.makeText(applicationContext, txt, Toast.LENGTH_SHORT).show() // Log exception Log.e(TAG, "Exception encountered while inserting contact: $e") } }
Java
// Ask the Contacts Provider to create a new contact Log.d(TAG,"Selected account: " + selectedAccount.getName() + " (" + selectedAccount.getType() + ")"); Log.d(TAG,"Creating contact: " + name); /* * Applies the array of ContentProviderOperation objects in batch. The results are * discarded. */ try { getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { // Display a warning Context ctx = getApplicationContext(); CharSequence txt = getString(R.string.contactCreationFailure); int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(ctx, txt, duration); toast.show(); // Log exception Log.e(TAG, "Exception encountered while inserting contact: " + e); } }
تسمح لك العمليات المجمّعة أيضًا بتنفيذ التحكّم المتفائل في التزامن، طريقة لتطبيق معاملات التعديل بدون الحاجة إلى قفل المستودع الأساسي. لاستخدام هذه الطريقة، يمكنك تطبيق المعاملة ثم البحث عن التعديلات الأخرى التي عملية البحث الأخرى في نفس الوقت. إذا لاحظت حدوث تعديل غير متّسق، عليك تراجع المعاملة وإعادة المحاولة.
يكون التحكّم في التزامن التفاؤلي مفيدًا للأجهزة الجوّالة التي يكون فيها مستخدم واحد فقط في كل مرة، وتكون عمليات الوصول المتزامنة إلى مستودع البيانات نادرة. وبما أنّه لا يتم استخدام قفل الجدول، لا يتم إضاعة الوقت في ضبط عمليات القفل أو انتظار المعاملات الأخرى لإزالة عمليات القفل.
لاستخدام ميزة التحكّم في الاتّساق التفاؤلي أثناء تعديل صف واحد
ContactsContract.RawContacts
، اتّبِع الخطوات التالية:
-
استرجع عمود
VERSION
لجهة الاتصال الأوّلية مع البيانات الأخرى التي تسترجعها. -
إنشاء عنصر
ContentProviderOperation.Builder
مناسب لـ وفرض قيد، باستخدام طريقةnewAssertQuery(Uri)
بالنسبة إلى معرّف الموارد المنتظم للمحتوى، استخدِمRawContacts.CONTENT_URI
مع إلحاق_ID
لجهة الاتصال الأوّلية. -
بالنسبة إلى الكائن
ContentProviderOperation.Builder
، يمكنك طلبwithValue()
لمقارنةVERSION
إلى رقم الإصدار الذي استعدته للتو. -
بالنسبة إلى رقم
ContentProviderOperation.Builder
نفسه، يُرجى الاتصالwithExpectedCount()
للتأكد من اختبار صف واحد فقط من خلال هذا التأكيد. -
يمكنك الاتصال بـ
build()
لإنشاءContentProviderOperation
، ثم أضِف هذا الكائن على أنّه الكائن الأول فيArrayList
الذي تمرر إليهapplyBatch()
- طبِّق معاملة الحزمة.
إذا تم تحديث صف جهة الاتصال الأولية بواسطة عملية أخرى بين وقت قراءة الصف
والوقت الذي تحاول فيه تعديله، فإن "التأكيد" ContentProviderOperation
سيفشل، وسيتم الاحتفاظ بنسخة احتياطية من دفعة العمليات بأكملها. يمكنك بعد ذلك اختيار إعادة محاولة
تحميل الحزمة أو اتّخاذ إجراء آخر.
يوضح المقتطف التالي كيفية إنشاء "تأكيد"
ContentProviderOperation
بعد إجراء طلب البحث عن جهة اتصال أولية واحدة باستخدام
CursorLoader
:
Kotlin
/* * The application uses CursorLoader to query the raw contacts table. The system calls this method * when the load is finished. */ override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor) { // Gets the raw contact's _ID and VERSION values rawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)) mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION)) } ... // Sets up a Uri for the assert operation val rawContactUri: Uri = ContentUris.withAppendedId( ContactsContract.RawContacts.CONTENT_URI, rawContactID ) // Creates a builder for the assert operation val assertOp: ContentProviderOperation.Builder = ContentProviderOperation.newAssertQuery(rawContactUri).apply { // Adds the assertions to the assert operation: checks the version withValue(SyncColumns.VERSION, mVersion) // and count of rows tested withExpectedCount(1) } // Creates an ArrayList to hold the ContentProviderOperation objects val ops = arrayListOf<ContentProviderOperation>() ops.add(assertOp.build()) // You would add the rest of your batch operations to "ops" here ... // Applies the batch. If the assert fails, an Exception is thrown try { val results: Array<ContentProviderResult> = contentResolver.applyBatch(AUTHORITY, ops) } catch (e: OperationApplicationException) { // Actions you want to take if the assert operation fails go here }
Java
/* * The application uses CursorLoader to query the raw contacts table. The system calls this method * when the load is finished. */ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // Gets the raw contact's _ID and VERSION values rawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)); mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION)); } ... // Sets up a Uri for the assert operation Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactID); // Creates a builder for the assert operation ContentProviderOperation.Builder assertOp = ContentProviderOperation.newAssertQuery(rawContactUri); // Adds the assertions to the assert operation: checks the version and count of rows tested assertOp.withValue(SyncColumns.VERSION, mVersion); assertOp.withExpectedCount(1); // Creates an ArrayList to hold the ContentProviderOperation objects ArrayList ops = new ArrayList<ContentProviderOperation>; ops.add(assertOp.build()); // You would add the rest of your batch operations to "ops" here ... // Applies the batch. If the assert fails, an Exception is thrown try { ContentProviderResult[] results = getContentResolver().applyBatch(AUTHORITY, ops); } catch (OperationApplicationException e) { // Actions you want to take if the assert operation fails go here }
الاسترجاع والتعديل باستخدام النوايا
يتيح لك إرسال نية إلى تطبيق جهات الاتصال على الجهاز الوصول إلى موفِّر جهات الاتصال بشكل غير مباشر. يبدأ الغرض واجهة المستخدم لتطبيق جهات الاتصال على الجهاز، والتي يمكن للمستخدمين من خلالها القيام بالأعمال المتعلقة بجهات الاتصال. باستخدام هذا النوع من الوصول، يمكن للمستخدمين:
- اختر جهة اتصال من قائمة واطلب منها إعادتها إلى تطبيقك لمزيد من العمل.
- تعديل بيانات جهة اتصال حالية
- إدراج جهة اتصال جديدة غير معالجة لأي من حساباته
- حذف بيانات جهة اتصال أو جهات اتصال
إذا كان المستخدم يُدخِل بيانات أو يعدّلها، يمكنك جمع البيانات أولاً وإرسالها كجزء من الطلب.
عند استخدام النوايا للوصول إلى مقدّم جهات الاتصال من خلال تطبيق جهات الاتصال على الجهاز، لن يكون عليك كتابة واجهة المستخدم أو الرمز البرمجي الخاصَين بك للوصول إلى مقدّم الخدمة. ولن تحتاج أيضًا إلى طلب إذن بالقراءة أو الكتابة إلى الموفّر. يمكن لتطبيق جهات الاتصال على الجهاز تفويض إذن القراءة لجهة اتصال إليك، وبما أنّك تُجري تعديلات على موفِّر الخدمات من خلال تطبيق آخر، ليس عليك الحصول على أذونات الكتابة.
يتم توضيح العملية العامة لإرسال intent إلى الوصول إلى أحد مقدمي الخدمة بالتفصيل في
دليل أساسيات موفّر المحتوى في قسم "الوصول إلى البيانات عبر الأهداف". الإجراء،
يتم تلخيص نوع MIME وقيم البيانات التي تستخدمها للمهام المتاحة في الجدول 4، بينما
القيم الإضافية التي يمكنك استخدامها
تم إدراج putExtra()
في
المستندات المرجعية لـ ContactsContract.Intents.Insert
:
الجدول 4. نوايا مقدّم جهات الاتصال
المهمة | الإجراء | البيانات | نوع MIME | ملاحظات |
---|---|---|---|---|
اختيار جهة اتصال من قائمة | ACTION_PICK |
أحد الخيارَين التاليَين:
|
لم يتم الاستخدام |
تعرِض هذه السمة قائمة بجهات الاتصال الأوّلية أو قائمة بالبيانات من جهة اتصال أوّلية، استنادًا إلى نوع
معرف الموارد المنتظم (URI) للمحتوى الذي تقدّمه.
استدعاء دالة
|
إدراج جهة اتصال جديدة غير معالجة | Insert.ACTION |
لا ينطبق |
RawContacts.CONTENT_TYPE ، نوع MIME لمجموعة من جهات الاتصال الأوّلية
|
تعرِض هذه القيمة شاشة إضافة جهة اتصال في تطبيق جهات الاتصال على الجهاز. يتم عرض
قيم الإضافات التي تضيفها إلى الطلب. في حال الإرسال باستخدام
startActivityForResult() ،
يتمّ تمرير معرّف الموارد المنتظم للمحتوى الخاص بجهة الاتصال الأوّلية التي تمت إضافتها حديثًا إلى onActivityResult()
طريقة الاستدعاء في نشاطك ضمن الوسيطة Intent في الحقل
"data". للحصول على القيمة، اتصل بالرقم getData() .
|
تعديل جهة اتصال | ACTION_EDIT |
CONTENT_LOOKUP_URI
جهة الاتصال. سيسمح نشاط المحرِّر للمستخدم بتعديل أي من البيانات المرتبطة
بجهة الاتصال هذه.
|
Contacts.CONTENT_ITEM_TYPE ، جهة اتصال واحدة |
تعرِض هذه القيمة شاشة "تعديل جهة الاتصال" في تطبيق "جهات الاتصال". القيم الإضافية التي تضيفها يتم عرض الغرض منها. عندما ينقر المستخدم على تم لحفظ التعديلات، يعود نشاطك إلى المقدمة. |
عرض أداة اختيار يمكنها أيضًا إضافة بيانات | ACTION_INSERT_OR_EDIT |
لا ينطبق |
CONTENT_ITEM_TYPE
|
يعرض هذا الغرض دائمًا شاشة أداة اختيار تطبيق جهات الاتصال. يمكن للمستخدم إما
اختر جهة اتصال لتعديلها، أو أضف جهة اتصال جديدة. شاشة التعديل أو الإضافة
اعتمادًا على اختيار المستخدم والبيانات الإضافية التي تمررها في المقصد
نتائج البحث. إذا كان تطبيقك يعرض بيانات جهات الاتصال، مثل عنوان بريد إلكتروني أو رقم هاتف، استخدِم
هذا الإذن للسماح للمستخدم بإضافة البيانات إلى جهة اتصال حالية.
جهة اتصال
ملاحظة: ما مِن حاجة إلى إرسال قيمة اسم في البيانات الإضافية لهذا الطلب، لأنّ المستخدم يختار دائمًا اسمًا حاليًا أو يضيف اسمًا جديدًا. بالإضافة إلى ذلك، إذا أرسلت اسمًا واختار المستخدم إجراء تعديل، سيعرِض تطبيق جهات الاتصال الاسم الذي ترسله، ما سيؤدي إلى استبدال القيمة السابقة. إذا لم يلاحظ المستخدِم ذلك وحفظ التعديل، سيتم فقدان القيمة القديمة. |
لا يسمح لك تطبيق جهات الاتصال على الجهاز بحذف جهة اتصال أولية أو أي من بياناتها باستخدام
والنية. بدلاً من ذلك، لحذف جهة اتصال أولية، استخدم
ContentResolver.delete()
أو ContentProviderOperation.newDelete()
.
يوضِّح المقتطف التالي كيفية إنشاء عنصر intent لإدراج عنصر جديد وإرساله. جهة الاتصال والبيانات:
Kotlin
// Gets values from the UI val name = contactNameEditText.text.toString() val phone = contactPhoneEditText.text.toString() val email = contactEmailEditText.text.toString() val company = companyName.text.toString() val jobtitle = jobTitle.text.toString() /* * Demonstrates adding data rows as an array list associated with the DATA key */ // Defines an array list to contain the ContentValues objects for each row val contactData = arrayListOf<ContentValues>() /* * Defines the raw contact row */ // Sets up the row as a ContentValues object val rawContactRow = ContentValues().apply { // Adds the account type and name to the row put(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.type) put(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.name) } // Adds the row to the array contactData.add(rawContactRow) /* * Sets up the phone number data row */ // Sets up the row as a ContentValues object val phoneRow = ContentValues().apply { // Specifies the MIME type for this data row (all data rows must be marked by their type) put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) // Adds the phone number and its type to the row put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) } // Adds the row to the array contactData.add(phoneRow) /* * Sets up the email data row */ // Sets up the row as a ContentValues object val emailRow = ContentValues().apply { // Specifies the MIME type for this data row (all data rows must be marked by their type) put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) // Adds the email address and its type to the row put(ContactsContract.CommonDataKinds.Email.ADDRESS, email) } // Adds the row to the array contactData.add(emailRow) // Creates a new intent for sending to the device's contacts application val insertIntent = Intent(ContactsContract.Intents.Insert.ACTION).apply { // Sets the MIME type to the one expected by the insertion activity type = ContactsContract.RawContacts.CONTENT_TYPE // Sets the new contact name putExtra(ContactsContract.Intents.Insert.NAME, name) // Sets the new company and job title putExtra(ContactsContract.Intents.Insert.COMPANY, company) putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle) /* * Adds the array to the intent's extras. It must be a parcelable object in order to * travel between processes. The device's contacts app expects its key to be * Intents.Insert.DATA */ putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData) } // Send out the intent to start the device's contacts app in its add contact activity. startActivity(insertIntent)
Java
// Gets values from the UI String name = contactNameEditText.getText().toString(); String phone = contactPhoneEditText.getText().toString(); String email = contactEmailEditText.getText().toString(); String company = companyName.getText().toString(); String jobtitle = jobTitle.getText().toString(); // Creates a new intent for sending to the device's contacts application Intent insertIntent = new Intent(ContactsContract.Intents.Insert.ACTION); // Sets the MIME type to the one expected by the insertion activity insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE); // Sets the new contact name insertIntent.putExtra(ContactsContract.Intents.Insert.NAME, name); // Sets the new company and job title insertIntent.putExtra(ContactsContract.Intents.Insert.COMPANY, company); insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle); /* * Demonstrates adding data rows as an array list associated with the DATA key */ // Defines an array list to contain the ContentValues objects for each row ArrayList<ContentValues> contactData = new ArrayList<ContentValues>(); /* * Defines the raw contact row */ // Sets up the row as a ContentValues object ContentValues rawContactRow = new ContentValues(); // Adds the account type and name to the row rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.getType()); rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.getName()); // Adds the row to the array contactData.add(rawContactRow); /* * Sets up the phone number data row */ // Sets up the row as a ContentValues object ContentValues phoneRow = new ContentValues(); // Specifies the MIME type for this data row (all data rows must be marked by their type) phoneRow.put( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE ); // Adds the phone number and its type to the row phoneRow.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone); // Adds the row to the array contactData.add(phoneRow); /* * Sets up the email data row */ // Sets up the row as a ContentValues object ContentValues emailRow = new ContentValues(); // Specifies the MIME type for this data row (all data rows must be marked by their type) emailRow.put( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE ); // Adds the email address and its type to the row emailRow.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email); // Adds the row to the array contactData.add(emailRow); /* * Adds the array to the intent's extras. It must be a parcelable object in order to * travel between processes. The device's contacts app expects its key to be * Intents.Insert.DATA */ insertIntent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData); // Send out the intent to start the device's contacts app in its add contact activity. startActivity(insertIntent);
تكامل البيانات
لأنّ مستودع جهات الاتصال يحتوي على بيانات مهمة وحساسة يتوقع المستخدمون صحيحة ومحدثة، فإن موفر جهات الاتصال لديه قواعد محددة جيدًا لسلامة البيانات. تقع على عاتقك مسؤولية الالتزام بهذه القواعد عند تعديل بيانات جهات الاتصال. في ما يلي أهم القواعد:
-
إضافة صف
ContactsContract.CommonDataKinds.StructuredName
دائمًا لكلContactsContract.RawContacts
صف تضيفه. -
صف
ContactsContract.RawContacts
بدون صف واحد (ContactsContract.CommonDataKinds.StructuredName
) في قد يتسبب الجدولContactsContract.Data
في حدوث مشاكل أثناء التجميع. -
ربط صفوف "
ContactsContract.Data
" الجديدة دائمًا بالصفوف الرئيسية صف واحد (ContactsContract.RawContacts
) -
صف
ContactsContract.Data
غير مرتبط لن يكونContactsContract.RawContacts
مرئيًا في جهات الاتصال، وقد يتسبب ذلك في حدوث مشكلات مع محوّلات المزامنة. - يمكنك تغيير البيانات لجهات الاتصال الأوّلية التي تملكها فقط.
- تذكَّر أنّ مقدّم جهات الاتصال يدير عادةً بيانات من عدة أنواع حسابات/خدمات على الإنترنت مختلفة. يجب التأكد من أن التطبيق يُجري تعديلات فقط أو يحذف بيانات الصفوف التي تخصك، وأن هذا الإجراء يدرج بيانات فقط ونوع الحساب والاسم اللذين يمكنك التحكم فيهما.
-
استخدِم دائمًا الثوابت المحدّدة في
ContactsContract
و الفئات الفرعية لها للسلطات وعناوين URL للمحتوى ومسارات عناوين URL وأسماء الأعمدة وأنواع MIME و قيم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
يتحقق برنامج المصادقة
هويّة المستخدم من خلال الخطوات التالية:
- جمع اسم المستخدم أو كلمة مروره أو معلومات مماثلة بيانات الاعتماد).
- إرسال بيانات الاعتماد إلى الخدمة
- فحص رد الخدمة.
إذا قبلت الخدمة بيانات الاعتماد، يمكن لأداة المصادقة
بتخزين بيانات الاعتماد لاستخدامها لاحقًا. بفضل إطار عمل مصادق المكوّن الإضافي،
يمكن لـ 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>
الخاص بخدمة محول المزامنة إلى نقطة ملف XMLres/xml/syncadapter.xml
. ويحدِّد هذا الملف بدوره عنوان URL لخدمة الويب التي ستتم مزامنتها مع مقدّم جهات الاتصال، ونوع حساب لخدمة الويب. -
اختياري: يشير عنصر
<meta-data>
مُعتمِد الهوية إلى ملف XMLres/xml/authenticator.xml
. بدوره، يحدِّد هذا الملف نوع الحساب الذي يتيح مصادقته، بالإضافة إلى موارد واجهة المستخدم التي تظهر أثناء عملية المصادقة. يجب أن يكون نوع الحساب المحدّد في هذا العنصر هو نفسه نوع الحساب المحدّد لمحوِّل المزامنة.
-
تشير رسالة الأشكال البيانية
بيانات ساحة مشاركات الشبكات الاجتماعية
يتيح android.provider.ContactsContacts.StreamItems جداول android.provider.ContactsContact.StreamItemPhotos وإدارة البيانات الواردة من الشبكات الاجتماعية. يمكنك كتابة محوّل مزامنة يضيف بيانات البث. من شبكتك الخاصة إلى هذه الجداول، أو يمكنك قراءة بيانات البث من هذه الجداول أو عرضها في التطبيق الخاص بك، أو كليهما. باستخدام هذه الميزات، يمكن أن تساعد شبكات التواصل الاجتماعي الخدمات والتطبيقات المختلفة في تجربة الشبكات الاجتماعية من Android.
نص ساحة مشاركات الشبكات الاجتماعية
ترتبط عناصر البث دائمًا بجهة اتصال أولية. يرتبط العنصر
android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID بالقيمة
_ID
لجهة الاتصال الأوّلية. يتم أيضًا تخزين نوع الحساب واسم الحساب لجهة
الاتصال الأوّلية في صف عنصر البث.
يمكنك تخزين البيانات من مصدر بياناتك في الأعمدة التالية:
- android.provider.Contacts استخدم.StreamItemsColumns#ACCOUNT_TYPE.
- مطلوبة: نوع حساب المستخدم لجهة الاتصال الأولية المرتبطة بهذا الحساب عنصر البث. تذكَّر ضبط هذه القيمة عند إدراج عنصر بث.
- android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME
- يجب ملء هذا الحقل. اسم حساب المستخدم لجهة الاتصال الأولية المرتبطة بهذا عنصر البث. تذكَّر ضبط هذه القيمة عند إدراج عنصر بث.
- أعمدة المعرّفات
-
مطلوبة. يجب إدراج أعمدة المعرّفات التالية عند
لإدراج عنصر ساحة مشاركات:
- android.provider.Contacts استخدم.StreamItemscolumn#CONTACT_ID: قيمة android.provider.BaseColumns#_ID لجهة الاتصال المدرَجة في مصدر البيانات هذا العنصر مرتبط به.
- android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY: قيمة android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY الخاصة بجهة الاتصال المرتبطة بعنصر البث هذا
- android.provider.ContactsContacts.StreamItemscolumn#RAW_CONTACT_ID: قيمة android.provider.Basecolumn#_ID لجهة الاتصال الأولية في ساحة المشاركات هذه العنصر مرتبط به.
- android.provider.Contacts استخدم.StreamItemscolumn#COMMENTS
- اختيارية. تخزِّن معلومات موجزة يمكنك عرضها في بداية عنصر مصدر بيانات.
- android.provider.ContactsContract.StreamItemsColumns#TEXT
-
نص عنصر البث، إما المحتوى الذي نشره مصدره،
أو وصف للإجراء الذي أدى إلى إنشاء عنصر البث. يمكن أن يحتوي هذا العمود على
أي تنسيق وصور موارد مضمّنة يمكن عرضها باستخدام
fromHtml()
قد يقطع موفّر المحتوى المحتوى الطويل أو يحذف منه أجزاء، ولكن سيحاول تجنُّب تقسيم العلامات. - android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP
- سلسلة نصية تحتوي على وقت إدراج عنصر البث أو تعديله، على شكل ملي ثانية منذ بدء حساب الوقت التطبيقات التي تُدرِج عناصر البث أو تعدِّلها: مسئولاً عن الحفاظ على هذا العمود؛ فلا تتم صيانته تلقائيًا من خلال جهات الاتصال
لعرض معلومات تعريفية لعناصر ساحة المشاركات، استخدم android.provider.Contacts استخدم.StreamItemscolumn#RES_ICON، android.provider.ContactsContacts.StreamItemscolumn#RES_LABEL، و android.provider.Contacts استخدم.StreamItemscolumn#RES_PACKAGE لربط الموارد في تطبيقك.
يحتوي الجدول android.provider.ContactsContacts.StreamItems أيضًا على الأعمدة من android.provider.Contacts استخدم.StreamItemsColumns#SYNC1 حتى يمكن استخدام android.provider.Contacts استخدم.StreamItemsColumns#SYNC4 للاستفادة حصريًا من محوّلات المزامنة.
صور ساحات المشاركات على وسائل التواصل الاجتماعي
يخزِّن جدول android.provider.ContactsContract.StreamItemPhotos الصور المرتبطة
بعنصر البث. يرتبط عمود
android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID في الجدول
بالقيم الواردة في عمود _ID
في جدول
android.provider.ContactsContract.StreamItems. يتم تخزين مراجع الصور في جدول
في الأعمدة التالية:
- عمود PHOTO في android.provider.ContactsContract.StreamItemPhotos# (وهو ملف BLOB)
- عرض ثنائي للصورة، يغيّر مقدّم الخدمة حجمه لتخزينه وعرضه يتوفّر هذا العمود للتوافق مع الإصدارات السابقة من موفِّر جهات الاتصال الذي كان يستخدمه لتخزين الصور. ومع ذلك، في الإصدار الحالي، يجب عدم استخدام هذا العمود لتخزين الصور. بدلاً من ذلك، استخدِم إما android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID أو android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI (كلاهما описанان في النقاط التالية) لتخزين الصور في ملف. يحتوي هذا العمود الآن على صورة مصغّرة للصورة، وهي متاحة للقراءة.
- android.provider.Contacts استخدم.StreamItemPhotosColumns#PHOTO_FILE_ID.
-
معرّف رقمي لصورة جهة اتصال أولية إلحاق هذه القيمة بالثابت
DisplayPhoto.CONTENT_URI
للحصول على عنوان URI للمحتوى يشير إلى ملف صورة واحد، ثم استدعاءopenAssetFileDescriptor()
للحصول على اسم معرِّف لملف الصورة. - android.provider.Contacts استخدم.StreamItemPhotosColumns#PHOTO_URI
-
معرّف موارد منتظم للمحتوى يشير مباشرةً إلى ملف الصورة التي يمثّلها هذا الصف
يمكنك الاتصال بـ
openAssetFileDescriptor()
باستخدام معرّف الموارد المنتظم (URI) هذا للحصول على اسم معرِّف لملف الصورة.
استخدام جداول "البثّ على الشبكات الاجتماعية"
تعمل هذه الجداول بالطريقة نفسها التي تعمل بها الجداول الرئيسية الأخرى في "موفر جهات الاتصال"، باستثناء ما يلي:
- تتطلّب هذه الجداول أذونات وصول إضافية. للقراءة من هذه المصادر، يجب أن يحصل تطبيقك على الإذن android.Manifest.permission#READ_SOCIAL_STREAM. لتعديلها، يجب أن يحصل تطبيقك على الإذن android.Manifest.permission#WRITE_SOCIAL_STREAM.
- عدد الصفوف في الجدول android.provider.ContactsContacts.StreamItems المخزنة لكل جهة اتصال أولية. وعند بلوغ هذا الحدّ، يوفّر "مقدِّم جهات الاتصال" مساحة لصفوف عناصر البث الجديدة عن طريق حذف الصفوف التي تحتوي على الأقدم android.provider.ContactsContact.StreamItemsColumns#TIMESTAMP. للحصول على الحدّ الأقصى، أدخِل طلب بحث إلى معرّف الموارد المنتظم للمحتوى android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI. يمكنك ترك جميع الوسيطات غير معرّفة باستثناء معرّف الموارد المتسلسل للمحتوى. يعرض الطلب مؤشرًا يحتوي على صف واحد، مع العمود الوحيد android.provider.ContactsContract.StreamItems#MAX_ITEMS.
تُحدد الفئة android.provider.Contacts استخدم.StreamItems.StreamItemPhotos الجدول الفرعي الخاص بـ android.provider.Contacts استخدم.StreamItemPhotos الصورة التي تحتوي على الصورة صفوف لعنصر مصدر بيانات واحد.
تفاعلات ساحة المشاركات على وسائل التواصل الاجتماعي
توفّر بيانات "البثّ الاجتماعي" التي يديرها "مزوّد جهات الاتصال"، إلى جانب تطبيق جهات اتصال الجهاز، طريقة فعّالة لربط نظام الشبكات الاجتماعية بجهات الاتصال الحالية. تتوفّر الميزات التالية:
- من خلال مزامنة خدمة الشبكات الاجتماعية مع مقدم جهات الاتصال باستخدام مزامنة محوّل، يمكنك استرداد الأنشطة الحديثة لجهات اتصال المستخدم وتخزينها في android.provider.ContactsContact.StreamItems. جداول android.provider.ContactItemPhotos لاستخدامها لاحقًا.
- إلى جانب المزامنة المنتظمة، يمكنك تشغيل محول المزامنة لاسترداد بيانات إضافية عندما يختار المستخدم جهة اتصال لعرضها. يتيح هذا الإجراء لمحول المزامنة لاسترداد الصور العالية الدقة وأحدث عناصر البث لجهة الاتصال.
- من خلال تسجيل إشعار في تطبيق جهات الاتصال على الجهاز وجهات الاتصال يمكنك الحصول على هدف عند عرض جهة اتصال، وعند هذه النقطة تعديل حالة جهة الاتصال من خدمتك قد يكون هذا الأسلوب أسرع ويستخدم معدل نقل بيانات أقل مقارنةً بإجراء مزامنة كاملة باستخدام محوِّل مزامنة.
- يمكن للمستخدمين إضافة جهة اتصال إلى خدمة شبكات التواصل الاجتماعي أثناء الاطّلاع على جهة الاتصال. في تطبيق جهات الاتصال على الجهاز. يمكنك تفعيل هذه الميزة باستخدام ميزة "دعوة جهة اتصال"، والتي يمكنك تفعيلها من خلال نشاط يضيف جهة اتصال حالية إلى الشبكة وملف XML يقدّم لتطبيق جهات الاتصال على الجهاز ومقدّم "جهات الاتصال" تفاصيل تطبيقك.
إن المزامنة المنتظمة لعناصر البث مع "مقدم جهات الاتصال" هي نفسها مزامنات أخرى. لمعرفة المزيد من المعلومات عن المزامنة، يمكنك الاطّلاع على القسم. محوّلات مزامنة موفّر جهات الاتصال يتم تناول تسجيل الإشعارات دعوة جهات الاتصال في القسمَين التاليَين.
التسجيل للتعامل مع مشاهدات الشبكات الاجتماعية
لتسجيل محوّل المزامنة لتلقّي إشعارات عندما يعرض المستخدم جهة اتصال تتم إدارتها بواسطة محوّل المزامنة:
-
أنشئ ملفًا باسم
contacts.xml
في الدليلres/xml/
في مشروعك. إذا كان لديك هذا الملف من قبل، يمكنك تخطّي هذه الخطوة. -
في هذا الملف، أضِف العنصر
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">
إذا كان هذا العنصر متوفّرًا، يمكنك تخطّي هذه الخطوة. -
لتسجيل خدمة يتم إشعارها عندما يفتح المستخدم صفحة تفاصيل جهة اتصال في
تطبيق جهات اتصال الجهاز، أضف السمة
viewContactNotifyService="serviceclass"
إلى العنصر، حيثserviceclass
هو اسم الفئة المؤهّل بالكامل للخدمة التي يُفترض أن تتلقى الغرض من تطبيق جهات الاتصال في الجهاز. بالنسبة إلى مُرسِل الإشعار خدمة، استخدم فئة تمتد إلىIntentService
، للسماح للخدمة تحقيق الأهداف. تشتمل البيانات الواردة في رسالة intent الواردة على معرّف الموارد المنتظم (URI) للمحتوى الاتصال التي نقر عليها المستخدم. من خدمة المُرسِل، يمكنك الربط ثمّ الاتصال بمحسِّن المزامنة لتعديل بيانات جهة الاتصال الأوّلية.
لتسجيل نشاط ليتم استدعاؤه عندما ينقر المستخدم على عنصر ساحة مشاركات أو صورة أو كليهما:
-
أنشئ ملفًا باسم
contacts.xml
في الدليلres/xml/
في مشروعك. إذا كان لديك هذا الملف، يمكنك تخطّي هذه الخطوة. -
في هذا الملف، أضِف العنصر
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">
إذا كان هذا العنصر موجودًا من قبل، يمكنك تخطي هذه الخطوة. -
لتسجيل أحد أنشطتك للتعامل مع نقر المستخدم على عنصر ساحة المشاركات في
تطبيق جهات الاتصال في الجهاز، أضف السمة
viewStreamItemActivity="activityclass"
إلى العنصر، حيثactivityclass
هو اسم الفئة المؤهّل بالكامل للنشاط التي يُفترض أن تتلقى الغرض من تطبيق جهات الاتصال في الجهاز. -
لتسجيل أحد الأنشطة الخاصة بك لمعالجة النقر على صورة بث في
تطبيق جهات اتصال الجهاز، أضِف السمة
viewStreamItemPhotoActivity="activityclass"
إلى العنصر، حيث يكونactivityclass
هو اسم فئة النشاط المؤهَّل بالكامل الذي من المفترض أن يتلقّى النية من تطبيق جهات اتصال الجهاز.
ويتوفّر شرح أكثر تفصيلاً للعنصر <ContactsAccountType>
في
القسم <ContactsAccountType> .
يحتوي الإجراء الوارد على معرّف الموارد الموحّد للمحتوى الخاص بالعنصر أو الصورة التي نقر عليها المستخدم. لإجراء أنشطة منفصلة للعناصر النصية وللصور، استخدِم السمتَين في الملف نفسه.
التفاعل مع خدمة الشبكات الاجتماعية
لا يضطر المستخدمون إلى مغادرة تطبيق جهات الاتصال في الجهاز لدعوة جهة اتصال إلى حسابك على وسائل التواصل الاجتماعي للتواصل الاجتماعي. بدلاً من ذلك، يمكنك أن تطلب من تطبيق جهات اتصال الجهاز إرسال نية لدعوة جهة الاتصال إلى أحد الأنشطة. لإعداد هذه الميزة:
-
أنشئ ملفًا باسم "
contacts.xml
" في "res/xml/
" الخاص بمشروعك. الدليل. إذا كان لديك هذا الملف من قبل، يمكنك تخطّي هذه الخطوة. -
في هذا الملف، أضِف العنصر
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">
إذا كان هذا العنصر متوفّرًا، يمكنك تخطّي هذه الخطوة. -
أضِف السمات التالية:
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
. إضافة واحد
عنصر <ContactsDataKind>
لكل نوع MIME مخصّص تستخدمه ليس لديك
لإضافة العنصر إذا كان لديك صف بيانات مخصص لا تريد عرض بيانات له.
السمات:
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
، باستخدام نوع ContactsContract.CommonDataKinds.GroupMembership
MIME.
إذا كنت تصمم محوّل مزامنة سيضيف بيانات جهات اتصال أولية من
إلى موفّر جهات الاتصال، ولا تستخدم مجموعات، فعليك إبلاغ
موفّر الخدمة لجعل بياناتك مرئية. في الرمز البرمجي الذي يتم تنفيذه عندما يضيف مستخدم حسابًا
إلى الجهاز، عدِّل صف ContactsContract.Settings
الذي يضيفه مقدّم خدمة جهات الاتصال للحساب. في هذا الصف، عيِّن قيمة
عمود Settings.UNGROUPED_VISIBLE
إلى 1. وعند القيام بذلك، سيقوم موفِّر جهات الاتصال دائمًا
تجعل بيانات جهات الاتصال مرئية، حتى إذا لم تكن تستخدم المجموعات.
صور المستخدمين المدرَجين في جهات الاتصال
يخزِّن جدول ContactsContract.Data
الصور كصفوف من النوع MIME
Photo.CONTENT_ITEM_TYPE
. يمثل الصف
تم ربط عمود "CONTACT_ID
" بـ
العمود _ID
من جهة الاتصال الأولية التي ينتمي إليها.
تحدد الفئة ContactsContract.Contacts.Photo
جدولاً فرعيًا
ContactsContract.Contacts
يحتوي على معلومات الصورة الخاصة بجهة اتصال
الصورة الأساسية، وهي الصورة الأساسية لجهة الاتصال الأولية لجهة الاتصال. وبالمثل،
الفئة ContactsContract.RawContacts.DisplayPhoto
تحدد جدولاً فرعيًا
من ContactsContract.RawContacts
تحتوي على معلومات صورة
الصورة الأساسية لجهة الاتصال الأولية.
المستندات المرجعية لـ ContactsContract.Contacts.Photo
تحتوي السمة ContactsContract.RawContacts.DisplayPhoto
على أمثلة
استرداد معلومات الصورة. لا تتوفّر فئة مساعدة لاسترداد المصغر الأساسي
لجهة اتصال غير معالجة، ولكن يمكنك إرسال طلب بحث إلى جدول
ContactsContract.Data
، واختيار عمود
_ID
وعمود
Photo.CONTENT_ITEM_TYPE
وعمود IS_PRIMARY
للعثور على صف الصورة الأساسية لجهة الاتصال غير المعالجة.
قد تتضمّن أيضًا بيانات "البثّ الاجتماعي" الخاصة بمستخدم صورًا. ويتم تخزينها في جدول android.provider.ContactsContract.StreamItemPhotos، والذي تم وصفه بالتفصيل في القسم صور خلاصة الشبكات الاجتماعية.