CordovaでFirebase Cloud Messaging(FCM)を使ってプッシュ通知(Android)

cordovaでAndroidのプッシュ通知をします。
GCMを使ってプッシュ通知する方法が、Firebaseを使う仕様に変更されています。FirebaseのFirebase Cloud Messaging(FCM)です。cordova-plugin-fcmというプラグインを利用します。

まずはFirebase Notificationを使ってテスト

まずは、Firebase Notificationを使ってテストします。Firebase Notificationは、FCMの一機能で、WEB上でメッセージなどを登録することで、簡単にpush通知ができるサービスです。アプリ側での受信設定などもせずにテストできます。やることは、FCMにアプリを登録し、AndroidにFirebaseを登録して、Firebase NotificationのWEBフォームからメッセージを送信するだけです。

Firebaseでアプリを登録

Firebaseのコンソールに行きます。

  • 新規プロジェクトを作成します。
  • AndroidアプリにFirebaseを追加をクリックして、追加します。
  • 追加した際にダウンロードされる、google-services.jsonをplatforms/android直下に配置します。

config.xmlの設定

プロジェクト作成時に記載したパッケージ名とconfig.xmlに記載されている、id名が同じか確認します。異なる場合は、config.xmlを正しいパッケージ名に修正します。

実機にAndroidアプリをインストール

$ cordova run android

Firebase Notificationのテスト

Firebaseのコンソールから、アプリを選択して、左側のサイドバーからNotificationsをクリックすると、Notificationの一覧画面が表示されます。右上の新しいメッセージをクリックして、メッセージを入力し、パッケージ名を選択して、送信します。これで画面に表示されれば成功です。Firebase Notificationは、デフォルトではアプリが表示されている状態だと何もしません。一旦アプリをバックグラウンドにしてから、メッセージを送信します。

FCMを使ってみます

FCMは、端末毎やトピック毎に送信を管理できます。まずは簡単なテストからやってみます。やることは、端末側で端末IDを取得し、その端末IDをコンソールに表示させます。その端末IDをメモって、FCMにPOSTでプッシュ通知させるようにしてみます。これで動けばとりあえずプッシュ通知成功です。

cordova-plugin-fcmプラグインをインストール

$ cordova plugin add cordova-plugin-fcm

cordova.jsを読み込む

www/index.html内で、cordova.jsを読み込むようにします。

<script type="text/javascript" src="cordova.js"></script>

端末IDの取得

端末IDの取得等のコードを書くときは、devicereadyイベントが取得後にしないといけません。deviceready前だと何もせずに終わってしまいます。cordova createで作成したプロジェクトはデフォルトで、index.jsというのがあります。ここにdevicereadyイベント発火後に動作する、onDeviceReady関数がありますので、この中に、端末取得コードを書いていきます。FCMPlugin.getToken()で取得できます。使い方の説明は、https://github.com/fechanique/cordova-plugin-fcmに色々書いてあります。

onDeviceReady() {
  /* global FCMPlugin */
  FCMPlugin.getToken(
    (token) => {
      console.log(token);
      alert(token);
    },
    (err) => {
      console.log(`error retrieving token: ${err}`);
    }
  );
}

上記を追加してcordova run android を実行すると、画面にトークンが表示されますし、ログにも出力されます。長いのでログからコピーしておきます。

Firebase APIにPOSTアクセスして、メッセージ送信

まず、Firebaseのコンソールに行き、プロジェクトを選択し、設定画面に行くと、クラウドメッセージングというタブがあるので、それをクリックします。すると、Server Keyがありますので、これをコピーします。

POSTアクセスする

ここに仕様が書いてあります。ここには、送信データのパラメータの説明が書いてあります。
chrome拡張のpostmanでやってみます。

URL: https://fcm.googleapis.com/fcm/send
method: POST

[header]

Content-Type: application/json
Authorization: key=(コピーしたServer Key)

[body]

{
  "to": "(コピーしたToken)",
  "priority": "high",
  "notification": {
    "title": "Test",
    "body": "テストです",
    "icon": "icon",
    "color": "#99cc22"
  }
}

これで端末にpush通知が来れば成功です。

プッシュ通知にdataを渡してアプリで使う

アプリに受け取りコードを書く

トークン取得時と同じ場所にコードを書きます。

onDeviceReady() {
  /* global FCMPlugin */
  FCMPlugin.onNotification(
    (data) => {
      if (data.wasTapped) {
        // Notification was received on device tray and tapped by the user.
        alert(JSON.stringify(data));
      } else {
        // Notification was received in foreground. Maybe the user needs to be notified.
        alert(JSON.stringify(data));
      }
    },
    (msg) => {
      console.log(`onNotification callback successfully registered: ${msg}`);
    },
    (err) => {
      console.log(`Error registering onNotification callback: ${err}`);
    }
  );
}

Firebase APIにPOSTアクセス

プッシュ通知にdataを渡すとアプリで使えます。postデータは下記のようにdataを使います。notificationに、click_actionを追加していますが、これがないと、Androidのバックグラウンド時に、通知をタップしたあとの処理が動きませんでした。

