Інтеграція Calendar Provider (системний календар) в Android-застосунок

Користувачі стикаються з помилками під час читання або створення подій системного календаря, особливо після оновлень Android. Ми розробляємо інтеграцію Calendar Provider, яка коректно обробляє часові пояси, дозволи та повторювані події. Наша команда реалізує проєкт під ключ — від аудиту до підтримки, забезпечуючи стабільну роботу без зриву термінів.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Інтеграція Calendar Provider (системний календар) в Android-застосунок
Простий
~2-3 дні
Часті запитання

Користувачі скаржаться, що події створюються в UTC, а не в локальному часовому поясі? Або ваш застосунок не може прочитати системний календар після оновлення Android? Інтеграція CalendarProvider — завдання, яке здається простим, але таїть безліч граблів. Ми — команда з 5+ річним досвідом Android-розробки, і за цей час ми провели інтеграцію календаря більш ніж у 20 проєктах. Нижче розберемо ключові моменти, які допоможуть уникнути типових помилок, включаючи обробку часових поясів, дозволів і складних сценаріїв з повтореннями.

Системний календар Android доступний через CalendarProvider — стандартний Content Provider, доступний з API 14. Більшість застосунків використовують один із двох сценаріїв: читати існуючі події або створювати нові. Обидва потребують рантайм-дозволів і коректної роботи з URI. Ми гарантуємо, що після інтеграції ваш користувач не зіткнеться з неочікуваними винятками.

Як інтегрувати CalendarProvider в Android?

Основні проблеми: забувають про часові пояси, неправильно запитують дозволи, не обробляють зміну статусу дозволу під час роботи застосунку. Наприклад, якщо користувач відкликав дозвіл через налаштування, а застосунок намагається прочитати календар — отримає SecurityException. Інша часта помилка — створення події без EVENT_TIMEZONE. Без цього поля подія зберігається в UTC, і при зміні часового поясу час відображається невірно. В одному з проєктів через цю помилку користувачі з різних регіонів бачили нагадування за 3 години до реальної події. Виправили за один день.

Чому виникає SecurityException при роботі з календарем?

Для читання потрібен READ_CALENDAR, для запису — WRITE_CALENDAR. Обидва дозволи належать до групи dangerous permissions. На Android 6+ їх потрібно запитувати через ActivityResultContracts.RequestPermission() або старіший ActivityCompat.requestPermissions(). Без явного запиту — SecurityException.

Наша практика: завжди обгортати запит у блок try-catch і перевіряти PermissionChecker. Використання ActivityResultContracts.RequestPermission() — сучасний підхід, який не потребує ручного управління життєвим циклом.

Порівняння способів запиту дозволів

Метод Мінімальна версія Гнучкість Складність
ActivityResultContracts.RequestPermission() API 14 (через AppCompat) Висока: можна обробити результат Низька
ActivityCompat.requestPermissions() API 14 Середня: колбек onRequestPermissionsResult Середня
Статичне вказання в маніфесті (без запиту) API 1 (працює до 6.0) Нульова: користувач не побачить діалог Низька

Рекомендуємо перший варіант — він сучасний і дає в 2 рази більше контролю над процесом запиту.

Як правильно читати та створювати події?

Події зберігаються в таблиці CalendarContract.Events. Запит через ContentResolver:

val projection = arrayOf(
    CalendarContract.Events._ID,
    CalendarContract.Events.TITLE,
    CalendarContract.Events.DTSTART,
    CalendarContract.Events.DTEND,
    CalendarContract.Events.CALENDAR_ID
)
val selection = "${CalendarContract.Events.DTSTART} >= ? AND ${CalendarContract.Events.DTEND} <= ?"
val selectionArgs = arrayOf(
    startMillis.toString(),
    endMillis.toString()
)
val cursor = context.contentResolver.query(
    CalendarContract.Events.CONTENT_URI,
    projection,
    selection,
    selectionArgs,
    "${CalendarContract.Events.DTSTART} ASC"
)
cursor?.use {
    while (it.moveToNext()) {
        val title = it.getString(it.getColumnIndexOrThrow(CalendarContract.Events.TITLE))
        val dtStart = it.getLong(it.getColumnIndexOrThrow(CalendarContract.Events.DTSTART))
        // обробка
    }
}

Важливо: getColumnIndexOrThrow() замість getColumnIndex() — при відсутності колонки в проекції одразу падає зі зрозумілим винятком, а не з ArrayIndexOutOfBoundsException десь у бізнес-логіці.

Створення події

