Runner in the High

技術のことをかくこころみ

WearOSアプリでGoogle Calendarの情報を取得したい備忘メモ

先日、新しく発表されたPixel Watch 2を買った。

それに伴いWearOS用のカレンダーアプリを自作しようとしているのだが、これが想像以上にむずかしそうなので備忘メモ。

ContentResolver

知っている人にとっては当然かもしれないが、AndroidにはContentResolverという仕組みがある。これは、ざっくりいうとあるアプリから異なるアプリやシステムに対してデータのCRUDを行うための抽象化されたI/Fを提供してくれるもの。

AndroidアプリからGoogle Calendarに対するアクセスもこのContentResolverによって抽象化されており、SQLクエリのような形をしたある程度柔軟なインターフェイスでデータの取得を宣言的に書くことができる。これは結構便利。

CalendarContract

今回、自分がやりたいことはGoogle Calendarのデータを取得することなので、該当するのはCalendarContractというContentProviderのアダプタ(?)だと思われたが、WearOSアプリからクエリを発行すること自体はできても、これで返ってくる値は常に0件の予定になる。

仮説ではあるが、おそらくCalendarContractはモバイルAndroidGoogle Calendarアプリに対するContentProviderだと考えられ、従って同じAndroidであってもWearOS上にはGoogle Calendarアプリは存在しないためデータを取得できず空データになっていると推測している。

WearableCalendarContract

というわけで、WearOSではCalendarContractの代わりにWearableCalendarContractを使う。

WearableなものとそうじゃないものでそれぞれCalendarContractが存在しているのはなんとなくleaky abstractionな感じもするが、そういうもんなのだろう。

公式ドキュメントによればWearableCalendarContractはCalendarContractのサブセットであるが、自動的に何らかのタイミングでCalendarContractのデータを同期したものが反映されるのが違いとのこと。同期のタイミングは不明。手動でこの同期処理をキックすることもできなさそう。

また、このWearableCalendarContractを用いて取得できるカレンダー情報には微妙に制限があるっぽく、自分の環境では現在時刻からざっくり12-24時間前後までの予定しか取得できていないようだった。軽く調べると、WearableCalendarContractには現在時刻から24時間のtime windowに当てはまる予定の情報しか含まれないという話もある。

stackoverflow.com

ContentResolverのI/Fを用いれば BEGIN > [特定のmillisec日時] のようなクエリを発行できるので、なんとなく時間範囲で予定情報を取得できそうな気もするが、これは動かなかった。

それ以外にも、WearableCalenadrContractはsortOrderパラメタもサポートしていない(エラーがでる)ので、I/FとしてContentResolverに対応しているだけで実際に触ってみるとできないことがそこそこあり、これはundocumentedなので実際にアプリを作ろうとしてみて初めて分かるという雰囲気がある。

なんとなく、WearableCalendarContractは本格的なWearOSアプリを作るために存在しているわけではなく、ウォッチフェイスで「今日の予定」みたいなのを出すためだけに存在しているContentProviderな予感がしている。

Data Layer API

つまり、限定期間的な予定以外も見れるまともなカレンダーアプリを作りたければ、CalendarContractやWearableCalendarContractは機能的に不十分である。となると最後のやり方はData Layer APIを用いるしかない。実際にstackoverflowでもそのやり方を提案している人は多かった。

詳しい部分は作ってみないとわからないが、WearOSアプリと連携するモバイルアプリ側でCalendarContract経由でカレンダー情報を取得し、Data Layer APIを用いてWearOSアプリ側に連携することでWearableCalendarContractの制限を回避する、という話だと思われる。

推測ではあるが、WearOSアプリにあるカレンダーアプリとしてそこそこ有名なPro Wear Calendarもこのやり方を採用していそう。というのもPro Wear CalendarはWearOSに対応するモバイルアプリも併せて提供しており、モバイルアプリ側にWearOSアプリへ予定情報を同期する機能がある。おそらく、内部的にはData Layer APIを用いてWearOSにデータを同期しているのだろう。

結論

WearOSで動くカレンダーアプリを作りたいだけなのに、だいぶ面倒な気がする。他にもっといいやり方があるのか?

しかし、アプリストアをみるとWearOS用のカレンダーアプリはそんなにバリエーションがないので、やっぱりそういうことなのかなという気もする。