Built to Roam created a “device_calendar” Flutter/Dart library to communicate with mobile device calendars (i.e. add, update, retrieve, delete Android/iOS calendar events). Their current Github page includes an example app that implements the library which I’d recommend looking over.

Their Github page does not currently have detailed info on how to use the library, so I figured I’d document some instructions to save other’s some time. I’ll use my app as an example to show how this library can be used. My app is called MMA Calendar. It retrieves future MMA (Mixed Martial Arts) events from the web and automatically creates/updates calendar events for the user.

My app can be seen at the link below for reference(please be sure to follow my Github 😎)

https://github.com/patpatchpatrick/MMACalendarFlutter-v2-

First, it’s necessary to add the package dependency to the pubspec.yaml file dependencies section, as is necessary with any other Flutter external library

dependencies:

flutter:

sdk: flutter



device_calendar: ^0.1.1

2. Permissions for calendar usage must also be added to the appropriate files in Android (AndroidManifest.xml) and iOS (Info.plist)

Android Manifest:

<uses-permission android:name="android.permission.READ_CALENDAR" />

<uses-permission android:name="android.permission.WRITE_CALENDAR" />

Info.plist:

<key>NSCalendarsUsageDescription</key>

<string>REASON_TO_USE_CALENDAR</string>

3. Make sure you import the device_calendar package to your application dart file that you are currently working on. In my MMA Calendar app, I use this library in my mainpage.dart file and also in the calendarpage.dart file so I import the package in both files



import 'package:device_calendar/device_calendar.dart';

4. In my application, I created a CalendarPage widget within the calendarpage.dart file. I used the Github device_calendar example app as reference when creating this widget but tweaked it slightly. My CalendarPage Widget contains a ListView which displays a list of the user’s calendars. The user can then select which calendar they want to use (i.e. which calendar the web-queried MMA Events should be added to). Then when the user clicks the “Load Fights and Add to Calendar” button, calendar events will be automatically created for the user (or events will be updated if they were previously created) An example of how the CalendarPage works can be seen below:

Example of User Selecting Calendar within App

5. Before communicating with the mobile device calendars, you need to create a DeviceCalendarPlugin object. When I construct my Calendar Page Widget’s state (CalendarPageState) I create a new DeviceCalendarPlugin instance within the constructor. I do this because the CalendarPage widget immediately needs the plugin to be available for methods which communicate with the mobile device calendar.

6. You’ll also notice above that after the DeviceCalendarPlugin is created when the state is constructed, the _retrieveCalendars method is called when the state is initialized (in the overidden initState() method). Essentially what is happening here, is immediately after the state is constructed, a list of calendars is retrieved from the device.

In the code below you’ll see that the _retrieveCalendars method asynchronously retrieves calendars from the device and sets the _calendars object (which is a List<Calendar> object) to the list of calendars. Before doing so, you must check whether the device has appropriate calendar permissions granted, and if not you must request the calendar permissions which are needed to retrieve the list of calendars from the device. If permissions are granted successfully, the retrieveCalendars() method of the DeviceCalendarPlugin can be used to retrieve a list of Calendars (List<Calendar>) from the mobile device. To summarize, when the CalendarPage widget is created, a new DeviceCalendarPlugin is created and calendars are subsequently retrieved from the device using the retrieveCalendars() method of the plugin.

7. After we have the list of calendars, we can begin using them! You have several options here — you can retrieve events from the calendars, add events, delete events, update events, etc…

In my MMA Calendar app I solely add and update events, so that is what I’ll focus on here. As mentioned in Step 4, my CalendarPage widget contains a ListView that displays the user’s calendars. This ListView also shows a lock icon if the calendar is read only (this code all comes with the device_calendar example app). The ListView has a GestureDetector within it that will get the calendarID of the calendar which is selected using the index of the ListView. I then created a callback function to return this calendar ID, calendar Name and deviceCalendarPlugin to the MainPage of my app so that they can be used within my MainPage widget. I’m not going to delve into details about how to use callbacks in Dart here, but to summarize you would simply create a function in your widget (MainPage), and pass that function into the constructor of your child widget (CalendarPage). You can then call this callback function from the child to provide the parent with needed objects (e.g. calendarID, calendarName, deviceCalendarPlugin). (An example of this can be seen in my code _calendarCallback function).

Callback to Send ID, Name, Plugin to Parent Widget(mainpage.dart)

8. After receiving calendar info via callback in my MainPage widget, a calendar has officially been selected by the user so I enable the “Load Fights and Add to Calendar” button for the user to select. I also display the selected calendar name to the user as can be seen in the above GIF of my app (in Step 4).

When the user clicks this Load Fights button, MMA event data is scraped from the web and MMA events are created which can be added to the user’s mobile device calendar. My code uses a method called _addEventsToCalendar to create/update events in the user’s calendar. Adding/updating events in the user’s calendar is relatively straight-forward. First, you must create a new Event(calendarID) using the selected calendar ID as the constructor. Then you will need to add certain pieces of data to the event (start time, duration, title, description, etc…). After your event has been created, you add it to the user’s calendar using the deviceCalendarPlugin.createOrUpdateEvent(event) method and plug in the event you created as the sole parameter. Annnnd done! You will receive a result variable (createEventResult) via your event creation method that you called. If your event was created successfully, the createEventResult.isSuccess bool will be TRUE.

One other important note, your createEventResult object will also have a data String variable (createEventResult.data)which corresponds to the ID of the event that you created in the mobile device. You can use this ID to update the event if you need to. To update an event, you must set the ID property on the event (i.e. event.ID = createEventResult.data). Then when you call the createOrUpdateEvent(event) method on the event it will be updated instead of a new/duplicate event being created.

I personally use SharedPreferences (shared_preferences library) to handle my event IDs. When I create MMA Events, I associate the event name/date with an ID, and then if a user already has an ID associated with an event, I make sure to update the event instead of creating a new/duplicate event in their calendar.

Adding/Updating Events in the Calendar

Events Added to Android Calendar

That’s all folks.

Again, make sure to check out the Built To Roam device_calendar plugin example app, and don’t forget to follow me on Github if you like 😎.

device_calendar plugin: https://pub.dartlang.org/packages/device_calendar

My Github: https://github.com/patpatchpatrick

MMA Calendar App: https://github.com/patpatchpatrick/MMACalendarFlutter-v2-