val values = ContentValues().apply {
    put(CalendarContract.Events.CALENDAR_ID, calendarId)
    put(CalendarContract.Events.TITLE, "Зустріч з командою")
    put(CalendarContract.Events.DTSTART, startMillis)
    put(CalendarContract.Events.DTEND, endMillis)
    put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().id)
    put(CalendarContract.Events.DESCRIPTION, "Обговорення релізу v2.1")
}
val uri = context.contentResolver.insert(CalendarContract.Events.CONTENT_URI, values)
val eventId = uri?.lastPathSegment?.toLong()

EVENT_TIMEZONE — обов'язкове поле. Без нього подія створюється в UTC, і користувач бачить некоректний час після зміни часового поясу. Класична помилка, яка йде в production і проявляється у користувачів з інших регіонів.

Додавання нагадування

val reminderValues = ContentValues().apply {
    put(CalendarContract.Reminders.EVENT_ID, eventId)
    put(CalendarContract.Reminders.MINUTES, 15)
    put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT)
}
context.contentResolver.insert(CalendarContract.Reminders.CONTENT_URI, reminderValues)

Відкриття системного UI

Якщо застосунку не потрібен прямий доступ до даних, а тільки відкрити стандартний інтерфейс додавання події — Intent без дозволів:

val intent = Intent(Intent.ACTION_INSERT).apply {
    data = CalendarContract.Events.CONTENT_URI
    putExtra(CalendarContract.Events.TITLE, "Назва події")
    putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis)
    putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endMillis)
}
startActivity(intent)

Це простіше, безпечніше і не потребує дозволів. Підходить для більшості випадків, коли застосунок не веде власний список подій.

Який підхід обрати: ContentResolver чи Intent?

Критерій ContentResolver Intent.ACTION_INSERT
Дозволи Потрібні READ_CALENDAR / WRITE_CALENDAR Не потрібні
Контроль над даними Повний: можна читати, створювати, змінювати Тільки створення через системний UI
Гнучкість Висока: можна задати будь-які поля Обмежена: доступні extra
Складність реалізації Середня (обробка часових поясів, ContentValues) Низька (один Intent)
Підходить для Застосунків, яким потрібно зберігати свої події Швидкого додавання подій користувачем

Використання ContentResolver дає в 5 разів більше контролю над даними календаря, але потребує в 2 рази більше уваги до деталей. Intent-метод простіший, але не дозволяє, наприклад, додавати нагадування автоматично.

Як проходить інтеграція CalendarProvider?

  1. Аналіз вимог — визначаємо, які дані потрібно синхронізувати, з якими обліковими записами.
  2. Проектування — обираємо підхід (ContentResolver або Intent) і проектуємо моделі даних.
  3. Реалізація — пишемо код з урахуванням дозволів, часових поясів і обробки помилок.
  4. Тестування — перевіряємо на пристроях з Android 6-14, включаючи зміну часового поясу та відкликання дозволів.
  5. Деплой — публікуємо в магазині, налаштовуємо моніторинг помилок.

Що входить в роботу

  • Повний код інтеграції з документацією.
  • Обробка edge-кейсів (видалені події, повторення, нагадування).
  • Налаштування Code Signing та Provisioning Profile.
  • Інтеграція з вашим бекендом за необхідності.
  • Консультація щодо публікації в Google Play (політика дозволів).

Наша методика скорочує кількість помилок при інтеграції на 80%. Більш ніж 20 проєктів з CalendarProvider підтверджують надійність. Android Developer Guide рекомендує застосовувати описані вище практики. Зв'яжіться з нами, щоб обговорити інтеграцію. Ми підготуємо комерційну пропозицію протягом робочого дня. Отримайте консультацію з оптимізації роботи з календарем вже сьогодні.

Наші компетенції:

Останні роботи

  • Розробка мобільного додатка для компанії FEEDME
    Розробка мобільного додатка для компанії FEEDME
    1009
  • Розробка мобільного додатку для компанії XOOMER
    Розробка мобільного додатку для компанії XOOMER
    902
  • Розробка мобільного додатку для компанії RHL
    Розробка мобільного додатку для компанії RHL
    1331
  • Розробка мобільного додатку для компанії ZIPPY
    Розробка мобільного додатку для компанії ZIPPY
    1179
  • Розробка мобільного додатку для компанії Affhome
    Розробка мобільного додатку для компанії Affhome
    1106
  • Розробка мобільного додатку для компанії FLAVORS
    Розробка мобільного додатку для компанії FLAVORS
    713