This project is a Calendar Service for Android and has been born since I was in need of a service which returned events from all the calendars embedded on an Android Smartphone in a specific timerange.

Hereby, the service basically returns a list which contains the id of a specific calendar and the events of the specific calendar.

You can either find the code repository on GitHub, or simply copy-paste the code below.

Please note that the repository is licensed under the Apache License, Version 2.0.

Basic use

Before going into too many details regarding the service itself, I will first of all show you how to use the library.

The code below essentially specifies how the library is intended to be taken into use:

// The basic constructor will return a time range of +/- 1 day
CalendarService.readCalendar(MainActivity.this);

// Please note that MainActivity.this should be replaced with your own class name or context

// If required, you can specify the required time range:
CalendarService.readCalendar(MainActivity.this, int days, int hours);

// An example can be seen below:
CalendarService.readCalendar(MainActivity.this, 2, 5);

// The example as seen above returns a list of events +/- 2 days and +/- 5 hours respecitvely

As seen, the use of the service is quite basic and can be used for many different purposes such as returning a list of events upon clicking a button.

Although, the service may still not be working as expected, which can be due to missing permissions. For that reason, include the following snippet in AndroidManifest.XML:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.calendarservice"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
    </application>

</manifest>

By now, you should be able to access the calendars on the phone and read the events hereof.

Implementation

Since that you by now understand the overall purpose of the service,  I will by now provide the actual implementation which consits of two classes:

  • The CalendarEvent class which is essentially an object of a calendar event
  • The CalendarService which creates a list of calendar events related to a specific calendar
    • If several calendars exist on the phone (which are not empty), the list will by then contain several calendar IDs which each will contain a list of calendar events

I will start of showing the most basic details, and go into the specifics as we move along.

The Calandar Object (CalendarEvent)

First of all, a Calendar Event (i.e. an object) basically contains the following information:

  • A title which contains the description of the event
  • The begin (start) date of the event which contains the day, the month, the date, the time, the timezone and the year
  • The end date of the event which contains the same information as above
  • Whether or not it is an all day event

The code of how a Calendar Event is implemented can be seen below:

import java.util.Date;

/* 
 * Created by David Laundav and contributed by Christian Orthmann
 * 
 * Copyright 2013 Daivd Laundav
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

public class CalendarEvent implements Comparable<CalendarEvent>{

	private String title;
	private Date begin, end;
	private boolean allDay;

	public CalendarEvent() {

	}

	public CalendarEvent(String title, Date begin, Date end, boolean allDay) {
		setTitle(title);
		setBegin(begin);
		setEnd(end);
		setAllDay(allDay);
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public Date getBegin() {
		return begin;
	}

	public void setBegin(Date begin) {
		this.begin = begin;
	}

	public Date getEnd() {
		return end;
	}

	public void setEnd(Date end) {
		this.end = end;
	}

	public boolean isAllDay() {
		return allDay;
	}

	public void setAllDay(boolean allDay) {
		this.allDay = allDay;
	}

	@Override
	public String toString(){
		return getTitle() + " " + getBegin() + " " + getEnd() + " " + isAllDay();
	}

	@Override
	public int compareTo(CalendarEvent other) {
		// -1 = less, 0 = equal, 1 = greater
		return getBegin().compareTo(other.begin);
	}

}

The Calendar Service (CalendarService)

The specific implementation details of the Calendar Service itself is – in comparison with a Calendar Event as seen above – although much more difficult to explain in brief.

Although, the basic purpose is, that the Calendar Service provides a hash map where each Calendar ID (which contain events) is mapped with its Calendar Events.

Hereby, the implementation details are provided as a part of the source code itself in form of comments.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.text.format.DateUtils;

/* 
 * Created by David Laundav and contributed by Christian Orthmann
 * 
 * Copyright 2013 Daivd Laundav
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * References:
 * http://stackoverflow.com/questions/5883938/getting-events-from-calendar
 * 
 * Please do not delete the references as they gave inspiration for the implementation
 */

public class CalendarService {

	// Default constructor
	public static void readCalendar(Context context) {
		readCalendar(context, 1, 0);
	}

