AndroidアプリからCalendarProviderを使って、Googleカレンダーに新規にイベントを追加する方法を紹介します。
User Permissions
カレンダーの読み書きに必要なパーミッションを設定しておきます。
<?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カレンダーでイベントの色を変更する際に表示されるリストと同じです。
なお、いくつかのGoogleアカウントで確認してみましたが、現時点ではいずれも上記の配色で固定されていました。
(変更する方法は、あるのでしょうか?)
イベントの追加
まず、"android.provider.CalendarContract.Events" を static import しておきます。
import static android.provider.CalendarContract.Events;
あとは、ContentValues
にイベント追加先のGoogleカレンダーの_ID
とイベントの各種プロパティを設定し、ContentResolver
のinsert()
を呼び出すと、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);
以下の通り、イベントが追加されました。