نمای کلی ارائه‌دهنده تقویم

«ارائه‌دهنده تقویم» مخزنی برای رویدادهای تقویم کاربر است. ‫Calendar Provider API به شما امکان می‌دهد عملیات پُرسمان، درج، به‌روزرسانی، و حذف را روی مواردی مانند تقویم‌ها، رویدادها، شرکت‌کنندگان، و یادآوری‌ها انجام دهید.

برنامه‌ها و وفق‌دهنده‌های همگام‌سازی می‌توانند از Calendar Provider API استفاده کنند. قوانین بسته به نوع برنامه‌ای که تماس‌ها را برقرار می‌کند متفاوت است. این سند عمدتاً بر استفاده از Calendar Provider API به‌عنوان یک برنامه تمرکز دارد. برای بحث درباره تفاوت وفق‌دهنده‌های همگام‌سازی، به وفق‌دهنده‌های همگام‌سازی مراجعه کنید.

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

اصول اولیه

ارائه‌دهندگان محتوا داده‌ها را ذخیره می‌کنند و آن‌ها را برای برنامه‌ها قابل‌دسترس می‌کنند. ارائه‌دهندگان محتوا که توسط پلاتفرم Android ارائه می‌شوند (ازجمله «ارائه‌دهنده تقویم») معمولاً داده‌ها را به‌عنوان مجموعه‌ای از جدول‌ها براساس مدل پایگاه داده رابطه‌ای نشان می‌دهند که در آن هر ردیف یک رکورد است و هر ستون داده‌ای از نوع و معنای خاص است. ازطریق Calendar Provider API، برنامه‌ها و وفق‌دهنده‌های همگام‌سازی می‌توانند به جدول‌های پایگاه داده که داده‌های تقویم کاربر را نگه می‌دارند دسترسی خواندن/نوشتن داشته باشند.

هر ارائه‌دهنده محتوا یک URI عمومی (که به‌عنوان یک شیء Uri بسته‌بندی شده است) را درمعرض دید قرار می‌دهد که به‌طور منحصربه‌فرد مجموعه داده‌های آن را شناسایی می‌کند. ارائه‌دهنده محتوایی که چندین مجموعه داده (چندین جدول) را کنترل می‌کند، برای هرکدام یک URI جداگانه ارائه می‌دهد. همه شناسه‌های منبع یکسان برای ارائه‌دهندگان با رشته «content://‎» شروع می‌شوند. این مشخص می‌کند که داده‌ها توسط ارائه‌دهنده محتوا کنترل می‌شود. «ارائه‌دهنده تقویم» ثابت‌هایی را برای URIهای هریک از کلاس‌هایش (جدول‌ها) تعریف می‌کند. این شناسه‌های منبع یکسان قالب <class>.CONTENT_URI دارند. برای مثال، Events.CONTENT_URI.

شکل ۱ نمایش گرافیکی مدل داده «ارائه‌دهنده تقویم» را نشان می‌دهد. این نمودار جدول‌های اصلی و فیلدهایی را که آن‌ها را به یکدیگر پیوند می‌دهد نشان می‌دهد.

مدل داده ارائه‌دهنده تقویم
شکل ۱. مدل داده «ارائه‌دهنده تقویم».

کاربر می‌تواند چند تقویم داشته باشد و تقویم‌های مختلف می‌توانند با انواع مختلف حساب (تقویم Google،‏ Exchange، و غیره) مرتبط باشند.

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

جدول (کلاس) شرح

CalendarContract.Calendars

