2011-10-03

プログラムからGoogleカレンダーを操作する


Googleカレンダーを初めとしたGoogleサービスは、「Google Data Protocol」として外部から利用できるようになっており、同じく公開されている「Google Data API」[1]をプログラムから呼び出すことで、操作する事が可能である。

Googleカレンダーをプログラムから操作する場合、「Google Calendar Data API」を呼び出すのがよさそうである。プログラム言語はJava/.NET/PHP/Python/JavaScript/Objective-C、他のAPIとしてはCalDAVからアクセスする方法もあるようだ[2]。ここでは、JavaのAPIを使って操作することとする。


実行に当たっての準備は、ライブラリとして以下のファイルを依存ライブラリとして設定し、実行を確認している。
  • gdata-calendar-1.0.jar
  • gdata-client-1.0.jar
  • mail.jar
なぜかJavaMailのjarであるmail.jarが必要である。これらが公式な説明として必要とされているが、mavenのセントラルリポジトリから取得できたため、以下にPOMのdependencyを記載する。「java mail」「google calendar」で検索した結果から得られたものである。

  <dependencies>
  	<dependency>
  		<groupId>org.codemonkey.simplejavamail</groupId>
  		<artifactId>simple-java-mail</artifactId>
  		<version>2.0</version>
  	</dependency>
  	<dependency>
  		<groupId>com.google.api.client</groupId>
  		<artifactId>google-api-data-calendar-v2</artifactId>
  		<version>1.0.10-alpha</version>
  	</dependency>
  	<dependency>
  		<groupId>org.openengsb.wrapped</groupId>
  		<artifactId>com.google.gdata</artifactId>
  		<version>1.41.5.w1</version>
  		<type>bundle</type>
  	</dependency>
  </dependencies>


まずは、自分のカレンダーの全エントリを取得するプログラム。このプログラムでは、以下のmainクラスの他に、Constantsというクラスを定義しており、以下のデータを定数として定義している。

  • String loginAddr(gmailのアカウント@gmail.com)
  • String loginPassword(アカウントのパスワード)
  • URL url("http://www.google.com/calendar/feeds/default/private/full")

import java.io.IOException;
import java.util.List;

import com.google.gdata.client.calendar.CalendarQuery;
import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.calendar.CalendarEventEntry;
import com.google.gdata.data.calendar.CalendarEventFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

public class SampleMain {

	public static void main(String[] args) throws IOException, ServiceException {
		Constants.setUrl();
		
		CalendarService service = getMyCalendar();
		
		List<CalendarEventEntry> eventList = getEverySchedules(service);
		
		displaySchedule(eventList);
	}
	
	public static CalendarService getMyCalendar() throws AuthenticationException
	{
		CalendarService service = new CalendarService("gmail-sample-1.0");
		service.setUserCredentials(Constants.loginAddr, Constants.loginPassword);
		System.out.println("CalendarService Created.");
		return service;
	}
	
	public static List<CalendarEventEntry> getEverySchedules(CalendarService service) throws IOException, ServiceException
	{
		CalendarQuery query = new CalendarQuery(Constants.url);
		CalendarEventFeed results = service.query(query, CalendarEventFeed.class);
		List<CalendarEventEntry> result = results.getEntries();
		System.out.println("Result get success.");
		return result;
	}
	
	public static void displaySchedule(List<CalendarEventEntry> entries)
	{
		System.out.println("=== BEGIN All schedules ===");
		for (CalendarEventEntry entry : entries)
		{
			System.out.println("== schedule begin ==");
			System.out.println("Title:[" + entry.getTitle().getPlainText() + "]");
			System.out.println("Start Date:[" + entry.getTimes().get(0).getStartTime() + "]");
			System.out.println("End Date:[" + entry.getTimes().get(0).getEndTime() + "]");
			System.out.println("Summary:[" + entry.getSummary() + "]");
			System.out.println("Place:[" + entry.getLocations().get(0).getValueString() + "]");
			System.out.println("== schedule end ==");
		}
		System.out.println("=== END All schedules ===");
	}
}

あらかじめ予定が入れてある場合、以下のような実行結果が得られる。

=== BEGIN All schedules ===
== schedule begin ==
Title:[適当な未来の予定]
Start Date:[2011-08-20T10:30:00.000+09:00]
End Date:[2011-08-20T11:30:00.000+09:00]
Summary:[null]
Place:[日本武道館]
== schedule end ==
== schedule begin ==
Title:[適当な過去の予定]
Start Date:[2011-08-18T09:00:00.000+09:00]
End Date:[2011-08-18T10:00:00.000+09:00]
Summary:[null]
Place:[埼玉スーパーアリーナ]
== schedule end ==
=== END All schedules ===

次に、単一ユーザで複数のカレンダーを持っている場合に、カレンダーの一覧を取得するサンプル。このサンプルでも、以下の値をConstantsクラスに別途定義している。


  • String loginAddr(gmailのアカウント@gmail.com)
  • String loginPassword(アカウントのパスワード)
  • URL url("http://www.google.com/calendar/feeds/default/allcalendars/full")
このとき、urlに"http://www.google.com/calendar/feeds/default/owncalendars/full"を指定すると、ユーザが所有するもののみ取得になる(allcalendarsでは、自分が所有していないカレンダーでも取得対象となる)

import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.calendar.CalendarEntry;
import com.google.gdata.data.calendar.CalendarFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;


public class TestMain {

	/**
	 * @param args
	 * @throws ServiceException 
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException, ServiceException {
		// TODO Auto-generated method stub

		CalendarService service = getMyCalendar();
		
		CalendarFeed feeds = service.getFeed(Constants.allCalendarUrl, CalendarFeed.class);
		
		List<CalendarEntry> entries = feeds.getEntries();
		
		for (CalendarEntry entry : entries)
		{
			System.out.println(entry.getTitle().getPlainText());
		}
		
	}

	private static CalendarService getMyCalendar() throws AuthenticationException {
		CalendarService ret = new CalendarService("example");
		ret.setUserCredentials(Constants.loginAddr, Constants.loginPassword);
		
		return ret;
	}

}

同じく、複数のカレンダーを保持するようにしている場合、実行結果は以下のようになる。

1つめのカレンダー(デバッグ用)
2番目のカレンダー(デバッグ用)
最初のカレンダー(デバッグ用)
4つ目のカレンダー(デバッグ用)
日本の祝日
連絡先の誕生日と予定

そして、上記2つの事ができるならば、「自分が保持しているカレンダーの下にぶら下がっている全ての予定を取得」することも可能ではないかと考えがち(というか、自分も考えた)だが、一筋縄ではいかない。方法はあるにはあるのだが、オフィシャルに公開されている方法でないし、いつまでも同じ方法でできるとも限らない。ともかく長くなってしまったので、このエントリはここまでとする。

0 件のコメント:

コメントを投稿