java—让计时器始终在没有服务的情况下运行

nzk0hqpo  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(396)

我用的是一个计时器,它需要持续运行直到停止。
我在下面使用的代码运行良好,计时表一直在运行,但是,当设备重新启动时,我得到负值。

SharedPreferences sharedPreferences = getSharedPreferences("chronometer", MODE_PRIVATE);

    //Check if the start time was saved before
    long elapsedTime = sharedPreferences.getLong("elapsed_time", 0);

    if (elapsedTime != 0) {
        //It means the chronometer was running before, so we set the time from SharedPreferences
        chronometer.setBase(elapsedTime);
        chronometer.start();
    }

    //Code below starts the chronometer, after the user manually starts it

    Button startButton = findViewById(R.id.btnStart);
    startButton.setOnClickListener(v -> {
        //Save the starting time
        long elapsedRealtime = SystemClock.elapsedRealtime();
        sharedPreferences.edit().putLong("elapsed_time", elapsedRealtime).apply();

        chronometer.setBase(SystemClock.elapsedRealtime());
        chronometer.start();
    });

为什么在重新启动后计时器显示负值&我该如何处理它?

fzwojiic

fzwojiic1#

你应该把钱存起来 elapsedMillis 进入共享首选项,当设备重新启动并设置计时表的底座时,您应该执行以下操作

chronometer.setBase(SystemClock.elapsedRealtime() - millis)

哪里 millis 是首选项中的值

gywdnpxw

gywdnpxw2#

来自android文档
计时器
实现简单计时器的类。
你可以在系统时钟elapsedrealtime时基中给它一个开始时间,然后从这个时间开始计算。
此类的时基基于systemclock.elapsedrealtime()。
延时 public static long elapsedRealtime() 返回启动后的毫秒数,包括睡眠时间。
回到你的问题上来:
为什么重新启动后,计时器显示负值?
下面是一个示例来演示这个场景。
假设您的手机在上次启动后大约10分钟内运行,此时用户打开活动 elapsedRealtime() 方法将返回600000l(10分钟=10601000毫秒)。当用户单击开始按钮时,您可以将计时器的时间设置为基准时间,并使用将600000升保存到sharepreferences elapsed_time 钥匙。
马上: elapsedRealTime() =10分钟|计时器=00:00
1分钟后: elapsedRealtime() =11分钟|计时器=01:00
10分钟后: elapsedRealTime() =20分钟|计时器=10:00
此时用户按后退键退出应用程序并重新启动手机。
手机有点慢,所以开机需要2分钟。用户再次打开活动。在这个时候。 elapsedRealtime() 返回120000l(2分钟=2601000毫秒)
保存在sharepreferences中的值( elapsed_time )是600000升
因为你设定的计时表的基准时间比 elapsedRealtime() ,因此计时表将显示-08:00并从该值开始计数。
我该怎么处理呢?
您可以保存计时器的运行时间以及从上次用户离开活动到下次用户打开活动的运行时间。然后用这两个值来计算天文钟的基准时间。
活动\u main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <Chronometer
        android:id="@+id/chronometer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:textColor="#F00"
        android:textSize="24sp" />

    <Button
        android:id="@+id/btnStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start" />
</LinearLayout>

主活动.java

public class MainActivity extends AppCompatActivity {

    private static final String KEY_CHRONOMETER_ELAPSED_TIME = "chronometerElapsedTime";
    private static final String KEY_CHRONOMETER_STOPPED_TIME = "chronometerStoppedTime";

    private Chronometer chronometer;
    private SharedPreferences prefs;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        chronometer = findViewById(R.id.chronometer);

        // Code below starts the chronometer, after the user manually starts it
        Button startButton = findViewById(R.id.btnStart);
        startButton.setOnClickListener(v -> {
            setElapsedTime(-1);
            setStoppedTime(-1);
            chronometer.setBase(SystemClock.elapsedRealtime());
            chronometer.start();
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        prefs = getSharedPreferences("chronometer", MODE_PRIVATE);
        if (prefs.contains(KEY_CHRONOMETER_ELAPSED_TIME)
                && prefs.contains(KEY_CHRONOMETER_STOPPED_TIME)) {
            long chronometerElapsedTime = prefs.getLong(KEY_CHRONOMETER_ELAPSED_TIME, -1);
            long chronometerStoppedTime = prefs.getLong(KEY_CHRONOMETER_STOPPED_TIME, -1);
            if (chronometerElapsedTime != -1 && chronometerStoppedTime != -1) {
                long now = System.currentTimeMillis();
                long elapsedTimeFromLastStop = now - chronometerStoppedTime; // Including restart time

                long elapsedRealTime = SystemClock.elapsedRealtime();
                long base = elapsedRealTime - (chronometerElapsedTime + elapsedTimeFromLastStop);

                chronometer.setBase(base);
                chronometer.start();
            }
        }
    }

    @Override
    protected void onStop() {
        setElapsedTime(getChronometerTimeMs());
        setStoppedTime(System.currentTimeMillis());
        super.onStop();
    }

    private void setElapsedTime(long elapsedTimeMs) {
        prefs.edit().putLong(KEY_CHRONOMETER_ELAPSED_TIME, elapsedTimeMs).apply();
    }

    private void setStoppedTime(long stoppedTimeMs) {
        prefs.edit().putLong(KEY_CHRONOMETER_STOPPED_TIME, stoppedTimeMs).apply();
    }

    private long getChronometerTimeMs() {
        long chronometerTimeMs = 0;

        // Regex for HH:MM:SS or MM:SS
        String regex = "([0-1]?\\d|2[0-3])(?::([0-5]?\\d))?(?::([0-5]?\\d))?";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(chronometer.getText());
        if (matcher.find()) {
            boolean isHHMMSSFormat = matcher.groupCount() == 4;
            if (isHHMMSSFormat) {
                int hour = Integer.valueOf(matcher.group(1));
                int minute = Integer.valueOf(matcher.group(2));
                int second = Integer.valueOf(matcher.group(3));
                chronometerTimeMs = (hour * DateUtils.HOUR_IN_MILLIS)
                        + (minute * DateUtils.MINUTE_IN_MILLIS)
                        + (second * DateUtils.SECOND_IN_MILLIS);
            } else {
                int minute = Integer.valueOf(matcher.group(1));
                int second = Integer.valueOf(matcher.group(2));
                chronometerTimeMs = (minute * DateUtils.MINUTE_IN_MILLIS)
                        + (second * DateUtils.SECOND_IN_MILLIS);
            }
        }

        return chronometerTimeMs;
    }
}

相关问题