این جدول حاوی اطلاعات مختص تقویم است. هر ردیف در این جدول حاوی جزئیات مربوط به یک تقویم است، مانند نام، رنگ، و اطلاعات همگام‌سازی.
CalendarContract.Events این جدول حاوی اطلاعات مختص رویداد است. هر ردیف در این جدول اطلاعات مربوط به یک رویداد را دارد—برای مثال، عنوان رویداد، مکان، زمان شروع، زمان پایان. رویداد می‌تواند یک‌بار اتفاق بیفتد یا چندین‌بار تکرار شود. شرکت‌کنندگان، یادآوری‌ها، و ویژگی‌های گسترش‌یافته در جدول‌های جداگانه ذخیره می‌شوند. هرکدام یک EVENT_ID دارند که به _ID در جدول «رویدادها» ارجاع می‌دهد.
CalendarContract.Instances این جدول زمان شروع و پایان هر رخداد رویداد را نگه می‌دارد. هر ردیف در این جدول نشان‌دهنده یک رخداد رویداد است. برای رویدادهای یک‌باره، نگاشت ۱:۱ از نمونه‌ها به رویدادها وجود دارد. برای رویدادهای تکرارشونده، چندین ردیف به‌طور خودکار تولید می‌شود که با چندین تکرار آن رویداد مطابقت دارد.
CalendarContract.Attendees این جدول حاوی اطلاعات شرکت‌کننده (مهمان) رویداد است. هر ردیف نشان‌دهنده یک مهمان رویداد است. این عنصر نوع مهمان و پاسخ حضور مهمان را برای رویداد مشخص می‌کند.
CalendarContract.Reminders این جدول حاوی داده‌های هشدار/اعلان است. هر ردیف نشان‌دهنده یک هشدار برای رویداد است. یک رویداد می‌تواند چندین یادآور داشته باشد. حداکثر تعداد یادآوری‌ها برای هر رویداد در MAX_REMINDERS مشخص شده است، که توسط وفق‌دهنده همگام‌سازی که مالک تقویم داده‌شده است تنظیم می‌شود. یادآوری‌ها براساس دقیقه قبل‌از رویداد مشخص می‌شوند و روشی دارند که نحوه هشدار به کاربر را تعیین می‌کند.

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

  • درج، به‌روزرسانی، و مشاهده رویدادهای تقویم. برای درج، اصلاح، و خواندن مستقیم رویدادها از «ارائه‌دهنده تقویم»، به اجازه‌های مناسب نیاز دارید. بااین‌حال، اگر برنامه تقویم یا وفق‌دهنده همگام‌سازی کاملی نمی‌سازید، درخواست این اجازه‌ها ضروری نیست. به‌جای آن می‌توانید از هدف‌های پشتیبانی‌شده توسط برنامه «تقویم» Android برای واگذاری عملیات خواندن و نوشتن به آن برنامه استفاده کنید. وقتی از هدف‌ها استفاده می‌کنید، برنامه‌تان کاربران را به برنامه «تقویم» می‌فرستد تا عملیات انتخاب‌شده را در فرمی ازپیش تکمیل‌شده انجام دهند. پس‌از اتمام کار، به برنامه شما برگردانده می‌شوند. با طراحی برنامه‌تان برای انجام عملیات رایج ازطریق «تقویم»، میانای کاربر منسجم و قدرتمندی را دراختیار کاربران قرار می‌دهید. این رویکرد توصیه می‌شود. برای اطلاعات بیشتر، قصدهای تقویم را ببینید.
  • وفق‌دهنده‌های همگام‌سازی. وفق‌دهنده همگام‌سازی داده‌های تقویم را در دستگاه کاربر با سرور یا منبع داده دیگری همگام‌سازی می‌کند. در جدول‌های 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 نشان می‌دهد که رویدادهای مرتبط با این تقویم نباید نشان داده شود. مقدار ۱ نشان می‌دهد که رویدادهای مرتبط با این تقویم باید نشان داده شود. این مقدار بر تولید ردیف‌ها در جدول CalendarContract.Instances تأثیر می‌گذارد.
SYNC_EVENTS بولی نشان‌دهنده اینکه آیا تقویم باید همگام‌سازی شود و رویدادهای آن در دستگاه ذخیره شود یا نه. مقدار ۰ یعنی این تقویم همگام‌سازی نشود یا رویدادهای آن در دستگاه ذخیره نشود. مقدار ۱ یعنی رویدادهای این تقویم همگام‌سازی شود و رویدادهای آن در دستگاه ذخیره شود.

نوع حساب را برای همه عملیات‌ها اضافه کنید

اگر در Calendars.ACCOUNT_NAME پُرسمان می‌کنید، باید Calendars.ACCOUNT_TYPE را نیز در انتخاب اضافه کنید. دلیلش این است که یک حساب مشخص فقط با داشتن هر دو ACCOUNT_NAME و ACCOUNT_TYPE منحصربه‌فرد درنظر گرفته می‌شود. ACCOUNT_TYPE رشته‌ای است که با اصالت‌سنج حساب که هنگام ثبت حساب با AccountManager استفاده شده است مطابقت دارد. نوع خاصی از حساب نیز وجود دارد که ACCOUNT_TYPE_LOCAL نامیده می‌شود و برای تقویم‌هایی است که با حساب دستگاه مرتبط نیستند. حساب‌های ACCOUNT_TYPE_LOCAL همگام‌سازی نمی‌شوند.

