トップ地図アプリMap > 万歩計(歩数表示と記録)

万歩計(歩数表示と記録)

はじめに

Androidスマホの場合、歩数カウンタに再起動時からの歩数が記録されている。 直接読み取ることはできず、カウンタの値が変わるごとに、イベントを受けることとなる。

前アプリでは、スマホの再起動時の処理に不備があった。

Pedometer#changed(int cumSteps)

必ずしも頻繁に SQLiteデータベースの値を更新する必要はないが、現時点では、60歩または10分毎に 更新している。

歩いている途中でシャットダウンが起きた場合、1日の歩数に 60歩未満の誤差が起こり得る。 しかし、通常は、10分以上静止した状態でスマホをシャットダウン(再起動)しているので、誤差は生じない。 不測の自体でシャットダウンが起きた場合に備えて、変化があれば 60歩または10分後にデータベースを 更新している。

シャットダウンの前にはイベントが送られるはずなので、このイベントをキャッチして、その時点で データベースに書き込めばいいのであろうが、記録歩数に多少の誤差が生まれても問題はないので、このようにした。

表示

今日の歩数は地図画面の最下部に表示している。日付更新イベントを受けて、その日の歩数をリセットする ことも可能であるが、今は、そうしていない。 朝一番では前日の歩数が表示されている。10歩以上歩いたとき、初めて changedイベントが連続して送られてくる。 これで、新しい日の歩数が表示されるようになる。

朝一番では昨日の歩数が分かる方がいいので、このようにしている。

日々の歩数や月別平均歩数グラフはデータベースから求める。

データベース自体には日々の歩数だけが記録されている。月別平均歩数は SQLの集計関数で求まるはずだが、 今はプログラムで算出している。

    int lastCumSteps = -1;
    long timeChanged = -1;
    void changed(int cumSteps) {
        long now = System.currentTimeMillis()/1000;
        if (cumSteps > lastCumSteps + 60 ||
                (now - timeChanged > 600 && cumSteps > lastCumSteps)) {
            int date = dateNow();
            int[][] cols = getRecordDesc(1);
            int date0 = cols[0][0];
            int steps0 = cols[0][1];
            int cum_steps0 = cols[0][2];

            int steps = (cumSteps - cum_steps0);

            if (date > date0) { // 日付が変わった
                if (cumSteps >= cum_steps0) {
                    insertOrUpdate(date, steps, cumSteps);
                } else {
                    // shutdownがあった
                    insertOrUpdate(date, cumSteps, cumSteps);
                }
            } else {
                if (cumSteps >= cum_steps0) {
                    steps = steps0 + (cumSteps - cum_steps0);
                } else { // shutdownがあった
                    steps = steps0;     // 2026.1.7
                }
                insertOrUpdate(date, steps, cumSteps);
            }
            app.setSteps(steps);
            timeChanged = now;
        }
    }

リファレンス

[1] [Android]Shutdownの処理の流れ