Pushで、アプリの起動チェックをしよう！

## アプリのテストってどうしてますか？
サーバーと違ってどうやって監視をしようなどの課題があると思います。
いろいろ方法はあると思いますが、実際にアプリを起動してチェックが一番安心と考えました。
※ サーバーから受け取ったデータが想定と違っており、エラーして落ちていた など起動しないとわからないもの

## Pushでアプリ起動チェック
URLスキームの機能とPushを使って定期起動チェックを実現しようと考えました。
定期的にPushを送り続けて、そのPushから該当のアプリを起動して、起動をちゃんとするかをテストするというのものです。流れは下記の感じです。

１、起動チェッカーにPushを送り、設定したページにブラウザ遷移させる
２、ブラウザ遷移した後に、Javascriptなどが動作し、起動したいテストアプリのURLスキームを生成
３、テストしたいアプリが起動
４、アプリがURLスキームを読み取り、どこか遷移させたいページに自動遷移

こうすると、
URLスキームを動的に生成するページで、起動するアプリを変えたり、URLスキームのクエリパラメーターに値を後から付与できたり、と後々便利です。
URLスキーム インジェクションと名付けました！

作り方はこんな感じ
１、起動チェッカーアプリを作成
２、テストしたいアプリにURLスキームで起動する設定を追加
３、URLスキームを動的に生成するページを作成
これだけ！

## 起動チェッカーアプリの準備
今回は、Push通知の部分にParseのPush機能を使いました。
Parseについては、Qiitaでもググってもたくさん情報があるのでそのあたりの説明は、省きます。
まずは、Pushを受け取れるアプリを作成します。

参考程度ですが、使用したコードを以下に記します。
Push受け取り時の処理です。

ParseのPushを受け取るParsePushBroadcastReceiverクラスを継承したCustomReceiverクラスを作成しました。
内容は、簡単で、Parseから送られてきたJSONデータにあるurlというキーの文字列を取り出し、そのページにブラウザで遷移させるIntentを投げます。

```java
public class CustomReceiver extends ParsePushBroadcastReceiver {

    @Override
    protected void onPushReceive(Context context, Intent intent) {
        JSONObject pushData = null;
        try {
            pushData = new JSONObject(intent.getStringExtra(KEY_PUSH_DATA));
            Log.d("pushData", pushData.toString());
            String url = pushData.getString("url");
            Uri uri = Uri.parse(url);
            Intent i = new Intent(Intent.ACTION_VIEW,uri);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(i);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

```

ParseのPushからurlというキーのデータを送る場合、以下のように設定しました。

Parseでやっているなら、変えるのは、Write your message のところだけ
この場合、ブラウザ起動し、Yahooのページを表示します。
![スクリーンショット 2015-12-25 0.52.24.png](https://qiita-image-store.s3.amazonaws.com/0/30138/50c8acb6-5b1b-9bf7-982b-0ff84a6d59de.png)

Pushを送り、アプリが立ち上がり、その後ブラウザが立ち上がったら、アプリ起動チェッカーの準備は終わりです。

## URLスキーム生成ページの準備
今回は、S3上に静的なhtmlを置いてURLスキーム生成ページを用意しました。
もちろん、URLスキームを自動で生成するなら、すでにあるアプリケーションに組み込むでもいいと思います。
ここをいろいろと工夫すると、起動チェックの幅がかなり広がると思います。（アプリ側の実装もしなくてはいけませんが）

今回試したHTMLを貼ります。
これはJavascriptにより、URLスキームを生成します。今回のは例なので決め打ちしてます。

```html
<!DOCTYPE html>
<html>
  <head>
    <title>Push Test</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script>
      $(function(){

        var ua = navigator.userAgent.toLowerCase();
        var isAndroid = /android/.test(ua);
        var isChrome = /chrome/.test(ua);

        var package_name = "logiclogic.jp.myapplication";
        var event_id = "1";

        if (isAndroid) {
          if (isChrome) {
            window.location.href = 'intent://event/' + event_id + '#Intent;scheme=myapp;package=' + package_name + ';end';
            } else {
            var iframe = document.createElement('iframe');
            iframe.className = 'is-hidden';
            iframe.onload= function() {
              iframe.parentNode.removeChild(iframe);
              window.location.href = "※アプリが入ってなかった時に遷移するページのURL";
            };
            iframe.src = 'myapp://event/' + event_id;
            document.body.appendChild(iframe);
          }
        }
      });
    </script>
  </head>
  <body>
  </body>
</html>
```
今回は、起動したいアプリを
Package名：logiclogic.jp.myapplication
起動したいアプリに登録するScheme：myapp
起動したいアプリに登録するHost：event
と想定して決め打ちしてあります。

## テストしたいアプリにURLスキームの設定
テストしたいアプリのAndroidManifest.xmlに以下を追加します。


```xml
<activity
    android:name="logiclogic.jp.activity.MainActivity"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    <intent-filter>
      <action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    <intent-filter>
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
        <data
          android:host="event"
          android:scheme="myapp" />
   </intent-filter>
</activity>
```


## 実際にアプリ起動チェック！
HTMLページのURLをPushで送ってブラウザ起動させてアプリが立ち上がることを確認しましょう。
これで完了です。
今回、S3上にhtmlを置いてやってみましたが、すぐにURLが発行されて許可を与えればアクセスできるようになるのでオススメです。


## あとは工夫次第
APIを叩く、メールアラートを飛ばす、Analyticsなどにデータを蓄積するなどいろいろあると思います。
・いつまで、起動できてるログが来ていた？
・じゃあエラーした時間のサーバー側のデータは？
・バージョン情報は？
・Pushを定期的に送る
・URLスキームを細かく定義して、アプリ側で色なページに遷移するようにする
などいろいろなことができますね。
Parseを使った場合、Analyticsの機能なんかもあるので、それを使うのもありかもですね。
今回僕は、HipchatからHubotを使い、APIを叩いてPushを送って、チャットで起動テストができるようなChatOpsに挑戦中です。