پرس‌وجو کردن تقویم

در اینجا مثالی آورده شده است که نشان می‌دهد چگونه تقویم‌هایی را که متعلق به یک کاربر خاص هستند دریافت کنید. برای سادگی، در این مثال عملیات پُرسمان در رشته میانای کاربر («رشته اصلی») نشان داده شده است. در عمل، این کار باید در یک رشته ناهمگام به‌جای رشته اصلی انجام شود. برای بحث بیشتر، به بارکننده‌ها مراجعه کنید. اگر فقط داده‌ها را نمی‌خوانید بلکه آن‌ها را اصلاح می‌کنید، AsyncQueryHandler را ببینید.

کاتلین

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

جاوا

// 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 را برمی‌گرداند که می‌توانید از آن برای پیمایش مجموعه نتایج برگردانده‌شده توسط پُرسمان پایگاه داده استفاده کنید. برای بحث بیشتر درباره استفاده از پُرسمان‌ها در ارائه‌دهندگان محتوا، به ارائه‌دهندگان محتوا مراجعه کنید.

کاتلین

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

جاوا

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

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

کاتلین

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

جاوا

// 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()) تغییر می‌دهد:

کاتلین

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

جاوا

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 زمان شروع رویداد برحسب میلی‌ثانیه UTC از تاریخ یونیکس.
DTEND زمان پایان رویداد برحسب میلی‌ثانیه UTC از مبدأ تاریخ.
EVENT_TIMEZONE منطقه زمانی رویداد.
EVENT_END_TIMEZONE منطقه زمانی برای زمان پایان رویداد.
DURATION مدت رویداد در قالب RFC5545. برای مثال، مقدار "PT1H" نشان می‌دهد که رویداد باید یک ساعت طول بکشد و مقدار "P2W" نشان‌دهنده مدت ۲ هفته است.
ALL_DAY مقدار ۱ نشان می‌دهد که این رویداد کل روز را اشغال می‌کند، همان‌طور که توسط منطقه زمانی محلی تعریف شده است. مقدار ۰ نشان می‌دهد که رویداد معمولی است و ممکن است در هر زمانی از روز شروع و تمام شود.
RRULE قانون تکرار برای قالب رویداد. برای مثال، "FREQ=WEEKLY;COUNT=10;WKST=SU". برای نمونه‌های بیشتر، مشخصات RFC5545 را ببینید.
RDATE تاریخ‌های تکرار رویداد. معمولاً از RDATE همراه با RRULE برای تعریف مجموعه‌ای از رخدادهای تکرارشونده استفاده می‌کنید. برای بحث بیشتر، مشخصات RFC5545 را ببینید.
AVAILABILITY اگر این رویداد به‌عنوان زمان مشغول به‌حساب می‌آید یا زمان آزادی است که می‌توان برای آن زمان‌بندی کرد.
GUESTS_CAN_MODIFY اینکه مهمانان می‌توانند رویداد را تغییر دهند یا نه.
GUESTS_CAN_INVITE_OTHERS آیا مهمانان می‌توانند مهمانان دیگر را دعوت کنند.
GUESTS_CAN_SEE_GUESTS اینکه مهمانان بتوانند فهرست شرکت‌کنندگان را ببینند یا نه.

افزودن رویداد

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

قوانین درج رویداد جدید در اینجا آمده است:

  • باید CALENDAR_ID و DTSTART را اضافه کنید.
  • باید EVENT_TIMEZONE را اضافه کنید. برای دریافت فهرست شناسه‌های منطقه زمانی نصب‌شده در سیستم، از getAvailableIDs() استفاده کنید. توجه داشته باشید که اگر رویدادی را ازطریق INSERT Intent وارد می‌کنید، این قانون اعمال نمی‌شود. این موضوع در استفاده از Intent برای درج رویداد توضیح داده شده است—در این سناریو، منطقه زمانی پیش‌فرض ارائه می‌شود.
  • برای رویدادهای غیرتکرارشونده، باید DTEND را اضافه کنید.
  • برای رویدادهای تکرارشونده، باید علاوه‌بر RRULE یا RDATE، DURATION را هم اضافه کنید. توجه داشته باشید که اگر رویدادی را ازطریق INSERT Intent درج می‌کنید، این قانون اعمال نمی‌شود. این موضوع در استفاده از Intent برای درج رویداد شرح داده شده است—در این سناریو، می‌توانید از RRULE در کنار DTSTART و DTEND استفاده کنید و برنامه «تقویم» آن را به‌طور خودکار به مدت تبدیل می‌کند.

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

