0

I need to store push notifications data to shared preference and show it inside the app. It's working fine while app is in open state. But if i force close the app. notification is received but shared preference not store the data. I unable to debug please tell me what i am missing

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();


    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.e(TAG, "From: " + remoteMessage.getFrom());

        if (remoteMessage == null)
            return;

        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
handleNotification(remoteMessage.getNotification().getBody());
            showSimpleMsg(remoteMessage.getNotification());
        }

        // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
            try {
                JSONObject json = new JSONObject(remoteMessage.getData());
                storeNotificationToPreferences(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody(),
                        json);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void showSimpleMsg(RemoteMessage.Notification notification) {
        Intent pushNotification = new Intent(Config.PUSH_NOTIFICATION);
        pushNotification.putExtra("message", notification.getBody());
        LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);

        showNotificationMessage(getApplicationContext(), notification.getTitle(), notification.getBody());
    }

    private void handleNotification(String message) {
        if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
            // app is in foreground, broadcast the push message
            Intent pushNotification = new Intent(Config.PUSH_NOTIFICATION);
            pushNotification.putExtra("message", message);
            LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);

            // play notification sound
            NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
            notificationUtils.playNotificationSound();
        } else {
            // If the app is in background, firebase itself handles the notification
        }
    }


    private void showNotificationMessage(Context context, String title, String message) {


        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            Intent intent = new Intent(getApplicationContext(), MainActivity.class);
            String CHANNEL_ID = "olonce";
            NotificationChannel notificationChannel = null;
            notificationChannel = new NotificationChannel(CHANNEL_ID, "olonce", NotificationManager.IMPORTANCE_LOW);
            PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 1, intent, 0);
            Notification notification = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
                    .setContentText(message)
                    .setContentTitle(title)
                    .setContentIntent(pendingIntent)
                    .setChannelId(CHANNEL_ID)
                    .setSmallIcon(R.mipmap.ic_launcher)

                    .build();

            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.createNotificationChannel(notificationChannel);
            notificationManager.notify(1, notification);
        } else {
            Intent intent = new Intent(getApplicationContext(), MainActivity.class);

            PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 1, intent, 0);
            Notification notification = new Notification.Builder(getApplicationContext())
                    .setContentText(message)
                    .setContentTitle(title)
                    .setContentIntent(pendingIntent)
                    .setSmallIcon(R.mipmap.ic_launcher)

                    .build();

            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.notify(1, notification);
        }
    }


    private void storeNotificationToPreferences(String title, String message,JSONObject extraData) {
        SharedPreferences preferences = getApplicationContext().getSharedPreferences("Notifications", MODE_PRIVATE);

        try {
            //Default Data
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("data", new JSONArray());
            jsonObject.put("unread", 0);

            JSONObject oldData = new JSONObject(preferences.getString("notifications", jsonObject.toString()));
            JSONArray data = oldData.getJSONArray("data");
            data.put(new JSONObject().put("title", title).put("message", message).put("data",extraData));

            int unread = (oldData.has("unread") ? oldData.getInt("unread") : 0) + 1;
            oldData.put("unread", unread);

            SharedPreferences.Editor editor = preferences.edit();
            editor.remove("notifications");
            editor.putString("notifications", oldData.toString());
            editor.commit();

            EventBus.getDefault().post(Common.EVENTS.NOTIFICATION);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}
Sabish.M
  • 2,022
  • 16
  • 34

2 Answers2

0

When you force stop an app, Android put the app in a freezed mode meaning that none of its background components (i.e. services and broadcast receivers) can run.

To get the app out of the freezed mode, you'd need an explicit Intent to start one of its components. For example you can manually open the app by tapping on its launcher icon.

frogatto
  • 28,539
  • 11
  • 83
  • 129
  • Then how to store notification data for later use. – Sabish.M Aug 21 '19 at 06:16
  • @Sabish.M You shouldn't force stop the app in the first place, but if you did, it seems there's nothing you can do about it. – frogatto Aug 21 '19 at 06:20
  • also with notification and data tags, as i said it will not trigger onMessageReceived in backgrounded mode so also consider that... if you always want your custom code to run, as i mentioned just use the data tag – Kushan Aug 21 '19 at 06:22
0

So u have two issues, as the previous answer states... On force stop, everything related to the app is killed and does not get restarted until you actually restart the app manually. Thus your FCM service basically gets haulted and doesn't get anything.

Second, when it's a notification that contains both Data and Notification tags, when the app is in background, The notification gets shown via the system tray and the data is passed in the intent which is fired when the notification is clicked. it does not trigger onMessageReceived.

Thus once you stop force stopping the app, you will run into the second one when the app is backgrounded

See

https://firebase.google.com/docs/cloud-messaging/android/receive

Kushan
  • 5,855
  • 3
  • 31
  • 45
  • solution would be to use just Data tags which will always trigger onMessageReceived... but this has a few limitations when it's targetted at ios devices so if u want cross platform notifications, you will have to think – Kushan Aug 21 '19 at 06:21