2014年9月16日火曜日

TitaniumアプリでPush Notification【Android版】

push-notification_android前回はiOSについて調査。今回はAndroid端末にプッシュ通知する方法を調査したときの覚書。

開発環境: Mac OS X 10.9.4, Titanium SDK 3.3.0.GA, Android 4.0.3
サーバー:CentOS 6.5

 

参考サイト

 

目次

  1. Google Cloud Messaging(GCM)を有効に
  2. GCMとの通信用モジュールを探す
  3. Titaniumモジュールをビルドする環境を整える
  4. Titaniumモジュールのビルド実行
  5. アプリからモジュールを利用
  6. サーバーからプッシュ通知テスト
  7. デバッグと検証してみた

 


1.Google Cloud Messaging(GCM)を有効に

iOSはApple Push Notification service(APNs)経由でプッシュ通知を送る。Androidの場合はGoogle Cloud Messaging(GCM)経由。

GCMのAPI Keyを取得

  1. Google API Consoleにアクセス
  2. プロジェクトを作成。
  3. プロジェクトの「Overview」を開くと左上に「Project Number」が表示されているのでこれをメモ。あとで「sender_id」としてアプリ側に記述する。
  4. APIs & auth → APIsから「Google Cloud Messaging for Android」を有効に
  5. APIs & auth → Credentialsから「Server Key」を作成。

 


2.GCMとの通信用モジュールを探す

iOSみたいにネイティブにサポートしてないので、公開されているモジュールを利用する。

「dist/com.activate.gcm-android-0.6.zip」をそのまま利用しても問題なかった。一応自分でカスタマイズできるようにビルドしてみた。

 

< 2014/12/15 Modified >
こちらの記事で紹介されている方がいろいろ修正されているみたい。

 


3.Titaniumモジュールをビルドする環境を整える

長くなったので別記事にした。

 


4.Titaniumモジュールのビルド実行

GitHubからcloneする
$ git clone https://github.com/liccowee/Google-Cloud-Messaging--Titanium-
$ cd Google-Cloud-Messaging--Titanium-/

環境変数を出力したいので、空のsampleモジュールを作る。
$ titanium create -p android -t module -d ./ -n sample --id com.sample

環境変数が記述されたbuild.propertiesをコピーする。
$ cp sample/android/build.properties ./

ちなみにbuild.propertiesはこんな感じだった。

titanium.platform=/Users/daiki/Library/Application Support/Titanium/mobilesdk/osx/3.3.0.GA/android
android.platform=/Applications/android-sdk-macosx/platforms/android-14
google.apis=/Applications/android-sdk-macosx/add-ons/addon-google_apis-google-14

 

manifestを編集
$ vi ./manifest

version: 0.6
minsdk: 3.3.0.GA

 

< 2015/04/24 Modified >
SDK 3.5.1.GAにしたらarchitecturesを加えないとビルドに失敗して「There is discrepancy between the architectures specified in manifest and compiled binary.」といわれた。

$ vi ./manifest

name: gcmjs
moduleid: net.iamyellow.gcmjs
guid:
platform: android
minsdk: 3.5.1.GA
architectures: armeabi armeabi-v7a x86

 

 

timodule.xmlを編集
$ vi ./timodule.xml

<uses-sdk android:minSdkVersion="10"/>

 

< 2015/04/24 Modified >
SDKをアップデートした場合はbuild.propertiesの値をチェック
$ vi ./build.properties

titanium.platform=/Users/daiki/Library/Application Support/Titanium/mobilesdk/osx/3.5.1.GA/android
android.platform=/Applications/android-sdk-macosx/platforms/android-21
google.apis=/Applications/android-sdk-macosx/add-ons/addon-google_apis-google-21

 

