首页 > 解决方案 > 同时运行多个定时器并保持定时器运行,即使用户已经关闭了android上的应用程序

问题描述

我需要同时启动多个计时器,并且在关闭应用程序后它们应该继续工作。为了继续计时器,我编写了一个服务,但如果应用程序被终止,它只会重新启动一个计时器。另外,重新启动应用程序后mCountDownTimer.cancel()不起作用

服务代码

public class MyService extends Service {

    IBinder mBinder = new LocalBinder();
    MyCountDownTimer myCountDownTimer = new MyCountDownTimer();

    public class LocalBinder extends Binder {
        public BroadcastService getServerInstance() {
            return BroadcastService.this;
        }
    }

    private static final String CHANNEL_ID = "Timer" ;

    @Override
    public void onCreate() {
        super.onCreate();
        myCountDownTimer.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        createNotificationChannel();
        myCountDownTimer.onBind(intent);
        return mBinder;
    }

    public void startTimer(Integer leftTime, String id) {
        myCountDownTimer.startTimer(leftTime, id);
    }

    public void pauseTimer(String id) {
        myCountDownTimer.pauseTimer(id);
    }

    public void resumeTimer(String id) {
        myCountDownTimer.resumeTimer(id);
    }

    public void resetTimer(Integer timeLeft, String id) {
        myCountDownTimer.resetTimer(timeLeft, id);
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Timer", importance);
            channel.setDescription("Notification channel for timers");

            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }
}

myCountDownTimer

class MyCountDownTimer  {
    SharedPreferences pref;
    SharedPreferences.Editor editor;

    NotificationCompat.Builder builder = null;
    NotificationManagerCompat notificationManagerCompat;
    private static final String CHANNEL_ID = "Timer" ;
    private int notificationId = 1;

    private CountDownTimer mCountDownTimer;
    private String mTimerId;
    private long mTimeLeftInMillis;
    private enum timerStatus { RUNNING, PAUSED, FINISHED, INITED }
    private timerStatus mTimerRunning = timerStatus.INITED;
    private static String TIMER_STATUS = "timerStatus";
    private static String TIMER_ID = "timerId";
    private static String TIMER_LEFT_TIME = "timerLeftTimer";

    public void onCreate() {
        notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext());

        pref = getApplicationContext().getSharedPreferences("MyPref", 0);
        editor = pref.edit();

        String timerIdFromStorage = pref.getString(TIMER_ID, "we");
        Integer timerLeftFromStorage = pref.getInt(TIMER_LEFT_TIME, 0);
        String timerStatusFromStorage = pref.getString(TIMER_STATUS, "INITED");

        if(timerIdFromStorage != ""){
            mTimerId = timerIdFromStorage;
        }

        if(timerLeftFromStorage > 0) {
            mTimeLeftInMillis = timerLeftFromStorage;
            if(timerStatusFromStorage.equals("RUNNING")){
                startTimer((int) mTimeLeftInMillis, timerIdFromStorage);
            }
        }
    }


    public void onBind(Intent intent) {
        Integer timeLeft = intent.getIntExtra("TIMER_TIME", 0);
        String timerId = intent.getStringExtra("TIMER_ID");
        Integer timerLeftFromStorage = pref.getInt(TIMER_LEFT_TIME, 0);

        mTimerId = timerId;
        if(timerLeftFromStorage <= 0) {
            mTimeLeftInMillis = timeLeft;
        }

        updateCountDownText();
    }

    public void startTimer(Integer leftTime, String id) {
        if (!id.equals(mTimerId)) {
            mCountDownTimer.cancel();
            mTimerRunning = timerStatus.INITED;

            mTimerId = id;
            mTimeLeftInMillis = leftTime;
        }
        runTimer();

    }

    public void pauseTimer(String id) {
        if(id.equals(mTimerId)){
            mCountDownTimer.cancel();
            mTimerRunning = timerStatus.PAUSED;

            updateCountDownText();
        }
    }

    public void resumeTimer(String id) {
        if(id.equals(mTimerId)){
            startTimer((int) mTimeLeftInMillis,id);
        }
    }

    public void resetTimer(Integer timeLeft, String id) {
        if(id.equals(mTimerId)){
            mTimeLeftInMillis = timeLeft;
            updateCountDownText();
        }
    }

    private void  runTimer() {
        mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                mTimeLeftInMillis = millisUntilFinished;
                updateCountDownText();
            }
            @Override
            public void onFinish() {
                mTimerRunning = timerStatus.FINISHED;
                editor.putString(TIMER_STATUS, String.valueOf(timerStatus.FINISHED));
                editor.apply();
            }
        }.start();

        mTimerRunning = timerStatus.RUNNING;

        Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);

        builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Timer")
                .setContentText("...")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setContentIntent(pendingIntent);
        notificationManagerCompat.notify(notificationId, builder.build());
    }

    private void updateCountDownText() {
        int minutes = (int) (mTimeLeftInMillis / 1000) / 60;
        int seconds = (int) (mTimeLeftInMillis / 1000) % 60;
        String timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);

        editor.putString(TIMER_ID, mTimerId);
        editor.putString(TIMER_STATUS, mTimerRunning.toString());
        editor.putInt(TIMER_LEFT_TIME, (int) mTimeLeftInMillis);
        editor.apply();

        Intent intent_ = new Intent(getApplicationContext(), ExecutableTask.class);
        intent_.putExtra("TIME_LEFT", String.valueOf(mTimeLeftInMillis));
        intent_.putExtra("TIMER_STATUS", mTimerRunning.toString());
        intent_.putExtra("TIMER_ID", mTimerId);
        getApplicationContext().sendBroadcast(intent_);

        if(builder != null) {
            builder.setContentText(timeLeftFormatted);
            notificationManagerCompat.notify(notificationId, builder.build());
        }
    }

}

标签: androidservicecountdowntimer

解决方案


推荐阅读