LoginSignup
11
10

More than 5 years have passed since last update.

Android から CalendarProviderを使ってGoogleカレンダーにイベントを追加する

Posted at

AndroidアプリからCalendarProviderを使って、Googleカレンダーに新規にイベントを追加する方法を紹介します。

User Permissions

カレンダーの読み書きに必要なパーミッションを設定しておきます。

AndroidManifets.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.xxx">
    ...
    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
    ...
</manifest>
  • Android 6.0 (Marshmallow) 以降もサポートする際には、追加でRuntime Permissionへの対応が必要です。

カレンダーの一覧取得

イベントの追加対象であるカレンダーを見つけるために、CalendarProviderを使ってカレンダーの一覧を取得します。
詳細は、「CalendarProviderを使ってGoogleカレンダーにアクセスする」をご確認ください。

まず、"android.provider.CalendarContract.Calendars"を static import しておきます。

import static android.provider.CalendarContract.Calendars;

次に、個々のカレンダーについて取得したいプロパティを列挙します。

    // プロジェクション配列。
    // 取得したいプロパティの一覧を指定する。
    private static final String[] CALENDAR_PROJECTION = new String[] {
            Calendars._ID,
            Calendars.NAME,
            Calendars.ACCOUNT_NAME,
            Calendars.ACCOUNT_TYPE,
            Calendars.CALENDAR_COLOR,
            Calendars.CALENDAR_COLOR_KEY,
            Calendars.CALENDAR_DISPLAY_NAME,
            Calendars.CALENDAR_ACCESS_LEVEL,
            Calendars.CALENDAR_TIME_ZONE,
            Calendars.VISIBLE,
            Calendars.SYNC_EVENTS,
            Calendars.OWNER_ACCOUNT,
    };

    // プロジェクション配列のインデックス。
    // パフォーマンス向上のために、動的に取得せずに、静的に定義しておく。
    private static final int CALENDAR_PROJECTION_IDX_ID = 0;
    private static final int CALENDAR_PROJECTION_IDX_NAME = 1;
    private static final int CALENDAR_PROJECTION_IDX_ACCOUNT_NAME = 2;
    private static final int CALENDAR_PROJECTION_IDX_ACCOUNT_TYPE = 3;
    private static final int CALENDAR_PROJECTION_IDX_CALENDAR_COLOR = 4;
    private static final int CALENDAR_PROJECTION_IDX_CALENDAR_COLOR_KEY = 5;
    private static final int CALENDAR_PROJECTION_IDX_CALENDAR_DISPLAY_NAME = 6;
    private static final int CALENDAR_PROJECTION_IDX_CALENDAR_ACCESS_LEVEL = 7;
    private static final int CALENDAR_PROJECTION_IDX_CALENDAR_TIME_ZONE = 8;
    private static final int CALENDAR_PROJECTION_IDX_VISIBLE = 9;
    private static final int CALENDAR_PROJECTION_IDX_SYNC_EVENTS = 10;
    private static final int CALENDAR_PROJECTION_IDX_OWNER_ACCOUNT = 11;

最後に、クエリを発行してカーソルを取得し、カーソルから個々のカレンダーの情報を取得します。
(事前に絞り込むための条件が明確な場合には、selection/selectionArgsに値を指定してください)

        // クエリ条件を設定する
        final Uri uri = Calendars.CONTENT_URI;
        final String[] projection = CALENDAR_PROJECTION;
        final String selection = null;
        final String[] selectionArgs = null;
        final String sortOrder = null;

        // クエリを発行してカーソルを取得する
        final ContentResolver cr = getContentResolver();
        final Cursor cur = cr.query(uri, projection, selection, selectionArgs, sortOrder);

        while (cur.moveToNext()) {
            // カーソルから各プロパティを取得する
            final long id = cur.getLong(CALENDAR_PROJECTION_IDX_ID);
            final String name = cur.getString(CALENDAR_PROJECTION_IDX_NAME);
            final String accountName = cur.getString(CALENDAR_PROJECTION_IDX_ACCOUNT_NAME);
            final String accountType = cur.getString(CALENDAR_PROJECTION_IDX_ACCOUNT_TYPE);
            final int calendarColor = cur.getInt(CALENDAR_PROJECTION_IDX_CALENDAR_COLOR);
            final String calendarColorkey = cur.getString(CALENDAR_PROJECTION_IDX_CALENDAR_COLOR_KEY);
            final String calendarDisplayName = cur.getString(CALENDAR_PROJECTION_IDX_CALENDAR_DISPLAY_NAME);
            final int calendarAccessLevel = cur.getInt(CALENDAR_PROJECTION_IDX_CALENDAR_ACCESS_LEVEL);
            final String calendarTimeZone = cur.getString(CALENDAR_PROJECTION_IDX_CALENDAR_TIME_ZONE);
            final int visible = cur.getInt(CALENDAR_PROJECTION_IDX_VISIBLE);
            final int syncEvents = cur.getInt(CALENDAR_PROJECTION_IDX_SYNC_EVENTS);
            final String ownerAccount = cur.getString(CALENDAR_PROJECTION_IDX_OWNER_ACCOUNT);
        }

これにより、イベント追加先のGoogleカレンダーを選択するための情報が得られました。
また、イベント追加先のGoogleカレンダーに関して、以下の情報も得られました。
- カレンダーの _ID(例: 1)
- ACCOUNT_NAME(例: "aaa@gmail.com")
- ACCOUNT_TYPE(例: "com.google")

色情報の一覧取得

