موفر التقويم هو مستودع لأحداث تقويم المستخدم. تسمح لك واجهة برمجة التطبيقات Calendar Provider API بإجراء طلبات بحث وإدراج وتحديث وحذف العمليات على التقاويم والأحداث والضيوف والتذكيرات وما إلى ذلك.
يمكن استخدام واجهة برمجة التطبيقات لموفّري خدمات التقويم من خلال التطبيقات ومحوّلات المزامنة. تختلف القواعد اعتمادًا على نوع البرنامج الذي يقوم بإجراء المكالمات. يركز هذا المستند بشكل أساسي على استخدام واجهة برمجة التطبيقات لموفّري خدمات التقويم كتطبيق. للاطّلاع على مناقشة حول أوجه الاختلاف بين محوّلات المزامنة، يُرجى مراجعة محوّلات المزامنة.
عادةً، لقراءة بيانات التقويم أو كتابتها، يجب أن يتضمن بيان التطبيق الأذونات المناسبة، الموضَّحة في أذونات المستخدم. لتسهيل تنفيذ العمليات الشائعة، يقدِّم موفّر خدمة التقويم مجموعة من الأغراض، كما هو موضّح في أهداف التقويم. تنقل هذه الأغراض المستخدمين إلى تطبيق "تقويم Google" لإدراج الأحداث وعرضها وتعديلها. يتفاعل المستخدم مع تطبيق التقويم ثم يعود إلى التطبيق الأصلي. وبالتالي، لا يحتاج تطبيقك إلى طلب أذونات، ولا يحتاج إلى توفير واجهة مستخدم لعرض الأحداث أو إنشائها.
الأساسيات
يخزّن موفرو المحتوى البيانات ويتيح وصول التطبيقات إليها. عادةً ما يعرض موفرو المحتوى الذي يوفره نظام Android الأساسي (بما في ذلك موفر التقويم) البيانات كمجموعة من الجداول استنادًا إلى نموذج قاعدة البيانات الارتباطية، حيث يكون كل صف عبارة عن سجل وكل عمود عبارة عن بيانات من نوع معين ومعنى معين. من خلال واجهة برمجة التطبيقات لموفّر خدمات التقويم، يمكن للتطبيقات ومحوّلات المزامنة الحصول على إذن وصول للقراءة/الكتابة إلى جداول قاعدة البيانات التي تحتوي على بيانات تقويم المستخدم.
يعرض كل موفّر محتوى معرّف موارد منتظم (URI) علني (يتم وضعه في شكل كائن Uri
) يُعرّف مجموعة بياناته بشكل فريد. فموفّر المحتوى الذي يتحكّم
في مجموعات بيانات متعددة (جداول متعددة) يعرض معرّف موارد منتظم (URI) منفصل لكل مجموعة. تبدأ جميع معرفات الموارد المنتظمة (URI) للموفرين بالسلسلة "content://". وهذا يحدد أن البيانات تخضع لتحكم موفّر المحتوى. يحدد موفّر التقويم الثوابت لعناوين URL لكل فئة من فئاته (الجداول). وتكون معرّفات الموارد المنتظمة (URI) هذه بالتنسيق <class>.CONTENT_URI
. على سبيل المثال، Events.CONTENT_URI
.
يوضح الشكل 1 تمثيلاً رسوميًا لنموذج بيانات موفّر التقويم. وهو يعرض الجداول الرئيسية والحقول التي تربطها ببعضها البعض.
![نموذج بيانات موفّر التقويم](https://developer.android.google.cn/static/images/providers/datamodel.png?authuser=0000&hl=ar)
الشكل 1. نموذج بيانات موفّر التقويم.
يمكن أن يمتلك المستخدم عدة تقاويم، كما يمكن ربط تقاويم مختلفة بأنواع مختلفة من الحسابات ("تقويم Google" وExchange وما إلى ذلك).
تحدِّد CalendarContract
نموذج البيانات للمعلومات ذات الصلة بالتقويم والأحداث. ويتم تخزين هذه البيانات في عدد من الجداول المدرجة أدناه.
الجدول (الفئة) | الوصف |
---|---|
يحتوي هذا الجدول على المعلومات الخاصة بالتقويم. يحتوي كل صف في هذا الجدول على تفاصيل تقويم واحد، مثل الاسم واللون ومعلومات المزامنة وما إلى ذلك. | |
CalendarContract.Events |
يحتوي هذا الجدول على
المعلومات الخاصة بالحدث. يحتوي كل صف في هذا الجدول على معلومات عن حدث واحد، مثل عنوان الفعالية والموقع الجغرافي ووقت البدء ووقت الانتهاء وغير ذلك. يمكن أن يقع الحدث لمرة واحدة أو يمكن أن يتكرّر عدة مرات. يتم تخزين الضيوف
والتذكيرات والخصائص الموسعة في جداول منفصلة.
ويتضمّن كل منها EVENT_ID
يشير إلى _ID في جدول "الأحداث". |
CalendarContract.Instances |
يحتوي هذا الجدول على وقت البدء والانتهاء لكل موضع ورود للحدث. يمثل كل صف في هذا الجدول موضع ورود حدث واحد. بالنسبة إلى الأحداث لمرة واحدة، يتوفّر تعيين 1:1 للمثيلات للأحداث. بالنسبة إلى الأحداث المتكرّرة، يتم إنشاء صفوف متعدّدة تلقائيًا تتوافق مع تكرارات متعددة لهذا الحدث. |
CalendarContract.Attendees |
يحتوي هذا الجدول على معلومات الحضور (الضيوف) في الحدث. يمثل كل صف ضيفًا واحدًا في حدث ما. وهي تحدد نوع الضيف وردود حضور الضيف للحدث. |
CalendarContract.Reminders |
يحتوي هذا الجدول على
بيانات التنبيه/الإشعارات. يمثل كل صف تنبيهًا واحدًا لحدث. يمكن أن يتضمن الحدث
تذكيرات متعددة. يتم تحديد الحد الأقصى لعدد التذكيرات لكل حدث
في
MAX_REMINDERS ، الذي يتم ضبطه من خلال محوِّل المزامنة
الذي يملك التقويم المحدد. يتم تحديد التذكيرات قبل الحدث بدقائق،
وتكون لها طريقة تحدد كيفية تنبيه المستخدم. |
تم تصميم واجهة برمجة التطبيقات لموفّري خدمات التقويم لتكون مرنة وفعّالة. في نفس الوقت، من المهم توفير تجربة مستخدم نهائي جيدة وحماية سلامة التقويم وبياناته. تحقيقًا لهذه الغاية، إليك بعض الأشياء التي يجب مراعاتها عند استخدام واجهة برمجة التطبيقات:
- إدراج أحداث التقويم وتعديلها وعرضها لإدراج الأحداث وتعديلها وقراءتها مباشرةً من موفّر "تقويم Google"، تحتاج إلى الأذونات المناسبة. ومع ذلك، إذا كنت لا تنشئ تطبيق تقويم كاملاً أو محوّل مزامنة، لا يلزم طلب هذه الأذونات. يمكنك بدلاً من ذلك استخدام الأغراض المتوافقة مع تطبيق "تقويم Google" على Android لتسليم عمليات القراءة والكتابة إلى هذا التطبيق. عند استخدام الأغراض، يرسل تطبيقك المستخدمين إلى تطبيق "تقويم Google" لتنفيذ العملية المطلوبة من خلال نموذج معبأ مسبقًا. وبعد انتهائها، يتم إرجاعها إلى طلبك. عند تصميم التطبيق لتنفيذ عمليات شائعة من خلال التقويم، تزود المستخدمين بواجهة مستخدم متسقة وقوية. وهذا هو النهج الموصى به. لمزيد من المعلومات، راجِع أهداف التقويم.
- مزامنة المحوّلات: يعمل محوِّل المزامنة على مزامنة بيانات التقويم على جهاز المستخدم مع خادم آخر أو مصدر بيانات آخر. في الجدولين
CalendarContract.Calendars
وCalendarContract.Events
، توجد أعمدة محجوزة لاستخدام محوّلات المزامنة. ويجب ألا يُعدِّلها الموفِّر والتطبيقات. في الواقع، لن تكون مرئية إلا إذا تم الوصول إليها كمحوّل مزامنة. لمزيد من المعلومات عن محوّلات المزامنة، يمكنك الاطّلاع على محوّلات المزامنة.
أذونات المستخدمين
لقراءة بيانات التقويم، يجب أن يتضمّن التطبيق الإذن READ_CALENDAR
في ملف البيان. يجب أن يتضمّن
الإذن WRITE_CALENDAR
لحذف بيانات التقويم أو إدراجها أو تعديلها:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"...> <uses-sdk android:minSdkVersion="14" /> <uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.WRITE_CALENDAR" /> ... </manifest>
جدول التقاويم
يحتوي الجدول CalendarContract.Calendars
على تفاصيل
لتقاويم فردية. أعمدة "التقاويم" التالية قابلة للكتابة من قِبل كل من التطبيق ومحوّل المزامنة.
للاطّلاع على قائمة كاملة بالحقول المتوافقة، يُرجى مراجعة
مرجع CalendarContract.Calendars
.
ثابت | الوصف |
---|---|
NAME |
اسم التقويم. |
CALENDAR_DISPLAY_NAME |
اسم هذا التقويم الذي يتم عرضه للمستخدم. |
VISIBLE |
قيمة منطقية تشير إلى ما إذا كان قد تم اختيار التقويم لعرضه أم لا. وتشير القيمة 0 إلى أنه يجب عدم عرض الأحداث المرتبطة بهذا التقويم. تشير القيمة 1 إلى أنه يجب عرض الأحداث المرتبطة بهذا التقويم. تؤثّر هذه القيمة في إنشاء الصفوف في جدول "CalendarContract.Instances ". |
SYNC_EVENTS |
قيمة منطقية تشير إلى ما إذا كان يجب مزامنة التقويم وتخزين أحداثه على الجهاز أم لا. تشير القيمة 0 إلى عدم مزامنة هذا التقويم أو تخزين أحداثه على الجهاز. تشير القيمة 1 إلى مزامنة الأحداث لهذا التقويم وتخزين أحداثه على الجهاز. |
تضمين نوع حساب لجميع العمليات
إذا أجريت طلب بحث على Calendars.ACCOUNT_NAME
، يجب أيضًا تضمين
Calendars.ACCOUNT_TYPE
في الاختيار. ويعود سبب ذلك إلى أنّ الحساب نفسه لا يُعدّ فريدًا إلّا استنادًا إلى كلٍّ من ACCOUNT_NAME
وACCOUNT_TYPE
الخاص به. ACCOUNT_TYPE
هي السلسلة المقابلة لبرنامج مصادقة الحساب الذي تم استخدامه عندما تم تسجيل الحساب في AccountManager
. هناك أيضًا نوع خاص من الحسابات يسمى ACCOUNT_TYPE_LOCAL
للتقاويم غير المرتبطة بحساب جهاز.
لا تتم مزامنة حسابات ACCOUNT_TYPE_LOCAL
.
إجراء طلب بحث في تقويم
إليك مثال يوضح كيفية الحصول على التقاويم التي يملكها مستخدم معين. للتيسير، في هذا المثال، تظهر عملية طلب البحث في سلسلة واجهة المستخدم ("سلسلة التعليمات الرئيسية"). عمليًا، يجب أن يتم ذلك في سلسلة غير متزامنة
بدلاً من سلسلة التعليمات الرئيسية. لمزيد من النقاش، راجع
Loaders. إذا كنت لا تقرأ فقط البيانات
بل تعدِّلها، يمكنك الاطّلاع على AsyncQueryHandler
.
Kotlin
// Projection array. Creating indices for this array instead of doing // dynamic lookups improves performance. private val EVENT_PROJECTION: Array<String> = arrayOf( CalendarContract.Calendars._ID, // 0 CalendarContract.Calendars.ACCOUNT_NAME, // 1 CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, // 2 CalendarContract.Calendars.OWNER_ACCOUNT // 3 ) // The indices for the projection array above. private const val PROJECTION_ID_INDEX: Int = 0 private const val PROJECTION_ACCOUNT_NAME_INDEX: Int = 1 private const val PROJECTION_DISPLAY_NAME_INDEX: Int = 2 private const val PROJECTION_OWNER_ACCOUNT_INDEX: Int = 3
Java
// Projection array. Creating indices for this array instead of doing // dynamic lookups improves performance. public static final String[] EVENT_PROJECTION = new String[] { Calendars._ID, // 0 Calendars.ACCOUNT_NAME, // 1 Calendars.CALENDAR_DISPLAY_NAME, // 2 Calendars.OWNER_ACCOUNT // 3 }; // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1; private static final int PROJECTION_DISPLAY_NAME_INDEX = 2; private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;
في الجزء التالي من المثال، تقوم بإنشاء الاستعلام الخاص بك. يحدد التحديد معايير الاستعلام. في هذا المثال، يبحث طلب البحث عن
التقاويم التي تحتوي على ACCOUNT_NAME
"hera@example.com" وACCOUNT_TYPE
"com.example" وOWNER_ACCOUNT
"hera@example.com". إذا كنت تريد الاطّلاع على جميع التقاويم التي اطّلع عليها المستخدم
وليس فقط التقاويم التي يملكها المستخدم، احذف OWNER_ACCOUNT
.
يعرض طلب البحث كائن Cursor
يمكنك استخدامه لاجتياز مجموعة النتائج التي يعرضها استعلام قاعدة البيانات. لمزيد من المناقشة حول استخدام طلبات البحث في موفري المحتوى،
راجع مقدمو المحتوى.
Kotlin
// Run query val uri: Uri = CalendarContract.Calendars.CONTENT_URI val selection: String = "((${CalendarContract.Calendars.ACCOUNT_NAME} = ?) AND (" + "${CalendarContract.Calendars.ACCOUNT_TYPE} = ?) AND (" + "${CalendarContract.Calendars.OWNER_ACCOUNT} = ?))" val selectionArgs: Array<String> = arrayOf("hera@example.com", "com.example", "hera@example.com") val cur: Cursor = contentResolver.query(uri, EVENT_PROJECTION, selection, selectionArgs, null)
Java
// Run query Cursor cur = null; ContentResolver cr = getContentResolver(); Uri uri = Calendars.CONTENT_URI; String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" + Calendars.ACCOUNT_TYPE + " = ?) AND (" + Calendars.OWNER_ACCOUNT + " = ?))"; String[] selectionArgs = new String[] {"hera@example.com", "com.example", "hera@example.com"}; // Submit the query and get a Cursor object back. cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);
يستخدم هذا القسم التالي المؤشر للتنقل بين مجموعة النتائج. وهو يستخدم الثوابت التي تم إعدادها في بداية المثال لإرجاع القيم لكل حقل.
Kotlin
// Use the cursor to step through the returned records while (cur.moveToNext()) { // Get the field values val calID: Long = cur.getLong(PROJECTION_ID_INDEX) val displayName: String = cur.getString(PROJECTION_DISPLAY_NAME_INDEX) val accountName: String = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX) val ownerName: String = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX) // Do something with the values... }
Java
// Use the cursor to step through the returned records while (cur.moveToNext()) { long calID = 0; String displayName = null; String accountName = null; String ownerName = null; // Get the field values calID = cur.getLong(PROJECTION_ID_INDEX); displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX); accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX); ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX); // Do something with the values... ... }
تعديل تقويم
لإجراء تحديث تقويم، يمكنك توفير _ID
في التقويم إما كمعرّف ملحق بمعرّف الموارد المنتظم (URI)
(withAppendedId()
)
أو كأول عنصر اختيار. يجب أن يبدأ التحديد
بـ "_id=?"
، ويجب أن يكون أول selectionArg
هو _ID
بالتقويم.
يمكنك أيضًا إجراء التحديثات من خلال ترميز المعرّف في معرّف الموارد المنتظم (URI). يغير هذا المثال
اسم عرض التقويم باستخدام نهج
(withAppendedId()
)
:
Kotlin
const val DEBUG_TAG: String = "MyActivity" ... val calID: Long = 2 val values = ContentValues().apply { // The new display name for the calendar put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar") } val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Calendars.CONTENT_URI, calID) val rows: Int = contentResolver.update(updateUri, values, null, null) Log.i(DEBUG_TAG, "Rows updated: $rows")
Java
private static final String DEBUG_TAG = "MyActivity"; ... long calID = 2; ContentValues values = new ContentValues(); // The new display name for the calendar values.put(Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar"); Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID); int rows = getContentResolver().update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows);
إدراج تقويم
تم تصميم التقاويم بحيث تتم إدارتها بشكل أساسي بواسطة محوّل مزامنة، لذا يجب عليك
إدراج التقاويم الجديدة فقط كمحوّل مزامنة. في الغالب، يمكن للتطبيقات إجراء تغييرات سطحية على التقاويم فقط، مثل تغيير الاسم المعروض. إذا احتاج أحد التطبيقات إلى إنشاء تقويم محلي، يمكنه إجراء ذلك عن طريق تنفيذ إدراج التقويم كمحوّل مزامنة، باستخدام ACCOUNT_TYPE
من ACCOUNT_TYPE_LOCAL
.
ACCOUNT_TYPE_LOCAL
هو نوع حساب خاص للتقاويم غير المرتبطة بحساب جهاز. لا تتم مزامنة تقاويم من هذا النوع مع خادم. لمناقشة محوّلات المزامنة، يُرجى الاطّلاع على محوّلات المزامنة.
جدول الأحداث
يحتوي الجدول "CalendarContract.Events
" على تفاصيل
للأحداث الفردية. لإضافة الأحداث أو تعديلها أو حذفها، يجب أن يتضمّن التطبيق
الإذن WRITE_CALENDAR
في
ملف البيان.
يمكن الكتابة في أعمدة الأحداث التالية بواسطة التطبيق ومحوِّل المزامنة. للحصول على قائمة كاملة بالحقول المتوافقة، يُرجى الاطّلاع على مرجع CalendarContract.Events
.
ثابت | الوصف |
---|---|
CALENDAR_ID |
_ID من التقويم الذي ينتمي إليه الحدث. |
ORGANIZER |
عنوان البريد الإلكتروني لمنظِّم (مالك) الحدث |
TITLE |
تمثّل هذه السمة عنوان الفعالية. |
EVENT_LOCATION |
مكان وقوع الحدث. |
DESCRIPTION |
وصف الحدث. |
DTSTART |
وقت بدء الحدث بالملي ثانية حسب التوقيت العالمي المتفق عليه منذ البداية. |
DTEND |
وقت انتهاء الحدث بالملي ثانية حسب التوقيت العالمي المتفق عليه منذ البداية. |
EVENT_TIMEZONE |
المنطقة الزمنية للحدث. |
EVENT_END_TIMEZONE |
المنطقة الزمنية لوقت انتهاء الحدث. |
DURATION |
تمثّل هذه السمة مدة الحدث بتنسيق RFC5545.
على سبيل المثال، تشير قيمة "PT1H" إلى أن الحدث
يجب أن يستمر ساعة واحدة، بينما تشير القيمة "P2W" إلى
المدة التي تبلغ أسبوعين. |
ALL_DAY |
تشير القيمة 1 إلى أنّ هذا الحدث يستغرق اليوم بأكمله، كما هو محدّد في المنطقة الزمنية المحلية. تشير القيمة 0 إلى أنه حدث عادي قد يبدأ وينتهي في أي وقت خلال اليوم. |
RRULE |
قاعدة التكرار لتنسيق الحدث على سبيل المثال، "FREQ=WEEKLY;COUNT=10;WKST=SU" . يمكنك العثور على
المزيد من الأمثلة هنا. |
RDATE |
تواريخ تكرار الحدث.
أنت تستخدم عادةً السمة RDATE
جنبًا إلى جنب مع RRULE
لتحديد مجموعة مجمّعة من
مرات التكرار المتكررة. لمزيد من المناقشة، يمكنك الاطّلاع على مواصفات RFC5545. |
AVAILABILITY |
إذا كان هذا الحدث يُعتبر وقتًا مشغولاً أو هو وقت فراغ يمكن جدولته. |
GUESTS_CAN_MODIFY |
ما إذا كان يمكن للمدعوين تعديل الحدث. |
GUESTS_CAN_INVITE_OTHERS |
ما إذا كان يمكن للمدعوين دعوة مدعوين آخرين. |
GUESTS_CAN_SEE_GUESTS |
ما إذا كان يمكن للمدعوين الاطّلاع على قائمة الضيوف. |
إضافة أحداث
عندما يُدرج تطبيقك حدثًا جديدًا، ننصحك باستخدام
INSERT
Intent، على النحو الموضَّح في استخدام هدف لإدراج حدث. ومع ذلك، يمكنك إدراج الأحداث مباشرةً إذا كنت بحاجة إلى ذلك. يصف هذا القسم
كيفية القيام بذلك.
في ما يلي قواعد إدراج حدث جديد:
- يجب تضمين
CALENDAR_ID
وDTSTART
. - يجب تضمين
EVENT_TIMEZONE
. وللحصول على قائمة بأرقام تعريف المنطقة الزمنية المثبّتة في النظام، استخدِم السمةgetAvailableIDs()
. يُرجى العلم أنّ هذه القاعدة لا تنطبق في حال كنت تُدرِج حدثًا من خلال هدفINSERT
الموضّح في قسم استخدام نية لإدراج حدث، في هذا السيناريو، يتمّ توفير منطقة زمنية تلقائية. - بالنسبة إلى الأحداث غير المتكرّرة، يجب تضمين
DTEND
. - بالنسبة إلى الأحداث المتكرّرة، يجب تضمين
DURATION
بالإضافة إلىRRULE
أوRDATE
. يُرجى العلم أنّ هذه القاعدة لا تنطبق في حال كنت تُدرِج حدثًا من خلال هدفINSERT
الموضّح في قسم استخدام هدف لإدراج حدث. وفي هذا السيناريو، يمكنك استخدام الشرطRRULE
بالتزامن معDTSTART
وDTEND
، وسيحوّله تطبيق "تقويم Google" إلى مدة تلقائيًا.
في ما يلي مثال لإدراج حدث. يتم تنفيذ ذلك في مؤشر ترابط
واجهة المستخدم من أجل البساطة. من الناحية العملية، يجب أن تتم عمليات الإدراج والتحديثات في سلسلة محادثات غير متزامنة لنقل الإجراء إلى سلسلة محادثات في الخلفية. لمزيد من المعلومات، يُرجى الاطّلاع على "AsyncQueryHandler
".
Kotlin
val calID: Long = 3 val startMillis: Long = Calendar.getInstance().run { set(2012, 9, 14, 7, 30) timeInMillis } val endMillis: Long = Calendar.getInstance().run { set(2012, 9, 14, 8, 45) timeInMillis } ... val values = ContentValues().apply { put(CalendarContract.Events.DTSTART, startMillis) put(CalendarContract.Events.DTEND, endMillis) put(CalendarContract.Events.TITLE, "Jazzercise") put(CalendarContract.Events.DESCRIPTION, "Group workout") put(CalendarContract.Events.CALENDAR_ID, calID) put(CalendarContract.Events.EVENT_TIMEZONE, "America/Los_Angeles") } val uri: Uri = contentResolver.insert(CalendarContract.Events.CONTENT_URI, values) // get the event ID that is the last element in the Uri val eventID: Long = uri.lastPathSegment.toLong() // // ... do something with event ID // //
Java
long calID = 3; long startMillis = 0; long endMillis = 0; Calendar beginTime = Calendar.getInstance(); beginTime.set(2012, 9, 14, 7, 30); startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2012, 9, 14, 8, 45); endMillis = endTime.getTimeInMillis(); ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(Events.DTSTART, startMillis); values.put(Events.DTEND, endMillis); values.put(Events.TITLE, "Jazzercise"); values.put(Events.DESCRIPTION, "Group workout"); values.put(Events.CALENDAR_ID, calID); values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles"); Uri uri = cr.insert(Events.CONTENT_URI, values); // get the event ID that is the last element in the Uri long eventID = Long.parseLong(uri.getLastPathSegment()); // // ... do something with event ID // //
ملاحظة: اطّلِع على كيفية تسجيل هذا المثال لرقم تعريف الحدث بعد إنشائه. هذه هي أسهل طريقة للحصول على رقم تعريف الحدث. وغالبًا ما تحتاج إلى رقم تعريف الحدث لتنفيذ عمليات أخرى في التقويم، مثلاً لإضافة الضيوف أو التذكيرات إلى فعالية.
تحديث الأحداث
عندما يريد تطبيقك السماح للمستخدم بتعديل حدث، ننصحك
باستخدام هدف EDIT
، كما هو موضّح في
استخدام هدف لتعديل حدث.
ومع ذلك، يمكنك تعديل الأحداث مباشرةً إذا كنت بحاجة إلى ذلك. لإجراء تحديث
لحدث ما، يمكنك توفير _ID
للحدث إما كمعرّف ملحق لمعرّف الموارد المنتظم (URI) (withAppendedId()
)
أو كأول عنصر محدّد.
يجب أن يبدأ الاختيار بـ "_id=?"
، ويجب أن يكون أول selectionArg
هو _ID
للفعالية. يمكنك أيضًا إجراء تعديلات باستخدام مجموعة محددة بدون معرّف. فيما يلي مثال على تحديث حدث. يغير عنوان الحدث باستخدام
نهج withAppendedId()
:
Kotlin
val DEBUG_TAG = "MyActivity" ... val eventID: Long = 188 ... val values = ContentValues().apply { // The new title for the event put(CalendarContract.Events.TITLE, "Kickboxing") } val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val rows: Int = contentResolver.update(updateUri, values, null, null) Log.i(DEBUG_TAG, "Rows updated: $rows")
Java
private static final String DEBUG_TAG = "MyActivity"; ... long eventID = 188; ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); Uri updateUri = null; // The new title for the event values.put(Events.TITLE, "Kickboxing"); updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = cr.update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows);
حذف الأحداث
يمكنك حذف حدث إما من خلال _ID
كمعرّف ملحق على معرّف الموارد المنتظم (URI) أو باستخدام
الاختيار العادي. إذا استخدمت معرّفًا ملحقًا، لن تتمكّن من الاختيار أيضًا.
هناك نسختان من الحذف: كتطبيق وكمحول مزامنة. يضبط حذف التطبيق العمود محذوف على 1. هذه العلامة التي تخبر محوِّل المزامنة بأنه تم حذف الصف وأنه يجب نشر هذا الحذف على الخادم. يؤدي حذف محوِّل المزامنة إلى إزالة الحدث من قاعدة البيانات مع جميع البيانات المرتبطة به. إليك مثال على حذف التطبيق لحدث من خلال _ID
:
Kotlin
val DEBUG_TAG = "MyActivity" ... val eventID: Long = 201 ... val deleteUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val rows: Int = contentResolver.delete(deleteUri, null, null) Log.i(DEBUG_TAG, "Rows deleted: $rows")
Java
private static final String DEBUG_TAG = "MyActivity"; ... long eventID = 201; ... ContentResolver cr = getContentResolver(); Uri deleteUri = null; deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = cr.delete(deleteUri, null, null); Log.i(DEBUG_TAG, "Rows deleted: " + rows);
جدول الضيوف
ويمثل كل صف من جدول CalendarContract.Attendees
ضيفًا أو ضيفًا واحدًا في الحدث. يؤدي استدعاء
query()
إلى عرض قائمة بضيوف
الحدث مع EVENT_ID
المحدّد.
يجب أن يتطابق EVENT_ID
مع _ID
لحدث معيّن.
يسرد الجدول التالي الحقول
القابلة للكتابة. عند إدراج ضيف جديد، يجب تضمينه جميعًا
باستثناء ATTENDEE_NAME
.
ثابت | الوصف |
---|---|
EVENT_ID |
رقم تعريف الحدث. |
ATTENDEE_NAME |
اسم الضيف |
ATTENDEE_EMAIL |
عنوان البريد الإلكتروني للضيف |
ATTENDEE_RELATIONSHIP |
علاقة الضيف بالحدث. واحد مما يلي: |
ATTENDEE_TYPE |
نوع الضيف واحد مما يلي: |
ATTENDEE_STATUS |
حالة حضور الضيف واحد مما يلي: |
إضافة ضيوف
إليك مثال لإضافة ضيف واحد إلى حدث. تجدر الإشارة إلى أنّ السمة
EVENT_ID
مطلوبة:
Kotlin
val eventID: Long = 202 ... val values = ContentValues().apply { put(CalendarContract.Attendees.ATTENDEE_NAME, "Trevor") put(CalendarContract.Attendees.ATTENDEE_EMAIL, "trevor@example.com") put( CalendarContract.Attendees.ATTENDEE_RELATIONSHIP, CalendarContract.Attendees.RELATIONSHIP_ATTENDEE ) put(CalendarContract.Attendees.ATTENDEE_TYPE, CalendarContract.Attendees.TYPE_OPTIONAL) put( CalendarContract.Attendees.ATTENDEE_STATUS, CalendarContract.Attendees.ATTENDEE_STATUS_INVITED ) put(CalendarContract.Attendees.EVENT_ID, eventID) } val uri: Uri = contentResolver.insert(CalendarContract.Attendees.CONTENT_URI, values)
Java
long eventID = 202; ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(Attendees.ATTENDEE_NAME, "Trevor"); values.put(Attendees.ATTENDEE_EMAIL, "trevor@example.com"); values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE); values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL); values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED); values.put(Attendees.EVENT_ID, eventID); Uri uri = cr.insert(Attendees.CONTENT_URI, values);
جدول التذكيرات
يمثل كل صف من صفوف الجدول CalendarContract.Reminders
تذكيرًا واحدًا لحدث ما. يؤدي استدعاء
query()
إلى عرض قائمة بالتذكيرات
للحدث باستخدام
EVENT_ID
المحدد.
يسرد الجدول التالي الحقول القابلة للكتابة للتذكيرات. يجب تضمينها جميعًا
عند إدراج تذكير جديد. تجدر الإشارة إلى أنّ محوّلات المزامنة تحدّد
أنواع التذكيرات المتوافقة في جدول CalendarContract.Calendars
. لمزيد من التفاصيل، يُرجى الانتقال إلى
ALLOWED_REMINDERS
.
ثابت | الوصف |
---|---|
EVENT_ID |
رقم تعريف الحدث. |
MINUTES |
الدقائق التي تسبق الحدث والتي يجب تنشيط التذكير فيها. |
METHOD |
طريقة الإنذار كما تم ضبطها على الخادم. واحد مما يلي: |
إضافة التذكيرات
يضيف هذا المثال تذكيرًا لحدث. يتم تنشيط التذكير قبل 15 دقيقة من الحدث.
Kotlin
val eventID: Long = 221 ... val values = ContentValues().apply { put(CalendarContract.Reminders.MINUTES, 15) put(CalendarContract.Reminders.EVENT_ID, eventID) put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT) } val uri: Uri = contentResolver.insert(CalendarContract.Reminders.CONTENT_URI, values)
Java
long eventID = 221; ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(Reminders.MINUTES, 15); values.put(Reminders.EVENT_ID, eventID); values.put(Reminders.METHOD, Reminders.METHOD_ALERT); Uri uri = cr.insert(Reminders.CONTENT_URI, values);
جدول المثيلات
ويتضمّن الجدول CalendarContract.Instances
وقتَي البدء والانتهاء لمرّات ورود الحدث. يمثل كل صف في هذا الجدول
موضع ورود حدث واحد. جدول المثيلات غير قابل للكتابة، ويوفّر فقط طريقة للاستعلام عن مواضع ورود الأحداث.
يسرد الجدول التالي بعض الحقول التي يمكنك الاستعلام عنها لمثيل. يُرجى العلم أنّه يتم تحديد المنطقة الزمنية باستخدام KEY_TIMEZONE_TYPE
وKEY_TIMEZONE_INSTANCES
.
ثابت | الوصف |
---|---|
BEGIN |
وقت بداية المثيل، بالمللي ثانية للتوقيت العالمي المتفق عليه. |
END |
وقت انتهاء المثيل، بالمللي ثانية من التوقيت العالمي المتفق عليه. |
END_DAY |
يوم الانتهاء الجولياني للمثيل، بالنسبة إلى المنطقة الزمنية في "تقويم Google". |
END_MINUTE |
دقيقة نهاية المثيل يتم قياسها من منتصف الليل في المنطقة الزمنية للتقويم. |
EVENT_ID |
تمثّل هذه السمة _ID للحدث الخاص بهذا المثيل. |
START_DAY |
يوم البدء الجولياني للمثيل، بالنسبة إلى المنطقة الزمنية في "تقويم Google". |
START_MINUTE |
دقيقة بدء المثيل التي يتم قياسها من منتصف الليل، بالنسبة إلى المنطقة الزمنية للتقويم. |
إرسال طلبات بحث في جدول المثيلات
للاستعلام عن جدول المثيلات، عليك تحديد وقت نطاق للاستعلام في URI. في هذا المثال، يحصل CalendarContract.Instances
على إذن الوصول إلى الحقل TITLE
من خلال
تنفيذه لواجهة CalendarContract.EventsColumns
.
بمعنى آخر، يتم عرض TITLE
من خلال
عرض قاعدة بيانات، وليس من خلال الاستعلام عن جدول CalendarContract.Instances
الأولي.
Kotlin
const val DEBUG_TAG: String = "MyActivity" val INSTANCE_PROJECTION: Array<String> = arrayOf( CalendarContract.Instances.EVENT_ID, // 0 CalendarContract.Instances.BEGIN, // 1 CalendarContract.Instances.TITLE // 2 ) // The indices for the projection array above. const val PROJECTION_ID_INDEX: Int = 0 const val PROJECTION_BEGIN_INDEX: Int = 1 const val PROJECTION_TITLE_INDEX: Int = 2 // Specify the date range you want to search for recurring // event instances val startMillis: Long = Calendar.getInstance().run { set(2011, 9, 23, 8, 0) timeInMillis } val endMillis: Long = Calendar.getInstance().run { set(2011, 10, 24, 8, 0) timeInMillis } // The ID of the recurring event whose instances you are searching // for in the Instances table val selection: String = "${CalendarContract.Instances.EVENT_ID} = ?" val selectionArgs: Array<String> = arrayOf("207") // Construct the query with the desired date range. val builder: Uri.Builder = CalendarContract.Instances.CONTENT_URI.buildUpon() ContentUris.appendId(builder, startMillis) ContentUris.appendId(builder, endMillis) // Submit the query val cur: Cursor = contentResolver.query( builder.build(), INSTANCE_PROJECTION, selection, selectionArgs, null ) while (cur.moveToNext()) { // Get the field values val eventID: Long = cur.getLong(PROJECTION_ID_INDEX) val beginVal: Long = cur.getLong(PROJECTION_BEGIN_INDEX) val title: String = cur.getString(PROJECTION_TITLE_INDEX) // Do something with the values. Log.i(DEBUG_TAG, "Event: $title") val calendar = Calendar.getInstance().apply { timeInMillis = beginVal } val formatter = SimpleDateFormat("MM/dd/yyyy") Log.i(DEBUG_TAG, "Date: ${formatter.format(calendar.time)}") }
Java
private static final String DEBUG_TAG = "MyActivity"; public static final String[] INSTANCE_PROJECTION = new String[] { Instances.EVENT_ID, // 0 Instances.BEGIN, // 1 Instances.TITLE // 2 }; // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_BEGIN_INDEX = 1; private static final int PROJECTION_TITLE_INDEX = 2; ... // Specify the date range you want to search for recurring // event instances Calendar beginTime = Calendar.getInstance(); beginTime.set(2011, 9, 23, 8, 0); long startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2011, 10, 24, 8, 0); long endMillis = endTime.getTimeInMillis(); Cursor cur = null; ContentResolver cr = getContentResolver(); // The ID of the recurring event whose instances you are searching // for in the Instances table String selection = Instances.EVENT_ID + " = ?"; String[] selectionArgs = new String[] {"207"}; // Construct the query with the desired date range. Uri.Builder builder = Instances.CONTENT_URI.buildUpon(); ContentUris.appendId(builder, startMillis); ContentUris.appendId(builder, endMillis); // Submit the query cur = cr.query(builder.build(), INSTANCE_PROJECTION, selection, selectionArgs, null); while (cur.moveToNext()) { String title = null; long eventID = 0; long beginVal = 0; // Get the field values eventID = cur.getLong(PROJECTION_ID_INDEX); beginVal = cur.getLong(PROJECTION_BEGIN_INDEX); title = cur.getString(PROJECTION_TITLE_INDEX); // Do something with the values. Log.i(DEBUG_TAG, "Event: " + title); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(beginVal); DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); } }
الأغراض من التقويم
لا يحتاج تطبيقك إلى أذونات لقراءة بيانات التقويم وكتابتها. وبدلاً من ذلك، يمكنه استخدام الأغراض التي يتيحها تطبيق "تقويم Google" على Android لتسليم عمليات القراءة والكتابة إلى هذا التطبيق. يسرد الجدول التالي الأغراض التي يتيحها موفّر خدمة "تقويم Google":
الإجراء | URI | الوصف | محتوى إضافي |
---|---|---|---|
VIEW |
CalendarContract.CONTENT_URI .
للحصول على مثال على استخدام هذا الغرض، راجع استخدام الأغراض لعرض بيانات التقويم.
|
فتح التقويم في الوقت المحدّد من قِبل <ms_since_epoch> . |
بلا عُري |
Events.CONTENT_URI .
للحصول على مثال على استخدام هذا الغرض، راجع استخدام الأغراض لعرض بيانات التقويم.
|
عرض الحدث المحدّد من قِبل "<event_id> " |
CalendarContract.EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_END_TIME |
|
EDIT |
Events.CONTENT_URI .
للاطّلاع على مثال على استخدام هذا الغرض، راجِع المقالة استخدام هدف لتعديل حدث.
|
تعديل الحدث الذي تم تحديده من قِبل "<event_id> " |
CalendarContract.EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_END_TIME |
EDIT INSERT |
Events.CONTENT_URI .
للاطّلاع على مثال عن استخدام هذا الغرض، راجِع المقالة استخدام غرض لإدراج حدث.
|
أنشِئ حدثًا. | أي من الميزات الإضافية المدرجة في الجدول أدناه. |
يسرد الجدول التالي عناصر intent الإضافية التي يتيحها موفّر خدمة "تقويم Google":
Intent إضافي | الوصف |
---|---|
Events.TITLE |
اسم الحدث |
CalendarContract.EXTRA_EVENT_BEGIN_TIME |
وقت بدء الحدث بالمللي ثانية من الحقبة. |
CalendarContract.EXTRA_EVENT_END_TIME |
وقت انتهاء الحدث بالمللي ثانية من الحقبة. |
CalendarContract.EXTRA_EVENT_ALL_DAY |
يشير ذلك المصطلح إلى قيمة منطقية تشير إلى أنّ الحدث يستمر طوال اليوم. يمكن أن تكون القيمة
true أو false . |
Events.EVENT_LOCATION |
الموقع الجغرافي حيث ستقام الفعالية. |
Events.DESCRIPTION |
وصف الحدث. |
Intent.EXTRA_EMAIL |
تمثّل هذه السمة عناوين البريد الإلكتروني للمستخدمين المطلوب دعوتهم في شكل قائمة مفصولة بفواصل. |
Events.RRULE |
قاعدة التكرار للحدث |
Events.ACCESS_LEVEL |
ما إذا كان الحدث خاصًا أو عامًا. |
Events.AVAILABILITY |
إذا كان هذا الحدث يُعتبر وقت مشغولاً أو وقت فراغ يمكن جدولته. |
توضّح الأقسام التالية كيفية استخدام هذه الأغراض.
استخدام هدف لإدراج حدث
ويتيح استخدام هدف INSERT
لتطبيقك تسليم مهمة إدراج الحدث إلى "تقويم Google" نفسه.
ومن خلال هذه الطريقة، لا يحتاج تطبيقك إلى الحصول على إذن "WRITE_CALENDAR
" في ملف البيان الخاص به.
وعندما يشغّل المستخدمون تطبيقًا يستخدم هذا الأسلوب، يرسلهم التطبيق
إلى التقويم لإنهاء عملية إضافة الحدث. يستخدم هدف INSERT
حقولاً إضافية لتعبئة
نموذج مسبقًا بتفاصيل الحدث في "تقويم Google". يمكن للمستخدمين بعد ذلك إلغاء الفعالية أو تعديل النموذج حسب الحاجة أو حفظ الحدث في تقاويمهم.
في ما يلي مقتطف رمز يُجدول حدثًا في 19 كانون الثاني (يناير) 2012 من الساعة 7:30 صباحًا إلى الساعة 8:30 صباحًا. لاحظ ما يلي بشأن مقتطف الرمز هذا:
- وهو يحدّد
Events.CONTENT_URI
على أنّه معرّف الموارد المنتظم (URI). - وتستخدم هذه السياسة الحقلَين
CalendarContract.EXTRA_EVENT_BEGIN_TIME
وCalendarContract.EXTRA_EVENT_END_TIME
الإضافيَين لتعبئة النموذج تلقائيًا بوقت الحدث. يجب أن تكون قيم هذه الأوقات بالملي ثانية بالتوقيت العالمي المنسق (UTC) من الحقبة. - تستخدِم الحقل
Intent.EXTRA_EMAIL
الإضافي لتوفير قائمة بالمدعوّين مفصولة بفواصل، يتم تحديدها حسب عنوان البريد الإلكتروني.
Kotlin
val startMillis: Long = Calendar.getInstance().run { set(2012, 0, 19, 7, 30) timeInMillis } val endMillis: Long = Calendar.getInstance().run { set(2012, 0, 19, 8, 30) timeInMillis } val intent = Intent(Intent.ACTION_INSERT) .setData(CalendarContract.Events.CONTENT_URI) .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis) .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endMillis) .putExtra(CalendarContract.Events.TITLE, "Yoga") .putExtra(CalendarContract.Events.DESCRIPTION, "Group class") .putExtra(CalendarContract.Events.EVENT_LOCATION, "The gym") .putExtra(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY) .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com") startActivity(intent)
Java
Calendar beginTime = Calendar.getInstance(); beginTime.set(2012, 0, 19, 7, 30); Calendar endTime = Calendar.getInstance(); endTime.set(2012, 0, 19, 8, 30); Intent intent = new Intent(Intent.ACTION_INSERT) .setData(Events.CONTENT_URI) .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis()) .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis()) .putExtra(Events.TITLE, "Yoga") .putExtra(Events.DESCRIPTION, "Group class") .putExtra(Events.EVENT_LOCATION, "The gym") .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY) .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com"); startActivity(intent);
استخدام هدف لتعديل حدث
يمكنك تعديل أحد الأحداث مباشرةً، كما هو موضَّح في تعديل الأحداث. أمّا استخدام هدف EDIT
، فيسمح لتطبيق لا يملك
إذنًا بتسليم مهام تعديل الأحداث إلى تطبيق "تقويم Google".
عند انتهاء المستخدمين من تعديل الحدث في "تقويم Google"، يتم إرجاعهم إلى التطبيق الأصلي.
في ما يلي مثال على هدف يحدّد عنوانًا جديدًا لحدث محدّد ويسمح للمستخدمين بتعديل الحدث في "تقويم Google".
Kotlin
val eventID: Long = 208 val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val intent = Intent(Intent.ACTION_EDIT) .setData(uri) .putExtra(CalendarContract.Events.TITLE, "My New Title") startActivity(intent)
Java
long eventID = 208; Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); Intent intent = new Intent(Intent.ACTION_EDIT) .setData(uri) .putExtra(Events.TITLE, "My New Title"); startActivity(intent);
استخدام الأغراض لعرض بيانات التقويم
يوفّر موفّر التقويم طريقتين مختلفتين لاستخدام هدف VIEW
:
- لفتح التقويم على تاريخ محدد.
- لعرض حدث.
إليك مثال يوضح كيفية فتح التقويم في تاريخ معين:
Kotlin
val startMillis: Long ... val builder: Uri.Builder = CalendarContract.CONTENT_URI.buildUpon() .appendPath("time") ContentUris.appendId(builder, startMillis) val intent = Intent(Intent.ACTION_VIEW) .setData(builder.build()) startActivity(intent)
Java
// A date-time specified in milliseconds since the epoch. long startMillis; ... Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon(); builder.appendPath("time"); ContentUris.appendId(builder, startMillis); Intent intent = new Intent(Intent.ACTION_VIEW) .setData(builder.build()); startActivity(intent);
إليك مثال يوضِّح كيفية فتح حدث للعرض:
Kotlin
val eventID: Long = 208 ... val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val intent = Intent(Intent.ACTION_VIEW).setData(uri) startActivity(intent)
Java
long eventID = 208; ... Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); Intent intent = new Intent(Intent.ACTION_VIEW) .setData(uri); startActivity(intent);
مزامنة محوّلات
هناك فقط اختلافات طفيفة في كيفية وصول تطبيق ومحوِّل مزامنة إلى موفِّر التقويم:
- يحتاج محوِّل المزامنة إلى تحديد أنّه محوِّل مزامنة عن طريق ضبط
CALLER_IS_SYNCADAPTER
علىtrue
. - يحتاج محوِّل المزامنة إلى توفير
ACCOUNT_NAME
وACCOUNT_TYPE
كمَعلمتَي طلب بحث في معرّف الموارد المنتظم (URI). - ويمتلك محوّل المزامنة إذن وصول للكتابة إلى أعمدة أكثر من التطبيق أو التطبيق المصغّر.
على سبيل المثال، يمكن لتطبيق تعديل بعض خصائص التقويم فقط، مثل الاسم والاسم المعروض وإعدادات مستوى الرؤية وما إذا كان التقويم قد تمت مزامنته. بالمقارنة، لا يمكن لمحوّل المزامنة الوصول إلى هذه الأعمدة فحسب، بل يمكن أيضًا الوصول إلى العديد من الأعمدة الأخرى،
مثل لون التقويم والمنطقة الزمنية ومستوى الوصول والموقع الجغرافي وما إلى ذلك.
ومع ذلك، يقتصر محوِّل المزامنة على
ACCOUNT_NAME
وACCOUNT_TYPE
التي تم تحديدها.
في ما يلي طريقة مساعِدة يمكنك استخدامها لإرجاع معرّف موارد منتظم (URI) لاستخدامه مع محوّل المزامنة:
Kotlin
fun asSyncAdapter(uri: Uri, account: String, accountType: String): Uri { return uri.buildUpon() .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true") .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, account) .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, accountType).build() }
Java
static Uri asSyncAdapter(Uri uri, String account, String accountType) { return uri.buildUpon() .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true") .appendQueryParameter(Calendars.ACCOUNT_NAME, account) .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); }