AndroidでCalendarを操作する

2011.09.03

Androidでカレンダー操作?

カレンダー操作といっても日付を変更したりホーム画面にカレンダーを表示・・・という意味ではありません。
Androidを実際に使用している人はわかると思いますが、Androidは標準でGoogleのサービスと非常に密接に関連しています。
標準で連携しているサービスとは、Gmailと連絡先リスト(コンタクトリスト)、そしてGoogleカレンダーです。
Android標準のカレンダーアプリを起動すると、通常ならばGoogleカレンダーと同期されたデータが表示されると思います。
また、Androidのカレンダーにイベントを追加すると、Googleカレンダーといつのまにかデータが同期されています。
このように、Googleカレンダーとの連携は標準でAndroidに組み込まれています。
Androidで実際に開発したことのある人は、コンタクトリストみたいにコンテンツプロバイダを使えばいいのでは?と思うかもしれません。
ではまず、コンテンツプロバイダについて簡単に説明をします。

コンテンツプロバイダとは

コンテンツプロバイダとは、Androidが提供している情報の連携方式です。
これを利用すれば、複数のアプリケーション間で共通のデータを共有することができます。
データベースのテーブルを用意しておき、複数のアプリケーションからアクセスしてもらうイメージです。
コンテンツプロバイダは自分で作成、公開することも可能です。
標準で用意されている電話帳のアクセスを例に見てみましょう。
※実際に実行するには、android.permission.READ_CONTACTSの権限が必要です

import android.database.Cursor;
import android.provider.ContactsContract.Contacts;

// カラムのリスト
String[] projection = new String[] { 
		Contacts.DISPLAY_NAME, 
		Contacts.HAS_PHONE_NUMBER };
//クエリの実行
Cursor c = managedQuery(
		Contacts.CONTENT_URI,//検索先のURI 
		projection, //取得するカラム
		null, //検索条件
		null, //検索条件にいれる値
		null  //ソート指定
		);
//これでもOK
//ContentResolver cr = context.getContentResolver();
//Cursor c = cr.query(Contacts.CONTENT_URI, projection, null, null, null);

//取得したカーソルを回し、1レコードずつ値を取得
while (c.moveToNext()) {
	String name = c.getString(0);
	String phoneNumber = c.getString(1);
}

電話帳のコンテンツプロバイダに対して、データを検索するクエリを実行しています。
取得するカラムをString配列で定義し、managedQueryメソッド(Activityクラスが持っています)へ各引数を渡し、結果を取得しています。
(ContentResolverを取得してqueryを実行しても実行は可能です)
カラムの定数名は、Contactsクラスで用意されてるものを使用します。
そして、Uriを使用してコンテンツプロバイダを指定しています。
これ以外にもいろいろなコンテンツプロバイダが用意されているので、公式ドキュメント等を確認してみてください。

カレンダー用のコンテンツプロバイダ?

このように、コンテンツプロバイダを使用すれば、電話帳などの共通データにアクセスできました。
カレンダーも同じようにコンテンツプロバイダにアクセスすればよさそうですね。
公式ドキュメントの下記ページにコンテンツプロバイダについての情報がのっているので、まずそこを確認してみましょう。
http://developer.android.com/intl/ja/reference/android/provider/package-summary.html
http://developer.android.com/intl/ja/guide/topics/providers/content-providers.html
これらのページを見てもらえばわかりますが、カレンダーに関する記述がありません。
正確な理由はわかりませんが、Googleは公式にカレンダー用のAPIやコンテンツプロバイダを公開していないのです。
ではどうすればよいのか?

カレンダーを操作してみる

公式にはドキュメント化されていませんが、カレンダーのコンテンツプロバイダはちゃんとあります。
では実際にカレンダー情報にアクセスしてみましょう。

Note:カレンダーを使用する際の注意点
Googleが公開していないということはそれなりの理由があるはずです。
将来的にカレンダー周りのコンテンツプロバイダに大きな変更が入る可能性もあるので、実際に開発する際には注意してください。

まず、AndroidManifest.xmlに権限を追記します。

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

これでカレンダーの読取が可能になりました。
次にコンテンツプロバイダにアクセスするコードを記述します。今回は自分が持っているカレンダーのリストを表示しましょう。
ちなみに、エミュレータ上で実行してもカレンダーのサービス自体がはいっていないので、エラーになります。
実機を接続して試してみてください。

//カラム
String[] projection = new String[] { "_id", "name" };
//Uriの作成
//Froyo以前のOSの場合、content://calendar/calendarsを指定する
Uri calendars = Uri.parse("content://com.android.calendar/calendars");
//クエリ実行
Cursor c = managedQuery(calendars, projection, null, null, null);
//値を取得
if (c.moveToFirst()) {
	String name;
	String id;
	int nameColumn = c.getColumnIndex("name");
	int idColumn = c.getColumnIndex("_id");
	do {
	  name = c.getString(nameColumn);
	  id = c.getString(idColumn);
	} while (c.moveToNext());
}

UriはOSのバージョンによって違います。 テストしている実機が2.1(Froyo)以前の場合「content://calenar/calendars」を指定します。
2.1より後のバージョンであれば、「content://com.android.calendar/calendars」を指定してください。
あとは普通に取得したカーソルを回して値を表示しています。
実機でためしている人は、実際に自分のカレンダーリストが取得できると思います。

まとめ

今回はカレンダーのリストを取得しましたが、取得したカレンダーに対してイベントの登録なども可能です。
なお、ここやAndroidのソースをdownloadしてみれば、実際に内部で使用されているクラスをみることができます。
カラム名などはここを参考に実装してみてください。