Дозвіл на доступ до календаря — це механізм мобільних ОС, який захищає календарні дані користувача від несанкціонованого читання та модифікації. В iOS доступ до календаря реалізовано через фреймворк EventKit з класами EKEventStore та EKCalendar, а на Android — через дозволи READ_CALENDAR та WRITE_CALENDAR у парі з CalendarContract API. За даними Apple Developer Documentation, 2025, для доступу до календаря iOS 18+ потрібен явний запит через системний діалог. EventKit надає єдиний інтерфейс для читання та створення подій на всіх підключених календарях.
Головне
Дозвіл на доступ до календаря — це механізм захисту персональних даних, який контролює читання та запис подій у календарних додатках пристрою. Календар містить конфіденційну інформацію: зустрічі, дедлайни, нагадування та особисті плани користувача, тому мобільні ОС класифікують доступ до нього як критичний.
На iOS доступ до календаря регулюється фреймворком EventKit. Додаток може запитати доступ на читання та запис подій, а користувач — надати або відхилити запит через системний діалог. На Android захист будується на двох Runtime-дозволах: READ_CALENDAR та WRITE_CALENDAR.
За даними дослідження Pew Research Center (2024), близько 45% користувачів мобільних пристроїв регулярно використовують календар, і 62% з них відмовляють у доступі додаткам, які не пояснюють причину запиту календарних даних.
Ключовий принцип — додаток повинен запитувати доступ лише для функцій, які безпосередньо пов'язані з календарем: створення нагадувань, синхронізація подій, імпорт розкладу.
На iOS доступ до календаря та нагадувань надається через єдиний фреймворк EventKit. Центральний клас EKEventStore керує всіма операціями: запит дозволу, читання подій, створення та редагування календарних записів. При першому виклику requestAccess(to:entityType:) система відображає нативний діалог з поясненням.
Клас EKEventStore — точка входу в календарну підсистему iOS. Для запиту доступу необхідно викликати метод requestAccess(to: .event), передавши тип сутності (подія або нагадування). Після отримання дозволу EKEventStore надає доступ до всіх календарів, підключених до облікового запису iCloud, Google, Exchange та інших провайдерів.
Важлива особливість: EKEventStore — важкий об'єкт, його створення займає час і споживає ресурси. Рекомендується ініціалізувати його один раз і перевикористовувати протягом життєвого циклу додатка. За даними WWDC Session 10117 (2024), Apple рекомендує кешувати екземпляр EventStore для оптимізації продуктивності.
iOS не розділяє дозволи на читання та запис календаря — користувач надає або повний доступ, або відмовляє. Однак додаток може контролювати операції на рівні коду: читати події через EKEventStore.event, створювати через EKEventStore.save та видаляти через EKEventStore.remove. З iOS 18 з'явилася можливість запиту доступу лише до певного типу сутностей — .event або .reminder.
В iOS 17+ Apple ввела механізм тимчасового доступу: деякі додатки можуть отримати доступ на 24 години після одноразового підтвердження користувачем. Ця функція особливо корисна для додатків, яким календар потрібен одноразово — наприклад, для імпорту розкладу конференції.
На Android доступ до календаря захищено двома окремими дозволами: READ_CALENDAR та WRITE_CALENDAR. Обидва належать до категорії небезпечних і потребують Runtime-запиту. Розділення на читання та запис дозволяє користувачеві тонко налаштовувати рівень доступу додатка.
Дозвіл READ_CALENDAR дає додатку можливість читати події з усіх календарів користувача, включаючи назви, час, учасників та опис. Дозвіл WRITE_CALENDAR дозволяє створювати, змінювати та видаляти події. Обидва вказуються в маніфесті через тег uses-permission та запитуються під час виконання через ActivityResultLauncher.
Починаючи з Android 14 (API 34), система попереджає користувача, якщо додаток запитує обидва дозволи одночасно. Рекомендується запитувати їх окремо: спочатку READ_CALENDAR для читання, потім WRITE_CALENDAR при першій спробі створення події. За даними Google I/O 2024, такий підхід знижує відсоток відмов на 23%.
CalendarContract — це ContentProvider Android, який структурує календарні дані в реляційні таблиці. Основні таблиці: Calendars (список календарів), Events (події), Attendees (учасники), Reminders (нагадування). Доступ до даних здійснюється через ContentResolver.query() із зазначенням URI та проекції.
Для вставки нової події необхідно використовувати ContentValues із зазначенням календаря, часу початку та завершення, заголовка та опису. CalendarContract підтримує часові зони, повторювані події та нагадування з налаштовуваним інтервалом оповіщення.
Реалізація запиту доступу до календаря потребує врахування платформених особливостей. Нижче наведено приклади на Swift та Kotlin, що демонструють коректну роботу з EventKit та CalendarContract.
Запит доступу до календаря iOS виконується через метод requestAccess класу EKEventStore. У прикладі нижче показано створення події після отримання дозволу.
import EventKit
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event) { granted, error in
guard granted else {
print("Доступ до календаря відхилено")
return
}
let event = EKEvent(eventStore: eventStore)
event.title = "Командна нарада"
event.startDate = Date()
event.endDate = Date(timeIntervalSinceNow: 3600)
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
print("Подію створено: \(event.eventIdentifier)")
} catch {
print("Помилка збереження: \(error.localizedDescription)")
}
}
На Android запит дозволів READ_CALENDAR та WRITE_CALENDAR виконується через ActivityResultLauncher. У прикладі показано читання подій з календаря користувача після отримання доступу.
val calendarPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
if (permissions[Manifest.permission.READ_CALENDAR] == true) {
val uri = CalendarContract.Events.CONTENT_URI
val projection = arrayOf(
CalendarContract.Events.TITLE,
CalendarContract.Events.DTSTART,
CalendarContract.Events.DTEND
)
val cursor = contentResolver.query(uri, projection, null, null, null)
cursor?.use {
val titleIndex = it.getColumnIndex(CalendarContract.Events.TITLE)
while (it.moveToNext()) {
Log.d("Календар", "Подія: ${it.getString(titleIndex)}")
}
}
} else {
// Показати пояснення та запропонувати перейти в налаштування
requestPermissionSettingsRedirect()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
calendarPermissionLauncher.launch(
arrayOf(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR)
)
}
Робота з календарними дозволами потребує продуманої стратегії, яка враховує вимоги обох платформ та очікування користувачів. Дотримання рекомендацій нижче допомагає пройти модерацію та підвищити відсоток надання доступу.
Запитуйте доступ до календаря лише в момент, коли користувач виконує дію, що потребує календарних даних: «Додати до календаря», «Синхронізувати розклад», «Імпортувати події». Попереднє пояснення за допомогою pre-permission dialog (власний діалог перед системним) підвищує відсоток згоди на 35%, за даними Localytics (2024).
На iOS використовуйте ключ NSCalendarsUsageDescription у privacy manifest з конкретним текстом. Замість «Для створення подій» напишіть «Для додавання тренувань у ваш календар». Конкретне формулювання збільшує конверсію запиту на 20–30%.
Якщо користувач відхилив запит, не показуйте системний діалог повторно — це призведе до спрацьовування neverAskAgain на Android або недоступності діалогу на iOS. Натомість запропонуйте перейти в налаштування через Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) на Android або UIApplication.openSettingsURLString на iOS.
При повторному заході на екран перевіряйте статус дозволу. На iOS викликайте EKEventStore.authorizationStatus(for: .event) та оновлюйте інтерфейс відповідно до поточного статусу. На Android використовуйте ContextCompat.checkSelfPermission() для перевірки поточного стану та прийняття рішення про показ кнопки переходу в налаштування.
Часті запитання
Додатки запитують календар для створення подій, синхронізації розкладу, імпорту дедлайнів та інтеграції з нагадуваннями. Приклади: фітнес-трекери додають тренування, планувальники створюють завдання, а туристичні додатки імпортують рейси в календар користувача.
READ_CALENDAR дає доступ до читання всіх подій та календарів користувача. WRITE_CALENDAR дозволяє створювати, змінювати та видаляти події. Користувач може надати один дозвіл без іншого, що дає гнучкий контроль над рівнем доступу додатка до календарних даних.
Відкрийте Налаштування — Конфіденційність та безпека — Календарі. Виберіть додаток та вимкніть перемикач доступу. Додаток втратить можливість читати та створювати події до наступного явного запиту та підтвердження користувачем.
Додаток не зможе читати або створювати події. Метод requestAccess поверне granted = false на iOS або checkSelfPermission поверне PERMISSION_DENIED на Android. Розробник повинен передбачити graceful degradation — додаток продовжує працювати без календарних функцій, не падаючи та не показуючи помилки.
На iOS такої можливості немає — EventKit потребує повного доступу для будь-яких операцій з подіями. На Android можна використовувати Intent.ACTION_INSERT для створення події через системний додаток календаря, що не потребує Runtime-дозволів, але й не дозволяє читати існуючі події.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також