مقدّم خدمة التقويم هو مستودع لأحداث التقويم الخاصة بالمستخدم. تتيح لك واجهة برمجة التطبيقات Calendar Provider API تنفيذ عمليات البحث والإضافة والتعديل والحذف في التقاويم والأحداث والضيوف والتذكيرات وما إلى ذلك.
يمكن للتطبيقات ومحوِّلات المزامنة استخدام Calendar Provider API. تختلف القواعد حسب نوع البرنامج الذي يجري المكالمات. يركز هذا المستند بشكل أساسي على استخدام واجهة برمجة التطبيقات Calendar Provider API كتطبيق. لمناقشة أوجه الاختلاف بين محوِّلات المزامنة، يُرجى الاطّلاع على محوِّلات المزامنة.
في العادة، لقراءة بيانات التقويم أو كتابتها، يجب أن يحتوي بيان التطبيق على الأذونات المناسبة الموضّحة في أذونات المستخدمين. لتسهيل تنفيذ العمليات الشائعة، يقدّم Calendar Provider مجموعة من الأهداف، كما هو موضّح في Calendar Intents. تنقل هذه النوايا المستخدمين إلى تطبيق "تقويم Google" لإدراج الأحداث وعرضها وتعديلها. يتفاعل المستخدم مع تطبيق التقويم ثم يعود إلى التطبيق الأصلي. وبالتالي، لا يحتاج تطبيقك إلى طلب الأذونات، ولا يحتاج إلى توفير واجهة مستخدم لعرض الأحداث أو إنشائها.
الأساسيات
مقدّمو المحتوى: يخزّنون البيانات ويسهّلون وصول التطبيقات إليها. عادةً ما يعرض موفّرو المحتوى الذي يوفّره نظام Android الأساسي (بما في ذلك "موفِّر التقويم") البيانات كمجموعة من الجداول بناءً على نموذج قاعدة بيانات ارتباطية، حيث يكون كلّ صفّ سجلاً ويكون كلّ عمود بيانات من نوع ومعنى معيّنين. من خلال واجهة برمجة التطبيقات Calendar Provider API، يمكن للتطبيقات ومحوِّلات المزامنة الحصول على إذن بالقراءة/الكتابة في جداول قاعدة البيانات التي تحتوي على بيانات تقويم المستخدم.
يعرض كل مقدّم محتوى معرّف موارد منتظمًا متاحًا للجميع (مُغلفًا كUri
عنصر) يحدّد مجموعة بياناته بشكل فريد. يعرض مقدّم المحتوى الذي يتحكّم في
مجموعات بيانات متعدّدة (جداول متعدّدة) عنوان URL منفصلاً لكل مجموعة. تبدأ كل عناوين URI لموفّري المحتوى بالسلسلة "content://". ويشير ذلك إلى أنّ البيانات خاضعة لتحكّم موفّر المحتوى. يحدِّد Calendar
Provider ثوابت لعناوين URL لكل فئة من فئات التقويم (الجداول). وتكون معرّفات الموارد المنتظمة (URI) هذه بالتنسيق <class>.CONTENT_URI
. على سبيل المثال، Events.CONTENT_URI
.
يعرض الشكل 1 تمثيلاً رسوميًا لنموذج بيانات مزوّد خدمة التقويم. ويعرض الجداول الرئيسية والحقول التي تربطها ببعضها.
يمكن أن يكون لدى المستخدم تقاويم متعددة، ويمكن ربط تقاويم مختلفة بأنواع مختلفة من الحسابات ("تقويم Google" وExchange وما إلى ذلك).
يحدِّد CalendarContract
نموذج البيانات للمعلومات المتعلّقة بالتقويم والأحداث. يتم تخزين هذه البيانات في عدد من الجداول المُدرَجة أدناه.
الجدول (الفئة) | الوصف |
---|---|
يحتوي هذا الجدول على المعلومات المتعلّقة بالتقويم. يحتوي كل صف في هذا الجدول على تفاصيل تقويم واحد، مثل الاسم واللون ومعلومات المزامنة وما إلى ذلك. | |
CalendarContract.Events |
يحتوي هذا الجدول على
المعلومات المتعلّقة بالحدث. ويحتوي كل صف في هذا الجدول على معلومات عن حدث واحد، مثل عنوان الحدث وموقعه الجغرافي ووقت البدء ووقت الانتهاء وما إلى ذلك. يمكن أن يحدث الحدث مرّة واحدة أو يمكن أن يتكرر عدّة مرّات. يتم تخزين بيانات الضيوف،
والتذكيرات، والسمات الموسّعة في جداول منفصلة.
يحتوي كلّ منها على EVENT_ID
يشير إلى _ID في جدول "الأحداث". |
CalendarContract.Instances |
يحتوي هذا الجدول على وقت البدء والانتهاء لكلّ مرّة من مرّات حدوث الحدث. يمثّل كل صف في هذا الجدول موضع حدوث حدث واحد. بالنسبة إلى الأحداث التي تقع لمرة واحدة، هناك تعيين 1:1 للمثيلات بالأحداث. بالنسبة إلى الأحداث المتكرّرة، يتم تلقائيًا إنشاء صفوف متعددة تتوافق مع مرّات متعددة من هذا الحدث. |
CalendarContract.Attendees |
يحتوي هذا الجدول على معلومات الحاضرين في الحدث (الضيف). يمثّل كل صف ضيفًا واحدًا في أحد الأحداث. وهي تحدّد نوع الضيف وردّه بشأن حضوره للفعالية. |
CalendarContract.Reminders |
يحتوي هذا الجدول على
بيانات التنبيهات. يمثّل كل صف تنبيهًا واحدًا لحدث معيّن. يمكن أن يتضمّن
الحدث تذكيرات متعددة. يتم تحديد الحد الأقصى لعدد التذكيرات لكل حدث في MAX_REMINDERS ، والذي يتم ضبطه بواسطة محوِّل المزامنة الذي يملك التقويم المحدَّد. يتم تحديد التذكيرات خلال دقائق قبل الحدث،
وتحتوي على طريقة تحدد كيفية تنبيه المستخدم. |
تم تصميم واجهة برمجة التطبيقات Calendar Provider API لتكون مرنة وفعّالة. وفي الوقت ذاته، من المهم توفير تجربة مستخدم جيدة وحماية سلامة التقويم وبياناته. لتحقيق هذا الهدف، إليك بعض النقاط التي يجب أخذها في الاعتبار عند استخدام واجهة برمجة التطبيقات:
- إدراج أحداث التقويم وتعديلها وعرضها لإدراج الأحداث وتعديلها وقراءتها مباشرةً من مقدّم التقويم، يجب أن يكون لديك الأذونات المناسبة. ومع ذلك، إذا لم تكن بصدد إنشاء تطبيق تقويم أو محوِّل مزامنة متكاملَين، ليس من الضروري طلب هذه الأذونات. يمكنك بدلاً من ذلك استخدام النوايا المتوافقة مع تطبيق "تقويم Google" على Android لنقل عمليات القراءة والكتابة إلى هذا التطبيق. عند استخدام النوايا، يوجّه تطبيقك المستخدمين إلى تطبيق "تقويم Google" لتنفيذ العملية المطلوبة في نموذج مملوء مسبقًا. وبعد الانتهاء، يتم إرجاعهم إلى طلبك. من خلال تصميم تطبيقك لتنفيذ العمليات الشائعة من خلال "تقويم Google"، توفّر للمستخدمين واجهة مستخدم متّسقة وفعّالة. هذا هو النهج المُقترَح. لمزيد من المعلومات، يُرجى الاطّلاع على "تقويم 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
للتقويمات غير المرتبطة بحساب جهاز.
لا تتم synchronization مع حسابات ACCOUNT_TYPE_LOCAL
.
الاستعلام عن تقويم
في ما يلي مثال يوضّح كيفية الحصول على التقاويم التي يملكها مستخدم معيّن. من أجل التبسيط، يتم عرض عملية طلب البحث في مثالنا هذا في سلسلت محادثات واجهة المستخدِم ("السلسلة الرئيسية"). من الناحية العملية، يجب إجراء ذلك في سلسلة تعليمات
غير متزامنة بدلاً من السلسلة الرئيسية. لمزيد من المناقشة، يُرجى الاطّلاع على
أدوات التحميل. إذا كنت لا تقرأ البيانات فقط بل تعدّلها أيضًا، اطّلِع على 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
التقويم.
يمكنك أيضًا إجراء تعديلات من خلال ترميز المعرّف في معرّف الموارد المنتظم. يغيّر هذا المثال الاسم المعروض للتقويم باستخدام الأسلوب (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
نية، كما هو موضّح في مقالة استخدام نية لإدراج حدث. ومع ذلك، إذا
كنت بحاجة إلى ذلك، يمكنك إدراج الأحداث مباشرةً. يوضّح هذا القسم كيفية تنفيذ
ذلك.
في ما يلي قواعد إدراج حدث جديد:
- يجب تضمين
CALENDAR_ID
وDTSTART
. - يجب تضمين
EVENT_TIMEZONE
. للحصول على قائمة بمعرّفات المناطق الزمنية المثبَّتة في النظام، استخدِمgetAvailableIDs()
. يُرجى العلم أنّ هذه القاعدة لا تنطبق في حال إدراج حدث من خلال نيةINSERT
الموضّحة في مقالة استخدام نية لإدراج حدث. وفي هذا السيناريو، يتم توفير منطقة زمنية تلقائية. - بالنسبة إلى الأحداث غير المتكرّرة، يجب تضمين
DTEND
. - بالنسبة إلى الأحداث المتكررة، يجب تضمين
DURATION
بالإضافة إلىRRULE
أوRDATE
. يُرجى العلم أنّ هذه القاعدة لا تنطبق في حال إدراج حدث من خلال IntentINSERT
الموضّح في المقالة استخدام نية لإدراج حدث. وفي هذا السيناريو، يمكنك استخدام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
Intent، كما هو описан في استخدام Intent لتعديل حدث.
ومع ذلك، يمكنك تعديل الأحداث مباشرةً إذا أردت ذلك. لإجراء تعديل على
حدث، يمكنك تقديم _ID
للحدث إما كرقم تعريف مرفق بعنوان URL (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
كرقم تعريف مرفق في عنوان URL أو باستخدام
الاختيار العادي. في حال استخدام معرّف مرفق، لا يمكنك أيضًا إجراء اختيار.
هناك إصداران من ميزة "الحذف": كتطبيق وكأداة ربط مزامنة. يؤدي حذف
تطبيق إلى ضبط العمود محذوف على 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 |
يوم انتهاء Julian للمثيل، بالنسبة إلى المنطقة الزمنية للتقويم. |
END_MINUTE |
دقيقة انتهاء الحدث المقاسة من منتصف الليل في المنطقة الزمنية التي يتّبعها "تقويم Google" |
EVENT_ID |
_ID للحدث لهذه الحالة |
START_DAY |
يوم البدء الميلادي للنسخة، نسبةً إلى المنطقة الزمنية للتقويم |
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 .
للاطّلاع على مثال لاستخدام هذا الإجراء، راجِع مقالة استخدام إجراء لإدراج حدث.
|
أنشِئ حدثًا. | أي من الميزات الإضافية المدرجة في الجدول أدناه. |
يسرد الجدول التالي عناصر العرض الإضافية للنوايا التي يتوافق معها مقدّم خدمة "تقويم Google":
Intent Extra | الوصف |
---|---|
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
Intent
لتطبيقك تسليم مهمة إدراج الحدث إلى "تقويم Google" نفسه.
باستخدام هذه الطريقة، لن يحتاج تطبيقك حتى إلى تضمين إذن WRITE_CALENDAR
في ملف البيان.
عند تشغيل المستخدمين لتطبيق يستخدم هذه الطريقة، يرسلهم التطبيق
إلى "تقويم Google" لإنهاء إضافة الحدث. يستخدم INSERT
Intent حقولًا إضافية لتمتلئ
النموذج مسبقًا بتفاصيل الحدث في التقويم. يمكن للمستخدمين
بعد ذلك إلغاء الحدث أو تعديل النموذج حسب الحاجة أو حفظ الحدث في
تقويماتهم.
في ما يلي مقتطف رمز تحدّد موعدًا لحدث في 19 كانون الثاني (يناير) 2012، والذي يبدأ من الساعة 7:30 صباحًا إلى الساعة 8:30 صباحًا. يُرجى ملاحظة ما يلي بشأن مقتطف الرمز هذا:
- ويحدّد
Events.CONTENT_URI
كعنوان URL. - ويستخدم الحقلَين
CalendarContract.EXTRA_EVENT_BEGIN_TIME
وCalendarContract.EXTRA_EVENT_END_TIME
الإضافيَين لتعبئة النموذج تلقائيًا بوقت الحدث. يجب أن تكون قيم هذه الأوقات بالتوقيت العالمي المتفق عليه بالملي ثانية من بداية حساب الوقت. - تستخدم هذه السياسة الحقل الإضافي
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);
استخدام النوايا لعرض بيانات التقويم
يوفّر موفِّر "تقويم Google" طريقتَين مختلفتَين لاستخدام Intent من النوع VIEW
:
- لفتح "تقويم Google" في تاريخ معيّن.
- لعرض حدث:
في ما يلي مثال يوضّح كيفية فتح "تقويم Google" لتاريخ معيّن:
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(); }