LoginSignup
23
21

More than 5 years have passed since last update.

【Firebase Notifications】アプリがバックグランドでもPUSH通知を表示する方法

Last updated at Posted at 2017-11-15

onMessageReceived()が呼び出されない問題

FireBaseコンソールのNotificationsからメッセージを送信すると、アプリがバックグランドの場合、FirebaseMessagingServiceを継承したクラスのonMessageReceived()が呼び出されずに、自動的にステータスバーに通知が表示されます。

この仕様はFCMのドキュメントにも記載されています。

アプリがバックグラウンドで動作しているとき、Android ではシステムトレイに通知メッセージが送られます。ユーザーが通知をタップすると、デフォルトでアプリ ランチャーが開きます。
通知とデータ ペイロードの両方を含むメッセージ(および Notifications コンソールから送信されたすべてのメッセージ)がここに含まれます。通知は端末の通知領域(システムトレイ)に配信され、データ ペイロードはランチャー アクティビティのインテントの追加部分で配信されます。

それでも、アプリがフォアグラウンドじゃない場合でもバナー状のPUSH通知を表示したいことがあると思います。

バックグランドでもPUSH通知を表示する方法

実はアプリがバックグランドにいる状態でもFirebaseMessagingServiceを継承したクラスは呼び出されます。
ただ、onMessageReceived()に到達しないだけなのです。

onMessageReceived()より前に呼び出されるのが、handleIntent(Intent intent)です。
引数のintentにはPUSH通知のメッセージ内容が格納されています。
ちなみに、アプリがフォアグラウンドの場合でも、同様にhandleIntent()は呼び出されます。

FireBaseコンソールでメッセージ作成時にカスタムデータを下記の様に設定して送信します。
スクリーンショット 2017-11-16 0.38.28.png

デバッグモードで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}]

bodytitleurlに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());

    }

おわりに

これが正しい方法かはわかりませんが、一応問題なく動いています。
他に良い方法があれば教えてください!

23
21
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
21