(書いた日: 2015/10/04)
まんまWebViewのアプリをつくってるんだけど、せっかく形だけでもネイティブにするんだからしたいじゃないですか、プッシュ通知。
ゴール
- Androidアプリで、デバイストークンを取得して、Logに出す
まずまとめ
公式: Set up a GCM Client App on Android | Cloud Messaging | Google Developers
親切: Google Cloud Messaging | CodePath Android Cliffnotes
- Google Developers Consoleでプロジェクトを新規作成(割愛)
- 1のプロジェクトに紐付いた、google-services.jsonというファイルを生成
- 2をAndroidプロジェクトに配置し、参照するようにbuild.gradleを編集する
- manifest.xmlを編集してpermissionsなどを追加、必要なSDKをインストール
- コード書く
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
を開いて、軒並みインストールしちゃう。
5: コード書く
書くべきコードの概要
- GoogleCloudMessagingクラスのインスタンスを取得する
- AsyncTaskクラスを使って、backgroundでGCM.registerメソッドを呼ぶ
- 今回はとりあえず最初のAcitvityのonCreateに書いちゃう
注意点
- GCM.registerはメインスレッドで呼んではいけないので、AsyncTaskクラスを使う
- 内部クラス(この場合AsyncTaskクラス)の内部で参照される変数は、finalにしとく
- (ほんとうは、GCM.registerはdeprecatedだけどAPIたたくのだるいので使う)
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); }
やってみた結果
いけてるっぽい
しっぱい例
しっぱい:
のログが出た例
MAIN_THREAD
- うえに書いたとおり、メインスレッドでregister呼んじゃだめ
SERVICE_NOT_AVAILABLE
- 端末がオフラインだったときに出た。WiFiつなぎ直したらなおった
TODO
- あとはこのデバイストークンを自分のサーバに放り投げて保存、gcmの通知APIをapi_keyとともにサーバから叩けばよい?
- GCM.registerはdeprecatedらしいんだけど、APIをつかったregisterいまいちよくわからないぞい
雑感
いろんなところに散らばってるドキュメントが、だいたいぜんぶ込み込みで書いてあるので、必要最低限の単位のdiffが何か判明するのに時間がかかったり、必要無いところでコケたりした。まあ、慣れ。がんばりたい。
DRY