forked from upstream-mirrors/OpenTracks
Refactor periodic tasks.
This commit is contained in:
@@ -112,9 +112,9 @@ limitations under the License.
|
||||
<item>3.1 miles (senyal GPS pobre)</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>Sense divisió</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Inactiu</item>
|
||||
<item>100 km</item>
|
||||
<item>50 km</item>
|
||||
<item>25 km</item>
|
||||
@@ -130,8 +130,8 @@ limitations under the License.
|
||||
<item>1 min</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>No splitting</item>
|
||||
<string-array name="task_frequency_options_ft">
|
||||
<item>Inactiu</item>
|
||||
<item>100 mi</item>
|
||||
<item>50 mi</item>
|
||||
<item>25 mi</item>
|
||||
@@ -286,6 +286,8 @@ limitations under the License.
|
||||
|
||||
<array name="sensor_type_options">
|
||||
<item>Cap</item>
|
||||
<item>ANT+ Sensors</item>
|
||||
<item>SRM ANT+ Bridge</item>
|
||||
<item>Zephyr Bluetooth</item>
|
||||
</array>
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ limitations under the License.
|
||||
<item>328 Fuß</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Maximum recording distance -->
|
||||
<string-array name="max_recording_distance_options">
|
||||
<item>50 m</item>
|
||||
@@ -113,9 +112,9 @@ limitations under the License.
|
||||
<item>3,1 Meilen (sehr schlechtes GPS-Signal)</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>Nicht zerteilen</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Aus</item>
|
||||
<item>100 km</item>
|
||||
<item>50 km</item>
|
||||
<item>25 km</item>
|
||||
@@ -132,7 +131,7 @@ limitations under the License.
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>Nicht zerteilen</item>
|
||||
<item>Aus</item>
|
||||
<item>100 Meilen</item>
|
||||
<item>50 Meilen</item>
|
||||
<item>25 Meilen</item>
|
||||
|
||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Apagado</item>
|
||||
<item>1 min</item>
|
||||
<item>2 min</item>
|
||||
<item>5 min</item>
|
||||
<item>10 min</item>
|
||||
<item>15 min</item>
|
||||
<item>30 min</item>
|
||||
<item>60 min</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Minimum recording distance -->
|
||||
<string-array name="min_recording_distance_options">
|
||||
<item>1 m</item>
|
||||
@@ -112,9 +100,9 @@ limitations under the License.
|
||||
<item>3.1 miles (señal GPS débil)</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>No dividir</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Apagado</item>
|
||||
<item>100 km</item>
|
||||
<item>50 km</item>
|
||||
<item>25 km</item>
|
||||
@@ -130,8 +118,8 @@ limitations under the License.
|
||||
<item>1 min</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>No dividir</item>
|
||||
<string-array name="task_frequency_options_ft">
|
||||
<item>Apagado</item>
|
||||
<item>100 mi</item>
|
||||
<item>50 mi</item>
|
||||
<item>25 mi</item>
|
||||
|
||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Absent</item>
|
||||
<item>1 min</item>
|
||||
<item>2 min</item>
|
||||
<item>5 min</item>
|
||||
<item>10 min</item>
|
||||
<item>15 min</item>
|
||||
<item>30 min</item>
|
||||
<item>60 min</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Minimum recording distance -->
|
||||
<string-array name="min_recording_distance_options">
|
||||
<item>1 m</item>
|
||||
@@ -112,10 +100,9 @@ limitations under the License.
|
||||
<item>3.1 miles (mauvais signal GPS)</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>Pas de séparation</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Absent</item>
|
||||
<item>100 km</item>
|
||||
<item>50 km</item>
|
||||
<item>25 km</item>
|
||||
@@ -131,8 +118,8 @@ limitations under the License.
|
||||
<item>1 min</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>Pas de séparation</item>
|
||||
<string-array name="task_frequency_options_ft">
|
||||
<item>Absent</item>
|
||||
<item>100 mi</item>
|
||||
<item>50 mi</item>
|
||||
<item>25 mi</item>
|
||||
@@ -310,5 +297,5 @@ limitations under the License.
|
||||
<item>Pont SRM ANT+</item>
|
||||
<item>Bluetooth Zephyr</item>
|
||||
</array>
|
||||
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Disattivato</item>
|
||||
<item>1 min</item>
|
||||
<item>2 min</item>
|
||||
<item>5 min</item>
|
||||
<item>10 min</item>
|
||||
<item>15 min</item>
|
||||
<item>30 min</item>
|
||||
<item>60 min</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Minimum recording distance -->
|
||||
<string-array name="min_recording_distance_options">
|
||||
<item>1 m</item>
|
||||
@@ -112,9 +100,9 @@ limitations under the License.
|
||||
<item>3.1 mi (segnale GPS debole)</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>Non dividere</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Disattivato</item>
|
||||
<item>100 km</item>
|
||||
<item>50 km</item>
|
||||
<item>25 km</item>
|
||||
@@ -130,8 +118,8 @@ limitations under the License.
|
||||
<item>1 min</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>Non dividere</item>
|
||||
<string-array name="task_frequency_options_ft">
|
||||
<item>Disattivato</item>
|
||||
<item>100 mi</item>
|
||||
<item>50 mi</item>
|
||||
<item>25 mi</item>
|
||||
|
||||
@@ -15,19 +15,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>不使用</item>
|
||||
<item>1 分</item>
|
||||
<item>2 分</item>
|
||||
<item>5 分</item>
|
||||
<item>10 分</item>
|
||||
<item>15 分</item>
|
||||
<item>30 分</item>
|
||||
<item>60 分</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Minimum recording distance -->
|
||||
<!-- Minimum recording distance -->
|
||||
<string-array name="min_recording_distance_options">
|
||||
<item>1 m</item>
|
||||
<item>2 m</item>
|
||||
@@ -48,7 +36,6 @@ limitations under the License.
|
||||
<item>328 ft</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Maximum recording distance -->
|
||||
<string-array name="max_recording_distance_options">
|
||||
<item>50 m</item>
|
||||
@@ -68,7 +55,6 @@ limitations under the License.
|
||||
<item>3.1 mi</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Minimum recording interval -->
|
||||
<string-array name="min_recording_interval_options">
|
||||
<item>電源節約 (動的制御)</item>
|
||||
@@ -89,7 +75,6 @@ limitations under the License.
|
||||
<item>30 分</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Minimum required accuracy -->
|
||||
<string-array name="min_required_accuracy_options">
|
||||
<item>10 m (GPS信号強度良好)</item>
|
||||
@@ -115,10 +100,9 @@ limitations under the License.
|
||||
<item>3.1 mi (GPS信号強度不良)</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>分割なし</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>不使用</item>
|
||||
<item>100 km</item>
|
||||
<item>50 km</item>
|
||||
<item>25 km</item>
|
||||
@@ -134,8 +118,8 @@ limitations under the License.
|
||||
<item>1 分</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>分割なし</item>
|
||||
<string-array name="task_frequency_options_ft">
|
||||
<item>不使用</item>
|
||||
<item>100 mi</item>
|
||||
<item>50 mi</item>
|
||||
<item>25 mi</item>
|
||||
@@ -294,4 +278,5 @@ limitations under the License.
|
||||
<item>SRM ANT+ ブリッジ</item>
|
||||
<item>Zephyr Bluetooth</item>
|
||||
</array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Brak</item>
|
||||
<item>1 min</item>
|
||||
<item>2 min</item>
|
||||
<item>5 min</item>
|
||||
<item>10 min</item>
|
||||
<item>15 min</item>
|
||||
<item>30 min</item>
|
||||
<item>60 min</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Minimum recording distance -->
|
||||
<string-array name="min_recording_distance_options">
|
||||
<item>1 m</item>
|
||||
@@ -112,9 +100,9 @@ limitations under the License.
|
||||
<item>3.1 mili (słaby sygnał GPS)</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>Brak dzielenia</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Brak</item>
|
||||
<item>100 km</item>
|
||||
<item>50 km</item>
|
||||
<item>25 km</item>
|
||||
@@ -130,8 +118,8 @@ limitations under the License.
|
||||
<item>1 min</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>Brak dzielenia</item>
|
||||
<string-array name="task_frequency_options_ft">
|
||||
<item>Brak</item>
|
||||
<item>100 mi</item>
|
||||
<item>50 mi</item>
|
||||
<item>25 mi</item>
|
||||
@@ -146,7 +134,7 @@ limitations under the License.
|
||||
<item>2 min</item>
|
||||
<item>1 min</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Auto-resume track timeout -->
|
||||
<string-array name="auto_resume_track_timeout_options">
|
||||
<item>Nigdy</item>
|
||||
|
||||
@@ -15,21 +15,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Task frequency -->
|
||||
<array name="task_frequency_options">
|
||||
<item>Desligado</item>
|
||||
<item>1 min</item>
|
||||
<item>2 min</item>
|
||||
<item>5 min</item>
|
||||
<item>10 min</item>
|
||||
<item>15 min</item>
|
||||
<item>30 min</item>
|
||||
<item>60 min</item>
|
||||
</array>
|
||||
|
||||
|
||||
<!-- Minimum recording distance -->
|
||||
<array name="min_recording_distance_options">
|
||||
<string-array name="min_recording_distance_options">
|
||||
<item>1 m</item>
|
||||
<item>2 m</item>
|
||||
<item>3 m</item>
|
||||
@@ -37,9 +24,9 @@ limitations under the License.
|
||||
<item>5 m (recomendada)</item>
|
||||
<item>10 m</item>
|
||||
<item>100 m</item>
|
||||
</array>
|
||||
</string-array>
|
||||
|
||||
<array name="min_recording_distance_options_ft">
|
||||
<string-array name="min_recording_distance_options_ft">
|
||||
<item>3 pés</item>
|
||||
<item>6 pés</item>
|
||||
<item>10 pés</item>
|
||||
@@ -47,31 +34,29 @@ limitations under the License.
|
||||
<item>16 pés (recomendado)</item>
|
||||
<item>33 pés</item>
|
||||
<item>328 pés</item>
|
||||
</array>
|
||||
|
||||
</string-array>
|
||||
|
||||
<!-- Maximum recording distance -->
|
||||
<array name="max_recording_distance_options">
|
||||
<string-array name="max_recording_distance_options">
|
||||
<item>50 m</item>
|
||||
<item>100 m</item>
|
||||
<item>200 m (recomendado)</item>
|
||||
<item>500 m</item>
|
||||
<item>1000 m</item>
|
||||
<item>5000 m</item>
|
||||
</array>
|
||||
</string-array>
|
||||
|
||||
<array name="max_recording_distance_options_ft">
|
||||
<string-array name="max_recording_distance_options_ft">
|
||||
<item>164 pés</item>
|
||||
<item>328 pés</item>
|
||||
<item>656 pés (recomendado)</item>
|
||||
<item>1640 pés</item>
|
||||
<item>0.6 milhas</item>
|
||||
<item>3.1 milhas</item>
|
||||
</array>
|
||||
|
||||
</string-array>
|
||||
|
||||
<!-- Minimum recording interval -->
|
||||
<array name="min_recording_interval_options">
|
||||
<string-array name="min_recording_interval_options">
|
||||
<item>economia de bateria (adaptativo)</item>
|
||||
<item>alta precisão (adaptativo)</item>
|
||||
<item>máxima (recomendada)</item>
|
||||
@@ -88,11 +73,10 @@ limitations under the License.
|
||||
<item>10 min</item>
|
||||
<item>15 min</item>
|
||||
<item>30 min</item>
|
||||
</array>
|
||||
|
||||
</string-array>
|
||||
|
||||
<!-- Minimum required accuracy -->
|
||||
<array name="min_required_accuracy_options">
|
||||
<string-array name="min_required_accuracy_options">
|
||||
<item>10 m (sinal de GPS excelente)</item>
|
||||
<item>20 m</item>
|
||||
<item>50 m</item>
|
||||
@@ -102,9 +86,9 @@ limitations under the License.
|
||||
<item>1000 m</item>
|
||||
<item>2000 m</item>
|
||||
<item>5000 m (sinal de GPS ruim)</item>
|
||||
</array>
|
||||
</string-array>
|
||||
|
||||
<array name="min_required_accuracy_options_ft">
|
||||
<string-array name="min_required_accuracy_options_ft">
|
||||
<item>33 pés (sinal de GPS excelente)</item>
|
||||
<item>66 pés</item>
|
||||
<item>165 pés</item>
|
||||
@@ -114,12 +98,11 @@ limitations under the License.
|
||||
<item>0.6 milhas</item>
|
||||
<item>1.2 milhas</item>
|
||||
<item>3.1 milhas (sinal de GPS ruim)</item>
|
||||
</array>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>Sem divisões</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Desligado</item>
|
||||
<item>100 km</item>
|
||||
<item>50 km</item>
|
||||
<item>25 km</item>
|
||||
@@ -135,8 +118,8 @@ limitations under the License.
|
||||
<item>1 min</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>Sem divisões</item>
|
||||
<string-array name="task_frequency_options_ft">
|
||||
<item>Desligado</item>
|
||||
<item>100 mi</item>
|
||||
<item>50 mi</item>
|
||||
<item>25 mi</item>
|
||||
|
||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Av</item>
|
||||
<item>1 min</item>
|
||||
<item>2 min</item>
|
||||
<item>5 min</item>
|
||||
<item>10 min</item>
|
||||
<item>15 min</item>
|
||||
<item>30 min</item>
|
||||
<item>60 min</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Minimum recording distance -->
|
||||
<string-array name="min_recording_distance_options">
|
||||
<item>1 m</item>
|
||||
@@ -67,7 +55,6 @@ limitations under the License.
|
||||
<item>3.1 miles</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Minimum recording interval -->
|
||||
<string-array name="min_recording_interval_options">
|
||||
<item>batterioptimerad (anpassningsbar)</item>
|
||||
@@ -113,9 +100,9 @@ limitations under the License.
|
||||
<item>3.1 miles (dålig GPS-signal)</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>Ingen delning</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Av</item>
|
||||
<item>100 km</item>
|
||||
<item>50 km</item>
|
||||
<item>25 km</item>
|
||||
@@ -131,8 +118,8 @@ limitations under the License.
|
||||
<item>1 min</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>Ingen delning</item>
|
||||
<string-array name="task_frequency_options_ft">
|
||||
<item>Av</item>
|
||||
<item>100 mi</item>
|
||||
<item>50 mi</item>
|
||||
<item>25 mi</item>
|
||||
|
||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>关闭</item>
|
||||
<item>1 分钟</item>
|
||||
<item>2 分钟</item>
|
||||
<item>5 分钟</item>
|
||||
<item>10 分钟</item>
|
||||
<item>15 分钟</item>
|
||||
<item>30 分钟</item>
|
||||
<item>60 分钟</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Minimum recording distance -->
|
||||
<string-array name="min_recording_distance_options">
|
||||
<item>1 米</item>
|
||||
@@ -112,9 +100,9 @@ limitations under the License.
|
||||
<item>3.1 英里 (糟糕的 GPS 信号)</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>不分割</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>关闭</item>
|
||||
<item>100 千米</item>
|
||||
<item>50 千米</item>
|
||||
<item>25 千米</item>
|
||||
@@ -130,8 +118,8 @@ limitations under the License.
|
||||
<item>1 分钟</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>不分割</item>
|
||||
<string-array name="task_frequency_options_ft">
|
||||
<item>关闭</item>
|
||||
<item>100 英里</item>
|
||||
<item>50 英里</item>
|
||||
<item>25 英里</item>
|
||||
@@ -155,6 +143,7 @@ limitations under the License.
|
||||
<item>15 分钟</item>
|
||||
<item>总是</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Other non-preference arrays -->
|
||||
<array name="activity_types">
|
||||
<item>未知</item>
|
||||
|
||||
@@ -15,31 +15,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Off</item>
|
||||
<item>1 min</item>
|
||||
<item>2 min</item>
|
||||
<item>5 min</item>
|
||||
<item>10 min</item>
|
||||
<item>15 min</item>
|
||||
<item>30 min</item>
|
||||
<item>60 min</item>
|
||||
</string-array>
|
||||
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string-array name="task_frequency_values">
|
||||
<item>-1</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
<item>15</item>
|
||||
<item>30</item>
|
||||
<item>60</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Minimum recording distance -->
|
||||
<string-array name="min_recording_distance_options">
|
||||
<item>1 m</item>
|
||||
@@ -61,18 +36,6 @@ limitations under the License.
|
||||
<item>328 ft</item>
|
||||
</string-array>
|
||||
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string-array name="min_recording_distance_values">
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
<item>100</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Maximum recording distance -->
|
||||
<string-array name="max_recording_distance_options">
|
||||
<item>50 m</item>
|
||||
@@ -92,17 +55,6 @@ limitations under the License.
|
||||
<item>3.1 miles</item>
|
||||
</string-array>
|
||||
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string-array name="max_recording_distance_values">
|
||||
<item>50</item>
|
||||
<item>100</item>
|
||||
<item>200</item>
|
||||
<item>500</item>
|
||||
<item>1000</item>
|
||||
<item>5000</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Minimum recording interval -->
|
||||
<string-array name="min_recording_interval_options">
|
||||
<item>battery miser (adaptive)</item>
|
||||
@@ -123,27 +75,6 @@ limitations under the License.
|
||||
<item>30 min</item>
|
||||
</string-array>
|
||||
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string-array name="min_recording_interval_values">
|
||||
<item>-2</item>
|
||||
<item>-1</item>
|
||||
<item>0</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
<item>20</item>
|
||||
<item>30</item>
|
||||
<item>60</item>
|
||||
<item>120</item>
|
||||
<item>300</item>
|
||||
<item>480</item>
|
||||
<item>900</item>
|
||||
<item>1800</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Minimum required accuracy -->
|
||||
<string-array name="min_required_accuracy_options">
|
||||
<item>10 m (excellent GPS signal)</item>
|
||||
@@ -169,23 +100,9 @@ limitations under the License.
|
||||
<item>3.1 miles (poor GPS signal)</item>
|
||||
</string-array>
|
||||
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string-array name="min_required_accuracy_values">
|
||||
<item>10</item>
|
||||
<item>20</item>
|
||||
<item>50</item>
|
||||
<item>100</item>
|
||||
<item>200</item>
|
||||
<item>500</item>
|
||||
<item>1000</item>
|
||||
<item>2000</item>
|
||||
<item>5000</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Split frequency -->
|
||||
<string-array name="split_frequency_options">
|
||||
<item>No splitting</item>
|
||||
<!-- Task frequency -->
|
||||
<string-array name="task_frequency_options">
|
||||
<item>Off</item>
|
||||
<item>100 km</item>
|
||||
<item>50 km</item>
|
||||
<item>25 km</item>
|
||||
@@ -201,8 +118,8 @@ limitations under the License.
|
||||
<item>1 min</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="split_frequency_options_ft">
|
||||
<item>No splitting</item>
|
||||
<string-array name="task_frequency_options_ft">
|
||||
<item>Off</item>
|
||||
<item>100 mi</item>
|
||||
<item>50 mi</item>
|
||||
<item>25 mi</item>
|
||||
@@ -218,24 +135,6 @@ limitations under the License.
|
||||
<item>1 min</item>
|
||||
</string-array>
|
||||
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string-array name="split_frequency_values">
|
||||
<item>0</item>
|
||||
<item>-100</item>
|
||||
<item>-50</item>
|
||||
<item>-25</item>
|
||||
<item>-10</item>
|
||||
<item>-5</item>
|
||||
<item>-1</item>
|
||||
<item>60</item>
|
||||
<item>30</item>
|
||||
<item>15</item>
|
||||
<item>10</item>
|
||||
<item>5</item>
|
||||
<item>2</item>
|
||||
<item>1</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Auto-resume track timeout -->
|
||||
<string-array name="auto_resume_track_timeout_options">
|
||||
<item>Never</item>
|
||||
@@ -245,16 +144,6 @@ limitations under the License.
|
||||
<item>Always</item>
|
||||
</string-array>
|
||||
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string-array name="auto_resume_track_timeout_values">
|
||||
<item>0</item>
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
<item>15</item>
|
||||
<item>-1</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<!-- Other non-preference arrays -->
|
||||
<array name="activity_types">
|
||||
<item>unknown</item>
|
||||
@@ -383,14 +272,6 @@ limitations under the License.
|
||||
<item>way point</item>
|
||||
</array>
|
||||
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<array name="export_formats">
|
||||
<item>GPX</item>
|
||||
<item>KML</item>
|
||||
<item>CSV</item>
|
||||
<item>TCX</item>
|
||||
</array>
|
||||
|
||||
<array name="sensor_type_options">
|
||||
<item>None</item>
|
||||
<item>ANT+ Sensors</item>
|
||||
@@ -398,18 +279,4 @@ limitations under the License.
|
||||
<item>Zephyr Bluetooth</item>
|
||||
</array>
|
||||
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<array name="sensor_type_values">
|
||||
<item>@string/none</item>
|
||||
<item>@string/ant_sensor_type</item>
|
||||
<item>@string/srm_ant_bridge_sensor_type</item>
|
||||
<item>@string/zephyr_sensor_type</item>
|
||||
</array>
|
||||
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string-array name="ant_sensor_type_values">
|
||||
<item>@string/ant_sensor_type</item>
|
||||
<item>@string/srm_ant_bridge_sensor_type</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2010 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Do not translate any arrays in this file. -->
|
||||
<string-array name="min_required_accuracy_values">
|
||||
<item>10</item>
|
||||
<item>20</item>
|
||||
<item>50</item>
|
||||
<item>100</item>
|
||||
<item>200</item>
|
||||
<item>500</item>
|
||||
<item>1000</item>
|
||||
<item>2000</item>
|
||||
<item>5000</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="min_recording_distance_values">
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
<item>100</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="min_recording_distance_values">
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
<item>100</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="max_recording_distance_values">
|
||||
<item>50</item>
|
||||
<item>100</item>
|
||||
<item>200</item>
|
||||
<item>500</item>
|
||||
<item>1000</item>
|
||||
<item>5000</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="min_recording_interval_values">
|
||||
<item>-2</item>
|
||||
<item>-1</item>
|
||||
<item>0</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
<item>20</item>
|
||||
<item>30</item>
|
||||
<item>60</item>
|
||||
<item>120</item>
|
||||
<item>300</item>
|
||||
<item>480</item>
|
||||
<item>900</item>
|
||||
<item>1800</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="task_frequency_values">
|
||||
<item>0</item>
|
||||
<item>-100</item>
|
||||
<item>-50</item>
|
||||
<item>-25</item>
|
||||
<item>-10</item>
|
||||
<item>-5</item>
|
||||
<item>-1</item>
|
||||
<item>60</item>
|
||||
<item>30</item>
|
||||
<item>15</item>
|
||||
<item>10</item>
|
||||
<item>5</item>
|
||||
<item>2</item>
|
||||
<item>1</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="auto_resume_track_timeout_values">
|
||||
<item>0</item>
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
<item>15</item>
|
||||
<item>-1</item>
|
||||
</string-array>
|
||||
|
||||
<array name="export_formats">
|
||||
<item>GPX</item>
|
||||
<item>KML</item>
|
||||
<item>CSV</item>
|
||||
<item>TCX</item>
|
||||
</array>
|
||||
|
||||
<array name="sensor_type_values">
|
||||
<item>@string/none</item>
|
||||
<item>@string/ant_sensor_type</item>
|
||||
<item>@string/srm_ant_bridge_sensor_type</item>
|
||||
<item>@string/zephyr_sensor_type</item>
|
||||
</array>
|
||||
|
||||
<string-array name="ant_sensor_type_values">
|
||||
<item>@string/ant_sensor_type</item>
|
||||
<item>@string/srm_ant_bridge_sensor_type</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
@@ -48,8 +48,8 @@ limitations under the License.
|
||||
android:key="@string/split_frequency_key"
|
||||
android:title="@string/settings_split_frequency"
|
||||
android:summary="@string/settings_split_frequency_summary"
|
||||
android:entries="@array/split_frequency_options"
|
||||
android:entryValues="@array/split_frequency_values"
|
||||
android:entries="@array/task_frequency_options"
|
||||
android:entryValues="@array/task_frequency_values"
|
||||
android:defaultValue="0" />
|
||||
|
||||
<com.google.android.apps.mytracks.IntegerListPreference
|
||||
|
||||
@@ -19,29 +19,21 @@ import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
|
||||
import com.google.android.apps.mytracks.ChartView.Mode;
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Sensor;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TrackPointsColumns;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.content.WaypointsColumns;
|
||||
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
|
||||
import com.google.android.apps.mytracks.stats.DoubleBuffer;
|
||||
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
|
||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@@ -58,48 +50,28 @@ import java.util.ArrayList;
|
||||
* An activity that displays a chart from the track point provider.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class ChartActivity extends Activity implements
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private final static int BUFFER_SIZE = 1024;
|
||||
private double profileLength = 0;
|
||||
|
||||
private boolean metricUnits = true;
|
||||
private boolean reportSpeed = true;
|
||||
|
||||
/**
|
||||
* The track id that is displayed.
|
||||
*/
|
||||
private long selectedTrackId = -1;
|
||||
|
||||
/**
|
||||
* Id of the last location that was seen when reading tracks from the
|
||||
* provider. This is used to determine which locations are new compared to the
|
||||
* last time the chart was updated.
|
||||
*/
|
||||
private long lastSeenLocationId = -1;
|
||||
|
||||
private long startTime = -1;
|
||||
|
||||
private Location lastLocation;
|
||||
|
||||
/**
|
||||
* The id of the track currently being recorded.
|
||||
*/
|
||||
private long recordingTrackId = -1;
|
||||
public class ChartActivity extends Activity implements TrackDataListener {
|
||||
|
||||
private final DoubleBuffer elevationBuffer =
|
||||
new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
|
||||
private final DoubleBuffer speedBuffer =
|
||||
new DoubleBuffer(Constants.SPEED_SMOOTHING_FACTOR);
|
||||
private final ArrayList<double[]> pendingPoints = new ArrayList<double[]>();
|
||||
|
||||
private TrackDataHub dataHub;
|
||||
|
||||
// Stats gathered from received data.
|
||||
private double profileLength = 0;
|
||||
private long startTime = -1;
|
||||
private Location lastLocation;
|
||||
private double trackMaxSpeed;
|
||||
|
||||
// Modes of operation
|
||||
private Mode mode = Mode.BY_DISTANCE;
|
||||
|
||||
/**
|
||||
* Utilities to deal with the database.
|
||||
*/
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
private boolean metricUnits;
|
||||
private boolean reportSpeed;
|
||||
|
||||
/*
|
||||
* UI elements:
|
||||
@@ -109,9 +81,6 @@ public class ChartActivity extends Activity implements
|
||||
private LinearLayout busyPane;
|
||||
private ZoomControls zoomControls;
|
||||
|
||||
/** Handler for callbacks to the UI thread */
|
||||
private final Handler uiHandler = new Handler();
|
||||
|
||||
/**
|
||||
* A runnable that can be posted to the UI thread. It will remove the spinner
|
||||
* (if any), enable/disable zoom controls and orange pointer as appropriate
|
||||
@@ -123,89 +92,17 @@ public class ChartActivity extends Activity implements
|
||||
busyPane.setVisibility(View.GONE);
|
||||
zoomControls.setIsZoomInEnabled(chartView.canZoomIn());
|
||||
zoomControls.setIsZoomOutEnabled(chartView.canZoomOut());
|
||||
chartView.setShowPointer(selectedTrackIsRecording());
|
||||
chartView.setShowPointer(dataHub.isRecordingSelected());
|
||||
chartView.invalidate();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A runnable that can be posted to the UI thread. It will show the spinner.
|
||||
*/
|
||||
private final Runnable showSpinner = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
busyPane.setVisibility(View.VISIBLE);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An observer for the tracks provider. Will listen to new track points being
|
||||
* added and update the chart if necessary.
|
||||
*/
|
||||
private ContentObserver observer;
|
||||
|
||||
/**
|
||||
* An observer for the waypoints provider. Will listen to new way points being
|
||||
* added and update the chart if necessary.
|
||||
*/
|
||||
private ContentObserver waypointObserver;
|
||||
|
||||
/**
|
||||
* A thread with a looper. Post to updateTrackHandler to execute Runnables on
|
||||
* this thread.
|
||||
*/
|
||||
private final HandlerThread updateTrackThread =
|
||||
new HandlerThread("updateTrackThread");
|
||||
|
||||
/** Handler for updateTrackThread */
|
||||
private Handler updateTrackHandler;
|
||||
|
||||
/**
|
||||
* A runnable that updates the profile from the provider.
|
||||
*/
|
||||
private final Runnable updateTrackRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
readNewTrackPoints();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||
String key) {
|
||||
if (key != null) {
|
||||
if (key.equals(getString(R.string.selected_track_key))) {
|
||||
selectedTrackId =
|
||||
sharedPreferences.getLong(getString(R.string.selected_track_key),
|
||||
-1);
|
||||
readProfileAsync();
|
||||
} else if (key.equals(getString(R.string.metric_units_key))) {
|
||||
metricUnits =
|
||||
sharedPreferences.getBoolean(getString(R.string.metric_units_key),
|
||||
true);
|
||||
chartView.setMetricUnits(metricUnits);
|
||||
readProfileAsync();
|
||||
} else if (key.equals(getString(R.string.report_speed_key))) {
|
||||
reportSpeed =
|
||||
sharedPreferences.getBoolean(getString(R.string.report_speed_key),
|
||||
true);
|
||||
chartView.setReportSpeed(reportSpeed, this);
|
||||
readProfileAsync();
|
||||
} else if (key.equals(getString(R.string.recording_track_key))) {
|
||||
recordingTrackId =
|
||||
sharedPreferences.getLong(getString(R.string.recording_track_key),
|
||||
-1);
|
||||
runOnUiThread(updateChart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
Log.w(TAG, "ChartActivity.onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
MyTracks.getInstance().setChartActivity(this);
|
||||
providerUtils = MyTracksProviderUtils.Factory.get(this);
|
||||
dataHub = MyTracks.getInstance().getDataHub();
|
||||
|
||||
// The volume we want to control is the Text-To-Speech volume
|
||||
int volumeStream =
|
||||
@@ -221,22 +118,6 @@ public class ChartActivity extends Activity implements
|
||||
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
|
||||
layout.addView(chartView, params);
|
||||
|
||||
SharedPreferences preferences =
|
||||
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
||||
if (preferences != null) {
|
||||
selectedTrackId =
|
||||
preferences.getLong(getString(R.string.selected_track_key), -1);
|
||||
recordingTrackId =
|
||||
preferences.getLong(getString(R.string.recording_track_key), -1);
|
||||
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key),
|
||||
true);
|
||||
chartView.setMetricUnits(metricUnits);
|
||||
reportSpeed = preferences.getBoolean(getString(R.string.report_speed_key),
|
||||
true);
|
||||
chartView.setReportSpeed(reportSpeed, this);
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
busyPane = (LinearLayout) findViewById(R.id.elevation_busypane);
|
||||
zoomControls = (ZoomControls) findViewById(R.id.elevation_zoom);
|
||||
zoomControls.setOnZoomInClickListener(new View.OnClickListener() {
|
||||
@@ -251,97 +132,20 @@ public class ChartActivity extends Activity implements
|
||||
zoomOut();
|
||||
}
|
||||
});
|
||||
|
||||
updateTrackThread.start();
|
||||
updateTrackHandler = new Handler(updateTrackThread.getLooper());
|
||||
|
||||
// Register observer for the track point provider:
|
||||
Handler contentHandler = new Handler();
|
||||
observer = new ContentObserver(contentHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
Log.d(TAG, "ChartActivity: ContentObserver.onChange");
|
||||
// Check for any new locations and append them to the currently
|
||||
// recording track.
|
||||
if (recordingTrackId < 0) {
|
||||
// No track is being recorded. We should not be here.
|
||||
return;
|
||||
}
|
||||
if (selectedTrackId != recordingTrackId) {
|
||||
// No track, or one other than the recording track is selected, don't
|
||||
// bother.
|
||||
return;
|
||||
}
|
||||
// Update can potentially be lengthy, put it in its own thread:
|
||||
updateTrackHandler.post(updateTrackRunnable);
|
||||
super.onChange(selfChange);
|
||||
}
|
||||
};
|
||||
|
||||
waypointObserver = new ContentObserver(contentHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
Log.d(TAG,
|
||||
"MyTracksMap: ContentObserver.onChange waypoints");
|
||||
if (selectedTrackId < 0) {
|
||||
return;
|
||||
}
|
||||
Thread t = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
readWaypoints();
|
||||
ChartActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chartView.invalidate();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
t.start();
|
||||
super.onChange(selfChange);
|
||||
}
|
||||
};
|
||||
|
||||
readProfileAsync();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
unregisterContentObservers();
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
||||
dataHub.registerTrackDataListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
// Make sure any updates that might have happened are propagated to this
|
||||
// activity:
|
||||
observer.onChange(false);
|
||||
waypointObserver.onChange(false);
|
||||
registerContentObservers();
|
||||
}
|
||||
protected void onStop() {
|
||||
dataHub.unregisterTrackDataListener(this);
|
||||
|
||||
/**
|
||||
* Register the content observer for the map overlay.
|
||||
*/
|
||||
private void registerContentObservers() {
|
||||
getContentResolver().registerContentObserver(TrackPointsColumns.CONTENT_URI,
|
||||
false/* notifyForDescendents */, observer);
|
||||
getContentResolver().registerContentObserver(WaypointsColumns.CONTENT_URI,
|
||||
false/* notifyForDescendents */, waypointObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the content observer for the map overlay.
|
||||
*/
|
||||
private void unregisterContentObservers() {
|
||||
getContentResolver().unregisterContentObserver(observer);
|
||||
getContentResolver().unregisterContentObserver(waypointObserver);
|
||||
}
|
||||
|
||||
private boolean selectedTrackIsRecording() {
|
||||
return selectedTrackId == recordingTrackId;
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
private void zoomIn() {
|
||||
@@ -360,7 +164,7 @@ public class ChartActivity extends Activity implements
|
||||
if (this.mode != newMode) {
|
||||
this.mode = newMode;
|
||||
chartView.setMode(this.mode);
|
||||
readProfileAsync();
|
||||
dataHub.reloadDataFor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,34 +181,6 @@ public class ChartActivity extends Activity implements
|
||||
return chartView.getChartValueSeries(index).isEnabled();
|
||||
}
|
||||
|
||||
private void readWaypoints() {
|
||||
if (selectedTrackId < 0) {
|
||||
return;
|
||||
}
|
||||
Cursor cursor = null;
|
||||
chartView.clearWaypoints();
|
||||
try {
|
||||
// We will silently drop extra waypoints to make the app responsive.
|
||||
cursor =
|
||||
providerUtils.getWaypointsCursor(selectedTrackId, 0,
|
||||
Constants.MAX_DISPLAYED_TRACK_POINTS);
|
||||
if (cursor != null) {
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
Waypoint wpt = providerUtils.createWaypoint(cursor);
|
||||
chartView.addWaypoint(wpt);
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
Log.w(TAG, "Caught an unexpected exception.", e);
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
@@ -440,43 +216,41 @@ public class ChartActivity extends Activity implements
|
||||
* This must be called in order for each point.
|
||||
*
|
||||
* @param location the location to get data for (this method takes ownership of that location)
|
||||
* @param track the track to get data from
|
||||
* @param result the resulting point to fill out
|
||||
* @return the previous location, now available for reuse
|
||||
*/
|
||||
private Location getDataPoint(Location location, Track track, double[] result) {
|
||||
private void fillDataPoint(Location location, double result[]) {
|
||||
double timeOrDistance = Double.NaN,
|
||||
elevation = Double.NaN,
|
||||
speed = Double.NaN,
|
||||
power = Double.NaN,
|
||||
cadence = Double.NaN,
|
||||
heartRate = Double.NaN;
|
||||
|
||||
if (location instanceof MyTracksLocation &&
|
||||
((MyTracksLocation) location).getSensorDataSet() != null) {
|
||||
SensorDataSet sensorData = ((MyTracksLocation) location).getSensorDataSet();
|
||||
if (sensorData.hasPower()
|
||||
&& sensorData.getPower().getState() == Sensor.SensorState.SENDING
|
||||
&& sensorData.getPower().hasValue()) {
|
||||
result[3] = sensorData.getPower().getValue();
|
||||
} else {
|
||||
result[3] = Double.NaN;
|
||||
power = sensorData.getPower().getValue();
|
||||
}
|
||||
if (sensorData.hasCadence()
|
||||
&& sensorData.getCadence().getState() == Sensor.SensorState.SENDING
|
||||
&& sensorData.getCadence().hasValue()) {
|
||||
result[4] = sensorData.getCadence().getValue();
|
||||
} else {
|
||||
result[4] = Double.NaN;
|
||||
cadence = sensorData.getCadence().getValue();
|
||||
}
|
||||
if (sensorData.hasHeartRate()
|
||||
&& sensorData.getHeartRate().getState() == Sensor.SensorState.SENDING
|
||||
&& sensorData.getHeartRate().hasValue()) {
|
||||
result[5] = sensorData.getHeartRate().getValue();
|
||||
} else {
|
||||
result[5] = Double.NaN;
|
||||
heartRate = sensorData.getHeartRate().getValue();
|
||||
}
|
||||
} else {
|
||||
result[3] = Double.NaN;
|
||||
result[4] = Double.NaN;
|
||||
result[5] = Double.NaN;
|
||||
}
|
||||
|
||||
// TODO: Account for segment splits?
|
||||
switch (mode) {
|
||||
case BY_DISTANCE:
|
||||
result[0] = profileLength;
|
||||
timeOrDistance = profileLength;
|
||||
if (lastLocation != null) {
|
||||
double d = lastLocation.distanceTo(location);
|
||||
if (metricUnits) {
|
||||
@@ -491,7 +265,7 @@ public class ChartActivity extends Activity implements
|
||||
// Base case
|
||||
startTime = location.getTime();
|
||||
}
|
||||
result[0] = (location.getTime() - startTime);
|
||||
timeOrDistance = (location.getTime() - startTime);
|
||||
break;
|
||||
default:
|
||||
Log.w(TAG, "ChartActivity unknown mode: " + mode);
|
||||
@@ -500,7 +274,7 @@ public class ChartActivity extends Activity implements
|
||||
elevationBuffer.setNext(metricUnits
|
||||
? location.getAltitude()
|
||||
: location.getAltitude() * UnitConversions.M_TO_FT);
|
||||
result[1] = elevationBuffer.getAverage();
|
||||
elevation = elevationBuffer.getAverage();
|
||||
|
||||
if (lastLocation == null) {
|
||||
if (Math.abs(location.getSpeed() - 128) > 1) {
|
||||
@@ -509,151 +283,134 @@ public class ChartActivity extends Activity implements
|
||||
} else if (TripStatisticsBuilder.isValidSpeed(
|
||||
location.getTime(), location.getSpeed(), lastLocation.getTime(),
|
||||
lastLocation.getSpeed(), speedBuffer)
|
||||
&& (location.getSpeed() <= track.getStatistics().getMaxSpeed())) {
|
||||
&& (location.getSpeed() <= trackMaxSpeed)) {
|
||||
speedBuffer.setNext(location.getSpeed());
|
||||
}
|
||||
result[2] = speedBuffer.getAverage() * 3.6;
|
||||
speed = speedBuffer.getAverage() * 3.6;
|
||||
if (!metricUnits) {
|
||||
result[2] *= UnitConversions.KM_TO_MI;
|
||||
speed *= UnitConversions.KM_TO_MI;
|
||||
}
|
||||
if (!reportSpeed && (result[2] != 0)) {
|
||||
// Format as hours per unit
|
||||
result[2] = (60.0 / result[2]);
|
||||
if (!reportSpeed) {
|
||||
if (speed != 0) {
|
||||
// Format as hours per unit
|
||||
speed = (60.0 / speed);
|
||||
} else {
|
||||
speed = Double.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
Location oldLastLocation = lastLocation;
|
||||
// Keep a copy so the location can be reused.
|
||||
lastLocation = location;
|
||||
|
||||
if (oldLastLocation == null) {
|
||||
// No previous location, but return a blank one for reuse
|
||||
return new MyTracksLocation("");
|
||||
if (result != null) {
|
||||
result[0] = timeOrDistance;
|
||||
result[1] = elevation;
|
||||
result[2] = speed;
|
||||
result[3] = power;
|
||||
result[4] = cadence;
|
||||
result[5] = heartRate;
|
||||
}
|
||||
|
||||
return oldLastLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the chart data points reading from the provider. This is non-blocking.
|
||||
*/
|
||||
private void readProfileAsync() {
|
||||
chartView.reset();
|
||||
updateTrackHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void onProviderStateChange(ProviderState state) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentLocationChanged(Location loc) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentHeadingChanged(double heading) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectedTrackChanged(Track track, boolean isRecording) {
|
||||
Log.e(TAG, "Visible", new Throwable());
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThread(showSpinner);
|
||||
readProfile();
|
||||
readWaypoints();
|
||||
runOnUiThread(updateChart);
|
||||
busyPane.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the track profile from the provider. This is a blocking function and
|
||||
* should not be run from the UI thread.
|
||||
*/
|
||||
private void readProfile() {
|
||||
@Override
|
||||
public void onTrackUpdated(Track track) {
|
||||
trackMaxSpeed = track.getStatistics().getMaxSpeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTrackPoints() {
|
||||
profileLength = 0;
|
||||
lastLocation = null;
|
||||
startTime = -1;
|
||||
if (selectedTrackId < 0) {
|
||||
return;
|
||||
}
|
||||
Track track = providerUtils.getTrack(selectedTrackId);
|
||||
if (track == null) {
|
||||
return;
|
||||
}
|
||||
lastSeenLocationId = track.getStartId();
|
||||
final ArrayList<double[]> theData = readPointsToList(track);
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
chartView.setDataPoints(theData);
|
||||
}
|
||||
});
|
||||
elevationBuffer.reset();
|
||||
speedBuffer.reset();
|
||||
chartView.reset();
|
||||
pendingPoints.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all new track points.
|
||||
*/
|
||||
private void readNewTrackPoints() {
|
||||
Log.i(TAG, "MyTracks: Updating chart last seen: " + lastSeenLocationId);
|
||||
Track track = providerUtils.getTrack(recordingTrackId);
|
||||
if (track == null) {
|
||||
Log.w(TAG, "MyTracks: track not found");
|
||||
return;
|
||||
@Override
|
||||
public void onNewTrackPoint(Location loc) {
|
||||
if (LocationUtils.isValidLocation(loc)) {
|
||||
double[] point = new double[6];
|
||||
fillDataPoint(loc, point);
|
||||
pendingPoints.add(point);
|
||||
}
|
||||
chartView.addDataPoints(readPointsToList(track));
|
||||
uiHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
chartView.invalidate();
|
||||
}
|
||||
});
|
||||
Log.i(TAG, "MyTracks: Updated chart last seen: " + lastSeenLocationId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the frequency at which points should be displayed.
|
||||
* Limit the number of chart readings. Ideally we would want around 1024.
|
||||
* @param track The track which will be displayed.
|
||||
* @return The inverse of the frequency of points to be displayed.
|
||||
*/
|
||||
private int getSamplingFrequency(Track track) {
|
||||
long totalLocations = track.getStopId() - track.getStartId();
|
||||
return Math.max(1, (int) (totalLocations / 1024.0));
|
||||
@Override
|
||||
public void onSampledOutTrackPoint(Location loc) {
|
||||
// Still account for the point in the smoothing buffers.
|
||||
fillDataPoint(loc, null);
|
||||
}
|
||||
|
||||
private Cursor getLocationsCursor(long lastLocationRead) {
|
||||
return providerUtils.getLocationsCursor(selectedTrackId, lastLocationRead, BUFFER_SIZE, false);
|
||||
@Override
|
||||
public void onSegmentSplit() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all of the points to a list.
|
||||
* @param track The track which will be displayed.
|
||||
* @return
|
||||
*/
|
||||
private ArrayList<double[]> readPointsToList(Track track) {
|
||||
Cursor cursor = null;
|
||||
long lastLocationRead = lastSeenLocationId;
|
||||
int points = 0;
|
||||
int chartSamplingFrequency = getSamplingFrequency(track);
|
||||
ArrayList<double[]> result = new ArrayList<double[]>();
|
||||
// Need two locations so we can keep track of the last location.
|
||||
Location location = new MyTracksLocation("");
|
||||
try {
|
||||
while (lastSeenLocationId < track.getStopId()) {
|
||||
cursor = getLocationsCursor(lastLocationRead);
|
||||
if (cursor != null) {
|
||||
elevationBuffer.reset();
|
||||
speedBuffer.reset();
|
||||
if (cursor.moveToFirst()) {
|
||||
final int idColumnIdx = cursor.getColumnIndexOrThrow(TrackPointsColumns._ID);
|
||||
while (cursor.moveToNext()) {
|
||||
points++;
|
||||
providerUtils.fillLocation(cursor, location);
|
||||
if (MyTracksUtils.isValidLocation(location)) {
|
||||
lastLocationRead = lastSeenLocationId =
|
||||
cursor.getLong(idColumnIdx);
|
||||
// TODO Can we be smarter about choosing 3 or 6 entries?
|
||||
double[] point = new double[6];
|
||||
location = getDataPoint(location, track, point);
|
||||
if (points % chartSamplingFrequency == 0) {
|
||||
result.add(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lastLocationRead += BUFFER_SIZE;
|
||||
}
|
||||
} else {
|
||||
lastLocationRead += BUFFER_SIZE;
|
||||
}
|
||||
cursor.close();
|
||||
cursor = null;
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onNewTrackPointsDone() {
|
||||
chartView.addDataPoints(pendingPoints);
|
||||
pendingPoints.clear();
|
||||
runOnUiThread(updateChart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearWaypoints() {
|
||||
chartView.clearWaypoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypoint(Waypoint wpt) {
|
||||
chartView.addWaypoint(wpt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypointsDone() {
|
||||
runOnUiThread(updateChart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onUnitsChanged(boolean metric) {
|
||||
this.metricUnits = metric;
|
||||
|
||||
chartView.setMetricUnits(metric);
|
||||
|
||||
return true; // Reload data
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onReportSpeedChanged(boolean reportSpeed) {
|
||||
this.reportSpeed = reportSpeed;
|
||||
|
||||
chartView.setReportSpeed(reportSpeed, this);
|
||||
|
||||
return true; // Reload data
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -266,9 +266,6 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
final ListPreference minRequiredAccuracy =
|
||||
(ListPreference) findPreference(
|
||||
getString(R.string.min_required_accuracy_key));
|
||||
final ListPreference splitFrequency =
|
||||
(ListPreference) findPreference(
|
||||
getString(R.string.split_frequency_key));
|
||||
|
||||
minRecordingDistance.setEntries(isMetric
|
||||
? R.array.min_recording_distance_options
|
||||
@@ -279,9 +276,16 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
minRequiredAccuracy.setEntries(isMetric
|
||||
? R.array.min_required_accuracy_options
|
||||
: R.array.min_required_accuracy_options_ft);
|
||||
splitFrequency.setEntries(isMetric
|
||||
? R.array.split_frequency_options
|
||||
: R.array.split_frequency_options_ft);
|
||||
setTaskOptions(isMetric, R.string.announcement_frequency_key);
|
||||
setTaskOptions(isMetric, R.string.split_frequency_key);
|
||||
}
|
||||
|
||||
private void setTaskOptions(boolean isMetric, int listId) {
|
||||
final ListPreference taskFrequency =
|
||||
(ListPreference) findPreference(getString(listId));
|
||||
taskFrequency.setEntries(isMetric
|
||||
? R.array.task_frequency_options
|
||||
: R.array.task_frequency_options_ft);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,26 +17,15 @@ package com.google.android.apps.mytracks;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtilsImpl;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||
import com.google.android.apps.mytracks.content.WaypointsColumns;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
|
||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.database.ContentObserver;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
import android.location.LocationProvider;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
@@ -44,66 +33,39 @@ import android.view.MenuItem;
|
||||
import android.view.Window;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* An activity that displays track statistics to the user.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class StatsActivity extends Activity
|
||||
implements OnSharedPreferenceChangeListener {
|
||||
|
||||
public class StatsActivity extends Activity implements TrackDataListener {
|
||||
private StatsUtilities utils;
|
||||
private UIUpdateThread thread;
|
||||
|
||||
private ContentObserver observer;
|
||||
|
||||
/**
|
||||
* The id of the currently selected track.
|
||||
*/
|
||||
private long selectedTrackId = -1;
|
||||
|
||||
/**
|
||||
* The id of the currently recording track.
|
||||
*/
|
||||
private long recordingTrackId = -1;
|
||||
|
||||
/**
|
||||
* The start time of the selected track.
|
||||
*/
|
||||
private long startTime = -1;
|
||||
|
||||
/**
|
||||
* True if distances should be displayed in metric units (from shared
|
||||
* preferences).
|
||||
*/
|
||||
private boolean metricUnits = true;
|
||||
|
||||
/**
|
||||
* True if pace should be displayed as dist/time (from shared preferences).
|
||||
*/
|
||||
private boolean displaySpeed = true;
|
||||
|
||||
/**
|
||||
* true if activity has resumed and is on top
|
||||
*/
|
||||
private boolean activityOnTop = false;
|
||||
|
||||
/**
|
||||
* If true, the statistics for the current segment are shown, otherwise
|
||||
* for the full track.
|
||||
*/
|
||||
private boolean showCurrentSegment = false;
|
||||
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
private TrackDataHub dataHub;
|
||||
|
||||
/**
|
||||
* A runnable for posting to the UI thread. Will update the total time field.
|
||||
*/
|
||||
private final Runnable updateResults = new Runnable() {
|
||||
public void run() {
|
||||
updateTotalTime();
|
||||
if (dataHub.isRecordingSelected()) {
|
||||
utils.setTime(R.id.total_time_register,
|
||||
System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -121,13 +83,11 @@ public class StatsActivity extends Activity
|
||||
public void run() {
|
||||
Log.i(TAG, "Started UI update thread");
|
||||
while (MyTracks.getInstance().isRecording()) {
|
||||
long sleeptime = 1000;
|
||||
runOnUiThread(updateResults);
|
||||
try {
|
||||
Thread.sleep(sleeptime);
|
||||
Thread.sleep(1000L);
|
||||
} catch (InterruptedException e) {
|
||||
Log.w(TAG,
|
||||
"StatsActivity: Caught exception on sleep.", e);
|
||||
Log.w(TAG, "StatsActivity: Caught exception on sleep.", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -140,9 +100,9 @@ public class StatsActivity extends Activity
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
dataHub = MyTracks.getInstance().getDataHub();
|
||||
utils = new StatsUtilities(this);
|
||||
providerUtils = new MyTracksProviderUtilsImpl(getContentResolver());
|
||||
|
||||
|
||||
// The volume we want to control is the Text-To-Speech volume
|
||||
int volumeStream =
|
||||
new StatusAnnouncerFactory(ApiFeatures.getInstance()).getVolumeStream();
|
||||
@@ -153,40 +113,10 @@ public class StatsActivity extends Activity
|
||||
|
||||
setContentView(R.layout.stats);
|
||||
|
||||
Handler contentHandler = new Handler();
|
||||
observer = new ContentObserver(contentHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
Log.d(TAG, "StatsActivity: ContentObserver.onChange");
|
||||
restoreStats();
|
||||
super.onChange(selfChange);
|
||||
}
|
||||
};
|
||||
|
||||
ScrollView sv = ((ScrollView) findViewById(R.id.scrolly));
|
||||
sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
|
||||
|
||||
SharedPreferences preferences =
|
||||
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
||||
if (preferences != null) {
|
||||
selectedTrackId = preferences.getLong(
|
||||
getString(R.string.selected_track_key), -1);
|
||||
recordingTrackId = preferences.getLong(
|
||||
getString(R.string.recording_track_key), -1);
|
||||
metricUnits = preferences.getBoolean(
|
||||
getString(R.string.metric_units_key), true);
|
||||
displaySpeed =
|
||||
preferences.getBoolean(getString(R.string.report_speed_key), true);
|
||||
checkLiveTrack();
|
||||
restoreStats();
|
||||
showUnknownLocation();
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
utils.setMetricUnits(metricUnits);
|
||||
utils.setReportSpeed(displaySpeed);
|
||||
utils.updateUnits();
|
||||
utils.setSpeedLabel(R.id.speed_label, R.string.speed, R.string.pace_label);
|
||||
utils.setSpeedLabels();
|
||||
showUnknownLocation();
|
||||
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||
@@ -196,74 +126,49 @@ public class StatsActivity extends Activity
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
unregisterLocationListener();
|
||||
protected void onStart() {
|
||||
dataHub.registerTrackDataListener(this);
|
||||
|
||||
super.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
dataHub.unregisterTrackDataListener(this);
|
||||
|
||||
if (thread != null) {
|
||||
thread.interrupt();
|
||||
thread = null;
|
||||
}
|
||||
getContentResolver().unregisterContentObserver(observer);
|
||||
activityOnTop = false;
|
||||
super.onPause();
|
||||
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
activityOnTop = true;
|
||||
checkLiveTrack();
|
||||
restoreStats();
|
||||
showUnknownLocation();
|
||||
super.onResume();
|
||||
public boolean onUnitsChanged(boolean metric) {
|
||||
utils.setMetricUnits(metric);
|
||||
updateLabels();
|
||||
|
||||
return true; // Reload data
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(
|
||||
final SharedPreferences sharedPreferences, final String key) {
|
||||
Log.d(TAG,
|
||||
"StatsActivity: onSharedPreferences changed " + key);
|
||||
if (key != null) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (key.equals(getString(R.string.selected_track_key))) {
|
||||
selectedTrackId =
|
||||
sharedPreferences.getLong(
|
||||
getString(R.string.selected_track_key),
|
||||
-1);
|
||||
checkLiveTrack();
|
||||
restoreStats();
|
||||
showUnknownLocation();
|
||||
} else if (key.equals(getString(R.string.recording_track_key))) {
|
||||
recordingTrackId =
|
||||
sharedPreferences.getLong(
|
||||
getString(R.string.recording_track_key),
|
||||
-1);
|
||||
checkLiveTrack();
|
||||
restoreStats();
|
||||
showUnknownLocation();
|
||||
} else if (key.equals(getString(R.string.metric_units_key))) {
|
||||
metricUnits =
|
||||
sharedPreferences.getBoolean(
|
||||
getString(R.string.metric_units_key), true);
|
||||
utils.setMetricUnits(metricUnits);
|
||||
utils.updateUnits();
|
||||
restoreStats();
|
||||
} else if (key.equals(getString(R.string.report_speed_key))) {
|
||||
displaySpeed =
|
||||
sharedPreferences.getBoolean(
|
||||
getString(R.string.report_speed_key),
|
||||
true);
|
||||
utils.setReportSpeed(displaySpeed);
|
||||
utils.updateUnits();
|
||||
utils.setSpeedLabel(
|
||||
R.id.speed_label, R.string.speed, R.string.pace_label);
|
||||
Log.w(TAG, "Setting speed labels");
|
||||
utils.setSpeedLabels();
|
||||
restoreStats();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
public boolean onReportSpeedChanged(boolean displaySpeed) {
|
||||
utils.setReportSpeed(displaySpeed);
|
||||
updateLabels();
|
||||
|
||||
return true; // Reload data
|
||||
}
|
||||
|
||||
private void updateLabels() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
utils.updateUnits();
|
||||
utils.setSpeedLabel(R.id.speed_label, R.string.speed, R.string.pace_label);
|
||||
utils.setSpeedLabels();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -291,137 +196,12 @@ public class StatsActivity extends Activity
|
||||
switch (item.getItemId()) {
|
||||
case Constants.MENU_CURRENT_SEGMENT:
|
||||
showCurrentSegment = !showCurrentSegment;
|
||||
restoreStats();
|
||||
// TODO: Re-read only the data that interests us
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private final LocationListener locationListener = new LocationListener() {
|
||||
@Override
|
||||
public void onLocationChanged(Location l) {
|
||||
if (selectedTrackIsRecording()) {
|
||||
showLocation(l);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderDisabled(String provider) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabled(String provider) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers to receive location updates from the GPS location provider.
|
||||
*/
|
||||
private void registerLocationListener() {
|
||||
LocationManager locationManager =
|
||||
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
||||
if (locationManager != null) {
|
||||
LocationProvider gpsProvider =
|
||||
locationManager.getProvider(Constants.GPS_PROVIDER);
|
||||
if (gpsProvider == null) {
|
||||
Toast.makeText(this, getString(R.string.error_no_gps_location_provider),
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
} else {
|
||||
Log.d(TAG, "StatsActivity: Using location provider "
|
||||
+ gpsProvider.getName());
|
||||
}
|
||||
locationManager.requestLocationUpdates(gpsProvider.getName(),
|
||||
0/*minTime*/, 0/*minDist*/, locationListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters all location listener.
|
||||
*/
|
||||
private void unregisterLocationListener() {
|
||||
LocationManager locationManager =
|
||||
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
||||
if (locationManager != null) {
|
||||
locationManager.removeUpdates(locationListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the selected track is the currently recording track
|
||||
*/
|
||||
private boolean selectedTrackIsRecording() {
|
||||
return MyTracks.getInstance().isRecording()
|
||||
&& selectedTrackId == recordingTrackId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads values for selected tracks from provider and update the UI.
|
||||
*/
|
||||
private void restoreStats() {
|
||||
if (selectedTrackId < 0) {
|
||||
utils.setAllToUnknown();
|
||||
return;
|
||||
}
|
||||
|
||||
Track track = providerUtils.getTrack(selectedTrackId);
|
||||
if (track == null || track.getStatistics() == null) {
|
||||
utils.setAllToUnknown();
|
||||
return;
|
||||
}
|
||||
|
||||
startTime = track.getStatistics().getStartTime();
|
||||
if (!selectedTrackIsRecording()) {
|
||||
utils.setTime(R.id.total_time_register,
|
||||
track.getStatistics().getTotalTime());
|
||||
}
|
||||
utils.setAllStats(track.getStatistics());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this activity needs to update live track data or not.
|
||||
* If so, make sure that:
|
||||
* a) a thread keeps updating the total time
|
||||
* b) a location listener is registered
|
||||
* c) a content observer is registered
|
||||
* Otherwise unregister listeners, observers, and kill update thread.
|
||||
*/
|
||||
private void checkLiveTrack() {
|
||||
final boolean isRecording = selectedTrackIsRecording();
|
||||
final boolean startThread =
|
||||
(thread == null) && isRecording && activityOnTop;
|
||||
final boolean killThread =
|
||||
(thread != null) && (!isRecording || !activityOnTop);
|
||||
if (startThread) {
|
||||
thread = new UIUpdateThread();
|
||||
thread.start();
|
||||
getContentResolver().registerContentObserver(
|
||||
TracksColumns.CONTENT_URI, false, observer);
|
||||
getContentResolver().registerContentObserver(
|
||||
WaypointsColumns.CONTENT_URI, false, observer);
|
||||
registerLocationListener();
|
||||
} else if (killThread) {
|
||||
thread.interrupt();
|
||||
thread = null;
|
||||
getContentResolver().unregisterContentObserver(observer);
|
||||
unregisterLocationListener();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTotalTime() {
|
||||
if (selectedTrackIsRecording()) {
|
||||
utils.setTime(R.id.total_time_register,
|
||||
System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the given location fields (latitude, longitude, altitude) and all
|
||||
* other fields.
|
||||
@@ -441,4 +221,112 @@ public class StatsActivity extends Activity
|
||||
utils.setUnknown(R.id.longitude_register);
|
||||
utils.setUnknown(R.id.speed_register);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectedTrackChanged(Track track, boolean isRecording) {
|
||||
/*
|
||||
* Checks if this activity needs to update live track data or not.
|
||||
* If so, make sure that:
|
||||
* a) a thread keeps updating the total time
|
||||
* b) a location listener is registered
|
||||
* c) a content observer is registered
|
||||
* Otherwise unregister listeners, observers, and kill update thread.
|
||||
*/
|
||||
final boolean startThread = (thread == null) && isRecording;
|
||||
final boolean killThread = (thread != null) && (!isRecording);
|
||||
if (startThread) {
|
||||
thread = new UIUpdateThread();
|
||||
thread.start();
|
||||
} else if (killThread) {
|
||||
thread.interrupt();
|
||||
thread = null;
|
||||
}
|
||||
|
||||
if (track == null || track.getStatistics() == null) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
utils.setAllToUnknown();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentLocationChanged(Location loc) {
|
||||
if (dataHub.isRecordingSelected()) {
|
||||
showLocation(loc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentHeadingChanged(double heading) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderStateChange(ProviderState state) {
|
||||
switch (state) {
|
||||
case DISABLED:
|
||||
case NO_FIX:
|
||||
showUnknownLocation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackUpdated(final Track track) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startTime = track.getStatistics().getStartTime();
|
||||
if (!dataHub.isRecordingSelected()) {
|
||||
utils.setTime(R.id.total_time_register,
|
||||
track.getStatistics().getTotalTime());
|
||||
showUnknownLocation();
|
||||
}
|
||||
utils.setAllStats(track.getStatistics());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearWaypoints() {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypoint(Waypoint wpt) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypointsDone() {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTrackPoints() {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewTrackPoint(Location loc) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSegmentSplit() {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSampledOutTrackPoint(Location loc) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewTrackPointsDone() {
|
||||
// We don't care.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -607,7 +607,7 @@ public class TrackDataHub {
|
||||
if (key.equals(RECORDING_TRACK_KEY)) {
|
||||
recordingTrackId = sharedPreferences.getLong(RECORDING_TRACK_KEY, -1);
|
||||
} else if (key.equals(MIN_REQUIRED_ACCURACY_KEY)) {
|
||||
minRequiredAccuracy = sharedPreferences.getInt(RECORDING_TRACK_KEY,
|
||||
minRequiredAccuracy = sharedPreferences.getInt(MIN_REQUIRED_ACCURACY_KEY,
|
||||
Constants.DEFAULT_MIN_REQUIRED_ACCURACY);
|
||||
} else if (key.equals(METRIC_UNITS_KEY)) {
|
||||
useMetricUnits = sharedPreferences.getBoolean(METRIC_UNITS_KEY, true);
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.google.android.apps.mytracks.services.sensors.SensorManager;
|
||||
import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory;
|
||||
import com.google.android.apps.mytracks.services.tasks.PeriodicTask;
|
||||
import com.google.android.apps.mytracks.services.tasks.PeriodicTaskExecuter;
|
||||
import com.google.android.apps.mytracks.services.tasks.SplitTask;
|
||||
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
|
||||
@@ -190,8 +191,6 @@ public class TrackRecordingService extends Service implements LocationListener {
|
||||
/**
|
||||
* The frequency of status announcements.
|
||||
*/
|
||||
private int announcementFrequency = -1;
|
||||
|
||||
private ExecutorService executerServce;
|
||||
|
||||
/*
|
||||
@@ -667,6 +666,8 @@ public class TrackRecordingService extends Service implements LocationListener {
|
||||
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
|
||||
|
||||
setUpAnnouncer();
|
||||
this.splitExecuter = new PeriodicTaskExecuter(this, new SplitTask());
|
||||
prefManager = new PreferenceManager(this);
|
||||
registerLocationListener();
|
||||
|
||||
@@ -702,32 +703,20 @@ public class TrackRecordingService extends Service implements LocationListener {
|
||||
private void setUpAnnouncer() {
|
||||
Log.d(TAG, "TrackRecordingService.setUpAnnouncer: "
|
||||
+ announcementExecuter);
|
||||
if (announcementFrequency != -1 && recordingTrackId != -1) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (announcementExecuter == null) {
|
||||
StatusAnnouncerFactory statusAnnouncerFactory =
|
||||
new StatusAnnouncerFactory(ApiFeatures.getInstance());
|
||||
PeriodicTask announcer = statusAnnouncerFactory.create(
|
||||
TrackRecordingService.this);
|
||||
if (announcer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Either use TaskExecuterManager everywhere, or get rid of it
|
||||
announcementExecuter = new PeriodicTaskExecuter(
|
||||
TrackRecordingService.this, announcer);
|
||||
}
|
||||
announcementExecuter.setTaskFrequency(announcementFrequency * 60000);
|
||||
}
|
||||
});
|
||||
StatusAnnouncerFactory statusAnnouncerFactory =
|
||||
new StatusAnnouncerFactory(ApiFeatures.getInstance());
|
||||
PeriodicTask announcer = statusAnnouncerFactory.create(
|
||||
TrackRecordingService.this);
|
||||
if (announcer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
announcementExecuter = new PeriodicTaskExecuter(
|
||||
TrackRecordingService.this, announcer);
|
||||
}
|
||||
|
||||
private void shutdownAnnouncer() {
|
||||
Log.d(TAG, "TrackRecordingService.shutdownAnnouncer: "
|
||||
+ announcementExecuter);
|
||||
private void shutdownExecuters() {
|
||||
Log.d(TAG, "TrackRecordingService.shutdownExecuters");
|
||||
if (announcementExecuter != null) {
|
||||
try {
|
||||
announcementExecuter.shutdown();
|
||||
@@ -735,6 +724,13 @@ public class TrackRecordingService extends Service implements LocationListener {
|
||||
announcementExecuter = null;
|
||||
}
|
||||
}
|
||||
if (splitExecuter != null) {
|
||||
try {
|
||||
splitExecuter.shutdown();
|
||||
} finally {
|
||||
splitExecuter = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -750,11 +746,7 @@ public class TrackRecordingService extends Service implements LocationListener {
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
unregisterLocationListener();
|
||||
shutdownAnnouncer();
|
||||
announcementExecuter.shutdown();
|
||||
announcementExecuter = null;
|
||||
splitExecuter.shutdown();
|
||||
splitExecuter = null;
|
||||
shutdownExecuters();
|
||||
if (sensorManager != null) {
|
||||
sensorManager.shutdown();
|
||||
sensorManager = null;
|
||||
@@ -1109,12 +1101,9 @@ public class TrackRecordingService extends Service implements LocationListener {
|
||||
waypointStatsBuilder = new TripStatisticsBuilder(startTime);
|
||||
waypointStatsBuilder.setMinRecordingDistance(minRecordingDistance);
|
||||
currentWaypointId = insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
|
||||
setUpAnnouncer();
|
||||
length = 0;
|
||||
showNotification();
|
||||
registerLocationListener();
|
||||
announcementExecuter.restore();
|
||||
splitExecuter.restore();
|
||||
sensorManager = SensorManagerFactory.getSensorManager(this);
|
||||
if (sensorManager != null) {
|
||||
sensorManager.onStartTrack();
|
||||
@@ -1129,6 +1118,8 @@ public class TrackRecordingService extends Service implements LocationListener {
|
||||
// Notify the world that we're now recording.
|
||||
sendTrackBroadcast(
|
||||
R.string.track_started_broadcast_action, recordingTrackId);
|
||||
announcementExecuter.restore();
|
||||
splitExecuter.restore();
|
||||
|
||||
return recordingTrackId;
|
||||
}
|
||||
@@ -1139,7 +1130,7 @@ public class TrackRecordingService extends Service implements LocationListener {
|
||||
throw new IllegalStateException("No recording track in progress!");
|
||||
}
|
||||
|
||||
shutdownAnnouncer();
|
||||
shutdownExecuters();
|
||||
isRecording = false;
|
||||
Track recordingTrack = providerUtils.getTrack(recordingTrackId);
|
||||
if (recordingTrack != null) {
|
||||
@@ -1199,19 +1190,6 @@ public class TrackRecordingService extends Service implements LocationListener {
|
||||
this.recordingTrackId = recordingTrackId;
|
||||
}
|
||||
|
||||
public int getAnnouncementFrequency() {
|
||||
return announcementFrequency;
|
||||
}
|
||||
|
||||
public void setAnnouncementFrequency(int announcementFrequency) {
|
||||
this.announcementFrequency = announcementFrequency;
|
||||
if (announcementFrequency == -1) {
|
||||
shutdownAnnouncer();
|
||||
} else {
|
||||
setUpAnnouncer();
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxRecordingDistance() {
|
||||
return maxRecordingDistance;
|
||||
}
|
||||
@@ -1257,12 +1235,24 @@ public class TrackRecordingService extends Service implements LocationListener {
|
||||
this.autoResumeTrackTimeout = autoResumeTrackTimeout;
|
||||
}
|
||||
|
||||
public void setAnnouncementFrequency(int announcementFrequency) {
|
||||
if (announcementExecuter != null) {
|
||||
announcementExecuter.setTaskFrequency(announcementFrequency);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSplitFrequency(int frequency) {
|
||||
splitExecuter.setTaskFrequency(frequency);
|
||||
if (splitExecuter != null) {
|
||||
splitExecuter.setTaskFrequency(frequency);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMetricUnits(boolean metric) {
|
||||
announcementExecuter.setMetricUnits(metric);
|
||||
splitExecuter.setMetricUnits(metric);
|
||||
if (announcementExecuter != null) {
|
||||
announcementExecuter.setMetricUnits(metric);
|
||||
}
|
||||
if (splitExecuter != null) {
|
||||
splitExecuter.setMetricUnits(metric);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-27
@@ -61,10 +61,29 @@ public class PeriodicTaskExecuter {
|
||||
* Restores the manager.
|
||||
*/
|
||||
public void restore() {
|
||||
if ((isTimeFrequency()) && (timerExecuter != null)) {
|
||||
timerExecuter.scheduleTask(taskFrequency * 60000);
|
||||
// TODO: Decouple service from this class once and forever.
|
||||
if (!service.isRecording()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isTimeFrequency()) {
|
||||
if (timerExecuter != null) {
|
||||
timerExecuter.shutdown();
|
||||
timerExecuter = null;
|
||||
}
|
||||
}
|
||||
if (taskFrequency == 0) {
|
||||
return;
|
||||
}
|
||||
if (isTimeFrequency()) {
|
||||
if (timerExecuter == null) {
|
||||
timerExecuter = new TimerTaskExecuter(task, service);
|
||||
}
|
||||
timerExecuter.scheduleTask(taskFrequency * 60000);
|
||||
} else {
|
||||
// For distance based splits.
|
||||
calculateNextTaskDistance();
|
||||
}
|
||||
calculateNextTaskDistance();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,30 +159,7 @@ public class PeriodicTaskExecuter {
|
||||
public void setTaskFrequency(int taskFrequency) {
|
||||
Log.d(TAG, "setTaskFrequency: taskFrequency = " + taskFrequency);
|
||||
this.taskFrequency = taskFrequency;
|
||||
|
||||
// TODO: Decouple service from this class once and forever.
|
||||
if (!service.isRecording()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isTimeFrequency()) {
|
||||
if (timerExecuter != null) {
|
||||
timerExecuter.shutdown();
|
||||
timerExecuter = null;
|
||||
}
|
||||
}
|
||||
if (taskFrequency == 0) {
|
||||
return;
|
||||
}
|
||||
if (isTimeFrequency()) {
|
||||
if (timerExecuter == null) {
|
||||
timerExecuter = new TimerTaskExecuter(task, service);
|
||||
}
|
||||
timerExecuter.scheduleTask(taskFrequency * 60000);
|
||||
} else {
|
||||
// For distance based splits.
|
||||
calculateNextTaskDistance();
|
||||
}
|
||||
restore();
|
||||
}
|
||||
|
||||
public void setMetricUnits(boolean metricUnits) {
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ import com.google.android.apps.mytracks.services.TrackRecordingService;
|
||||
* A simple task to insert statistics markers every n minutes.
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class TimeSplitTask implements PeriodicTask {
|
||||
public class SplitTask implements PeriodicTask {
|
||||
|
||||
@Override
|
||||
public void run(TrackRecordingService service) {
|
||||
+1
-2
@@ -19,7 +19,6 @@ package com.google.android.apps.mytracks.services.tasks;
|
||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.MyTracksSettings;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingService;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
@@ -177,7 +176,7 @@ public class StatusAnnouncerTask implements PeriodicTask {
|
||||
// @VisibleForTesting
|
||||
protected String getAnnouncement(TripStatistics stats) {
|
||||
SharedPreferences preferences =
|
||||
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
||||
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||
boolean metricUnits = true;
|
||||
boolean reportSpeed = true;
|
||||
if (preferences != null) {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.services;
|
||||
package com.google.android.apps.mytracks.services.tasks;
|
||||
|
||||
import com.google.android.apps.mytracks.services.tasks.PeriodicTask;
|
||||
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.services;
|
||||
package com.google.android.apps.mytracks.services.tasks;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.capture;
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
Reference in New Issue
Block a user