Google for Mobileで気になったこと

この記事は[リクルートライフスタイル Advent Calendar 2015 - Qiita](http://qiita.com/advent-calendar/2015/recruitlifestyle)の13日目です。
リクルートライフスタイルでギャザリーというキュレーションサイトの開発を担当しているnozomirです。
一週間前までは、Java9の話をしようと思いましたが、Java8のラムダ式のようなすごく分かりやすい変化がなかったので、別の話をしようかと思います。まあ、言語の強化ではなくシートベルトって言ってますもんね。
そんなわけで、今回はGoogle for Mobileに行ってきた話です。

## はじめに

先日、[Google for Mobile - Tokyo](https://events.withgoogle.com/google-for-mobile-tokyo/)に行ってきました。
基本的にはネイティブアプリの話が中心でしたが、GCPの話やプログレッシブウェブアプリの話など、ネイティブアプリ以外の話も色々と聞くことができました。
その中でも、印象に残った話を中心に、少し実装を混ぜつつお話をしたいと思います。

## Background sync

ウェブアプリを如何にしてネイティブアプリに近づけて、UXを向上させるのか、というセッションの中で紹介されていました。要はService Workerです。

言葉で説明するより、以下の動画を見ていただいたほうが早いかと思います。

[![Background sync Chrome デモ](http://img.youtube.com/vi/2ugAVXRkr9U/0.jpg)](https://www.youtube.com/watch?v=2ugAVXRkr9U)

[Background sync](https://www.chromestatus.com/feature/6170807885627392)

上記リンクのDocumentationからも参照できますが、他のService Workerと実装方法はほぼ同じです。

```service-worker.js
self.addEventListener('sync', function(event) {
  // 同期が完了した後に実行する処理
  event.waitUntil(sendEverythingInTheOutbox());
});
```

同期処理のコールバック関数に、同期が完了したら実行する処理を書けばいいだけですね。すごく楽です。
あとはページが読み込み終わったことを通知するなどすればいいですね。

ちなみにローカルで試す方法とかは[こちらの記事](http://qiita.com/tmtysk/items/f77e31d6e9380e1c94a2)に載っていますが、最新版のChrome Canaryを使用している場合、若干設定方法が異なりますので注意してください。
具体的には

デベロッパーツールを開き `Settings - Experiments` のメニューで **Shiftキーを6回押**　しても、`Service workers in Resources panel`は出てきません。
但し、`chrome://flags`で`#enable-devtools-experiments`を有効にしておけば、問題なくlocalhostでデバッグできますので、ご安心を！

## Accelerated Mobile Pages(AMP)

モバイルページの表示速度を早めよう、という取り組みです。
「定めた仕様にきっちり従って書けば早くなるよ」ということです。
ちなみに仕様は[ここ](https://github.com/ampproject/amphtml/tree/master/spec)

既存と違ってどれぐらい早くなるかを試そうかと思いましたが、結構労力がかかりそうなのでやめました。。。
新規に作る分には検討の価値がありそうです。

ちなみに2016年前半サービス公開開始とのことでした。

## Nearby Messages API

今年の8月に公開されたNearbyの一つですね。もう一つはNearby Connectionsです。

試しにちょっと使ってみました。

###1 Nearby Messages APIの有効化

事前にNearby MessagesをGoogle Developer Consoleから有効化します。
ここの手順は割愛します。

###2 Androidプロジェクトの準備

1. Google Play ServicesのNearbyを`bundle.gradle`に追加します。

```
compile 'com.google.android.gms:play-services-nearby:7.8.0'
```

2.AndroidManifestに設定を追加します。

`application`タグ内に`meta-data`を以下の形で追加します。

```
<meta-data
    android:name="com.google.android.nearby.messages.API_KEY"
    android:value="[各自のAPIキー]" />
```


###3 Nearby Messages APIの実装

1. Google API Clientの用意

APIに接続するためのクライアントを用意します。

```MainActivity.java
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this).addApi(Nearby.MESSAGES_API)
            .addConnectionCallbacks(callbacks)
            .addOnConnectionFailedListener(failedListener)
            .build();

```

クライアントからAPIに接続します。

```MainActivity.java
if (!googleApiClient.isConnected()) {
   googleApiClient.connect();
}
```

2.パーミッションの確認

Nearby Messages APIは実行時にユーザからの許可が必要となります。
そのため、接続の成功後、Nearby Messages APIのパーミッションを確認する必要があります。

Nearby APIへの接続コールバックの中で、パーミッションの確認をしています。

```MainActivity.java
class NearbyTestConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks {

    @Override
    public void onConnected(Bundle bundle) {
        Log.d(TAG, "onConnected");
        // パーミッションの確認
        Nearby.Messages.getPermissionStatus(googleApiClient).setResultCallback();
    }

    @Override
    public void onConnectionSuspended(int i) {

    }
}
    
class NearbyResultCallback implements ResultCallback<Status> {

    String method;
    Runnable runOnSuccess;
    public NearbyResultCallback(String method, Runnable runOnSuccess) {
        this.method = method;
        this.runOnSuccess = runOnSuccess;
    }

    @Override
    public void onResult(Status status) {
        if (status.isSuccess()) {
            // 通信結果が成功の時の処理
            Log.d(TAG, "$method succeeded");
            MainActivity.this.runOnUiThread(runOnSuccess);
        } else {
            // ユーザーに許可を求めることができるか
            if (status.hasResolution()) {
                if (!resolvingError) {
                    try {
                        // ユーザに許可を求める
                        status.startResolutionForResult(MainActivity.this, REQUEST_RESOLVE_ERROR);
                        resolvingError = true;
                    } catch (IntentSender.SendIntentException e) {
                        Toast.makeText(MainActivity.this, "faile for exception" + e, Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Log.d(TAG, "failed for this status: $status .")
                }
            } else {
                Log.d(TAG, "failed status: $status resolving error: $resolvingError")
            }
        }
    }
}
```


ユーザが許可したかどうかは`onActivityResult`で受け取ります。

```MainActivity.java
@Override
public void onActivityResult(int request, int result, Intent intent) {
    super.onActivityResult(request, result, intent);
    if (request == REQUEST_RESOLVE_ERROR) {
        resolvingError = false;
        if (result == Activity.RESULT_OK) {
            Log.d(TAG, "Start subscribe");
            Nearby.Messages.subscribe(googleApiClient, messageListener);
        }
    } else {
        Log.d(TAG, "Failed to resolve error: $result");
    }
}
    
```

以上でNearby Messagesを使用する準備は整いました。
あとは、Nearby Messagesを使用したチャットなど、簡単なアプリであればすぐに作れるようになるかと思います。

## Google Container Engine

言わずと知れたGCPのコンテナサービスです。
Google Compute Engine上にKubernetesのクラスタを作成し、Dockerコンテナを配置可能にするものです。
こちらについては、セッション中にチュートリアルをしたり、利便性を力強くアピールするなど、GCPのセッションの中では最も力が入っていたのではないかと思います。

こちらも、簡単に使った結果を書こうと思いましたが、[既にたくさん記事がある](http://qiita.com/search?q=Google+Container+Engine&sort=rel)ので、ここでは割愛いたします。


## まとめ

個人的には「スマートフォン体験を一歩先へ - プログレッシブウェブアプリの作り方」の中で、Service Workerのゴリ押しや、AMPの紹介、そして今回は紹介しませんでしたが、Smart Lock for PasswordsやApp Indexingの話を聞いて、Web AppとNative Appの垣根をどんどんなくそうとしている動きが強く感じられました。

特にService WorkerはHTTPS通信のサイトであればすぐに実装できますしね。(AMPは既存サイトの移行が少し大変そうですが…)

そして、Nearby APIも今後のアプリのあり方を変えてくれそうな期待もあります。今回は紹介しませんでしたが、EddystoneなどのBeaconもあるので、広がりを見せそうな気もします。

今回紹介したサービスは、どれも最初のハードルは高くないので、興味あるけど触ってないという方は一度触ってみるといいと思います！

以上、初のQiita投稿でした！