کاتلین

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

جاوا

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 رویداد را به‌عنوان شناسه پیوست‌شده به شناسه منبع یکسان (withAppendedId()) یا به‌عنوان اولین مورد انتخابی ارائه دهید. انتخاب باید با "_id=?" شروع شود و اولین selectionArg باید _ID رویداد باشد. همچنین می‌توانید بااستفاده از انتخاب بدون شناسه، به‌روزرسانی کنید. در اینجا نمونه‌ای از به‌روزرسانی رویداد آورده شده است. عنوان رویداد را بااستفاده از رویکرد withAppendedId() تغییر می‌دهد:

کاتلین

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

جاوا

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 یا بااستفاده از انتخاب استاندارد حذف کنید. اگر از شناسه پیوست‌شده استفاده می‌کنید، نمی‌توانید انتخاب هم انجام دهید. دو نسخه از حذف وجود دارد: به‌عنوان برنامه و به‌عنوان وفق‌دهنده همگام‌سازی. حذف برنامه، ستون حذف‌شده را روی ۱ تنظیم می‌کند. این پرچم به وفق‌دهنده همگام‌سازی می‌گوید که ردیف حذف شده است و این حذف باید به سرور منتقل شود. حذف وفق‌دهنده همگام‌سازی رویداد را به‌همراه همه داده‌های منسوب به آن از پایگاه داده برمی‌دارد. در اینجا نمونه‌ای از حذف رویداد توسط برنامه ازطریق _ID آن آورده شده است:

کاتلین

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

جاوا

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 الزامی است:

کاتلین

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)

جاوا

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

روش هشدار، همان‌طور که در سرور تنظیم شده است. یکی از:

افزودن یادآوری‌ها

این مثال یادآوری را به رویداد اضافه می‌کند. یادآور ۱۵ دقیقه قبل‌از رویداد فعال می‌شود.

کاتلین

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)

جاوا

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 زمان شروع نمونه، برحسب میلی‌ثانیه UTC.
END زمان پایان نمونه، برحسب میلی‌ثانیه UTC.
END_DAY روز پایانی ژولیوسی نمونه، نسبت به منطقه زمانی «تقویم».
END_MINUTE دقیقه پایان نمونه که از نیمه‌شب در منطقه زمانی «تقویم» اندازه‌گیری می‌شود.
EVENT_ID _ID رویداد برای این نمونه.
START_DAY روز شروع ژولیوسی نمونه، نسبت به منطقه زمانی «تقویم».
START_MINUTE دقیقه شروع نمونه که از نیمه‌شب نسبت به منطقه زمانی «تقویم» اندازه‌گیری می‌شود.

پرس‌وجو کردن جدول نمونه‌ها

برای پُرسمان جدول «نمونه‌ها»، باید محدوده زمانی پُرسمان را در URI مشخص کنید. در این مثال، CalendarContract.Instances ازطریق پیاده‌سازی میانای CalendarContract.EventsColumns به فیلد TITLE دسترسی پیدا می‌کند. به عبارت دیگر، TITLE ازطریق نمای پایگاه داده برگردانده می‌شود، نه ازطریق پُرسمان جدول خام CalendarContract.Instances.

کاتلین

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

جاوا

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()));
    }
 }

هدف‌های تقویم

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

کنش URI شرح جایزه‌ها

VIEW

content://com.android.calendar/time/<ms_since_epoch>

همچنین می‌توانید به URI با CalendarContract.CONTENT_URI مراجعه کنید. برای نمونه‌ای از استفاده از این هدف، به استفاده از اهداف برای مشاهده داده‌های تقویم مراجعه کنید.
تقویم را در زمان مشخص‌شده توسط <ms_since_epoch> باز کنید. هیچ‌کدام.

VIEW

content://com.android.calendar/events/<event_id>

