Awareness API - Google I/O 2016

# Awareness API

Google I/O 2016 では Firebase や Instant Apps などが大いに注目されているが、個人的には Awareness API が凄く魅力的だった。

* 参考
  * [Google Awareness API  |  Google Developers](https://developers.google.com/awareness/)
  * [Google、Awareness APIをリリース―Androidアプリがユーザー環境に反応するようになる | TechCrunch Japan](http://jp.techcrunch.com/2016/05/20/20160519android-apps-can-now-react-to-your-environment/)
  * [Google's Awareness API can turn every Android app into a smart assistant | The Verge](http://www.theverge.com/2016/5/19/11712608/android-awareness-api-google-io-2016)
  * [Y.A.M の 雑記帳: Introducing the Awareness API, an easy way to make your apps context aware - Google I/O 2016](http://y-anz-m.blogspot.jp/2016/05/introducing-awareness-api-easy-way-to.html)
  * [Introducing the Awareness API, an easy way to make your apps context aware - Google I/O 2016 - YouTube](https://www.youtube.com/watch?v=37ia7S4Lsv4)
* early access
  * [Awareness API Preview](https://docs.google.com/forms/d/1evLhLIgdDDuC-7J8OXPc6paEVlSKJV1WmkrUBfieOE0/viewform)

## Awareness API の概要

![top.png](https://qiita-image-store.s3.amazonaws.com/0/35834/fb12499e-3a29-1b31-cf39-e6c8c9dbadcd.png)

Awareness API は、 `Super easy make to your application.` な API とのこと。

<img width="853" alt="context_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/35834/86b226da-2d1f-8018-9ffd-cce56623810e.png">


Awareness API では、７種のコンテキストを取得することが可能。

|Context|Example|
|:--|:--|
|Location|Latitude and longitude|
|Place|Place, including place type|
|Beacons|Nearby beacons (including namespace, type, and content)|
|Time|Current local time|
|Activity|Detected user activity (walking, running, biking)|
|Headphones|Are headphones plugged in?|
|Weather|Current weather conditions|

## Awareness API の用途

上記の情報を取得できることから、ユーザーを取り巻く環境に反応してアプリの挙動を変えるときに有効と思われる。

例えば、

* くるまでドライブ（Activity）してて、
* 特定のお店の近く（Location/Place）を走っていたとき、
* そのお店が営業中（Time）だったら、
* リマインドを促す。

みたいな。

## Awareness API の魅力

### インターフェースがシンプル

上記の挙動を実装する場合、旧来だと、主に次のような API を駆使して実現していた。

<img width="853" alt="context_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/35834/92c5e7ed-cfac-381a-403f-352cdf55ba0f.png">


それぞれの API を呼び出す実装を、更に組み合わせてごにょごにょする... 実装コストとしてはかなり高め。

それを解消するのが Awareness API 。

Awareness API は直感的なインターフェースの API なので、実装コストは旧来より格段に下がってる。

```java
// 「ドライブ開始」の条件設定...
AwarenessFence startDriving = DetectedActivityFence.starting(
        DetectedActivityFence.IN_VEHICLE);

// 「ドライブ中」の条件設定...
AwarenessFence duringDriving = DetectedActivityFence.during(
        DetectedActivityFence.IN_VEHICLE);

// 「特定のお店の近く」の条件設定...
AwarenessFence areaAroundStore = LocationFence.in(
        STORE_LATITUDE, STORE_LONGITUDE,
        1000 /* radius in meters */, 0L /* dwell time */);

// 「お店の営業時刻」の条件設定...
AwarenessFence openHours = TimeFence.inDailyInterval(TimeZone.getDefault(),
        10 * HOURS_IN_MILLIS, 18 + HOURS_IN_MILLIS);

// 「ドライブ中」「お店の近く」「お店の営業時間」の複数条件をまとめて...
AwarenessFence drivingNearStore = AwarenessFence.and(
        areaAroundStore,
        duringDriving,
        openHours);

// 更新リクエストのビルダークラスをインスタンス化
// ・「ドライブ開始したとき」
// ・「営業時間内のお店の近くをドライブしてるとき」の条件を設定...
FenceUpdateRequest fenceUpdateRequest = new FenceUpdateRequest.Builder()
        .addFence("startDriving", startDriving, pendingIntent)
        .addFence("drivingNearStore", drivingNearStore, pendingIntent)
        .build();

// 更新リクエストを投げる
Awareness.FenceApi.updateFences(googleApiClient, fenceUpdateRequest);
```

リクエストしたので、コールバック処理を実装。

```java
void onReceive(Context context, Intent intent) {
    FenceState fenceState = FenceState.extract(intent);

    if (fenceState.getFenceKey().equals("startDriving")) {
        if (fenceState.getCurrentState() == FenceState.TRUE) {
          // ドライブ開始したので、マップを表示する
        }
    } else if (fenceState.getFenceKey().equals("drivingNearStore")) {
        if (fenceState.getCurrentState() == FenceState.TRUE) {
          // 営業中のお店の近くを走ってるので、そのお店に紐づく予定をリマインド
        }
    }
}
```

見たまんま、凄くシンプルで直感的なインターフェース。

---

Awareness API からコンテキストを取得する方法は２つ。

#### Fence API

![api_fence.png](https://qiita-image-store.s3.amazonaws.com/0/35834/c6967a38-a214-51d9-ca67-64e9e095dadc.png)


上記に示した実装例が **Fence API** で、登録した条件下に合致したらコールバックされる。

#### Snapshot API

![api_snapshot.png](https://qiita-image-store.s3.amazonaws.com/0/35834/087d9d2c-641e-01ab-3063-d2b8aa0d87ea.png)


現在のユーザーのコンテキストを取得する。

```
PlacesResult placesResult = Awareness.SnapshotApi.getPlaces(googleApiClient).await();
WeatherResult weatherResult = Awareness.SnapshotApi.getWeather(googleApiClient).await();
```

### バッテリー/メモリ使用を最適化

Awareness API のほうでバッテリー/メモリ容量を最適にしてくれるので、API 使用側はあまり意識せずに済む。

> Smart battery savings
>
> Power consumption and memory usage are automatically optimized to maximize battery life and memory capacity on your users' devices.

## Awareness API の効果

これだけシンプルなインターフェースであれば、複雑な条件のユーザー環境内にアプリのコンテンツを訴求するための実装や評価結果による改善など、PDCA の足かせにならずに済みそう。（複雑な API は実装/テストのし辛さが目立つので）

また、バッテリーやメモリの面倒も見てくれるとのことなので、低スペック端末や古い OS version をサポートしているアプリなどでも導入敷居は低いと思った。

---

以上です。補足・修正あればご指摘ください。