distディレクトリは空にしておく。
$ rm dist/*
$ ant clean

ビルド実行
$ ant

libディレクトリがないって怒られた。
$ mkdir lib

再ビルド
$ ant

distディレクトリに出力される。

 


5.アプリからモジュールを利用

Titaniumプロジェクトの直下に「com.activate.gcm-android-0.6.zip」を設置するだけで、次回ビルド時にインストールしてくれる。

自分で解凍しても同じ。
Titanium_Studio_Workspace/test_app/modules/android/com.activate.gcm

tiapp.xmlを編集。sender_idはGoogle API Consoleの「Project Number」

<modules>
    <module platform="android" version="0.6">com.activate.gcm</module>
</modules>
<property name="com.activate.gcm.sender_id" type="string">123427670900</property>
<property name="com.activate.gcm.component" type="string">com.hoge.app/org.appcelerator.titanium.TiActivity</property>

 

アプリ起動後に下記コードを実行して動作するか確認。

var gcm = require('com.activate.gcm');

gcm.registerC2dm({
    success: function(e) {
        console.log(e);
        alert('Registration ID:' + gcm.getRegistrationId());
    },
    error: function(e) {
        console.log(e);
    },
    callback: function(e) {
        alert('JS message event: ' + JSON.stringify(e.data));
        console.log(e);
    }
});

GCMにデバイスの登録が成功すると「success」プロパティに設定した関数が実行されて、registrationIdが返ってくる。

 


6.サーバーからプッシュ通知テスト

さっき取得したregistrationIdをターゲットにプッシュ通知をサーバーから送信してみる。

こちらを参考にしたPHPを設置。「$registration_id」にはデバイスのregistrationId。「$header」のkeyにはAPI Keyを記述する。

パラメーターの詳細は公式サイトを参考に。

<?php
$url = 'https://android.googleapis.com/gcm/send';

$registration_id = 'APAxxx';

$message = 'Hello, GCM!!';

$header = array(
  'Content-Type: application/json',
  'Authorization: key=xxx',
);
$post_list = array(
  'registration_ids' => array($registration_id),
  'collapse_key'     => 'demo',
  'data'             => array( "message" => $message )
);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_list));

$ret = curl_exec($ch);
 
var_dump($ret);
?>

これを実行するとアプリ側で「callback」に設定した関数が実行されるはず。

 


7.デバッグと検証してみた

ddmsを立ち上げてログ出力を監視してみる。「C2dmModule」「GCM」というTagで絞り込むと見やすい。

image

どんな仕組みで動いているかまだよく分かっていない。

 

< 2015/04/24 Modified >
アプリのti.xmlにandroid:debuggable="true"を追記するとddmsでそのアプリの出力だけに絞り込むことが出来るので便利。

またtimodule.xmlに
<property name="ti.android.debug" type="bool">true</property>
を追記しないとモジュール内の
org.appcelerator.kroll.common.TiConfig.LOGD
がtrueにならないので、デバッグログを出力しない。

 

 

その他検証して分かったことなど

  • アプリをタスクマネージャーからKILLした時はプッシュ通知を受け取れない。GCMBaseIntentServiceがプッシュ通知に反応しない。
    これはLINEも同じ。これを解決するにはMessengerのように常時稼働するサービスを作る必要がある。
    メモリが圧迫されてアクティビティが破棄されるのはAndroid端末の「開発者向けオプション」→「アクティビティを破棄」をチェックすると再現できる。
  • 画面をロックしている状態だとcom.activate.gcm.componentを正しく設定してないと動かない(たぶん)。下記コマンドで現在稼働中のActivityを表示できる。
    $ ./adb shell dumpsys activity | grep -i run
  • 再起動直後はうまく動いてくれない。ddmsで見るとサービスは動いてプッシュ通知を検知している。要調査。

 

< 2014/12/19 Modified >
アプリがバックグラウンドのときにうまく動かなかったのはgcm.jsとgcm_activity.jsをResourcesの直下に設置してなかったから。

Forkされている方が断然使いやすかった。

 

< Related Posts >

コメントを投稿
Related Posts Plugin for WordPress, Blogger...

Blog Archives