カレンダーやイベントに設定できる色情報に関しては、カレンダーやイベントのテーブルとは別のテーブルでに管理されています。

CalendarProvider を使うことで、特定のGoogleアカウントにおいて、イベントに使用可能な色情報の一覧を取得することができます。

まず、"android.provider.CalendarContract.Colors" を static import しておきます。

import static android.provider.CalendarContract.Colors;

次に、個々の色情報について取得したいプロパティを列挙します。

    // プロジェクション配列
    private static final String[] COLOR_PROJECTION = new String[] {
            Colors._ID,
            Colors.COLOR,
            Colors.COLOR_KEY,
            Colors.COLOR_TYPE,
            Colors.ACCOUNT_NAME,
            Colors.ACCOUNT_TYPE,
    };

    // プロジェクション配列のインデックス
    private static final int COLOR_PROJECTION_IDX_ID = 0;
    private static final int COLOR_PROJECTION_IDX_COLOR = 1;
    private static final int COLOR_PROJECTION_IDX_COLOR_KEY = 2;
    private static final int COLOR_PROJECTION_IDX_COLOR_TYPE = 3;
    private static final int COLOR_PROJECTION_IDX_ACCOUNT_NAME = 4;
    private static final int COLOR_PROJECTION_IDX_ACCOUNT_TYPE = 5;

最後に、クエリを発行してカーソルを取得し、カーソルから個々の色情報を取得します。

    private void queryColors(
            final String accountName,    // 例)"aaa@google.com"
            final String accountType       // 例)"com.google"
    ) {
        // クエリ条件を設定する
        final Uri uri = Colors.CONTENT_URI;
        final String[] projection = COLOR_PROJECTION;
        // 特定のアカウントで、イベントの色情報を持つレコードのみを対象とする
        final String selection =
                "((" + Colors.ACCOUNT_NAME + " = ?)"
                + "AND (" + Colors.ACCOUNT_TYPE + " = ?)"
                + "AND (" + Colors.COLOR_TYPE + " = ?))";
        final String[] selectionArgs = new String[] {
                accountName,
                accountType,
                String.valueOf(Colors.TYPE_EVENT),
        };
        final String sortOrder = null;

        // クエリを発行してカーソルを取得する
        final ContentResolver cr = getContentResolver();
        final Cursor cur = cr.query(uri, projection, selection, selectionArgs, sortOrder);

        while (cur.moveToNext()) {
            // カーソルから各プロパティを取得する
            final long id = cur.getLong(COLOR_PROJECTION_IDX_ID);
            final int color = cur.getInt(COLOR_PROJECTION_IDX_COLOR);
            final String colorKey = cur.getString(COLOR_PROJECTION_IDX_COLOR_KEY);
            final String colorType = cur.getString(COLOR_PROJECTION_IDX_COLOR_TYPE);
        }
    }

これにより、以下のような、イベントに使用可能な色情報のテーブルが作成できました。
イベントを追加する際に、以下の color_index の値でイベントの色を指定します。

_id color_index color Googleカレンダーでの表記
33 11 0xFFDC2127 Tomato / トマト
28 6 0xFFFFB878 Tangerine / ミカン
30 5 0xFFFBD75B Banana / バナナ
27 10 0xFF51B749 Basil / バジル
35 2 0xFF7AE7BF Sage / セージ
31 7 0xFF46D6DB Peacock / ピーコック
32 9 0xFF5484ED Blueberry / ブルーベリー
25 1 0xFFA4BDFC Lavender / ラベンダー
34 3 0xFFDBADFF Grape / ブドウ
29 4 0xFFFF887C Flamingo / フラミンゴ
26 8 0xFFE1E1E1 Graphite / グラファイト

この配色は、Googleカレンダーでイベントの色を変更する際に表示されるリストと同じです。

device-2016-10-12-152024.png

なお、いくつかのGoogleアカウントで確認してみましたが、現時点ではいずれも上記の配色で固定されていました。
(変更する方法は、あるのでしょうか?)

イベントの追加

まず、"android.provider.CalendarContract.Events" を static import しておきます。

import static android.provider.CalendarContract.Events;

あとは、ContentValuesにイベント追加先のGoogleカレンダーの_IDとイベントの各種プロパティを設定し、ContentResolverinsert()を呼び出すと、Googleカレンダーにイベントが追加されます。

    private long addEvent(
            final long calendarId,
            final String title,
            final String description,
            final String colorKey,
            final long startMillis,
            final long endMillis
    ) {
        final ContentResolver cr = getContentResolver();

        final ContentValues values = new ContentValues();
        values.put(Events.CALENDAR_ID, calendarId);
        values.put(Events.TITLE, title);
        values.put(Events.DESCRIPTION, description);
        values.put(Events.EVENT_COLOR_KEY, colorKey);
        values.put(Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
        values.put(Events.DTSTART, startMillis);
        values.put(Events.DTEND, endMillis);

        final Uri uri = cr.insert(Events.CONTENT_URI, values);

        final long eventId = Long.parseLong(uri.getLastPathSegment());
        return eventId;
    }

なお、呼び出し側は以下のようになります。

        final long calendarId = 1;
        final String eventColorKey = "4";

        final long now = new Date().getTime();
        final long anHourLater = now + 60 * 60 * 1000;
        this.addEvent(calendarId, "イベントのタイトル", "イベントの説明", eventColorKey, now, anHourLater);

以下の通り、イベントが追加されました。

device-2016-10-12-200306.png

参考情報

11
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10