tags:

views:

1381

answers:

4

Is it possible to get the calendar's entries from the phone offline? It seem the only way is to use gdata-java-client.

+3  A: 

You can use the calendar content provider (com.android.providers.calendar.CalendarProvider). Example:


ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = contentResolver.query(Uri.parse("content://calendar/events"), null, null, null, null);

while(cursor.moveToNext()) {
    String eventTitle = cursor.getString(cursor.getColumnIndex("title"));
    Date eventStart = new Date(cursor.getLong(cursor.getColumnIndex("dtstart")));
    // etc.
}

edit: you might want to put this in a wrapper (see Isaac's post) as it's currently a private API.

Josef
Yes, but this is a private API that could break any time.
Isaac Waller
You're absolutely right and your wrapper is obviously a very good idea even though you still have to go back into your app's code when/if they change something. And once the API is made public, the wrapper might be obsolete anyways.
Josef
+3  A: 

Currently, this is not possible without using private APIs (see Josef's post.) There is a Calendar provider, but it is not public yet. It could change anytime and break your app.
Though, it probably will not change (I don't think they will change it from "calendar"), so you might be able to use it. But my recommendation is to use a separate class like this:

public class CalendarProvider {
     public static final Uri CONTENT_URI = Uri.parse("content://calendar");
     public static final String TITLE = "title";
     public static final String ....

And use those instead of the strings directly. This will let you change it very easily if/when the API changes or it is made public.

Isaac Waller
Thanks! Btw, are you able to use the Calendar (by building the 2 apk from the sources) and the "Google Login Service" from the DevTools with the latest SDK (1.5 R1) ?
brunoqc
Google Login Service is Google proprietary stuff, it always crashes unless you have a real phone. I haven't tried the calendar.
Isaac Waller
+1  A: 

About the API that can change... The whole ContentProvider approach won't change that quickly so can already overcome a lot of problems by only updating the strings. Therefor create constants you reuse over the whole project.

public static final String URI_CONTENT_CALENDAR_EVENTS = "content://calendar/events";

ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = contentResolver.query(Uri.parse(URI_CONTENT_CALENDAR_EVENTS), null, null, null, null);
    //etc

If you want a proper private API you'll have to create a pojo and some services like this:

public class CalendarEvent {
    private long id;
    private long date;
    //etc...
}

public interface CalendarService {

    public Set<CalendarEvent> getAllCalendarEvents();

    public CalendarEvent findCalendarEventById(long id);

    public CalendarEvent findCalendarEventByDate(long date);

}

and so on. This way you'll only have to update the CalendarEvent object and this service in case the API changes.

hcpl
+1  A: 

Josef and Isaac's solutions for accessing the calendar only work in Android 2.1 and earlier. Google have changed the base content URI in 2.2 from "content://calendar" to "content://com.android.calendar". This change means the best approach is to attempt to obtain a cursor using the old base URI, and if the returned cursor is null, then try the new base URI.

Please note that I got this approach from the open source test code that Shane Conder and Lauren Darcey provide with their Working With The Android Calendar article.

private final static String BASE_CALENDAR_URI_PRE_2_2 = "content://calendar";
private final static String BASE_CALENDAR_URI_2_2 = "content://com.android.calendar";
/*
 * Determines if we need to use a pre 2.2 calendar Uri, or a 2.2 calendar Uri, and returns the base Uri
 */
private String getCalendarUriBase() {
    Uri calendars = Uri.parse(BASE_CALENDAR_URI_PRE_2_2 + "/calendars");
    try {
        Cursor managedCursor = managedQuery(calendars, null, null, null, null);
        if (managedCursor != null) {
            return BASE_CALENDAR_URI_PRE_2_2;
        }
        else {
            calendars = Uri.parse(BASE_CALENDAR_URI_2_2 + "/calendars");
            managedCursor = managedQuery(calendars, null, null, null, null);

            if (managedCursor != null) {
                return BASE_CALENDAR_URI_2_2;
            }
        }
    } catch (Exception e) { /* eat any exceptions */ }

    return null; // No working calendar URI found
}
Nick Street