New Calendar APIs have been introduced with Android Ice Cream Sandwich for managing calendars. Event, attendee, alert, and reminder databases can be managed with these APIs. These APIs allow us to easily integrate calendars with our Android applications. This chapter shows how to use Calendar APIs with examples.
The topics covered in this chapter are as follows:
The main class that manages the calendar data is the CalendarContract
class. Noteworthy tables that store the calendar information are as follows:
CalendarContract.Calendar
: This table stores calendar specific data for each calendarCalendarContract.Event
: This table stores event specific data for each eventCalendarContract.Attendee
: This table stores data about the attendee of an eventCalendarContract.Reminder
: This table stores data about the reminder for an eventIn the following examples, we will execute the applications in an Android device, because in order to test the Calendar API in an emulator, an account is needed. If you want to test examples in an emulator, make sure to choose the Google API's API Level 14 or higher when creating the AVD. The Google API allows you to add a Google account to an emulator, which is needed for the Calendar APIs. You also need to set up the Calendar to sync with Gmail. You can use m.google.com as the server and <[email protected]>
as the Domain/Username when adding an account. After creating and syncing your account, you can run the following examples in the emulator.
In order to create a calendar event, we need to create a ContentValues
instance and put event information to this instance. Then, using the ContentResolver
class, we could insert the event information into the calendar. There are some required fields in order to insert an event in to calendar. These fields are as follows:
The Activity
class that inserts an event is defined as follows:
package com.chapter4; import java.util.Calendar; import java.util.TimeZone; import android.app.Activity; import android.content.ContentValues; import android.database.Cursor; import android.os.Bundle; import android.content.ContentUris; import android.net.Uri; import android.provider.CalendarContract; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class Chapter4_1Activity extends Activity implements OnClickListener { Button insertButton; long calendarID; long eventID; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); insertButton = (Button)this.findViewById(R.id.buttonInsertEvent); insertButton.setOnClickListener(this); } @Override public void onClick(View v) { addEvent(); } private void addEvent() { calendarID = getCalendarID(); ContentValues eventValues = new ContentValues (); // provide the required fields for creating an event to // ContentValues instance and insert event using // ContentResolver eventValues.put (CalendarContract.Events.CALENDAR_ID,calendarID); eventValues.put (CalendarContract.Events.TITLE,"Event 1"); eventValues.put (CalendarContract.Events.DESCRIPTION, "Testing Calendar API"); eventValues.put (CalendarContract.Events.DTSTART,Calendar.getInstance().getTimeInMillis()); eventValues.put (CalendarContract.Events.DTEND,Calendar.getInstance().getTimeInMillis()); eventValues.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().toString()); Uri eventUri = this.getContentResolver().insert (CalendarContract.Events.CONTENT_URI, eventValues); eventID = ContentUris.parseId(eventUri); } // we use this method in order to get the ID of the calendar because // calendar ID is a required field in creating an event public long getCalendarID() { Cursor cur = null; try { // provide CalendarContract.Calendars.CONTENT_URI to // ContentResolver to query calendars cur = this.getContentResolver().query( CalendarContract.Calendars.CONTENT_URI, null,null,null, null); if (cur.moveToFirst()) { return cur .getLong(cur .getColumnIndex(CalendarContract.Calendars._ID)); } } catch (Exception e) { e.printStackTrace(); } finally { if (cur != null) { cur.close(); } } return -1L; } }
As you can see in this code, we use the
getCalendarID()
method in order to get the ID of the calendar because calendarID
is a required field in creating an event. We provided CalendarContract.Calendars.CONTENT_URI
to ContentResolver
to query calendars.
We used a button click event in order to add an event. On the clicking of this button, we call the
addEvent()
method. In the
addEvent()
method, we provide the required fields for creating an event to the
ContentValues
instance and insert the event using the ContentResolver
. We provide CalendarContract.Events.CONTENT_URI
to ContentResolver
in order to add an event.
The XML code of the layout of this application is LinearLayout
with a Button
component as seen in the following code block:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/buttonInsertEvent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="insert event" /> </LinearLayout>
The screen will look like the following when you execute this code:
In order to use the new Calendar APIs, the minimum SDK version in the AndroidManifest.xml
file should be API Level 14 or more. Furthermore, WRITE_CALENDAR
and
READ_CALENDAR
permissions are required for reading and writing to the calendar. The AndroidManifest.xml
file should look like the following:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.chapter4" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="14" /> <uses-permission android:name="android.permission.WRITE_CALENDAR" /> <uses-permission android:name="android.permission.READ_CALENDAR" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".Chapter4_1Activity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
When the event is created, the calendar will look like the following:
The same event could also be created using Intent
objects
.
The following method shows how to add an event using Intent objects
:
private void addEventUsingIntent() { calendarID = getCalendarID(); Intent intent = new Intent(Intent.ACTION_INSERT) .setData(CalendarContract.Events.CONTENT_URI) .putExtra(CalendarContract.Events.DTSTART, Calendar.getInstance().getTimeInMillis()) .putExtra(CalendarContract.Events.DTEND, Calendar.getInstance().getTimeInMillis()) .putExtra(CalendarContract.Events.TITLE,"Event 1") .putExtra(CalendarContract.Events.DESCRIPTION,"Testing Calendar API"); startActivity(intent); }
We can call this method instead of the
addEvent()
method in order to create an event using Intent
objects. By using Intent
objects, we don't need to create a view in order to create an event. Using Intent
objects is a best practice for
modifying and showing calendars.
Adding an attendee is similar to creating an event. We use CalendarContract.Attendees.CONTENT_URI
as the URI for inserting an attendee. The required fields for inserting an attendee are event ID, attendee e-mail, attendee relationship, attendee status, and attendee type. We put a Button
component in the XML layout of the application. The resulting layout is as follows:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/buttonInsertEvent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="insert event" /> <Button android:id="@+id/buttonInsertAttendee" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="insert attendee" /> </LinearLayout>
Then we call the following method on clicking the insert attendee button:
private void addAttendee() { ContentValues cv = new ContentValues(); cv.put(Attendees.ATTENDEE_NAME, "Murat AYDIN"); cv.put(Attendees.ATTENDEE_EMAIL, "[email protected]"); cv.put(Attendees.EVENT_ID, eventID); cv.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE); cv.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED); cv.put(Attendees.ATTENDEE_TYPE,Attendees.TYPE_OPTIONAL); this.getContentResolver().insert(CalendarContract.Attendees.CONTENT_URI, cv); }
Before clicking on the insert attendee button, an event should be created because we are using an event ID when inserting an attendee.
We use CalendarContract.Reminder.CONTENT_URI
as the URI in inserting a reminder for an event. The required fields for inserting a reminder are event ID, minutes that the reminder needs to fire before the event, and method. We put a
Button
component in the XML layout of the application. The resulting layout is as follows:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/buttonInsertEvent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="insert event" /> <Button android:id="@+id/buttonInsertAttendee" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="insert attendee" /> <Button android:id="@+id/buttonInsertReminder" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="insert reminder" /> </LinearLayout>
Then we call the following method on the click of the insert reminder button:
private void addReminder() { ContentValues values = new ContentValues(); values.put(Reminders.MINUTES, 15); values.put(Reminders.EVENT_ID, eventID); values.put(Reminders.METHOD, Reminders.METHOD_ALERT); this.getContentResolver().insert(CalendarContract.Reminders.CONTENT_URI, values); }
As you see in this code, this reminder will fire 15 minutes before the event's time. Before pressing the insert reminder button, an event should be created because we are using the event ID when inserting a reminder.
When the reminder is added, the calendar will look like the following:
35.171.45.182