onMessageReceived()が呼び出されない問題
FireBaseコンソールのNotificationsからメッセージを送信すると、アプリがバックグランドの場合、FirebaseMessagingServiceを継承したクラスのonMessageReceived()が呼び出されずに、自動的にステータスバーに通知が表示されます。
この仕様はFCMのドキュメントにも記載されています。
アプリがバックグラウンドで動作しているとき、Android ではシステムトレイに通知メッセージが送られます。ユーザーが通知をタップすると、デフォルトでアプリ ランチャーが開きます。
通知とデータ ペイロードの両方を含むメッセージ(および Notifications コンソールから送信されたすべてのメッセージ)がここに含まれます。通知は端末の通知領域(システムトレイ)に配信され、データ ペイロードはランチャー アクティビティのインテントの追加部分で配信されます。
それでも、アプリがフォアグラウンドじゃない場合でもバナー状のPUSH通知を表示したいことがあると思います。
バックグランドでもPUSH通知を表示する方法
実はアプリがバックグランドにいる状態でもFirebaseMessagingServiceを継承したクラスは呼び出されます。
ただ、onMessageReceived()に到達しないだけなのです。
onMessageReceived()より前に呼び出されるのが、handleIntent(Intent intent)
です。
引数のintent
にはPUSH通知のメッセージ内容が格納されています。
ちなみに、アプリがフォアグラウンドの場合でも、同様にhandleIntent()
は呼び出されます。
FireBaseコンソールでメッセージ作成時にカスタムデータを下記の様に設定して送信します。
デバッグモードでIntentの中身を見てみると以下のようになっています。
Bundle[{google.c.a.udt=0, google.sent_time=1510755428922, gcm.notification.e=1, google.c.a.c_id=xxxxxxxxxx, google.c.a.ts=xxxxxxxx, gcm.notification.sound=default, gcm.n.e=1, url=https://xxxx/yyyyy/zzzz, body=ボディ, from=xxxxxxxxx, gcm.notification.sound2=default, title=タイトル, google.message_id=0:xxxxxxxxxxxxx, gcm.notification.body=android---, google.c.a.e=1, collapse_key=jp.co.xxxxxxxxxx}]
body
、 title
、url
にFireBaseコンソールでメッセージ作成時に設定したカスタムデータが入ってきてますね。
あとはこの値を取得して、通常通りPUSH通知を表示します。
全体的な実装はこうなります。
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void handleIntent(Intent intent) {
if (intent.getExtras() == null) return;
Map<String, String> data = new HashMap<>();
data.put("body", intent.getExtras().getString("body"));
data.put("title", intent.getExtras().getString("title"));
data.put("url", intent.getExtras().getString("url"));
sendNotification(data);
}
private void sendNotification(Map<String, String> data) {
String title = data.get("title");
String message = data.get("body");
String url = data.get("url");
Intent intent = new Intent(this, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle(title)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText(message)
.setAutoCancel(true)
.setPriority(1 /* Notification.PRIORITY_HIGH */)
.setFullScreenIntent(null, true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
おわりに
これが正しい方法かはわかりませんが、一応問題なく動いています。
他に良い方法があれば教えてください!