【はじめてのAndroidアプリ開発】プッシュ通知 今回作成するプッシュ通知機能搭載のアプリについて
今回作成するプッシュ機能搭載のアプリは、 Firebase にてプッシュ通知を操作。そして送った通知は、アプリ利用中の方、もしくはメモリー下にアプリがおかれているデバイスを対象に通知。
そして通知する内容は、簡単なテキスト・スタイルのものとしました。
Firebaseについて
https://firebase.google.com/
まず今回利用する Firebase について簡単にご紹介。 Firebase は、 Google 社が運営するアプリ用開発プラットフォーム。 Firebase を利用すると、以下のような機能を無料でアプリに実装できます。
データベース
統計(アナリティクス)
通知機能
ログイン機能
機械学習機能
予測機能
アプリのクラッシュ状況確認
A/Bテスト etc
こんなにたくさんの機能を無料で利用できるって、さすが Google って感じですね。
また Firebaseは、 Web(クラウド)上で操作しますので、 Androidでも iOS でも Unityでも ハイブリッド型アプリでも利用可能。もはやアプリ開発のインフラ的な存在ともいえますので、使い方を知っておくと様々な場面で役立つと思います。
Firebaseのプッシュ通知について
アプリを作成する時に、Firebase対応のプッシュ通知機能を組み込んでおくことで、ブラウザ画面からいつでもプッシュ通知を設定することが可能。プッシュ通知の設定科目としては以下のようなものがあります。
テキスト内容
ターゲットの指定(Topic や Channel)
通知の予約
開封状況などのリアクション確認
有効期限
通知音の有無
そして Firebase を使って発信した通知は、端末の状況によって通知が表示される場合と表示されない場合が存在。例えばアプリを起動していればプッシュ通知は表示されますが、アプリを立ち上げていなければブッシュ通知は表示されません。
このあたりのことは、バックグラウンドで常時稼働するようにアプリを設定すればいいのですが、アプリ開発の初期段階でバックグラウンド処理はちょっと難しい内容。 そしてまた 2019年 1月
からは、 FCM(Firebase Cloud Messaging)はバックグラウンド下に置かれているアプリに対しては通知をしないと宣言* 。
そうしたことから今回は Firebaseに慣れ、プッシュ通知を体験するということを目的に、一番簡単に設定できる「起動中のアプリに対してテキストのプッシュ通知を発信」していくことにしました。
プッシュ通知のエミュレーター環境
これから作成していく「プッシュ機能搭載のアプリ」をテストする環境は、実機をお勧めします。理由はエミュレーターのセットアップによっては、プッシュ通知が届かないためです。
通常新規でエミュレーターを起動すると Android のセットアップが起動し、アカウント情報なども入力する必要があります。しかし本当のスマホとは違うエミュレーターで、アカウント情報を入力されている方は少ないのではないでしょうか。セットアップができてない・・・・・ 、もしくは中途半端・・・・ な状況ですと、正しくアプリが開発されて正しく Firebase のプッシュ通知が設定されていても、その通知が端末に届くことはありません。
以上のことより、プッシュ通知のテストは実機を用いてお試しすることを勧めます。
プッシュ通知機能搭載のアプリを作る様子
VIDEO
今回ご紹介するプッシュ通知機能対応のアプリを制作している様子です。Google で「firebase android notification」と検索すると、いくつかのチュートリアルが表示。20種類ほどプッシュ通知のチュートリアルを確認しましたが、どれも作り方は違いました。また実際に紹介されているコードを入力してもうまくいかないケースもありますし、 Firebaseの管理画面が古かったり、 Android Studio のバージョンが低かったりして、テストしていても常に不安。
そのため今回は、今後 Firebase の管理画面が変わったり、 Android Studio のバージョンが変わっても、プッシュ通知機能を利用できるように公式ドキュメントをテキストとして、プッシュ通知の実装方法をご紹介することとしました。
FirebaseとAndroid Studioと公式ドキュメント
「Firebase、どうやって使うんだ?」 と思って Google で情報収集しようとすると、ちょっと疲れるかもしれません。理由は、 Firebase の設定方法が一つではないからです。
【Firebaseの設定方法の例】
Android Studio から設定
Firebase の管理画面から設定
Firebase の公式ドキュメントに従って設定
Firebase の設定方法は、上記の 3例が代表的と思いますが、どれも手順は違いますし、実行した結果も異なります。例えば Android Studio から設定する方法は簡単ですが、 SDK が足りないとエラーが出たり、バージョンが古いと黄色いエラーが出たりなど。
【Tools → Firebase → Cloud Messaging から設定した直後の画面】
それぞれの設定方法の特徴をまとめると、以下のようになりました。
設定方法
特徴
Android Studioから
2回のクリックでFirebaseの設定が完了、と思いきや、いくつかのエラー解消が必要に。 Firebaseの仕組みを理解していれば大丈夫ですが、Firebase初心者には分かりにくいエラーです。 Firebaseに慣れてきてから使うことを勧めます。
Firebaseの管理画面から
設定に必要なコードをAndroi Studio側に貼り付けたりと、いくつか手作業が必要ですが、どんな設定が必要になるのか把握することができます。 他の Firebaseチュートリアルを見る時に、何が今のバージョンと合っていないか、など応用を利かすことが可能に。 Firebaseの利用初期にオススメの設定方法です。
公式ドキュメントから
注意点や関連情報なども詳しく書かれていていいのですが、ちょっと文章量が多く読みにくいです。 エラーが発生したときや機能を把握したい時におすすめですね。
以上のことから、今回は Firebase の管理画面から手順を把握し、プッシュ通知に必要な設定を行っていくことにしました。
開発するアプリと Firebase を接続 Firebaseを確認
Google検索で「firebase console」 検索後に「Firebase Console」を選択、 もしくは https://console.firebase.google.com/ に直接アクセス。
Firebaseのコンソール画面。早速 「Add Project」 をクリック。
新規プロジェクト作成に必要な情報が求められますので、 Project name を入力し、利用規約等にチェック。そして最後に Create project を選択。
この時入力するプロジェクト名は、 Firebase 管理画面で扱っていく名称であり、 Android Studio のプロジェクト名と違っても大丈夫です。
プロジェクトの作成が完了したら、 Continue をクリック。すると Firebase のプロジェクト管理画面が開きます。
画面上部に現在のプロジェクト名「PushDemo007」が表示されて、画面左がメニューバーになります。プッシュ通知は、左サイドバーの「Grow」内にある 「Cloud Messaging」 から操作。
まずはこの Firebase と Androidアプリを接続する必要がありますので、アンドロイドのマーク「ドロイド君」をクリック。
ドロイド君をクリックするとアプリの登録画面が表示。3項目中 一番上の項目「Android package name」 のみ必須であとは任意の設定。まずはこの「Android package name」を入力、ですがこれには Android Studio で新規プロジェクトを作成する必要があります。
Android Studio を起動して、新規プロジェクトを作成。
Empty Activity。
プロジェクト名を入力して、Javaを選択、 Finish。今回プロジェクト名は、「MyPushDemo001」としました。
それで Firebase に入力する「Android package name」 は、 manifests フォルダ下にある AndroidManifest.xml 内を確認する必要が。 AndroidManifest.xml を開くと上から 3行目に
package="com.example.mypushdemo001"
と書かれた項目があります。この com.example.mypushdemo001 が、 Android package name になります。コピーして、 Firebase に貼り付けましょう。
そして今回はオプション設定はスルーして、 「Register app」 をクリック。すると次の設定へ画面が進みます。
こちらは Firebase と Android アプリを接続するために必要な、 JSONファイルの設定。画面に表示されている「Download google-service.json」をクリックして、 JSONファイルをダウンロード。そしてダウンロードされた google-services.json をコピー。
コピーした google-services.json ファイルは、 Project 下の app 内に貼付け(上図参照)。JSONファイル貼付け後、 JSONファイル内のコードも確認できますので、どんなことが書かれているかざっと見ておくといいでしょう。
そして再び Firebase の画面に戻って、 Nextボタンをクリック。
すると今度は設定に必要なコードが表示。表示されている 3つのコードをコピーして、 Android Studio の Gradle ファイルに貼付け。
まずは一番上のコードをコピーして、 Projectレベルの build.gradle 内に貼付けます。ちなみにこれらのコードは、 プラグインや SDKの読み込みを意味するもの。
一番上のコード
classpath 'com.google.gms:google-services:4.0.1'
を Project レベルの build.gradle に貼り付けたところ、貼り付けコードは黄色エラーで、画面右上には 「Sync Now」 が表示。ここではまず、貼り付けたコードにマウスカーソルを合わせて、 Alt + Enterキーでエラーハンドリング。今回のケースは、バージョンを 4.2.0 に上げてくださいとのこと。
バージョンを変更すると
classpath 'com.google.gms:google-services:4.2.0'
上の黄色エラーは消えるでしょう。 Sync Now は、今行っても OKですし、後でまとめてやっても OK。今回は今 Sync Now してみました。
Sync Now したところ、画面上のエラーが消えてキレイになりました。個人的には設定を変える度に Sync Now する方が、エラーを把握しやすいと思います。
次は再び Firebase の画面に戻って、今度は Appレベルの build.gradle コードをコピー。
Appレベルの build.gradle へコードを追加したところ、先ほどと同じようにエラーが。エラー表示部分で Alt + Enter キーでエラーを確認すると、前回同様バージョンに関するもの。
バージョンを更新して、 Sync Now したところ再び support に関する行でエラーが発生。
suppress:add//noinspection gradle
ということで、バージョン関係でこのようなエラーが表示されている様子。suppress:add//noinspection gradle をクリックして、エラーを抑えます。
そして Sync Now をクリックして、 Gradle を更新。再び Firebase の画面に戻って、 Nextボタンをクリック。
すると設定した Androidアプリ起動してくださいとのこと。 Firebase と アプリがつながるか、 Firebaseの設定が正しく行われたかチェックしてくれます。
Android Studio のエミュレーターを起動してみましょう。
エミュレーターを起動し、10〜20秒ほど待つと、 Firebase の画面に 設定完了の旨が表示。これで Androidアプリに Firebase の基本的な設定ができました。ただ、これだけでは プッシュ通知やアナリティクスの機能は使えません。利用したい機能のプログラムをアプリ側に設定する必要があります。
一旦 「Continue to console」 ボタンで管理画面に戻ってみましょう。
プロジェクト PushDemo007 に対して、 Android アプリ com.example.mypushdemo001 がセットされたことが確認できます。他の Android アプリや iOS アプリ、 Unity など他の環境下のアプリも同時に 管理したい場合は、 「Add App」で追加可能。
今回は 1つのアプリを対象にプッシュ通知テストを行います。左サイドバーの Grow → Cloud Messaging をクリック。
プッシュ通知の設定
Firebase のプロジェクト管理画面から Grow → Cloud Messaging をクリックすると、 Cloud Messaging の管理画面に。今回はまだメッセージ機能の設定ができていませんので 「How do I get Started?どうやって使うの? 」 をクリック。
画面移動後、英語表示であれば、ページ最下部で言語変更可能。とりあえず左サイドバーで 「Android」 を選択し、「Androidクライアントを設定する」を選択。
すると最初にメッセージ機能を使うために必要な SDK の設定コードが紹介されてきます。書かれている通りにコピーして、アプリレベルの build.gradle に追加しましょう。
指定コード
implementation 'com.google.firebase:firebase-messaging:17.3.4'
をアプリレベルの build.gradle に追加すると、貼り付けたコードに対して黄色エラー。 Alt + Enter キーでバージョンを更新し、 Sync Now で Gradle を整えましょう。
メッセージ機能の SDK のバージョンが 17.3.4 から 17.6.0 に更新されましたね。
次はマニフェストの設定。一見するとコードだけ書かれていて、どこに貼り付ければいいか分かりません。そんな時は コード右下のファイル名をクリック。すると GitHubのサンプルコードのページに飛びます。 AndroidManifest.xml 全般のコードが書かれていて、今回使うコードにピンポイントで移動してくれますので、自分のアプリのマニフェストファイルのどこにコードを貼り付ければいいか簡単に理解することが可能。
早速、参考コード
<service android:name=".java.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
を AndroidManifest.xml に貼り付けるものの、上図のように赤色エラー。これは赤色の .java.MyFirebaseMessagingService クラスがないね、というエラー。
あとで .java.MyFirebaseMessagingService を作成しましょう。
設定ページを進めますと、次はオプション設定。設定しなくても大丈夫な項目なので、今回は飛ばします。また以下の内容はトークンに関するもの。テストメッセージなどでは必要な設定ですが、今回はパス。
次は「メッセージを受信する」の項目に移動。
プッシュ通知のプログラム
アプリが Firebase から発信される通知を受け取り、表示するためにはアプリ内に適切な設定を行う必要があります。公式ドキュメント を参考に作業開始。
まず設定の概要は、目次にあるとおり
マニフェストの設定
onMessageReceivedクラスの設定
on DeletedMessagesクラスの設定
バックグラウンド下のアプリについて
今回は onMessageReceived クラスの設定まで行います。
まずはマニフェストに必要なコードを追加。 また?と思うかもしれませんが、内容を確認。
指定コード
<service android:name=".java.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
はい、これは Firebase とアプリの接続設定で追加したコードと同じですね。重複した内容です。 Firebase のドキュメントではこのようによく重複した内容が登場します。
コードが重複するとエラーも重複し、ややこしくなるので注意しましょう。
【重複したコード】
次はメッセージの受信を制御するプログラムの設定。上記のようなコードを入力する必要があるのですが、ファイル名は MyFirebaseMessagingService.java 。現在のアプリにこのようなファイルはありませんので、新規クラスの作成を行う必要が。
上図のように新規クラス MyFirebaseMessagingService を作成し、指定コードを貼り付けるものの、エラーだらけ。まずは RemoteMessage や Log などは必要な class がないというエラーなので、マウスカーソルを合わせて Alt + Enter キーでクラスをインポート。
そして一旦ここで GitHub のサンプルコードと照らしあわせてみると、 FirebaseMessagingService クラスが継承されていなかったり、 TAGプロパティがセットされていなかったりといくつかのミスポイントが確認できます。
GitHub のサンプル を元にコードを更新。
MyFirebaseMessagingServiceクラスで FirebaseMessagingService クラスを継承したところ、クラス名にエラー発生。これは前に設定した AndroidManifest.xml 内の name のこと? というエラー。 AndroidManifest 側の name を
.MyFirebaseMessagingService
にセットし直しましょう。
schedulejob() と handleNow() というメソッドの定義がない、とエラー。 GitHub のコードを参考にしてもいいのですが、これはなくてもいいので消しちゃいます。
MyFirebaseMessagingServiceクラスのコード
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "【Firebaseテスト中】";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO(developer): Handle FCM messages here.
Log.d(TAG, "From: " + remoteMessage.getFrom());
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
}
エミュレーターを起動するとエラーなくアプリが起動。ただし私の場合、エミュレーター上では Android のセットアップが完了していません。この状態では Firebase からのメッセージを受け取れませんでした。そのため実機を接続し、作成したアプリを実機で起動。
実機の場合は、 Android のセットアップが完了していますので、 Firebase からのメッセージを受け取れそうです。
Firebaseからメッセージを送信
再び Firebase の管理画面に戻って、メッセージを送信してみましょう。とりあえず 「Send your first message」 をクリック。
Title 部分と Text 部分に文字を適当に入力して、 Nextボタン。
次は、送信先に関する設定。
大分類として 「User segment」 「Topic」 があり、User segment は送信先アプリを個別に指定でき、 Topic は特定のキーワードがセットされたアプリに対して送信。
今回は簡単な User segment を利用し、対象アプリは com.example.mypushdemo001 を設定。
あとはメッセージの送信するタイミングやコンバーション(反応)、通知音などの設定なのでこれはデフォルトのままでいきます。
ページ最下部の Review をクリックし、Publish をクリック。すると管理画面に送信履歴が表示されます。
Firebase からメッセージ送信後、 Android Studio の Logcat を確認すると、設定したメッセージが書かれています。これで Firebase から Androidアプリにメッセージが送れていることが確認できますね。
あとはプッシュ通知ぽく、メッセージを表示すれば OK。プッシュ通知の表示には、 NotificationCompat.Builderクラスと NotificationManagerCompatクラスが便利でしょう。
下記のように MyFirebaseMessagingServiceクラスを書き換えると、 Firebaseからのメッセージがプッシュ通知として端末に表示されます。
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "【Firebaseテスト中】";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
//Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
String title = remoteMessage.getNotification().getTitle();
String message = remoteMessage.getNotification().getBody();
Log.d(TAG, "Title: " + title);
Log.d(TAG,"Body: " + message);
}
super.onMessageReceived(remoteMessage);
showNotification(remoteMessage.getNotification().getTitle(),remoteMessage.getNotification().getBody());
}
public void showNotification(String title,String message){
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"MyNotification")
.setContentTitle(title)
.setAutoCancel(true)
.setContentText(message);
NotificationManagerCompat manager = NotificationManagerCompat.from(this);
manager.notify(999,builder.build());
}
}
実機でプログラムを再起動し、 Firebase からメッセージを送ってみます。
すると、アプリが落ちました....
Logcat を確認すると...
java.lang.IllegalArgumentException: Invalid notification (no valid small icon)
どうもアイコンがないことでエラーとのこと。確かに現状では AndroidManifest.xml に
android:roundIcon="@mipmap/ic_launcher_round"
と書かれていますが、ダメな様子。このあたりは公式ドキュメントに従ってセットしたはずなのですが。。。
アイコンを設定
通知のアイコン設定は、 res → drawable の drawable フォルダで右クリックし、 New → Image Asset を選択。あとは上図のように icon Type を Notification に変えて、ロゴや文字を変更。今回は Aa という文字にロゴをセットしました。
アイコンが作成できたら、上図のように MyFirebaseMessagingService クラス内にアイコンコードを追加。そして再びアプリを起動し、 Firebase からメッセージを送信してみます。
最終的なMyFirebaseMessagingServiceクラスのコード
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "【Firebaseテスト中】";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
//Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
String title = remoteMessage.getNotification().getTitle();
String message = remoteMessage.getNotification().getBody();
Log.d(TAG, "Title: " + title);
Log.d(TAG,"Body: " + message);
}
super.onMessageReceived(remoteMessage);
showNotification(remoteMessage.getNotification().getTitle(),remoteMessage.getNotification().getBody());
}
public void showNotification(String title,String message){
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"MyNotification")
.setContentTitle(title)
.setSmallIcon(R.drawable.ic_stat_name)
.setAutoCancel(true)
.setContentText(message);
NotificationManagerCompat manager = NotificationManagerCompat.from(this);
manager.notify(999,builder.build());
}
}
ちょっと小さくて見難いですが、実機のスマホ上に設定したアイコン Aa が表示されています。
そして通知を確認すると...
きちんと Firebase で設定したテキストが表示されていますね。
尚、今回作成したプログラムは、バックグラウンドで動くアプリには対応していません。起動中もしくはメモリー下におかれたアプリにのみメッセージが送られます。
Firebaseのプロジェクト削除
Firebaseで作成したプロジェクト、ちょっと困ったことに Firebase管理画面からは削除できません。削除は、 Google Cloud Platform から削除する必要があります。