	// Use to specify specific the time span
	public static void readCalendar(Context context, int days, int hours) {

		ContentResolver contentResolver = context.getContentResolver();

		// Create a cursor and read from the calendar
		final Cursor cursor = contentResolver.query(Uri.parse("content://com.android.calendar/calendars"),
		        (new String[] { "_id", "displayName", "selected" }), null, null, null);

		// Create a set containing all of the calendar IDs available on the phone
		HashSet<String> calendarIds = getCalenderIds(cursor);

		// Create a hash map of calendar ids and the events of each id
		HashMap<String, List<CalendarEvent>> eventMap = new HashMap<String, List<CalendarEvent>>();

		// Loop over all of the calendars
		for (String id : calendarIds) {

			// Create a builder to define the time span
			Uri.Builder builder = Uri.parse("content://com.android.calendar/instances/when").buildUpon();
	        long now = new Date().getTime();

	        // create the time span based on the inputs
	        ContentUris.appendId(builder, now - (DateUtils.DAY_IN_MILLIS * days) - (DateUtils.HOUR_IN_MILLIS * hours));
	        ContentUris.appendId(builder, now + (DateUtils.DAY_IN_MILLIS * days) + (DateUtils.HOUR_IN_MILLIS * hours));

	        // Create an event cursor to find all events in the calendar
	        Cursor eventCursor = contentResolver.query(builder.build(),
	                new String[]  { "title", "begin", "end", "allDay"}, "Calendars._id=" + id,
	                null, "startDay ASC, startMinute ASC");

	        System.out.println("eventCursor count="+eventCursor.getCount());

	        // If there are actual events in the current calendar, the count will exceed zero
	        if(eventCursor.getCount()>0)
	        {

	        	// Create a list of calendar events for the specific calendar
	        	List<CalendarEvent> eventList = new ArrayList<CalendarEvent>();

	        	// Move to the first object
	            eventCursor.moveToFirst();

	            // Create an object of CalendarEvent which contains the title, when the event begins and ends, 
	            // and if it is a full day event or not 
	            CalendarEvent ce = loadEvent(eventCursor);

	            // Adds the first object to the list of events
	            eventList.add(ce);

	            System.out.println(ce.toString());

	            // While there are more events in the current calendar, move to the next instance
	            while (eventCursor.moveToNext())
	            {

	            	// Adds the object to the list of events
	            	ce = loadEvent(eventCursor);
	            	eventList.add(ce);

	            	System.out.println(ce.toString());

	            }

	    	    Collections.sort(eventList);
	    	    eventMap.put(id, eventList);

	    	    System.out.println(eventMap.keySet().size() + " " + eventMap.values());

	        }
		}
	}

	// Returns a new instance of the calendar object
	private static CalendarEvent loadEvent(Cursor csr) {
		return new CalendarEvent(csr.getString(0), 
						new Date(csr.getLong(1)),
						new Date(csr.getLong(2)), 
						!csr.getString(3).equals("0"));
	}

	// Creates the list of calendar ids and returns it in a set
	private static HashSet<String> getCalenderIds(Cursor cursor) {

		HashSet<String> calendarIds = new HashSet<String>();

		try
	    {

			// If there are more than 0 calendars, continue
	        if(cursor.getCount() > 0)
	        {

	        	// Loop to set the id for all of the calendars
		        while (cursor.moveToNext()) {

		             String _id = cursor.getString(0);
		             String displayName = cursor.getString(1);
		             Boolean selected = !cursor.getString(2).equals("0");

		            System.out.println("Id: " + _id + " Display Name: " + displayName + " Selected: " + selected);
		            calendarIds.add(_id);

		        	}
	        } 
	    }

	    catch(AssertionError ex)
	    {
	        ex.printStackTrace();
	    }
	    catch(Exception e)
	    {
	        e.printStackTrace();
	    }

		return calendarIds;

	}
}

Conclusion

The Calendar Service has proven to provide the help which I required in form of retrieving all the events from different calendars in a specific time range.

Furthermore, the service itself can be used for a variety of purposes and can easily be expanded for future purposes.

Future Work

I have personally created this service based on my own needs, but I would not hesitate improving it.

If you hereby are in need of specific features, please let me know and I will adapt the service as soon as possible.

Thanks for any feedback in advance.

References

As stated in the CalendarServicethis repository has found inspiration from Akash Thakkar from Stackoverflow.

// David

Leave a Reply

Your email address will not be published. Required fields are marked *