Calendar
- PDF for offline use:
- Sample Code:
- Related SDKs:
Let us know how you feel about this.
0/250
Calendar API
A new set of calendar APIs introduced in Android 4 supports applications that are designed to read or write data to the calendar provider. These APIs support a wealth of interaction options with calendar data, including the ability to read and write events, attendees, and reminders. By using the calendar provider in your application, data you add through the API will appear in the built-in calendar app that comes with Android 4.
Adding Permissions
When working with the new calendar APIs in your application, the first thing
you need to do is add the appropriate permissions to the Android manifest. The
permissions you need to add are android.permisson.READ_CALENDAR and android.permission.WRITE_CALENDAR, depending on whether you are
reading and/or writing calendar data.
Using the Calendar Contract
Once you set the permissions, you can interact with calendar data by using
the CalendarContract class. This class provides a data model that
applications can use when they interact with the calendar provider. The CalendarContract allows applications to resolve the Uris to
calendar entities, such as calendars and events. It also provides a way to
interact with various fields in each entity, such as a calendar’s name and ID,
or an event’s start and end date.
Let’s look at an example that uses the Calendar API. In this example, we’ll examine how to enumerate calendars and their events, as well as how to add a new event to a calendar.
Listing Calendars
First, let’s examine how to enumerate the calendars that have been
registered in the calendar app. To do this, we can call the ManagedQuery method. At a minimum, we’ll need to specify the
content Uri for calendars and the columns we want to return; this column
specification is known as a projection. Calling ManagedQuery allows
us to query a content provider for data, such as the calendar provider, and
returns a Cursor with the results of the query.
The CalendarContract assists us in specifying both the content Uri and the projection. To get the content Uri for
querying calendars, we can simply use the CalendarContract.Calendars.ContentUri property like this:
var calendarsUri = CalendarContract.Calendars.ContentUri;
Using the CalendarContract to specify which calendar columns we
want is equally simple. We just add fields in the CalendarContract.Calendars.InterfaceConsts class to an array. For
example, the following code includes the calendar’s ID, display name, and
account name:
string[] calendarsProjection = {
CalendarContract.Calendars.InterfaceConsts.Id,
CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
CalendarContract.Calendars.InterfaceConsts.AccountName
};
The Id is important to include if you are using a SimpleCursorAdapter to bind the data to the UI, as we will see
shortly.
With the content Uri and projection in place, we call the ManagedQuery method to return a cursor with the calendar data as
shown below:
var cursor = ManagedQuery (calendarsUri, calendarsProjection, null, null, null);
The UI for this example contains a ListView, with each item in
the list representing a single calendar. The following XML shows the markup that
includes the ListView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="@android:id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Also, we need to specify the UI for each list item, which we place in a separate XML file as follows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:id="@+id/calDisplayName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16dip" />
<TextView android:id="@+id/calAccountName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12dip" />
</LinearLayout>
From this point on, it’s just normal Android code to bind the data from the
cursor to the UI. We’ll use a SimpleCursorAdapter as follows:
string[] sourceColumns = {
CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
CalendarContract.Calendars.InterfaceConsts.AccountName };
int[] targetResources = {
Resource.Id.calDisplayName, Resource.Id.calAccountName };
SimpleCursorAdapter adapter = new SimpleCursorAdapter (this,
Resource.Layout.CalListItem, cursor, sourceColumns, targetResources);
ListAdapter = adapter;
In the above code, the adapter takes the columns specified in the sourceColumns array and writes them to the user interface elements
in the targetResources array for each calendar entry in the cursor.
The Activity used here is a subclass of ListActivity; it includes
the ListAdapter property to which we set the adapter.
Here’s a screenshot showing the end result, with the calendar info
displayed in the ListView:
Listing Calendar Events
Next let’s look at how to enumerate the events for a given calendar. Building upon the example above, we’ll present a list of events when the user selects one of the calendars. Therefore, we’ll need to handle the item selection in the previous code:
ListView.ItemClick += (sender, e) => {
int i = (e as ItemEventArgs).Position;
cursor.MoveToPosition(i);
int calId =
cursor.GetInt (cursor.GetColumnIndex (calendarsProjection [0]));
var showEvents = new Intent(this, typeof(EventListActivity));
showEvents.PutExtra("calId", calId);
StartActivity(showEvents);
};
In this code, we’re creating an Intent to open an Activity of type EventListActivity, passing the calendar’s ID in the Intent. We
will need the ID in order to know which calendar to query for events. In the EventListActivity’s OnCreate method, we can retrieve
the ID from the Intent as shown below:
_calId = Intent.GetIntExtra ("calId", -1);
Now let’s query events for this calendar ID. The process to query for
events is similar to the way we queried for a list of calendars earlier, only
this time we’ll work with the CalendarContract.Events class. The
following code creates a managed query to retrieve events:
var eventsUri = CalendarContract.Events.ContentUri;
string[] eventsProjection = {
CalendarContract.Events.InterfaceConsts.Id,
CalendarContract.Events.InterfaceConsts.Title,
CalendarContract.Events.InterfaceConsts.Dtstart
};
var cursor = ManagedQuery (eventsUri, eventsProjection,
String.Format ("calendar_id={0}", _calId), null, "dtstart ASC");
In this code, we first get the content Uri for events from the CalendarContract.Events.ContentUri property. Then we specify the
event columns we want to retrieve in the eventsProjection array. Finally, we
build a managed query by calling the ManagedQuery method, which
returns a cursor with event data.
To display the event data in the UI, we can use markup and code just like we
did before to display the list of calendars. Again, we use SimpleCursorAdapter to bind the data to a ListView as
shown in the following code:
string[] sourceColumns = {
CalendarContract.Events.InterfaceConsts.Title,
CalendarContract.Events.InterfaceConsts.Dtstart };
int[] targetResources = {
Resource.Id.eventTitle,
Resource.Id.eventStartDate };
var adapter = new SimpleCursorAdapter (this, Resource.Layout.EventListItem,
cursor, sourceColumns, targetResources);
adapter.ViewBinder = new ViewBinder ();
ListAdapter = adapter;
The main difference between this code and the code that we used earlier to
show the calendar list is the use of a ViewBinder, which is set on
the line:
adapter.ViewBinder = new ViewBinder ();
The ViewBinder class allows us to further control how we bind
values to views. In this case, we use it to convert the event start time from
milliseconds to a date string, as shown in the following implementation:
class ViewBinder : Java.Lang.Object, SimpleCursorAdapter.IViewBinder
{
public bool SetViewValue (View view, Android.Database.ICursor cursor,
int columnIndex)
{
if (columnIndex == 2) {
long ms = cursor.GetLong (columnIndex);
DateTime date = new DateTime (1970, 1, 1, 0, 0, 0,
DateTimeKind.Utc).AddMilliseconds (ms).ToLocalTime ();
TextView textView = (TextView)view;
textView.Text = date.ToLongDateString ();
return true;
}
return false;
}
}
This displays a list of events as shown below:
Adding a Calendar Event
We’ve seen how to read calendar data. Now let’s see how to add an event
to a calendar. For this to work, be sure to include the android.permission.WRITE_CALENDAR permission we mentioned earlier.
To add an event to a calendar, we will:
- Create a
ContentValuesinstance. - Use keys from the
CalendarContract.Events.InterfaceConstsclass to populate theContentValuesinstance. - Set the time zones for the event start and end times.
- Use a
ContentResolverto insert the event data into the calendar.
The code below illustrates these steps:
ContentValues eventValues = new ContentValues ();
eventValues.Put (CalendarContract.Events.InterfaceConsts.CalendarId,
_calId);
eventValues.Put (CalendarContract.Events.InterfaceConsts.Title,
"Test Event from M4A");
eventValues.Put (CalendarContract.Events.InterfaceConsts.Description,
"This is an event created from Xamarin.Android");
eventValues.Put (CalendarContract.Events.InterfaceConsts.Dtstart,
GetDateTimeMS (2011, 12, 15, 10, 0));
eventValues.Put (CalendarContract.Events.InterfaceConsts.Dtend,
GetDateTimeMS (2011, 12, 15, 11, 0));
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone,
"UTC");
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone,
"UTC");
var uri = ContentResolver.Insert (CalendarContract.Events.ContentUri,
eventValues);
Note that if we do not set the time zone, an exception of type
Java.Lang.IllegalArgumentException will be thrown. Because event time
values must be expressed in milliseconds since epoch, we create a
GetDateTimeMS method (in EventListActivity) to convert our date
specifications into millisecond format:
long GetDateTimeMS (int yr, int month, int day, int hr, int min)
{
Calendar c = Calendar.GetInstance (Java.Util.TimeZone.Default);
c.Set (Calendar.DayOfMonth, 15);
c.Set (Calendar.HourOfDay, hr);
c.Set (Calendar.Minute, min);
c.Set (Calendar.Month, Calendar.December);
c.Set (Calendar.Year, 2011);
return c.TimeInMillis;
}
If we add a button to the event list UI and run the above code in the button’s click event handler, the event is added to the calendar and updated in our list as shown below:
If we open the calendar app, then we will see that the event is written there as well:
As you can see, Android 4.0 allows powerful and easy access to retrieve and persist calendar data, allowing applications to seamlessly integrate calendar capabilities.
Let us know how you feel about this.
0/250
Xamarin Workbook
If it's not already installed, install the Xamarin Workbooks app first. The workbook file should download automatically, but if it doesn't, just click to start the workbook download manually.