{
  "to": "(コピーしたToken)",
  "priority": "high",
  "notification": {
    "title": "Test",
    "body": "テストです",
    "icon": "icon",
    "color": "#99cc22",
    "click_action":"FCM_PLUGIN_ACTIVITY"
  },
  "data": {
    "title": "受け取りテスト",
    "score": 30
  }
}

これで、Androidの場合、フォアグラウンド時、バックグラウンド時ともに、プッシュ通知が表示され、アプリ側でdataの内容を操作できることが確認できました。

Android – Google Static Maps APIで地図画像を取得して表示する

最初にgoogle static map apiを有効にし、APIキーを取得・設定する必要がある。
https://console.developers.google.com

下記のように表示したい地図情報をパラメタに含めたURLを作成し、地図画像を取得する。
下記コードのmContextは、コンストラクタで、引数で取得したContextを入れたprivate変数。

//地図画像を表示させるviewを取得
ImageView mapView = (ImageView) view.findViewById(R.id.img_map);

//地図画像情報の作成
String lat = "35.039352";
String lng = "135.729265";

String url =
        "http://maps.google.com/maps/api/staticmap?center=" +
        lat + "," + lng + "&zoom=13&size=180x120&markers=" +
        lat + "%2C" + lng + "&sensor=false&key=" + mContext.getString(R.string.google_maps_key);

//地図画像の取得・表示
new DownloadImageTask(mapView).execute(url);

DownloadImageTaskクラスは、下記。
(参考:http://stackoverflow.com/questions/5776851/load-image-from-url
下記コードの、getCroppedBitmapは、Bitmap画像を角丸にする関数。

/**
 * URLから画像をダウンロードする
 */
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    ImageView bmImage;

    public DownloadImageTask(ImageView bmImage) {
        this.bmImage = bmImage;
    }

    protected Bitmap doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap mIcon11 = null;
        try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            mIcon11 = BitmapFactory.decodeStream(in);
            mIcon11 = getCroppedBitmap(mIcon11);
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return mIcon11;
    }

    protected void onPostExecute(Bitmap result) {
        bmImage.setImageBitmap(result);
    }
}

getCroppedBitmap関数は、下記。
(参考:ImageView を 簡単に 角丸 にする

/**
 * 画像を角丸にする
 * @param bitmap
 * @return
 */
public Bitmap getCroppedBitmap(Bitmap bitmap) {
    int width  = bitmap.getWidth();
    int height = bitmap.getHeight();

    final Rect rect   = new Rect(0, 0, width, height);
    final RectF rectf = new RectF(0, 0, width, height);

    Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(output);

    final Paint paint = new Paint();
    paint.setAntiAlias(true);

    canvas.drawRoundRect(rectf, width / 10, height / 10, paint);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    canvas.drawBitmap(bitmap, rect, rect, paint);
    return output;
}

PhoneGap

PhoneGapをインストールしましょう。
http://phonegap.com/install/

今のバージョンは3.4なのかな。node.jsをインストールしておく必要があるっぽい。これだけでインストールできた。便利だの。

sudo npm install -g phonegap

ドキュメントも日本語があるんだな。http://docs.phonegap.com/ja/3.4.0/index.html

あら、 Cordova は以前は PhoneGap と呼ばれていたためと書いてあるけど、今はCordovaと呼ぶんすかね。にしても、ドキュメントの翻訳めちゃくちゃだな笑

にしても、Monacaというのはgithubで公開されており、必ずしもクラウドモナカを使わなくてはならないわけではないということで、しかもモナカというのはフォンギャップを拡張してくれている物である為、フォンギャップをインストールして使うのではなく初心者は初心者らしくクラウドモナカを使い、クラウドモナカではどうしようもなかったりいっぱいつくるしクラウドモナカにお金払いたくないという段階で初めてローカルモナカを使えばいいのではないかという考えに本投稿を通じて思い至った次第である。

Androidの開発環境つくる

Androidの開発環境は全て奇麗に削除していたので復活させます。そのメモ。

PCはMacで、Eclipse使います。

参考:MacでAndroid開発環境を手早く整える

まず、Android SDKをダウンロードします。
おおAndroidSDKの中にEclipseが入ってるらしい。それを使うか。workspaceはホームディレクトリ直下のandroidにしてみた。

次にEclipseを開いて、Android Developer Toolsの導入をします。
なんかもう入ってるみたいだな。そりゃそうか。。むしろこのEclipseはADTと自分を名乗っているなあ。
文字コードをutf-8にした。文字コードは、ADT->環境設定->General->Editors->Text Editors->Spelingに設定箇所がある。
EclipseにAndroidSDKのパスを設定する必要があります。AndroidSDKのパスをmacにパスを通したら自動で設定されてた。あるいはそれをしなくてもAndroidSDKのEclipseを使うと自動設定されてるのかも。設定されていない場合は、ADT->環境設定->Android内のSDK Locationに設定をする。

あとは今度やる。