【问题标题】:How to create a countdown inside Android FirebaseMessagingService?如何在 Android FirebaseMessagingService 中创建倒计时?
【发布时间】:2023-03-29 06:53:01
【问题描述】:

我正在尝试像这样在 FirebaseMessagingService 中创建倒计时:

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();
}

但是当我收到消息时出现此错误:

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

我该如何解决?

【问题讨论】:

    标签: android firebase firebase-cloud-messaging runtimeexception android-looper


    【解决方案1】:

    在创建new CountDownTimer 之前,您可以随时收听日志并调用Looper.prepare(),但我建议您使用一些调度机制,例如WorkManagerAlarmManager。这取决于你想在计数器完成后实现什么

    由于 cmets 而编辑:

    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 是一个BroadcastReceiver,它将在 5 秒后触发(onReceive 方法)。您可以在Intent 中使用Bundle extras 传递一些数据

    【讨论】:

    • 嗨,tnks 回答,我使用 Looper.prepare()。现在我没有错误,但我看不到Log.d("timerleft: ",""+timerLeft);。这个倒计时没有开始。我希望如果我收到第一条消息,倒计时开始。如果在 5 秒内我收到另一条消息,则发生了某事,否则会发生另一件事。
    • 您可能还需要使用Looper.loop(),但请记住,当第二个消息到达时,可能会创建MyFirebaseMessagingService 的新实例,并且在其中不会有CountDownTimer 运行。我建议您存储一些数据并留下第一个服务以进行杀戮。当将创建新/另一个实例时,然后检查上一条消息的传递时间。最快的方法是使用SharedPreferences,查看我的答案编辑
    • 这不起作用,因为if(lastMsgTimestamp + 5000 >= System.currentTimeMillis()) 只有在新消息到达时才会被调用。我想要“如果没有消息在 5 秒内到达”然后做点什么..
    • 事实上,我的想法是使用当一条消息到达时开始的倒计时,如果另一条消息在 5 秒内到达,则倒计时再次重新开始.. 如果在 5 秒内没有消息到达,那么就会发生一些事情
    • 我在 sn-p 下面写了你必须使用AlarmManager 或任何其他调度机制...用一些示例编辑答案 - 当消息更频繁地出现 5 秒然后@987654338 @(以前设置的)警报将被调用。在设置(另一个/新)警报后 5 秒后触发。在BroadcastReceiver做你的工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-27
    相关资源
    最近更新 更多