Search code examples
androidapicalendaraccountmanager

How do you get a list of accounts on Android that have calendars?


I am writing an app for Android that creates a series of events in a calendar for the user where normal recurrence just can't handle it. I want to allow the user to choose which account they want to use for the calendar (primarily for sharing the calendar later).

Using AccountManager, I can get all accounts, but not all of them have calendars. Google accounts would technically work, but I want to use Exchange accounts or others that also have calendars.

All of the AccountManager API docs I've read say that features to search for are authenticator specific (and can change). Keeping a list of those would be near impossible. Limiting to a list of known account types is more limiting than I really want.

Are there any other options I missed?


Solution

  • Contrary to my initial beliefs, you do not actually need to touch the account list at all. This was helpful in simplifying the process, and in reducing the number of required permissions.

    Using the information from this page (under Querying a Calendar), you can write a query to the Calendars table and get a full list of Calendars and the Account they belong to.

    In the end, this approach is going to be much more useful to me. Basically, the EVENT_PROJECTION is changed as below from what the example shows.

    public static final String[] EVENT_PROJECTION = new String[] {
        Calendars._ID,
        Calendars.ACCOUNT_NAME,
        Calendars.CALENDAR_DISPLAY_NAME,
        Calendars.ACCOUNT_TYPE,
        Calendars.CALENDAR_ACCESS_LEVEL,
        Calendars.IS_PRIMARY
    };
    

    ACCOUNT_TYPE, CALENDAR_ACCESS_LEVEL and IS_PRIMARY were added so that we know a) which calendar is primary for the account for sorting later, and b) whether or not the user can actually write to it, because we don't want it if it's read-only.

    Also, in the actual query of the calendars table, I made the following changes.

    // Run query
    Cursor cur = null;
    ContentResolver cr = getContentResolver();
    Uri uri = Calendars.CONTENT_URI;
    // Submit the query and get a Cursor object back.
    cur = cr.query(uri, EVENT_PROJECTION, "", null, null);
    

    Since we want all the calendars to start off, the selection and selectionArgs variables in the example are useless.

    Up until we get the final result of the query, basically everything else in the example remains the same.

    Once we have the data, it can be parsed and put into a List, HashMap, etc. sorted and filtered as needed.