読者です 読者をやめる 読者になる 読者になる

DRYな備忘録

Don't Repeat Yourself.

【Android】GCMでプッシュ通知(クライアント編)

(書いた日: 2015/10/04)

まんまWebViewのアプリをつくってるんだけど、せっかく形だけでもネイティブにするんだからしたいじゃないですか、プッシュ通知。

ゴール

  • Androidアプリで、デバイストークンを取得して、Logに出す

まずまとめ

公式: Set up a GCM Client App on Android  |  Cloud Messaging  |  Google Developers
親切: Google Cloud Messaging | CodePath Android Cliffnotes

  1. Google Developers Consoleでプロジェクトを新規作成(割愛)
  2. 1のプロジェクトに紐付いた、google-services.jsonというファイルを生成
  3. 2をAndroidプロジェクトに配置し、参照するようにbuild.gradleを編集する
  4. manifest.xmlを編集してpermissionsなどを追加、必要なSDKをインストール
  5. コード書く

2: google-services.jsonというファイルをつくる

Set up a GCM Client App on Android  |  Cloud Messaging  |  Google Developers このセクションの「GET A CONFIGURATION FILE」というボタンをポチると、プロジェクトに紐付いたgoogle-services.jsonというファイルがもらえる。以上

3:build.gradleの編集

Set up a GCM Client App on Android  |  Cloud Messaging  |  Google Developers このセクションの通り。

build.gradeには「トップレベルのbuild.gradle」と「appレベルのbuild.gradle」という2種類があるので、とても迷った。AndroidStudioじゃなく、ふつうにターミナルからtreeとか見ると「./build.gradle」と「./app/build.gradle」があるので一目瞭然なんだけど。

./build.gradle (AndroidStudioでは (Project: プロジェクト名) という表現がされてるほう)に以下を追加

         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
+        classpath 'com.google.gms:google-services:1.4.0-beta3'
     }

(なんか「ここに書くな」的なコメントアウトがあるけど、とりあえず無視で)

一方、 ./app/build.gradle (AndroidStudioでは (Module: app) という表現がされてるほう)に以下を追加

 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"
 }

4: manifest.xmlを編集し、必要なSDKをインストール

ほぼ、Set up a GCM Client App on Android  |  Cloud Messaging  |  Google Developersこのセクションのとおり。今回は、ローカルでデバイストークンを取得してログ煮出してみるだけなので、GCMRecieverとかListenerServiceとかはあえて書かない。

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.otiai10.chantroid" >

+    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/>
+
+    <uses-permission android:name="android.permission.INTERNET" />

     <application
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
         android:theme="@android:style/Theme.NoTitleBar" >

         <activity
             android:name=".MainEntranceActivity"
             android:label="@string/app_name" >

Cmd + Rでビルドしてみて、インストールしなきゃいけないSDKを言われるので、インストールしましょう。必要があれば、AndroidStudioのSDK Managerを開いて、軒並みインストールしちゃう。

f:id:otiai10:20151004181128p:plain

5: コード書く

書くべきコードの概要

  1. GoogleCloudMessagingクラスのインスタンスを取得する
  2. AsyncTaskクラスを使って、backgroundでGCM.registerメソッドを呼ぶ
  3. 今回はとりあえず最初のAcitvityのonCreateに書いちゃう

注意点

    public void onClick(View v) {

        final GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(getApplicationContext());
        // これは単なるプロジェクトID
        // http://stackoverflow.com/questions/11294602/android-gcm-sender-id
        final String SENDER_ID = "72171162121";

        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... params) {
                try {
                    String regid = gcm.register(SENDER_ID);
                    return "とれたやつ:" + regid;
                } catch (java.io.IOException err) {
                    return "しっぱい:" + err.toString();
                }
            }
            @Override
            protected void onPostExecute(String msg) {
                Log.d("onPostExecute", msg);
            }
        }.execute(null, null, null);
    }

やってみた結果

いけてるっぽい

f:id:otiai10:20151004182422p:plain

しっぱい例

しっぱい: のログが出た例

  • MAIN_THREAD
    • うえに書いたとおり、メインスレッドでregister呼んじゃだめ
  • SERVICE_NOT_AVAILABLE
    • 端末がオフラインだったときに出た。WiFiつなぎ直したらなおった

TODO

  • あとはこのデバイストークンを自分のサーバに放り投げて保存、gcmの通知APIapi_keyとともにサーバから叩けばよい?
  • GCM.registerはdeprecatedらしいんだけど、APIをつかったregisterいまいちよくわからないぞい

雑感

いろんなところに散らばってるドキュメントが、だいたいぜんぶ込み込みで書いてあるので、必要最低限の単位のdiffが何か判明するのに時間がかかったり、必要無いところでコケたりした。まあ、慣れ。がんばりたい。

DRY