2011-02-07 21 views
9

私は、四半期/半期/期間の経過時間を追跡する必要があるスポーツアプリを書いています。経過時間は秒まで正確である必要があります。ユーザーが電源ボタンを押して明示的にデバイスをスリープモードにしても、ゲームクロックは継続して動作する必要があります。この時デバイスがスリープ状態のときに動作するAndroidタイマー

私の最初の試みは、クロックをトリガするHandler.postDelayed()を使用して関与「時計」は、画面のタイムアウトによって停止されなかったことを確認するために、すべての200msとWindowManager.LayoutParms.FLAG_KEEP_SCREEN_ONを刻みます。しかし、私はすぐに電源ボタンを押して手動でデバイスをスリープ状態にすることでこの方法を回避することが可能であることを学びました。さらに、postDelayed()アプローチでは、クロックドリフトが発生しています。これは明らかにrun()メソッドで費やされた時間の結果です。実際の数はまだ正確ですが、例えば、ユーザーが容易に理解できる5秒の境界で整列するのではなく、関連するタイマーがドリフトし始め、ユーザーの混乱を招きます。

少しの調査の結果、サービスを使用するためのテクニック、すなわちタイマを実装するために、java timersAlarmManager、およびPartialWakeLockが見つかりました。サービス自体はスリープ状態になるデバイスに関連する問題を解決しません。 Javaタイマーはサービスのように、スリープ状態になるデバイスの問題を解決しません。 AlarmManagerは良いアプローチだと思われますが、これはAlarmManagerの適切な使用(つまり、アラーム間の間隔が非常に短い)ではないことが懸念されます。 PartialWakeLockを使用することも有望ですが、それだけでは私が経験しているクロックドリフトの問題に対処できません。

私は、AlarmManagerとPartialWakeLockの組み合わせを試みます。このアイデアは、AlarmManagerがクロックドリフトやPartialWakeLockとの戦いを助け、コードを単純なものに(指が交差して)維持するのを助けるということです。私は、このアプローチが省電力、コードの複雑さ、ユーザーの期待との間で妥当なバランスをもたらすことを期待しています。アドバイスをいただければ幸いです。

おかげで、

リッチ

+0

。 – NitZRobotKoder

+0

あなたは、「経過時間は秒まで正確である必要がある」と言った。なぜ単純なシステム時間(System.currentTimeMillis()のような)を使用しないのですか?開始時にタイムスタンプを保存し、必要なときに現在の時刻から減算するだけです – Dmitry

答えて

4

私は上記の私のオリジナルのポストへの部分的な解決策を持っています。 postDelayed()処理中に計算に費やされた時間に関連するクロックドリフトにはまだ対応していませんが、それは前進です。さらに、それは信じられないほどシンプルで、常に良い兆候です。

それは私がSystemClock.elapsedRealtime()を使用している必要があるとき、私はSystemClock.uptimeMillis()を使用していたが判明しました。 2の違いは微妙ですが、重要です。

私の解決策は、postDelayed() - 、つまり経過時間= elapsedTime + lastClockIntervalの呼び出しの間に期間を累積して経過時間を記録します。上記のとおり、元の実装では、uptimeMillis()を使用していました。 javadoc reveals that uptimeMillis()を慎重に読むことは、「深い眠り」に費やされた時間、例えばユーザが電源ボタンを押した時間を含まない。しかし、elapsedRealtime()メソッドには、「ディープスリープ」モードで費やされた時間は含まれません。深いスリープサイクルで時間を追跡するために必要だったのは、uptimeMillis()の使用をelapsedRealtime()に置き換えることでした。成功! AlarmManager、PartialWakeLockなどを使用する必要はありません。確かに、これらのメソッドはまだ使用されていますが、シンプルな経過時間のクロックやタイマーを実装する場合は、過剰です。

次の問題は、postDelayed()処理に関連するゼロ以外の実行時間によって引き起こされるクロックドリフトです。私は処理を行うためにスレッドを生成することでこの問題に対処し、非同期呼び出しを模倣することが可能であることを、postDelayed()に願っています。もう1つの方法は、のpostDelayed()の遅延時間を調整することです。の時間はpostDelayed()です。私は結果を掲載します。

私の調査中、無関係なメモで、私は自分自身をCommonsWare Warescriptionに扱いました。私はこの問題のためにこのソースのアイデアを直接使用していませんでしたが、近い将来私のAndroid go-to情報ソースになると思います。私は仕事の中でO'Reillyのサブスクリプションを持っていますが、私はコモンズウェアの本が少なくとも、良いとは限りませんが、O'ReillyのリソースとしてのAndroid開発に関する情報源であることがわかりました。そして、私はO'Reilly Safariのリソースがかなり良いと判断しました。興味深い...

乾杯、あなたが任意のドリフトは表示されませんが、あなたのバッテリーが消耗しますPartialWakeLockを使用して リッチ

関連する問題