webscript.ioからGoogle Cloud Messageを投げる

# はじめに
webscript.ioからGoogle Cloud MessagingでAndroidアプリケーションにメッセージを送信するという例を実装します。webscript.ioについてご存知ない方は、合わせて以下の記事もご覧下さい。

http://qiita.com/yokobonbon/items/c69f6bf4cff6df644d56

# プロジェクトの作成
Google Developers Consoleでプロジェクトを作成します。その後、"Google Cloud Messaging For Android"をEnableにします。

<img width="856" alt="スクリーンショット 2016-01-22 23.48.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/9066dcba-0e0d-d335-983e-b5f709d7188b.png">

API Keyを作成します。今回は、webscript.ioからメッセージを投げるのでWeb Serverを選択します。

<img width="395" alt="スクリーンショット 2016-01-22 23.54.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/f1f65814-bfa8-b16f-9cff-b46c90c1847f.png">

<img width="472" alt="スクリーンショット 2016-01-22 23.57.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/5c52e966-79d5-cb03-f78c-d56bd69a8445.png">

# Android Applicationを作成
まず普通にAndroidStudioでプロジェクトを作成します。その後に以下の修正をします。

まず、プロジェクトフォルダ直下のbuild.gradleに以下を追加します。

```java
    dependencies {
        classpath 'com.android.tools.build:gradle:1.0.0'
+        classpath 'com.google.gms:google-services:1.4.0-beta3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
```

次にapp以下のbuild.gradleに以下を追加します

```java
apply plugin: 'com.android.application'
+ apply plugin: 'com.google.gms.google-services'

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
+    compile 'com.google.android.gms:play-services:8.1.0'
}
```

必要なライブラリがダウンロードされてビルドが通れば成功です。

# google-service.jsonの作成
公式サイト(https://developers.google.com/cloud-messaging/android/client) の以下のボタンをクリックしてgoogle-service.jsonを作成することができます。

<img width="808" alt="スクリーンショット 2016-01-24 16.18.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/c3e593a6-38a4-ee13-74e1-871a578af87d.png">

<img width="498" alt="スクリーンショット 2016-01-24 16.22.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/4bffdd67-98f0-70e7-1df8-d2e27f44764e.png">

Choose and configure servicesのページで有効にするとサーバー側でメッセージを送信するためのAPI KeyやSender IDなどの情報と共に、下の方にgoogle-service.jsonを作成するボタンがあり、そこからgoogle-service.jsonがダウンロードできます。

<img width="556" alt="スクリーンショット 2016-01-24 16.33.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/b93583a0-97dc-b32a-871e-75b01cac73a3.png">

ダウンロードされたgoog-service.jsonは作成したアプリケーションのプロジェクトのappディレクトリ以下にコピーします

```bash
$mv ~/Downloads/google-services.json <YOUR_APP_DIR>/app/
```

# Android Applicationの編集
次に実際のコードを記述していきます。今回のAndroid ApplicationはあくまでもシンプルにGCMの受信だけを行います。よってGCMを受信するBroadcastReceiverを以下のように作成します。

```java
public class GcmReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        if (bundle != null) {
            android.util.Log.d("GCMSample", "onReceive() : " + bundle.getString("message"));
        }
    }
}
```
次にこのAndroid ApplicationのRegistrationIDを取得する部分を作成します。GCMでメッセージを送る場合、送り先の住所にあたるRegistrationIDを指定する必要があります。アプリケーションのRegistrationIDは以下のように取得が可能です。注意すべき点はAndroidのUIスレッドではregister()メソッドが呼び出せないのでAsyncTaskなどを利用する必要があります。

```java
public class GcmRegister extends AsyncTask<Void, Void, String> {
    private static final String SENDER_ID = "<YOUR SENDER ID>";
    public interface OnRegistrationIdReceiver {
        void onReceived(String registrationId);
    }

    private final Context mContext;

    private final OnRegistrationIdReceiver mReceiver;

    public GcmRegister(@NonNull Context context, @NonNull OnRegistrationIdReceiver receiver) {
        mContext = context;
        mReceiver = receiver;
    }

    @Override
    protected String doInBackground(Void... params) {
        String msg = "";
        try {
            GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(mContext);
            msg = gcm.register(SENDER_ID);
        } catch (IOException ex) {
            msg = "Error :" + ex.getMessage();
        }
        return msg;
    }

    @Override
    protected void onPostExecute(String msg) {
        mReceiver.onReceived(msg);
    }
}
```
このクラスをActivityのonCreate()などで適当に呼んで頂ければ Registration IDが取得されます。Registration IDは基本的に同じ端末で、同じアプリケーションであれば変更されることはありません。

```java
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        GcmRegister register = new GcmRegister(getApplicationContext(), this);
        register.execute(null, null, null);
    }
```

最後にAndroidManifest.xmlにPermissionを追加します

```xml
    <uses-permission android:name="android.permission.INTERNET" />

    <permission android:name="jp.gp.java_conf.ulexite.gcmsample.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="jp.gp.java_conf.ulexite.gcmsample.C2D_MESSAGE" />

    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
```

```xml
        <receiver
            android:name=".GcmReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="jp.gp.java_conf.ulexite.gcmsample" />
            </intent-filter>
        </receiver>
```

# webscript.ioからメッセージを投げる
これでAndroid App側で受信する準備や、Google Cloud Messagingの準備は整いました。後は、webscript.ioからメッセージを投げるだけです。

GCMの送信は以下のように行います

```http
POST https://android.googleapis.com/gcm/send
Authentication: key=<YOUR API KEY>
Content-Type: application/json

{
    "registration_ids":["<REGISTRATION ID>"],
    "data":{
        "message":"Message from webscript.io"
    }
}
```
上記のメッセージを送るwebscript.ioのスクリプトは以下のようになります。

```js
local respont = http.request {
	  url = 'https://android.googleapis.com/gcm/send',
	  method = 'POST',
	  headers = {
		  ['Authorization'] = 'key=<YOUR API KEY>',
		  ['Content-Type'] = 'application/json'
		},
	  data = '{ "registration_ids":["<REGISTRATIOn ID>"], "data":{"message":"Message from webscript.io"}}'
}
```

これで無事、webscript.ioからAndroid Applicationにメッセージを送ることができました。