【Java】APIでGoogleカレンダーの予定登録+取得+更新

虎の穴ラボのH.Hです。
Googleカレンダーに自動で予定を登録取得更新するプログラムを作ったので、手順をまとめました。
# 1.準備
## 1.1 APIの有効化する
### 1.1.1 GoogleCoudPlatformにアクセスする
下記のURLにアクセスする
https://console.cloud.google.com/
### 1.1.2 初回アクセスした際には利用規約に同意する
### 1.1.3 APIを画面上部の検索枠で検索する
「CalendarAPI」と検索すると「Google Calendar API」が見つかる
### 1.1.4 APIを有効にする
「Google Calendar API」のリンクをクリックするとAPIの詳細画面に遷移するので「有効にするボタン」をおす
## 1.2 認証情報の設定
### 1.2.1 認証情報を作成するプロジェクトを作成する
初回の場合は「My First Project」が作成されている。そのままでも問題はありません。（専用のプロジェクトを作成しても良い）
### 1.2.2 プロジェクトのダッシュボードを開く
プロジェクトの設定に移動する
![7EE39E0D-203A-4BFB-8D8F-7C8B23490750_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869077/22728aca-8af8-8128-64d2-e60c361e9cfc.jpeg)
### 1.2.3 メニューからサービスアカウントを選択
![BEE5E3ED-4327-4F21-A2A9-54E748DF1C44_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869077/0c42fc44-61ef-6b26-9199-a88ccb9c609f.jpeg)
### 1.2.4 サービスアカウントの作成
サービスアカウント名は任意の値で問題はありません。
プロジェクトへのアクセスの許可などは不要です。
完了すると以下のような画面になります。
![14FBCDC3-8416-4B84-97A4-D6F32A28FCBD_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869077/b4dc0018-7318-9099-3851-f405fccdce38.jpeg)
### 1.2.5 操作の中から「鍵を管理」を選択する
選択すると下のような画面になります。
![A72E4DB2-08EB-4D8E-858E-C949D3A5608F_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869077/7934e511-2f0b-10a0-5c05-867dee383ec7.jpeg)
### 1.2.6 鍵を追加から「新しい鍵を生成」する
キーのタイプはJSONを選択する。成功するとjsonファイルがダウンロードされる。

## 1.3 連携するGoogleカレンダーの設定
### 1.3.1 今回は新しいカレンダーを作る。
![49DC417A-CB0F-461F-8C66-1E6247A1F5A6_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869077/09bc4f86-82b6-be16-ea48-67b451864d75.jpeg)
### 1.3.2 設定から「特定のユーザーとの共有」にユーザーを追加する
追加するユーザーは「サービスアカウントの作成」の画面に表示されたメールアドレスを入力し、権限は「変更及び共有の管理権限」に変更する。

設定はここまでです。

# 2.プログラム
## 2.1 jarファイルの取得
認証部分のライブラリーはカレンダーAPI用など様々なライブラリーが必要です。
今回使用したライブラリーは以下の場所やファイルです。
1)api-client-library
https://developers.google.com/api-client-library/java/google-api-java-client/download
2)認証関連のライブラリ
appengine-api-1.0-sdk-1.9.88.jar
google-auth-library-appengine-0.25.3.jar
google-auth-library-credentials-0.25.3.jar
google-auth-library-oauth2-http-0.25.3.jar
3)Googleカレンダーのライブラリ
google-api-services-calendar-v3-rev411-1.25.0.jar

## 2.2 登録
認証を行い予定情報作成し、登録を行う。
例) 2021/4/17 15:00~15:10の予定の登録

```java
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();

Credentials credentials =AppEngineCredentials.fromStream(new FileInputStream(jsonファイルのパス))
                        .createScoped(Collections.singleton(CalendarScopes.CALENDAR_EVENTS));

Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JacksonFactory.getDefaultInstance(), new HttpCredentialsAdapter(credentials))
        .setApplicationName(任意の文字列)
        .build();

EventDateTime startEventDateTime = new EventDateTime().setDateTime(new DateTime("2021-04-17T15:00:00.000+09:00")); // イベント開始日時
EventDateTime endEventDateTime = new EventDateTime().setDateTime(new DateTime("2021-04-17T15:10:00.000+09:00")); // イベント終了日時

String summary = "タイトル";
String description = "詳細";

Event event = new Event()
       .setSummary(summary)
       .setDescription(description)
       .setStart(startEventDateTime)
       .setEnd(endEventDateTime);

event = service.events().insert("XXXXXXXXXXXXXXXXXXXXX@group.calendar.google.com", event).execute(); //カレンダーの設定画面にあるカレンダーIDをいれる
```
終日の予定の登録はイベント開始と終了日時を以下のように設定します。

```java
EventDateTime startEventDateTime = new EventDateTime().setDate(new DateTime("2021-04-17")); // イベント開始日時
EventDateTime endEventDateTime = new EventDateTime().setDate(new DateTime("2021-04-17")); // イベント終了日時
```
## 2.3 取得
予定の取得する。
基本は下記の処理で取得できる。

```java
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();

Credentials credentials =AppEngineCredentials.fromStream(new FileInputStream(jsonファイルのパス))
                        .createScoped(Collections.singleton(CalendarScopes.CALENDAR_EVENTS));

Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JacksonFactory.getDefaultInstance(), new HttpCredentialsAdapter(credentials))
        .setApplicationName(任意の文字列)
        .build();

Events events = service.events().list("XXXXXXXXXXXXXXXXXXXXX@group.calendar.google.com").execute();
```
期間指定する場合(以下の例は4/17~4/18の予定の取得)は以下の通り

```java
Events events=service.events().list("XXXXXXXXXXXXXXXXXXXXX@group.calendar.google.com")
                .setTimeMax(new DateTime("2021-04-18T00:00:00.000+09:00"))
                .setTimeMin(new DateTime("2021-04-17T00:00:00.000+09:00")).execute();
```

## 2.4 更新
予定の更新は予定個別に設定されるeventIDを指定してAPIを実行する。
以下の例はタイトルの変更した場合

```java
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();

Credentials credential =AppEngineCredentials.fromStream(new FileInputStream(jsonファイルのパス))
                        .createScoped(Collections.singleton(CalendarScopes.CALENDAR_EVENTS));

Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JacksonFactory.getDefaultInstance(), new HttpCredentialsAdapter(credential))
        .setApplicationName(任意の文字列)
        .build();
Event event=null;
//イベントの登録や検索から更新するEventを取得する
event.setSummary("更新後タイトル");
event = service.events().update("XXXXXXXXXXXXXXXXXXXXX@group.calendar.google.com",event.getId(), event).execute();
```

# 注意点
作成するにあたり以下の点に気をつける必要があります。
## 1)タイムゾーンの指定が必要になる
予定登録の際に「+09:00」を付けないと、カレンダーが日本時間の設定だとしても時間がずれて登録されます。
## 2)取得された予定の順序が決まっていない
予定の取得にはorderByの変数の指定をしないと、順序は確定されません。
今回は特定期間の予定の取得を行っただけなので設定はしませんでした。
## 3)認証に使用するクラスの非推奨化
過去のバージョンで使用されていた認証部分のクラスが最新のライブラリでは非推奨になっていました。非推奨のクラスでも認証は可能ですが、今後のことを考えると推奨されているクラスで実装が必要だと思います。

|  |クラス名|
|---|---|
|非推奨|GoogleCredential|
|推奨|AppEngineCredentials|