AIPOのモバイル画面のスケジュールがものすごーく見づらいのでGoogleカレンダーにAIPOのスケジュールを書き出してGoogleカレンダーでスケジュールを確認できるようにします。
今回はjavaを使用してGoogleカレンダーAPIを操作します。
やり方は完全な同期というわけではなく、AIPO→Googleカレンダーへの反映です。
Googleカレンダーの予定を消して新たにAIPOスケジュールを書き出すというのを定期的に実行します。
なのでGoogleカレンダーの予定を変更してもAIPO側には同期されません。
あくまでAIPOのスケジュールをGoogleカレンダーに表示するだけです。
Googleカレンダー側の設定
GoogleカレンダーでAIPO用の新しいカレンダーを作成します。
作成しなくてもいいんですが、プライマリーを使用するとAIPO以外のスケジュールも消えてしまいます。
「友だちのカレンダーを追加」と書かれている右のプラスボタンをクリックして「新しいカレンダー」を選択。
名前を「AIPO」として作成します。
マイカレンダーのAIPOの右のメニューバーから「設定と共有」を選択。
「カレンダーの統合」パネルの「カレンダー ID」をメモります。
Google Calendar APIの設定
新しいプロジェクトの作成
デベロッパーコンソールで新しいプロジェクトを作成。
作成しなくてもすでにあるプロジェクトを使用しても構いません。
コンソール左上のセレクトボックスを押す。
プロジェクトの選択画面が出るので「新しいプロジェクト」を選択。
適当にプロジェクト名を決めて「作成」。
Google Calendar APIの有効化
左上のナビゲーションメニューから「APIとサービス」→「ライブラリ」を選択。
「calendar」と検索。
「Google Calendar API」を選択。
「有効にする」をクリック。
認証情報の設定
認証情報の「OAuth同意画面」で「ユーザーに表示するサービス名」を設定して「保存」。
ここのサービス名がユーザーにカレンダー操作の認証を得るとき表示されるので、わかりやすくしたほうがいいでしょう。
「認証情報」→「認証情報を作成」→「OAtuhクライアントID」を選択。
「アプリケーションの種類」を「その他」にして名前を適当に付けます。
一番右のダウンロードボタンからJSONファイルをダウンロードします。
保存したファイル名を「client_secret.json」に変更します。
java側のプログラム
ecliseの設定
クライアントプログラムはeclipseで作成します。
Gradleを使用しますのでeclipseでGradleが使えるようにプラグインをインストールします。
「ヘルプ」→「Eclipseマーケットプレイス」で「Gradle」と検索します。
Gradle IDE Packをインストール。
これでGradleが使用できます。
Gradleプロジェクトの作成
新規プロジェクトで「Gradle(STS)プロジェクト」を作成。
サンプル・プロジェクトはJava Quickstartでいいでしょう。
プロジェクト作成するとサンプルクラスが作成されているので削除します。
build.gradleを以下に書き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
apply plugin: 'java' apply plugin: 'application' mainClassName = 'CalendarQuickstart' sourceCompatibility = 1.7 targetCompatibility = 1.7 version = '1.0' repositories { mavenCentral() } dependencies { compile 'com.google.api-client:google-api-client:1.23.0' compile 'com.google.oauth-client:google-oauth-client-jetty:1.23.0' compile 'com.google.apis:google-api-services-calendar:v3-rev305-1.23.0' } |
mainClassNameは実行するクラス名にしてください。
プロジェクトを右クリック→Gradle(STS)→「すべてリフレッシュ」します。
他の環境設定
さきほどダウンロードして名前変更したclient_secret.jsonを「src/main/resources」に保存します。
AIPOはPostgreSQLで動いていますのでPostgreSQLのJDBCドライバを用意します。
PostgreSQL JDBC Download
保存したjarファイルをプロジェクト直下にコピーしてビルドパスを通します。
同期用プログラムの開発
「CalendarQuickstart」という名前でクラスを作成します。
以下コード。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.security.CodeSource; import java.security.ProtectionDomain; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; import java.util.List; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.client.util.DateTime; import com.google.api.client.util.store.FileDataStoreFactory; import com.google.api.services.calendar.Calendar; import com.google.api.services.calendar.CalendarScopes; import com.google.api.services.calendar.model.Event; import com.google.api.services.calendar.model.EventDateTime; import com.google.api.services.calendar.model.Events; public class CalendarQuickstart { private static final String APPLICATION_NAME = "AIPO"; private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); private static final String CREDENTIALS_FOLDER = "credentials"; private static final List<String> SCOPES = Collections.singletonList(CalendarScopes.CALENDAR); private static final String CLIENT_SECRET_DIR = "client_secret.json"; private static String calendarId; private static String userId; private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException { InputStream in = CalendarQuickstart.class.getResourceAsStream(CLIENT_SECRET_DIR); GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES) .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(CREDENTIALS_FOLDER))) .setAccessType("offline").build(); return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user"); } public static void main(String... args) throws Exception { ProtectionDomain pd = CalendarQuickstart.class.getProtectionDomain(); CodeSource cs = pd.getCodeSource(); URL location = cs.getLocation(); URI uri = location.toURI(); Path path = Paths.get(uri); System.out.println(path.toString().replaceAll("CalendarQuickstart.jar", "") + "\\conf.txt"); // カレンダーIDとAIPOのユーザーIDをファイルから取得 File file = new File(path.toString().replaceAll("CalendarQuickstart.jar", "") + "\\conf.txt"); if (!file.exists()) { System.out.print("設定ファイルが存在しません"); return; } FileReader fileReader = new FileReader(file); BufferedReader bufferedReader = new BufferedReader(fileReader); String data; int cnt = 0; while ((data = bufferedReader.readLine()) != null) { switch (cnt) { case 0: calendarId = data; break; default: userId = data; break; } cnt++; } fileReader.close(); // Build a new authorized API client service. final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT)) .setApplicationName(APPLICATION_NAME).build(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); Date date = new Date(); date = sdf.parse(sdf.format(date)); DateTime now = new DateTime(date); // 本日以降の予定を取得 Events events = service.events() .list(calendarId) .setMaxResults(1000) .setTimeMin(now) .setOrderBy("startTime") .setSingleEvents(true) .execute(); List<Event> items = events.getItems(); for (Event event : items) { // 予定を削除 service.events().delete(calendarId, event.getId()).execute(); } System.out.println("end delete"); insert(); System.exit(0); } private static void insert() throws Exception { final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT)) .setApplicationName(APPLICATION_NAME).build(); Connection connection = DriverManager.getConnection("jdbc:postgresql://192.168.123.123:5432/org001", "aipo_postgres", ""); // AIPOからスケジュールを取得 PreparedStatement statement = connection .prepareStatement( "select A.* from eip_t_schedule A inner join eip_t_schedule_map B on A.schedule_id = B.schedule_id " + "where (B.user_id = ? and A.name <> 'dummy' and A.start_date >= current_date) " + "order by A.start_date", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); statement.setInt(1, Integer.parseInt(userId)); ResultSet resultSet = statement.executeQuery(); resultSet.last(); int count = resultSet.getRow(); resultSet.beforeFirst(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); int now = 0; while (resultSet.next()) { Event event = new Event().setSummary(resultSet.getString("name")).setLocation(resultSet.getString("place")) .setDescription(resultSet.getString("note")); DateTime startDateTime = new DateTime(sdf.parse(resultSet.getString("start_date"))); EventDateTime start = new EventDateTime().setDateTime(startDateTime).setTimeZone("Asia/Tokyo"); event.setStart(start); String endTime = resultSet.getString("end_date"); if ("00:00:00".equals(rightstring(endTime, 8))) { endTime = endTime.replaceAll("00:00:00", "23:59:59"); } DateTime endDateTime = new DateTime(sdf.parse(endTime)); EventDateTime end = new EventDateTime().setDateTime(endDateTime).setTimeZone("Asia/Tokyo"); event.setEnd(end); // Googleカレンダーへ予定の書き込み event = service.events().insert(calendarId, event).execute(); now++; System.out.println("insert " + now + "/" + count + " " + resultSet.getString("name")); } resultSet.close(); connection.close(); System.out.println("complete"); } public static String rightstring(String value, int length) { try { if (value.length() >= length) return value.substring(value.length() - length); else return value.substring(1); } catch (Exception e) { return value; } } } |
カレンダーIDとAIPOのユーザーIDはプログラムに書いてしまってもいいのですが、誰でも使えるように設定ファイルから読み込む形にしました。
「conf.txt」という名前で作成します。
中身はこんな感じ。
1 2 |
9ukdoqtdk1u6gr3a15hhfpefa4@group.calendar.google.com 10 |
1行目に一番はじめに作ったGoogleカレンダーのカレンダーID、2行目にAIPO側のユーザーIDを書いておきます。
テスト時は「プロジェクトルート\bin」に置いておきます。
なお、このプログラムはあくまで開始日が本日以降のスケジュールしか対象にしていません。
繰り返しの予定は普通開始日が本日より以前なので対象外となっています。
開始日が未来だとしても繰り返し設定はないですが・・・
ちょっとそこまで対応するのは面倒なのでやってません。
また、Googleカレンダー側のスケジュールIDをこちらで決められるので、そういったことを使えば消去して挿入ではなく、更新という形で同期が実現できそうです。
テスト
実行してみます。
ソースファイルを右クリックして実行。
初回起動時にブラウザが起動してリクエストの許可を促す画面が表示されますので許可します。
Googleカレンダーに予定が書き込まれたと思います。
リクエストを許可すると「credentials」というフォルダが作られ、その中に認証状態が保存されます。
このフォルダを削除すれば未許可状態に戻ります。
本番用jarファイルの作成
プロジェクトを右クリック→エクスポート→Java→実行可能JARファイルを選択。
起動構成に「CalendarQuickstart」を選択してjarを作成します。
作成されたjarと同階層に「conf.txt」を置いてjarを実行するだけです。
あとはこれをタスクスケジューラで動かすなりして定期実行します。
AIPOのテーブルについて(おまけ)
Windows版の場合、AIPOのPostgresのID、パスワードは「C:\aipo\dpl004\tomcat\webapps\aipo\WEB-INF\datasource\dbcp-org001.properties」に書いてありました。
IDはおそらく「aipo_postgres」固定だと思います。
デフォルトでは外部からの接続が許可されていないので、同期用プログラムを他のPCから実行する場合は外部からの接続を許可する必要があります。
PostgresSQLの外部からの接続許可
「C:\aipo\dpl004\postgresql\data\postgresql.conf」のlisten_addressesと書かれている部分を検索してコメントを外します。
1 |
listen_addresses = '*' |
「C:\aipo\dpl004\postgresql\data\pg_hba.conf」の一番下を以下に変えます。
1 2 3 4 5 6 7 |
# TYPE DATABASE USER CIDR-ADDRESS METHOD # IPv4 local connections: #host all all 127.0.0.1/32 trust host all all 0.0.0.0/0 trust # IPv6 local connections: host all all ::1/128 trust |
0.0.0.0/0でどこからでも接続可能です。
AIPOを再起動すれば完了です。
AIPOのユーザーID
AIPOのユーザーIDは管理画面からは見られません。
「turbine_user」というテーブルがユーザーマスタなのでこちらを見てください。
スポンサーサイト
アフィリエイトはエーハチネット
ドメイン取るならお名前.com