همچنین می‌توانید به URI با Events.CONTENT_URI مراجعه کنید. برای نمونه‌ای از استفاده از این هدف، به استفاده از اهداف برای مشاهده داده‌های تقویم مراجعه کنید.
مشاهده رویداد مشخص‌شده توسط <event_id>. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

content://com.android.calendar/events/<event_id>

همچنین می‌توانید به URI با Events.CONTENT_URI مراجعه کنید. برای مشاهده نمونه‌ای از استفاده از این هدف، به استفاده از هدف برای ویرایش رویداد مراجعه کنید.
رویداد مشخص‌شده با <event_id> را ویرایش کنید. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

INSERT

content://com.android.calendar/events

همچنین می‌توانید به URI با Events.CONTENT_URI مراجعه کنید. برای مشاهده نمونه‌ای از استفاده از این هدف، به استفاده از هدف برای درج رویداد مراجعه کنید.
رویدادی ایجاد کنید. هریک از موارد اضافی فهرست‌شده در جدول زیر.

جدول زیر موارد اضافی هدف را که «ارائه‌دهنده تقویم» پشتیبانی می‌کند فهرست می‌کند:

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 به برنامه شما اجازه می‌دهد تا وظیفه درج رویداد را به خود «تقویم» واگذار کند. با این رویکرد، برنامه شما حتی نیازی به داشتن اجازه WRITE_CALENDAR در فایل مانیفست خود ندارد.

وقتی کاربران برنامه‌ای را اجرا می‌کنند که از این رویکرد استفاده می‌کند، برنامه آن‌ها را به «تقویم» می‌فرستد تا افزودن رویداد را تکمیل کنند. INSERT Intent از فیلدهای اضافی برای ازپیش تکمیل کردن فرم با جزئیات رویداد در «تقویم» استفاده می‌کند. سپس کاربران می‌توانند رویداد را لغو کنند، فرم را درصورت نیاز ویرایش کنند، یا رویداد را در تقویمشان ذخیره کنند.

در اینجا تکه‌کدی وجود دارد که رویدادی را در ۱۹ ژانویه ۲۰۱۲ زمان‌بندی می‌کند که از ساعت ۷:۳۰ صبح تا ۸:۳۰ صبح اجرا می‌شود. به موارد زیر درباره این تکه‌کد توجه کنید:

  • ‫Events.CONTENT_URI را به‌عنوان «شناسه منبع یکسان» مشخص می‌کند.
  • این الگو از فیلدهای اضافی CalendarContract.EXTRA_EVENT_BEGIN_TIME و CalendarContract.EXTRA_EVENT_END_TIME برای ازپیش تکمیل کردن فرم با زمان رویداد استفاده می‌کند. مقادیر این زمان‌ها باید برحسب میلی‌ثانیه ساعت هماهنگ جهانی از تاریخ باشد.
  • میانا برای ارائه فهرست جداشده با کاما از دعوت‌شدگان که با نشانی ایمیل مشخص شده‌اند، از فیلد اضافی Intent.EXTRA_EMAIL استفاده می‌کند.

کاتلین

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)

جاوا

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 Intent به برنامه‌ای که اجازه ندارد امکان می‌دهد ویرایش رویداد را به برنامه «تقویم» واگذار کند. وقتی کاربران ویرایش رویدادشان را در «تقویم» تمام می‌کنند، به برنامه اصلی برگردانده می‌شوند.

در اینجا نمونه‌ای از قصدی را می‌بینید که عنوان جدیدی برای رویداد مشخصی تنظیم می‌کند و به کاربران اجازه می‌دهد رویداد را در «تقویم» ویرایش کنند.

کاتلین

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)

جاوا

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 Intent ارائه می‌دهد:

  • برای باز کردن «تقویم» در تاریخی خاص.
  • برای مشاهده رویداد.

در اینجا مثالی آورده شده است که نشان می‌دهد چگونه «تقویم» را در تاریخ خاصی باز کنید:

کاتلین

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)

جاوا

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

در اینجا مثالی آورده شده است که نحوه باز کردن رویداد را برای مشاهده نشان می‌دهد:

کاتلین

val eventID: Long = 208
...
val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val intent = Intent(Intent.ACTION_VIEW).setData(uri)
startActivity(intent)

جاوا

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 برای استفاده با وفق‌دهنده همگام‌سازی استفاده کنید:

کاتلین

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

جاوا

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();
 }