Search code examples
androidfirebasefirebase-cloud-messagingruntimeexceptionandroid-looper

How to create a countdown inside Android FirebaseMessagingService?


I'm trying to create countdown inside FirebaseMessagingService like this:

public class MyFirebaseMessagingService extends FirebaseMessagingService {
CountDownTimer countDownTimer;
long timerLeft = 5000;

public void onMessageReceived(RemoteMessage remoteMessage) {
startTimer();
}

  public void startTimer() {

    countDownTimer = new CountDownTimer(timerLeft, 1000) {

        public void onTick(long millisUntilFinished) {
            timerLeft = millisUntilFinished;
            Log.d("timerleft: ",""+timerLeft);
        }
        public void onFinish() {

            timerLeft=10000;
        }
    }.start();
}

But when I recieve message I have this error:

java.lang.RuntimeException: Can't create handler inside thread Thread[Firebase-Messaging-Intent-Handle,5,main] that has not called Looper.prepare()

How can I resolve?


Solution

  • you can always listen to the log and call Looper.prepare() before creating new CountDownTimer, but I would advise you to use some scheduling mechanism, e.g. WorkManager or AlarmManager. that depends on what do you want to achieve after counter finish

    edit due to comments:

    public void onMessageReceived(RemoteMessage remoteMessage) {
        long lastMsgTimestamp = PreferenceManager.getDefaultSharedPreferences(this).
                getLong("lastMsgTimestamp", 0L);
    
        AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        PendingIntent pi = getPendingIntent(this);
        if(lastMsgTimestamp + 5000 >= System.currentTimeMillis()) {
            mgr.cancel(pi);
        }
        mgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 5000, pi);
    
        PreferenceManager.getDefaultSharedPreferences(this).edit().
                putLong("lastMsgTimestamp", System.currentTimeMillis()).apply();
    }
    
    private static PendingIntent getPendingIntent(Context ctx){
        Intent i = new Intent(ctx, FiveSecsBroadcast.class);
        return PendingIntent.getBroadcast(ctx, 0, i, 0);
    }
    

    FiveSecsBroadcast is a BroadcastReceiver which will fire after 5 secs (onReceive method). you may pass some data using Bundle extras in Intent