0

I have a push notification server to deliver messages to my Android app and I'd like to know the best way to notify the server when the message has been seen.

Currently i'm trying to send the ack message to the server as soon as the main activity of my app calls its onResume callback, but as I use a SingleTop main activity, and I treat some intents with the onNewIntent method, I cannot be sure if the onResume is due to an Intent or the app coming to the foreground. I've mapped the callback flow in the three situations my activity can be when it receives an intent to start it, and they are:

  • The activity is running on the foreground (top of the stack)(1)

    Running -> onPause() -> onNewIntent(intent) -> onResume()

  • The activity is paused on the foreground (screen of for example)(2)

    Paused -> onRestart() -> onStart() -> onResume() -> onPause() -> onNewIntent(intent)

  • The activity is paused on the background (i'm in another activity, for example)(3)

    Paused on background -> onNewIntent(intent) -> onRestart() -> onStart() -> onResume()

In the case i navigate to my activity without receiving an intent:

  • The activity is paused and the user navigates to it (4)

    Paused -> onRestart() -> onStart() -> onResume()

In cases 1, 3 and 4 the user ends in a screen where he/she can actually see the message, so i want to send the ack message.

If there was a callback that is called just in the case the activity really become visible in the screen it'd be perfect, but I'm having trouble finding it.

Someone know how can I solve this?

Felipe Jun
  • 722
  • 11
  • 22

1 Answers1

0

I got a solution, maybe it isn't the best one, but is working for now.

I schedule the ack message every onResume of the target activity, and cancel it in case onPause is called to fast (what in most cases indicates that it was due to an external intent, not the activity being awake).

onResume()

@Override
protected void onResume() {

    Log.d("MainActivity", "onResume");
    super.onResume();

    final SharedPreferences prefs = getSharedPreferences("lastMessageId", Context.MODE_PRIVATE);
    final Long messageId = prefs.getLong("lastMessageId", -1L);

    Runnable task = new Runnable() {

        @Override
        public void run() {
            if(messageId!=-1L){
                Request req = getAgent().notifyMessageSeen(messageId, ((ApplicationILocate)getApplication()).getUser(MainActivity.this), MainActivity.this);
                ((ApplicationILocate)getApplication()).addRequestToQueue(req);
                prefs.edit().putLong("lastMessageId", -1).commit();
            }
        }
    };
    future = scheduler.schedule(task, 1, TimeUnit.SECONDS);
    resumedTime = new Time();
    resumedTime.setToNow();
}

onPause()

protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    Log.d("MainActivity", "onPause");

    pausedTime = new Time();
    pausedTime.setToNow();
    Log.d("MainActivity", "elapsed between resume and pause: "+(pausedTime.toMillis(false)-resumedTime.toMillis(false)));
    if(pausedTime.toMillis(false)-resumedTime.toMillis(false) < 100){
        future.cancel(true);
    }
}

So the message is receiving the ack every time it goes to the screen and the screen is not locked. Any better solution is welcome.

Felipe Jun
  • 722
  • 11
  • 22