簡単にリアルタイムアプリ作成MilkCocoa入門

[MKAK Advent Calendar 2016](http://www.adventar.org/calendars/1985) 4日目担当しますmoroku0519です．
何を書こうかいろいろ悩みましたが，私はMilkCocoaについて紹介します．

#MilkCocoaとは
[MilkCocoa](https://mlkcca.com/)は[Uhuru社](http://uhuru.co.jp/)から提供されているBaaSで，自前でサーバを用意することなく簡単にリアルタイムアプリを作ることができます．

#何が嬉しいの？
1.データの保存・更新・取得が簡単
完全に公式サイトの受け売りですが，データの保存までMilkCocoaがやってくれます．
例えばチャットアプリをMilkCocoaを使って作る時，デバイス間の通信をするだけでなく，そのデータのやり取りをDataStoreという仕組み上に保存してくれ，SDKを通じていつでも読み込むことができます．

2.マイコンなどからも利用出来る．
MilkCocoaのSDKは
-Arduino
-ESP8266
-mbed
と言ったマイコンの類からも利用することができます．
つまり，IoTにも応用することができます．

例えば，私は友人とチームを組み，ハードウェアコンテストGugenに次のデバイスを作成して応募しました．
https://gugen.jp/entry2016/2016-149

動作デモ
https://www.youtube.com/watch?v=Z_Z9AtcIMd0

これはタブレットのコマンドをMilkCocoaに投げて，それをWifiモジュールであるESP8266に流しています．そして，コマンドを受け取ったESP8266はシリアル通信でArduinoへデータを渡してロボット本体の制御をおこなっています．

![ヒカロ解説.png](https://qiita-image-store.s3.amazonaws.com/0/28622/83931071-a04d-2c98-c3cb-13ee83568071.png)

動画がちょっと見づらいですが，ほぼ遅延なく操作ができていることがわかります．
あ，ちなみに欲しいね!ボタン押してもらえると嬉しいです．

#MilkCocoaを使ってみる
試しに，ブラウザとAndroid間でやり取りをするチャットを実装してみます．
まずはMilkCocoaの登録から．

##ユーザ登録
[トップページ](https://mlkcca.com/)の無料登録から登録します．できたらログインします．

##ダッシュボード
ログインしたらダッシュボード画面が出きます．
早速，「新しいアプリを作る」ボタンを押してアプリを作成します．（無料プランだと6つまで）

![スクリーンショット 2016-12-04 16.43.17.png](https://qiita-image-store.s3.amazonaws.com/0/28622/99707100-bd58-30dc-68b5-6f3d8fcf8412.png)

データ数，コネクション数などの用語がありますが，それらのことはプランの説明に書いてあるのでそちらを御覧ください．
https://mlkcca.com/price.html

ここではデータストアについて説明します．

###データストア
![スクリーンショット 2016-12-04 16.50.07.png](https://qiita-image-store.s3.amazonaws.com/0/28622/a4945223-f93d-7080-b598-6335da4af084.png)

データストアはクライアント間のデータのやり取りを担ったり、データを保存したりする場所のことです．
保存されたデータはユニークなID, タイムスタンプ，クライアントから送信された値を持っています．
このデータを無償プランでは100,000まで保存することができます．
データストアはクライアント側で宣言し，使用します．

##ブラウザ側実装
test_appの概要を見ると，すでに書くべきコードが示してあります．

```html
<script src="https://cdn.mlkcca.com/v0.6.0/milkcocoa.js"></script>
```

```js
var milkcocoa = new MilkCocoa('your_app_id.mlkcca.com');
```

これらを踏まえて，次のような簡単なJavaScriptを書きます．

```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <script src="http://cdn.mlkcca.com/v0.6.0/milkcocoa.js"></script>
    <script type="text/javascript">
      var milkcocoa = new MilkCocoa('your_app_id.mlkcca.com');
      var ds = milkcocoa.dataStore('messages');
      function sendMessage() {
        var text_form = document.getElementById('message');
        var message = text_form.value;
        var data = {title : 'chat', content: message};
        ds.send(data);
        text_form.value = "";
      }
    </script>
  </head>
  <body>
    <div>
      <input type="text" id="message" />
      <input type="button" value="送信" onclick="sendMessage()"/>
    </div>
  </body>
</html>
```

ポイントは

```js
var milkcocoa = new MilkCocoa('your_app_id.mlkcca.com');
var ds = milkcocoa.dataStore('messages');
```

です．new MilkCocoa()でMilkCocoaとのやり取りを行うMilkCocoaオブジェクトを生成し，
dataStore('送るデータストア名')メソッドでデータを送るデータストアを指定します．
データストアがなければこの時作成されます．GUI画面で先に作成しなければいけないと言った必要性はありません．

```js
var data = {title : 'chat', content: message};
```
送るデータはJSON形式にして送ります．
そして，

``` js
ds.send(data);
```

sendメソッドを使ってMilkCocoaに送ります．
送るメソッドは2種類あり，
sendとpushがあります．
違いはというと，sendはデータストアに保存されませんが，pushは保存されます．
pushを使って送ったデータは先ほどのダッシュボードのデータストアの欄で確認することができます．

無料プランの場合，データの上限があるので保存の必要がなければsendメソッドを使うべきでしょう．

##Android側実装
[jarファイル](http://cdn.mlkcca.com/java/milkcocoa-dev.jar)が配布されているのでダウンロードします．

AndroidStudioにてプロジェクトを作成したら，以下のコードを書きます．（サンプルを少し）

```java:MainActivity.java
public class MainActivity extends Activity implements DataStoreEventListener{

    private static final String APP_ID = "your_app_id.mlkcca.com";
    private static final String DATASTORE = "messages";

    private MilkCocoa mMilkCocoa;
    private DataStore mMessagesDataStore;
    private Handler mHandler = new Handler();
    private ArrayAdapter<String> mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView = (ListView) findViewById(R.id.list_view);
        try {
            mMilkCocoa = new MilkCocoa(APP_ID);
            mMessagesDataStore = mMilkCocoa.dataStore(DATASTORE);
        } catch (MilkcocoaException e) {
            e.printStackTrace();
        }
        mAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1);
        listView.setAdapter(mAdapter);

        mMessagesDataStore.addDataStoreEventListener(this);
        mMessagesDataStore.on("send");
        mMessagesDataStore.on("push");


    }


    @Override
    public void onPushed(DataElement dataElement) {
        final DataElement pushed = dataElement;
        new Thread(new Runnable() {
            public void run() {
                mHandler.post(new Runnable() {
                    public void run() {
                        String content = pushed.getValue("content");
                        mAdapter.add(content);
                    }
                });
            }
        }).start();
    }

    @Override
    public void onSetted(DataElement dataElement) {

    }

    @Override
    public void onSended(DataElement dataElement) {
        final DataElement pushed = dataElement;
        new Thread(new Runnable() {
            public void run() {
                mHandler.post(new Runnable() {
                    public void run() {
                        String content = pushed.getValue("content");
                        mAdapter.add(content);
                    }
                });
            }
        }).start();

    }

    @Override
    public void onRemoved(DataElement dataElement) {

    }
}

```

DataStoreEventListnerを実装します．すると，4種類のメソッド
onSended()
onPushed()
onSetted()
onRemoved()
をオーバーライドします．

これらはデータストアが何かしらのイベントを受け取った時に呼び出されます．
OnSended()はsendイベントを，OnPushed()はpushイベントを，，，と言った具合です．

今回はブラウザがMIlkCocoaにsendしたらそのデータを受け取りたいため，onSended（）に処理を書きました．一応onPushed()もデータの保存以外挙動は同じなので同じ処理を入れておきました．

xml側は

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/activity_main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="hogehoge.milkcocoa_chat.MainActivity">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

```
と，簡単に書いておきました．

##動作画面

実際にチャットを行うと以下の画面のようになります．
チャットとは言っても，簡単にブラウザからAndroidにしか送っていませんが．

![chat.gif](https://qiita-image-store.s3.amazonaws.com/0/28622/ff71125a-9253-132d-0d64-9106646bdb79.gif)

簡単にチャットができてしまいました．
例えば何かのモックアップを作りたいとき，ハッカソンなどでぱぱっとチャットを実装したいときに有用です．

#おわりに
MilkCocoaを使うことでリアルタイムアプリを簡単に作ることができます．
今回はチャットアプリで例を示しましたが，データの送信の部分を人ではなく，センサーからの値にすればIoTに使うこともできます．
公式にもリファレンスがあるので，一回使ってみたらいかがでしょうか？

以上，MKAK Advent Calendar 2016 4日目担当moroku0519でした．