forked from upstream-mirrors/OpenTracks
Kill second head.
This commit is contained in:
@@ -5,3 +5,5 @@ syntax:glob
|
|||||||
*/proguard/**
|
*/proguard/**
|
||||||
.metadata
|
.metadata
|
||||||
MyTracksTest/annotations.log
|
MyTracksTest/annotations.log
|
||||||
|
**/*.pyc
|
||||||
|
**/*.pyo
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ limitations under the License.
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.google.android.maps.mytracks"
|
package="com.google.android.maps.mytracks"
|
||||||
android:installLocation="auto"
|
android:installLocation="auto"
|
||||||
android:versionCode="24"
|
android:versionCode="27"
|
||||||
android:versionName="1.1.1">
|
android:versionName="1.1.4">
|
||||||
<application android:icon="@drawable/arrow_icon"
|
<application android:icon="@drawable/arrow_icon"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:backupAgent="com.google.android.apps.mytracks.io.backup.MyTracksBackupAgent">
|
android:backupAgent="com.google.android.apps.mytracks.io.backup.MyTracksBackupAgent">
|
||||||
@@ -52,23 +52,28 @@ limitations under the License.
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name="com.google.android.apps.mytracks.MyTracksMap"
|
<activity android:name="com.google.android.apps.mytracks.MapActivity"
|
||||||
android:label="MyTracks"
|
android:label="MyTracks"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<activity android:name="com.google.android.apps.mytracks.MyTracksList"
|
<activity android:name="com.google.android.apps.mytracks.MyMapsList"
|
||||||
|
android:label="@string/map_list_title"
|
||||||
|
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|fontScale"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
|
<activity android:name="com.google.android.apps.mytracks.TrackList"
|
||||||
android:label="Recorded Tracks" />
|
android:label="Recorded Tracks" />
|
||||||
|
|
||||||
<activity android:name="com.google.android.apps.mytracks.MyTracksWaypointsList"
|
<activity android:name="com.google.android.apps.mytracks.WaypointsList"
|
||||||
android:label="Recorded Waypoints" />
|
android:label="Recorded Waypoints" />
|
||||||
|
|
||||||
<activity android:name="com.google.android.apps.mytracks.MyTracksDetails"
|
<activity android:name="com.google.android.apps.mytracks.TrackDetails"
|
||||||
android:label="@string/trackdetails_title" />
|
android:label="@string/trackdetails_title" />
|
||||||
|
|
||||||
<activity android:name="com.google.android.apps.mytracks.MyTracksWaypointDetails"
|
<activity android:name="com.google.android.apps.mytracks.WaypointDetails"
|
||||||
android:label="@string/waypointdetails_title" />
|
android:label="@string/waypointdetails_title" />
|
||||||
|
|
||||||
<activity android:name="com.google.android.apps.mytracks.MyTracksSettings"
|
<activity android:name="com.google.android.apps.mytracks.SettingsActivity"
|
||||||
android:label="@string/mytracks_settings" />
|
android:label="@string/mytracks_settings" />
|
||||||
|
|
||||||
<activity android:name="com.google.android.apps.mytracks.AggregatedStatsActivity"
|
<activity android:name="com.google.android.apps.mytracks.AggregatedStatsActivity"
|
||||||
@@ -96,7 +101,7 @@ limitations under the License.
|
|||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:permission="com.google.android.apps.mytracks.WRITE_TRACK_DATA" />
|
android:permission="com.google.android.apps.mytracks.WRITE_TRACK_DATA" />
|
||||||
|
|
||||||
<receiver android:name="com.google.android.apps.mytracks.MyTracksReceiver">
|
<receiver android:name="com.google.android.apps.mytracks.BootReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
@@ -159,14 +164,15 @@ limitations under the License.
|
|||||||
<!-- Features required -->
|
<!-- Features required -->
|
||||||
<uses-feature android:name="android.hardware.location" android:required="true"/>
|
<uses-feature android:name="android.hardware.location" android:required="true"/>
|
||||||
<uses-feature android:name="android.hardware.location.gps" android:required="true"/>
|
<uses-feature android:name="android.hardware.location.gps" android:required="true"/>
|
||||||
<uses-feature android:name="android.hardware.touchscreen" android:required="true"/>
|
|
||||||
|
|
||||||
<!-- Features optional -->
|
<!-- Features optional -->
|
||||||
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
|
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
|
||||||
|
<uses-feature android:name="android.hardware.faketouch" android:required="false"/>
|
||||||
<uses-feature android:name="android.hardware.location.network" android:required="false"/>
|
<uses-feature android:name="android.hardware.location.network" android:required="false"/>
|
||||||
<uses-feature android:name="android.hardware.sensor.compass" android:required="false"/>
|
<uses-feature android:name="android.hardware.sensor.compass" android:required="false"/>
|
||||||
<uses-feature android:name="android.hardware.telephony" android:required="false"/>
|
<uses-feature android:name="android.hardware.telephony" android:required="false"/>
|
||||||
<uses-feature android:name="android.hardware.telephony.gsm" android:required="false"/>
|
<uses-feature android:name="android.hardware.telephony.gsm" android:required="false"/>
|
||||||
|
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
|
||||||
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false"/>
|
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false"/>
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="3"/>
|
<uses-sdk android:minSdkVersion="3"/>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
# Indicates whether an apk should be generated for each density.
|
# Indicates whether an apk should be generated for each density.
|
||||||
split.density=false
|
split.density=false
|
||||||
# Project target.
|
# Project target.
|
||||||
target=Google Inc.:Google APIs:9
|
target=Google Inc.:Google APIs:11
|
||||||
android.library.reference.1=../MyTracksLib/
|
android.library.reference.1=../MyTracksLib/
|
||||||
|
|
||||||
# ProGuard is turned off while we investigate the removal of code that
|
# ProGuard is turned off while we investigate the removal of code that
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
The libraries contained here in binary format are licensed according to their
|
||||||
|
own licenses, which allow their usage for the My Tracks application. Any other
|
||||||
|
applications that wish to use these files should consult the appropriate
|
||||||
|
licenses or the JAR's authors.
|
||||||
|
|
||||||
|
References are provided to the libraries:
|
||||||
|
|
||||||
|
accounts.jar (Android accounts library):
|
||||||
|
http://code.google.com/p/libs-for-android/wiki/AccountsLibrary
|
||||||
|
|
||||||
|
google-api-client-*.jar (GData client):
|
||||||
|
http://code.google.com/p/google-api-java-client/
|
||||||
|
|
||||||
|
google-common.jar,
|
||||||
|
googleloginclient-helper.jar,
|
||||||
|
libmymaps.jar (Google My Maps upload library):
|
||||||
|
Licensed exclusively for use in My Tracks and derived Android applications.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 676 B |
Binary file not shown.
|
After Width: | Height: | Size: 766 B |
@@ -0,0 +1,103 @@
|
|||||||
|
<?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.
|
||||||
|
-->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apl/res/com.google.android.maps"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent">
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/list_bar"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:padding="3dip">
|
||||||
|
<TextView android:id="@+id/message"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="16dip"
|
||||||
|
android:textColor="#fff"
|
||||||
|
android:text="@string/select_map_message"
|
||||||
|
android:layout_weight="0"/>
|
||||||
|
</LinearLayout>
|
||||||
|
<ListView android:id="@+id/maplist"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
<TextView android:id="@+id/mapslist_empty"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="3dip"
|
||||||
|
android:textSize="16dip"
|
||||||
|
android:textColor="#c00"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="@string/mapslist_no_maps_available"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
<TextView android:id="@+id/failed"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="3dip"
|
||||||
|
android:textSize="16dip"
|
||||||
|
android:textColor="#c00"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="@string/maps_list_failed"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/list_bar"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:padding="3dip">
|
||||||
|
<LinearLayout android:id="@+id/loading"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="3dip"
|
||||||
|
android:layout_gravity="center">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
<ProgressBar
|
||||||
|
android:layout_height="20dip"
|
||||||
|
android:layout_width="20dip"
|
||||||
|
android:layout_gravity="center"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:paddingLeft="3dip"
|
||||||
|
android:textSize="16dip"
|
||||||
|
android:textColor="#fff"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="@string/maps_list_loading"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
</LinearLayout>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
@@ -41,6 +41,39 @@ limitations under the License.
|
|||||||
android:stretchColumns="1"
|
android:stretchColumns="1"
|
||||||
android:layout_marginTop="5dip"
|
android:layout_marginTop="5dip"
|
||||||
android:layout_marginLeft="5dip">
|
android:layout_marginLeft="5dip">
|
||||||
|
|
||||||
|
<!-- My Maps -->
|
||||||
|
<TableRow>
|
||||||
|
<ImageView android:src="@drawable/mymaps_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginLeft="10dip">
|
||||||
|
<CheckBox android:id="@+id/sendtogoogle_google_mymaps"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/sendtogoogle_google_mymaps"
|
||||||
|
android:textSize="20dip"
|
||||||
|
android:checked="true"/>
|
||||||
|
<RadioGroup android:id="@+id/sendtogoogle_group_mymaps"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<RadioButton android:id="@+id/sendtogoogle_create_new_map"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/sendtogoogle_create_new_map"/>
|
||||||
|
<RadioButton android:id="@+id/sendtogoogle_pick_existing_map"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/sendtogoogle_pick_existing_map"/>
|
||||||
|
</RadioGroup>
|
||||||
|
</LinearLayout>
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<!-- Fusion Tables -->
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<ImageView android:src="@drawable/googledocs_icon"
|
<ImageView android:src="@drawable/googledocs_icon"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -58,6 +91,8 @@ limitations under the License.
|
|||||||
android:checked="true"/>
|
android:checked="true"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
|
<!-- Google Docs -->
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<ImageView android:src="@drawable/googledocs_icon"
|
<ImageView android:src="@drawable/googledocs_icon"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2011 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.
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
This layout is used as the content view for the send-to-Google result dialog.
|
||||||
|
It is used to summarize the results of uploading track data to one or more
|
||||||
|
services.
|
||||||
|
-->
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="5dip"
|
||||||
|
android:paddingBottom="5dip"
|
||||||
|
android:paddingLeft="14dip"
|
||||||
|
android:paddingRight="14dip"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/status_track_upload_status"
|
||||||
|
style="?android:attr/textAppearanceLarge"/>
|
||||||
|
<TableLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal">
|
||||||
|
<!-- We don't want a divider, so we set its color to transparent. -->
|
||||||
|
<!-- We do this explicitly, rather than with a color resource, because -->
|
||||||
|
<!-- an apparent bug causes the divider to be wildly misrendered on -->
|
||||||
|
<!-- a Mini X10 running 2.1. -->
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/send_to_google_result_list"
|
||||||
|
android:clickable="false"
|
||||||
|
android:paddingTop="10dip"
|
||||||
|
android:paddingBottom="10dip"
|
||||||
|
android:divider="#00000000"/>
|
||||||
|
</TableLayout>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/send_to_google_result_comment"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/status_mymap_info"
|
||||||
|
android:visibility="gone"
|
||||||
|
style="?android:attr/textAppearanceSmall"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/send_to_google_result_error"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/error_please_try_again_later"
|
||||||
|
android:visibility="gone"
|
||||||
|
style="?android:attr/textAppearanceLarge"/>
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2011 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.
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
This layout represents the result of sending track data to a single service.
|
||||||
|
It will be instantiated by a custom ListAdapter - once for each service to
|
||||||
|
which track data was uploaded.
|
||||||
|
-->
|
||||||
|
<TableRow
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/send_to_google_result_icon"
|
||||||
|
android:src="@drawable/success"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_gravity="top"/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/send_to_google_result_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Google Docs"
|
||||||
|
style="?android:attr/textAppearanceMedium"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/send_to_google_result_url"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="http://google.com"
|
||||||
|
style="?android:attr/textAppearanceSmall"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</TableRow>
|
||||||
@@ -112,9 +112,9 @@ limitations under the License.
|
|||||||
<item>3.1 miles (senyal GPS pobre)</item>
|
<item>3.1 miles (senyal GPS pobre)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Split frequency -->
|
<!-- Task frequency -->
|
||||||
<string-array name="split_frequency_options">
|
<string-array name="task_frequency_options">
|
||||||
<item>Sense divisió</item>
|
<item>Inactiu</item>
|
||||||
<item>100 km</item>
|
<item>100 km</item>
|
||||||
<item>50 km</item>
|
<item>50 km</item>
|
||||||
<item>25 km</item>
|
<item>25 km</item>
|
||||||
@@ -130,8 +130,8 @@ limitations under the License.
|
|||||||
<item>1 min</item>
|
<item>1 min</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="task_frequency_options_ft">
|
||||||
<item>No splitting</item>
|
<item>Inactiu</item>
|
||||||
<item>100 mi</item>
|
<item>100 mi</item>
|
||||||
<item>50 mi</item>
|
<item>50 mi</item>
|
||||||
<item>25 mi</item>
|
<item>25 mi</item>
|
||||||
@@ -286,6 +286,8 @@ limitations under the License.
|
|||||||
|
|
||||||
<array name="sensor_type_options">
|
<array name="sensor_type_options">
|
||||||
<item>Cap</item>
|
<item>Cap</item>
|
||||||
|
<item>ANT+ Sensors</item>
|
||||||
|
<item>SRM ANT+ Bridge</item>
|
||||||
<item>Zephyr Bluetooth</item>
|
<item>Zephyr Bluetooth</item>
|
||||||
</array>
|
</array>
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,6 @@ limitations under the License.
|
|||||||
<string name="tracklist_all_tracks">Totes les rutes:</string>
|
<string name="tracklist_all_tracks">Totes les rutes:</string>
|
||||||
<string name="tracklist_this_track">Aquesta ruta</string>
|
<string name="tracklist_this_track">Aquesta ruta</string>
|
||||||
<string name="tracklist_share_track">Comparteix amb amics...</string>
|
<string name="tracklist_share_track">Comparteix amb amics...</string>
|
||||||
<string name="tracklist_share_linkfusion">Un enllaç a Google Fusion Table</string>
|
|
||||||
<string name="tracklist_share_gpx_file">Un fitxer GPX</string>
|
<string name="tracklist_share_gpx_file">Un fitxer GPX</string>
|
||||||
<string name="tracklist_share_kml_file">Un fitxer KML</string>
|
<string name="tracklist_share_kml_file">Un fitxer KML</string>
|
||||||
<string name="tracklist_share_csv_file">Un fitxer CSV</string>
|
<string name="tracklist_share_csv_file">Un fitxer CSV</string>
|
||||||
@@ -226,7 +225,6 @@ limitations under the License.
|
|||||||
<string name="settings_backup_to_sd_summary">Escriu una còpia completa de totes les rutes i els paràmetres a la targeta SD</string>
|
<string name="settings_backup_to_sd_summary">Escriu una còpia completa de totes les rutes i els paràmetres a la targeta SD</string>
|
||||||
<string name="settings_restore_from_sd">Restaura ara</string>
|
<string name="settings_restore_from_sd">Restaura ara</string>
|
||||||
<string name="settings_restore_from_sd_summary">Restaura totes les rutes i els paràmetres des de la targeta SD.</string>
|
<string name="settings_restore_from_sd_summary">Restaura totes les rutes i els paràmetres des de la targeta SD.</string>
|
||||||
<string name="settings_no_backup_while_recording">No es poden gestionar les còpies de seguretat mentre s\'enregistra una ruta.</string>
|
|
||||||
|
|
||||||
<!-- Backups -->
|
<!-- Backups -->
|
||||||
<string name="restore_overwrites_warning">La restauració d\'una còpia de seguretat des de la targeta SD sobreescriurà totes les rutes i paràmetres. Esteu segur?</string>
|
<string name="restore_overwrites_warning">La restauració d\'una còpia de seguretat des de la targeta SD sobreescriurà totes les rutes i paràmetres. Esteu segur?</string>
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ limitations under the License.
|
|||||||
<item>328 Fuß</item>
|
<item>328 Fuß</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<!-- Maximum recording distance -->
|
<!-- Maximum recording distance -->
|
||||||
<string-array name="max_recording_distance_options">
|
<string-array name="max_recording_distance_options">
|
||||||
<item>50 m</item>
|
<item>50 m</item>
|
||||||
@@ -113,9 +112,9 @@ limitations under the License.
|
|||||||
<item>3,1 Meilen (sehr schlechtes GPS-Signal)</item>
|
<item>3,1 Meilen (sehr schlechtes GPS-Signal)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Split frequency -->
|
<!-- Task frequency -->
|
||||||
<string-array name="split_frequency_options">
|
<string-array name="task_frequency_options">
|
||||||
<item>Nicht zerteilen</item>
|
<item>Aus</item>
|
||||||
<item>100 km</item>
|
<item>100 km</item>
|
||||||
<item>50 km</item>
|
<item>50 km</item>
|
||||||
<item>25 km</item>
|
<item>25 km</item>
|
||||||
@@ -132,7 +131,7 @@ limitations under the License.
|
|||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="split_frequency_options_ft">
|
||||||
<item>Nicht zerteilen</item>
|
<item>Aus</item>
|
||||||
<item>100 Meilen</item>
|
<item>100 Meilen</item>
|
||||||
<item>50 Meilen</item>
|
<item>50 Meilen</item>
|
||||||
<item>25 Meilen</item>
|
<item>25 Meilen</item>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ limitations under the License.
|
|||||||
<string name="switch_to_sat">Satellitenansicht</string>
|
<string name="switch_to_sat">Satellitenansicht</string>
|
||||||
<string name="switch_to_map">Kartenansicht</string>
|
<string name="switch_to_map">Kartenansicht</string>
|
||||||
<string name="mylocation">Mein Aufenthaltsort</string>
|
<string name="mylocation">Mein Aufenthaltsort</string>
|
||||||
|
<!--string name="list_tracks">Tracks</string-->
|
||||||
<string name="list_markers">Wegpunkte</string>
|
<string name="list_markers">Wegpunkte</string>
|
||||||
<string name="delete_all_tracks">Alle Tracks löschen</string>
|
<string name="delete_all_tracks">Alle Tracks löschen</string>
|
||||||
<string name="settings">Einstellungen</string>
|
<string name="settings">Einstellungen</string>
|
||||||
@@ -35,7 +36,7 @@ limitations under the License.
|
|||||||
<string name="error_no_location_manager">Es wurde kein Dienst zur Positionsermittlung auf diesem Gerät gefunden.</string>
|
<string name="error_no_location_manager">Es wurde kein Dienst zur Positionsermittlung auf diesem Gerät gefunden.</string>
|
||||||
<string name="error_no_gps_location_provider">Es wurde kein GPS-Empfänger auf diesem Gerät gefunden.</string>
|
<string name="error_no_gps_location_provider">Es wurde kein GPS-Empfänger auf diesem Gerät gefunden.</string>
|
||||||
<string name="error_sending_to_fusiontables">Beim Senden des Tracks an Google Fusion Tables ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
|
<string name="error_sending_to_fusiontables">Beim Senden des Tracks an Google Fusion Tables ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
|
||||||
<string name="error_sending_to_docs">Beim Senden des Tracks an Google Docs ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
|
<string name="error_sending_to_docs">Beim Senden des Tracks an Google Text & Tabellen ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
|
||||||
<string name="error_unable_to_start_recording">Start der Aufzeichnung fehlgeschlagen. Bitte versuche es noch einmal.</string>
|
<string name="error_unable_to_start_recording">Start der Aufzeichnung fehlgeschlagen. Bitte versuche es noch einmal.</string>
|
||||||
<string name="error_unable_to_stop_recording">Anhalten unmöglich. Bitte versuche es noch einmal.</string>
|
<string name="error_unable_to_stop_recording">Anhalten unmöglich. Bitte versuche es noch einmal.</string>
|
||||||
<string name="error_unable_to_read_file">Konnte Datei nicht lesen.</string>
|
<string name="error_unable_to_read_file">Konnte Datei nicht lesen.</string>
|
||||||
@@ -65,8 +66,8 @@ limitations under the License.
|
|||||||
<string name="progress_message_reading_track">Lese Track...</string>
|
<string name="progress_message_reading_track">Lese Track...</string>
|
||||||
<string name="progress_message_preparing_track">Bereite Track vor...</string>
|
<string name="progress_message_preparing_track">Bereite Track vor...</string>
|
||||||
<string name="progress_message_authenticating_fusiontables">Anmeldung bei Google Fusion Tables...</string>
|
<string name="progress_message_authenticating_fusiontables">Anmeldung bei Google Fusion Tables...</string>
|
||||||
<string name="progress_message_authenticating_docs">Anmeldung bei Google Docs...</string>
|
<string name="progress_message_authenticating_docs">Anmeldung bei Google Text & Tabellen...</string>
|
||||||
<string name="progress_message_sending_docs">Track wird an Google Docs gesendet...</string>
|
<string name="progress_message_sending_docs">Track wird an Google Text & Tabellen gesendet...</string>
|
||||||
<string name="progress_message_sending_fusiontables">Track wird an Google Fusion Tables gesendet...</string>
|
<string name="progress_message_sending_fusiontables">Track wird an Google Fusion Tables gesendet...</string>
|
||||||
<string name="progress_message_creating_fusiontable">Neue \'Fusion Tabelle\' wird erstellt...</string>
|
<string name="progress_message_creating_fusiontable">Neue \'Fusion Tabelle\' wird erstellt...</string>
|
||||||
<string name="import_progress_message">Importiere GPS-Track. Das kann ein wenig dauern.</string>
|
<string name="import_progress_message">Importiere GPS-Track. Das kann ein wenig dauern.</string>
|
||||||
@@ -92,10 +93,12 @@ limitations under the License.
|
|||||||
|
|
||||||
<!-- Used by the track recording service -->
|
<!-- Used by the track recording service -->
|
||||||
<string name="recording_your_track">Dein Track wird aufgezeichnet…</string>
|
<string name="recording_your_track">Dein Track wird aufgezeichnet…</string>
|
||||||
|
<!--string name="new_track">Track %d</string-->
|
||||||
|
|
||||||
<!-- Common -->
|
<!-- Common -->
|
||||||
<string name="no">Nein</string>
|
<string name="no">Nein</string>
|
||||||
<string name="yes">Ja</string>
|
<string name="yes">Ja</string>
|
||||||
|
<!--string name="ok">OK</string-->
|
||||||
<string name="error">Fehler</string>
|
<string name="error">Fehler</string>
|
||||||
<string name="success">Erfolgreich</string>
|
<string name="success">Erfolgreich</string>
|
||||||
<string name="waypoint">Wegpunkt</string>
|
<string name="waypoint">Wegpunkt</string>
|
||||||
@@ -106,13 +109,14 @@ limitations under the License.
|
|||||||
<string name="save">Sichern</string>
|
<string name="save">Sichern</string>
|
||||||
|
|
||||||
<!-- Placemark labels for start and end of track -->
|
<!-- Placemark labels for start and end of track -->
|
||||||
|
<!--string name="start">(Start)</string-->
|
||||||
<string name="end">(Ende)</string>
|
<string name="end">(Ende)</string>
|
||||||
|
|
||||||
<!-- TrackList -->
|
<!-- TrackList -->
|
||||||
<string name="tracklist_show_track">Anzeigen</string>
|
<string name="tracklist_show_track">Anzeigen</string>
|
||||||
<string name="tracklist_send_to_fusiontables">An eine Google Fusion Tables-Karte senden</string>
|
<string name="tracklist_send_to_fusiontables">An eine Google Fusion Tables-Karte senden</string>
|
||||||
<string name="tracklist_send_to_new_fusiontable">An eine neue Google Fusion Tables-Karte senden</string>
|
<string name="tracklist_send_to_new_fusiontable">An eine neue Google Fusion Tables-Karte senden</string>
|
||||||
<string name="tracklist_send_to_docs">An Google Docs senden</string>
|
<string name="tracklist_send_to_docs">An Google Text & Tabellen senden</string>
|
||||||
<string name="tracklist_send_to_google">An Google senden…</string>
|
<string name="tracklist_send_to_google">An Google senden…</string>
|
||||||
<string name="tracklist_delete_track">Vom Gerät löschen…</string>
|
<string name="tracklist_delete_track">Vom Gerät löschen…</string>
|
||||||
<string name="tracklist_edit_track">Bearbeiten</string>
|
<string name="tracklist_edit_track">Bearbeiten</string>
|
||||||
@@ -249,7 +253,7 @@ limitations under the License.
|
|||||||
<string name="send_track_subject">Ich möchte einen GPS-Track mit Dir teilen</string>
|
<string name="send_track_subject">Ich möchte einen GPS-Track mit Dir teilen</string>
|
||||||
<string name="send_track_body_format">Vielleicht interessierst Du Dich für diese Track:
|
<string name="send_track_body_format">Vielleicht interessierst Du Dich für diese Track:
|
||||||
|
|
||||||
%s.</string>
|
Der Track kann mit Google Earth oder anderer Karten-Software visualisiert werden.</string>
|
||||||
<string name="share_track">Track mit Freunden teilen</string>
|
<string name="share_track">Track mit Freunden teilen</string>
|
||||||
|
|
||||||
<!-- Visibility -->
|
<!-- Visibility -->
|
||||||
@@ -299,22 +303,37 @@ limitations under the License.
|
|||||||
<string name="hour">Stunde</string>
|
<string name="hour">Stunde</string>
|
||||||
<string name="hours">Stunden</string>
|
<string name="hours">Stunden</string>
|
||||||
<string name="hr">Std</string>
|
<string name="hr">Std</string>
|
||||||
|
<string name="min">Min</string>
|
||||||
<string name="minute">Minute</string>
|
<string name="minute">Minute</string>
|
||||||
<string name="minutes">Minuten</string>
|
<string name="minutes">Minuten</string>
|
||||||
<string name="second">Sekunde</string>
|
<string name="second">Sekunde</string>
|
||||||
<string name="seconds">Sekunden</string>
|
<string name="seconds">Sekunden</string>
|
||||||
|
<!--string name="milliseconds">ms</string-->
|
||||||
|
|
||||||
<!-- Distance -->
|
<!-- Distance -->
|
||||||
|
<!--string name="meter">m</string-->
|
||||||
|
<!--string name="kilometer">km</string-->
|
||||||
<string name="kilometers_long">Kilometer</string>
|
<string name="kilometers_long">Kilometer</string>
|
||||||
<string name="feet">Fuß</string>
|
<string name="feet">Fuß</string>
|
||||||
|
<!--string name="mile">mi</string-->
|
||||||
<string name="miles_long">Meilen</string>
|
<string name="miles_long">Meilen</string>
|
||||||
|
|
||||||
<!-- Speed and Pace -->
|
<!-- Speed and Pace -->
|
||||||
|
<!--string name="kilometer_per_hour">km/h</string-->
|
||||||
<string name="kilometer_per_hour_long">Kilometer pro Stunde</string>
|
<string name="kilometer_per_hour_long">Kilometer pro Stunde</string>
|
||||||
|
<!--string name="min_per_kilometer">min/km</string-->
|
||||||
<string name="per_kilometer">pro Kilometer</string>
|
<string name="per_kilometer">pro Kilometer</string>
|
||||||
|
<!--string name="mile_per_hour">mi/h</string-->
|
||||||
<string name="mile_per_hour_long">Meilen pro Stunde</string>
|
<string name="mile_per_hour_long">Meilen pro Stunde</string>
|
||||||
|
<!--string name="min_per_mile">min/mi</string-->
|
||||||
<string name="per_mile">pro Meile</string>
|
<string name="per_mile">pro Meile</string>
|
||||||
|
|
||||||
|
<!-- Sensors -->
|
||||||
|
<!--string name="watts">W</string-->
|
||||||
|
|
||||||
|
<!--string name="revolutions_per_minute">rpm</string-->
|
||||||
|
<!--string name="bpm">bpm</string-->
|
||||||
|
|
||||||
<!-- Stats Labels -->
|
<!-- Stats Labels -->
|
||||||
<string name="moving_time_label">Zeit in Bewegung</string>
|
<string name="moving_time_label">Zeit in Bewegung</string>
|
||||||
<string name="total_time_label">Gesamtzeit</string>
|
<string name="total_time_label">Gesamtzeit</string>
|
||||||
@@ -329,6 +348,7 @@ limitations under the License.
|
|||||||
<string name="cadence">Kadenz</string>
|
<string name="cadence">Kadenz</string>
|
||||||
<string name="heart_rate">Herzfrequenz</string>
|
<string name="heart_rate">Herzfrequenz</string>
|
||||||
<string name="max_heart_rate">Höchste Herzfrequenz</string>
|
<string name="max_heart_rate">Höchste Herzfrequenz</string>
|
||||||
|
<!--string name="unknown">-</string-->
|
||||||
<string name="waiting">Bitte warten…</string>
|
<string name="waiting">Bitte warten…</string>
|
||||||
|
|
||||||
<!-- End User License Agreement -->
|
<!-- End User License Agreement -->
|
||||||
@@ -339,11 +359,14 @@ limitations under the License.
|
|||||||
<!-- About -->
|
<!-- About -->
|
||||||
<string name="about">Über</string>
|
<string name="about">Über</string>
|
||||||
<string name="help">Hilfe</string>
|
<string name="help">Hilfe</string>
|
||||||
|
<!--string name="about_team">Team:</string-->
|
||||||
|
<!--string name="about_version">Version:</string-->
|
||||||
<string name="about_support">Unterstützung:</string>
|
<string name="about_support">Unterstützung:</string>
|
||||||
<string name="about_privacy">Datenschutz:</string>
|
<string name="about_privacy">Datenschutz:</string>
|
||||||
|
|
||||||
<!-- Send to Google -->
|
<!-- Send to Google -->
|
||||||
<string name="sendtogoogle_title">Senden an…</string>
|
<string name="sendtogoogle_title">Senden an…</string>
|
||||||
|
<!--string name="sendtogoogle_google_fusiontables">Google Fusion Tables</string-->
|
||||||
<string name="sendtogoogle_google_docs">Google Text & Tabellen</string>
|
<string name="sendtogoogle_google_docs">Google Text & Tabellen</string>
|
||||||
<string name="sendtogoogle_send_now">Jetzt senden</string>
|
<string name="sendtogoogle_send_now">Jetzt senden</string>
|
||||||
<string name="sendtogoogle_send_stats">Trackstatistik senden</string>
|
<string name="sendtogoogle_send_stats">Trackstatistik senden</string>
|
||||||
@@ -392,9 +415,11 @@ limitations under the License.
|
|||||||
<string name="check_units_message">Voreingestellt sind metrische Einheiten. Willst Du diese Einstellung ändern?</string>
|
<string name="check_units_message">Voreingestellt sind metrische Einheiten. Willst Du diese Einstellung ändern?</string>
|
||||||
|
|
||||||
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
|
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
|
||||||
|
<string name="method_bluetooth">Bluetooth</string>
|
||||||
<string name="bluetooth_options">Bluetooth-Einstellungen</string>
|
<string name="bluetooth_options">Bluetooth-Einstellungen</string>
|
||||||
<string name="bluetooth_pairing">Geräteverbindung</string>
|
<string name="bluetooth_pairing">Geräteverbindung</string>
|
||||||
<string name="bluetooth_pairing_summary">Öffnet Androids Bluetooth-Einstellungen, um Geräte zu verbinden.</string>
|
<string name="bluetooth_pairing_summary">Öffnet Androids Bluetooth-Einstellungen, um Geräte zu verbinden.</string>
|
||||||
|
<!--string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string-->
|
||||||
<string name="sensor_options">Sensor-Einstellungen</string>
|
<string name="sensor_options">Sensor-Einstellungen</string>
|
||||||
|
|
||||||
<!-- Bluetooth Sensor -->
|
<!-- Bluetooth Sensor -->
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ limitations under the License.
|
|||||||
<string name="tracklist_save_as_tcx">Guardar en archivo TCX</string>
|
<string name="tracklist_save_as_tcx">Guardar en archivo TCX</string>
|
||||||
<string name="tracklist_btn_send_all_to_fusiontables">Enviar a Google Fusion Tables</string>
|
<string name="tracklist_btn_send_all_to_fusiontables">Enviar a Google Fusion Tables</string>
|
||||||
<!-- Export All -->
|
<!-- Export All -->
|
||||||
<string name="tracklist_share_linkfusion">Un enlace a Google Fusion Tables</string>
|
|
||||||
<string name="tracklist_share_csv_file">Un archivo CSV</string>
|
<string name="tracklist_share_csv_file">Un archivo CSV</string>
|
||||||
<string name="tracklist_share_tcx_file">Un archivo TCX</string>
|
<string name="tracklist_share_tcx_file">Un archivo TCX</string>
|
||||||
|
|
||||||
|
|||||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<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 -->
|
<!-- Minimum recording distance -->
|
||||||
<string-array name="min_recording_distance_options">
|
<string-array name="min_recording_distance_options">
|
||||||
<item>1 m</item>
|
<item>1 m</item>
|
||||||
@@ -112,9 +100,9 @@ limitations under the License.
|
|||||||
<item>3.1 miles (señal GPS débil)</item>
|
<item>3.1 miles (señal GPS débil)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Split frequency -->
|
<!-- Task frequency -->
|
||||||
<string-array name="split_frequency_options">
|
<string-array name="task_frequency_options">
|
||||||
<item>No dividir</item>
|
<item>Apagado</item>
|
||||||
<item>100 km</item>
|
<item>100 km</item>
|
||||||
<item>50 km</item>
|
<item>50 km</item>
|
||||||
<item>25 km</item>
|
<item>25 km</item>
|
||||||
@@ -130,8 +118,8 @@ limitations under the License.
|
|||||||
<item>1 min</item>
|
<item>1 min</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="task_frequency_options_ft">
|
||||||
<item>No dividir</item>
|
<item>Apagado</item>
|
||||||
<item>100 mi</item>
|
<item>100 mi</item>
|
||||||
<item>50 mi</item>
|
<item>50 mi</item>
|
||||||
<item>25 mi</item>
|
<item>25 mi</item>
|
||||||
|
|||||||
@@ -25,37 +25,37 @@ limitations under the License.
|
|||||||
<string name="delete_all_tracks">Borrar todos los recorridos</string>
|
<string name="delete_all_tracks">Borrar todos los recorridos</string>
|
||||||
<string name="settings">Configuraciones</string>
|
<string name="settings">Configuraciones</string>
|
||||||
<string name="elevation">Elevación</string>
|
<string name="elevation">Elevación</string>
|
||||||
<string name="choose_track_message">Por favor seleccione el recorrido que desea ver</string>
|
<string name="choose_track_message">Por favor, seleccione el recorrido que desea ver</string>
|
||||||
<string name="current_track">Recorrido actual</string>
|
<string name="current_track">Recorrido actual</string>
|
||||||
<string name="current_segment">Último segmento</string>
|
<string name="current_segment">Último segmento</string>
|
||||||
|
|
||||||
<!-- Error messages -->
|
<!-- Error messages -->
|
||||||
<string name="error_no_location_manager">Ningún administrador de ubicación fue hallado en este aparato! </string>
|
<string name="error_no_location_manager">Ningún administrador de ubicación fue hallado en este dispositivo! </string>
|
||||||
<string name="error_no_gps_location_provider">Ningún proveedor GPS de ubicación fue hallado en este aparato.</string>
|
<string name="error_no_gps_location_provider">Ningún proveedor de ubicación GPS fue hallado en este dispositivo.</string>
|
||||||
<string name="error_sending_to_fusiontables">Hubo un error al mandar su recorrido a Google Fusion Tables. Por favor inténtelo de nuevo más tarde.</string>
|
<string name="error_sending_to_fusiontables">Se produjo un error al enviar su recorrido a Google Fusion Tables.</string>
|
||||||
<string name="error_sending_to_docs">Hubo un error al mandar su recorrido a Google Docs. Por favor inténtelo de nuevo más tarde.</string>
|
<string name="error_sending_to_docs">Se produjo un error al enviar su recorrido a Google Docs.</string>
|
||||||
<string name="error_unable_to_start_recording">No pude empezar a grabar. Por favor inténtelo de nuevo. </string>
|
<string name="error_unable_to_start_recording">No se puede iniciar la grabación. Inténtelo de nuevo. </string>
|
||||||
<string name="error_unable_to_stop_recording">No pude dejar de grabar. Por favor inténtelo de nuevo.</string>
|
<string name="error_unable_to_stop_recording">No se puede detener la grabación. Inténtelo de nuevo.</string>
|
||||||
<string name="error_unable_to_read_file">No pude leer del archivo.</string>
|
<string name="error_unable_to_read_file">No pude leer del archivo.</string>
|
||||||
<string name="error_invalid_gpx_format">El archivo no tiene un format GPX válido.</string>
|
<string name="error_invalid_gpx_format">El archivo no tiene un format GPX válido.</string>
|
||||||
<string name="error_generic">Error. Por favor inténtelo de nuevo.</string>
|
<string name="error_generic">A ocurrido un error. Por favor, inténtelo de nuevo.</string>
|
||||||
<string name="error_track_does_not_exist">El recorrido no existe.</string>
|
<string name="error_track_does_not_exist">El recorrido no existe.</string>
|
||||||
<string name="error_out_of_memory">El archivo es demasiado grande (tiene que ser menor a 500 KB). Abortando.</string>
|
<string name="error_out_of_memory">El archivo es demasiado grande (tiene que ser menor a 500 KB). Abortando.</string>
|
||||||
<string name="error_unable_to_insert_marker">No pude insertar la señal. La ubicación no esta disponible.</string>
|
<string name="error_unable_to_insert_marker">No se puede insertar el marcador. La ubicación no está disponible.</string>
|
||||||
|
|
||||||
<!-- Status messages -->
|
<!-- Status messages -->
|
||||||
<string name="wait_for_fix">Esperando una ubicación mas exacta del GPS. Asegúrese que el cielo sea visible.</string>
|
<string name="wait_for_fix">Esperando una ubicación mas exacta del GPS. Asegúrese que el cielo sea visible.</string>
|
||||||
<string name="status_now_recording">Grabando un nuevo recorrido.</string>
|
<string name="status_now_recording">Grabando un nuevo recorrido.</string>
|
||||||
<string name="status_stopped_recording">Grabacíon interrumpida.</string>
|
<string name="status_stopped_recording">Grabación interrumpida.</string>
|
||||||
<string name="status_new_fusiontable_has_been_created">Un mapa Google Fusion Tables nuevo has sido creado en google.com/fusiontables.</string>
|
<string name="status_new_fusiontable_has_been_created">Una nueva tabla de Google Fusion ha sido creada en google.com/fusiontables.</string>
|
||||||
<string name="status_tracks_have_been_uploaded">Su recorrido ha sido enviado a maps.google.com.</string>
|
<string name="status_tracks_have_been_uploaded">Su recorrido ha sido enviado a maps.google.com.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_new_doc">Su recorrido ha sido enviado a una nueva hoja de cálculo en docs.google.com.</string>
|
<string name="status_tracks_have_been_uploaded_to_new_doc">Su recorrido ha sido enviado a una nueva hoja de cálculo de docs.google.com.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_docs">Su recorrido ha sido enviado a docs.google.com.</string>
|
<string name="status_tracks_have_been_uploaded_to_docs">Su recorrido ha sido enviado a docs.google.com.</string>
|
||||||
<string name="status_enable_gps">Por favor presione aquí para ir al menú de Seguridad y Ubicación y asegúrese que el GPS esté habilitado. Presione el botón de regreso para regresar.</string>
|
<string name="status_enable_gps">Por favor, presione aquí para ir al menú de Seguridad y Ubicación, y asegúrese que el GPS esté habilitado. Presione el botón "atrás" para regresar.</string>
|
||||||
<string name="status_approximate_location">Nota: Una ubicación aproximada es mostrada, basada en informacion de torres de telefonía celular y red WIFI.</string>
|
<string name="status_approximate_location">Nota: Una ubicación aproximada es determinada a partir de torres de telefonía celular y redes WIFI.</string>
|
||||||
<string name="status_no_location">La ubicación actual no puede ser determinada. Habilite más fuentes de datos (vea configuraciones de Seguridad y Ubicación) y asegúrese que el cielo sea visible. Inténtelo mas tarde.</string>
|
<string name="status_no_location">No puede ser determinada la ubicación actual. Habilite más fuentes de datos (vea las configuraciones de Seguridad y Ubicación) y asegúrese que el cielo sea visible. Inténtelo mas tarde.</string>
|
||||||
<string name="status_waypoint_inserted">Una señal de recorrido fue insertada.</string>
|
<string name="status_waypoint_inserted">Un marcador de recorrido fue insertado.</string>
|
||||||
<string name="status_statistics_inserted">Una señal con estadísticas fue insertada.</string>
|
<string name="status_statistics_inserted">Un marcador de estadísticas fue insertado.</string>
|
||||||
|
|
||||||
<!-- Progress dialog -->
|
<!-- Progress dialog -->
|
||||||
<string name="progress_title">Por favor espere...</string>
|
<string name="progress_title">Por favor espere...</string>
|
||||||
@@ -121,7 +121,6 @@ limitations under the License.
|
|||||||
<string name="tracklist_all_tracks">Todos los recorridos:"</string>
|
<string name="tracklist_all_tracks">Todos los recorridos:"</string>
|
||||||
<string name="tracklist_this_track">Este recorrido"</string>
|
<string name="tracklist_this_track">Este recorrido"</string>
|
||||||
<string name="tracklist_share_track">Compartir con amigos..."</string>
|
<string name="tracklist_share_track">Compartir con amigos..."</string>
|
||||||
<string name="tracklist_share_linkfusion">Un enlace a Google Fusion Tables</string>
|
|
||||||
<string name="tracklist_share_gpx_file">Un archivo GPX"</string>
|
<string name="tracklist_share_gpx_file">Un archivo GPX"</string>
|
||||||
<string name="tracklist_share_kml_file">Un archivo KML"</string>
|
<string name="tracklist_share_kml_file">Un archivo KML"</string>
|
||||||
<string name="tracklist_clear_map">"Limpiar mapa"</string>
|
<string name="tracklist_clear_map">"Limpiar mapa"</string>
|
||||||
@@ -213,7 +212,6 @@ limitations under the License.
|
|||||||
<string name="settings_backup_to_sd_summary">Hacer una copia total de sus recorridos y configuraciones a la tarjeta SD</string>
|
<string name="settings_backup_to_sd_summary">Hacer una copia total de sus recorridos y configuraciones a la tarjeta SD</string>
|
||||||
<string name="settings_restore_from_sd">Restaurar</string>
|
<string name="settings_restore_from_sd">Restaurar</string>
|
||||||
<string name="settings_restore_from_sd_summary">Restaurar todos los recorridos y configuraciones desde la tarjeta SD</string>
|
<string name="settings_restore_from_sd_summary">Restaurar todos los recorridos y configuraciones desde la tarjeta SD</string>
|
||||||
<string name="settings_no_backup_while_recording">No se pueden manejar backups mientras se está registrando un recorrido.</string>
|
|
||||||
|
|
||||||
<string name="restore_overwrites_warning">Restaurar un backup desde la tarjeta SD SOBREESCRIBIRÁ todos sus recorridos y configuraciones actuales. ¿Está usted seguro?</string>
|
<string name="restore_overwrites_warning">Restaurar un backup desde la tarjeta SD SOBREESCRIBIRÁ todos sus recorridos y configuraciones actuales. ¿Está usted seguro?</string>
|
||||||
<string name="select_backup_to_restore">Seleccionar el backup para restaurar</string>
|
<string name="select_backup_to_restore">Seleccionar el backup para restaurar</string>
|
||||||
|
|||||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<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 -->
|
<!-- Minimum recording distance -->
|
||||||
<string-array name="min_recording_distance_options">
|
<string-array name="min_recording_distance_options">
|
||||||
<item>1 m</item>
|
<item>1 m</item>
|
||||||
@@ -112,10 +100,9 @@ limitations under the License.
|
|||||||
<item>3.1 miles (mauvais signal GPS)</item>
|
<item>3.1 miles (mauvais signal GPS)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Task frequency -->
|
||||||
<!-- Split frequency -->
|
<string-array name="task_frequency_options">
|
||||||
<string-array name="split_frequency_options">
|
<item>Absent</item>
|
||||||
<item>Pas de séparation</item>
|
|
||||||
<item>100 km</item>
|
<item>100 km</item>
|
||||||
<item>50 km</item>
|
<item>50 km</item>
|
||||||
<item>25 km</item>
|
<item>25 km</item>
|
||||||
@@ -131,8 +118,8 @@ limitations under the License.
|
|||||||
<item>1 min</item>
|
<item>1 min</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="task_frequency_options_ft">
|
||||||
<item>Pas de séparation</item>
|
<item>Absent</item>
|
||||||
<item>100 mi</item>
|
<item>100 mi</item>
|
||||||
<item>50 mi</item>
|
<item>50 mi</item>
|
||||||
<item>25 mi</item>
|
<item>25 mi</item>
|
||||||
|
|||||||
@@ -127,7 +127,6 @@ limitations under the License.
|
|||||||
<string name="tracklist_all_tracks">Tous les parcours:</string>
|
<string name="tracklist_all_tracks">Tous les parcours:</string>
|
||||||
<string name="tracklist_this_track">Ce parcours</string>
|
<string name="tracklist_this_track">Ce parcours</string>
|
||||||
<string name="tracklist_share_track">Partager...</string>
|
<string name="tracklist_share_track">Partager...</string>
|
||||||
<string name="tracklist_share_linkfusion">Lien sur Google Fusion Tables</string>
|
|
||||||
<string name="tracklist_share_gpx_file">Fichier GPX</string>
|
<string name="tracklist_share_gpx_file">Fichier GPX</string>
|
||||||
<string name="tracklist_share_kml_file">Fichier KML</string>
|
<string name="tracklist_share_kml_file">Fichier KML</string>
|
||||||
<string name="tracklist_clear_map">Effacer la carte</string>
|
<string name="tracklist_clear_map">Effacer la carte</string>
|
||||||
@@ -161,7 +160,7 @@ limitations under the License.
|
|||||||
<string name="settings_sharing">Partage</string>
|
<string name="settings_sharing">Partage</string>
|
||||||
|
|
||||||
<string name="settings_announcement_frequency">Fréquence des annonces</string>
|
<string name="settings_announcement_frequency">Fréquence des annonces</string>
|
||||||
<string name="settings_announcement_frequency_summary">Temps minimum entre eux annonces vocales</string>
|
<string name="settings_announcement_frequency_summary">Temps minimum entre deux annonces vocales</string>
|
||||||
|
|
||||||
<string name="settings_min_recording_distance">Distance min. entre 2 points</string>
|
<string name="settings_min_recording_distance">Distance min. entre 2 points</string>
|
||||||
<string name="settings_min_recording_distance_summary">Plus petite distance entre deux enregistrements de votre position</string>
|
<string name="settings_min_recording_distance_summary">Plus petite distance entre deux enregistrements de votre position</string>
|
||||||
@@ -214,8 +213,6 @@ limitations under the License.
|
|||||||
<string name="settings_backup_to_sd_summary">Copier tous vos parcours et paramètres sur la carte SD</string>
|
<string name="settings_backup_to_sd_summary">Copier tous vos parcours et paramètres sur la carte SD</string>
|
||||||
<string name="settings_restore_from_sd">Restaurer</string>
|
<string name="settings_restore_from_sd">Restaurer</string>
|
||||||
<string name="settings_restore_from_sd_summary">Restaurer tous les parcours et paramètres depuis la carte SD</string>
|
<string name="settings_restore_from_sd_summary">Restaurer tous les parcours et paramètres depuis la carte SD</string>
|
||||||
<string name="settings_no_backup_while_recording">Sauvegarde impossible lors de l\'enregistrement d\'un parcours.</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="restore_overwrites_warning">Restaurer une sauvegarde depuis la carte SD écrasera tous vos parcours et paramètres actuels.</string>
|
<string name="restore_overwrites_warning">Restaurer une sauvegarde depuis la carte SD écrasera tous vos parcours et paramètres actuels.</string>
|
||||||
<string name="select_backup_to_restore">Choisissez la sauvegarde à restaurer</string>
|
<string name="select_backup_to_restore">Choisissez la sauvegarde à restaurer</string>
|
||||||
|
|||||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<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 -->
|
<!-- Minimum recording distance -->
|
||||||
<string-array name="min_recording_distance_options">
|
<string-array name="min_recording_distance_options">
|
||||||
<item>1 m</item>
|
<item>1 m</item>
|
||||||
@@ -112,9 +100,9 @@ limitations under the License.
|
|||||||
<item>3.1 mi (segnale GPS debole)</item>
|
<item>3.1 mi (segnale GPS debole)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Split frequency -->
|
<!-- Task frequency -->
|
||||||
<string-array name="split_frequency_options">
|
<string-array name="task_frequency_options">
|
||||||
<item>Non dividere</item>
|
<item>Disattivato</item>
|
||||||
<item>100 km</item>
|
<item>100 km</item>
|
||||||
<item>50 km</item>
|
<item>50 km</item>
|
||||||
<item>25 km</item>
|
<item>25 km</item>
|
||||||
@@ -130,8 +118,8 @@ limitations under the License.
|
|||||||
<item>1 min</item>
|
<item>1 min</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="task_frequency_options_ft">
|
||||||
<item>Non dividere</item>
|
<item>Disattivato</item>
|
||||||
<item>100 mi</item>
|
<item>100 mi</item>
|
||||||
<item>50 mi</item>
|
<item>50 mi</item>
|
||||||
<item>25 mi</item>
|
<item>25 mi</item>
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ limitations under the License.
|
|||||||
<string name="tracklist_all_tracks">Tutti i percorsi:</string>
|
<string name="tracklist_all_tracks">Tutti i percorsi:</string>
|
||||||
<string name="tracklist_this_track">Questo percorso</string>
|
<string name="tracklist_this_track">Questo percorso</string>
|
||||||
<string name="tracklist_share_track">Condividi con amici...</string>
|
<string name="tracklist_share_track">Condividi con amici...</string>
|
||||||
<!-- <string name="tracklist_share_linkfusion">Un link alla mappa in «Le mie mappe» di Google</string> -->
|
<string name="tracklist_share_link">Un link alla mappa</string>
|
||||||
<string name="tracklist_share_gpx_file">Un file GPX</string>
|
<string name="tracklist_share_gpx_file">Un file GPX</string>
|
||||||
<string name="tracklist_share_kml_file">Un file KML</string>
|
<string name="tracklist_share_kml_file">Un file KML</string>
|
||||||
<string name="tracklist_clear_map">Cancella la mappa</string>
|
<string name="tracklist_clear_map">Cancella la mappa</string>
|
||||||
|
|||||||
@@ -15,19 +15,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Task frequency -->
|
<!-- Minimum recording distance -->
|
||||||
<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">
|
<string-array name="min_recording_distance_options">
|
||||||
<item>1 m</item>
|
<item>1 m</item>
|
||||||
<item>2 m</item>
|
<item>2 m</item>
|
||||||
@@ -48,7 +36,6 @@ limitations under the License.
|
|||||||
<item>328 ft</item>
|
<item>328 ft</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<!-- Maximum recording distance -->
|
<!-- Maximum recording distance -->
|
||||||
<string-array name="max_recording_distance_options">
|
<string-array name="max_recording_distance_options">
|
||||||
<item>50 m</item>
|
<item>50 m</item>
|
||||||
@@ -68,7 +55,6 @@ limitations under the License.
|
|||||||
<item>3.1 mi</item>
|
<item>3.1 mi</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<!-- Minimum recording interval -->
|
<!-- Minimum recording interval -->
|
||||||
<string-array name="min_recording_interval_options">
|
<string-array name="min_recording_interval_options">
|
||||||
<item>電源節約 (動的制御)</item>
|
<item>電源節約 (動的制御)</item>
|
||||||
@@ -89,7 +75,6 @@ limitations under the License.
|
|||||||
<item>30 分</item>
|
<item>30 分</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<!-- Minimum required accuracy -->
|
<!-- Minimum required accuracy -->
|
||||||
<string-array name="min_required_accuracy_options">
|
<string-array name="min_required_accuracy_options">
|
||||||
<item>10 m (GPS信号強度良好)</item>
|
<item>10 m (GPS信号強度良好)</item>
|
||||||
@@ -115,10 +100,9 @@ limitations under the License.
|
|||||||
<item>3.1 mi (GPS信号強度不良)</item>
|
<item>3.1 mi (GPS信号強度不良)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Task frequency -->
|
||||||
<!-- Split frequency -->
|
<string-array name="task_frequency_options">
|
||||||
<string-array name="split_frequency_options">
|
<item>不使用</item>
|
||||||
<item>分割なし</item>
|
|
||||||
<item>100 km</item>
|
<item>100 km</item>
|
||||||
<item>50 km</item>
|
<item>50 km</item>
|
||||||
<item>25 km</item>
|
<item>25 km</item>
|
||||||
@@ -134,8 +118,8 @@ limitations under the License.
|
|||||||
<item>1 分</item>
|
<item>1 分</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="task_frequency_options_ft">
|
||||||
<item>分割なし</item>
|
<item>不使用</item>
|
||||||
<item>100 mi</item>
|
<item>100 mi</item>
|
||||||
<item>50 mi</item>
|
<item>50 mi</item>
|
||||||
<item>25 mi</item>
|
<item>25 mi</item>
|
||||||
@@ -287,4 +271,12 @@ limitations under the License.
|
|||||||
<item>噴水</item>
|
<item>噴水</item>
|
||||||
<item>ウェイポイント</item>
|
<item>ウェイポイント</item>
|
||||||
</array>
|
</array>
|
||||||
|
|
||||||
|
<array name="sensor_type_options">
|
||||||
|
<item>なし</item>
|
||||||
|
<item>ANT+ センサー</item>
|
||||||
|
<item>SRM ANT+ ブリッジ</item>
|
||||||
|
<item>Zephyr Bluetooth</item>
|
||||||
|
</array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ limitations under the License.
|
|||||||
<!-- Error messages -->
|
<!-- Error messages -->
|
||||||
<string name="error_no_location_manager">この端末でロケーションマネージャを発見できませんでした.</string>
|
<string name="error_no_location_manager">この端末でロケーションマネージャを発見できませんでした.</string>
|
||||||
<string name="error_no_gps_location_provider">この端末でGPSロケーションプロバイダを発見できました.</string>
|
<string name="error_no_gps_location_provider">この端末でGPSロケーションプロバイダを発見できました.</string>
|
||||||
|
<string name="error_sending_to_mymap">Googleマイマップへのトラック送信でエラーが発生しました.しばらく待って試して下さい.</string>
|
||||||
<string name="error_sending_to_fusiontables">Google Fusion Tablesへのトラック送信でエラーが発生しました.しばらく待って試して下さい.</string>
|
<string name="error_sending_to_fusiontables">Google Fusion Tablesへのトラック送信でエラーが発生しました.しばらく待って試して下さい.</string>
|
||||||
<string name="error_sending_to_docs">Google Docsへのトラック送信でエラーが発生しました.しばらく待って試して下さい.</string>
|
<string name="error_sending_to_docs">Google Docsへのトラック送信でエラーが発生しました.しばらく待って試して下さい.</string>
|
||||||
<string name="error_unable_to_start_recording">記録作成開始できません.もう一度試して下さい.</string>
|
<string name="error_unable_to_start_recording">記録作成開始できません.もう一度試して下さい.</string>
|
||||||
@@ -50,11 +51,13 @@ limitations under the License.
|
|||||||
<string name="wait_for_fix">GPS位置精度がよくなるまで待機しています.空が見えるところにいて下さい.</string>
|
<string name="wait_for_fix">GPS位置精度がよくなるまで待機しています.空が見えるところにいて下さい.</string>
|
||||||
<string name="status_now_recording">新しいトラックを記録中です.</string>
|
<string name="status_now_recording">新しいトラックを記録中です.</string>
|
||||||
<string name="status_stopped_recording">トラック記録を停止しました.</string>
|
<string name="status_stopped_recording">トラック記録を停止しました.</string>
|
||||||
|
<string name="status_new_mymap_has_been_created">新しいマイマップをmap.google.comに作成しました.</string>
|
||||||
<string name="status_new_fusiontable_has_been_created">新しいGoogle Fusion Tableをgoogle.com/fusiontablesに作成しました.</string>
|
<string name="status_new_fusiontable_has_been_created">新しいGoogle Fusion Tableをgoogle.com/fusiontablesに作成しました.</string>
|
||||||
<string name="status_tracks_have_been_uploaded">トラックをmaps.google.comに送信しました.</string>
|
<string name="status_tracks_have_been_uploaded">トラックをmaps.google.comに送信しました.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_new_doc">トラックをdocs.google.comの新しいスプレッドシートに送信しました.</string>
|
<string name="status_tracks_have_been_uploaded_to_new_doc">トラックをdocs.google.comの新しいスプレッドシートに送信しました.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_docs">トラックをdocs.google.comに送信しました.</string>
|
<string name="status_tracks_have_been_uploaded_to_docs">トラックをdocs.google.comに送信しました.</string>
|
||||||
<string name="status_enable_gps">ここをタップして「位置情報とセキュリティの設定」を開いて「GPS機能を使用」にチェックして下さい.バックボタンで戻ってください.</string>
|
<string name="status_mymap_info">新しいトラックが表示されるまでに数分かかることがあります.</string>
|
||||||
|
<string name="status_enable_gps">ここをタップして「位置情報とセキュリティの設定」を開いて「GPS機能を使用」にチェックを入れて下さい.バックボタンで戻ってください.</string>
|
||||||
<string name="status_approximate_location">ご注意: 携帯電話中継局とWi-Fiネットワークから大まかな位置を特定します.</string>
|
<string name="status_approximate_location">ご注意: 携帯電話中継局とWi-Fiネットワークから大まかな位置を特定します.</string>
|
||||||
<string name="status_no_location">現在位置決定ができません.位置取得源を増やし(位置情報とセキュリティの設定 をご覧ください)、空が見えるようにして下さい.もう一度試して下さい.</string>
|
<string name="status_no_location">現在位置決定ができません.位置取得源を増やし(位置情報とセキュリティの設定 をご覧ください)、空が見えるようにして下さい.もう一度試して下さい.</string>
|
||||||
<string name="status_waypoint_inserted">ウェイポイントマーカーを挿入しました.</string>
|
<string name="status_waypoint_inserted">ウェイポイントマーカーを挿入しました.</string>
|
||||||
@@ -62,14 +65,17 @@ limitations under the License.
|
|||||||
|
|
||||||
<!-- Progress dialog -->
|
<!-- Progress dialog -->
|
||||||
<string name="progress_title">お待ちください...</string>
|
<string name="progress_title">お待ちください...</string>
|
||||||
<string name="progress_message">トラックをGoogleに送信しました.</string>
|
<string name="progress_message">トラックをGoogleに送信しています.</string>
|
||||||
<string name="progress_message_reading_track">トラックを読んでいます...</string>
|
<string name="progress_message_reading_track">トラックを読んでいます...</string>
|
||||||
<string name="progress_message_preparing_track">トラックを準備しています...</string>
|
<string name="progress_message_preparing_track">トラックを準備しています...</string>
|
||||||
<string name="progress_message_authenticating_fusiontables">Google Fusion Tablesへの認証を行っています...</string>
|
<string name="progress_message_authenticating_fusiontables">Google Fusion Tablesへの認証を行っています...</string>
|
||||||
|
<string name="progress_message_authenticating_mymaps">Googleマップへの認証を行っています...</string>
|
||||||
<string name="progress_message_authenticating_docs">Google Docsへの認証を行っています...</string>
|
<string name="progress_message_authenticating_docs">Google Docsへの認証を行っています...</string>
|
||||||
<string name="progress_message_sending_docs">トラックをGoogle Docsに送信しています...</string>
|
<string name="progress_message_sending_docs">トラックをGoogle Docsに送信しています...</string>
|
||||||
|
<string name="progress_message_sending_mymaps">トラックをGoogleマップに送信しています...</string>
|
||||||
|
<string name="progress_message_creating_map">新しいマイマップを作成しています...</string>
|
||||||
<string name="progress_message_sending_fusiontables">トラックをFusion Tablesに送信しています...</string>
|
<string name="progress_message_sending_fusiontables">トラックをFusion Tablesに送信しています...</string>
|
||||||
<string name="progress_message_creating_fusiontable">新しいFusion Tablesを生成しています...</string>
|
<string name="progress_message_creating_fusiontable">新しいFusionテーブルを生成しています...</string>
|
||||||
<string name="import_progress_message">GPSトラックをインポートしています.若干時間がかかります.</string>
|
<string name="import_progress_message">GPSトラックをインポートしています.若干時間がかかります.</string>
|
||||||
<string name="write_progress_message">SDカードにデータを書き込んでいます.若干時間がかかります.</string>
|
<string name="write_progress_message">SDカードにデータを書き込んでいます.若干時間がかかります.</string>
|
||||||
<string name="progress_message_updating_track">トラック統計情報を更新しています...</string>
|
<string name="progress_message_updating_track">トラック統計情報を更新しています...</string>
|
||||||
@@ -84,6 +90,10 @@ limitations under the License.
|
|||||||
<string name="new_map_description">Android用My Tracksで作成</string>
|
<string name="new_map_description">Android用My Tracksで作成</string>
|
||||||
<string name="fusiontable_link">Android用<a href=\'http://mytracks.appspot.com\'>My Tracks</a>で作成しました.</string>
|
<string name="fusiontable_link">Android用<a href=\'http://mytracks.appspot.com\'>My Tracks</a>で作成しました.</string>
|
||||||
|
|
||||||
|
<!-- Text and links when uploading to Google My Maps -->
|
||||||
|
<string name="my_map_link">Android用<a href=\'http://mytracks.appspot.com\'>My Tracks</a>で作成しました.</string>
|
||||||
|
<string name="new_map_title">新規マップ</string>
|
||||||
|
|
||||||
<!-- Formatting of track and marker descriptions -->
|
<!-- Formatting of track and marker descriptions -->
|
||||||
<string name="points">ポイント</string>
|
<string name="points">ポイント</string>
|
||||||
<string name="recorded_date">記録日</string>
|
<string name="recorded_date">記録日</string>
|
||||||
@@ -113,10 +123,12 @@ limitations under the License.
|
|||||||
|
|
||||||
<!-- TrackList -->
|
<!-- TrackList -->
|
||||||
<string name="tracklist_show_track">表示</string>
|
<string name="tracklist_show_track">表示</string>
|
||||||
<string name="tracklist_send_to_fusiontables">Google Fusion Tablesへ送信</string>
|
<string name="tracklist_send_to_mymaps">Googleマイマップに送信</string>
|
||||||
<string name="tracklist_send_to_new_fusiontable">新規Google Fusion Tableへ送信</string>
|
<string name="tracklist_send_to_new_mymap">新規Googleマイマップに送信</string>
|
||||||
<string name="tracklist_send_to_docs">Google Docsへ送信</string>
|
<string name="tracklist_send_to_fusiontables">Google Fusion Tablesに送信</string>
|
||||||
<string name="tracklist_send_to_google">Googleへ送信...</string>
|
<string name="tracklist_send_to_new_fusiontable">新規Google Fusion Tableに送信</string>
|
||||||
|
<string name="tracklist_send_to_docs">Google Docsに送信</string>
|
||||||
|
<string name="tracklist_send_to_google">Googleに送信...</string>
|
||||||
<string name="tracklist_delete_track">端末から削除...</string>
|
<string name="tracklist_delete_track">端末から削除...</string>
|
||||||
<string name="tracklist_edit_track">詳細編集</string>
|
<string name="tracklist_edit_track">詳細編集</string>
|
||||||
<string name="tracklist_write_to_sd">SDへの書き込み...</string>
|
<string name="tracklist_write_to_sd">SDへの書き込み...</string>
|
||||||
@@ -124,21 +136,33 @@ limitations under the License.
|
|||||||
<string name="tracklist_save_as_kml">KMLファイルの保存</string>
|
<string name="tracklist_save_as_kml">KMLファイルの保存</string>
|
||||||
<string name="tracklist_save_as_csv">CVSファイルの保存</string>
|
<string name="tracklist_save_as_csv">CVSファイルの保存</string>
|
||||||
<string name="tracklist_save_as_tcx">TCXファイルの保存</string>
|
<string name="tracklist_save_as_tcx">TCXファイルの保存</string>
|
||||||
<string name="tracklist_btn_send_all_to_fusiontables">Google Fusion Tablesへの送信</string>
|
<string name="tracklist_btn_send_all_to_fusiontables">Google Fusion Tablesに送信</string>
|
||||||
<string name="tracklist_btn_delete_all">全トラックの削除</string>
|
<string name="tracklist_btn_send_all_to_mymaps">Googleマイマップに送信</string>
|
||||||
|
<string name="tracklist_btn_delete_all">全て削除</string>
|
||||||
<!-- Export All -->
|
<!-- Export All -->
|
||||||
<string name="tracklist_btn_export_all">全トラックの出力</string>
|
<string name="tracklist_btn_export_all">全て出力</string>
|
||||||
<string name="export_done">出力終了</string>
|
<string name="export_done">出力終了</string>
|
||||||
<string name="tracklist_pick_one">トラックを選択します.オプションを表示するには長押しして下さい.</string>
|
<string name="tracklist_pick_one">トラックを選択します.オプションを表示するには長押しして下さい.</string>
|
||||||
<string name="tracklist_all_tracks">全てのトラック:</string>
|
<string name="tracklist_all_tracks">全トラック:</string>
|
||||||
<string name="tracklist_this_track">このトラック</string>
|
<string name="tracklist_this_track">このトラック</string>
|
||||||
<string name="tracklist_share_track">共有...</string>
|
<string name="tracklist_share_track">共有...</string>
|
||||||
<string name="tracklist_share_linkfusion">Google Fusion Tablesへのリンク</string>
|
<string name="tracklist_share_link">マップへのリンク</string>
|
||||||
<string name="tracklist_share_gpx_file">GPXファイル</string>
|
<string name="tracklist_share_gpx_file">GPXファイル</string>
|
||||||
<string name="tracklist_share_kml_file">KMLファイル</string>
|
<string name="tracklist_share_kml_file">KMLファイル</string>
|
||||||
<string name="tracklist_share_csv_file">CSVファイル</string>
|
<string name="tracklist_share_csv_file">CSVファイル</string>
|
||||||
<string name="tracklist_share_tcx_file">TCXファイル</string>
|
<string name="tracklist_share_tcx_file">TCXファイル</string>
|
||||||
<string name="tracklist_clear_map">マップの消去</string>
|
<string name="tracklist_clear_map">マップのクリア</string>
|
||||||
|
<!-- Import All -->
|
||||||
|
<string name="tracklist_btn_import_all">全てインポート</string>
|
||||||
|
<string name="import_done">インポート終了</string>
|
||||||
|
<!-- Format:
|
||||||
|
$1 : Successful imports
|
||||||
|
$2 : Attempted imports
|
||||||
|
$3 : MyTracks gpx path
|
||||||
|
-->
|
||||||
|
<string name="import_done">%3$s からGPXファイル %2$d件のうち %1$d件をインポートしました</string>
|
||||||
|
<string name="import_empty">%s ではGPXファイルがありません.SDカードを読み込めないかディレクトリにGPXファイルが無いかも知れません.</string>
|
||||||
|
<string name="import_error">ファイル %s のインポートエラー</string>
|
||||||
|
|
||||||
<!-- Waypoints list -->
|
<!-- Waypoints list -->
|
||||||
<string name="waypointslist_btn_delete_all">全てのマーカーの削除</string>
|
<string name="waypointslist_btn_delete_all">全てのマーカーの削除</string>
|
||||||
@@ -191,7 +215,7 @@ limitations under the License.
|
|||||||
|
|
||||||
<string name="settings_map_public">マップの公開</string>
|
<string name="settings_map_public">マップの公開</string>
|
||||||
<string name="settings_map_public_summary_on">アップロードされたマップはmaps.google.comで誰でも閲覧できます</string>
|
<string name="settings_map_public_summary_on">アップロードされたマップはmaps.google.comで誰でも閲覧できます</string>
|
||||||
<string name="settings_map_public_summary_off">アップロードされたマップはmaps.google.comのリストに公開されません.</string>
|
<string name="settings_map_public_summary_off">アップロードされたマップはmaps.google.comのリストに公開されません</string>
|
||||||
|
|
||||||
<string name="settings_report_speed_or_pace">速度表示</string>
|
<string name="settings_report_speed_or_pace">速度表示</string>
|
||||||
<string name="settings_report_speed_or_pace_summary_on">速度が表示されます</string>
|
<string name="settings_report_speed_or_pace_summary_on">速度が表示されます</string>
|
||||||
@@ -232,7 +256,6 @@ limitations under the License.
|
|||||||
<string name="settings_backup_to_sd_summary">SDカードに全てのトラックと設定をバックアップします</string>
|
<string name="settings_backup_to_sd_summary">SDカードに全てのトラックと設定をバックアップします</string>
|
||||||
<string name="settings_restore_from_sd">今すぐ復元</string>
|
<string name="settings_restore_from_sd">今すぐ復元</string>
|
||||||
<string name="settings_restore_from_sd_summary">SDカードから全てのトラックと設定を復元します</string>
|
<string name="settings_restore_from_sd_summary">SDカードから全てのトラックと設定を復元します</string>
|
||||||
<string name="settings_no_backup_while_recording">トラック記録中はバックアップ操作はできません.</string>
|
|
||||||
|
|
||||||
<string name="restore_overwrites_warning">SDカードからの復元を実行すると、現在のトラックと設定は *全て上書き* されてしまいます.よろしいですか?</string>
|
<string name="restore_overwrites_warning">SDカードからの復元を実行すると、現在のトラックと設定は *全て上書き* されてしまいます.よろしいですか?</string>
|
||||||
<string name="select_backup_to_restore">復元するバックアップの選択</string>
|
<string name="select_backup_to_restore">復元するバックアップの選択</string>
|
||||||
@@ -243,6 +266,23 @@ limitations under the License.
|
|||||||
<!-- MyTracksSky -->
|
<!-- MyTracksSky -->
|
||||||
<string name="mytracks_sky">GPS衛星</string>
|
<string name="mytracks_sky">GPS衛星</string>
|
||||||
|
|
||||||
|
<!-- My Maps -->
|
||||||
|
<string name="select_map_message">アカウントからのマップ選択:</string>
|
||||||
|
<string name="create_new_map">新規マップ作成...</string>
|
||||||
|
<string name="map_list_title">Googleマイマップに送信</string>
|
||||||
|
<string name="maps_list_loading">マップをロード中...</string>
|
||||||
|
<string name="maps_list_failed">今回はマップをロードできませんでした!</string>
|
||||||
|
<string name="open_map">このマップを選択</string>
|
||||||
|
<string name="edit_map_details">マップ詳細編集</string>
|
||||||
|
<string name="share_track">トラック共有</string>
|
||||||
|
<string name="delete_map">アカウントからマップを削除</string>
|
||||||
|
<string name="map_title">マップタイトル:</string>
|
||||||
|
<string name="map_description">マップ説明:</string>
|
||||||
|
<string name="map_searchable_edit">このマップまたはコンテンツを検索結果に表示</string>
|
||||||
|
<string name="map_not_searchable_edit">このマップまたはコンテンツを検索結果に表示しない(直接URLで見られる可能性があります)</string>
|
||||||
|
<string name="map_searchable">このマップまたはコンテンツは検索結果に表示されます</string>
|
||||||
|
<string name="map_not_searchable">このマップもコンテンツも検索結果に表示されませんが、直接リンクで見られる可能性があります</string>
|
||||||
|
|
||||||
<!-- Sharing -->
|
<!-- Sharing -->
|
||||||
<string name="share_map">マップ共有</string>
|
<string name="share_map">マップ共有</string>
|
||||||
<string name="share_map_subject">マップを共有したいと思います</string>
|
<string name="share_map_subject">マップを共有したいと思います</string>
|
||||||
@@ -333,7 +373,6 @@ limitations under the License.
|
|||||||
<string name="cadence">ケイデンス</string>
|
<string name="cadence">ケイデンス</string>
|
||||||
<string name="heart_rate">心拍数</string>
|
<string name="heart_rate">心拍数</string>
|
||||||
<string name="max_heart_rate">最大心拍数</string>
|
<string name="max_heart_rate">最大心拍数</string>
|
||||||
<string name="unknown">-</string>
|
|
||||||
<string name="waiting">待機中...</string>
|
<string name="waiting">待機中...</string>
|
||||||
|
|
||||||
<!-- End User License Agreement -->
|
<!-- End User License Agreement -->
|
||||||
@@ -351,8 +390,10 @@ limitations under the License.
|
|||||||
|
|
||||||
<!-- Send to Google -->
|
<!-- Send to Google -->
|
||||||
<string name="sendtogoogle_title">送信...</string>
|
<string name="sendtogoogle_title">送信...</string>
|
||||||
<string name="sendtogoogle_google_fusiontables">Googleマイマップ</string>
|
<string name="sendtogoogle_google_mymaps">Googleマイマップ</string>
|
||||||
<string name="sendtogoogle_send_now">今すぐ送信</string>
|
<string name="sendtogoogle_send_now">今すぐ送信</string>
|
||||||
|
<string name="sendtogoogle_create_new_map">新規マップ作成</string>
|
||||||
|
<string name="sendtogoogle_pick_existing_map">既存マップ選択</string>
|
||||||
<string name="sendtogoogle_send_stats">トラック統計情報送信</string>
|
<string name="sendtogoogle_send_stats">トラック統計情報送信</string>
|
||||||
<string name="sendtogoogle_send_stats_and_points">統計情報とポイント送信</string>
|
<string name="sendtogoogle_send_stats_and_points">統計情報とポイント送信</string>
|
||||||
|
|
||||||
@@ -365,7 +406,7 @@ limitations under the License.
|
|||||||
<string name="io_no_external_storage_found">外部ストレージを発見できませんでした.SDカードが刺さっているか、端末がコンピュータにマウントされていないか確認してください.</string>
|
<string name="io_no_external_storage_found">外部ストレージを発見できませんでした.SDカードが刺さっているか、端末がコンピュータにマウントされていないか確認してください.</string>
|
||||||
<string name="io_write_failed">ファイルへの書き込みができません.</string>
|
<string name="io_write_failed">ファイルへの書き込みができません.</string>
|
||||||
<string name="io_read_failed">ファイルからの読み込みができません.</string>
|
<string name="io_read_failed">ファイルからの読み込みができません.</string>
|
||||||
<string name="io_create_dir_failed">SDカードにディレクトリを作成できません.</string>
|
<string name="io_create_dir_failed">SDカード上でディレクトリを作成できません.</string>
|
||||||
<string name="io_write_finished">SDカードへの書き込み終了.</string>
|
<string name="io_write_finished">SDカードへの書き込み終了.</string>
|
||||||
<string name="io_read_finished">SDカードからの読み込み終了.</string>
|
<string name="io_read_finished">SDカードからの読み込み終了.</string>
|
||||||
|
|
||||||
@@ -398,11 +439,11 @@ limitations under the License.
|
|||||||
<string name="check_units_message">デフォルトの単位はメートルです.設定を変更しますか?</string>
|
<string name="check_units_message">デフォルトの単位はメートルです.設定を変更しますか?</string>
|
||||||
|
|
||||||
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
|
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
|
||||||
<!-- string name="method_bluetooth">Bluetooth</string --> <!-- duplicate -->
|
|
||||||
<string name="bluetooth_options">Bluetoothオプション</string>
|
<string name="bluetooth_options">Bluetoothオプション</string>
|
||||||
<string name="bluetooth_pairing">ペアリング</string>
|
<string name="bluetooth_pairing">ペアリング</string>
|
||||||
<string name="bluetooth_pairing_summary">ペアリングを行うには「Bluetooth設定」を開いて下さい</string>
|
<string name="bluetooth_pairing_summary">ペアリングを行うには「Bluetooth設定」を開いて下さい</string>
|
||||||
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
|
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
|
||||||
|
<string name="ant_options">ANTオプション</string>
|
||||||
<string name="sensor_options">センサーオプション</string>
|
<string name="sensor_options">センサーオプション</string>
|
||||||
|
|
||||||
<!-- Bluetooth Sensor -->
|
<!-- Bluetooth Sensor -->
|
||||||
@@ -426,7 +467,7 @@ limitations under the License.
|
|||||||
<!-- Manifest description (not seen inside the app) -->
|
<!-- Manifest description (not seen inside the app) -->
|
||||||
<string name="notification_permission_label">トラック記録通知受信</string>
|
<string name="notification_permission_label">トラック記録通知受信</string>
|
||||||
<string name="read_tracks_permission_label">トラック読み込み</string>
|
<string name="read_tracks_permission_label">トラック読み込み</string>
|
||||||
<string name="write_tracks_permission_label">トラック書き込み トラック記録の開始・終了</string>
|
<string name="write_tracks_permission_label">トラック書き込みとトラック記録の開始・終了</string>
|
||||||
<string name="notification_permission_description">トラック記録の開始・終了時に通知されます.</string>
|
<string name="notification_permission_description">トラック記録の開始・終了時に通知されます.</string>
|
||||||
<string name="read_tracks_permission_description">ポイントやウェイポイントといったトラックの読み込みを可能にします.</string>
|
<string name="read_tracks_permission_description">ポイントやウェイポイントといったトラックの読み込みを可能にします.</string>
|
||||||
<string name="write_tracks_permission_description">記録開始やウェイポイント追加といったトラック記録を可能にします.</string>
|
<string name="write_tracks_permission_description">記録開始やウェイポイント追加といったトラック記録を可能にします.</string>
|
||||||
|
|||||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<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 -->
|
<!-- Minimum recording distance -->
|
||||||
<string-array name="min_recording_distance_options">
|
<string-array name="min_recording_distance_options">
|
||||||
<item>1 m</item>
|
<item>1 m</item>
|
||||||
@@ -112,9 +100,9 @@ limitations under the License.
|
|||||||
<item>3.1 mili (słaby sygnał GPS)</item>
|
<item>3.1 mili (słaby sygnał GPS)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Split frequency -->
|
<!-- Task frequency -->
|
||||||
<string-array name="split_frequency_options">
|
<string-array name="task_frequency_options">
|
||||||
<item>Brak dzielenia</item>
|
<item>Brak</item>
|
||||||
<item>100 km</item>
|
<item>100 km</item>
|
||||||
<item>50 km</item>
|
<item>50 km</item>
|
||||||
<item>25 km</item>
|
<item>25 km</item>
|
||||||
@@ -130,8 +118,8 @@ limitations under the License.
|
|||||||
<item>1 min</item>
|
<item>1 min</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="task_frequency_options_ft">
|
||||||
<item>Brak dzielenia</item>
|
<item>Brak</item>
|
||||||
<item>100 mi</item>
|
<item>100 mi</item>
|
||||||
<item>50 mi</item>
|
<item>50 mi</item>
|
||||||
<item>25 mi</item>
|
<item>25 mi</item>
|
||||||
|
|||||||
@@ -131,7 +131,6 @@ limitations under the License.
|
|||||||
<string name="tracklist_all_tracks">Wszystkie trasy:</string>
|
<string name="tracklist_all_tracks">Wszystkie trasy:</string>
|
||||||
<string name="tracklist_this_track">Ta trasa</string>
|
<string name="tracklist_this_track">Ta trasa</string>
|
||||||
<string name="tracklist_share_track">Podziel się z przyjaciółmi...</string>
|
<string name="tracklist_share_track">Podziel się z przyjaciółmi...</string>
|
||||||
<!-- <string name="tracklist_share_linkfusion">Link do Moich Map Google</string> -->
|
|
||||||
<string name="tracklist_share_gpx_file">Plik GPX</string>
|
<string name="tracklist_share_gpx_file">Plik GPX</string>
|
||||||
<string name="tracklist_share_kml_file">PLik KML</string>
|
<string name="tracklist_share_kml_file">PLik KML</string>
|
||||||
<string name="tracklist_share_csv_file">Plik CSV</string>
|
<string name="tracklist_share_csv_file">Plik CSV</string>
|
||||||
@@ -218,7 +217,6 @@ limitations under the License.
|
|||||||
<string name="settings_backup_to_sd_summary">Tworzy kopię zapasową wszystkich tras i ustawień i zapisuje je na karcie SD</string>
|
<string name="settings_backup_to_sd_summary">Tworzy kopię zapasową wszystkich tras i ustawień i zapisuje je na karcie SD</string>
|
||||||
<string name="settings_restore_from_sd">Odtwórz z kopii</string>
|
<string name="settings_restore_from_sd">Odtwórz z kopii</string>
|
||||||
<string name="settings_restore_from_sd_summary">Odtwarza wszystkie trasy i ustawienia z kopii zapasowej z karty SD</string>
|
<string name="settings_restore_from_sd_summary">Odtwarza wszystkie trasy i ustawienia z kopii zapasowej z karty SD</string>
|
||||||
<string name="settings_no_backup_while_recording">Nie można tworzyć/odtwarzać kopii zapasowej podczas rejestrowania trasy.</string>
|
|
||||||
|
|
||||||
<!-- Backups -->
|
<!-- Backups -->
|
||||||
<string name="restore_overwrites_warning">Odtworzenie z kopii zapasowej z karty SD zastąpi wszystkie bieżące trasy i ustawienia. Jesteś tego pewien?</string>
|
<string name="restore_overwrites_warning">Odtworzenie z kopii zapasowej z karty SD zastąpi wszystkie bieżące trasy i ustawienia. Jesteś tego pewien?</string>
|
||||||
|
|||||||
@@ -15,21 +15,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<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 -->
|
<!-- Minimum recording distance -->
|
||||||
<array name="min_recording_distance_options">
|
<string-array name="min_recording_distance_options">
|
||||||
<item>1 m</item>
|
<item>1 m</item>
|
||||||
<item>2 m</item>
|
<item>2 m</item>
|
||||||
<item>3 m</item>
|
<item>3 m</item>
|
||||||
@@ -37,9 +24,9 @@ limitations under the License.
|
|||||||
<item>5 m (recomendada)</item>
|
<item>5 m (recomendada)</item>
|
||||||
<item>10 m</item>
|
<item>10 m</item>
|
||||||
<item>100 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>3 pés</item>
|
||||||
<item>6 pés</item>
|
<item>6 pés</item>
|
||||||
<item>10 pés</item>
|
<item>10 pés</item>
|
||||||
@@ -47,31 +34,29 @@ limitations under the License.
|
|||||||
<item>16 pés (recomendado)</item>
|
<item>16 pés (recomendado)</item>
|
||||||
<item>33 pés</item>
|
<item>33 pés</item>
|
||||||
<item>328 pés</item>
|
<item>328 pés</item>
|
||||||
</array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<!-- Maximum recording distance -->
|
<!-- Maximum recording distance -->
|
||||||
<array name="max_recording_distance_options">
|
<string-array name="max_recording_distance_options">
|
||||||
<item>50 m</item>
|
<item>50 m</item>
|
||||||
<item>100 m</item>
|
<item>100 m</item>
|
||||||
<item>200 m (recomendado)</item>
|
<item>200 m (recomendado)</item>
|
||||||
<item>500 m</item>
|
<item>500 m</item>
|
||||||
<item>1000 m</item>
|
<item>1000 m</item>
|
||||||
<item>5000 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>164 pés</item>
|
||||||
<item>328 pés</item>
|
<item>328 pés</item>
|
||||||
<item>656 pés (recomendado)</item>
|
<item>656 pés (recomendado)</item>
|
||||||
<item>1640 pés</item>
|
<item>1640 pés</item>
|
||||||
<item>0.6 milhas</item>
|
<item>0.6 milhas</item>
|
||||||
<item>3.1 milhas</item>
|
<item>3.1 milhas</item>
|
||||||
</array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<!-- Minimum recording interval -->
|
<!-- Minimum recording interval -->
|
||||||
<array name="min_recording_interval_options">
|
<string-array name="min_recording_interval_options">
|
||||||
<item>economia de bateria (adaptativo)</item>
|
<item>economia de bateria (adaptativo)</item>
|
||||||
<item>alta precisão (adaptativo)</item>
|
<item>alta precisão (adaptativo)</item>
|
||||||
<item>máxima (recomendada)</item>
|
<item>máxima (recomendada)</item>
|
||||||
@@ -88,11 +73,10 @@ limitations under the License.
|
|||||||
<item>10 min</item>
|
<item>10 min</item>
|
||||||
<item>15 min</item>
|
<item>15 min</item>
|
||||||
<item>30 min</item>
|
<item>30 min</item>
|
||||||
</array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<!-- Minimum required accuracy -->
|
<!-- 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>10 m (sinal de GPS excelente)</item>
|
||||||
<item>20 m</item>
|
<item>20 m</item>
|
||||||
<item>50 m</item>
|
<item>50 m</item>
|
||||||
@@ -102,9 +86,9 @@ limitations under the License.
|
|||||||
<item>1000 m</item>
|
<item>1000 m</item>
|
||||||
<item>2000 m</item>
|
<item>2000 m</item>
|
||||||
<item>5000 m (sinal de GPS ruim)</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>33 pés (sinal de GPS excelente)</item>
|
||||||
<item>66 pés</item>
|
<item>66 pés</item>
|
||||||
<item>165 pés</item>
|
<item>165 pés</item>
|
||||||
@@ -114,12 +98,11 @@ limitations under the License.
|
|||||||
<item>0.6 milhas</item>
|
<item>0.6 milhas</item>
|
||||||
<item>1.2 milhas</item>
|
<item>1.2 milhas</item>
|
||||||
<item>3.1 milhas (sinal de GPS ruim)</item>
|
<item>3.1 milhas (sinal de GPS ruim)</item>
|
||||||
</array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Task frequency -->
|
||||||
<!-- Split frequency -->
|
<string-array name="task_frequency_options">
|
||||||
<string-array name="split_frequency_options">
|
<item>Desligado</item>
|
||||||
<item>Sem divisões</item>
|
|
||||||
<item>100 km</item>
|
<item>100 km</item>
|
||||||
<item>50 km</item>
|
<item>50 km</item>
|
||||||
<item>25 km</item>
|
<item>25 km</item>
|
||||||
@@ -135,8 +118,8 @@ limitations under the License.
|
|||||||
<item>1 min</item>
|
<item>1 min</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="task_frequency_options_ft">
|
||||||
<item>Sem divisões</item>
|
<item>Desligado</item>
|
||||||
<item>100 mi</item>
|
<item>100 mi</item>
|
||||||
<item>50 mi</item>
|
<item>50 mi</item>
|
||||||
<item>25 mi</item>
|
<item>25 mi</item>
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ limitations under the License.
|
|||||||
<!-- Used by the Menu -->
|
<!-- Used by the Menu -->
|
||||||
<string name="start_recording">Gravar caminho</string>
|
<string name="start_recording">Gravar caminho</string>
|
||||||
<string name="stop_recording">Para gravação</string>
|
<string name="stop_recording">Para gravação</string>
|
||||||
<string name="switch_to_sat">Modo do satélite"</string>
|
<string name="switch_to_sat">Modo do satélite</string>
|
||||||
<string name="switch_to_map">Modo do mapa"</string>
|
<string name="switch_to_map">Modo do mapa</string>
|
||||||
<string name="mylocation">Minha Localização"</string>
|
<string name="mylocation">Minha Localização</string>
|
||||||
<string name="list_tracks">Caminhos</string>
|
<string name="list_tracks">Caminhos</string>
|
||||||
<string name="list_markers">Marcadores</string>
|
<string name="list_markers">Marcadores</string>
|
||||||
<string name="delete_all_tracks">Apagar todos os caminhos</string>
|
<string name="delete_all_tracks">Apagar todos os caminhos</string>
|
||||||
@@ -31,10 +31,10 @@ limitations under the License.
|
|||||||
<string name="current_segment">Último segmento</string>
|
<string name="current_segment">Último segmento</string>
|
||||||
|
|
||||||
<!-- Error messages -->
|
<!-- Error messages -->
|
||||||
<string name="error_no_location_manager">Gerenciador de localização não encontrado neste dispositivo!"</string>
|
<string name="error_no_location_manager">Gerenciador de localização não encontrado neste dispositivo!</string>
|
||||||
<string name="error_no_gps_location_provider">"Provedor de posição de GPS não encontrado neste dispositivo."</string>
|
<string name="error_no_gps_location_provider">"Provedor de posição de GPS não encontrado neste dispositivo.</string>
|
||||||
<string name="error_sending_to_fusiontables">Ocorreu um erro ao enviar seu caminho para o Google Fusion Tables. Por favor tente novamente mais tarde."</string>
|
<string name="error_sending_to_fusiontables">Ocorreu um erro ao enviar seu caminho para o Google Fusion Tables. Por favor tente novamente mais tarde.</string>
|
||||||
<string name="error_sending_to_docs">Ocorreu um erro ao enviar seu caminho para o Google Docs. Por favor tente novamente mais tarde."</string>
|
<string name="error_sending_to_docs">Ocorreu um erro ao enviar seu caminho para o Google Docs. Por favor tente novamente mais tarde.</string>
|
||||||
<string name="error_unable_to_start_recording">Impossível iniciar a gravação. Tente novamente.</string>
|
<string name="error_unable_to_start_recording">Impossível iniciar a gravação. Tente novamente.</string>
|
||||||
<string name="error_unable_to_stop_recording">Impossível interromper a gravação. Tente novamente.</string>
|
<string name="error_unable_to_stop_recording">Impossível interromper a gravação. Tente novamente.</string>
|
||||||
<string name="error_unable_to_read_file">Impossível ler do arquivo.</string>
|
<string name="error_unable_to_read_file">Impossível ler do arquivo.</string>
|
||||||
@@ -52,7 +52,7 @@ limitations under the License.
|
|||||||
<string name="status_tracks_have_been_uploaded">Seu caminho foi enviado para maps.google.com.</string>
|
<string name="status_tracks_have_been_uploaded">Seu caminho foi enviado para maps.google.com.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_new_doc">Seu caminho foi enviado para uma nova planilha em docs.google.com.</string>
|
<string name="status_tracks_have_been_uploaded_to_new_doc">Seu caminho foi enviado para uma nova planilha em docs.google.com.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_docs">Seu caminho foi enviado para docs.google.com.</string>
|
<string name="status_tracks_have_been_uploaded_to_docs">Seu caminho foi enviado para docs.google.com.</string>
|
||||||
<string name="status_enable_gps">"Por favor pressione aqui para ir aos ajustes de segurança e localização e verifique que o GPS esteja habilitado. Pressione o botão de voltar para retornar."</string>
|
<string name="status_enable_gps">"Por favor pressione aqui para ir aos ajustes de segurança e localização e verifique que o GPS esteja habilitado. Pressione o botão de voltar para retornar.</string>
|
||||||
<string name="status_approximate_location">Nota: Uma localização aproximada, determinada por torres de telefonia celular, está sendo mostrada.</string>
|
<string name="status_approximate_location">Nota: Uma localização aproximada, determinada por torres de telefonia celular, está sendo mostrada.</string>
|
||||||
<string name="status_no_location">Sua localização não pôde ser determinada. Habilite fontes adicionais de localização (veja configurações de Segurança e Localização) e assegure-se de que o céu está visível.</string>
|
<string name="status_no_location">Sua localização não pôde ser determinada. Habilite fontes adicionais de localização (veja configurações de Segurança e Localização) e assegure-se de que o céu está visível.</string>
|
||||||
<string name="status_waypoint_inserted">Um marcador de ponto de passagem foi inserido.</string>
|
<string name="status_waypoint_inserted">Um marcador de ponto de passagem foi inserido.</string>
|
||||||
@@ -79,23 +79,24 @@ limitations under the License.
|
|||||||
<string name="marker_will_be_permanently_deleted">O marcador será permanentemente apagado deste telefone.</string>
|
<string name="marker_will_be_permanently_deleted">O marcador será permanentemente apagado deste telefone.</string>
|
||||||
|
|
||||||
<!-- Text and links when uploading to Google My Maps -->
|
<!-- Text and links when uploading to Google My Maps -->
|
||||||
<string name="new_map_description">"Criado por My Tracks no Android."</string>
|
<string name="new_map_description">"Criado por My Tracks no Android.</string>
|
||||||
<string name="fusiontable_link">"Criado por <a href='http://mytracks.appspot.com'>My Tracks</a> no Android."</string>
|
<string name="fusiontable_link">"Criado por <a href='http://mytracks.appspot.com'>My Tracks</a> no Android.</string>
|
||||||
|
|
||||||
<!-- Formatting of track and marker descriptions -->
|
<!-- Formatting of track and marker descriptions -->
|
||||||
<string name="points">Pontos</string>
|
<string name="points">Pontos</string>
|
||||||
<string name="recorded_date">Gravado"</string>
|
<string name="recorded_date">Gravado</string>
|
||||||
<string name="category">"Tipo de atividade"</string>
|
<string name="category">"Tipo de atividade</string>
|
||||||
<string name="waypoint_category">"Tipo de marcador"</string>
|
<string name="waypoint_category">"Tipo de marcador</string>
|
||||||
<string name="part">"(Parte %d)"</string>
|
<string name="part">"(Parte %d)</string>
|
||||||
|
|
||||||
<!-- Used by the track recording service -->
|
<!-- Used by the track recording service -->
|
||||||
<string name="recording_your_track">"Gravando seu caminho..."</string>
|
<string name="recording_your_track">"Gravando seu caminho...</string>
|
||||||
<string name="new_track">"Caminho %d"</string>
|
<string name="new_track">"Caminho %d</string>
|
||||||
|
|
||||||
<!-- Common -->
|
<!-- Common -->
|
||||||
<string name="no">Não</string>
|
<string name="no">Não</string>
|
||||||
<string name="yes">Sim</string>
|
<string name="yes">Sim</string>
|
||||||
|
<!-- KEEP_PARENT name="ok" rev="7cbb95c69f35" -->
|
||||||
<string name="error">Erro</string>
|
<string name="error">Erro</string>
|
||||||
<string name="success">Successo</string>
|
<string name="success">Successo</string>
|
||||||
<string name="waypoint">Ponto de passagem</string>
|
<string name="waypoint">Ponto de passagem</string>
|
||||||
@@ -122,22 +123,22 @@ limitations under the License.
|
|||||||
<string name="tracklist_btn_send_all_to_fusiontables">Enviar para o Google Fusion Tables</string>
|
<string name="tracklist_btn_send_all_to_fusiontables">Enviar para o Google Fusion Tables</string>
|
||||||
<string name="tracklist_btn_delete_all">Apagar todos os caminhos</string>
|
<string name="tracklist_btn_delete_all">Apagar todos os caminhos</string>
|
||||||
<string name="tracklist_pick_one">Escolha um caminho. Pressione&segure para mais opções.</string>
|
<string name="tracklist_pick_one">Escolha um caminho. Pressione&segure para mais opções.</string>
|
||||||
<string name="tracklist_all_tracks">Todos os Caminhos:"</string>
|
<string name="tracklist_all_tracks">Todos os Caminhos:</string>
|
||||||
<string name="tracklist_this_track">Este Caminho"</string>
|
<string name="tracklist_this_track">Este Caminho</string>
|
||||||
<string name="tracklist_share_track">Compartilhar com amigos..."</string>
|
<string name="tracklist_share_track">Compartilhar com amigos...</string>
|
||||||
<string name="tracklist_share_linkfusion">Um link para a Google Fusion Table"</string>
|
<string name="tracklist_share_link">Um link para a mapa</string>
|
||||||
<string name="tracklist_share_gpx_file">Um arquivo GPX"</string>
|
<string name="tracklist_share_gpx_file">Um arquivo GPX</string>
|
||||||
<string name="tracklist_share_kml_file">Um arquivo KML"</string>
|
<string name="tracklist_share_kml_file">Um arquivo KML</string>
|
||||||
<string name="tracklist_clear_map">"Limpar mapa"</string>
|
<string name="tracklist_clear_map">Limpar mapa</string>
|
||||||
|
|
||||||
<!-- Waypoints list -->
|
<!-- Waypoints list -->
|
||||||
<string name="waypointslist_btn_delete_all">Apagar todos os marcadores</string>
|
<string name="waypointslist_btn_delete_all">Apagar todos os marcadores</string>
|
||||||
<string name="waypointslist_this_waypoint">Este Marcador</string>
|
<string name="waypointslist_this_waypoint">Este Marcador</string>
|
||||||
<string name="waypointslist_delete_waypoint">Apagar</string>
|
<string name="waypointslist_delete_waypoint">Apagar</string>
|
||||||
<string name="waypointslist_edit_waypoint">Editar detalhes"</string>
|
<string name="waypointslist_edit_waypoint">Editar detalhes</string>
|
||||||
<string name="waypointslist_show_waypoint">Mostrar no mapa"</string>
|
<string name="waypointslist_show_waypoint">Mostrar no mapa</string>
|
||||||
<string name="waypointslist_btn_insert_waypoint">Inserir ponto no caminho"</string>
|
<string name="waypointslist_btn_insert_waypoint">Inserir ponto no caminho</string>
|
||||||
<string name="waypointslist_btn_insert_statistics">Inserir estatísticas"</string>
|
<string name="waypointslist_btn_insert_statistics">Inserir estatísticas</string>
|
||||||
<string name="waypointslist_pick_one">Escolha um marcador. Pressione&segure para mais opções.</string>
|
<string name="waypointslist_pick_one">Escolha um marcador. Pressione&segure para mais opções.</string>
|
||||||
|
|
||||||
<!-- MyTracks Details -->
|
<!-- MyTracks Details -->
|
||||||
@@ -157,6 +158,8 @@ limitations under the License.
|
|||||||
<string name="settings_display">Exibição</string>
|
<string name="settings_display">Exibição</string>
|
||||||
<string name="settings_recording">Gravação</string>
|
<string name="settings_recording">Gravação</string>
|
||||||
<string name="settings_sharing">Compartilhamento</string>
|
<string name="settings_sharing">Compartilhamento</string>
|
||||||
|
<string name="settings_not_available_summary">Não disponível na sua versão do Android</string>
|
||||||
|
<string name="settings_not_while_recording">Não disponível durante a gravação de uma trilha</string>
|
||||||
<string name="settings_announcement_frequency">Tempo entre anúncios</string>
|
<string name="settings_announcement_frequency">Tempo entre anúncios</string>
|
||||||
<string name="settings_announcement_frequency_summary">Tempo mínimo entre dois anúncios de voz</string>
|
<string name="settings_announcement_frequency_summary">Tempo mínimo entre dois anúncios de voz</string>
|
||||||
<string name="settings_min_recording_distance">Dist. mín. entre pontos</string>
|
<string name="settings_min_recording_distance">Dist. mín. entre pontos</string>
|
||||||
|
|||||||
Executable
+282
@@ -0,0 +1,282 @@
|
|||||||
|
<?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>
|
||||||
|
<!-- Minimum recording distance -->
|
||||||
|
<string-array name="min_recording_distance_options">
|
||||||
|
<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_options_ft">
|
||||||
|
<item>3 фута</item>
|
||||||
|
<item>6 футов</item>
|
||||||
|
<item>10 футов</item>
|
||||||
|
<item>13 футов</item>
|
||||||
|
<item>16 футов (рекомендуется)</item>
|
||||||
|
<item>33 фута</item>
|
||||||
|
<item>328 футов</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Maximum recording distance -->
|
||||||
|
<string-array name="max_recording_distance_options">
|
||||||
|
<item>50 м</item>
|
||||||
|
<item>100 м</item>
|
||||||
|
<item>200 м (рекомендуется)</item>
|
||||||
|
<item>500 м</item>
|
||||||
|
<item>1000 м</item>
|
||||||
|
<item>5000 м</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="max_recording_distance_options_ft">
|
||||||
|
<item>164 фута</item>
|
||||||
|
<item>328 футов</item>
|
||||||
|
<item>656 фута (рекомендуется)</item>
|
||||||
|
<item>1640 футов</item>
|
||||||
|
<item>0,6 мили</item>
|
||||||
|
<item>3,1 мили</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Minimum recording interval -->
|
||||||
|
<string-array name="min_recording_interval_options">
|
||||||
|
<item>экономия батареи (адаптивная)</item>
|
||||||
|
<item>высокая точность (адаптивная)</item>
|
||||||
|
<item>высочайшая точность (рекомендуется)</item>
|
||||||
|
<item>2 с</item>
|
||||||
|
<item>3 с</item>
|
||||||
|
<item>4 с</item>
|
||||||
|
<item>5 с</item>
|
||||||
|
<item>10 с</item>
|
||||||
|
<item>20 с</item>
|
||||||
|
<item>30 с</item>
|
||||||
|
<item>1 мин</item>
|
||||||
|
<item>2 мин</item>
|
||||||
|
<item>5 мин</item>
|
||||||
|
<item>10 мин</item>
|
||||||
|
<item>15 мин</item>
|
||||||
|
<item>30 мин</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Minimum required accuracy -->
|
||||||
|
<string-array name="min_required_accuracy_options">
|
||||||
|
<item>10 м (отличный сигнал GPS)</item>
|
||||||
|
<item>20 м</item>
|
||||||
|
<item>50 м</item>
|
||||||
|
<item>100 м</item>
|
||||||
|
<item>200 м (рекомендуется)</item>
|
||||||
|
<item>500 м</item>
|
||||||
|
<item>1000 м</item>
|
||||||
|
<item>2000 м</item>
|
||||||
|
<item>5000 м (плохой сигнал GPS)</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="min_required_accuracy_options_ft">
|
||||||
|
<item>33 фута (отличный сигнал GPS)</item>
|
||||||
|
<item>66 футов</item>
|
||||||
|
<item>165 футов</item>
|
||||||
|
<item>328 футов</item>
|
||||||
|
<item>656 футов (рекомендуется)</item>
|
||||||
|
<item>1640 футов</item>
|
||||||
|
<item>0,6 мили</item>
|
||||||
|
<item>1,2 мили</item>
|
||||||
|
<item>3,1 мили (плохой сигнал GPS)</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Task frequency -->
|
||||||
|
<string-array name="task_frequency_options">
|
||||||
|
<item>Выкл.</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="task_frequency_options_ft">
|
||||||
|
<item>Выкл.</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>Никогда</item>
|
||||||
|
<item>5 мин</item>
|
||||||
|
<item>10 мин</item>
|
||||||
|
<item>15 мин</item>
|
||||||
|
<item>Всегда</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Other non-preference arrays -->
|
||||||
|
<array name="activity_types">
|
||||||
|
<item>не определен</item>
|
||||||
|
<item>смешанного типа</item>
|
||||||
|
<item>другое</item>
|
||||||
|
|
||||||
|
<item>бег</item>
|
||||||
|
<item>бег по улице</item>
|
||||||
|
<item>бег по треку</item>
|
||||||
|
<item>бег по тропе</item>
|
||||||
|
<item>ходьба</item>
|
||||||
|
<item>быстрая ходьба</item>
|
||||||
|
<item>пешая прогулка</item>
|
||||||
|
<item>прогулка по туристической тропе</item>
|
||||||
|
<item>прогулка по бездорожью</item>
|
||||||
|
<item>восхождение</item>
|
||||||
|
|
||||||
|
<item>велосипедная прогулка</item>
|
||||||
|
<item>шоссейный велосипед</item>
|
||||||
|
<item>горный велосипед</item>
|
||||||
|
<item>велотрек</item>
|
||||||
|
|
||||||
|
<item>катание на коньках</item>
|
||||||
|
<item>катания на роликовых коньках</item>
|
||||||
|
<item>катания на роликовых коньках</item>
|
||||||
|
|
||||||
|
<item>прогулка на снегоступах</item>
|
||||||
|
<item>лыжи</item>
|
||||||
|
<item>сноубординг</item>
|
||||||
|
<item>сани</item>
|
||||||
|
<item>ледяной парусный спорт</item>
|
||||||
|
|
||||||
|
<item>парусный спорт</item>
|
||||||
|
<item>гребля</item>
|
||||||
|
<item>каякинг</item>
|
||||||
|
<item>академическая гребля</item>
|
||||||
|
<item>моторная лодка</item>
|
||||||
|
<item>паром</item>
|
||||||
|
<item>RC лодка</item>
|
||||||
|
<item>серфинг</item>
|
||||||
|
<item>виндсерфинг</item>
|
||||||
|
<item>кайтсерфинг</item>
|
||||||
|
<item>водные лыжи</item>
|
||||||
|
<item>вейкбординг</item>
|
||||||
|
|
||||||
|
<item>самолет</item>
|
||||||
|
<item>гидроплан</item>
|
||||||
|
<item>коммерческий самолет</item>
|
||||||
|
<item>вертолет</item>
|
||||||
|
<item>воздушный шар</item>
|
||||||
|
<item>дирижабль</item>
|
||||||
|
<item>RC самолет</item>
|
||||||
|
<item>RC вертолет</item>
|
||||||
|
<item>прыжки</item>
|
||||||
|
<item>планеризм</item>
|
||||||
|
<item>дельтаплан</item>
|
||||||
|
<item>парный планеризм</item>
|
||||||
|
|
||||||
|
<item>верховая езда</item>
|
||||||
|
<item>катание на лошадях</item>
|
||||||
|
<item>прогулка на осле</item>
|
||||||
|
|
||||||
|
<item>вождение автомобиля</item>
|
||||||
|
<item>вождение автобуса</item>
|
||||||
|
<item>поезд</item>
|
||||||
|
<item>мотоцикл</item>
|
||||||
|
<item>Байк</item>
|
||||||
|
<item>ATV</item>
|
||||||
|
|
||||||
|
<item>парусный спорт на земле</item>
|
||||||
|
<item>фрисби</item>
|
||||||
|
<item>алтимат фризби</item>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<array name="waypoint_types">
|
||||||
|
<item>банкомат</item>
|
||||||
|
<item>банк</item>
|
||||||
|
<item>бар</item>
|
||||||
|
<item>барбекю</item>
|
||||||
|
<item>здание</item>
|
||||||
|
<item>автобусная остановка</item>
|
||||||
|
<item>кафе</item>
|
||||||
|
<item>костер</item>
|
||||||
|
<item>лагерь</item>
|
||||||
|
<item>церковь</item>
|
||||||
|
<item>кофейня</item>
|
||||||
|
<item>удобный магазин</item>
|
||||||
|
<item>питьевая вода</item>
|
||||||
|
<item>оползень</item>
|
||||||
|
<item>паром</item>
|
||||||
|
<item>камин</item>
|
||||||
|
<item>пожарная станция</item>
|
||||||
|
<item>рыболовство</item>
|
||||||
|
<item>автозаправочная станция</item>
|
||||||
|
<item>поле для гольфа</item>
|
||||||
|
<item>продуктовый магазин</item>
|
||||||
|
<item>парикмахерская</item>
|
||||||
|
<item>гавань</item>
|
||||||
|
<item>тропа</item>
|
||||||
|
<item>отель</item>
|
||||||
|
<item>дом</item>
|
||||||
|
<item>информация</item>
|
||||||
|
<item>пересечение</item>
|
||||||
|
<item>почтовый ящик</item>
|
||||||
|
<item>рынок</item>
|
||||||
|
<item>место встречи</item>
|
||||||
|
<item>опера</item>
|
||||||
|
<item>парковка</item>
|
||||||
|
<item>почтовое отделение</item>
|
||||||
|
<item>выбоина</item>
|
||||||
|
<item>полицейский участок</item>
|
||||||
|
<item>железнодорожный переезд</item>
|
||||||
|
<item>ресторан</item>
|
||||||
|
<item>покупки</item>
|
||||||
|
<item>вид</item>
|
||||||
|
<item>магазин</item>
|
||||||
|
<item>бассейн</item>
|
||||||
|
<item>телефон</item>
|
||||||
|
<item>театр</item>
|
||||||
|
<item>туалет</item>
|
||||||
|
<item>туристическая информация</item>
|
||||||
|
<item>туннель</item>
|
||||||
|
<item>дерево</item>
|
||||||
|
<item>водопад</item>
|
||||||
|
<item>фонтан</item>
|
||||||
|
<item>путевая точка</item>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<array name="sensor_type_options">
|
||||||
|
<item>Нет</item>
|
||||||
|
<item>ANT+ Sensors</item>
|
||||||
|
<item>SRM ANT+ Bridge</item>
|
||||||
|
<item>Zephyr Bluetooth</item>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,501 @@
|
|||||||
|
<?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>
|
||||||
|
<!-- Used by the Menu -->
|
||||||
|
<string name="start_recording">Запись трека</string>
|
||||||
|
<string name="stop_recording">Остановить запись</string>
|
||||||
|
<string name="switch_to_sat">Режим спутника</string>
|
||||||
|
<string name="switch_to_map">Режим карты</string>
|
||||||
|
<string name="mylocation">Мое местоположение</string>
|
||||||
|
<string name="list_tracks">Треки</string>
|
||||||
|
<string name="list_markers">Маркеры</string>
|
||||||
|
<string name="delete_all_tracks">Удалить все треки</string>
|
||||||
|
<string name="settings">Настройки</string>
|
||||||
|
<string name="elevation">Высота</string>
|
||||||
|
<string name="choose_track_message">Пожалуйста, выберите трек для просмотра</string>
|
||||||
|
<string name="current_track">Текущий трек</string>
|
||||||
|
<string name="current_segment">Последний сегмент</string>
|
||||||
|
<string name="sensor_state">Состояние датчика</string>
|
||||||
|
<string name="aggregated_stats">Совокупная статистика</string>
|
||||||
|
|
||||||
|
<!-- Error messages -->
|
||||||
|
<string name="error_no_location_manager">На этом устройстве не был обнаружен диспетчер местоположения!</string>
|
||||||
|
<string name="error_no_gps_location_provider">На этом устройстве не был обнаружен поставщик GPS местоположения.</string>
|
||||||
|
<string name="error_sending_to_mymap">Ошибка при отправке вашего трека в Google \"Мои карты\".</string>
|
||||||
|
<string name="error_sending_to_fusiontables">Ошибка при отправке вашего трека в Google Fusion Tables.</string>
|
||||||
|
<string name="error_sending_to_docs">Ошибка при отправке вашего трека в Google Документы.</string>
|
||||||
|
<string name="error_please_try_again_later">Пожалуйста, повторите попытку позже.</string>
|
||||||
|
<string name="error_unable_to_start_recording">Не удалось начать запись. Попробуйте еще раз.</string>
|
||||||
|
<string name="error_unable_to_stop_recording">Не удалось остановить запись. Попробуйте еще раз.</string>
|
||||||
|
<string name="error_unable_to_read_file">Не удалось прочитать из файла.</string>
|
||||||
|
<string name="error_invalid_gpx_format">Неверный формат GPX файла.</string>
|
||||||
|
<string name="error_generic">Произошла ошибка. Пожалуйста, попробуйте еще раз.</string>
|
||||||
|
<string name="error_track_does_not_exist">Трек не существует.</string>
|
||||||
|
<string name="error_out_of_memory">Этот файл слишком большой (должен быть меньше, чем 500 КБ). Прервано.</string>
|
||||||
|
<string name="error_unable_to_insert_marker">Невозможно вставить маркер. Местоположение неизвестно.</string>
|
||||||
|
|
||||||
|
<!-- Status messages -->
|
||||||
|
<string name="wait_for_fix">Ожидание сигнала GPS. Убедитесь в том, что вы находитесь под открытым небом.</string>
|
||||||
|
<string name="status_now_recording">Записывается новый трек.</string>
|
||||||
|
<string name="status_stopped_recording">Запись вашего трека остановлена.</string>
|
||||||
|
<string name="status_new_mymap_has_been_created">Новая Google \"Мои карты\" была создана на maps.google.com.</string>
|
||||||
|
<string name="status_new_fusiontable_has_been_created">Новая таблица Google Fusion была создана на google.com/fusiontables.</string>
|
||||||
|
<string name="status_tracks_have_been_uploaded">Твой трек был отправлен на maps.google.com.</string>
|
||||||
|
<string name="status_tracks_have_been_uploaded_to_new_doc">Ваш трек был отправлен в новую электронную таблицу на docs.google.com.</string>
|
||||||
|
<string name="status_tracks_have_been_uploaded_to_docs">Ваш трек был отправлен в docs.google.com.</string>
|
||||||
|
<string name="status_mymap_info">Это может занять несколько минут, прежде чем появятся новые треки.</string>
|
||||||
|
<string name="status_enable_gps">Пожалуйста, нажмите здесь для перехода к разделу настроек Координаты и отметьте пункт \"Спутники GPS\". Для возвращения нажмите кнопку Назад.</string>
|
||||||
|
<string name="status_approximate_location">Примечание: приблизительное местоположение определено относительно вышек сотовой связи и беспроводных сетей.</string>
|
||||||
|
<string name="status_no_location">В настоящее время местоположение не может быть определено. Включите больше источников местоположение (см. раздел настроек Координаты) и убедитесь в том, что находитесь под открытым небом. Повторите попытку позднее.</string>
|
||||||
|
<string name="status_waypoint_inserted">Маркер путевой точки был вставлен.</string>
|
||||||
|
<string name="status_statistics_inserted">Маркер статистики был вставлен.</string>
|
||||||
|
<string name="status_track_upload_status">Статус загрузки:</string>
|
||||||
|
|
||||||
|
<!-- Progress dialog -->
|
||||||
|
<string name="progress_title">Пожалуйста, подождите...</string>
|
||||||
|
<string name="progress_message">Отправка вашего трека в Google.</string>
|
||||||
|
<string name="progress_message_reading_track">Чтение трека...</string>
|
||||||
|
<string name="progress_message_preparing_track">Подготовка трека...</string>
|
||||||
|
<string name="progress_message_authenticating_fusiontables">Аутентификация на Google Fusion Tables...</string>
|
||||||
|
<string name="progress_message_authenticating_mymaps">Аутентификация на Google Карты...</string>
|
||||||
|
<string name="progress_message_authenticating_docs">Аутентификация в Google Документы...</string>
|
||||||
|
<string name="progress_message_sending_docs">Отправка трека в Google Документы...</string>
|
||||||
|
<string name="progress_message_sending_mymaps">Отправка трека в Google Карты...</string>
|
||||||
|
<string name="progress_message_creating_map">Создание новой \"Моей карты\" ...</string>
|
||||||
|
<string name="progress_message_sending_fusiontables">Отправка трека в Fusion Tables...</string>
|
||||||
|
<string name="progress_message_creating_fusiontable">Создание новой Fusion table...</string>
|
||||||
|
<string name="import_progress_message">Импорт GPS трека. Это может занять некоторое время.</string>
|
||||||
|
<string name="write_progress_message">Запись файла на SD карту. Это может занять некоторое время.</string>
|
||||||
|
<string name="progress_message_updating_track">Обновление статистики трека...</string>
|
||||||
|
|
||||||
|
<!-- Used by DeleteAllDataHandler -->
|
||||||
|
<string name="are_you_sure_question">Вы уверены?</string>
|
||||||
|
<string name="all_data_will_be_permanently_deleted">Все треки и маркеры будут удалены с этого телефона.</string>
|
||||||
|
<string name="track_will_be_permanently_deleted">Трек и его маркеры будут удалены из этого телефона.</string>
|
||||||
|
<string name="marker_will_be_permanently_deleted">Маркер будет удален с этого телефона.</string>
|
||||||
|
|
||||||
|
<!-- Text and links when uploading to Google Fusion Tables -->
|
||||||
|
<string name="new_map_description">Создано My Tracks на Android.</string>
|
||||||
|
<string name="fusiontable_link">Создано <a href=\'http://mytracks.appspot.com\'>My Tracks</a> на Android.</string>
|
||||||
|
|
||||||
|
<!-- Text and links when uploading to Google My Maps -->
|
||||||
|
<string name="my_map_link">Создано <a href=\'http://mytracks.appspot.com\'>My Tracks</a> на Android.</string>
|
||||||
|
<string name="new_map_title">Новая карта</string>
|
||||||
|
|
||||||
|
<!-- Formatting of track and marker descriptions -->
|
||||||
|
<string name="points">Точки</string>
|
||||||
|
<string name="recorded_date">Записан</string>
|
||||||
|
<string name="category">Тип деятельности</string>
|
||||||
|
<string name="waypoint_category">Тип маркера</string>
|
||||||
|
<string name="part">(Часть %d)</string>
|
||||||
|
|
||||||
|
<!-- Used by the track recording service -->
|
||||||
|
<string name="recording_your_track">Запись трека...</string>
|
||||||
|
<string name="new_track">Трек %d</string>
|
||||||
|
|
||||||
|
<!-- Common -->
|
||||||
|
<string name="no">Нет</string>
|
||||||
|
<string name="yes">Да</string>
|
||||||
|
<string name="ok">ОК</string>
|
||||||
|
<string name="error">Ошибка</string>
|
||||||
|
<string name="success">Готово</string>
|
||||||
|
<string name="waypoint">Путевая точка</string>
|
||||||
|
<string name="license">Лицензия</string>
|
||||||
|
<string name="cancel">Отмена</string>
|
||||||
|
<string name="close">Закрыть</string>
|
||||||
|
<string name="edit">Правка</string>
|
||||||
|
<string name="save">Сохранить</string>
|
||||||
|
|
||||||
|
<!-- Placemark labels for start and end of track -->
|
||||||
|
<string name="start">(Старт)</string>
|
||||||
|
<string name="end">(Конец)</string>
|
||||||
|
|
||||||
|
<!-- TrackList -->
|
||||||
|
<string name="tracklist_show_track">Показать</string>
|
||||||
|
<string name="tracklist_send_to_mymaps">Отправить в Google \"Мои карты\"</string>
|
||||||
|
<string name="tracklist_send_to_new_mymap">Отправить в новый Google \"Мои карты\"</string>
|
||||||
|
<string name="tracklist_send_to_fusiontables">Отправить в Google Fusion Tables</string>
|
||||||
|
<string name="tracklist_send_to_new_fusiontable">Отправить в новую Google Fusion Table</string>
|
||||||
|
<string name="tracklist_send_to_docs">Отправить в Google Документы</string>
|
||||||
|
<string name="tracklist_send_to_google">Отправить в Google ...</string>
|
||||||
|
<string name="tracklist_delete_track">Удалить из телефона...</string>
|
||||||
|
<string name="tracklist_edit_track">Править детали</string>
|
||||||
|
<string name="tracklist_write_to_sd">Записать на SD карту...</string>
|
||||||
|
<string name="tracklist_save_as_gpx">Сохранить файл GPX</string>
|
||||||
|
<string name="tracklist_save_as_kml">Сохранить файл KML</string>
|
||||||
|
<string name="tracklist_save_as_csv">Сохранить файл CSV</string>
|
||||||
|
<string name="tracklist_save_as_tcx">Сохранить файл TCX</string>
|
||||||
|
<string name="tracklist_btn_send_all_to_fusiontables">Отправить в Google Fusion Tables</string>
|
||||||
|
<string name="tracklist_btn_send_all_to_mymaps">Отправить в Google \"Мои карты\"</string>
|
||||||
|
<string name="tracklist_btn_delete_all">Удалить все</string>
|
||||||
|
<!-- Export All -->
|
||||||
|
<string name="tracklist_btn_export_all">Экспорт всех</string>
|
||||||
|
<string name="export_done">Экспорт закончен</string>
|
||||||
|
<string name="tracklist_pick_one">Выберите трек. Нажмите и удерживайте для получения дополнительных возможностей.</string>
|
||||||
|
<string name="tracklist_all_tracks">Все треки:</string>
|
||||||
|
<string name="tracklist_this_track">Этот трек</string>
|
||||||
|
<string name="tracklist_share_track">Поделиться с друзьями...</string>
|
||||||
|
<string name="tracklist_share_link">Ссылка на карту</string>
|
||||||
|
<string name="tracklist_share_gpx_file">Файл GPX</string>
|
||||||
|
<string name="tracklist_share_kml_file">Файл KML</string>
|
||||||
|
<string name="tracklist_share_csv_file">Файла CSV</string>
|
||||||
|
<string name="tracklist_share_tcx_file">Файл TCX</string>
|
||||||
|
<string name="tracklist_clear_map">Очистить карту</string>
|
||||||
|
<!-- Import All -->
|
||||||
|
<string name="tracklist_btn_import_all">Импорт всех</string>
|
||||||
|
<string name="import_done">Импорт закончен</string>
|
||||||
|
<!-- Format:
|
||||||
|
$1 : Successful imports
|
||||||
|
$2 : Attempted imports
|
||||||
|
$3 : MyTracks gpx path
|
||||||
|
-->
|
||||||
|
<string name="import_done">Импортировано %1$d из %2$d GPX файлов с %3$s</string>
|
||||||
|
<string name="import_empty">GPX файлы не найденны в %s. Возможно не читается SD-карта или каталог не содержит GPX файлы.</string>
|
||||||
|
<string name="import_error">Ошибка импорта файла %s</string>
|
||||||
|
|
||||||
|
<!-- Waypoints list -->
|
||||||
|
<string name="waypointslist_btn_delete_all">Удалить все маркеры</string>
|
||||||
|
<string name="waypointslist_this_waypoint">Этот маркер</string>
|
||||||
|
<string name="waypointslist_delete_waypoint">Удалить</string>
|
||||||
|
<string name="waypointslist_edit_waypoint">Править детали</string>
|
||||||
|
<string name="waypointslist_show_waypoint">Показать на карте</string>
|
||||||
|
<string name="waypointslist_btn_insert_waypoint">Вставить путевую точку</string>
|
||||||
|
<string name="waypointslist_btn_insert_statistics">Вставить статистику</string>
|
||||||
|
<string name="waypointslist_pick_one">Выберите маркер. Нажмите и удерживайте для получения дополнительных возможностей.</string>
|
||||||
|
|
||||||
|
<!-- MyTracks Details -->
|
||||||
|
<string name="trackdetails_title">Трек детали</string>
|
||||||
|
<string name="trackdetails_name">Название трека</string>
|
||||||
|
<string name="trackdetails_description">Описание трека</string>
|
||||||
|
<string name="trackdetails_category">Тип деятельности (например: пешая прогулка, велосипедная прогулка, бег, восхождение...)</string>
|
||||||
|
|
||||||
|
<!-- MyTracks Waypoint Details -->
|
||||||
|
<string name="waypointdetails_title">Маркер детали</string>
|
||||||
|
<string name="waypointdetails_name">Имя маркера</string>
|
||||||
|
<string name="waypointdetails_description">Описание маркера</string>
|
||||||
|
<string name="waypointdetails_category">Тип маркера (например: здание, выбоина, достопримечательность...)</string>
|
||||||
|
|
||||||
|
<!-- MyTracks Settings -->
|
||||||
|
<string name="mytracks_settings">Настройки My Tracks</string>
|
||||||
|
<string name="settings_display">Отображение</string>
|
||||||
|
<string name="settings_recording">Запись</string>
|
||||||
|
<string name="settings_sharing">Обмен</string>
|
||||||
|
|
||||||
|
<string name="settings_not_available_summary">Не доступен в вашем версии Android</string>
|
||||||
|
<string name="settings_not_while_recording">Не доступно во время записи трека</string>
|
||||||
|
|
||||||
|
<string name="settings_announcement_frequency">Частота объявлений</string>
|
||||||
|
<string name="settings_announcement_frequency_summary">Минимальное время между двумя голосовыми объявлениями</string>
|
||||||
|
|
||||||
|
<string name="settings_min_recording_distance">Минимальное расстояние между точками</string>
|
||||||
|
<string name="settings_min_recording_distance_summary">Наименьшее расстояние между двумя записями вашей позиции</string>
|
||||||
|
|
||||||
|
<string name="settings_max_recording_distance">Максимальное расстояние между точками</string>
|
||||||
|
<string name="settings_max_recording_distance_summary">Если два пункта находятся дальше, чем указано, то трек будет разделен</string>
|
||||||
|
|
||||||
|
<string name="settings_min_recording_interval">Минимальное время между точками</string>
|
||||||
|
<string name="settings_min_recording_interval_summary">Наименьший интервал времени между двумя записями вашей позиции</string>
|
||||||
|
|
||||||
|
<string name="settings_min_required_accuracy">Минимальная точность</string>
|
||||||
|
<string name="settings_min_required_accuracy_summary">Запись будет приостановлена, если ваша позиция не является достаточно точной</string>
|
||||||
|
|
||||||
|
<string name="settings_metric_units">Использовать метрические единицы</string>
|
||||||
|
<string name="settings_metric_units_summary_on">Все расстояния будут отображаться в метрических единицах</string>
|
||||||
|
<string name="settings_metric_units_summary_off">Все расстояния будут отображаться в имперских единицах</string>
|
||||||
|
|
||||||
|
<string name="settings_map_public">Обнародовать карты</string>
|
||||||
|
<string name="settings_map_public_summary_on">Загруженные карты будут общедоступны на maps.google.com</string>
|
||||||
|
<string name="settings_map_public_summary_off">Загруженные карты не будут перечислены публично на maps.google.com</string>
|
||||||
|
|
||||||
|
<string name="settings_report_speed_or_pace">Отображать скорость</string>
|
||||||
|
<string name="settings_report_speed_or_pace_summary_on">Скорость будет отображаться</string>
|
||||||
|
<string name="settings_report_speed_or_pace_summary_off">Темп будет отображаться</string>
|
||||||
|
|
||||||
|
<string name="settings_share_url_only">Поделиться только URL</string>
|
||||||
|
<string name="settings_share_url_only_summary_on">При обмене будет отправлен только URL-адрес</string>
|
||||||
|
<string name="settings_share_url_only_summary_off">Содержимое трека будет также включено при обмене</string>
|
||||||
|
|
||||||
|
<string name="settings_split_frequency">Частота деления</string>
|
||||||
|
<string name="settings_split_frequency_summary">Максимальное время или расстояние, после которого будет вставлен новый маркер деления</string>
|
||||||
|
|
||||||
|
<string name="settings_auto_resume_track_timeout">Автоматическое возобновление трек тайм-аут</string>
|
||||||
|
<string name="settings_auto_resume_track_timeout_summary">Максимальное время в минутах, после которого предыдущая запись трека не будет возобновлена на перезагруженном телефоне</string>
|
||||||
|
|
||||||
|
<string name="settings_timestamp_track_name">Штамп времени как название дорожки</string>
|
||||||
|
<string name="settings_timestamp_track_name_summary_on">По умолчанию имя трека будет складываться из даты и времени старта трека</string>
|
||||||
|
<string name="settings_timestamp_track_name_summary_off">Названия треков будут иметь прирост чисел для каждого нового трека.</string>
|
||||||
|
|
||||||
|
<string name="settings_reset">Восстановить значения по умолчанию</string>
|
||||||
|
<string name="settings_reset_summary">Восстановить значения по умолчанию во всех настройках</string>
|
||||||
|
<string name="settings_reset_dialog_message">Все ваши настройки будут стерты и восстановлены значения по умолчанию. Записанные треки будут сохранены. Вы уверены?</string>
|
||||||
|
<string name="settings_reset_done">Все настройки были возвращены к значениям по умолчанию.</string>
|
||||||
|
|
||||||
|
<string name="pace_label">Темп</string>
|
||||||
|
|
||||||
|
<string name="eclair_required">Поддерживается только в Android 2.0 или выше</string>
|
||||||
|
<string name="settings_sensor_type">Тип датчика</string>
|
||||||
|
<string name="settings_sensor_type_summary">Тип подключенного датчика</string>
|
||||||
|
<string name="settings_heart_rate_ant_sensor_id">Очистить ANT подсоединенного датчика пульса</string>
|
||||||
|
<string name="settings_power_ant_sensor_id">Очистить ANT подсоединенного датчика мощности</string>
|
||||||
|
<string name="settings_srm_bridge_ant_sensor_id">Очистить ANT подсоединенного датчика SRM</string>
|
||||||
|
<string name="settings_ant_not_paired">ANT датчик не подсоединен</string>
|
||||||
|
<string name="settings_ant_paired">ANT датчик подсоединен с: %d</string>
|
||||||
|
<string name="bluetooth_sensor_title">Bluetooth датчик</string>
|
||||||
|
<string name="bluetooth_sensor_summary">Подключенный bluetooth датчик</string>
|
||||||
|
<string name="settings_modular_stats_display_title">Отображение модульной статистики</string>
|
||||||
|
|
||||||
|
<!-- Backups -->
|
||||||
|
<string name="settings_backup">Резервное копирование (BETA)</string>
|
||||||
|
<string name="settings_sd_backup">Резервное копирование SD карты</string>
|
||||||
|
<string name="settings_backup_to_sd">Резервировать</string>
|
||||||
|
<string name="settings_backup_to_sd_summary">Создать полную копию всех ваших треков и настроек на SD карту</string>
|
||||||
|
<string name="settings_restore_from_sd">Восстановить</string>
|
||||||
|
<string name="settings_restore_from_sd_summary">Восстановить все треки и параметры с SD карты</string>
|
||||||
|
|
||||||
|
<string name="restore_overwrites_warning">Восстановление резервной копии с SD карты ПЕРЕЗАПИШЕТ все текущие треки и настройки. Вы уверены?</string>
|
||||||
|
<string name="select_backup_to_restore">Выберите резервную копию для восстановления</string>
|
||||||
|
<string name="no_backups">Резервные копии не найдены.</string>
|
||||||
|
<string name="backup_write_progress_message">Запись на SD-карту всех треков и настроек. Это может занять некоторое время...</string>
|
||||||
|
<string name="backup_import_progress_message">Чтение всех треков и настроек с SD-карты. Это может занять некоторое время...</string>
|
||||||
|
|
||||||
|
<!-- MyTracksSky -->
|
||||||
|
<string name="mytracks_sky">Спутники GPS</string>
|
||||||
|
|
||||||
|
<!-- My Maps -->
|
||||||
|
<string name="select_map_message">Выберите карту из вашей учетной записи:</string>
|
||||||
|
<string name="create_new_map">Создать новую карту...</string>
|
||||||
|
<string name="map_list_title">Отправить в Google \"Мои карты\"</string>
|
||||||
|
<string name="maps_list_loading">Загрузка карты ...</string>
|
||||||
|
<string name="maps_list_failed">Ваши карты не могут быть загружены в данный момент!</string>
|
||||||
|
<string name="open_map">Выберите эту карту</string>
|
||||||
|
<string name="edit_map_details">Править детали карты</string>
|
||||||
|
<string name="share_track">Поделиться треком</string>
|
||||||
|
<string name="delete_map">Удалить Карту из вашей учетной записи</string>
|
||||||
|
<string name="map_title">Название карты:</string>
|
||||||
|
<string name="map_description">Описание карты:</string>
|
||||||
|
<string name="map_searchable_edit">Сделать чтобы карта и ее содержимое отображались в результатах поиска</string>
|
||||||
|
<string name="map_not_searchable_edit">Не позволить этой карте или ее содержимому отображаться в результатах поиска, хотя они все еще могут просматриваться другими через прямой URL-адрес</string>
|
||||||
|
<string name="map_searchable">Эта карта и ее содержимое будут отображаться в результатах поиска</string>
|
||||||
|
<string name="map_not_searchable">Ни эта карта, ни ее содержимое не будут отображаться в результатах поиска, но их могут по-прежнему просматривать другие через прямую ссылку</string>
|
||||||
|
|
||||||
|
<!-- Sharing -->
|
||||||
|
<string name="share_map">Поделиться картой с друзьями</string>
|
||||||
|
<string name="share_map_subject">Я хотел бы поделиться с вами треком</string>
|
||||||
|
<string name="share_map_body_format">Я думаю, вы можете быть заинтересованы в этом треке:
|
||||||
|
|
||||||
|
%s</string>
|
||||||
|
<string name="send_track_subject">Я хотел бы поделиться с вами треком</string>
|
||||||
|
<string name="send_track_body_format">Я думаю, вы можете быть заинтересованы в этом треке.
|
||||||
|
|
||||||
|
Просмотреть трек можно с помощью Google Планета Земля или другого программного обоспечения для карт.</string>
|
||||||
|
|
||||||
|
<!-- Visibility -->
|
||||||
|
<string name="public_map">Общественные</string>
|
||||||
|
<string name="unlisted_map">Частные</string>
|
||||||
|
<string name="mapslist_no_maps_available">У вас пока еще нет карт.</string>
|
||||||
|
|
||||||
|
<!-- Statistics View -->
|
||||||
|
<!-- Average Moving -->
|
||||||
|
<string name="average_moving_speed_label">Средняя скорость движения</string>
|
||||||
|
<string name="average_moving_pace_label">Средний темп движения</string>
|
||||||
|
|
||||||
|
<!-- Average -->
|
||||||
|
<string name="average_speed_label">Средняя скорость</string>
|
||||||
|
<string name="average_pace_label">Средний темп</string>
|
||||||
|
|
||||||
|
<string name="elevation_chart_name">Диаграмма высоты</string>
|
||||||
|
<string name="elevation_gain_label">Набор высоты</string>
|
||||||
|
<string name="elevation_label">Высота</string>
|
||||||
|
<string name="latitude_label">Широта</string>
|
||||||
|
<string name="longitude_label">Долгота</string>
|
||||||
|
|
||||||
|
<!-- Min -->
|
||||||
|
<string name="min_elevation_label">Минимальная высота</string>
|
||||||
|
<string name="min_grade_label">Минимальный уклон</string>
|
||||||
|
<string name="min_pace_label">Минимальный темп</string>
|
||||||
|
|
||||||
|
<!-- Max -->
|
||||||
|
<string name="max_elevation_label">Максимальная высота</string>
|
||||||
|
<string name="max_grade_label">Максимальный уклон</string>
|
||||||
|
<string name="max_speed_label">Максимальная скорость</string>
|
||||||
|
|
||||||
|
<string name="loading_track">Загрузка трека...</string>
|
||||||
|
|
||||||
|
<!-- Chart Settings -->
|
||||||
|
<string name="chart_settings">Настройки диаграммы</string>
|
||||||
|
<!-- X Axis -->
|
||||||
|
<string name="x_axis">Ось X</string>
|
||||||
|
<string name="by_distance">По расстоянию</string>
|
||||||
|
<string name="by_time">По времени</string>
|
||||||
|
|
||||||
|
<!-- Y Axis -->
|
||||||
|
<string name="y_axis">Ось Y</string>
|
||||||
|
|
||||||
|
<!-- Units -->
|
||||||
|
<!-- Time -->
|
||||||
|
<string name="hour">час</string>
|
||||||
|
<string name="hours">часов</string>
|
||||||
|
<string name="hr">ч</string>
|
||||||
|
<string name="min">мин</string>
|
||||||
|
<string name="minute">минута</string>
|
||||||
|
<string name="minutes">минут</string>
|
||||||
|
<string name="second">секунда</string>
|
||||||
|
<string name="seconds">секунд</string>
|
||||||
|
<string name="milliseconds">мс</string>
|
||||||
|
|
||||||
|
<!-- Distance -->
|
||||||
|
<string name="meter">м</string>
|
||||||
|
<string name="kilometer">км</string>
|
||||||
|
<string name="kilometers_long">километров</string>
|
||||||
|
<string name="feet">футов</string>
|
||||||
|
<string name="mile">миль</string>
|
||||||
|
<string name="miles_long">мили</string>
|
||||||
|
|
||||||
|
<!-- Speed and Pace -->
|
||||||
|
<string name="kilometer_per_hour">км/ч</string>
|
||||||
|
<string name="kilometer_per_hour_long">километров в час</string>
|
||||||
|
<string name="min_per_kilometer">мин/км</string>
|
||||||
|
<string name="per_kilometer">за километр</string>
|
||||||
|
<string name="mile_per_hour">миль/ч</string>
|
||||||
|
<string name="mile_per_hour_long">миль в час</string>
|
||||||
|
<string name="min_per_mile">мин/миля</string>
|
||||||
|
<string name="per_mile">за милю</string>
|
||||||
|
|
||||||
|
<!-- Sensors -->
|
||||||
|
<string name="watts">Вт</string>
|
||||||
|
|
||||||
|
<string name="revolutions_per_minute">об/мин</string>
|
||||||
|
<string name="bpm">bpm</string>
|
||||||
|
|
||||||
|
<!-- Stats Labels -->
|
||||||
|
<string name="moving_time_label">Время движения</string>
|
||||||
|
<string name="total_time_label">Общее время</string>
|
||||||
|
<string name="time_label">Время</string>
|
||||||
|
<string name="sd_unavail">SD карта недоступна</string>
|
||||||
|
<string name="speed">Скорость</string>
|
||||||
|
<string name="start_trip">Вы должны начать путешествие.</string>
|
||||||
|
<string name="statistics">Статистика</string>
|
||||||
|
<string name="total_distance_label">Общее расстояние</string>
|
||||||
|
<string name="distance_label">Расстояние</string>
|
||||||
|
<string name="power">Мощность</string>
|
||||||
|
<string name="cadence">Каденс</string>
|
||||||
|
<string name="heart_rate">Пульс</string>
|
||||||
|
<string name="max_heart_rate">Максимальный пульс</string>
|
||||||
|
<string name="unknown">-</string>
|
||||||
|
<string name="waiting">Ожидание...</string>
|
||||||
|
|
||||||
|
<!-- End User License Agreement -->
|
||||||
|
<string name="eula_title">Лицензионное соглашение</string>
|
||||||
|
<string name="accept">Принять</string>
|
||||||
|
<string name="decline">Отклонить</string>
|
||||||
|
|
||||||
|
<!-- About -->
|
||||||
|
<string name="about">О программе</string>
|
||||||
|
<string name="help">Справка</string>
|
||||||
|
<string name="about_team">Команда:</string>
|
||||||
|
<string name="about_version">Версия:</string>
|
||||||
|
<string name="about_support">Поддержка:</string>
|
||||||
|
<string name="about_privacy">Приватность:</string>
|
||||||
|
|
||||||
|
<!-- Send to Google -->
|
||||||
|
<string name="sendtogoogle_title">Отправить...</string>
|
||||||
|
<string name="sendtogoogle_google_fusiontables">Google Fusion Tables</string>
|
||||||
|
<string name="sendtogoogle_google_mymaps">Google \"Мои карты\"</string>
|
||||||
|
<string name="sendtogoogle_google_docs">Google Документы</string>
|
||||||
|
<string name="sendtogoogle_send_now">Отправить</string>
|
||||||
|
<string name="sendtogoogle_create_new_map">Создать новую карту</string>
|
||||||
|
<string name="sendtogoogle_pick_existing_map">Выбрать существующую карту</string>
|
||||||
|
<string name="sendtogoogle_send_stats">Отправить статистику трека</string>
|
||||||
|
<string name="sendtogoogle_send_stats_and_points">Отправить статистику и точки</string>
|
||||||
|
|
||||||
|
<!-- Getting the account to upload to. -->
|
||||||
|
<string name="no_account_found_title">Учетная запись не найдена</string>
|
||||||
|
<string name="no_account_found">Не найдена учетная запись для загрузки треков.</string>
|
||||||
|
<string name="choose_account_title">Выбор учетной записи</string>
|
||||||
|
|
||||||
|
<!-- SD card -->
|
||||||
|
<string name="io_no_external_storage_found">Не обнаружено внешнее устройство хранения данных. Убедитесь, что SD карта вставлена, и что ваш телефон не подключен к компьютеру.</string>
|
||||||
|
<string name="io_write_failed">Невозможно записать файл.</string>
|
||||||
|
<string name="io_read_failed">Невозможно прочитать из файла.</string>
|
||||||
|
<string name="io_create_dir_failed">Невозможно создать папку на SD карте.</string>
|
||||||
|
<string name="io_write_finished">Запись на SD карту закончена.</string>
|
||||||
|
<string name="io_read_finished">Чтение с SD карты закончено.</string>
|
||||||
|
|
||||||
|
<!-- VersionChecker -->
|
||||||
|
<string name="version_check_title">Проверить обновления</string>
|
||||||
|
<string name="version_check_upgrade_button">Обновить сейчас</string>
|
||||||
|
<string name="version_check_continue_button">Продолжить без обновления</string>
|
||||||
|
<string name="upgrade_required">Ваша версия %1$S больше не может работать должным образом, и больше не поддерживается. Обновите %1$s для продолжения использования.</string>
|
||||||
|
<string name="upgrade_recommended">Ваша версия %1$S больше не может работать должным образом. Вы можете обновить ее сейчас, либо продолжать использовать ее на свой страх и риск. Некоторые функции, такие как синхронизация с сервером может не функционировать до обновления.</string>
|
||||||
|
<string name="upgrade_available">Доступна новая версия %1$s. Вы можете продолжать использовать текущую версию без проблем, но вы не получите новейшие функции, до тех пор, пока не обновитесь.</string>
|
||||||
|
|
||||||
|
<!-- Welcome -->
|
||||||
|
<string name="welcome">Добро пожаловать</string>
|
||||||
|
<string name="welcome_read_later">Ок</string>
|
||||||
|
<string name="welcome_about">О My Tracks</string>
|
||||||
|
|
||||||
|
<!-- Announcement -->
|
||||||
|
<string name="announce_no_distance">My Tracks нет расстояния</string>
|
||||||
|
<!-- Format:
|
||||||
|
$1 : Distance label
|
||||||
|
$2 : Distance value (5)
|
||||||
|
$3 : Distance units (mi, km)
|
||||||
|
$4 : Time description (10 minutes 5 seconds)
|
||||||
|
$5 : Speed value (5.6) : Pace value (5 minutes 6 seconds)
|
||||||
|
$6 : Speed units (mph) : Pace units (per mile)
|
||||||
|
-->
|
||||||
|
<string name="announce_template">Мои треки %1$s %2$.2f %3$s в %4$s на %5$s %6$s</string>
|
||||||
|
|
||||||
|
<!-- Check Units -->
|
||||||
|
<string name="check_units_title">Единицы измерения обратите внимание</string>
|
||||||
|
<string name="check_units_message">По умолчанию используются метрические единицы. Вы хотели бы изменить этот параметр?</string>
|
||||||
|
|
||||||
|
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
|
||||||
|
<string name="method_bluetooth">Bluetooth</string>
|
||||||
|
<string name="bluetooth_options">Параметры Bluetooth</string>
|
||||||
|
<string name="bluetooth_pairing">Подключение устройства</string>
|
||||||
|
<string name="bluetooth_pairing_summary">Открыть настройки Android по bluetooth для подключения устройства</string>
|
||||||
|
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
|
||||||
|
<string name="ant_options">Параметры ANT</string>
|
||||||
|
<string name="sensor_options">Параметры датчика</string>
|
||||||
|
|
||||||
|
<!-- Bluetooth Sensor -->
|
||||||
|
<string name="bluetooth_connected">Подключен к %s</string>
|
||||||
|
<string name="bluetooth_connecting">Подключение Bluetooth датчика...</string>
|
||||||
|
<string name="bluetooth_not_connected">Bluetooth датчик не подключен</string>
|
||||||
|
|
||||||
|
<!-- Sensor State -->
|
||||||
|
<string name="sensor_data_time">Датчик времени</string>
|
||||||
|
<string name="power_meter_enabled">Измеритель мощности включен</string>
|
||||||
|
<string name="heart_rate_monitor_enabled">Монитор пульса включен</string>
|
||||||
|
<string name="no_sensor_manager">Нет диспетчера датчиков</string>
|
||||||
|
<string name="enabled">Включено</string>
|
||||||
|
<string name="connecting">Подключение</string>
|
||||||
|
<string name="connected">Подключено</string>
|
||||||
|
<string name="disconnected">Отключено</string>
|
||||||
|
<string name="no_sensor_service">Нет службы датчиков</string>
|
||||||
|
<string name="searching">Поиск</string>
|
||||||
|
<string name="sending">Отправка</string>
|
||||||
|
|
||||||
|
<!-- Manifest description (not seen inside the app) -->
|
||||||
|
<string name="notification_permission_label">получать уведомления о записи трека</string>
|
||||||
|
<string name="read_tracks_permission_label">чтение записанных данных трека</string>
|
||||||
|
<string name="write_tracks_permission_label">запись данных трека, старт/стоп записи треков</string>
|
||||||
|
<string name="notification_permission_description">Получать уведомления, при старте или останове записи трека.</string>
|
||||||
|
<string name="read_tracks_permission_description">Иметь возможность читать данные трека, такие как точки и путевые точки.</string>
|
||||||
|
<string name="write_tracks_permission_description">Иметь возможность записать данные трека, такие как начало записи или добавление путевых точек.</string>
|
||||||
|
</resources>
|
||||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<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 -->
|
<!-- Minimum recording distance -->
|
||||||
<string-array name="min_recording_distance_options">
|
<string-array name="min_recording_distance_options">
|
||||||
<item>1 m</item>
|
<item>1 m</item>
|
||||||
@@ -67,7 +55,6 @@ limitations under the License.
|
|||||||
<item>3.1 miles</item>
|
<item>3.1 miles</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<!-- Minimum recording interval -->
|
<!-- Minimum recording interval -->
|
||||||
<string-array name="min_recording_interval_options">
|
<string-array name="min_recording_interval_options">
|
||||||
<item>batterioptimerad (anpassningsbar)</item>
|
<item>batterioptimerad (anpassningsbar)</item>
|
||||||
@@ -113,9 +100,9 @@ limitations under the License.
|
|||||||
<item>3.1 miles (dålig GPS-signal)</item>
|
<item>3.1 miles (dålig GPS-signal)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Split frequency -->
|
<!-- Task frequency -->
|
||||||
<string-array name="split_frequency_options">
|
<string-array name="task_frequency_options">
|
||||||
<item>Ingen delning</item>
|
<item>Av</item>
|
||||||
<item>100 km</item>
|
<item>100 km</item>
|
||||||
<item>50 km</item>
|
<item>50 km</item>
|
||||||
<item>25 km</item>
|
<item>25 km</item>
|
||||||
@@ -131,8 +118,8 @@ limitations under the License.
|
|||||||
<item>1 min</item>
|
<item>1 min</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="task_frequency_options_ft">
|
||||||
<item>Ingen delning</item>
|
<item>Av</item>
|
||||||
<item>100 mi</item>
|
<item>100 mi</item>
|
||||||
<item>50 mi</item>
|
<item>50 mi</item>
|
||||||
<item>25 mi</item>
|
<item>25 mi</item>
|
||||||
|
|||||||
@@ -131,7 +131,6 @@ limitations under the License.
|
|||||||
<string name="tracklist_all_tracks">Alla spår:</string>
|
<string name="tracklist_all_tracks">Alla spår:</string>
|
||||||
<string name="tracklist_this_track">Det här spåret</string>
|
<string name="tracklist_this_track">Det här spåret</string>
|
||||||
<string name="tracklist_share_track">Dela med vänner...</string>
|
<string name="tracklist_share_track">Dela med vänner...</string>
|
||||||
<!-- <string name="tracklist_share_linkfusion">En länk till Google Mina Kartor</string> -->
|
|
||||||
<string name="tracklist_share_gpx_file">En GPX-fil</string>
|
<string name="tracklist_share_gpx_file">En GPX-fil</string>
|
||||||
<string name="tracklist_share_kml_file">En KML-fil</string>
|
<string name="tracklist_share_kml_file">En KML-fil</string>
|
||||||
<string name="tracklist_share_csv_file">En CSV-fil</string>
|
<string name="tracklist_share_csv_file">En CSV-fil</string>
|
||||||
|
|||||||
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<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">
|
<string-array name="min_recording_distance_options">
|
||||||
<item>1 米</item>
|
<item>1 米</item>
|
||||||
@@ -112,9 +100,9 @@ limitations under the License.
|
|||||||
<item>3.1 英里 (糟糕的 GPS 信号)</item>
|
<item>3.1 英里 (糟糕的 GPS 信号)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Split frequency -->
|
<!-- Task frequency -->
|
||||||
<string-array name="split_frequency_options">
|
<string-array name="task_frequency_options">
|
||||||
<item>不分割</item>
|
<item>关闭</item>
|
||||||
<item>100 千米</item>
|
<item>100 千米</item>
|
||||||
<item>50 千米</item>
|
<item>50 千米</item>
|
||||||
<item>25 千米</item>
|
<item>25 千米</item>
|
||||||
@@ -130,8 +118,8 @@ limitations under the License.
|
|||||||
<item>1 分钟</item>
|
<item>1 分钟</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="task_frequency_options_ft">
|
||||||
<item>不分割</item>
|
<item>关闭</item>
|
||||||
<item>100 英里</item>
|
<item>100 英里</item>
|
||||||
<item>50 英里</item>
|
<item>50 英里</item>
|
||||||
<item>25 英里</item>
|
<item>25 英里</item>
|
||||||
@@ -155,6 +143,7 @@ limitations under the License.
|
|||||||
<item>15 分钟</item>
|
<item>15 分钟</item>
|
||||||
<item>总是</item>
|
<item>总是</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Other non-preference arrays -->
|
<!-- Other non-preference arrays -->
|
||||||
<array name="activity_types">
|
<array name="activity_types">
|
||||||
<item>未知</item>
|
<item>未知</item>
|
||||||
|
|||||||
@@ -132,7 +132,6 @@ limitations under the License.
|
|||||||
<string name="tracklist_all_tracks">全部轨迹:</string>
|
<string name="tracklist_all_tracks">全部轨迹:</string>
|
||||||
<string name="tracklist_this_track">此轨迹</string>
|
<string name="tracklist_this_track">此轨迹</string>
|
||||||
<string name="tracklist_share_track">与朋友分享...</string>
|
<string name="tracklist_share_track">与朋友分享...</string>
|
||||||
<string name="tracklist_share_linkfusion">链接到 Google Fusion Table</string>
|
|
||||||
<string name="tracklist_share_gpx_file">GPX 文件</string>
|
<string name="tracklist_share_gpx_file">GPX 文件</string>
|
||||||
<string name="tracklist_share_kml_file">KML 文件</string>
|
<string name="tracklist_share_kml_file">KML 文件</string>
|
||||||
<string name="tracklist_share_csv_file">CSV 文件</string>
|
<string name="tracklist_share_csv_file">CSV 文件</string>
|
||||||
@@ -220,7 +219,6 @@ limitations under the License.
|
|||||||
<string name="settings_backup_to_sd_summary">将你所有轨迹和设置的完整备份写入到 SD 存储卡</string>
|
<string name="settings_backup_to_sd_summary">将你所有轨迹和设置的完整备份写入到 SD 存储卡</string>
|
||||||
<string name="settings_restore_from_sd">立即恢复</string>
|
<string name="settings_restore_from_sd">立即恢复</string>
|
||||||
<string name="settings_restore_from_sd_summary">从 SD 存储卡恢复所有轨迹和设置</string>
|
<string name="settings_restore_from_sd_summary">从 SD 存储卡恢复所有轨迹和设置</string>
|
||||||
<string name="settings_no_backup_while_recording">在记录轨迹时无法处理备份数据.</string>
|
|
||||||
|
|
||||||
<!-- Backups -->
|
<!-- Backups -->
|
||||||
<string name="restore_overwrites_warning">从 SD 存储卡恢复备份数据将覆盖掉你当前的所有轨迹和设置. 确定要继续吗?</string>
|
<string name="restore_overwrites_warning">从 SD 存储卡恢复备份数据将覆盖掉你当前的所有轨迹和设置. 确定要继续吗?</string>
|
||||||
|
|||||||
@@ -15,31 +15,6 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<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 -->
|
<!-- Minimum recording distance -->
|
||||||
<string-array name="min_recording_distance_options">
|
<string-array name="min_recording_distance_options">
|
||||||
<item>1 m</item>
|
<item>1 m</item>
|
||||||
@@ -61,18 +36,6 @@ limitations under the License.
|
|||||||
<item>328 ft</item>
|
<item>328 ft</item>
|
||||||
</string-array>
|
</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 -->
|
<!-- Maximum recording distance -->
|
||||||
<string-array name="max_recording_distance_options">
|
<string-array name="max_recording_distance_options">
|
||||||
<item>50 m</item>
|
<item>50 m</item>
|
||||||
@@ -92,17 +55,6 @@ limitations under the License.
|
|||||||
<item>3.1 miles</item>
|
<item>3.1 miles</item>
|
||||||
</string-array>
|
</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 -->
|
<!-- Minimum recording interval -->
|
||||||
<string-array name="min_recording_interval_options">
|
<string-array name="min_recording_interval_options">
|
||||||
<item>battery miser (adaptive)</item>
|
<item>battery miser (adaptive)</item>
|
||||||
@@ -123,27 +75,6 @@ limitations under the License.
|
|||||||
<item>30 min</item>
|
<item>30 min</item>
|
||||||
</string-array>
|
</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 -->
|
<!-- Minimum required accuracy -->
|
||||||
<string-array name="min_required_accuracy_options">
|
<string-array name="min_required_accuracy_options">
|
||||||
<item>10 m (excellent GPS signal)</item>
|
<item>10 m (excellent GPS signal)</item>
|
||||||
@@ -169,23 +100,9 @@ limitations under the License.
|
|||||||
<item>3.1 miles (poor GPS signal)</item>
|
<item>3.1 miles (poor GPS signal)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- DO NOT TRANSLATE -->
|
<!-- Task frequency -->
|
||||||
<string-array name="min_required_accuracy_values">
|
<string-array name="task_frequency_options">
|
||||||
<item>10</item>
|
<item>Off</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>
|
|
||||||
<item>100 km</item>
|
<item>100 km</item>
|
||||||
<item>50 km</item>
|
<item>50 km</item>
|
||||||
<item>25 km</item>
|
<item>25 km</item>
|
||||||
@@ -201,8 +118,8 @@ limitations under the License.
|
|||||||
<item>1 min</item>
|
<item>1 min</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="split_frequency_options_ft">
|
<string-array name="task_frequency_options_ft">
|
||||||
<item>No splitting</item>
|
<item>Off</item>
|
||||||
<item>100 mi</item>
|
<item>100 mi</item>
|
||||||
<item>50 mi</item>
|
<item>50 mi</item>
|
||||||
<item>25 mi</item>
|
<item>25 mi</item>
|
||||||
@@ -218,24 +135,6 @@ limitations under the License.
|
|||||||
<item>1 min</item>
|
<item>1 min</item>
|
||||||
</string-array>
|
</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 -->
|
<!-- Auto-resume track timeout -->
|
||||||
<string-array name="auto_resume_track_timeout_options">
|
<string-array name="auto_resume_track_timeout_options">
|
||||||
<item>Never</item>
|
<item>Never</item>
|
||||||
@@ -245,16 +144,6 @@ limitations under the License.
|
|||||||
<item>Always</item>
|
<item>Always</item>
|
||||||
</string-array>
|
</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 -->
|
<!-- Other non-preference arrays -->
|
||||||
<array name="activity_types">
|
<array name="activity_types">
|
||||||
<item>unknown</item>
|
<item>unknown</item>
|
||||||
@@ -383,14 +272,6 @@ limitations under the License.
|
|||||||
<item>way point</item>
|
<item>way point</item>
|
||||||
</array>
|
</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">
|
<array name="sensor_type_options">
|
||||||
<item>None</item>
|
<item>None</item>
|
||||||
<item>ANT+ Sensors</item>
|
<item>ANT+ Sensors</item>
|
||||||
@@ -398,12 +279,4 @@ limitations under the License.
|
|||||||
<item>Zephyr Bluetooth</item>
|
<item>Zephyr Bluetooth</item>
|
||||||
</array>
|
</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>
|
|
||||||
|
|
||||||
</resources>
|
</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>
|
||||||
@@ -34,4 +34,9 @@ limitations under the License.
|
|||||||
<string name="ant_sensor_type">ANT</string>
|
<string name="ant_sensor_type">ANT</string>
|
||||||
<string name="srm_ant_bridge_sensor_type">SRM_ANT_BRIDGE</string>
|
<string name="srm_ant_bridge_sensor_type">SRM_ANT_BRIDGE</string>
|
||||||
<string name="zephyr_sensor_type">ZEPHYR</string>
|
<string name="zephyr_sensor_type">ZEPHYR</string>
|
||||||
|
|
||||||
|
<!-- Send to Google URLs -->
|
||||||
|
<string name="sendtogoogle_google_fusiontables_url">google.com/fusiontables</string>
|
||||||
|
<string name="sendtogoogle_google_mymaps_url">maps.google.com</string>
|
||||||
|
<string name="sendtogoogle_google_docs_url">docs.google.com</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ limitations under the License.
|
|||||||
<string name="send_stats_and_points_key">sendStatsAndPoints</string>
|
<string name="send_stats_and_points_key">sendStatsAndPoints</string>
|
||||||
<string name="send_to_docs_key">sendToDocs</string>
|
<string name="send_to_docs_key">sendToDocs</string>
|
||||||
<string name="send_to_my_maps_key">sendToMyMaps</string>
|
<string name="send_to_my_maps_key">sendToMyMaps</string>
|
||||||
|
<string name="send_to_fusion_tables_key">sendToFusionTables</string>
|
||||||
<string name="sensor_type_key">sensorType</string>
|
<string name="sensor_type_key">sensorType</string>
|
||||||
<string name="share_url_only_key">shareUrlOnly</string>
|
<string name="share_url_only_key">shareUrlOnly</string>
|
||||||
<string name="split_frequency_key">splitFrequency</string>
|
<string name="split_frequency_key">splitFrequency</string>
|
||||||
@@ -49,4 +50,7 @@ limitations under the License.
|
|||||||
<!-- Keys for non-persisted preferences - DO NOT TRANSLATE -->
|
<!-- Keys for non-persisted preferences - DO NOT TRANSLATE -->
|
||||||
<string name="backup_to_sd_key">backupToSd</string>
|
<string name="backup_to_sd_key">backupToSd</string>
|
||||||
<string name="restore_from_sd_key">restoreFromSd</string>
|
<string name="restore_from_sd_key">restoreFromSd</string>
|
||||||
|
<string name="reset_key">resetToDefaults</string>
|
||||||
|
<string name="sensor_options_key">sensorOptions</string>
|
||||||
|
<string name="ant_options_key">antOptions</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -35,14 +35,17 @@ limitations under the License.
|
|||||||
<!-- Error messages -->
|
<!-- Error messages -->
|
||||||
<string name="error_no_location_manager">No location manager was found on this device!</string>
|
<string name="error_no_location_manager">No location manager was found on this device!</string>
|
||||||
<string name="error_no_gps_location_provider">No GPS location provider was found on this device.</string>
|
<string name="error_no_gps_location_provider">No GPS location provider was found on this device.</string>
|
||||||
<string name="error_sending_to_fusiontables">There was an error while sending your track to Google Fusion Tables. Please try again later.</string>
|
<string name="error_sending_to_mymap">There was an error while sending your track to Google My Map.</string>
|
||||||
<string name="error_sending_to_docs">There was an error while sending your track to Google Docs. Please try again later.</string>
|
<string name="error_sending_to_fusiontables">There was an error while sending your track to Google Fusion Tables.</string>
|
||||||
|
<string name="error_sending_to_docs">There was an error while sending your track to Google Docs.</string>
|
||||||
|
<string name="error_please_try_again_later">Please try again later.</string>
|
||||||
<string name="error_unable_to_start_recording">Unable to start recording. Try again.</string>
|
<string name="error_unable_to_start_recording">Unable to start recording. Try again.</string>
|
||||||
<string name="error_unable_to_stop_recording">Unable to stop recording. Try again.</string>
|
<string name="error_unable_to_stop_recording">Unable to stop recording. Try again.</string>
|
||||||
<string name="error_unable_to_read_file">Unable to read from file.</string>
|
<string name="error_unable_to_read_file">Unable to read from file.</string>
|
||||||
<string name="error_invalid_gpx_format">File does not have a valid GPX format.</string>
|
<string name="error_invalid_gpx_format">File does not have a valid GPX format.</string>
|
||||||
<string name="error_generic">An error occurred. Please try again.</string>
|
<string name="error_generic">An error occurred. Please try again.</string>
|
||||||
<string name="error_track_does_not_exist">Track does not exist.</string>
|
<string name="error_track_does_not_exist">Track does not exist.</string>
|
||||||
|
<string name="error_operation_cancelled">The operation was cancelled.</string>
|
||||||
<string name="error_out_of_memory">This file is too big (must be less than 500 KB). Aborting.</string>
|
<string name="error_out_of_memory">This file is too big (must be less than 500 KB). Aborting.</string>
|
||||||
<string name="error_unable_to_insert_marker">Unable to insert marker. No location fix available.</string>
|
<string name="error_unable_to_insert_marker">Unable to insert marker. No location fix available.</string>
|
||||||
|
|
||||||
@@ -50,23 +53,30 @@ limitations under the License.
|
|||||||
<string name="wait_for_fix">Waiting for a better GPS fix. Make sure the sky is visible.</string>
|
<string name="wait_for_fix">Waiting for a better GPS fix. Make sure the sky is visible.</string>
|
||||||
<string name="status_now_recording">Now recording a new track.</string>
|
<string name="status_now_recording">Now recording a new track.</string>
|
||||||
<string name="status_stopped_recording">Stopped recording your track.</string>
|
<string name="status_stopped_recording">Stopped recording your track.</string>
|
||||||
|
<string name="status_new_mymap_has_been_created">A new Google My Map has been created at maps.google.com.</string>
|
||||||
<string name="status_new_fusiontable_has_been_created">A new Google Fusion table has been created at google.com/fusiontables.</string>
|
<string name="status_new_fusiontable_has_been_created">A new Google Fusion table has been created at google.com/fusiontables.</string>
|
||||||
<string name="status_tracks_have_been_uploaded">Your track has been sent to maps.google.com.</string>
|
<string name="status_tracks_have_been_uploaded">Your track has been sent to maps.google.com.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_new_doc">Your track has been sent to a new spreadsheet at docs.google.com.</string>
|
<string name="status_tracks_have_been_uploaded_to_new_doc">Your track has been sent to a new spreadsheet at docs.google.com.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_docs">Your track has been sent to docs.google.com.</string>
|
<string name="status_tracks_have_been_uploaded_to_docs">Your track has been sent to docs.google.com.</string>
|
||||||
|
<string name="status_mymap_info">It may take a few minutes before new tracks appear.</string>
|
||||||
<string name="status_enable_gps">Please tap here to go to Security and Location Settings and check \'enable GPS satellites\'. Press back button to return.</string>
|
<string name="status_enable_gps">Please tap here to go to Security and Location Settings and check \'enable GPS satellites\'. Press back button to return.</string>
|
||||||
<string name="status_approximate_location">Note: An approximate location as determined from cell towers and WIFI networks is shown.</string>
|
<string name="status_approximate_location">Note: An approximate location as determined from cell towers and WIFI networks is shown.</string>
|
||||||
<string name="status_no_location">A location can currently not be determined. Enable more location sources (see Security and Location Settings) and make sure the sky is visible. Try again later.</string>
|
<string name="status_no_location">A location can currently not be determined. Enable more location sources (see Security and Location Settings) and make sure the sky is visible. Try again later.</string>
|
||||||
<string name="status_waypoint_inserted">A way point marker was inserted.</string>
|
<string name="status_waypoint_inserted">A way point marker was inserted.</string>
|
||||||
<string name="status_statistics_inserted">A statistics marker was inserted.</string>
|
<string name="status_statistics_inserted">A statistics marker was inserted.</string>
|
||||||
|
<string name="status_track_upload_status">Upload status:</string>
|
||||||
|
|
||||||
<!-- Progress dialog -->
|
<!-- Progress dialog -->
|
||||||
<string name="progress_title">Please wait...</string>
|
<string name="progress_title">Please wait...</string>
|
||||||
<string name="progress_message">Sending your track to Google.</string>
|
<string name="progress_message">Sending your track to Google.</string>
|
||||||
<string name="progress_message_reading_track">Reading track...</string>
|
<string name="progress_message_reading_track">Reading track...</string>
|
||||||
|
<string name="progress_message_preparing_track">Preparing track...</string>
|
||||||
<string name="progress_message_authenticating_fusiontables">Authenticating to Google Fusion Tables...</string>
|
<string name="progress_message_authenticating_fusiontables">Authenticating to Google Fusion Tables...</string>
|
||||||
|
<string name="progress_message_authenticating_mymaps">Authenticating to Google Maps...</string>
|
||||||
<string name="progress_message_authenticating_docs">Authenticating to Google Docs...</string>
|
<string name="progress_message_authenticating_docs">Authenticating to Google Docs...</string>
|
||||||
<string name="progress_message_sending_docs">Sending track to Google Docs...</string>
|
<string name="progress_message_sending_docs">Sending track to Google Docs...</string>
|
||||||
|
<string name="progress_message_sending_mymaps">Sending track to Google Maps...</string>
|
||||||
|
<string name="progress_message_creating_map">Creating new My Map...</string>
|
||||||
<string name="progress_message_sending_fusiontables">Sending track to Fusion Tables...</string>
|
<string name="progress_message_sending_fusiontables">Sending track to Fusion Tables...</string>
|
||||||
<string name="progress_message_creating_fusiontable">Creating new Fusion table...</string>
|
<string name="progress_message_creating_fusiontable">Creating new Fusion table...</string>
|
||||||
<string name="import_progress_message">Importing a GPS track. This may take a while.</string>
|
<string name="import_progress_message">Importing a GPS track. This may take a while.</string>
|
||||||
@@ -83,6 +93,10 @@ limitations under the License.
|
|||||||
<string name="new_map_description">Created by My Tracks on Android.</string>
|
<string name="new_map_description">Created by My Tracks on Android.</string>
|
||||||
<string name="fusiontable_link">Created by <a href=\'http://mytracks.appspot.com\'>My Tracks</a> on Android.</string>
|
<string name="fusiontable_link">Created by <a href=\'http://mytracks.appspot.com\'>My Tracks</a> on Android.</string>
|
||||||
|
|
||||||
|
<!-- Text and links when uploading to Google My Maps -->
|
||||||
|
<string name="my_map_link">Created by <a href=\'http://mytracks.appspot.com\'>My Tracks</a> on Android.</string>
|
||||||
|
<string name="new_map_title">New map</string>
|
||||||
|
|
||||||
<!-- Formatting of track and marker descriptions -->
|
<!-- Formatting of track and marker descriptions -->
|
||||||
<string name="points">Points</string>
|
<string name="points">Points</string>
|
||||||
<string name="recorded_date">Recorded</string>
|
<string name="recorded_date">Recorded</string>
|
||||||
@@ -113,6 +127,8 @@ limitations under the License.
|
|||||||
|
|
||||||
<!-- TrackList -->
|
<!-- TrackList -->
|
||||||
<string name="tracklist_show_track">Show</string>
|
<string name="tracklist_show_track">Show</string>
|
||||||
|
<string name="tracklist_send_to_mymaps">Send to Google My Maps</string>
|
||||||
|
<string name="tracklist_send_to_new_mymap">Send to New Google My Map</string>
|
||||||
<string name="tracklist_send_to_fusiontables">Send to Google Fusion Tables</string>
|
<string name="tracklist_send_to_fusiontables">Send to Google Fusion Tables</string>
|
||||||
<string name="tracklist_send_to_new_fusiontable">Send to New Google Fusion Table</string>
|
<string name="tracklist_send_to_new_fusiontable">Send to New Google Fusion Table</string>
|
||||||
<string name="tracklist_send_to_docs">Send to Google Docs</string>
|
<string name="tracklist_send_to_docs">Send to Google Docs</string>
|
||||||
@@ -125,6 +141,7 @@ limitations under the License.
|
|||||||
<string name="tracklist_save_as_csv">Save a CSV file</string>
|
<string name="tracklist_save_as_csv">Save a CSV file</string>
|
||||||
<string name="tracklist_save_as_tcx">Save a TCX file</string>
|
<string name="tracklist_save_as_tcx">Save a TCX file</string>
|
||||||
<string name="tracklist_btn_send_all_to_fusiontables">Send to Google Fusion Tables</string>
|
<string name="tracklist_btn_send_all_to_fusiontables">Send to Google Fusion Tables</string>
|
||||||
|
<string name="tracklist_btn_send_all_to_mymaps">Send to Google My Maps</string>
|
||||||
<string name="tracklist_btn_delete_all">Delete all</string>
|
<string name="tracklist_btn_delete_all">Delete all</string>
|
||||||
<!-- Export All -->
|
<!-- Export All -->
|
||||||
<string name="tracklist_btn_export_all">Export all</string>
|
<string name="tracklist_btn_export_all">Export all</string>
|
||||||
@@ -133,7 +150,7 @@ limitations under the License.
|
|||||||
<string name="tracklist_all_tracks">All Tracks:</string>
|
<string name="tracklist_all_tracks">All Tracks:</string>
|
||||||
<string name="tracklist_this_track">This Track</string>
|
<string name="tracklist_this_track">This Track</string>
|
||||||
<string name="tracklist_share_track">Share with Friends...</string>
|
<string name="tracklist_share_track">Share with Friends...</string>
|
||||||
<string name="tracklist_share_linkfusion">A link to Google Fusion Tables</string>
|
<string name="tracklist_share_link">A link to the map</string>
|
||||||
<string name="tracklist_share_gpx_file">A GPX file</string>
|
<string name="tracklist_share_gpx_file">A GPX file</string>
|
||||||
<string name="tracklist_share_kml_file">A KML file</string>
|
<string name="tracklist_share_kml_file">A KML file</string>
|
||||||
<string name="tracklist_share_csv_file">A CSV file</string>
|
<string name="tracklist_share_csv_file">A CSV file</string>
|
||||||
@@ -180,6 +197,7 @@ limitations under the License.
|
|||||||
<string name="settings_sharing">Sharing</string>
|
<string name="settings_sharing">Sharing</string>
|
||||||
|
|
||||||
<string name="settings_not_available_summary">Not available in your version of Android</string>
|
<string name="settings_not_available_summary">Not available in your version of Android</string>
|
||||||
|
<string name="settings_not_while_recording">Not available while recording a track</string>
|
||||||
|
|
||||||
<string name="settings_announcement_frequency">Announcement frequency</string>
|
<string name="settings_announcement_frequency">Announcement frequency</string>
|
||||||
<string name="settings_announcement_frequency_summary">Minimum time between two voice announcements</string>
|
<string name="settings_announcement_frequency_summary">Minimum time between two voice announcements</string>
|
||||||
@@ -222,6 +240,11 @@ limitations under the License.
|
|||||||
<string name="settings_timestamp_track_name_summary_on">The default track name will be the date and time at the start of the track</string>
|
<string name="settings_timestamp_track_name_summary_on">The default track name will be the date and time at the start of the track</string>
|
||||||
<string name="settings_timestamp_track_name_summary_off">Track names will have numbers which increment for each new track.</string>
|
<string name="settings_timestamp_track_name_summary_off">Track names will have numbers which increment for each new track.</string>
|
||||||
|
|
||||||
|
<string name="settings_reset">Reset to defaults</string>
|
||||||
|
<string name="settings_reset_summary">Revert all your settings to the default values</string>
|
||||||
|
<string name="settings_reset_dialog_message">All your settings will be erased and reverted to the default values. Saved tracks will be preserved. Are you sure?</string>
|
||||||
|
<string name="settings_reset_done">All settings have been reverted to their defaults.</string>
|
||||||
|
|
||||||
<string name="pace_label">Pace</string>
|
<string name="pace_label">Pace</string>
|
||||||
|
|
||||||
<string name="eclair_required">Only supported in Android 2.0 or above</string>
|
<string name="eclair_required">Only supported in Android 2.0 or above</string>
|
||||||
@@ -229,7 +252,7 @@ limitations under the License.
|
|||||||
<string name="settings_sensor_type_summary">The type of sensor to connect to</string>
|
<string name="settings_sensor_type_summary">The type of sensor to connect to</string>
|
||||||
<string name="settings_heart_rate_ant_sensor_id">Clear ANT heart rate sensor pairing</string>
|
<string name="settings_heart_rate_ant_sensor_id">Clear ANT heart rate sensor pairing</string>
|
||||||
<string name="settings_power_ant_sensor_id">Clear ANT power sensor pairing</string>
|
<string name="settings_power_ant_sensor_id">Clear ANT power sensor pairing</string>
|
||||||
<string name="settings_srm_bridge_ant_sensor_id">Clear ANT srm bridge sensor pairing</string>
|
<string name="settings_srm_bridge_ant_sensor_id">Clear ANT SRM bridge sensor pairing</string>
|
||||||
<string name="settings_ant_not_paired">ANT sensor not paired</string>
|
<string name="settings_ant_not_paired">ANT sensor not paired</string>
|
||||||
<string name="settings_ant_paired">ANT sensor paired with: %d</string>
|
<string name="settings_ant_paired">ANT sensor paired with: %d</string>
|
||||||
<string name="bluetooth_sensor_title">Bluetooth sensor</string>
|
<string name="bluetooth_sensor_title">Bluetooth sensor</string>
|
||||||
@@ -243,7 +266,6 @@ limitations under the License.
|
|||||||
<string name="settings_backup_to_sd_summary">Write a full copy of all your tracks and settings to the SD card</string>
|
<string name="settings_backup_to_sd_summary">Write a full copy of all your tracks and settings to the SD card</string>
|
||||||
<string name="settings_restore_from_sd">Restore now</string>
|
<string name="settings_restore_from_sd">Restore now</string>
|
||||||
<string name="settings_restore_from_sd_summary">Restore all tracks and settings from the SD card</string>
|
<string name="settings_restore_from_sd_summary">Restore all tracks and settings from the SD card</string>
|
||||||
<string name="settings_no_backup_while_recording">Cannot manipulate backups while recording a track.</string>
|
|
||||||
|
|
||||||
<string name="restore_overwrites_warning">Restoring a backup from the SD card will OVERWRITE all your current tracks and settings. Are you sure?</string>
|
<string name="restore_overwrites_warning">Restoring a backup from the SD card will OVERWRITE all your current tracks and settings. Are you sure?</string>
|
||||||
<string name="select_backup_to_restore">Select the backup to restore</string>
|
<string name="select_backup_to_restore">Select the backup to restore</string>
|
||||||
@@ -254,6 +276,23 @@ limitations under the License.
|
|||||||
<!-- MyTracksSky -->
|
<!-- MyTracksSky -->
|
||||||
<string name="mytracks_sky">GPS Satellites</string>
|
<string name="mytracks_sky">GPS Satellites</string>
|
||||||
|
|
||||||
|
<!-- My Maps -->
|
||||||
|
<string name="select_map_message">Pick a map from your account:</string>
|
||||||
|
<string name="create_new_map">Create new map...</string>
|
||||||
|
<string name="map_list_title">Send to Google My Maps</string>
|
||||||
|
<string name="maps_list_loading">Loading maps...</string>
|
||||||
|
<string name="maps_list_failed">Your maps could not be loaded at this time!</string>
|
||||||
|
<string name="open_map">Select this Map</string>
|
||||||
|
<string name="edit_map_details">Edit Map Details</string>
|
||||||
|
<string name="share_track">Share Track</string>
|
||||||
|
<string name="delete_map">Delete Map from your Account</string>
|
||||||
|
<string name="map_title">Map Title:</string>
|
||||||
|
<string name="map_description">Map Description:</string>
|
||||||
|
<string name="map_searchable_edit">Make this map and its contents show up in search results</string>
|
||||||
|
<string name="map_not_searchable_edit">Do not let this map or its contents show up in search results, though they may still be viewed be others through the direct URL</string>
|
||||||
|
<string name="map_searchable">This map and its contents will show in search results</string>
|
||||||
|
<string name="map_not_searchable">Neither this map nor its contents will show in search results, but they may still be viewed by others through a direct link</string>
|
||||||
|
|
||||||
<!-- Sharing -->
|
<!-- Sharing -->
|
||||||
<string name="share_map">Share map with friends</string>
|
<string name="share_map">Share map with friends</string>
|
||||||
<string name="share_map_subject">I would like to share a track with you</string>
|
<string name="share_map_subject">I would like to share a track with you</string>
|
||||||
@@ -264,7 +303,6 @@ limitations under the License.
|
|||||||
<string name="send_track_body_format">I think you might be interested in this track.
|
<string name="send_track_body_format">I think you might be interested in this track.
|
||||||
|
|
||||||
To view this track use Google Earth or other mapping software.</string>
|
To view this track use Google Earth or other mapping software.</string>
|
||||||
<string name="share_track">Share track with friends</string>
|
|
||||||
|
|
||||||
<!-- Visibility -->
|
<!-- Visibility -->
|
||||||
<string name="public_map">Public</string>
|
<string name="public_map">Public</string>
|
||||||
@@ -377,8 +415,11 @@ limitations under the License.
|
|||||||
<!-- Send to Google -->
|
<!-- Send to Google -->
|
||||||
<string name="sendtogoogle_title">Send to...</string>
|
<string name="sendtogoogle_title">Send to...</string>
|
||||||
<string name="sendtogoogle_google_fusiontables">Google Fusion Tables</string>
|
<string name="sendtogoogle_google_fusiontables">Google Fusion Tables</string>
|
||||||
|
<string name="sendtogoogle_google_mymaps">Google My Maps</string>
|
||||||
<string name="sendtogoogle_google_docs">Google Docs</string>
|
<string name="sendtogoogle_google_docs">Google Docs</string>
|
||||||
<string name="sendtogoogle_send_now">Send now</string>
|
<string name="sendtogoogle_send_now">Send now</string>
|
||||||
|
<string name="sendtogoogle_create_new_map">Create a new map</string>
|
||||||
|
<string name="sendtogoogle_pick_existing_map">Pick an existing map</string>
|
||||||
<string name="sendtogoogle_send_stats">Send track statistics</string>
|
<string name="sendtogoogle_send_stats">Send track statistics</string>
|
||||||
<string name="sendtogoogle_send_stats_and_points">Send statistics and points</string>
|
<string name="sendtogoogle_send_stats_and_points">Send statistics and points</string>
|
||||||
|
|
||||||
@@ -430,6 +471,7 @@ limitations under the License.
|
|||||||
<string name="bluetooth_pairing">Device pairing</string>
|
<string name="bluetooth_pairing">Device pairing</string>
|
||||||
<string name="bluetooth_pairing_summary">Open Android\'s bluetooth settings to pair a device</string>
|
<string name="bluetooth_pairing_summary">Open Android\'s bluetooth settings to pair a device</string>
|
||||||
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
|
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
|
||||||
|
<string name="ant_options">ANT options</string>
|
||||||
<string name="sensor_options">Sensor Options</string>
|
<string name="sensor_options">Sensor Options</string>
|
||||||
|
|
||||||
<!-- Bluetooth Sensor -->
|
<!-- Bluetooth Sensor -->
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ limitations under the License.
|
|||||||
android:key="@string/split_frequency_key"
|
android:key="@string/split_frequency_key"
|
||||||
android:title="@string/settings_split_frequency"
|
android:title="@string/settings_split_frequency"
|
||||||
android:summary="@string/settings_split_frequency_summary"
|
android:summary="@string/settings_split_frequency_summary"
|
||||||
android:entries="@array/split_frequency_options"
|
android:entries="@array/task_frequency_options"
|
||||||
android:entryValues="@array/split_frequency_values"
|
android:entryValues="@array/task_frequency_values"
|
||||||
android:defaultValue="0" />
|
android:defaultValue="0" />
|
||||||
|
|
||||||
<com.google.android.apps.mytracks.IntegerListPreference
|
<com.google.android.apps.mytracks.IntegerListPreference
|
||||||
@@ -102,7 +102,8 @@ limitations under the License.
|
|||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
||||||
<!-- Sensors -->
|
<!-- Sensors -->
|
||||||
<PreferenceScreen android:title="@string/sensor_options">
|
<PreferenceScreen android:title="@string/sensor_options"
|
||||||
|
android:key="@string/sensor_options_key">
|
||||||
<ListPreference android:key="@string/sensor_type_key"
|
<ListPreference android:key="@string/sensor_type_key"
|
||||||
android:title="@string/settings_sensor_type"
|
android:title="@string/settings_sensor_type"
|
||||||
android:summary="@string/settings_sensor_type_summary"
|
android:summary="@string/settings_sensor_type_summary"
|
||||||
@@ -123,19 +124,21 @@ limitations under the License.
|
|||||||
android:persistent="false" />
|
android:persistent="false" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<com.google.android.apps.mytracks.AntPreference
|
<PreferenceCategory android:title="@string/ant_options"
|
||||||
android:key="@string/ant_heart_rate_sensor_id_key"
|
android:key="@string/ant_options_key">
|
||||||
android:title="@string/settings_heart_rate_ant_sensor_id"/>
|
<com.google.android.apps.mytracks.AntPreference
|
||||||
|
android:key="@string/ant_heart_rate_sensor_id_key"
|
||||||
|
android:title="@string/settings_heart_rate_ant_sensor_id"/>
|
||||||
<!--
|
<!--
|
||||||
<com.google.android.apps.mytracks.AntPreference
|
<com.google.android.apps.mytracks.AntPreference
|
||||||
android:key="@string/ant_power_sensor_id_key"
|
android:key="@string/ant_power_sensor_id_key"
|
||||||
android:title="@string/settings_power_ant_sensor_id"/>
|
android:title="@string/settings_power_ant_sensor_id"/>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<com.google.android.apps.mytracks.AntPreference
|
<com.google.android.apps.mytracks.AntPreference
|
||||||
android:key="@string/ant_srm_bridge_sensor_id_key"
|
android:key="@string/ant_srm_bridge_sensor_id_key"
|
||||||
android:title="@string/settings_srm_bridge_ant_sensor_id"/>
|
android:title="@string/settings_srm_bridge_ant_sensor_id"/>
|
||||||
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
||||||
<!-- Sharing settings -->
|
<!-- Sharing settings -->
|
||||||
@@ -170,4 +173,11 @@ limitations under the License.
|
|||||||
android:persistent="false" />
|
android:persistent="false" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
||||||
|
<!-- Reset to defaults -->
|
||||||
|
<Preference
|
||||||
|
android:title="@string/settings_reset"
|
||||||
|
android:key="@string/reset_key"
|
||||||
|
android:summary="@string/settings_reset_summary"
|
||||||
|
android:persistent="false" />
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class AntInterface {
|
|||||||
public static final String TAG = "ANTInterface";
|
public static final String TAG = "ANTInterface";
|
||||||
|
|
||||||
/** Enable debug logging. */
|
/** Enable debug logging. */
|
||||||
public static boolean DEBUG = true;
|
public static boolean DEBUG = false;
|
||||||
|
|
||||||
/** Search string to find ANT Radio Proxy Service in the Android Marketplace */
|
/** Search string to find ANT Radio Proxy Service in the Android Marketplace */
|
||||||
private static final String MARKET_SEARCH_TEXT_DEFAULT = "ANT Radio Service Dynastream Innovations Inc";
|
private static final String MARKET_SEARCH_TEXT_DEFAULT = "ANT Radio Service Dynastream Innovations Inc";
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class AccountChooser {
|
|||||||
public void chooseAccount(final Activity activity,
|
public void chooseAccount(final Activity activity,
|
||||||
final AccountHandler handler) {
|
final AccountHandler handler) {
|
||||||
final Account[] accounts = AccountManager.get(activity)
|
final Account[] accounts = AccountManager.get(activity)
|
||||||
.getAccountsByType(MyTracksConstants.ACCOUNT_TYPE);
|
.getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||||
if (accounts.length < 1) {
|
if (accounts.length < 1) {
|
||||||
alertNoAccounts(activity, handler);
|
alertNoAccounts(activity, handler);
|
||||||
return;
|
return;
|
||||||
@@ -76,7 +76,7 @@ public class AccountChooser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Let the user choose.
|
// Let the user choose.
|
||||||
Log.e(MyTracksConstants.TAG, "Multiple matching accounts found.");
|
Log.e(Constants.TAG, "Multiple matching accounts found.");
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.setTitle(R.string.choose_account_title);
|
builder.setTitle(R.string.choose_account_title);
|
||||||
builder.setCancelable(false);
|
builder.setCancelable(false);
|
||||||
@@ -112,7 +112,7 @@ public class AccountChooser {
|
|||||||
*/
|
*/
|
||||||
private void alertNoAccounts(final Activity activity,
|
private void alertNoAccounts(final Activity activity,
|
||||||
final AccountHandler handler) {
|
final AccountHandler handler) {
|
||||||
Log.e(MyTracksConstants.TAG, "No matching accounts found.");
|
Log.e(Constants.TAG, "No matching accounts found.");
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.setTitle(R.string.no_account_found_title);
|
builder.setTitle(R.string.no_account_found_title);
|
||||||
builder.setMessage(R.string.no_account_found);
|
builder.setMessage(R.string.no_account_found);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class AggregatedStatsActivity extends Activity implements
|
|||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||||
String key) {
|
String key) {
|
||||||
Log.d(MyTracksConstants.TAG, "StatsActivity: onSharedPreferences changed "
|
Log.d(Constants.TAG, "StatsActivity: onSharedPreferences changed "
|
||||||
+ key);
|
+ key);
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
if (key.equals(R.string.metric_units_key)) {
|
if (key.equals(R.string.metric_units_key)) {
|
||||||
@@ -67,7 +67,7 @@ public class AggregatedStatsActivity extends Activity implements
|
|||||||
sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
|
sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
|
||||||
|
|
||||||
SharedPreferences preferences = getSharedPreferences(
|
SharedPreferences preferences = getSharedPreferences(
|
||||||
MyTracksSettings.SETTINGS_NAME, 0);
|
Constants.SETTINGS_NAME, 0);
|
||||||
if (preferences != null) {
|
if (preferences != null) {
|
||||||
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
|
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
|
||||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||||
|
|||||||
+5
-5
@@ -16,8 +16,8 @@
|
|||||||
package com.google.android.apps.mytracks;
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
import static android.content.Intent.ACTION_BOOT_COMPLETED;
|
import static android.content.Intent.ACTION_BOOT_COMPLETED;
|
||||||
import static com.google.android.apps.mytracks.MyTracksConstants.RESUME_TRACK_EXTRA_NAME;
|
import static com.google.android.apps.mytracks.Constants.RESUME_TRACK_EXTRA_NAME;
|
||||||
import static com.google.android.apps.mytracks.MyTracksConstants.TAG;
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.services.TrackRecordingService;
|
import com.google.android.apps.mytracks.services.TrackRecordingService;
|
||||||
|
|
||||||
@@ -41,17 +41,17 @@ import android.util.Log;
|
|||||||
*
|
*
|
||||||
* @author Bartlomiej Niechwiej
|
* @author Bartlomiej Niechwiej
|
||||||
*/
|
*/
|
||||||
public class MyTracksReceiver extends BroadcastReceiver {
|
public class BootReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
Log.d(TAG, "MyTracksReceiver.onReceive: " + intent.getAction());
|
Log.d(TAG, "BootReceiver.onReceive: " + intent.getAction());
|
||||||
if (ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
|
if (ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
|
||||||
Intent startIntent = new Intent(context, TrackRecordingService.class);
|
Intent startIntent = new Intent(context, TrackRecordingService.class);
|
||||||
startIntent.putExtra(RESUME_TRACK_EXTRA_NAME, true);
|
startIntent.putExtra(RESUME_TRACK_EXTRA_NAME, true);
|
||||||
context.startService(startIntent);
|
context.startService(startIntent);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "MyTracksReceiver: unsupported action");
|
Log.w(TAG, "BootReceiver: unsupported action");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,31 +15,26 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks;
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.ChartView.Mode;
|
import com.google.android.apps.mytracks.ChartView.Mode;
|
||||||
|
import com.google.android.apps.mytracks.TrackDataHub.ListenerDataType;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
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.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.Sensor.SensorDataSet;
|
||||||
import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
|
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.DoubleBuffer;
|
||||||
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
|
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
|
||||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
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.apps.mytracks.util.UnitConversions;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.database.ContentObserver;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@@ -51,53 +46,34 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.ZoomControls;
|
import android.widget.ZoomControls;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An activity that displays a chart from the track point provider.
|
* An activity that displays a chart from the track point provider.
|
||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
|
* @author Rodrigo Damazio
|
||||||
*/
|
*/
|
||||||
public class ChartActivity extends Activity implements
|
public class ChartActivity extends Activity implements TrackDataListener {
|
||||||
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;
|
|
||||||
|
|
||||||
private final DoubleBuffer elevationBuffer =
|
private final DoubleBuffer elevationBuffer =
|
||||||
new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
|
new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
|
||||||
private final DoubleBuffer speedBuffer =
|
private final DoubleBuffer speedBuffer =
|
||||||
new DoubleBuffer(MyTracksConstants.SPEED_SMOOTHING_FACTOR);
|
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;
|
private Mode mode = Mode.BY_DISTANCE;
|
||||||
|
private boolean metricUnits;
|
||||||
/**
|
private boolean reportSpeed;
|
||||||
* Utilities to deal with the database.
|
|
||||||
*/
|
|
||||||
private MyTracksProviderUtils providerUtils;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UI elements:
|
* UI elements:
|
||||||
@@ -107,9 +83,6 @@ public class ChartActivity extends Activity implements
|
|||||||
private LinearLayout busyPane;
|
private LinearLayout busyPane;
|
||||||
private ZoomControls zoomControls;
|
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
|
* 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
|
* (if any), enable/disable zoom controls and orange pointer as appropriate
|
||||||
@@ -121,89 +94,17 @@ public class ChartActivity extends Activity implements
|
|||||||
busyPane.setVisibility(View.GONE);
|
busyPane.setVisibility(View.GONE);
|
||||||
zoomControls.setIsZoomInEnabled(chartView.canZoomIn());
|
zoomControls.setIsZoomInEnabled(chartView.canZoomIn());
|
||||||
zoomControls.setIsZoomOutEnabled(chartView.canZoomOut());
|
zoomControls.setIsZoomOutEnabled(chartView.canZoomOut());
|
||||||
chartView.setShowPointer(selectedTrackIsRecording());
|
chartView.setShowPointer(dataHub.isRecordingSelected());
|
||||||
chartView.invalidate();
|
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
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
Log.w(MyTracksConstants.TAG, "ChartActivity.onCreate");
|
Log.w(TAG, "ChartActivity.onCreate");
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
MyTracks.getInstance().setChartActivity(this);
|
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
|
// The volume we want to control is the Text-To-Speech volume
|
||||||
int volumeStream =
|
int volumeStream =
|
||||||
@@ -219,22 +120,6 @@ public class ChartActivity extends Activity implements
|
|||||||
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
|
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
|
||||||
layout.addView(chartView, params);
|
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);
|
busyPane = (LinearLayout) findViewById(R.id.elevation_busypane);
|
||||||
zoomControls = (ZoomControls) findViewById(R.id.elevation_zoom);
|
zoomControls = (ZoomControls) findViewById(R.id.elevation_zoom);
|
||||||
zoomControls.setOnZoomInClickListener(new View.OnClickListener() {
|
zoomControls.setOnZoomInClickListener(new View.OnClickListener() {
|
||||||
@@ -249,97 +134,25 @@ public class ChartActivity extends Activity implements
|
|||||||
zoomOut();
|
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(MyTracksConstants.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(MyTracksConstants.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
|
@Override
|
||||||
protected void onPause() {
|
protected void onStart() {
|
||||||
super.onPause();
|
super.onStart();
|
||||||
unregisterContentObservers();
|
|
||||||
|
dataHub.registerTrackDataListener(this, EnumSet.of(
|
||||||
|
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||||
|
ListenerDataType.POINT_UPDATES,
|
||||||
|
ListenerDataType.SAMPLED_OUT_POINT_UPDATES,
|
||||||
|
ListenerDataType.WAYPOINT_UPDATES,
|
||||||
|
ListenerDataType.DISPLAY_PREFERENCES));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onStop() {
|
||||||
super.onResume();
|
dataHub.unregisterTrackDataListener(this);
|
||||||
// Make sure any updates that might have happened are propagated to this
|
|
||||||
// activity:
|
|
||||||
observer.onChange(false);
|
|
||||||
waypointObserver.onChange(false);
|
|
||||||
registerContentObservers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
super.onStop();
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void zoomIn() {
|
private void zoomIn() {
|
||||||
@@ -358,7 +171,7 @@ public class ChartActivity extends Activity implements
|
|||||||
if (this.mode != newMode) {
|
if (this.mode != newMode) {
|
||||||
this.mode = newMode;
|
this.mode = newMode;
|
||||||
chartView.setMode(this.mode);
|
chartView.setMode(this.mode);
|
||||||
readProfileAsync();
|
dataHub.reloadDataForListener(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,39 +188,11 @@ public class ChartActivity extends Activity implements
|
|||||||
return chartView.getChartValueSeries(index).isEnabled();
|
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,
|
|
||||||
MyTracksConstants.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(MyTracksConstants.TAG, "Caught an unexpected exception.", e);
|
|
||||||
} finally {
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
super.onCreateOptionsMenu(menu);
|
super.onCreateOptionsMenu(menu);
|
||||||
chartSettingsMenuItem =
|
chartSettingsMenuItem =
|
||||||
menu.add(0, MyTracksConstants.MENU_CHART_SETTINGS, 0,
|
menu.add(0, Constants.MENU_CHART_SETTINGS, 0,
|
||||||
R.string.chart_settings);
|
R.string.chart_settings);
|
||||||
chartSettingsMenuItem.setIcon(R.drawable.chart_settings);
|
chartSettingsMenuItem.setIcon(R.drawable.chart_settings);
|
||||||
return true;
|
return true;
|
||||||
@@ -416,7 +201,7 @@ public class ChartActivity extends Activity implements
|
|||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case MyTracksConstants.MENU_CHART_SETTINGS:
|
case Constants.MENU_CHART_SETTINGS:
|
||||||
MyTracks.getInstance().getDialogManager().showDialogSafely(
|
MyTracks.getInstance().getDialogManager().showDialogSafely(
|
||||||
DialogManager.DIALOG_CHART_SETTINGS);
|
DialogManager.DIALOG_CHART_SETTINGS);
|
||||||
return true;
|
return true;
|
||||||
@@ -438,43 +223,41 @@ public class ChartActivity extends Activity implements
|
|||||||
* This must be called in order for each point.
|
* 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 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
|
* @param result the resulting point to fill out
|
||||||
* @return the previous location, now available for reuse
|
* @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 &&
|
if (location instanceof MyTracksLocation &&
|
||||||
((MyTracksLocation) location).getSensorDataSet() != null) {
|
((MyTracksLocation) location).getSensorDataSet() != null) {
|
||||||
SensorDataSet sensorData = ((MyTracksLocation) location).getSensorDataSet();
|
SensorDataSet sensorData = ((MyTracksLocation) location).getSensorDataSet();
|
||||||
if (sensorData.hasPower()
|
if (sensorData.hasPower()
|
||||||
&& sensorData.getPower().getState() == Sensor.SensorState.SENDING
|
&& sensorData.getPower().getState() == Sensor.SensorState.SENDING
|
||||||
&& sensorData.getPower().hasValue()) {
|
&& sensorData.getPower().hasValue()) {
|
||||||
result[3] = sensorData.getPower().getValue();
|
power = sensorData.getPower().getValue();
|
||||||
} else {
|
|
||||||
result[3] = Double.NaN;
|
|
||||||
}
|
}
|
||||||
if (sensorData.hasCadence()
|
if (sensorData.hasCadence()
|
||||||
&& sensorData.getCadence().getState() == Sensor.SensorState.SENDING
|
&& sensorData.getCadence().getState() == Sensor.SensorState.SENDING
|
||||||
&& sensorData.getCadence().hasValue()) {
|
&& sensorData.getCadence().hasValue()) {
|
||||||
result[4] = sensorData.getCadence().getValue();
|
cadence = sensorData.getCadence().getValue();
|
||||||
} else {
|
|
||||||
result[4] = Double.NaN;
|
|
||||||
}
|
}
|
||||||
if (sensorData.hasHeartRate()
|
if (sensorData.hasHeartRate()
|
||||||
&& sensorData.getHeartRate().getState() == Sensor.SensorState.SENDING
|
&& sensorData.getHeartRate().getState() == Sensor.SensorState.SENDING
|
||||||
&& sensorData.getHeartRate().hasValue()) {
|
&& sensorData.getHeartRate().hasValue()) {
|
||||||
result[5] = sensorData.getHeartRate().getValue();
|
heartRate = sensorData.getHeartRate().getValue();
|
||||||
} else {
|
|
||||||
result[5] = Double.NaN;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
result[3] = Double.NaN;
|
|
||||||
result[4] = Double.NaN;
|
|
||||||
result[5] = Double.NaN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Account for segment splits?
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case BY_DISTANCE:
|
case BY_DISTANCE:
|
||||||
result[0] = profileLength;
|
timeOrDistance = profileLength;
|
||||||
if (lastLocation != null) {
|
if (lastLocation != null) {
|
||||||
double d = lastLocation.distanceTo(location);
|
double d = lastLocation.distanceTo(location);
|
||||||
if (metricUnits) {
|
if (metricUnits) {
|
||||||
@@ -489,16 +272,16 @@ public class ChartActivity extends Activity implements
|
|||||||
// Base case
|
// Base case
|
||||||
startTime = location.getTime();
|
startTime = location.getTime();
|
||||||
}
|
}
|
||||||
result[0] = (location.getTime() - startTime);
|
timeOrDistance = (location.getTime() - startTime);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.w(MyTracksConstants.TAG, "ChartActivity unknown mode: " + mode);
|
Log.w(TAG, "ChartActivity unknown mode: " + mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
elevationBuffer.setNext(metricUnits
|
elevationBuffer.setNext(metricUnits
|
||||||
? location.getAltitude()
|
? location.getAltitude()
|
||||||
: location.getAltitude() * UnitConversions.M_TO_FT);
|
: location.getAltitude() * UnitConversions.M_TO_FT);
|
||||||
result[1] = elevationBuffer.getAverage();
|
elevation = elevationBuffer.getAverage();
|
||||||
|
|
||||||
if (lastLocation == null) {
|
if (lastLocation == null) {
|
||||||
if (Math.abs(location.getSpeed() - 128) > 1) {
|
if (Math.abs(location.getSpeed() - 128) > 1) {
|
||||||
@@ -507,151 +290,134 @@ public class ChartActivity extends Activity implements
|
|||||||
} else if (TripStatisticsBuilder.isValidSpeed(
|
} else if (TripStatisticsBuilder.isValidSpeed(
|
||||||
location.getTime(), location.getSpeed(), lastLocation.getTime(),
|
location.getTime(), location.getSpeed(), lastLocation.getTime(),
|
||||||
lastLocation.getSpeed(), speedBuffer)
|
lastLocation.getSpeed(), speedBuffer)
|
||||||
&& (location.getSpeed() <= track.getStatistics().getMaxSpeed())) {
|
&& (location.getSpeed() <= trackMaxSpeed)) {
|
||||||
speedBuffer.setNext(location.getSpeed());
|
speedBuffer.setNext(location.getSpeed());
|
||||||
}
|
}
|
||||||
result[2] = speedBuffer.getAverage() * 3.6;
|
speed = speedBuffer.getAverage() * 3.6;
|
||||||
if (!metricUnits) {
|
if (!metricUnits) {
|
||||||
result[2] *= UnitConversions.KM_TO_MI;
|
speed *= UnitConversions.KM_TO_MI;
|
||||||
}
|
}
|
||||||
if (!reportSpeed && (result[2] != 0)) {
|
if (!reportSpeed) {
|
||||||
// Format as hours per unit
|
if (speed != 0) {
|
||||||
result[2] = (60.0 / result[2]);
|
// 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;
|
lastLocation = location;
|
||||||
|
|
||||||
if (oldLastLocation == null) {
|
if (result != null) {
|
||||||
// No previous location, but return a blank one for reuse
|
result[0] = timeOrDistance;
|
||||||
return new MyTracksLocation("");
|
result[1] = elevation;
|
||||||
|
result[2] = speed;
|
||||||
|
result[3] = power;
|
||||||
|
result[4] = cadence;
|
||||||
|
result[5] = heartRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
return oldLastLocation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the chart data points reading from the provider. This is non-blocking.
|
public void onProviderStateChange(ProviderState state) {
|
||||||
*/
|
// We don't care.
|
||||||
private void readProfileAsync() {
|
}
|
||||||
chartView.reset();
|
|
||||||
updateTrackHandler.post(new Runnable() {
|
@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() {
|
public void run() {
|
||||||
runOnUiThread(showSpinner);
|
busyPane.setVisibility(View.VISIBLE);
|
||||||
readProfile();
|
|
||||||
readWaypoints();
|
|
||||||
runOnUiThread(updateChart);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Reads the track profile from the provider. This is a blocking function and
|
public void onTrackUpdated(Track track) {
|
||||||
* should not be run from the UI thread.
|
trackMaxSpeed = track.getStatistics().getMaxSpeed();
|
||||||
*/
|
}
|
||||||
private void readProfile() {
|
|
||||||
|
@Override
|
||||||
|
public void clearTrackPoints() {
|
||||||
profileLength = 0;
|
profileLength = 0;
|
||||||
lastLocation = null;
|
lastLocation = null;
|
||||||
startTime = -1;
|
startTime = -1;
|
||||||
if (selectedTrackId < 0) {
|
elevationBuffer.reset();
|
||||||
return;
|
speedBuffer.reset();
|
||||||
}
|
chartView.reset();
|
||||||
Track track = providerUtils.getTrack(selectedTrackId);
|
pendingPoints.clear();
|
||||||
if (track == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lastSeenLocationId = track.getStartId();
|
|
||||||
final ArrayList<double[]> theData = readPointsToList(track);
|
|
||||||
runOnUiThread(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
chartView.setDataPoints(theData);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Read all new track points.
|
public void onNewTrackPoint(Location loc) {
|
||||||
*/
|
if (LocationUtils.isValidLocation(loc)) {
|
||||||
private void readNewTrackPoints() {
|
double[] point = new double[6];
|
||||||
Log.i(MyTracksConstants.TAG, "MyTracks: Updating chart last seen: " + lastSeenLocationId);
|
fillDataPoint(loc, point);
|
||||||
Track track = providerUtils.getTrack(recordingTrackId);
|
pendingPoints.add(point);
|
||||||
if (track == null) {
|
|
||||||
Log.w(MyTracksConstants.TAG, "MyTracks: track not found");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
chartView.addDataPoints(readPointsToList(track));
|
|
||||||
uiHandler.post(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
chartView.invalidate();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Log.i(MyTracksConstants.TAG, "MyTracks: Updated chart last seen: " + lastSeenLocationId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get the frequency at which points should be displayed.
|
public void onSampledOutTrackPoint(Location loc) {
|
||||||
* Limit the number of chart readings. Ideally we would want around 1024.
|
// Still account for the point in the smoothing buffers.
|
||||||
* @param track The track which will be displayed.
|
fillDataPoint(loc, null);
|
||||||
* @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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cursor getLocationsCursor(long lastLocationRead) {
|
@Override
|
||||||
return providerUtils.getLocationsCursor(selectedTrackId, lastLocationRead, BUFFER_SIZE, false);
|
public void onSegmentSplit() {
|
||||||
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Read all of the points to a list.
|
public void onNewTrackPointsDone() {
|
||||||
* @param track The track which will be displayed.
|
chartView.addDataPoints(pendingPoints);
|
||||||
* @return
|
pendingPoints.clear();
|
||||||
*/
|
runOnUiThread(updateChart);
|
||||||
private ArrayList<double[]> readPointsToList(Track track) {
|
}
|
||||||
Cursor cursor = null;
|
|
||||||
long lastLocationRead = lastSeenLocationId;
|
@Override
|
||||||
int points = 0;
|
public void clearWaypoints() {
|
||||||
int chartSamplingFrequency = getSamplingFrequency(track);
|
chartView.clearWaypoints();
|
||||||
ArrayList<double[]> result = new ArrayList<double[]>();
|
}
|
||||||
// Need two locations so we can keep track of the last location.
|
|
||||||
Location location = new MyTracksLocation("");
|
@Override
|
||||||
try {
|
public void onNewWaypoint(Waypoint wpt) {
|
||||||
while (lastSeenLocationId < track.getStopId()) {
|
chartView.addWaypoint(wpt);
|
||||||
cursor = getLocationsCursor(lastLocationRead);
|
}
|
||||||
if (cursor != null) {
|
|
||||||
elevationBuffer.reset();
|
@Override
|
||||||
speedBuffer.reset();
|
public void onNewWaypointsDone() {
|
||||||
if (cursor.moveToFirst()) {
|
runOnUiThread(updateChart);
|
||||||
final int idColumnIdx = cursor.getColumnIndexOrThrow(TrackPointsColumns._ID);
|
}
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
points++;
|
@Override
|
||||||
providerUtils.fillLocation(cursor, location);
|
public boolean onUnitsChanged(boolean metric) {
|
||||||
if (MyTracksUtils.isValidLocation(location)) {
|
this.metricUnits = metric;
|
||||||
lastLocationRead = lastSeenLocationId =
|
|
||||||
cursor.getLong(idColumnIdx);
|
chartView.setMetricUnits(metric);
|
||||||
// TODO Can we be smarter about choosing 3 or 6 entries?
|
|
||||||
double[] point = new double[6];
|
return true; // Reload data
|
||||||
location = getDataPoint(location, track, point);
|
}
|
||||||
if (points % chartSamplingFrequency == 0) {
|
|
||||||
result.add(point);
|
@Override
|
||||||
}
|
public boolean onReportSpeedChanged(boolean reportSpeed) {
|
||||||
}
|
this.reportSpeed = reportSpeed;
|
||||||
}
|
|
||||||
} else {
|
chartView.setReportSpeed(reportSpeed, this);
|
||||||
lastLocationRead += BUFFER_SIZE;
|
|
||||||
}
|
return true; // Reload data
|
||||||
} else {
|
|
||||||
lastLocationRead += BUFFER_SIZE;
|
|
||||||
}
|
|
||||||
cursor.close();
|
|
||||||
cursor = null;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} finally {
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -527,8 +527,8 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
if (nearestWaypoint != null && dmin < 100) {
|
if (nearestWaypoint != null && dmin < 100) {
|
||||||
Intent intent =
|
Intent intent =
|
||||||
new Intent(getContext(), MyTracksWaypointDetails.class);
|
new Intent(getContext(), WaypointDetails.class);
|
||||||
intent.putExtra("waypointid", nearestWaypoint.getId());
|
intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, nearestWaypoint.getId());
|
||||||
getContext().startActivity(intent);
|
getContext().startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -728,7 +728,7 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
float density = getContext().getResources().getDisplayMetrics().density;
|
float density = getContext().getResources().getDisplayMetrics().density;
|
||||||
// TODO: This should be function of the number of variables displayed.
|
maxLength = Math.max(maxLength, 1);
|
||||||
leftBorder = (int) (density * (4 + 8 * maxLength));
|
leftBorder = (int) (density * (4 + 8 * maxLength));
|
||||||
effectiveWidth = w - leftBorder - RIGHT_BORDER;
|
effectiveWidth = w - leftBorder - RIGHT_BORDER;
|
||||||
bottomBorder = (int) (density * BOTTOM_BORDER);
|
bottomBorder = (int) (density * BOTTOM_BORDER);
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class CheckUnits {
|
|||||||
|
|
||||||
private static void accept(Context context, SharedPreferences preferences) {
|
private static void accept(Context context, SharedPreferences preferences) {
|
||||||
recordCheckPerformed(preferences);
|
recordCheckPerformed(preferences);
|
||||||
Intent startIntent = new Intent(context, MyTracksSettings.class);
|
Intent startIntent = new Intent(context, SettingsActivity.class);
|
||||||
context.startActivity(startIntent);
|
context.startActivity(startIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+74
-53
@@ -20,18 +20,13 @@ package com.google.android.apps.mytracks;
|
|||||||
*
|
*
|
||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
public abstract class MyTracksConstants {
|
public abstract class Constants {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should be used by all log statements
|
* Should be used by all log statements
|
||||||
*/
|
*/
|
||||||
public static final String TAG = "MyTracks";
|
public static final String TAG = "MyTracks";
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the gps location provider:
|
|
||||||
*/
|
|
||||||
public static final String GPS_PROVIDER = "gps";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the top-level directory inside the SD card where our files will
|
* Name of the top-level directory inside the SD card where our files will
|
||||||
* be read from/written to.
|
* be read from/written to.
|
||||||
@@ -50,26 +45,26 @@ public abstract class MyTracksConstants {
|
|||||||
public static final int FEATURE_DETAILS = 5;
|
public static final int FEATURE_DETAILS = 5;
|
||||||
public static final int START_RECORDING = 6;
|
public static final int START_RECORDING = 6;
|
||||||
public static final int STOP_RECORDING = 7;
|
public static final int STOP_RECORDING = 7;
|
||||||
public static final int AUTHENTICATE_TO_DOCLIST = 8;
|
public static final int AUTHENTICATE_TO_MY_MAPS = 8;
|
||||||
public static final int AUTHENTICATE_TO_TRIX = 9;
|
public static final int AUTHENTICATE_TO_FUSION_TABLES = 9;
|
||||||
public static final int SEND_TO_DOCS = 10;
|
public static final int AUTHENTICATE_TO_DOCLIST = 10;
|
||||||
public static final int DELETE_TRACK = 11;
|
public static final int AUTHENTICATE_TO_TRIX = 11;
|
||||||
public static final int SEND_TO_GOOGLE = 12;
|
public static final int DELETE_TRACK = 13;
|
||||||
public static final int SEND_TO_GOOGLE_DIALOG = 13;
|
public static final int SEND_TO_GOOGLE_DIALOG = 14;
|
||||||
public static final int SHARE_LINK = 14;
|
public static final int SHARE_LINK = 15;
|
||||||
public static final int SHARE_GPX_FILE = 15;
|
public static final int SHARE_GPX_FILE = 16;
|
||||||
public static final int SHARE_KML_FILE = 16;
|
public static final int SHARE_KML_FILE = 17;
|
||||||
public static final int SHARE_CSV_FILE = 17;
|
public static final int SHARE_CSV_FILE = 18;
|
||||||
public static final int SHARE_TCX_FILE = 18;
|
public static final int SHARE_TCX_FILE = 19;
|
||||||
public static final int EDIT_DETAILS = 19;
|
public static final int EDIT_DETAILS = 20;
|
||||||
public static final int SAVE_GPX_FILE = 20;
|
public static final int SAVE_GPX_FILE = 21;
|
||||||
public static final int SAVE_KML_FILE = 21;
|
public static final int SAVE_KML_FILE = 22;
|
||||||
public static final int SAVE_CSV_FILE = 22;
|
public static final int SAVE_CSV_FILE = 23;
|
||||||
public static final int SAVE_TCX_FILE = 23;
|
public static final int SAVE_TCX_FILE = 24;
|
||||||
public static final int CLEAR_MAP = 24;
|
public static final int CLEAR_MAP = 25;
|
||||||
public static final int SHOW_WAYPOINT = 25;
|
public static final int SHOW_WAYPOINT = 26;
|
||||||
public static final int EDIT_WAYPOINT = 26;
|
public static final int EDIT_WAYPOINT = 27;
|
||||||
public static final int WELCOME = 27;
|
public static final int WELCOME = 28;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Menu ids:
|
* Menu ids:
|
||||||
@@ -140,6 +135,12 @@ public abstract class MyTracksConstants {
|
|||||||
*/
|
*/
|
||||||
public static final int MAX_LOADED_TRACK_POINTS = 20000;
|
public static final int MAX_LOADED_TRACK_POINTS = 20000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of track points ever loaded at once from the provider into
|
||||||
|
* memory in a single call to read points.
|
||||||
|
*/
|
||||||
|
public static final int MAX_LOADED_TRACK_POINTS_PER_BATCH = 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum number of way points displayed by the map overlay.
|
* Maximum number of way points displayed by the map overlay.
|
||||||
*/
|
*/
|
||||||
@@ -168,6 +169,12 @@ public abstract class MyTracksConstants {
|
|||||||
*/
|
*/
|
||||||
public static final double MAX_ACCELERATION = 0.02;
|
public static final double MAX_ACCELERATION = 0.02;
|
||||||
|
|
||||||
|
/** Maximum age of a GPS location to be considered current. */
|
||||||
|
public static final long MAX_LOCATION_AGE_MS = 60 * 1000; // 1 minute
|
||||||
|
|
||||||
|
/** Maximum age of a network location to be considered current. */
|
||||||
|
public static final long MAX_NETWORK_AGE_MS = 1000 * 60 * 10; // 10 minutes
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of account that we can use for gdata uploads.
|
* The type of account that we can use for gdata uploads.
|
||||||
*/
|
*/
|
||||||
@@ -182,32 +189,32 @@ public abstract class MyTracksConstants {
|
|||||||
|
|
||||||
public static int getActionFromMenuId(int menuId) {
|
public static int getActionFromMenuId(int menuId) {
|
||||||
switch (menuId) {
|
switch (menuId) {
|
||||||
case MyTracksConstants.MENU_SEND_TO_GOOGLE:
|
case Constants.MENU_SEND_TO_GOOGLE:
|
||||||
return MyTracksConstants.SEND_TO_GOOGLE_DIALOG;
|
return Constants.SEND_TO_GOOGLE_DIALOG;
|
||||||
case MyTracksConstants.MENU_EDIT:
|
case Constants.MENU_EDIT:
|
||||||
return MyTracksConstants.EDIT_DETAILS;
|
return Constants.EDIT_DETAILS;
|
||||||
case MyTracksConstants.MENU_DELETE:
|
case Constants.MENU_DELETE:
|
||||||
return MyTracksConstants.DELETE_TRACK;
|
return Constants.DELETE_TRACK;
|
||||||
case MyTracksConstants.MENU_SHARE_LINK:
|
case Constants.MENU_SHARE_LINK:
|
||||||
return MyTracksConstants.SHARE_LINK;
|
return Constants.SHARE_LINK;
|
||||||
case MyTracksConstants.MENU_SHARE_KML_FILE:
|
case Constants.MENU_SHARE_KML_FILE:
|
||||||
return MyTracksConstants.SHARE_KML_FILE;
|
return Constants.SHARE_KML_FILE;
|
||||||
case MyTracksConstants.MENU_SHARE_GPX_FILE:
|
case Constants.MENU_SHARE_GPX_FILE:
|
||||||
return MyTracksConstants.SHARE_GPX_FILE;
|
return Constants.SHARE_GPX_FILE;
|
||||||
case MyTracksConstants.MENU_SHARE_CSV_FILE:
|
case Constants.MENU_SHARE_CSV_FILE:
|
||||||
return MyTracksConstants.SHARE_CSV_FILE;
|
return Constants.SHARE_CSV_FILE;
|
||||||
case MyTracksConstants.MENU_SHARE_TCX_FILE:
|
case Constants.MENU_SHARE_TCX_FILE:
|
||||||
return MyTracksConstants.SHARE_TCX_FILE;
|
return Constants.SHARE_TCX_FILE;
|
||||||
case MyTracksConstants.MENU_SAVE_GPX_FILE:
|
case Constants.MENU_SAVE_GPX_FILE:
|
||||||
return MyTracksConstants.SAVE_GPX_FILE;
|
return Constants.SAVE_GPX_FILE;
|
||||||
case MyTracksConstants.MENU_SAVE_KML_FILE:
|
case Constants.MENU_SAVE_KML_FILE:
|
||||||
return MyTracksConstants.SAVE_KML_FILE;
|
return Constants.SAVE_KML_FILE;
|
||||||
case MyTracksConstants.MENU_SAVE_CSV_FILE:
|
case Constants.MENU_SAVE_CSV_FILE:
|
||||||
return MyTracksConstants.SAVE_CSV_FILE;
|
return Constants.SAVE_CSV_FILE;
|
||||||
case MyTracksConstants.MENU_SAVE_TCX_FILE:
|
case Constants.MENU_SAVE_TCX_FILE:
|
||||||
return MyTracksConstants.SAVE_TCX_FILE;
|
return Constants.SAVE_TCX_FILE;
|
||||||
case MyTracksConstants.MENU_CLEAR_MAP:
|
case Constants.MENU_CLEAR_MAP:
|
||||||
return MyTracksConstants.CLEAR_MAP;
|
return Constants.CLEAR_MAP;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -216,8 +223,22 @@ public abstract class MyTracksConstants {
|
|||||||
public static final String MAPSHOP_BASE_URL =
|
public static final String MAPSHOP_BASE_URL =
|
||||||
"http://maps.google.com/maps/ms";
|
"http://maps.google.com/maps/ms";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default values - keep in sync with those in preferences.xml.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static final int DEFAULT_ANNOUNCEMENT_FREQUENCY = -1;
|
||||||
|
public static final int DEFAULT_AUTO_RESUME_TRACK_TIMEOUT = 10; // In min.
|
||||||
|
public static final int DEFAULT_MAX_RECORDING_DISTANCE = 200;
|
||||||
|
public static final int DEFAULT_MIN_RECORDING_DISTANCE = 5;
|
||||||
|
public static final int DEFAULT_MIN_RECORDING_INTERVAL = 0;
|
||||||
|
public static final int DEFAULT_MIN_REQUIRED_ACCURACY = 200;
|
||||||
|
public static final int DEFAULT_SPLIT_FREQUENCY = 0;
|
||||||
|
|
||||||
|
public static final String SETTINGS_NAME = "SettingsActivity";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an abstract utility class.
|
* This is an abstract utility class.
|
||||||
*/
|
*/
|
||||||
protected MyTracksConstants() { }
|
protected Constants() { }
|
||||||
}
|
}
|
||||||
+5
-4
@@ -34,12 +34,12 @@ import android.util.Log;
|
|||||||
*
|
*
|
||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
public class MyTracksDeleteAllTracks extends Handler {
|
public class DeleteAllTracks extends Handler {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final Runnable done;
|
private final Runnable done;
|
||||||
|
|
||||||
public MyTracksDeleteAllTracks(Context context, Runnable done) {
|
public DeleteAllTracks(Context context, Runnable done) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.done = done;
|
this.done = done;
|
||||||
}
|
}
|
||||||
@@ -58,11 +58,12 @@ public class MyTracksDeleteAllTracks extends Handler {
|
|||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int i) {
|
public void onClick(DialogInterface dialog, int i) {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
Log.w(MyTracksConstants.TAG, "deleting all!");
|
Log.w(Constants.TAG, "deleting all!");
|
||||||
MyTracksProviderUtils.Factory.get(context).deleteAllTracks();
|
MyTracksProviderUtils.Factory.get(context).deleteAllTracks();
|
||||||
SharedPreferences prefs =
|
SharedPreferences prefs =
|
||||||
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
|
// TODO: Go through data manager
|
||||||
editor.putLong(context.getString(R.string.selected_track_key), -1);
|
editor.putLong(context.getString(R.string.selected_track_key), -1);
|
||||||
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(editor);
|
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(editor);
|
||||||
if (done != null) {
|
if (done != null) {
|
||||||
@@ -15,15 +15,17 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks;
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.io.sendtogoogle.SendDialog;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager.BadTokenException;
|
import android.view.WindowManager.BadTokenException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,14 +39,10 @@ public class DialogManager {
|
|||||||
public static final int DIALOG_IMPORT_PROGRESS = 2;
|
public static final int DIALOG_IMPORT_PROGRESS = 2;
|
||||||
public static final int DIALOG_PROGRESS = 3;
|
public static final int DIALOG_PROGRESS = 3;
|
||||||
public static final int DIALOG_SEND_TO_GOOGLE = 4;
|
public static final int DIALOG_SEND_TO_GOOGLE = 4;
|
||||||
public static final int DIALOG_SEND_TO_GOOGLE_RESULT = 5;
|
|
||||||
public static final int DIALOG_WRITE_PROGRESS = 6;
|
|
||||||
|
|
||||||
private ProgressDialog progressDialog;
|
private ProgressDialog progressDialog;
|
||||||
private ProgressDialog importProgressDialog;
|
private ProgressDialog importProgressDialog;
|
||||||
private ProgressDialog writeProgressDialog;
|
private SendDialog sendToGoogleDialog;
|
||||||
private SendToGoogleDialog sendToGoogleDialog;
|
|
||||||
private AlertDialog sendToGoogleResultDialog;
|
|
||||||
private ChartSettingsDialog chartSettingsDialog;
|
private ChartSettingsDialog chartSettingsDialog;
|
||||||
|
|
||||||
private MyTracks activity;
|
private MyTracks activity;
|
||||||
@@ -77,32 +75,8 @@ public class DialogManager {
|
|||||||
progressDialog.setProgress(10);
|
progressDialog.setProgress(10);
|
||||||
return progressDialog;
|
return progressDialog;
|
||||||
case DIALOG_SEND_TO_GOOGLE:
|
case DIALOG_SEND_TO_GOOGLE:
|
||||||
sendToGoogleDialog = new SendToGoogleDialog(activity);
|
sendToGoogleDialog = new SendDialog(activity);
|
||||||
return sendToGoogleDialog;
|
return sendToGoogleDialog;
|
||||||
case DIALOG_SEND_TO_GOOGLE_RESULT:
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
|
||||||
builder.setIcon(android.R.drawable.ic_dialog_info);
|
|
||||||
builder.setTitle("Title");
|
|
||||||
builder.setMessage("Message");
|
|
||||||
builder.setPositiveButton(activity.getString(R.string.ok), null);
|
|
||||||
builder.setNeutralButton(activity.getString(R.string.share_track),
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
activity.shareLinkToFusionTable(activity.sendToTrackId);
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
sendToGoogleResultDialog = builder.create();
|
|
||||||
return sendToGoogleResultDialog;
|
|
||||||
case DIALOG_WRITE_PROGRESS:
|
|
||||||
writeProgressDialog = new ProgressDialog(activity);
|
|
||||||
writeProgressDialog.setIcon(android.R.drawable.ic_dialog_info);
|
|
||||||
writeProgressDialog.setTitle(
|
|
||||||
activity.getString(R.string.progress_title));
|
|
||||||
writeProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
|
||||||
writeProgressDialog.setMessage(
|
|
||||||
activity.getString(R.string.write_progress_message));
|
|
||||||
return writeProgressDialog;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -112,24 +86,8 @@ public class DialogManager {
|
|||||||
case DIALOG_SEND_TO_GOOGLE:
|
case DIALOG_SEND_TO_GOOGLE:
|
||||||
activity.resetSendToGoogleStatus();
|
activity.resetSendToGoogleStatus();
|
||||||
break;
|
break;
|
||||||
case DIALOG_SEND_TO_GOOGLE_RESULT:
|
|
||||||
boolean success = activity.getSendToGoogleSuccess();
|
|
||||||
sendToGoogleResultDialog.setTitle(
|
|
||||||
success ? R.string.success : R.string.error);
|
|
||||||
sendToGoogleResultDialog.setIcon(success
|
|
||||||
? android.R.drawable.ic_dialog_info
|
|
||||||
: android.R.drawable.ic_dialog_alert);
|
|
||||||
sendToGoogleResultDialog.setMessage(activity.getFusionTablesResultMessage());
|
|
||||||
|
|
||||||
boolean canShare = activity.getSendToFusionTablesTableId() != null;
|
|
||||||
View share =
|
|
||||||
sendToGoogleResultDialog.findViewById(android.R.id.button3);
|
|
||||||
if (share != null) {
|
|
||||||
share.setVisibility(canShare ? View.VISIBLE : View.GONE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DIALOG_CHART_SETTINGS:
|
case DIALOG_CHART_SETTINGS:
|
||||||
Log.d(MyTracksConstants.TAG, "MyTracks.onPrepare chart dialog");
|
Log.d(TAG, "MyTracks.onPrepare chart dialog");
|
||||||
chartSettingsDialog.setup(activity.getChartActivity());
|
chartSettingsDialog.setup(activity.getChartActivity());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -162,7 +120,7 @@ public class DialogManager {
|
|||||||
/**
|
/**
|
||||||
* @return the sendToGoogleDialog
|
* @return the sendToGoogleDialog
|
||||||
*/
|
*/
|
||||||
public SendToGoogleDialog getSendToGoogleDialog() {
|
public SendDialog getSendToGoogleDialog() {
|
||||||
return sendToGoogleDialog;
|
return sendToGoogleDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,9 +149,9 @@ public class DialogManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just like showDialog, but will catch a BadTokenException that sometimes
|
* Just like showDialog, but will catch a {@link BadTokenException} that
|
||||||
* (very rarely) gets thrown. This might happen if the user hits the "back"
|
* sometimes (very rarely) gets thrown. This might happen if the user hits
|
||||||
* button immediately after sending tracks to google.
|
* the "back" button immediately after sending tracks to google.
|
||||||
*
|
*
|
||||||
* @param id the dialog id
|
* @param id the dialog id
|
||||||
*/
|
*/
|
||||||
@@ -203,11 +161,27 @@ public class DialogManager {
|
|||||||
try {
|
try {
|
||||||
activity.showDialog(id);
|
activity.showDialog(id);
|
||||||
} catch (BadTokenException e) {
|
} catch (BadTokenException e) {
|
||||||
Log.w(MyTracksConstants.TAG,
|
Log.w(TAG, "Could not display dialog with id " + id, e);
|
||||||
"Could not display dialog with id " + id, e);
|
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
Log.w(MyTracksConstants.TAG,
|
Log.w(TAG, "Could not display dialog with id " + id, e);
|
||||||
"Could not display dialog with id " + id, e);
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The equivalent of {@link #showDialogSafely(int)}, but for a specific
|
||||||
|
* dialog instance.
|
||||||
|
*/
|
||||||
|
public static void showDialogSafely(Activity activity, final Dialog dialog) {
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
dialog.show();
|
||||||
|
} catch (BadTokenException e) {
|
||||||
|
Log.w(TAG, "Could not display dialog", e);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
Log.w(TAG, "Could not display dialog", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -228,4 +202,19 @@ public class DialogManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The equivalent of {@link #dismissDialogSafely(int)}, but for a specific
|
||||||
|
* dialog instance.
|
||||||
|
*/
|
||||||
|
public static void dismissDialogSafely(Activity activity, final Dialog dialog) {
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
dialog.dismiss();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// This will be thrown if this dialog was not shown before.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ class Eula {
|
|||||||
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(
|
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(
|
||||||
preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true));
|
preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true));
|
||||||
Intent startIntent = new Intent(activity, WelcomeActivity.class);
|
Intent startIntent = new Intent(activity, WelcomeActivity.class);
|
||||||
activity.startActivityForResult(startIntent, MyTracksConstants.WELCOME);
|
activity.startActivityForResult(startIntent, Constants.WELCOME);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void refuse(Activity activity) {
|
private static void refuse(Activity activity) {
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ package com.google.android.apps.mytracks;
|
|||||||
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||||
import com.google.android.apps.mytracks.io.TrackWriter;
|
import com.google.android.apps.mytracks.io.file.TrackWriter;
|
||||||
import com.google.android.apps.mytracks.io.TrackWriterFactory;
|
import com.google.android.apps.mytracks.io.file.TrackWriterFactory;
|
||||||
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
|
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
|
||||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@@ -71,14 +71,14 @@ public class ExportAllTracks {
|
|||||||
format = TrackFileFormat.TCX;
|
format = TrackFileFormat.TCX;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.w(MyTracksConstants.TAG, "Unknown export format: " + which);
|
Log.w(Constants.TAG, "Unknown export format: " + which);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public ExportAllTracks(Activity activity) {
|
public ExportAllTracks(Activity activity) {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
Log.i(MyTracksConstants.TAG, "ExportAllTracks: Starting");
|
Log.i(Constants.TAG, "ExportAllTracks: Starting");
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.setSingleChoiceItems(R.array.export_formats, 0, itemClick);
|
builder.setSingleChoiceItems(R.array.export_formats, 0, itemClick);
|
||||||
@@ -113,14 +113,14 @@ public class ExportAllTracks {
|
|||||||
*/
|
*/
|
||||||
private void aquireLocksAndExport() {
|
private void aquireLocksAndExport() {
|
||||||
SharedPreferences prefs =
|
SharedPreferences prefs =
|
||||||
activity.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
activity.getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||||
long recordingTrackId = -1;
|
long recordingTrackId = -1;
|
||||||
if (prefs != null) {
|
if (prefs != null) {
|
||||||
recordingTrackId =
|
recordingTrackId =
|
||||||
prefs.getLong(activity.getString(R.string.recording_track_key), -1);
|
prefs.getLong(activity.getString(R.string.recording_track_key), -1);
|
||||||
}
|
}
|
||||||
if (recordingTrackId != -1) {
|
if (recordingTrackId != -1) {
|
||||||
wakeLock = MyTracksUtils.acquireWakeLock(activity, wakeLock);
|
wakeLock = SystemUtils.acquireWakeLock(activity, wakeLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we can safely export everything.
|
// Now we can safely export everything.
|
||||||
@@ -130,9 +130,9 @@ public class ExportAllTracks {
|
|||||||
// TODO check what happens if we started recording after getting this lock.
|
// TODO check what happens if we started recording after getting this lock.
|
||||||
if (wakeLock != null && wakeLock.isHeld()) {
|
if (wakeLock != null && wakeLock.isHeld()) {
|
||||||
wakeLock.release();
|
wakeLock.release();
|
||||||
Log.i(MyTracksConstants.TAG, "ExportAllTracks: Releasing wake lock.");
|
Log.i(Constants.TAG, "ExportAllTracks: Releasing wake lock.");
|
||||||
}
|
}
|
||||||
Log.i(MyTracksConstants.TAG, "ExportAllTracks: Done");
|
Log.i(Constants.TAG, "ExportAllTracks: Done");
|
||||||
Toast.makeText(activity, R.string.export_done, Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, R.string.export_done, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ public class ExportAllTracks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final int trackCount = cursor.getCount();
|
final int trackCount = cursor.getCount();
|
||||||
Log.i(MyTracksConstants.TAG,
|
Log.i(Constants.TAG,
|
||||||
"ExportAllTracks: Exporting: " + cursor.getCount() + " tracks.");
|
"ExportAllTracks: Exporting: " + cursor.getCount() + " tracks.");
|
||||||
int idxTrackId = cursor.getColumnIndexOrThrow(TracksColumns._ID);
|
int idxTrackId = cursor.getColumnIndexOrThrow(TracksColumns._ID);
|
||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
@@ -186,7 +186,7 @@ public class ExportAllTracks {
|
|||||||
});
|
});
|
||||||
|
|
||||||
long id = cursor.getLong(idxTrackId);
|
long id = cursor.getLong(idxTrackId);
|
||||||
Log.i(MyTracksConstants.TAG, "ExportAllTracks: exporting: " + id);
|
Log.i(Constants.TAG, "ExportAllTracks: exporting: " + id);
|
||||||
TrackWriter writer =
|
TrackWriter writer =
|
||||||
TrackWriterFactory.newWriter(activity, providerUtils, id, format);
|
TrackWriterFactory.newWriter(activity, providerUtils, id, format);
|
||||||
writer.writeTrack();
|
writer.writeTrack();
|
||||||
|
|||||||
@@ -16,9 +16,9 @@
|
|||||||
package com.google.android.apps.mytracks;
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
import com.google.android.apps.mytracks.io.GpxImporter;
|
import com.google.android.apps.mytracks.io.file.GpxImporter;
|
||||||
import com.google.android.apps.mytracks.util.FileUtils;
|
import com.google.android.apps.mytracks.util.FileUtils;
|
||||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@@ -60,7 +60,7 @@ public class ImportAllTracks {
|
|||||||
|
|
||||||
public ImportAllTracks(Activity activity) {
|
public ImportAllTracks(Activity activity) {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
Log.i(MyTracksConstants.TAG, "ImportAllTracks: Starting");
|
Log.i(Constants.TAG, "ImportAllTracks: Starting");
|
||||||
fileUtils = new FileUtils();
|
fileUtils = new FileUtils();
|
||||||
gpxPath = fileUtils.buildExternalDirectoryPath("gpx");
|
gpxPath = fileUtils.buildExternalDirectoryPath("gpx");
|
||||||
HandlerThread handlerThread;
|
HandlerThread handlerThread;
|
||||||
@@ -82,13 +82,13 @@ public class ImportAllTracks {
|
|||||||
* track. Acquire a wake lock if there is no current track.
|
* track. Acquire a wake lock if there is no current track.
|
||||||
*/
|
*/
|
||||||
private void aquireLocksAndImport() {
|
private void aquireLocksAndImport() {
|
||||||
SharedPreferences prefs = activity.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
SharedPreferences prefs = activity.getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||||
long recordingTrackId = -1;
|
long recordingTrackId = -1;
|
||||||
if (prefs != null) {
|
if (prefs != null) {
|
||||||
recordingTrackId = prefs.getLong(activity.getString(R.string.recording_track_key), -1);
|
recordingTrackId = prefs.getLong(activity.getString(R.string.recording_track_key), -1);
|
||||||
}
|
}
|
||||||
if (recordingTrackId != -1) {
|
if (recordingTrackId != -1) {
|
||||||
wakeLock = MyTracksUtils.acquireWakeLock(activity, wakeLock);
|
wakeLock = SystemUtils.acquireWakeLock(activity, wakeLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we can safely import everything.
|
// Now we can safely import everything.
|
||||||
@@ -98,10 +98,10 @@ public class ImportAllTracks {
|
|||||||
// TODO check what happens if we started recording after getting this lock.
|
// TODO check what happens if we started recording after getting this lock.
|
||||||
if (wakeLock != null && wakeLock.isHeld()) {
|
if (wakeLock != null && wakeLock.isHeld()) {
|
||||||
wakeLock.release();
|
wakeLock.release();
|
||||||
Log.i(MyTracksConstants.TAG, "ImportAllTracks: Releasing wake lock.");
|
Log.i(Constants.TAG, "ImportAllTracks: Releasing wake lock.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(MyTracksConstants.TAG, "ImportAllTracks: Done");
|
Log.i(Constants.TAG, "ImportAllTracks: Done");
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
if (gpxFileCount == 0) {
|
if (gpxFileCount == 0) {
|
||||||
builder.setMessage(activity.getString(R.string.import_empty, gpxPath + "/"));
|
builder.setMessage(activity.getString(R.string.import_empty, gpxPath + "/"));
|
||||||
@@ -141,7 +141,7 @@ public class ImportAllTracks {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(MyTracksConstants.TAG, "ImportAllTracks: Importing: " + gpxFileCount + " tracks.");
|
Log.i(Constants.TAG, "ImportAllTracks: Importing: " + gpxFileCount + " tracks.");
|
||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
makeProgressDialog(gpxFileCount);
|
makeProgressDialog(gpxFileCount);
|
||||||
@@ -180,19 +180,19 @@ public class ImportAllTracks {
|
|||||||
* notifications and returns false on failure.
|
* notifications and returns false on failure.
|
||||||
*/
|
*/
|
||||||
private boolean importFile(File gpxFile, MyTracksProviderUtils providerUtils) {
|
private boolean importFile(File gpxFile, MyTracksProviderUtils providerUtils) {
|
||||||
Log.i(MyTracksConstants.TAG, "ImportAllTracks: importing: " + gpxFile.getName());
|
Log.i(Constants.TAG, "ImportAllTracks: importing: " + gpxFile.getName());
|
||||||
try {
|
try {
|
||||||
GpxImporter.importGPXFile(new FileInputStream(gpxFile), providerUtils);
|
GpxImporter.importGPXFile(new FileInputStream(gpxFile), providerUtils);
|
||||||
return true;
|
return true;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.w(MyTracksConstants.TAG, "GPX file wasn't found/went missing: "
|
Log.w(Constants.TAG, "GPX file wasn't found/went missing: "
|
||||||
+ gpxFile.getAbsolutePath(), e);
|
+ gpxFile.getAbsolutePath(), e);
|
||||||
} catch (ParserConfigurationException e) {
|
} catch (ParserConfigurationException e) {
|
||||||
Log.w(MyTracksConstants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e);
|
Log.w(Constants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e);
|
||||||
} catch (SAXException e) {
|
} catch (SAXException e) {
|
||||||
Log.w(MyTracksConstants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e);
|
Log.w(Constants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(MyTracksConstants.TAG, "Error reading file: " + gpxFile.getAbsolutePath(), e);
|
Log.w(Constants.TAG, "Error reading file: " + gpxFile.getAbsolutePath(), e);
|
||||||
}
|
}
|
||||||
Toast.makeText(activity, activity.getString(R.string.import_error, gpxFile.getName()),
|
Toast.makeText(activity, activity.getString(R.string.import_error, gpxFile.getName()),
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
|
|||||||
@@ -0,0 +1,580 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 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.
|
||||||
|
*/
|
||||||
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.TrackDataHub.ListenerDataType;
|
||||||
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
|
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.TripStatistics;
|
||||||
|
import com.google.android.apps.mytracks.util.ApiFeatures;
|
||||||
|
import com.google.android.apps.mytracks.util.GeoRect;
|
||||||
|
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||||
|
import com.google.android.maps.GeoPoint;
|
||||||
|
import com.google.android.maps.MapController;
|
||||||
|
import com.google.android.maps.MapView;
|
||||||
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.location.Location;
|
||||||
|
import android.location.LocationManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.ContextMenu;
|
||||||
|
import android.view.ContextMenu.ContextMenuInfo;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.SubMenu;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnCreateContextMenuListener;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map view activity of the MyTracks application.
|
||||||
|
*
|
||||||
|
* @author Leif Hendrik Wilden
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public class MapActivity extends com.google.android.maps.MapActivity
|
||||||
|
implements View.OnTouchListener, View.OnClickListener,
|
||||||
|
TrackDataListener {
|
||||||
|
|
||||||
|
// Saved instance state keys:
|
||||||
|
// ---------------------------
|
||||||
|
|
||||||
|
private static final String KEY_CURRENT_LOCATION = "currentLocation";
|
||||||
|
private static final String KEY_KEEP_MY_LOCATION_VISIBLE = "keepMyLocationVisible";
|
||||||
|
|
||||||
|
private TrackDataHub dataHub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the map should be scrolled so that the pointer is always in the
|
||||||
|
* visible area.
|
||||||
|
*/
|
||||||
|
private boolean keepMyLocationVisible;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current pointer location.
|
||||||
|
* This is kept to quickly center on it when the user requests.
|
||||||
|
*/
|
||||||
|
private Location currentLocation;
|
||||||
|
|
||||||
|
// UI elements:
|
||||||
|
// -------------
|
||||||
|
|
||||||
|
private RelativeLayout screen;
|
||||||
|
private MapView mapView;
|
||||||
|
private MapOverlay mapOverlay;
|
||||||
|
private LinearLayout messagePane;
|
||||||
|
private TextView messageText;
|
||||||
|
private LinearLayout busyPane;
|
||||||
|
private ImageButton optionsBtn;
|
||||||
|
|
||||||
|
private MenuItem myLocation;
|
||||||
|
private MenuItem toggleLayers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We are not displaying driving directions. Just an arbitrary track that is
|
||||||
|
* not associated to any licensed mapping data. Therefore it should be okay to
|
||||||
|
* return false here and still comply with the terms of service.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean isRouteDisplayed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We are displaying a location. This needs to return true in order to comply
|
||||||
|
* with the terms of service.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean isLocationDisplayed() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Application life cycle:
|
||||||
|
// ------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle bundle) {
|
||||||
|
Log.d(TAG, "MapActivity.onCreate");
|
||||||
|
super.onCreate(bundle);
|
||||||
|
|
||||||
|
// The volume we want to control is the Text-To-Speech volume
|
||||||
|
int volumeStream =
|
||||||
|
new StatusAnnouncerFactory(ApiFeatures.getInstance()).getVolumeStream();
|
||||||
|
setVolumeControlStream(volumeStream);
|
||||||
|
|
||||||
|
dataHub = MyTracks.getInstance().getDataHub();
|
||||||
|
|
||||||
|
// We don't need a window title bar:
|
||||||
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
|
|
||||||
|
// Inflate the layout:
|
||||||
|
setContentView(R.layout.mytracks_layout);
|
||||||
|
|
||||||
|
// Remove the window's background because the MapView will obscure it
|
||||||
|
getWindow().setBackgroundDrawable(null);
|
||||||
|
|
||||||
|
// Set up a map overlay:
|
||||||
|
screen = (RelativeLayout) findViewById(R.id.screen);
|
||||||
|
mapView = (MapView) findViewById(R.id.map);
|
||||||
|
mapView.requestFocus();
|
||||||
|
mapOverlay = new MapOverlay(this);
|
||||||
|
mapView.getOverlays().add(mapOverlay);
|
||||||
|
mapView.setOnTouchListener(this);
|
||||||
|
mapView.setBuiltInZoomControls(true);
|
||||||
|
messagePane = (LinearLayout) findViewById(R.id.messagepane);
|
||||||
|
messageText = (TextView) findViewById(R.id.messagetext);
|
||||||
|
busyPane = (LinearLayout) findViewById(R.id.busypane);
|
||||||
|
optionsBtn = (ImageButton) findViewById(R.id.showOptions);
|
||||||
|
|
||||||
|
optionsBtn.setOnCreateContextMenuListener(contextMenuListener);
|
||||||
|
optionsBtn.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onRestoreInstanceState(Bundle bundle) {
|
||||||
|
Log.d(TAG, "MapActivity.onRestoreInstanceState");
|
||||||
|
if (bundle != null) {
|
||||||
|
super.onRestoreInstanceState(bundle);
|
||||||
|
keepMyLocationVisible =
|
||||||
|
bundle.getBoolean(KEY_KEEP_MY_LOCATION_VISIBLE, false);
|
||||||
|
if (bundle.containsKey(KEY_CURRENT_LOCATION)) {
|
||||||
|
currentLocation = (Location) bundle.getParcelable(KEY_CURRENT_LOCATION);
|
||||||
|
if (currentLocation != null) {
|
||||||
|
showCurrentLocation();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentLocation = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
Log.d(TAG, "MapActivity.onStart");
|
||||||
|
super.onStart();
|
||||||
|
|
||||||
|
dataHub.registerTrackDataListener(this, EnumSet.of(
|
||||||
|
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||||
|
ListenerDataType.POINT_UPDATES,
|
||||||
|
ListenerDataType.WAYPOINT_UPDATES,
|
||||||
|
ListenerDataType.LOCATION_UPDATES,
|
||||||
|
ListenerDataType.COMPASS_UPDATES));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
|
Log.d(TAG, "MapActivity.onSaveInstanceState");
|
||||||
|
outState.putBoolean(KEY_KEEP_MY_LOCATION_VISIBLE, keepMyLocationVisible);
|
||||||
|
if (currentLocation != null) {
|
||||||
|
outState.putParcelable(KEY_CURRENT_LOCATION, currentLocation);
|
||||||
|
}
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
Log.d(TAG, "MapActivity.onStop");
|
||||||
|
|
||||||
|
dataHub.unregisterTrackDataListener(this);
|
||||||
|
|
||||||
|
super.onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility functions:
|
||||||
|
// -------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the options button if a track is selected, or hide it if not.
|
||||||
|
*/
|
||||||
|
private void updateOptionsButton(boolean trackSelected) {
|
||||||
|
optionsBtn.setVisibility(
|
||||||
|
trackSelected ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if a location is visible.
|
||||||
|
*
|
||||||
|
* @param location a given location
|
||||||
|
* @return true if the given location is within the visible map area
|
||||||
|
*/
|
||||||
|
private boolean locationIsVisible(Location location) {
|
||||||
|
if (location == null || mapView == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GeoPoint center = mapView.getMapCenter();
|
||||||
|
int latSpan = mapView.getLatitudeSpan();
|
||||||
|
int lonSpan = mapView.getLongitudeSpan();
|
||||||
|
|
||||||
|
// Bottom of map view is obscured by zoom controls/buttons.
|
||||||
|
// Subtract a margin from the visible area:
|
||||||
|
GeoPoint marginBottom = mapView.getProjection().fromPixels(
|
||||||
|
0, mapView.getHeight());
|
||||||
|
GeoPoint marginTop = mapView.getProjection().fromPixels(0,
|
||||||
|
mapView.getHeight()
|
||||||
|
- mapView.getZoomButtonsController().getZoomControls().getHeight());
|
||||||
|
int margin =
|
||||||
|
Math.abs(marginTop.getLatitudeE6() - marginBottom.getLatitudeE6());
|
||||||
|
GeoRect r = new GeoRect(center, latSpan, lonSpan);
|
||||||
|
r.top += margin;
|
||||||
|
|
||||||
|
GeoPoint geoPoint = LocationUtils.getGeoPoint(location);
|
||||||
|
return r.contains(geoPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the location pointer to the current location and center the map if
|
||||||
|
* the current location is outside the visible area.
|
||||||
|
*/
|
||||||
|
private void showCurrentLocation() {
|
||||||
|
if (currentLocation == null || mapOverlay == null || mapView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mapOverlay.setMyLocation(currentLocation);
|
||||||
|
mapView.postInvalidate();
|
||||||
|
if (keepMyLocationVisible && !locationIsVisible(currentLocation)) {
|
||||||
|
GeoPoint geoPoint = LocationUtils.getGeoPoint(currentLocation);
|
||||||
|
MapController controller = mapView.getController();
|
||||||
|
controller.animateTo(geoPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrackUpdated(Track track) {
|
||||||
|
// We don't care.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zooms and pans the map so that the given track is visible.
|
||||||
|
*
|
||||||
|
* @param track the track
|
||||||
|
*/
|
||||||
|
private void zoomMapToBoundaries(Track track) {
|
||||||
|
if (mapView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (track == null || track.getNumberOfPoints() < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TripStatistics stats = track.getStatistics();
|
||||||
|
int bottom = stats.getBottom();
|
||||||
|
int left = stats.getLeft();
|
||||||
|
int latSpanE6 = stats.getTop() - bottom;
|
||||||
|
int lonSpanE6 = stats.getRight() - left;
|
||||||
|
if (latSpanE6 > 0
|
||||||
|
&& latSpanE6 < 180E6
|
||||||
|
&& lonSpanE6 > 0
|
||||||
|
&& lonSpanE6 < 360E6) {
|
||||||
|
keepMyLocationVisible = false;
|
||||||
|
GeoPoint center = new GeoPoint(
|
||||||
|
bottom + latSpanE6 / 2,
|
||||||
|
left + lonSpanE6 / 2);
|
||||||
|
if (LocationUtils.isValidGeoPoint(center)) {
|
||||||
|
mapView.getController().setCenter(center);
|
||||||
|
mapView.getController().zoomToSpan(latSpanE6, lonSpanE6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zooms and pans the map so that the given waypoint is visible.
|
||||||
|
*/
|
||||||
|
public void showWaypoint(long waypointId) {
|
||||||
|
MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(this);
|
||||||
|
Waypoint wpt = providerUtils.getWaypoint(waypointId);
|
||||||
|
if (wpt != null && wpt.getLocation() != null) {
|
||||||
|
keepMyLocationVisible = false;
|
||||||
|
GeoPoint center = new GeoPoint(
|
||||||
|
(int) (wpt.getLocation().getLatitude() * 1E6),
|
||||||
|
(int) (wpt.getLocation().getLongitude() * 1E6));
|
||||||
|
mapView.getController().setCenter(center);
|
||||||
|
mapView.getController().setZoom(20);
|
||||||
|
mapView.invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSelectedTrackChanged(final Track track, final boolean isRecording) {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
boolean trackSelected = track != null;
|
||||||
|
updateOptionsButton(trackSelected);
|
||||||
|
|
||||||
|
mapOverlay.setTrackDrawingEnabled(trackSelected);
|
||||||
|
|
||||||
|
if (trackSelected) {
|
||||||
|
busyPane.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
zoomMapToBoundaries(track);
|
||||||
|
|
||||||
|
mapOverlay.setShowEndMarker(!isRecording);
|
||||||
|
busyPane.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
mapView.invalidate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private final OnCreateContextMenuListener contextMenuListener =
|
||||||
|
new OnCreateContextMenuListener() {
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||||
|
ContextMenuInfo menuInfo) {
|
||||||
|
menu.setHeaderTitle(R.string.tracklist_this_track);
|
||||||
|
menu.add(0, Constants.MENU_EDIT, 0,
|
||||||
|
R.string.tracklist_edit_track);
|
||||||
|
if (!dataHub.isRecordingSelected()) {
|
||||||
|
menu.add(0, Constants.MENU_SEND_TO_GOOGLE, 0,
|
||||||
|
R.string.tracklist_send_to_google);
|
||||||
|
SubMenu share = menu.addSubMenu(0, Constants.MENU_SHARE, 0,
|
||||||
|
R.string.tracklist_share_track);
|
||||||
|
share.add(0, Constants.MENU_SHARE_LINK, 0,
|
||||||
|
R.string.tracklist_share_link);
|
||||||
|
share.add(0, Constants.MENU_SHARE_GPX_FILE, 0,
|
||||||
|
R.string.tracklist_share_gpx_file);
|
||||||
|
share.add(0, Constants.MENU_SHARE_KML_FILE, 0,
|
||||||
|
R.string.tracklist_share_kml_file);
|
||||||
|
share.add(0, Constants.MENU_SHARE_CSV_FILE, 0,
|
||||||
|
R.string.tracklist_share_csv_file);
|
||||||
|
share.add(0, Constants.MENU_SHARE_TCX_FILE, 0,
|
||||||
|
R.string.tracklist_share_tcx_file);
|
||||||
|
SubMenu save = menu.addSubMenu(0,
|
||||||
|
Constants.MENU_WRITE_TO_SD_CARD, 0,
|
||||||
|
R.string.tracklist_write_to_sd);
|
||||||
|
save.add(0, Constants.MENU_SAVE_GPX_FILE, 0,
|
||||||
|
R.string.tracklist_save_as_gpx);
|
||||||
|
save.add(0, Constants.MENU_SAVE_KML_FILE, 0,
|
||||||
|
R.string.tracklist_save_as_kml);
|
||||||
|
save.add(0, Constants.MENU_SAVE_CSV_FILE, 0,
|
||||||
|
R.string.tracklist_save_as_csv);
|
||||||
|
save.add(0, Constants.MENU_SAVE_TCX_FILE, 0,
|
||||||
|
R.string.tracklist_save_as_tcx);
|
||||||
|
menu.add(0, Constants.MENU_CLEAR_MAP, 0,
|
||||||
|
R.string.tracklist_clear_map);
|
||||||
|
menu.add(0, Constants.MENU_DELETE, 0,
|
||||||
|
R.string.tracklist_delete_track);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||||
|
if (!super.onMenuItemSelected(featureId, item)) {
|
||||||
|
MyTracks.getInstance().onActivityResult(
|
||||||
|
Constants.getActionFromMenuId(item.getItemId()), RESULT_OK,
|
||||||
|
new Intent());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
super.onCreateOptionsMenu(menu);
|
||||||
|
myLocation = menu.add(0, Constants.MENU_MY_LOCATION, 0,
|
||||||
|
R.string.mylocation);
|
||||||
|
myLocation.setIcon(android.R.drawable.ic_menu_mylocation);
|
||||||
|
toggleLayers = menu.add(0, Constants.MENU_TOGGLE_LAYERS, 0,
|
||||||
|
R.string.switch_to_sat);
|
||||||
|
toggleLayers.setIcon(android.R.drawable.ic_menu_mapmode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
|
toggleLayers.setTitle(mapView.isSatellite() ?
|
||||||
|
R.string.switch_to_map : R.string.switch_to_sat);
|
||||||
|
return super.onPrepareOptionsMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case Constants.MENU_MY_LOCATION: {
|
||||||
|
dataHub.forceUpdateLocation();
|
||||||
|
keepMyLocationVisible = true;
|
||||||
|
if (mapView.getZoomLevel() < 18) {
|
||||||
|
mapView.getController().setZoom(18);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case Constants.MENU_TOGGLE_LAYERS: {
|
||||||
|
mapView.setSatellite(!mapView.isSatellite());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (v == messagePane) {
|
||||||
|
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
|
||||||
|
} else if (v == optionsBtn) {
|
||||||
|
optionsBtn.performLongClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We want the pointer to become visible again in case of the next location
|
||||||
|
* update:
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View view, MotionEvent event) {
|
||||||
|
if (keepMyLocationVisible && event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||||
|
if (!locationIsVisible(currentLocation)) {
|
||||||
|
keepMyLocationVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderStateChange(ProviderState state) {
|
||||||
|
final int messageId;
|
||||||
|
final boolean bindClick;
|
||||||
|
switch (state) {
|
||||||
|
case DISABLED:
|
||||||
|
messageId = R.string.status_enable_gps;
|
||||||
|
bindClick = true;
|
||||||
|
break;
|
||||||
|
case NO_FIX:
|
||||||
|
case BAD_FIX:
|
||||||
|
messageId = R.string.wait_for_fix;
|
||||||
|
bindClick = false;
|
||||||
|
break;
|
||||||
|
case GOOD_FIX:
|
||||||
|
// Nothing to show.
|
||||||
|
messageId = -1;
|
||||||
|
bindClick = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unexpected state: " + state);
|
||||||
|
}
|
||||||
|
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (messageId != -1) {
|
||||||
|
messageText.setText(messageId);
|
||||||
|
messagePane.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
if (bindClick) {
|
||||||
|
messagePane.setOnClickListener(MapActivity.this);
|
||||||
|
} else {
|
||||||
|
messagePane.setOnClickListener(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
messagePane.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
screen.requestLayout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCurrentLocationChanged(Location location) {
|
||||||
|
if (!location.getProvider().equals(LocationManager.GPS_PROVIDER)) {
|
||||||
|
Log.d(TAG,
|
||||||
|
"MapActivity: Network location update received (provider '" + location.getProvider() + "'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
currentLocation = location;
|
||||||
|
showCurrentLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCurrentHeadingChanged(double heading) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (mapOverlay.setHeading((float) heading)) {
|
||||||
|
mapView.postInvalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearWaypoints() {
|
||||||
|
mapOverlay.clearWaypoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNewWaypoint(Waypoint waypoint) {
|
||||||
|
if (LocationUtils.isValidLocation(waypoint.getLocation())) {
|
||||||
|
// TODO: Optimize locking inside addWaypoint
|
||||||
|
mapOverlay.addWaypoint(waypoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNewWaypointsDone() {
|
||||||
|
mapView.postInvalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearTrackPoints() {
|
||||||
|
mapOverlay.clearPoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNewTrackPoint(Location loc) {
|
||||||
|
mapOverlay.addLocation(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSegmentSplit() {
|
||||||
|
mapOverlay.addSegmentSplit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSampledOutTrackPoint(Location loc) {
|
||||||
|
// We don't care.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNewTrackPointsDone() {
|
||||||
|
mapView.postInvalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onUnitsChanged(boolean metric) {
|
||||||
|
// We don't care.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onReportSpeedChanged(boolean reportSpeed) {
|
||||||
|
// We don't care.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
-11
@@ -16,7 +16,7 @@
|
|||||||
package com.google.android.apps.mytracks;
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||||
import com.google.android.maps.GeoPoint;
|
import com.google.android.maps.GeoPoint;
|
||||||
import com.google.android.maps.MapView;
|
import com.google.android.maps.MapView;
|
||||||
import com.google.android.maps.Overlay;
|
import com.google.android.maps.Overlay;
|
||||||
@@ -45,7 +45,7 @@ import java.util.concurrent.BlockingQueue;
|
|||||||
*
|
*
|
||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
public class MyTracksOverlay extends Overlay {
|
public class MapOverlay extends Overlay {
|
||||||
|
|
||||||
private final Drawable[] arrows;
|
private final Drawable[] arrows;
|
||||||
private final int arrowWidth, arrowHeight;
|
private final int arrowWidth, arrowHeight;
|
||||||
@@ -80,19 +80,30 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
public final boolean valid;
|
public final boolean valid;
|
||||||
public final GeoPoint geoPoint;
|
public final GeoPoint geoPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for an invalid cached location.
|
||||||
|
*/
|
||||||
|
public CachedLocation() {
|
||||||
|
this.valid = false;
|
||||||
|
this.geoPoint = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for a potentially valid cached location.
|
||||||
|
*/
|
||||||
public CachedLocation(Location location) {
|
public CachedLocation(Location location) {
|
||||||
this.valid = MyTracksUtils.isValidLocation(location);
|
this.valid = LocationUtils.isValidLocation(location);
|
||||||
this.geoPoint = valid ? MyTracksUtils.getGeoPoint(location) : null;
|
this.geoPoint = valid ? LocationUtils.getGeoPoint(location) : null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public MyTracksOverlay(Context context) {
|
public MapOverlay(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
this.waypoints = new ArrayList<Waypoint>();
|
this.waypoints = new ArrayList<Waypoint>();
|
||||||
this.points = new ArrayList<CachedLocation>(1024);
|
this.points = new ArrayList<CachedLocation>(1024);
|
||||||
this.pendingPoints = new ArrayBlockingQueue<CachedLocation>(
|
this.pendingPoints = new ArrayBlockingQueue<CachedLocation>(
|
||||||
MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS, true);
|
Constants.MAX_DISPLAYED_TRACK_POINTS, true);
|
||||||
|
|
||||||
// TODO: Can we use a FrameAnimation or similar here rather
|
// TODO: Can we use a FrameAnimation or similar here rather
|
||||||
// than individual resources for each arrow direction?
|
// than individual resources for each arrow direction?
|
||||||
@@ -164,6 +175,13 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
pendingPoints.offer(new CachedLocation(l));
|
pendingPoints.offer(new CachedLocation(l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a segment split to the map overlay.
|
||||||
|
*/
|
||||||
|
public void addSegmentSplit() {
|
||||||
|
pendingPoints.offer(new CachedLocation());
|
||||||
|
}
|
||||||
|
|
||||||
public void addWaypoint(Waypoint wpt) {
|
public void addWaypoint(Waypoint wpt) {
|
||||||
// Note: We don't cache waypoints, because it's not worth the effort.
|
// Note: We don't cache waypoints, because it's not worth the effort.
|
||||||
if (wpt != null && wpt.getLocation() != null) {
|
if (wpt != null && wpt.getLocation() != null) {
|
||||||
@@ -260,7 +278,7 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
synchronized (waypoints) {;
|
synchronized (waypoints) {;
|
||||||
for (Waypoint wpt : waypoints) {
|
for (Waypoint wpt : waypoints) {
|
||||||
Location loc = wpt.getLocation();
|
Location loc = wpt.getLocation();
|
||||||
drawElement(canvas, projection, MyTracksUtils.getGeoPoint(loc),
|
drawElement(canvas, projection, LocationUtils.getGeoPoint(loc),
|
||||||
wpt.getType() == Waypoint.TYPE_STATISTICS ? statsMarker
|
wpt.getType() == Waypoint.TYPE_STATISTICS ? statsMarker
|
||||||
: waypointMarker, -(markerWidth / 2) + 3, -markerHeight);
|
: waypointMarker, -(markerWidth / 2) + 3, -markerHeight);
|
||||||
}
|
}
|
||||||
@@ -274,7 +292,7 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Point pt = drawElement(canvas, projection,
|
Point pt = drawElement(canvas, projection,
|
||||||
MyTracksUtils.getGeoPoint(myLocation), arrows[lastHeading],
|
LocationUtils.getGeoPoint(myLocation), arrows[lastHeading],
|
||||||
-(arrowWidth / 2) + 3, -(arrowHeight / 2));
|
-(arrowWidth / 2) + 3, -(arrowHeight / 2));
|
||||||
// Draw the error circle.
|
// Draw the error circle.
|
||||||
float radius = projection.metersToEquatorPixels(myLocation.getAccuracy());
|
float radius = projection.metersToEquatorPixels(myLocation.getAccuracy());
|
||||||
@@ -423,7 +441,7 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Location tapLocation = MyTracksUtils.getLocation(p);
|
final Location tapLocation = LocationUtils.getLocation(p);
|
||||||
double dmin = Double.MAX_VALUE;
|
double dmin = Double.MAX_VALUE;
|
||||||
Waypoint waypoint = null;
|
Waypoint waypoint = null;
|
||||||
synchronized (waypoints) {
|
synchronized (waypoints) {
|
||||||
@@ -442,8 +460,8 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
|
|
||||||
if (waypoint != null &&
|
if (waypoint != null &&
|
||||||
dmin < 15000000 / Math.pow(2, mapView.getZoomLevel())) {
|
dmin < 15000000 / Math.pow(2, mapView.getZoomLevel())) {
|
||||||
Intent intent = new Intent(context, MyTracksWaypointDetails.class);
|
Intent intent = new Intent(context, WaypointDetails.class);
|
||||||
intent.putExtra("waypointid", waypoint.getId());
|
intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, waypoint.getId());
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -64,21 +64,21 @@ class MenuManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.menu_list_tracks: {
|
case R.id.menu_list_tracks: {
|
||||||
activity.startActivityForResult(new Intent(activity, MyTracksList.class),
|
activity.startActivityForResult(new Intent(activity, TrackList.class),
|
||||||
MyTracksConstants.SHOW_TRACK);
|
Constants.SHOW_TRACK);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.menu_list_markers: {
|
case R.id.menu_list_markers: {
|
||||||
Intent startIntent = new Intent(activity, MyTracksWaypointsList.class);
|
Intent startIntent = new Intent(activity, WaypointsList.class);
|
||||||
startIntent.putExtra("trackid", activity.getSelectedTrackId());
|
startIntent.putExtra("trackid", activity.getSelectedTrackId());
|
||||||
activity.startActivityForResult(startIntent, MyTracksConstants.SHOW_WAYPOINT);
|
activity.startActivityForResult(startIntent, Constants.SHOW_WAYPOINT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.menu_sensor_state: {
|
case R.id.menu_sensor_state: {
|
||||||
return startActivity(SensorStateActivity.class);
|
return startActivity(SensorStateActivity.class);
|
||||||
}
|
}
|
||||||
case R.id.menu_settings: {
|
case R.id.menu_settings: {
|
||||||
return startActivity(MyTracksSettings.class);
|
return startActivity(SettingsActivity.class);
|
||||||
}
|
}
|
||||||
case R.id.menu_aggregated_stats: {
|
case R.id.menu_aggregated_stats: {
|
||||||
return startActivity(AggregatedStatsActivity.class);
|
return startActivity(AggregatedStatsActivity.class);
|
||||||
@@ -86,8 +86,8 @@ class MenuManager {
|
|||||||
case R.id.menu_help: {
|
case R.id.menu_help: {
|
||||||
return startActivity(WelcomeActivity.class);
|
return startActivity(WelcomeActivity.class);
|
||||||
}
|
}
|
||||||
case MyTracksConstants.MENU_CLEAR_MAP: {
|
case Constants.MENU_CLEAR_MAP: {
|
||||||
activity.setSelectedTrackId(-1);
|
activity.clearSelectedTrack();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 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.
|
||||||
|
*/
|
||||||
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
|
import com.google.android.accounts.Account;
|
||||||
|
import com.google.android.apps.mytracks.io.AuthManager;
|
||||||
|
import com.google.android.apps.mytracks.io.AuthManagerFactory;
|
||||||
|
import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
|
||||||
|
import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants;
|
||||||
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.ContextMenu;
|
||||||
|
import android.view.ContextMenu.ContextMenuInfo;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnCreateContextMenuListener;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activity which displays the list of current My Maps tracks for the user.
|
||||||
|
* Returns RESULT_OK if the user picked a map, and returns "mapid" as an extra.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public class MyMapsList extends Activity implements MapsFacade.MapsListCallback {
|
||||||
|
private static final int MENU_OPEN = 0;
|
||||||
|
private static final int MENU_SHARE = 2;
|
||||||
|
private static final int GET_LOGIN = 1;
|
||||||
|
|
||||||
|
private MapsFacade mapsClient;
|
||||||
|
private AuthManager auth;
|
||||||
|
private MyMapsListAdapter listAdapter;
|
||||||
|
|
||||||
|
private int contextPosition;
|
||||||
|
|
||||||
|
private final OnCreateContextMenuListener contextMenuListener =
|
||||||
|
new OnCreateContextMenuListener() {
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||||
|
ContextMenuInfo menuInfo) {
|
||||||
|
AdapterView.AdapterContextMenuInfo info =
|
||||||
|
(AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||||
|
contextPosition = info.position;
|
||||||
|
menu.add(0, MENU_OPEN, 0, R.string.open_map);
|
||||||
|
menu.add(0, MENU_SHARE, 0, R.string.share_map);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final OnItemClickListener clickListener =
|
||||||
|
new OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View v, int position,
|
||||||
|
long id) {
|
||||||
|
Intent result = new Intent();
|
||||||
|
result.putExtra("mapid", (String) listAdapter.getItem(position));
|
||||||
|
setResult(RESULT_OK, result);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Called when the activity is first created. */
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle icicle) {
|
||||||
|
super.onCreate(icicle);
|
||||||
|
|
||||||
|
auth = AuthManagerFactory.getAuthManager(this, GET_LOGIN, null, true,
|
||||||
|
MyMapsConstants.SERVICE_NAME);
|
||||||
|
|
||||||
|
setContentView(R.layout.list);
|
||||||
|
|
||||||
|
listAdapter = new MyMapsListAdapter(this);
|
||||||
|
|
||||||
|
ListView list = (ListView) findViewById(R.id.maplist);
|
||||||
|
list.setOnItemClickListener(clickListener);
|
||||||
|
list.setOnCreateContextMenuListener(contextMenuListener);
|
||||||
|
list.setAdapter(listAdapter);
|
||||||
|
|
||||||
|
startLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startLogin() {
|
||||||
|
// Starts in the UI thread.
|
||||||
|
// TODO fix this for non-froyo devices.
|
||||||
|
if (AuthManagerFactory.useModernAuthManager()) {
|
||||||
|
MyTracks.getInstance().getAccountChooser().chooseAccount(
|
||||||
|
MyMapsList.this,
|
||||||
|
new AccountChooser.AccountHandler() {
|
||||||
|
@Override
|
||||||
|
public void handleAccountSelected(Account account) {
|
||||||
|
// Account selection happens in the UI thread.
|
||||||
|
if (account != null) {
|
||||||
|
// The user did not quit and there was a valid google
|
||||||
|
// account.
|
||||||
|
doLogin(account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
doLogin(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doLogin(final Account account) {
|
||||||
|
// Starts in the UI thread.
|
||||||
|
auth.doLogin(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
// Runs in UI thread.
|
||||||
|
mapsClient = new MapsFacade(MyMapsList.this, auth);
|
||||||
|
|
||||||
|
startLookup();
|
||||||
|
}
|
||||||
|
}, account);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startLookup() {
|
||||||
|
// Starts in the UI thread.
|
||||||
|
new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Communication with Maps happens in its own thread.
|
||||||
|
// This will call onReceivedMapListing below.
|
||||||
|
final boolean success = mapsClient.getMapsList(MyMapsList.this);
|
||||||
|
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Updating the UI when done happens in the UI thread.
|
||||||
|
onLookupDone(success);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceivedMapListing(final String mapId, final String title,
|
||||||
|
final String description, final boolean isPublic) {
|
||||||
|
// Starts in the communication thread.
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Updating the list with new contents happens in the UI thread.
|
||||||
|
listAdapter.addMapListing(mapId, title, description, isPublic);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onLookupDone(boolean success) {
|
||||||
|
// Starts in the UI thread.
|
||||||
|
findViewById(R.id.loading).setVisibility(View.GONE);
|
||||||
|
if (!success) {
|
||||||
|
findViewById(R.id.failed).setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
TextView emptyView = (TextView) findViewById(R.id.mapslist_empty);
|
||||||
|
ListView list = (ListView) findViewById(R.id.maplist);
|
||||||
|
list.setEmptyView(emptyView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode,
|
||||||
|
Intent data) {
|
||||||
|
if (requestCode == GET_LOGIN) {
|
||||||
|
auth.authResult(resultCode, data);
|
||||||
|
}
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case MENU_OPEN:
|
||||||
|
clickListener.onItemClick(null, null, contextPosition, 0);
|
||||||
|
return true;
|
||||||
|
case MENU_SHARE:
|
||||||
|
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||||
|
shareIntent.setType("text/plain");
|
||||||
|
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
|
||||||
|
getText(R.string.share_map_subject));
|
||||||
|
String[] listItem = (String[]) listAdapter.getMapListingArray(contextPosition);
|
||||||
|
shareIntent.putExtra(Intent.EXTRA_TEXT, String.format(
|
||||||
|
getText(R.string.share_map_body_format).toString(),
|
||||||
|
listItem[1],
|
||||||
|
MapsFacade.buildMapUrl(listItem[0])));
|
||||||
|
startActivity(Intent.createChooser(shareIntent,
|
||||||
|
getText(R.string.share_map).toString()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.database.DataSetObserver;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ListAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
public class MyMapsListAdapter implements ListAdapter {
|
||||||
|
private Vector<String[]> mapsList;
|
||||||
|
private Vector<Boolean> publicList;
|
||||||
|
private Set<DataSetObserver> observerSet;
|
||||||
|
private final Activity activity;
|
||||||
|
|
||||||
|
public MyMapsListAdapter(Activity activity) {
|
||||||
|
this.activity = activity;
|
||||||
|
|
||||||
|
mapsList = new Vector<String[]>();
|
||||||
|
publicList = new Vector<Boolean>();
|
||||||
|
observerSet = new HashSet<DataSetObserver>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMapListing(String mapId, String title,
|
||||||
|
String description, boolean isPublic) {
|
||||||
|
synchronized (mapsList) {
|
||||||
|
// Search through the maps list to see if it has the mapid and
|
||||||
|
// remove it if so, so that we can replace it with updated info
|
||||||
|
for (int i = 0; i < mapsList.size(); ++i) {
|
||||||
|
if (mapId.equals(mapsList.get(i)[0])) {
|
||||||
|
mapsList.remove(i);
|
||||||
|
publicList.remove(i);
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mapsList.add(new String[] { mapId, title, description });
|
||||||
|
publicList.add(isPublic);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<DataSetObserver> iter = observerSet.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
iter.next().onChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getMapListingArray(int position) {
|
||||||
|
return mapsList.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areAllItemsEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(int position) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return mapsList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getItem(int position) {
|
||||||
|
return mapsList.get(position)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView =
|
||||||
|
activity.getLayoutInflater().inflate(R.layout.listitem, parent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] map = mapsList.get(position);
|
||||||
|
((TextView) convertView.findViewById(R.id.maplistitem)).setText(map[1]);
|
||||||
|
((TextView) convertView.findViewById(R.id.maplistdesc)).setText(map[2]);
|
||||||
|
TextView publicUnlisted =
|
||||||
|
(TextView) convertView.findViewById(R.id.maplistpublic);
|
||||||
|
if (publicList.get(position)) {
|
||||||
|
publicUnlisted.setTextColor(Color.RED);
|
||||||
|
publicUnlisted.setText(R.string.public_map);
|
||||||
|
} else {
|
||||||
|
publicUnlisted.setTextColor(Color.GREEN);
|
||||||
|
publicUnlisted.setText(R.string.unlisted_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewTypeCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasStableIds() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return mapsList.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerDataSetObserver(DataSetObserver observer) {
|
||||||
|
observerSet.add(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterDataSetObserver(DataSetObserver observer) {
|
||||||
|
observerSet.remove(observer);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks;
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
import static com.google.android.apps.mytracks.MyTracksConstants.TAG;
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
import com.google.android.apps.mytracks.content.Sensor;
|
import com.google.android.apps.mytracks.content.Sensor;
|
||||||
import com.google.android.apps.mytracks.services.ITrackRecordingService;
|
import com.google.android.apps.mytracks.services.ITrackRecordingService;
|
||||||
import com.google.android.apps.mytracks.services.sensors.SensorUtils;
|
import com.google.android.apps.mytracks.services.sensors.SensorUtils;
|
||||||
@@ -103,7 +103,7 @@ public class SensorStateActivity extends Activity {
|
|||||||
ITrackRecordingService service =
|
ITrackRecordingService service =
|
||||||
mt == null ? null : mt.getTrackRecordingService();
|
mt == null ? null : mt.getTrackRecordingService();
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
Log.d(MyTracksConstants.TAG, "Could not get track recording service.");
|
Log.d(Constants.TAG, "Could not get track recording service.");
|
||||||
updateSensorState(Sensor.SensorState.NONE);
|
updateSensorState(Sensor.SensorState.NONE);
|
||||||
updateSensorData(null);
|
updateSensorData(null);
|
||||||
return;
|
return;
|
||||||
@@ -116,9 +116,9 @@ public class SensorStateActivity extends Activity {
|
|||||||
updateSensorData(sds);
|
updateSensorData(sds);
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Could not read sensor data.", e);
|
Log.e(Constants.TAG, "Could not read sensor data.", e);
|
||||||
} catch (InvalidProtocolBufferException e) {
|
} catch (InvalidProtocolBufferException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Could not read sensor data.", e);
|
Log.e(Constants.TAG, "Could not read sensor data.", e);
|
||||||
}
|
}
|
||||||
updateSensorData(sds);
|
updateSensorData(sds);
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ public class SensorStateActivity extends Activity {
|
|||||||
int i = service.getSensorState();
|
int i = service.getSensorState();
|
||||||
updateSensorState(Sensor.SensorState.valueOf(i));
|
updateSensorState(Sensor.SensorState.valueOf(i));
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Could not read sensor state.", e);
|
Log.e(Constants.TAG, "Could not read sensor state.", e);
|
||||||
updateSensorState(Sensor.SensorState.NONE);
|
updateSensorState(Sensor.SensorState.NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+153
-46
@@ -15,27 +15,38 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks;
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.backup.BackupActivityHelper;
|
import com.google.android.apps.mytracks.io.backup.BackupActivityHelper;
|
||||||
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener;
|
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener;
|
||||||
import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
|
import com.google.android.apps.mytracks.services.sensors.ant.AntUtils;
|
||||||
|
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
|
||||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
import com.google.android.apps.mytracks.util.ApiFeatures;
|
||||||
import com.google.android.apps.mytracks.util.BluetoothDeviceUtils;
|
import com.google.android.apps.mytracks.util.BluetoothDeviceUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.DialogInterface.OnClickListener;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.CheckBoxPreference;
|
import android.preference.CheckBoxPreference;
|
||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceActivity;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.preference.Preference.OnPreferenceChangeListener;
|
import android.preference.Preference.OnPreferenceChangeListener;
|
||||||
import android.preference.Preference.OnPreferenceClickListener;
|
import android.preference.Preference.OnPreferenceClickListener;
|
||||||
|
import android.preference.PreferenceActivity;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.preference.PreferenceScreen;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An activity that let's the user see and edit the settings.
|
* An activity that let's the user see and edit the settings.
|
||||||
@@ -43,28 +54,14 @@ import android.provider.Settings;
|
|||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
* @author Rodrigo Damazio
|
* @author Rodrigo Damazio
|
||||||
*/
|
*/
|
||||||
public class MyTracksSettings extends PreferenceActivity {
|
public class SettingsActivity extends PreferenceActivity {
|
||||||
|
|
||||||
public static final String SETTINGS_NAME = "MyTracksSettings";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Default values - keep in sync with those in preferences.xml.
|
|
||||||
*/
|
|
||||||
public static final int DEFAULT_AUTO_RESUME_TRACK_TIMEOUT = 10; // In min.
|
|
||||||
public static final int DEFAULT_ANNOUNCEMENT_FREQUENCY = -1;
|
|
||||||
public static final int DEFAULT_MAX_RECORDING_DISTANCE = 200;
|
|
||||||
public static final int DEFAULT_MIN_RECORDING_DISTANCE = 5;
|
|
||||||
public static final int DEFAULT_MIN_RECORDING_INTERVAL = 0;
|
|
||||||
public static final int DEFAULT_MIN_REQUIRED_ACCURACY = 200;
|
|
||||||
public static final int DEFAULT_SPLIT_FREQUENCY = 0;
|
|
||||||
|
|
||||||
private BackupPreferencesListener backupListener;
|
private BackupPreferencesListener backupListener;
|
||||||
|
|
||||||
private SharedPreferences preferences;
|
private SharedPreferences preferences;
|
||||||
|
|
||||||
/** Called when the activity is first created. */
|
/** Called when the activity is first created. */
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
protected void onCreate(Bundle icicle) {
|
||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
|
|
||||||
// The volume we want to control is the Text-To-Speech volume
|
// The volume we want to control is the Text-To-Speech volume
|
||||||
@@ -75,7 +72,7 @@ public class MyTracksSettings extends PreferenceActivity {
|
|||||||
|
|
||||||
// Tell it where to read/write preferences
|
// Tell it where to read/write preferences
|
||||||
PreferenceManager preferenceManager = getPreferenceManager();
|
PreferenceManager preferenceManager = getPreferenceManager();
|
||||||
preferenceManager.setSharedPreferencesName(SETTINGS_NAME);
|
preferenceManager.setSharedPreferencesName(Constants.SETTINGS_NAME);
|
||||||
preferenceManager.setSharedPreferencesMode(0);
|
preferenceManager.setSharedPreferencesMode(0);
|
||||||
|
|
||||||
// Set up automatic preferences backup
|
// Set up automatic preferences backup
|
||||||
@@ -103,6 +100,31 @@ public class MyTracksSettings extends PreferenceActivity {
|
|||||||
});
|
});
|
||||||
updatePreferenceUnits(metricUnitsPreference.isChecked());
|
updatePreferenceUnits(metricUnitsPreference.isChecked());
|
||||||
|
|
||||||
|
customizeSensorOptionsPreferences();
|
||||||
|
|
||||||
|
// Disable TTS announcement preference if not available
|
||||||
|
if (!apiFeatures.hasTextToSpeech()) {
|
||||||
|
IntegerListPreference announcementFrequency =
|
||||||
|
(IntegerListPreference) findPreference(
|
||||||
|
getString(R.string.announcement_frequency_key));
|
||||||
|
announcementFrequency.setEnabled(false);
|
||||||
|
announcementFrequency.setValue("-1");
|
||||||
|
announcementFrequency.setSummary(
|
||||||
|
R.string.settings_not_available_summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hook up action for resetting all settings
|
||||||
|
Preference resetPreference = findPreference(getString(R.string.reset_key));
|
||||||
|
resetPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference arg0) {
|
||||||
|
onResetPreferencesClick();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void customizeSensorOptionsPreferences() {
|
||||||
ListPreference sensorTypePreference =
|
ListPreference sensorTypePreference =
|
||||||
(ListPreference) findPreference(getString(R.string.sensor_type_key));
|
(ListPreference) findPreference(getString(R.string.sensor_type_key));
|
||||||
sensorTypePreference.setOnPreferenceChangeListener(
|
sensorTypePreference.setOnPreferenceChangeListener(
|
||||||
@@ -116,15 +138,36 @@ public class MyTracksSettings extends PreferenceActivity {
|
|||||||
});
|
});
|
||||||
updateSensorSettings(sensorTypePreference.getValue());
|
updateSensorSettings(sensorTypePreference.getValue());
|
||||||
|
|
||||||
// Disable TTS announcement preference if not available
|
if (!AntUtils.hasAntSupport(this)) {
|
||||||
if (!apiFeatures.hasTextToSpeech()) {
|
// The sensor options screen has a few ANT-specific options which we
|
||||||
IntegerListPreference announcementFrequency =
|
// need to remove. First, we need to remove the ANT sensor types.
|
||||||
(IntegerListPreference) findPreference(
|
// Second, we need to remove the ANT unpairing options.
|
||||||
getString(R.string.announcement_frequency_key));
|
|
||||||
announcementFrequency.setEnabled(false);
|
Set<Integer> toRemove = new HashSet<Integer>();
|
||||||
announcementFrequency.setValue("-1");
|
|
||||||
announcementFrequency.setSummary(
|
String[] antValues = getResources().getStringArray(R.array.ant_sensor_type_values);
|
||||||
R.string.settings_not_available_summary);
|
for (String antValue : antValues) {
|
||||||
|
toRemove.add(sensorTypePreference.findIndexOfValue(antValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
CharSequence[] entries = sensorTypePreference.getEntries();
|
||||||
|
CharSequence[] entryValues = sensorTypePreference.getEntryValues();
|
||||||
|
|
||||||
|
CharSequence[] filteredEntries = new CharSequence[entries.length - toRemove.size()];
|
||||||
|
CharSequence[] filteredEntryValues = new CharSequence[filteredEntries.length];
|
||||||
|
for (int i = 0, last = 0; i < entries.length; i++) {
|
||||||
|
if (!toRemove.contains(i)) {
|
||||||
|
filteredEntries[last] = entries[i];
|
||||||
|
filteredEntryValues[last++] = entryValues[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sensorTypePreference.setEntries(filteredEntries);
|
||||||
|
sensorTypePreference.setEntryValues(filteredEntryValues);
|
||||||
|
|
||||||
|
PreferenceScreen sensorOptionsScreen =
|
||||||
|
(PreferenceScreen) findPreference(getString(R.string.sensor_options_key));
|
||||||
|
sensorOptionsScreen.removePreference(findPreference(getString(R.string.ant_options_key)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,19 +180,24 @@ public class MyTracksSettings extends PreferenceActivity {
|
|||||||
findPreference(getString(R.string.backup_to_sd_key));
|
findPreference(getString(R.string.backup_to_sd_key));
|
||||||
Preference restoreNowPreference =
|
Preference restoreNowPreference =
|
||||||
findPreference(getString(R.string.restore_from_sd_key));
|
findPreference(getString(R.string.restore_from_sd_key));
|
||||||
|
Preference resetPreference = findPreference(getString(R.string.reset_key));
|
||||||
|
|
||||||
// If recording, disable backup/restore
|
// If recording, disable backup/restore/reset
|
||||||
// (we don't want to get to inconsistent states)
|
// (we don't want to get to inconsistent states)
|
||||||
boolean recording =
|
boolean recording =
|
||||||
preferences.getLong(getString(R.string.recording_track_key), -1) != -1;
|
preferences.getLong(getString(R.string.recording_track_key), -1) != -1;
|
||||||
backupNowPreference.setEnabled(!recording);
|
backupNowPreference.setEnabled(!recording);
|
||||||
restoreNowPreference.setEnabled(!recording);
|
restoreNowPreference.setEnabled(!recording);
|
||||||
|
resetPreference.setEnabled(!recording);
|
||||||
backupNowPreference.setSummary(
|
backupNowPreference.setSummary(
|
||||||
recording ? R.string.settings_no_backup_while_recording
|
recording ? R.string.settings_not_while_recording
|
||||||
: R.string.settings_backup_to_sd_summary);
|
: R.string.settings_backup_to_sd_summary);
|
||||||
restoreNowPreference.setSummary(
|
restoreNowPreference.setSummary(
|
||||||
recording ? R.string.settings_no_backup_while_recording
|
recording ? R.string.settings_not_while_recording
|
||||||
: R.string.settings_restore_from_sd_summary);
|
: R.string.settings_restore_from_sd_summary);
|
||||||
|
resetPreference.setSummary(
|
||||||
|
recording ? R.string.settings_not_while_recording
|
||||||
|
: R.string.settings_reset_summary);
|
||||||
|
|
||||||
// Add actions to the backup preferences
|
// Add actions to the backup preferences
|
||||||
backupNowPreference.setOnPreferenceClickListener(
|
backupNowPreference.setOnPreferenceClickListener(
|
||||||
@@ -157,7 +205,7 @@ public class MyTracksSettings extends PreferenceActivity {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
BackupActivityHelper backupHelper =
|
BackupActivityHelper backupHelper =
|
||||||
new BackupActivityHelper(MyTracksSettings.this);
|
new BackupActivityHelper(SettingsActivity.this);
|
||||||
backupHelper.writeBackup();
|
backupHelper.writeBackup();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -167,7 +215,7 @@ public class MyTracksSettings extends PreferenceActivity {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
BackupActivityHelper backupHelper =
|
BackupActivityHelper backupHelper =
|
||||||
new BackupActivityHelper(MyTracksSettings.this);
|
new BackupActivityHelper(SettingsActivity.this);
|
||||||
backupHelper.restoreBackup();
|
backupHelper.restoreBackup();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -192,10 +240,14 @@ public class MyTracksSettings extends PreferenceActivity {
|
|||||||
|
|
||||||
// Update the ANT+ sensors.
|
// Update the ANT+ sensors.
|
||||||
// TODO: Only enable on phones that have ANT+.
|
// TODO: Only enable on phones that have ANT+.
|
||||||
findPreference(getString(R.string.ant_heart_rate_sensor_id_key))
|
Preference antHrm = findPreference(getString(R.string.ant_heart_rate_sensor_id_key));
|
||||||
.setEnabled(getString(R.string.ant_sensor_type).equals(sensorType));
|
Preference antSrm = findPreference(getString(R.string.ant_srm_bridge_sensor_id_key));
|
||||||
findPreference(getString(R.string.ant_srm_bridge_sensor_id_key))
|
if (antHrm != null && antSrm != null) {
|
||||||
.setEnabled(getString(R.string.srm_ant_bridge_sensor_type).equals(sensorType));
|
antHrm
|
||||||
|
.setEnabled(getString(R.string.ant_sensor_type).equals(sensorType));
|
||||||
|
antSrm
|
||||||
|
.setEnabled(getString(R.string.srm_ant_bridge_sensor_type).equals(sensorType));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -214,9 +266,6 @@ public class MyTracksSettings extends PreferenceActivity {
|
|||||||
final ListPreference minRequiredAccuracy =
|
final ListPreference minRequiredAccuracy =
|
||||||
(ListPreference) findPreference(
|
(ListPreference) findPreference(
|
||||||
getString(R.string.min_required_accuracy_key));
|
getString(R.string.min_required_accuracy_key));
|
||||||
final ListPreference splitFrequency =
|
|
||||||
(ListPreference) findPreference(
|
|
||||||
getString(R.string.split_frequency_key));
|
|
||||||
|
|
||||||
minRecordingDistance.setEntries(isMetric
|
minRecordingDistance.setEntries(isMetric
|
||||||
? R.array.min_recording_distance_options
|
? R.array.min_recording_distance_options
|
||||||
@@ -227,11 +276,20 @@ public class MyTracksSettings extends PreferenceActivity {
|
|||||||
minRequiredAccuracy.setEntries(isMetric
|
minRequiredAccuracy.setEntries(isMetric
|
||||||
? R.array.min_required_accuracy_options
|
? R.array.min_required_accuracy_options
|
||||||
: R.array.min_required_accuracy_options_ft);
|
: R.array.min_required_accuracy_options_ft);
|
||||||
splitFrequency.setEntries(isMetric
|
setTaskOptions(isMetric, R.string.announcement_frequency_key);
|
||||||
? R.array.split_frequency_options
|
setTaskOptions(isMetric, R.string.split_frequency_key);
|
||||||
: R.array.split_frequency_options_ft);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the user visible options for a periodic task.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures preference actions related to bluetooth.
|
* Configures preference actions related to bluetooth.
|
||||||
@@ -271,4 +329,53 @@ public class MyTracksSettings extends PreferenceActivity {
|
|||||||
devicesPreference.setEntryValues(entryValuesArray);
|
devicesPreference.setEntryValues(entryValuesArray);
|
||||||
devicesPreference.setEntries(entriesArray);
|
devicesPreference.setEntries(entriesArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Callback for when user asks to reset all settings. */
|
||||||
|
private void onResetPreferencesClick() {
|
||||||
|
AlertDialog dialog = new AlertDialog.Builder(this)
|
||||||
|
.setCancelable(true)
|
||||||
|
.setTitle(R.string.settings_reset)
|
||||||
|
.setMessage(R.string.settings_reset_dialog_message)
|
||||||
|
.setPositiveButton(android.R.string.ok,
|
||||||
|
new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int button) {
|
||||||
|
onResetPreferencesConfirmed();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.create();
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Callback for when user confirms resetting all settings. */
|
||||||
|
private void onResetPreferencesConfirmed() {
|
||||||
|
// Change preferences in a separate thread.
|
||||||
|
new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Log.i(TAG, "Resetting all settings");
|
||||||
|
|
||||||
|
// Actually wipe preferences (and save synchronously).
|
||||||
|
preferences.edit().clear().commit();
|
||||||
|
|
||||||
|
// Give UI feedback in the UI thread.
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Give feedback to the user.
|
||||||
|
Toast.makeText(
|
||||||
|
SettingsActivity.this,
|
||||||
|
R.string.settings_reset_done,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
|
// Restart the settings activity so all changes are loaded.
|
||||||
|
Intent intent = getIntent();
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -15,26 +15,18 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks;
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtilsImpl;
|
|
||||||
|
import com.google.android.apps.mytracks.TrackDataHub.ListenerDataType;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.content.WaypointsColumns;
|
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
|
||||||
import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
|
|
||||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
import com.google.android.apps.mytracks.util.ApiFeatures;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
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.Location;
|
||||||
import android.location.LocationListener;
|
|
||||||
import android.location.LocationManager;
|
|
||||||
import android.location.LocationProvider;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -42,66 +34,41 @@ import android.view.MenuItem;
|
|||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.widget.ScrollView;
|
import android.widget.ScrollView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An activity that displays track statistics to the user.
|
* An activity that displays track statistics to the user.
|
||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
|
* @author Rodrigo Damazio
|
||||||
*/
|
*/
|
||||||
public class StatsActivity extends Activity
|
public class StatsActivity extends Activity implements TrackDataListener {
|
||||||
implements OnSharedPreferenceChangeListener {
|
|
||||||
|
|
||||||
private StatsUtilities utils;
|
private StatsUtilities utils;
|
||||||
private UIUpdateThread thread;
|
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.
|
* The start time of the selected track.
|
||||||
*/
|
*/
|
||||||
private long startTime = -1;
|
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
|
* If true, the statistics for the current segment are shown, otherwise
|
||||||
* for the full track.
|
* for the full track.
|
||||||
*/
|
*/
|
||||||
private boolean showCurrentSegment = false;
|
private boolean showCurrentSegment = false;
|
||||||
|
|
||||||
private MyTracksProviderUtils providerUtils;
|
private TrackDataHub dataHub;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A runnable for posting to the UI thread. Will update the total time field.
|
* A runnable for posting to the UI thread. Will update the total time field.
|
||||||
*/
|
*/
|
||||||
private final Runnable updateResults = new Runnable() {
|
private final Runnable updateResults = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
updateTotalTime();
|
if (dataHub.isRecordingSelected()) {
|
||||||
|
utils.setTime(R.id.total_time_register,
|
||||||
|
System.currentTimeMillis() - startTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -112,24 +79,22 @@ public class StatsActivity extends Activity
|
|||||||
|
|
||||||
public UIUpdateThread() {
|
public UIUpdateThread() {
|
||||||
super();
|
super();
|
||||||
Log.i(MyTracksConstants.TAG, "Created UI update thread");
|
Log.i(TAG, "Created UI update thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Log.i(MyTracksConstants.TAG, "Started UI update thread");
|
Log.i(TAG, "Started UI update thread");
|
||||||
while (MyTracks.getInstance().isRecording()) {
|
while (MyTracks.getInstance().isRecording()) {
|
||||||
long sleeptime = 1000;
|
|
||||||
runOnUiThread(updateResults);
|
runOnUiThread(updateResults);
|
||||||
try {
|
try {
|
||||||
Thread.sleep(sleeptime);
|
Thread.sleep(1000L);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Log.w(MyTracksConstants.TAG,
|
Log.w(TAG, "StatsActivity: Caught exception on sleep.", e);
|
||||||
"StatsActivity: Caught exception on sleep.", e);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.w(MyTracksConstants.TAG, "UIUpdateThread finished.");
|
Log.w(TAG, "UIUpdateThread finished.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,8 +103,8 @@ public class StatsActivity extends Activity
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
dataHub = MyTracks.getInstance().getDataHub();
|
||||||
utils = new StatsUtilities(this);
|
utils = new StatsUtilities(this);
|
||||||
providerUtils = new MyTracksProviderUtilsImpl(getContentResolver());
|
|
||||||
|
|
||||||
// The volume we want to control is the Text-To-Speech volume
|
// The volume we want to control is the Text-To-Speech volume
|
||||||
int volumeStream =
|
int volumeStream =
|
||||||
@@ -151,40 +116,10 @@ public class StatsActivity extends Activity
|
|||||||
|
|
||||||
setContentView(R.layout.stats);
|
setContentView(R.layout.stats);
|
||||||
|
|
||||||
Handler contentHandler = new Handler();
|
|
||||||
observer = new ContentObserver(contentHandler) {
|
|
||||||
@Override
|
|
||||||
public void onChange(boolean selfChange) {
|
|
||||||
Log.d(MyTracksConstants.TAG, "StatsActivity: ContentObserver.onChange");
|
|
||||||
restoreStats();
|
|
||||||
super.onChange(selfChange);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ScrollView sv = ((ScrollView) findViewById(R.id.scrolly));
|
ScrollView sv = ((ScrollView) findViewById(R.id.scrolly));
|
||||||
sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
|
sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
|
||||||
|
|
||||||
SharedPreferences preferences =
|
showUnknownLocation();
|
||||||
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();
|
|
||||||
|
|
||||||
DisplayMetrics metrics = new DisplayMetrics();
|
DisplayMetrics metrics = new DisplayMetrics();
|
||||||
getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||||
@@ -194,88 +129,67 @@ public class StatsActivity extends Activity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onStart() {
|
||||||
unregisterLocationListener();
|
dataHub.registerTrackDataListener(this, EnumSet.of(
|
||||||
|
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||||
|
ListenerDataType.TRACK_UPDATES,
|
||||||
|
ListenerDataType.LOCATION_UPDATES,
|
||||||
|
ListenerDataType.DISPLAY_PREFERENCES));
|
||||||
|
|
||||||
|
super.onStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
dataHub.unregisterTrackDataListener(this);
|
||||||
|
|
||||||
if (thread != null) {
|
if (thread != null) {
|
||||||
thread.interrupt();
|
thread.interrupt();
|
||||||
thread = null;
|
thread = null;
|
||||||
}
|
}
|
||||||
getContentResolver().unregisterContentObserver(observer);
|
|
||||||
activityOnTop = false;
|
super.onStop();
|
||||||
super.onPause();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
public boolean onUnitsChanged(boolean metric) {
|
||||||
activityOnTop = true;
|
utils.setMetricUnits(metric);
|
||||||
checkLiveTrack();
|
updateLabels();
|
||||||
restoreStats();
|
|
||||||
showUnknownLocation();
|
return true; // Reload data
|
||||||
super.onResume();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(
|
public boolean onReportSpeedChanged(boolean displaySpeed) {
|
||||||
final SharedPreferences sharedPreferences, final String key) {
|
utils.setReportSpeed(displaySpeed);
|
||||||
Log.d(MyTracksConstants.TAG,
|
updateLabels();
|
||||||
"StatsActivity: onSharedPreferences changed " + key);
|
|
||||||
if (key != null) {
|
return true; // Reload data
|
||||||
runOnUiThread(new Runnable() {
|
}
|
||||||
@Override
|
|
||||||
public void run() {
|
private void updateLabels() {
|
||||||
if (key.equals(getString(R.string.selected_track_key))) {
|
runOnUiThread(new Runnable() {
|
||||||
selectedTrackId =
|
@Override
|
||||||
sharedPreferences.getLong(
|
public void run() {
|
||||||
getString(R.string.selected_track_key),
|
utils.updateUnits();
|
||||||
-1);
|
utils.setSpeedLabel(R.id.speed_label, R.string.speed, R.string.pace_label);
|
||||||
checkLiveTrack();
|
utils.setSpeedLabels();
|
||||||
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(MyTracksConstants.TAG, "Setting speed labels");
|
|
||||||
utils.setSpeedLabels();
|
|
||||||
restoreStats();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
super.onCreateOptionsMenu(menu);
|
super.onCreateOptionsMenu(menu);
|
||||||
MenuItem currentSegment = menu.add(0,
|
MenuItem currentSegment = menu.add(0,
|
||||||
MyTracksConstants.MENU_CURRENT_SEGMENT, 0, R.string.current_segment);
|
Constants.MENU_CURRENT_SEGMENT, 0, R.string.current_segment);
|
||||||
currentSegment.setIcon(R.drawable.ic_menu_lastsegment);
|
currentSegment.setIcon(R.drawable.ic_menu_lastsegment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
MenuItem item = menu.findItem(MyTracksConstants.MENU_CURRENT_SEGMENT);
|
MenuItem item = menu.findItem(Constants.MENU_CURRENT_SEGMENT);
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.setTitle(showCurrentSegment
|
item.setTitle(showCurrentSegment
|
||||||
? getString(R.string.current_track)
|
? getString(R.string.current_track)
|
||||||
@@ -287,139 +201,14 @@ public class StatsActivity extends Activity
|
|||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case MyTracksConstants.MENU_CURRENT_SEGMENT:
|
case Constants.MENU_CURRENT_SEGMENT:
|
||||||
showCurrentSegment = !showCurrentSegment;
|
showCurrentSegment = !showCurrentSegment;
|
||||||
restoreStats();
|
// TODO: Re-read only the data that interests us
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
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(MyTracksConstants.GPS_PROVIDER);
|
|
||||||
if (gpsProvider == null) {
|
|
||||||
Toast.makeText(this, getString(R.string.error_no_gps_location_provider),
|
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
Log.d(MyTracksConstants.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
|
* Updates the given location fields (latitude, longitude, altitude) and all
|
||||||
* other fields.
|
* other fields.
|
||||||
@@ -439,4 +228,112 @@ public class StatsActivity extends Activity
|
|||||||
utils.setUnknown(R.id.longitude_register);
|
utils.setUnknown(R.id.longitude_register);
|
||||||
utils.setUnknown(R.id.speed_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.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ public class StatsUtilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setSpeedLabel(int id, int speedString, int paceString) {
|
public void setSpeedLabel(int id, int speedString, int paceString) {
|
||||||
Log.w(MyTracksConstants.TAG, "Setting view " + id +
|
Log.w(Constants.TAG, "Setting view " + id +
|
||||||
" to " + reportSpeed +
|
" to " + reportSpeed +
|
||||||
" speed: " + speedString +
|
" speed: " + speedString +
|
||||||
" pace: " + paceString);
|
" pace: " + paceString);
|
||||||
@@ -243,7 +243,7 @@ public class StatsUtilities {
|
|||||||
if (tv != null) {
|
if (tv != null) {
|
||||||
tv.setText(reportSpeed ? speedString : paceString);
|
tv.setText(reportSpeed ? speedString : paceString);
|
||||||
} else {
|
} else {
|
||||||
Log.w(MyTracksConstants.TAG, "Could not find id: " + id);
|
Log.w(Constants.TAG, "Could not find id: " + id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 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.
|
||||||
|
*/
|
||||||
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
|
|
||||||
|
import android.location.Location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener for track data, for both initial and incremental loading.
|
||||||
|
*
|
||||||
|
* TODO: Allow listening to just part of the data received here.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public interface TrackDataListener {
|
||||||
|
|
||||||
|
/** States for the GPS location provider. */
|
||||||
|
public enum ProviderState {
|
||||||
|
DISABLED,
|
||||||
|
NO_FIX,
|
||||||
|
BAD_FIX,
|
||||||
|
GOOD_FIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the location provider changes state.
|
||||||
|
*/
|
||||||
|
void onProviderStateChange(ProviderState state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the current location changes.
|
||||||
|
* This is meant for immediate location display only - track point data is
|
||||||
|
* delivered by other methods below, such as {@link #onNewTrackPoint}.
|
||||||
|
*
|
||||||
|
* @param loc the last known location
|
||||||
|
*/
|
||||||
|
void onCurrentLocationChanged(Location loc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the current heading changes.
|
||||||
|
*
|
||||||
|
* @param heading the current heading, already accounting magnetic declination
|
||||||
|
*/
|
||||||
|
void onCurrentHeadingChanged(double heading);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the currently-selected track changes.
|
||||||
|
* This will be followed by calls to data methods such as
|
||||||
|
* {@link #onTrackUpdated}, {@link #clearTrackPoints},
|
||||||
|
* {@link #onNewTrackPoint(Location)}, etc., even if no track is currently
|
||||||
|
* selected (in which case you'll only get calls to clear the current data).
|
||||||
|
*
|
||||||
|
* @param track the selected track, or null if no track is selected
|
||||||
|
* @param isRecording whether we're currently recording the selected track
|
||||||
|
*/
|
||||||
|
void onSelectedTrackChanged(Track track, boolean isRecording);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the track and/or its statistics have been updated.
|
||||||
|
*
|
||||||
|
* @param track the updated version of the track
|
||||||
|
*/
|
||||||
|
void onTrackUpdated(Track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to clear any previously-sent track points.
|
||||||
|
* This can be called at any time that we decide the data needs to be
|
||||||
|
* reloaded, such as when it needs to be resampled.
|
||||||
|
*/
|
||||||
|
void clearTrackPoints();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a new interesting track point is read.
|
||||||
|
* In this case, interesting means that the point has already undergone
|
||||||
|
* sampling and invalid point filtering.
|
||||||
|
*
|
||||||
|
* @param loc the new track point
|
||||||
|
*/
|
||||||
|
void onNewTrackPoint(Location loc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a uninteresting track point is read.
|
||||||
|
* Uninteresting points are all points that get sampled out of the track.
|
||||||
|
*
|
||||||
|
* @param loc the new track point
|
||||||
|
*/
|
||||||
|
void onSampledOutTrackPoint(Location loc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an invalid point (representing a segment split) is read.
|
||||||
|
*/
|
||||||
|
void onSegmentSplit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when we're done (for the time being) sending new points.
|
||||||
|
* This gets called after every batch of calls to {@link #onNewTrackPoint},
|
||||||
|
* {@link #onSampledOutTrackPoint} and {@link #onSegmentSplit}.
|
||||||
|
*/
|
||||||
|
void onNewTrackPointsDone();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to clear any previously-sent waypoints.
|
||||||
|
* This can be called at any time that we decide the data needs to be
|
||||||
|
* reloaded.
|
||||||
|
*/
|
||||||
|
void clearWaypoints();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a new waypoint is read.
|
||||||
|
*
|
||||||
|
* @param wpt the new waypoint
|
||||||
|
*/
|
||||||
|
void onNewWaypoint(Waypoint wpt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when we're done (for the time being) sending new waypoints.
|
||||||
|
* This gets called after every batch of calls to {@link #clearWaypoints} and
|
||||||
|
* {@link #onNewWaypoint}.
|
||||||
|
*/
|
||||||
|
void onNewWaypointsDone();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the display units are changed by the user.
|
||||||
|
*
|
||||||
|
* @param metric true if the units are metric, false if imperial
|
||||||
|
* @return true to reload all the data, false otherwise
|
||||||
|
*/
|
||||||
|
boolean onUnitsChanged(boolean metric);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the speed/pace display unit is changed by the user.
|
||||||
|
*
|
||||||
|
* @param reportSpeed true to report speed, false for pace
|
||||||
|
* @return true to reload all the data, false otherwise
|
||||||
|
*/
|
||||||
|
boolean onReportSpeedChanged(boolean reportSpeed);
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 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.
|
||||||
|
*/
|
||||||
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
|
import android.database.ContentObserver;
|
||||||
|
import android.hardware.Sensor;
|
||||||
|
import android.hardware.SensorEventListener;
|
||||||
|
import android.location.Location;
|
||||||
|
import android.location.LocationListener;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for abstracting external data sources.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
interface TrackDataSources {
|
||||||
|
// Preferences
|
||||||
|
void registerOnSharedPreferenceChangeListener(
|
||||||
|
OnSharedPreferenceChangeListener listener);
|
||||||
|
void unregisterOnSharedPreferenceChangeListener(
|
||||||
|
OnSharedPreferenceChangeListener listener);
|
||||||
|
|
||||||
|
// Content provider
|
||||||
|
void registerContentObserver(Uri contentUri, boolean descendents,
|
||||||
|
ContentObserver observer);
|
||||||
|
void unregisterContentObserver(ContentObserver observer);
|
||||||
|
|
||||||
|
// Sensors
|
||||||
|
Sensor getSensor(int type);
|
||||||
|
void registerSensorListener(SensorEventListener listener,
|
||||||
|
Sensor sensor, int sensorDelay);
|
||||||
|
void unregisterSensorListener(SensorEventListener listener);
|
||||||
|
|
||||||
|
// Location
|
||||||
|
boolean isLocationProviderEnabled(String provider);
|
||||||
|
void requestLocationUpdates(LocationListener listener);
|
||||||
|
void removeLocationUpdates(LocationListener listener);
|
||||||
|
Location getLastKnownLocation();
|
||||||
|
}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 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.
|
||||||
|
*/
|
||||||
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
|
import static com.google.android.apps.mytracks.Constants.MAX_LOCATION_AGE_MS;
|
||||||
|
import static com.google.android.apps.mytracks.Constants.MAX_NETWORK_AGE_MS;
|
||||||
|
|
||||||
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
|
import android.database.ContentObserver;
|
||||||
|
import android.hardware.Sensor;
|
||||||
|
import android.hardware.SensorEventListener;
|
||||||
|
import android.hardware.SensorManager;
|
||||||
|
import android.location.Location;
|
||||||
|
import android.location.LocationListener;
|
||||||
|
import android.location.LocationManager;
|
||||||
|
import android.location.LocationProvider;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Real implementation of the data sources, which talks to system services.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
class TrackDataSourcesImpl implements TrackDataSources {
|
||||||
|
// System services
|
||||||
|
private final SensorManager sensorManager;
|
||||||
|
private final LocationManager locationManager;
|
||||||
|
private final ContentResolver contentResolver;
|
||||||
|
private final SharedPreferences sharedPreferences;
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
TrackDataSourcesImpl(Context context, SharedPreferences sharedPreferences) {
|
||||||
|
this.context = context;
|
||||||
|
this.sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||||
|
this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||||
|
this.contentResolver = context.getContentResolver();
|
||||||
|
this.sharedPreferences = sharedPreferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerOnSharedPreferenceChangeListener(
|
||||||
|
OnSharedPreferenceChangeListener listener) {
|
||||||
|
sharedPreferences.registerOnSharedPreferenceChangeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterOnSharedPreferenceChangeListener(
|
||||||
|
OnSharedPreferenceChangeListener listener) {
|
||||||
|
sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerContentObserver(Uri contentUri, boolean descendents,
|
||||||
|
ContentObserver observer) {
|
||||||
|
contentResolver.registerContentObserver(contentUri, descendents, observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterContentObserver(ContentObserver observer) {
|
||||||
|
contentResolver.unregisterContentObserver(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Sensor getSensor(int type) {
|
||||||
|
return sensorManager.getDefaultSensor(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerSensorListener(SensorEventListener listener,
|
||||||
|
Sensor sensor, int sensorDelay) {
|
||||||
|
sensorManager.registerListener(listener, sensor, sensorDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterSensorListener(SensorEventListener listener) {
|
||||||
|
sensorManager.unregisterListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLocationProviderEnabled(String provider) {
|
||||||
|
return locationManager.isProviderEnabled(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestLocationUpdates(LocationListener listener) {
|
||||||
|
// Check if the provider exists.
|
||||||
|
LocationProvider gpsProvider = locationManager.getProvider(LocationManager.GPS_PROVIDER);
|
||||||
|
if (gpsProvider == null) {
|
||||||
|
listener.onProviderDisabled(LocationManager.GPS_PROVIDER);
|
||||||
|
locationManager.removeUpdates(listener);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen to GPS location.
|
||||||
|
String providerName = gpsProvider.getName();
|
||||||
|
Log.d(Constants.TAG, "TrackDataHub: Using location provider " + providerName);
|
||||||
|
locationManager.requestLocationUpdates(providerName,
|
||||||
|
0 /*minTime*/, 0 /*minDist*/, listener);
|
||||||
|
|
||||||
|
// Give an initial update on provider state.
|
||||||
|
if (locationManager.isProviderEnabled(providerName)) {
|
||||||
|
listener.onProviderEnabled(providerName);
|
||||||
|
} else {
|
||||||
|
listener.onProviderDisabled(providerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen to network location
|
||||||
|
try {
|
||||||
|
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
|
||||||
|
1000 * 60 * 5 /*minTime*/, 0 /*minDist*/, listener);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// If anything at all goes wrong with getting a cell location do not
|
||||||
|
// abort. Cell location is not essential to this app.
|
||||||
|
Log.w(Constants.TAG, "Could not register network location listener.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Location getLastKnownLocation() {
|
||||||
|
// TODO: Let's look at more advanced algorithms to determine the best
|
||||||
|
// current location.
|
||||||
|
|
||||||
|
Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
|
||||||
|
final long now = System.currentTimeMillis();
|
||||||
|
if (loc == null || loc.getTime() < now - MAX_LOCATION_AGE_MS) {
|
||||||
|
// We don't have a recent GPS fix, just use cell towers if available
|
||||||
|
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
|
||||||
|
|
||||||
|
int toastResId = R.string.status_approximate_location;
|
||||||
|
if (loc == null || loc.getTime() < now - MAX_NETWORK_AGE_MS) {
|
||||||
|
// We don't have a recent cell tower location, let the user know:
|
||||||
|
toastResId = R.string.status_no_location;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let the user know we have only an approximate location:
|
||||||
|
Toast.makeText(context, context.getString(toastResId), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeLocationUpdates(LocationListener listener) {
|
||||||
|
locationManager.removeUpdates(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -37,7 +37,7 @@ import android.widget.EditText;
|
|||||||
*
|
*
|
||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
public class MyTracksDetails extends Activity implements OnClickListener {
|
public class TrackDetails extends Activity implements OnClickListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The id of the track being edited (taken from bundle, "trackid")
|
* The id of the track being edited (taken from bundle, "trackid")
|
||||||
@@ -56,7 +56,7 @@ public class MyTracksDetails extends Activity implements OnClickListener {
|
|||||||
// Required extra when launching this intent:
|
// Required extra when launching this intent:
|
||||||
trackId = getIntent().getLongExtra("trackid", -1);
|
trackId = getIntent().getLongExtra("trackid", -1);
|
||||||
if (trackId < 0) {
|
if (trackId < 0) {
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"MyTracksDetails intent was launched w/o track id.");
|
"MyTracksDetails intent was launched w/o track id.");
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
+34
-29
@@ -45,7 +45,7 @@ import android.widget.TextView;
|
|||||||
*
|
*
|
||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
public class MyTracksList extends ListActivity
|
public class TrackList extends ListActivity
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener,
|
implements SharedPreferences.OnSharedPreferenceChangeListener,
|
||||||
View.OnClickListener {
|
View.OnClickListener {
|
||||||
|
|
||||||
@@ -70,40 +70,40 @@ public class MyTracksList extends ListActivity
|
|||||||
AdapterView.AdapterContextMenuInfo info =
|
AdapterView.AdapterContextMenuInfo info =
|
||||||
(AdapterView.AdapterContextMenuInfo) menuInfo;
|
(AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||||
contextPosition = info.position;
|
contextPosition = info.position;
|
||||||
trackId = MyTracksList.this.listView.getAdapter().getItemId(
|
trackId = TrackList.this.listView.getAdapter().getItemId(
|
||||||
contextPosition);
|
contextPosition);
|
||||||
menu.add(0, MyTracksConstants.MENU_SHOW, 0,
|
menu.add(0, Constants.MENU_SHOW, 0,
|
||||||
R.string.tracklist_show_track);
|
R.string.tracklist_show_track);
|
||||||
menu.add(0, MyTracksConstants.MENU_EDIT, 0,
|
menu.add(0, Constants.MENU_EDIT, 0,
|
||||||
R.string.tracklist_edit_track);
|
R.string.tracklist_edit_track);
|
||||||
if (!MyTracks.getInstance().isRecording()
|
if (!MyTracks.getInstance().isRecording()
|
||||||
|| trackId != recordingTrackId) {
|
|| trackId != recordingTrackId) {
|
||||||
menu.add(0, MyTracksConstants.MENU_SEND_TO_GOOGLE, 0,
|
menu.add(0, Constants.MENU_SEND_TO_GOOGLE, 0,
|
||||||
R.string.tracklist_send_to_google);
|
R.string.tracklist_send_to_google);
|
||||||
SubMenu share = menu.addSubMenu(0, MyTracksConstants.MENU_SHARE, 0,
|
SubMenu share = menu.addSubMenu(0, Constants.MENU_SHARE, 0,
|
||||||
R.string.tracklist_share_track);
|
R.string.tracklist_share_track);
|
||||||
share.add(0, MyTracksConstants.MENU_SHARE_LINK, 0,
|
share.add(0, Constants.MENU_SHARE_LINK, 0,
|
||||||
R.string.tracklist_share_linkfusion);
|
R.string.tracklist_share_link);
|
||||||
share.add(0, MyTracksConstants.MENU_SHARE_GPX_FILE, 0,
|
share.add(0, Constants.MENU_SHARE_GPX_FILE, 0,
|
||||||
R.string.tracklist_share_gpx_file);
|
R.string.tracklist_share_gpx_file);
|
||||||
share.add(0, MyTracksConstants.MENU_SHARE_KML_FILE, 0,
|
share.add(0, Constants.MENU_SHARE_KML_FILE, 0,
|
||||||
R.string.tracklist_share_kml_file);
|
R.string.tracklist_share_kml_file);
|
||||||
share.add(0, MyTracksConstants.MENU_SHARE_CSV_FILE, 0,
|
share.add(0, Constants.MENU_SHARE_CSV_FILE, 0,
|
||||||
R.string.tracklist_share_csv_file);
|
R.string.tracklist_share_csv_file);
|
||||||
share.add(0, MyTracksConstants.MENU_SHARE_TCX_FILE, 0,
|
share.add(0, Constants.MENU_SHARE_TCX_FILE, 0,
|
||||||
R.string.tracklist_share_tcx_file);
|
R.string.tracklist_share_tcx_file);
|
||||||
SubMenu save = menu.addSubMenu(0,
|
SubMenu save = menu.addSubMenu(0,
|
||||||
MyTracksConstants.MENU_WRITE_TO_SD_CARD, 0,
|
Constants.MENU_WRITE_TO_SD_CARD, 0,
|
||||||
R.string.tracklist_write_to_sd);
|
R.string.tracklist_write_to_sd);
|
||||||
save.add(0, MyTracksConstants.MENU_SAVE_GPX_FILE, 0,
|
save.add(0, Constants.MENU_SAVE_GPX_FILE, 0,
|
||||||
R.string.tracklist_save_as_gpx);
|
R.string.tracklist_save_as_gpx);
|
||||||
save.add(0, MyTracksConstants.MENU_SAVE_KML_FILE, 0,
|
save.add(0, Constants.MENU_SAVE_KML_FILE, 0,
|
||||||
R.string.tracklist_save_as_kml);
|
R.string.tracklist_save_as_kml);
|
||||||
save.add(0, MyTracksConstants.MENU_SAVE_CSV_FILE, 0,
|
save.add(0, Constants.MENU_SAVE_CSV_FILE, 0,
|
||||||
R.string.tracklist_save_as_csv);
|
R.string.tracklist_save_as_csv);
|
||||||
save.add(0, MyTracksConstants.MENU_SAVE_TCX_FILE, 0,
|
save.add(0, Constants.MENU_SAVE_TCX_FILE, 0,
|
||||||
R.string.tracklist_save_as_tcx);
|
R.string.tracklist_save_as_tcx);
|
||||||
menu.add(0, MyTracksConstants.MENU_DELETE, 0,
|
menu.add(0, Constants.MENU_DELETE, 0,
|
||||||
R.string.tracklist_delete_track);
|
R.string.tracklist_delete_track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ public class MyTracksList extends ListActivity
|
|||||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
result.putExtra("trackid", id);
|
result.putExtra("trackid", id);
|
||||||
setResult(MyTracksConstants.SHOW_TRACK, result);
|
setResult(Constants.SHOW_TRACK, result);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,24 +140,24 @@ public class MyTracksList extends ListActivity
|
|||||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||||
if (!super.onMenuItemSelected(featureId, item)) {
|
if (!super.onMenuItemSelected(featureId, item)) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case MyTracksConstants.MENU_SHOW: {
|
case Constants.MENU_SHOW: {
|
||||||
onListItemClick(null, null, 0, trackId);
|
onListItemClick(null, null, 0, trackId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case MyTracksConstants.MENU_EDIT: {
|
case Constants.MENU_EDIT: {
|
||||||
Intent intent = new Intent(this, MyTracksDetails.class);
|
Intent intent = new Intent(this, TrackDetails.class);
|
||||||
intent.putExtra("trackid", trackId);
|
intent.putExtra("trackid", trackId);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case MyTracksConstants.MENU_SHARE:
|
case Constants.MENU_SHARE:
|
||||||
case MyTracksConstants.MENU_WRITE_TO_SD_CARD:
|
case Constants.MENU_WRITE_TO_SD_CARD:
|
||||||
return false;
|
return false;
|
||||||
default: {
|
default: {
|
||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
result.putExtra("trackid", trackId);
|
result.putExtra("trackid", trackId);
|
||||||
setResult(
|
setResult(
|
||||||
MyTracksConstants.getActionFromMenuId(item.getItemId()), result);
|
Constants.getActionFromMenuId(item.getItemId()), result);
|
||||||
finish();
|
finish();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,7 @@ public class MyTracksList extends ListActivity
|
|||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
switch (v.getId()) {
|
switch (v.getId()) {
|
||||||
case R.id.tracklist_btn_delete_all: {
|
case R.id.tracklist_btn_delete_all: {
|
||||||
Handler h = new MyTracksDeleteAllTracks(this, null);
|
Handler h = new DeleteAllTracks(this, null);
|
||||||
h.handleMessage(null);
|
h.handleMessage(null);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -197,12 +197,17 @@ public class MyTracksList extends ListActivity
|
|||||||
listView = getListView();
|
listView = getListView();
|
||||||
listView.setOnCreateContextMenuListener(contextMenuListener);
|
listView.setOnCreateContextMenuListener(contextMenuListener);
|
||||||
|
|
||||||
findViewById(R.id.tracklist_btn_delete_all).setOnClickListener(this);
|
View deleteAll = findViewById(R.id.tracklist_btn_delete_all);
|
||||||
findViewById(R.id.tracklist_btn_export_all).setOnClickListener(this);
|
View exportAll = findViewById(R.id.tracklist_btn_export_all);
|
||||||
|
boolean notRecording = !MyTracks.getInstance().isRecording();
|
||||||
|
deleteAll.setOnClickListener(this);
|
||||||
|
deleteAll.setEnabled(notRecording);
|
||||||
|
exportAll.setOnClickListener(this);
|
||||||
|
exportAll.setEnabled(notRecording);
|
||||||
findViewById(R.id.tracklist_btn_import_all).setOnClickListener(this);
|
findViewById(R.id.tracklist_btn_import_all).setOnClickListener(this);
|
||||||
|
|
||||||
SharedPreferences preferences =
|
SharedPreferences preferences =
|
||||||
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||||
metricUnits =
|
metricUnits =
|
||||||
preferences.getBoolean(getString(R.string.metric_units_key), true);
|
preferences.getBoolean(getString(R.string.metric_units_key), true);
|
||||||
+3
-3
@@ -39,7 +39,7 @@ import android.widget.ImageView;
|
|||||||
*
|
*
|
||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
public class MyTracksWaypointDetails extends Activity
|
public class WaypointDetails extends Activity
|
||||||
implements OnClickListener {
|
implements OnClickListener {
|
||||||
|
|
||||||
public static final String WAYPOINT_ID_EXTRA = "com.google.android.apps.mytracks.WAYPOINT_ID";
|
public static final String WAYPOINT_ID_EXTRA = "com.google.android.apps.mytracks.WAYPOINT_ID";
|
||||||
@@ -65,7 +65,7 @@ public class MyTracksWaypointDetails extends Activity
|
|||||||
|
|
||||||
utils = new StatsUtilities(this);
|
utils = new StatsUtilities(this);
|
||||||
SharedPreferences preferences =
|
SharedPreferences preferences =
|
||||||
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||||
if (preferences != null) {
|
if (preferences != null) {
|
||||||
boolean useMetric =
|
boolean useMetric =
|
||||||
preferences.getBoolean(getString(R.string.metric_units_key), true);
|
preferences.getBoolean(getString(R.string.metric_units_key), true);
|
||||||
@@ -82,7 +82,7 @@ public class MyTracksWaypointDetails extends Activity
|
|||||||
// Required extra when launching this intent:
|
// Required extra when launching this intent:
|
||||||
waypointId = getIntent().getLongExtra(WAYPOINT_ID_EXTRA, -1);
|
waypointId = getIntent().getLongExtra(WAYPOINT_ID_EXTRA, -1);
|
||||||
if (waypointId < 0) {
|
if (waypointId < 0) {
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"MyTracksWaypointsDetails intent was launched w/o waypoint id.");
|
"MyTracksWaypointsDetails intent was launched w/o waypoint id.");
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
+22
-20
@@ -49,7 +49,7 @@ import android.widget.TextView;
|
|||||||
*
|
*
|
||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
public class MyTracksWaypointsList extends ListActivity
|
public class WaypointsList extends ListActivity
|
||||||
implements View.OnClickListener {
|
implements View.OnClickListener {
|
||||||
|
|
||||||
private int contextPosition = -1;
|
private int contextPosition = -1;
|
||||||
@@ -59,7 +59,6 @@ public class MyTracksWaypointsList extends ListActivity
|
|||||||
private Button insertWaypointButton = null;
|
private Button insertWaypointButton = null;
|
||||||
private Button insertStatisticsButton = null;
|
private Button insertStatisticsButton = null;
|
||||||
private long recordingTrackId = -1;
|
private long recordingTrackId = -1;
|
||||||
private long selectedTrackId = -1;
|
|
||||||
private MyTracksProviderUtils providerUtils;
|
private MyTracksProviderUtils providerUtils;
|
||||||
|
|
||||||
private Cursor waypointsCursor = null;
|
private Cursor waypointsCursor = null;
|
||||||
@@ -72,14 +71,14 @@ public class MyTracksWaypointsList extends ListActivity
|
|||||||
AdapterView.AdapterContextMenuInfo info =
|
AdapterView.AdapterContextMenuInfo info =
|
||||||
(AdapterView.AdapterContextMenuInfo) menuInfo;
|
(AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||||
contextPosition = info.position;
|
contextPosition = info.position;
|
||||||
waypointId = MyTracksWaypointsList.this.listView.getAdapter()
|
waypointId = WaypointsList.this.listView.getAdapter()
|
||||||
.getItemId(contextPosition);
|
.getItemId(contextPosition);
|
||||||
int type = providerUtils.getWaypoint(info.id).getType();
|
int type = providerUtils.getWaypoint(info.id).getType();
|
||||||
menu.add(0, MyTracksConstants.MENU_SHOW, 0,
|
menu.add(0, Constants.MENU_SHOW, 0,
|
||||||
R.string.waypointslist_show_waypoint);
|
R.string.waypointslist_show_waypoint);
|
||||||
menu.add(0, MyTracksConstants.MENU_EDIT, 0,
|
menu.add(0, Constants.MENU_EDIT, 0,
|
||||||
R.string.waypointslist_edit_waypoint);
|
R.string.waypointslist_edit_waypoint);
|
||||||
menu.add(0, MyTracksConstants.MENU_DELETE, 0,
|
menu.add(0, Constants.MENU_DELETE, 0,
|
||||||
R.string.waypointslist_delete_waypoint).setEnabled(
|
R.string.waypointslist_delete_waypoint).setEnabled(
|
||||||
recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT ||
|
recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT ||
|
||||||
info.id != providerUtils.getLastWaypointId(recordingTrackId));
|
info.id != providerUtils.getLastWaypointId(recordingTrackId));
|
||||||
@@ -90,8 +89,8 @@ public class MyTracksWaypointsList extends ListActivity
|
|||||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
result.putExtra("trackid", trackId);
|
result.putExtra("trackid", trackId);
|
||||||
result.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, id);
|
result.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, id);
|
||||||
setResult(MyTracksConstants.EDIT_WAYPOINT, result);
|
setResult(Constants.EDIT_WAYPOINT, result);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,18 +98,18 @@ public class MyTracksWaypointsList extends ListActivity
|
|||||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||||
if (!super.onMenuItemSelected(featureId, item)) {
|
if (!super.onMenuItemSelected(featureId, item)) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case MyTracksConstants.MENU_SHOW: {
|
case Constants.MENU_SHOW: {
|
||||||
onListItemClick(null, null, 0, waypointId);
|
onListItemClick(null, null, 0, waypointId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case MyTracksConstants.MENU_EDIT: {
|
case Constants.MENU_EDIT: {
|
||||||
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
|
Intent intent = new Intent(this, WaypointDetails.class);
|
||||||
intent.putExtra("trackid", trackId);
|
intent.putExtra("trackid", trackId);
|
||||||
intent.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, waypointId);
|
intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, waypointId);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case MyTracksConstants.MENU_DELETE: {
|
case Constants.MENU_DELETE: {
|
||||||
deleteWaypoint(waypointId);
|
deleteWaypoint(waypointId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +138,10 @@ public class MyTracksWaypointsList extends ListActivity
|
|||||||
(Button) findViewById(R.id.waypointslist_btn_insert_statistics);
|
(Button) findViewById(R.id.waypointslist_btn_insert_statistics);
|
||||||
insertStatisticsButton.setOnClickListener(this);
|
insertStatisticsButton.setOnClickListener(this);
|
||||||
SharedPreferences preferences =
|
SharedPreferences preferences =
|
||||||
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||||
|
|
||||||
|
// TODO: Get rid of selected and recording track IDs
|
||||||
|
long selectedTrackId = -1;
|
||||||
if (preferences != null) {
|
if (preferences != null) {
|
||||||
recordingTrackId =
|
recordingTrackId =
|
||||||
preferences.getLong(getString(R.string.recording_track_key), -1);
|
preferences.getLong(getString(R.string.recording_track_key), -1);
|
||||||
@@ -183,18 +185,18 @@ public class MyTracksWaypointsList extends ListActivity
|
|||||||
try {
|
try {
|
||||||
id = MyTracks.getInstance().insertWaypoint(request);
|
id = MyTracks.getInstance().insertWaypoint(request);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Cannot insert marker.", e);
|
Log.e(Constants.TAG, "Cannot insert marker.", e);
|
||||||
return;
|
return;
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Cannot insert marker.", e);
|
Log.e(Constants.TAG, "Cannot insert marker.", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
Log.e(MyTracksConstants.TAG, "Failed to insert marker.");
|
Log.e(Constants.TAG, "Failed to insert marker.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
|
Intent intent = new Intent(this, WaypointDetails.class);
|
||||||
intent.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, id);
|
intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, id);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +261,7 @@ public class MyTracksWaypointsList extends ListActivity
|
|||||||
public void onClick(DialogInterface dialog, int i) {
|
public void onClick(DialogInterface dialog, int i) {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
providerUtils.deleteWaypoint(waypointId,
|
providerUtils.deleteWaypoint(waypointId,
|
||||||
new StringUtils(MyTracksWaypointsList.this));
|
new StringUtils(WaypointsList.this));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.setNegativeButton(getString(R.string.no),
|
builder.setNegativeButton(getString(R.string.no),
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks;
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@@ -82,6 +82,6 @@ public class WelcomeActivity extends Activity {
|
|||||||
AlertDialog dialog = builder.create();
|
AlertDialog dialog = builder.create();
|
||||||
dialog.show();
|
dialog.show();
|
||||||
((TextView) dialog.findViewById(R.id.about_version_register)).
|
((TextView) dialog.findViewById(R.id.about_version_register)).
|
||||||
setText(MyTracksUtils.getMyTracksVersion(this));
|
setText(SystemUtils.getMyTracksVersion(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 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.
|
||||||
|
*/
|
||||||
|
package com.google.android.apps.mytracks;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.io.file.TrackWriter;
|
||||||
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.ProgressDialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a {@link TrackWriter}, this class manages the process of writing the
|
||||||
|
* data in the track represented by the writer. This includes the display of
|
||||||
|
* a progress dialog, updating the progress bar in said dialog, and notifying
|
||||||
|
* interested parties when the write completes.
|
||||||
|
*
|
||||||
|
* @author Matthew Simmons
|
||||||
|
*/
|
||||||
|
class WriteProgressController {
|
||||||
|
/**
|
||||||
|
* This listener is used to notify interested parties when the write has
|
||||||
|
* completed.
|
||||||
|
*/
|
||||||
|
public interface OnCompletionListener {
|
||||||
|
/**
|
||||||
|
* When this method is invoked, the write has completed, and the progress
|
||||||
|
* dialog has been dismissed. Whether the write succeeded can be
|
||||||
|
* determined by examining the {@link TrackWriter}.
|
||||||
|
*/
|
||||||
|
public void onComplete(TrackWriter writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Activity activity;
|
||||||
|
private final TrackWriter writer;
|
||||||
|
private final ProgressDialog dialog;
|
||||||
|
|
||||||
|
private OnCompletionListener onCompletionListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param activity the activity associated with this write
|
||||||
|
* @param writer the writer which writes the track to disk. Note that this
|
||||||
|
* class will use the writer's completion listener. If callers are
|
||||||
|
* interested in notification upon completion of the write, they should
|
||||||
|
* use {@link #setOnCompletionListener}.
|
||||||
|
*/
|
||||||
|
public WriteProgressController(Activity activity, TrackWriter writer) {
|
||||||
|
this.activity = activity;
|
||||||
|
this.writer = writer;
|
||||||
|
|
||||||
|
dialog = new ProgressDialog(activity);
|
||||||
|
dialog.setIcon(android.R.drawable.ic_dialog_info);
|
||||||
|
dialog.setTitle(activity.getString(R.string.progress_title));
|
||||||
|
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||||
|
dialog.setMessage(activity.getString(R.string.write_progress_message));
|
||||||
|
dialog.setIndeterminate(true);
|
||||||
|
dialog.setOnCancelListener(dialogCancelListener);
|
||||||
|
|
||||||
|
writer.setOnCompletionListener(writerCompleteListener);
|
||||||
|
writer.setOnWriteListener(writerWriteListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set a listener to be invoked when the write completes. */
|
||||||
|
public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
|
||||||
|
this.onCompletionListener = onCompletionListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initiate an asynchronous write. */
|
||||||
|
public void startWrite() {
|
||||||
|
DialogManager.showDialogSafely(activity, dialog);
|
||||||
|
writer.writeTrackAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** VisibleForTesting */
|
||||||
|
ProgressDialog getDialog() {
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final DialogInterface.OnCancelListener dialogCancelListener =
|
||||||
|
new DialogInterface.OnCancelListener() {
|
||||||
|
@Override
|
||||||
|
public void onCancel(DialogInterface dialog) {
|
||||||
|
writer.stopWriteTrack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final TrackWriter.OnCompletionListener writerCompleteListener =
|
||||||
|
new TrackWriter.OnCompletionListener() {
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
DialogManager.dismissDialogSafely(activity, dialog);
|
||||||
|
|
||||||
|
if (onCompletionListener != null) {
|
||||||
|
onCompletionListener.onComplete(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final TrackWriter.OnWriteListener writerWriteListener =
|
||||||
|
new TrackWriter.OnWriteListener() {
|
||||||
|
@Override
|
||||||
|
public void onWrite(int number, int max) {
|
||||||
|
if (number % 500 == 0) {
|
||||||
|
dialog.setIndeterminate(false);
|
||||||
|
dialog.setMax(max);
|
||||||
|
dialog.setProgress(Math.min(number, max));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.content;
|
package com.google.android.apps.mytracks.content;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
import com.google.android.apps.mytracks.util.ApiFeatures;
|
||||||
|
|
||||||
import android.content.ContentProvider;
|
import android.content.ContentProvider;
|
||||||
@@ -193,12 +193,14 @@ public class MyTracksProvider extends ContentProvider {
|
|||||||
@Override
|
@Override
|
||||||
public int delete(Uri url, String where, String[] selectionArgs) {
|
public int delete(Uri url, String where, String[] selectionArgs) {
|
||||||
String table;
|
String table;
|
||||||
|
boolean shouldVacuum = false;
|
||||||
switch (urlMatcher.match(url)) {
|
switch (urlMatcher.match(url)) {
|
||||||
case TRACKPOINTS:
|
case TRACKPOINTS:
|
||||||
table = TRACKPOINTS_TABLE;
|
table = TRACKPOINTS_TABLE;
|
||||||
break;
|
break;
|
||||||
case TRACKS:
|
case TRACKS:
|
||||||
table = TRACKS_TABLE;
|
table = TRACKS_TABLE;
|
||||||
|
shouldVacuum = true;
|
||||||
break;
|
break;
|
||||||
case WAYPOINTS:
|
case WAYPOINTS:
|
||||||
table = WAYPOINTS_TABLE;
|
table = WAYPOINTS_TABLE;
|
||||||
@@ -210,6 +212,13 @@ public class MyTracksProvider extends ContentProvider {
|
|||||||
Log.w(MyTracksProvider.TAG, "provider delete in " + table + "!");
|
Log.w(MyTracksProvider.TAG, "provider delete in " + table + "!");
|
||||||
int count = db.delete(table, where, selectionArgs);
|
int count = db.delete(table, where, selectionArgs);
|
||||||
getContext().getContentResolver().notifyChange(url, null, true);
|
getContext().getContentResolver().notifyChange(url, null, true);
|
||||||
|
|
||||||
|
if (shouldVacuum) {
|
||||||
|
// If a potentially large amount of data was deleted, we want to reclaim its space.
|
||||||
|
Log.i(TAG, "Vacuuming the database");
|
||||||
|
db.execSQL("VACUUM");
|
||||||
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +382,7 @@ public class MyTracksProvider extends ContentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ApiFeatures.getInstance().canReuseSQLiteQueryBuilder()) {
|
if (ApiFeatures.getInstance().canReuseSQLiteQueryBuilder()) {
|
||||||
Log.i(MyTracksConstants.TAG,
|
Log.i(Constants.TAG,
|
||||||
"Build query: " + qb.buildQuery(projection, selection, selectionArgs,
|
"Build query: " + qb.buildQuery(projection, selection, selectionArgs,
|
||||||
null, null, sortOrder, null));
|
null, null, sortOrder, null));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@@ -46,11 +46,11 @@ public class AuthManagerFactory {
|
|||||||
public static AuthManager getAuthManager(Activity activity, int code,
|
public static AuthManager getAuthManager(Activity activity, int code,
|
||||||
Bundle extras, boolean requireGoogle, String service) {
|
Bundle extras, boolean requireGoogle, String service) {
|
||||||
if (useModernAuthManager()) {
|
if (useModernAuthManager()) {
|
||||||
Log.i(MyTracksConstants.TAG,
|
Log.i(Constants.TAG,
|
||||||
"Creating modern auth manager: " + service);
|
"Creating modern auth manager: " + service);
|
||||||
return new ModernAuthManager(activity, code, extras, requireGoogle, service);
|
return new ModernAuthManager(activity, code, extras, requireGoogle, service);
|
||||||
} else {
|
} else {
|
||||||
Log.i(MyTracksConstants.TAG,
|
Log.i(Constants.TAG,
|
||||||
"Creating legacy auth manager: " + service);
|
"Creating legacy auth manager: " + service);
|
||||||
return new AuthManagerOld(activity, code, extras, requireGoogle, service);
|
return new AuthManagerOld(activity, code, extras, requireGoogle, service);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import com.google.android.accounts.AuthenticatorException;
|
|||||||
import com.google.android.accounts.OperationCanceledException;
|
import com.google.android.accounts.OperationCanceledException;
|
||||||
import com.google.android.apps.mytracks.AccountChooser;
|
import com.google.android.apps.mytracks.AccountChooser;
|
||||||
import com.google.android.apps.mytracks.MyTracks;
|
import com.google.android.apps.mytracks.MyTracks;
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -104,20 +104,20 @@ public class ModernAuthManager implements AuthManager {
|
|||||||
if (result.containsKey(AccountManager.KEY_INTENT)) {
|
if (result.containsKey(AccountManager.KEY_INTENT)) {
|
||||||
Intent intent = (Intent) result.get(AccountManager.KEY_INTENT);
|
Intent intent = (Intent) result.get(AccountManager.KEY_INTENT);
|
||||||
clearNewTaskFlag(intent);
|
clearNewTaskFlag(intent);
|
||||||
activity.startActivityForResult(intent, MyTracksConstants.GET_LOGIN);
|
activity.startActivityForResult(intent, Constants.GET_LOGIN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
authToken = result.getString(
|
authToken = result.getString(
|
||||||
AccountManager.KEY_AUTHTOKEN);
|
AccountManager.KEY_AUTHTOKEN);
|
||||||
Log.e(MyTracksConstants.TAG, "Got auth token.");
|
Log.e(Constants.TAG, "Got auth token.");
|
||||||
runWhenFinished();
|
runWhenFinished();
|
||||||
} catch (OperationCanceledException e) {
|
} catch (OperationCanceledException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Operation Canceled", e);
|
Log.e(Constants.TAG, "Operation Canceled", e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "IOException", e);
|
Log.e(Constants.TAG, "IOException", e);
|
||||||
} catch (AuthenticatorException e) {
|
} catch (AuthenticatorException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Authentication Failed", e);
|
Log.e(Constants.TAG, "Authentication Failed", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, null /* handler */);
|
}, null /* handler */);
|
||||||
@@ -149,9 +149,9 @@ public class ModernAuthManager implements AuthManager {
|
|||||||
if (results != null) {
|
if (results != null) {
|
||||||
authToken = results.getStringExtra(
|
authToken = results.getStringExtra(
|
||||||
AccountManager.KEY_AUTHTOKEN);
|
AccountManager.KEY_AUTHTOKEN);
|
||||||
Log.w(MyTracksConstants.TAG, "authResult: " + authToken);
|
Log.w(Constants.TAG, "authResult: " + authToken);
|
||||||
} else {
|
} else {
|
||||||
Log.e(MyTracksConstants.TAG, "No auth result results!!");
|
Log.e(Constants.TAG, "No auth result results!!");
|
||||||
}
|
}
|
||||||
runWhenFinished();
|
runWhenFinished();
|
||||||
return authToken != null;
|
return authToken != null;
|
||||||
@@ -181,7 +181,7 @@ public class ModernAuthManager implements AuthManager {
|
|||||||
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
accountManager.invalidateAuthToken(MyTracksConstants.ACCOUNT_TYPE,
|
accountManager.invalidateAuthToken(Constants.ACCOUNT_TYPE,
|
||||||
authToken);
|
authToken);
|
||||||
MyTracks.getInstance().getAccountChooser().chooseAccount(activity,
|
MyTracks.getInstance().getAccountChooser().chooseAccount(activity,
|
||||||
new AccountChooser.AccountHandler() {
|
new AccountChooser.AccountHandler() {
|
||||||
|
|||||||
@@ -16,8 +16,7 @@
|
|||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracks;
|
import com.google.android.apps.mytracks.MyTracks;
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.MyTracksSettings;
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.io.docs.DocsHelper;
|
import com.google.android.apps.mytracks.io.docs.DocsHelper;
|
||||||
@@ -28,7 +27,7 @@ import com.google.android.maps.mytracks.R;
|
|||||||
import com.google.wireless.gdata.client.GDataClient;
|
import com.google.wireless.gdata.client.GDataClient;
|
||||||
import com.google.wireless.gdata.docs.DocumentsClient;
|
import com.google.wireless.gdata.docs.DocumentsClient;
|
||||||
import com.google.wireless.gdata.docs.SpreadsheetsClient;
|
import com.google.wireless.gdata.docs.SpreadsheetsClient;
|
||||||
import com.google.wireless.gdata.maps.xml.XmlMapsGDataParserFactory;
|
import com.google.wireless.gdata.docs.XmlDocsGDataParserFactory;
|
||||||
import com.google.wireless.gdata.client.GDataServiceClient;
|
import com.google.wireless.gdata.client.GDataServiceClient;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@@ -73,7 +72,7 @@ public class SendToDocs {
|
|||||||
this.trackId = trackId;
|
this.trackId = trackId;
|
||||||
|
|
||||||
SharedPreferences preferences = activity.getSharedPreferences(
|
SharedPreferences preferences = activity.getSharedPreferences(
|
||||||
MyTracksSettings.SETTINGS_NAME, 0);
|
Constants.SETTINGS_NAME, 0);
|
||||||
if (preferences != null) {
|
if (preferences != null) {
|
||||||
metricUnits =
|
metricUnits =
|
||||||
preferences.getBoolean(activity.getString(R.string.metric_units_key),
|
preferences.getBoolean(activity.getString(R.string.metric_units_key),
|
||||||
@@ -82,7 +81,7 @@ public class SendToDocs {
|
|||||||
metricUnits = true;
|
metricUnits = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"Sending to Google Docs: trackId = " + trackId);
|
"Sending to Google Docs: trackId = " + trackId);
|
||||||
handlerThread = new HandlerThread("SendToGoogleDocs");
|
handlerThread = new HandlerThread("SendToGoogleDocs");
|
||||||
handlerThread.start();
|
handlerThread.start();
|
||||||
@@ -99,12 +98,13 @@ public class SendToDocs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doUpload() {
|
private void doUpload() {
|
||||||
|
// TODO
|
||||||
statusMessage = activity.getString(R.string.error_sending_to_fusiontables);
|
statusMessage = activity.getString(R.string.error_sending_to_fusiontables);
|
||||||
success = false;
|
success = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (trackId == -1) {
|
if (trackId == -1) {
|
||||||
Log.w(MyTracksConstants.TAG, "Cannot get track id.");
|
Log.w(Constants.TAG, "Cannot get track id.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,14 +112,14 @@ public class SendToDocs {
|
|||||||
Track track =
|
Track track =
|
||||||
MyTracksProviderUtils.Factory.get(activity).getTrack(trackId);
|
MyTracksProviderUtils.Factory.get(activity).getTrack(trackId);
|
||||||
if (track == null) {
|
if (track == null) {
|
||||||
Log.w(MyTracksConstants.TAG, "Cannot get track.");
|
Log.w(Constants.TAG, "Cannot get track.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transmit track stats via GData feed:
|
// Transmit track stats via GData feed:
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
|
|
||||||
Log.d(MyTracksConstants.TAG, "SendToDocs: Uploading to spreadsheet");
|
Log.d(Constants.TAG, "SendToDocs: Uploading to spreadsheet");
|
||||||
success = uploadToDocs(track);
|
success = uploadToDocs(track);
|
||||||
if (success) {
|
if (success) {
|
||||||
if (createdNewSpreadSheet) {
|
if (createdNewSpreadSheet) {
|
||||||
@@ -132,7 +132,7 @@ public class SendToDocs {
|
|||||||
} else {
|
} else {
|
||||||
statusMessage = activity.getString(R.string.error_sending_to_docs);
|
statusMessage = activity.getString(R.string.error_sending_to_docs);
|
||||||
}
|
}
|
||||||
Log.d(MyTracksConstants.TAG, "SendToDocs: Done.");
|
Log.d(Constants.TAG, "SendToDocs: Done.");
|
||||||
} finally {
|
} finally {
|
||||||
if (onCompletion != null) {
|
if (onCompletion != null) {
|
||||||
activity.runOnUiThread(onCompletion);
|
activity.runOnUiThread(onCompletion);
|
||||||
@@ -173,9 +173,9 @@ public class SendToDocs {
|
|||||||
try {
|
try {
|
||||||
androidClient = GDataClientFactory.getGDataClient(activity);
|
androidClient = GDataClientFactory.getGDataClient(activity);
|
||||||
SpreadsheetsClient gdataClient = new SpreadsheetsClient(androidClient,
|
SpreadsheetsClient gdataClient = new SpreadsheetsClient(androidClient,
|
||||||
new XmlMapsGDataParserFactory(new AndroidXmlParserFactory()));
|
new XmlDocsGDataParserFactory(new AndroidXmlParserFactory()));
|
||||||
trixWrapper.setClient(gdataClient);
|
trixWrapper.setClient(gdataClient);
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"GData connection prepared: " + this.docListAuth);
|
"GData connection prepared: " + this.docListAuth);
|
||||||
String sheetTitle = "My Tracks";
|
String sheetTitle = "My Tracks";
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ public class SendToDocs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DocumentsClient docsGdataClient = new DocumentsClient(androidClient,
|
DocumentsClient docsGdataClient = new DocumentsClient(androidClient,
|
||||||
new XmlMapsGDataParserFactory(new AndroidXmlParserFactory()));
|
new XmlDocsGDataParserFactory(new AndroidXmlParserFactory()));
|
||||||
docListWrapper.setClient(docsGdataClient);
|
docListWrapper.setClient(docsGdataClient);
|
||||||
|
|
||||||
// First try to find the spreadsheet:
|
// First try to find the spreadsheet:
|
||||||
@@ -193,7 +193,7 @@ public class SendToDocs {
|
|||||||
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
||||||
sheetTitle);
|
sheetTitle);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.i(MyTracksConstants.TAG, "Spreadsheet lookup failed.", e);
|
Log.i(Constants.TAG, "Spreadsheet lookup failed.", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,14 +204,14 @@ public class SendToDocs {
|
|||||||
try {
|
try {
|
||||||
Thread.sleep(5000);
|
Thread.sleep(5000);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Sleep interrupted", e);
|
Log.e(Constants.TAG, "Sleep interrupted", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
||||||
sheetTitle);
|
sheetTitle);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.i(MyTracksConstants.TAG, "2nd spreadsheet lookup failed.", e);
|
Log.i(Constants.TAG, "2nd spreadsheet lookup failed.", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,13 +219,13 @@ public class SendToDocs {
|
|||||||
// We were unable to find an existing spreadsheet, so create a new one.
|
// We were unable to find an existing spreadsheet, so create a new one.
|
||||||
MyTracks.getInstance().setProgressValue(70);
|
MyTracks.getInstance().setProgressValue(70);
|
||||||
if (spreadsheetId == null) {
|
if (spreadsheetId == null) {
|
||||||
Log.i(MyTracksConstants.TAG, "Creating new spreadsheet: " + sheetTitle);
|
Log.i(Constants.TAG, "Creating new spreadsheet: " + sheetTitle);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
spreadsheetId = docsHelper.createSpreadsheet(activity, docListWrapper,
|
spreadsheetId = docsHelper.createSpreadsheet(activity, docListWrapper,
|
||||||
sheetTitle);
|
sheetTitle);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.i(MyTracksConstants.TAG, "Failed to create new spreadsheet "
|
Log.i(Constants.TAG, "Failed to create new spreadsheet "
|
||||||
+ sheetTitle, e);
|
+ sheetTitle, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -238,19 +238,19 @@ public class SendToDocs {
|
|||||||
// reported an error. Seems to be a know bug,
|
// reported an error. Seems to be a know bug,
|
||||||
// see http://code.google.com/p/gdata-issues/issues/detail?id=929
|
// see http://code.google.com/p/gdata-issues/issues/detail?id=929
|
||||||
// Try to find the created spreadsheet:
|
// Try to find the created spreadsheet:
|
||||||
Log.w(MyTracksConstants.TAG,
|
Log.w(Constants.TAG,
|
||||||
"Create might have failed. Trying to find created document.");
|
"Create might have failed. Trying to find created document.");
|
||||||
try {
|
try {
|
||||||
Thread.sleep(5000);
|
Thread.sleep(5000);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Sleep interrupted", e);
|
Log.e(Constants.TAG, "Sleep interrupted", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
||||||
sheetTitle);
|
sheetTitle);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.i(MyTracksConstants.TAG, "Failed create-failed lookup", e);
|
Log.i(Constants.TAG, "Failed create-failed lookup", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,19 +260,19 @@ public class SendToDocs {
|
|||||||
try {
|
try {
|
||||||
Thread.sleep(5000);
|
Thread.sleep(5000);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Sleep interrupted", e);
|
Log.e(Constants.TAG, "Sleep interrupted", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
||||||
sheetTitle);
|
sheetTitle);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.i(MyTracksConstants.TAG, "Failed create-failed relookup", e);
|
Log.i(Constants.TAG, "Failed create-failed relookup", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (spreadsheetId == null) {
|
if (spreadsheetId == null) {
|
||||||
Log.i(MyTracksConstants.TAG,
|
Log.i(Constants.TAG,
|
||||||
"Creating new spreadsheet really failed.");
|
"Creating new spreadsheet really failed.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -286,7 +286,7 @@ public class SendToDocs {
|
|||||||
throw new IOException("Worksheet ID lookup returned empty");
|
throw new IOException("Worksheet ID lookup returned empty");
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.i(MyTracksConstants.TAG, "Looking up worksheet id failed.", e);
|
Log.i(Constants.TAG, "Looking up worksheet id failed.", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,9 +294,9 @@ public class SendToDocs {
|
|||||||
|
|
||||||
docsHelper.addTrackRow(activity, trixAuth, spreadsheetId, worksheetId,
|
docsHelper.addTrackRow(activity, trixAuth, spreadsheetId, worksheetId,
|
||||||
track, metricUnits);
|
track, metricUnits);
|
||||||
Log.i(MyTracksConstants.TAG, "Done uploading to docs.");
|
Log.i(Constants.TAG, "Done uploading to docs.");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Unable to upload docs.", e);
|
Log.e(Constants.TAG, "Unable to upload docs.", e);
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
if (androidClient != null) {
|
if (androidClient != null) {
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.MyTracksSettings;
|
|
||||||
import com.google.android.apps.mytracks.ProgressIndicator;
|
import com.google.android.apps.mytracks.ProgressIndicator;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
@@ -25,8 +24,9 @@ import com.google.android.apps.mytracks.io.gdata.GDataWrapper;
|
|||||||
import com.google.android.apps.mytracks.io.gdata.GDataWrapper.QueryFunction;
|
import com.google.android.apps.mytracks.io.gdata.GDataWrapper.QueryFunction;
|
||||||
import com.google.android.apps.mytracks.stats.DoubleBuffer;
|
import com.google.android.apps.mytracks.stats.DoubleBuffer;
|
||||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||||
import com.google.android.apps.mytracks.util.StringUtils;
|
import com.google.android.apps.mytracks.util.StringUtils;
|
||||||
|
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
import com.google.api.client.googleapis.GoogleHeaders;
|
import com.google.api.client.googleapis.GoogleHeaders;
|
||||||
@@ -141,7 +141,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
this.providerUtils = MyTracksProviderUtils.Factory.get(context);
|
this.providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||||
|
|
||||||
GoogleHeaders headers = new GoogleHeaders();
|
GoogleHeaders headers = new GoogleHeaders();
|
||||||
headers.setApplicationName("Google-MyTracks-" + MyTracksUtils.getMyTracksVersion(context));
|
headers.setApplicationName("Google-MyTracks-" + SystemUtils.getMyTracksVersion(context));
|
||||||
headers.gdataVersion = GDATA_VERSION;
|
headers.gdataVersion = GDATA_VERSION;
|
||||||
|
|
||||||
transport = new HttpTransport();
|
transport = new HttpTransport();
|
||||||
@@ -151,7 +151,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Log.d(MyTracksConstants.TAG, "Sending to Fusion tables: trackId = " + trackId);
|
Log.d(Constants.TAG, "Sending to Fusion tables: trackId = " + trackId);
|
||||||
doUpload();
|
doUpload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
statusMessageId = R.string.status_new_fusiontable_has_been_created;
|
statusMessageId = R.string.status_new_fusiontable_has_been_created;
|
||||||
Log.d(MyTracksConstants.TAG, "SendToFusionTables: Done: " + success);
|
Log.d(Constants.TAG, "SendToFusionTables: Done: " + success);
|
||||||
progressIndicator.setProgressValue(PROGRESS_COMPLETE);
|
progressIndicator.setProgressValue(PROGRESS_COMPLETE);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
||||||
@@ -228,14 +228,14 @@ public class SendToFusionTables implements Runnable {
|
|||||||
* @return true in case of success.
|
* @return true in case of success.
|
||||||
*/
|
*/
|
||||||
private boolean createNewTable(Track track) {
|
private boolean createNewTable(Track track) {
|
||||||
Log.d(MyTracksConstants.TAG, "Creating a new fusion table.");
|
Log.d(Constants.TAG, "Creating a new fusion table.");
|
||||||
String query = "CREATE TABLE '" + sqlEscape(track.getName()) +
|
String query = "CREATE TABLE '" + sqlEscape(track.getName()) +
|
||||||
"' (name:STRING,description:STRING,geometry:LOCATION,marker:STRING)";
|
"' (name:STRING,description:STRING,geometry:LOCATION,marker:STRING)";
|
||||||
return runUpdate(query);
|
return runUpdate(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean makeTableUnlisted(String tableId) {
|
private boolean makeTableUnlisted(String tableId) {
|
||||||
Log.d(MyTracksConstants.TAG, "Setting visibility to unlisted.");
|
Log.d(Constants.TAG, "Setting visibility to unlisted.");
|
||||||
String query = "UPDATE TABLE " + tableId + " SET VISIBILITY = UNLISTED";
|
String query = "UPDATE TABLE " + tableId + " SET VISIBILITY = UNLISTED";
|
||||||
return runUpdate(query);
|
return runUpdate(query);
|
||||||
}
|
}
|
||||||
@@ -274,7 +274,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
*/
|
*/
|
||||||
private boolean createNewPoint(String name, String description, Location location,
|
private boolean createNewPoint(String name, String description, Location location,
|
||||||
String marker) {
|
String marker) {
|
||||||
Log.d(MyTracksConstants.TAG, "Creating a new row with a point.");
|
Log.d(Constants.TAG, "Creating a new row with a point.");
|
||||||
String query = "INSERT INTO " + tableId + " (name,description,geometry,marker) VALUES "
|
String query = "INSERT INTO " + tableId + " (name,description,geometry,marker) VALUES "
|
||||||
+ values(name, description, getKmlPoint(location), marker);
|
+ values(name, description, getKmlPoint(location), marker);
|
||||||
return runUpdate(query);
|
return runUpdate(query);
|
||||||
@@ -287,7 +287,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
* @return true in case of success.
|
* @return true in case of success.
|
||||||
*/
|
*/
|
||||||
private boolean createNewLineString(Track track) {
|
private boolean createNewLineString(Track track) {
|
||||||
Log.d(MyTracksConstants.TAG, "Creating a new row with a point.");
|
Log.d(Constants.TAG, "Creating a new row with a point.");
|
||||||
String query = "INSERT INTO " + tableId
|
String query = "INSERT INTO " + tableId
|
||||||
+ " (name,description,geometry) VALUES "
|
+ " (name,description,geometry) VALUES "
|
||||||
+ values(track.getName(), track.getDescription(), getKmlLineString(track));
|
+ values(track.getName(), track.getDescription(), getKmlLineString(track));
|
||||||
@@ -296,7 +296,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
|
|
||||||
private boolean uploadAllTrackPoints(final Track track, String originalDescription) {
|
private boolean uploadAllTrackPoints(final Track track, String originalDescription) {
|
||||||
|
|
||||||
SharedPreferences preferences = context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
SharedPreferences preferences = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||||
boolean metricUnits = true;
|
boolean metricUnits = true;
|
||||||
if (preferences != null) {
|
if (preferences != null) {
|
||||||
metricUnits = preferences.getBoolean(context.getString(R.string.metric_units_key), true);
|
metricUnits = preferences.getBoolean(context.getString(R.string.metric_units_key), true);
|
||||||
@@ -305,7 +305,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
Cursor locationsCursor = providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
|
Cursor locationsCursor = providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
|
||||||
try {
|
try {
|
||||||
if (!locationsCursor.moveToFirst()) {
|
if (!locationsCursor.moveToFirst()) {
|
||||||
Log.w(MyTracksConstants.TAG, "Unable to get any points to upload");
|
Log.w(Constants.TAG, "Unable to get any points to upload");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,14 +318,14 @@ public class SendToFusionTables implements Runnable {
|
|||||||
// Limit the number of elevation readings. Ideally we would want around 250.
|
// Limit the number of elevation readings. Ideally we would want around 250.
|
||||||
int elevationSamplingFrequency =
|
int elevationSamplingFrequency =
|
||||||
Math.max(1, (int) (totalLocations / 250.0));
|
Math.max(1, (int) (totalLocations / 250.0));
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"Using elevation sampling factor: " + elevationSamplingFrequency
|
"Using elevation sampling factor: " + elevationSamplingFrequency
|
||||||
+ " on " + totalLocations);
|
+ " on " + totalLocations);
|
||||||
double totalDistance = 0;
|
double totalDistance = 0;
|
||||||
|
|
||||||
Vector<Double> distances = new Vector<Double>();
|
Vector<Double> distances = new Vector<Double>();
|
||||||
Vector<Double> elevations = new Vector<Double>();
|
Vector<Double> elevations = new Vector<Double>();
|
||||||
DoubleBuffer elevationBuffer = new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
|
DoubleBuffer elevationBuffer = new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
|
||||||
|
|
||||||
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
|
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
|
||||||
Location lastLocation = null;
|
Location lastLocation = null;
|
||||||
@@ -344,7 +344,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add to the elevation profile.
|
// Add to the elevation profile.
|
||||||
if (loc != null && MyTracksUtils.isValidLocation(loc)) {
|
if (loc != null && LocationUtils.isValidLocation(loc)) {
|
||||||
// All points go into the smoothing buffer...
|
// All points go into the smoothing buffer...
|
||||||
elevationBuffer.setNext(metricUnits ? loc.getAltitude()
|
elevationBuffer.setNext(metricUnits ? loc.getAltitude()
|
||||||
: loc.getAltitude() * UnitConversions.M_TO_FT);
|
: loc.getAltitude() * UnitConversions.M_TO_FT);
|
||||||
@@ -447,7 +447,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
|
|
||||||
int numLocations = locations.size();
|
int numLocations = locations.size();
|
||||||
if (numLocations < 2) {
|
if (numLocations < 2) {
|
||||||
Log.d(MyTracksConstants.TAG, "Not preparing/uploading too few points");
|
Log.d(Constants.TAG, "Not preparing/uploading too few points");
|
||||||
totalLocationsUploaded += numLocations;
|
totalLocationsUploaded += numLocations;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -463,16 +463,16 @@ public class SendToFusionTables implements Runnable {
|
|||||||
context.getString(R.string.part), totalSegmentsUploaded));
|
context.getString(R.string.part), totalSegmentsUploaded));
|
||||||
}
|
}
|
||||||
totalSegmentsUploaded++;
|
totalSegmentsUploaded++;
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"SendToFusionTables: Prepared feature for upload w/ "
|
"SendToFusionTables: Prepared feature for upload w/ "
|
||||||
+ splitTrack.getLocations().size() + " points.");
|
+ splitTrack.getLocations().size() + " points.");
|
||||||
|
|
||||||
// Transmit tracks via GData feed:
|
// Transmit tracks via GData feed:
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"SendToFusionTables: Uploading to table " + tableId + " w/ auth " + auth);
|
"SendToFusionTables: Uploading to table " + tableId + " w/ auth " + auth);
|
||||||
if (!uploadTrackPoints(splitTrack)) {
|
if (!uploadTrackPoints(splitTrack)) {
|
||||||
Log.e(MyTracksConstants.TAG, "Uploading failed");
|
Log.e(Constants.TAG, "Uploading failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -518,7 +518,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
// Close up the last segment.
|
// Close up the last segment.
|
||||||
prepareTrackSegment(segment, splitTracks);
|
prepareTrackSegment(segment, splitTracks);
|
||||||
|
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"MyTracksSendToFusionTables: Starting new track segment...");
|
"MyTracksSendToFusionTables: Starting new track segment...");
|
||||||
startNewTrackSegment = false;
|
startNewTrackSegment = false;
|
||||||
segment = new Track();
|
segment = new Track();
|
||||||
@@ -566,12 +566,12 @@ public class SendToFusionTables implements Runnable {
|
|||||||
* Decimate to 2 meter precision. Fusion tables doesn't like too many
|
* Decimate to 2 meter precision. Fusion tables doesn't like too many
|
||||||
* points:
|
* points:
|
||||||
*/
|
*/
|
||||||
MyTracksUtils.decimate(segment, 2.0);
|
LocationUtils.decimate(segment, 2.0);
|
||||||
|
|
||||||
/* If the track still has > 2500 points, split it in pieces: */
|
/* If the track still has > 2500 points, split it in pieces: */
|
||||||
final int maxPoints = 2500;
|
final int maxPoints = 2500;
|
||||||
if (segment.getLocations().size() > maxPoints) {
|
if (segment.getLocations().size() > maxPoints) {
|
||||||
splitTracks.addAll(MyTracksUtils.split(segment, maxPoints));
|
splitTracks.addAll(LocationUtils.split(segment, maxPoints));
|
||||||
} else if (segment.getLocations().size() >= 2) {
|
} else if (segment.getLocations().size() >= 2) {
|
||||||
splitTracks.add(segment);
|
splitTracks.add(segment);
|
||||||
}
|
}
|
||||||
@@ -581,7 +581,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
int numLocations = splitTrack.getLocations().size();
|
int numLocations = splitTrack.getLocations().size();
|
||||||
if (numLocations < 2) {
|
if (numLocations < 2) {
|
||||||
// Need at least two points for a polyline:
|
// Need at least two points for a polyline:
|
||||||
Log.w(MyTracksConstants.TAG, "Not uploading too few points");
|
Log.w(Constants.TAG, "Not uploading too few points");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return createNewLineString(splitTrack);
|
return createNewLineString(splitTrack);
|
||||||
@@ -604,14 +604,14 @@ public class SendToFusionTables implements Runnable {
|
|||||||
try {
|
try {
|
||||||
c = providerUtils.getWaypointsCursor(
|
c = providerUtils.getWaypointsCursor(
|
||||||
track.getId(), 0,
|
track.getId(), 0,
|
||||||
MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS);
|
Constants.MAX_LOADED_WAYPOINTS_POINTS);
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
if (c.moveToFirst()) {
|
if (c.moveToFirst()) {
|
||||||
// This will skip the 1st waypoint (it carries the stats for the
|
// This will skip the 1st waypoint (it carries the stats for the
|
||||||
// last segment).
|
// last segment).
|
||||||
while (c.moveToNext()) {
|
while (c.moveToNext()) {
|
||||||
Waypoint wpt = providerUtils.createWaypoint(c);
|
Waypoint wpt = providerUtils.createWaypoint(c);
|
||||||
Log.d(MyTracksConstants.TAG, "SendToFusionTables: Creating waypoint.");
|
Log.d(Constants.TAG, "SendToFusionTables: Creating waypoint.");
|
||||||
success = createNewPoint(wpt.getName(), wpt.getDescription(), wpt.getLocation(),
|
success = createNewPoint(wpt.getName(), wpt.getDescription(), wpt.getLocation(),
|
||||||
MARKER_TYPE_WAYPOINT);
|
MARKER_TYPE_WAYPOINT);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@@ -621,7 +621,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Log.w(MyTracksConstants.TAG, "SendToFusionTables: upload waypoints failed.");
|
Log.w(Constants.TAG, "SendToFusionTables: upload waypoints failed.");
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -656,7 +656,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
wrapper.setAuthManager(auth);
|
wrapper.setAuthManager(auth);
|
||||||
wrapper.setRetryOnAuthFailure(true);
|
wrapper.setRetryOnAuthFailure(true);
|
||||||
wrapper.setClient(transport);
|
wrapper.setClient(transport);
|
||||||
Log.d(MyTracksConstants.TAG, "GData connection prepared: " + this.auth);
|
Log.d(Constants.TAG, "GData connection prepared: " + this.auth);
|
||||||
wrapper.runQuery(new QueryFunction<HttpTransport>() {
|
wrapper.runQuery(new QueryFunction<HttpTransport>() {
|
||||||
@Override
|
@Override
|
||||||
public void query(HttpTransport client)
|
public void query(HttpTransport client)
|
||||||
@@ -671,7 +671,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
isc.inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql));
|
isc.inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql));
|
||||||
request.content = isc;
|
request.content = isc;
|
||||||
|
|
||||||
Log.d(MyTracksConstants.TAG, "Running update query " + url.toString() + ": " + sql);
|
Log.d(Constants.TAG, "Running update query " + url.toString() + ": " + sql);
|
||||||
HttpResponse response;
|
HttpResponse response;
|
||||||
try {
|
try {
|
||||||
response = request.execute();
|
response = request.execute();
|
||||||
@@ -686,12 +686,12 @@ public class SendToFusionTables implements Runnable {
|
|||||||
String[] lines = s.split(Strings.LINE_SEPARATOR);
|
String[] lines = s.split(Strings.LINE_SEPARATOR);
|
||||||
if (lines[0].equals("tableid")) {
|
if (lines[0].equals("tableid")) {
|
||||||
tableId = lines[1];
|
tableId = lines[1];
|
||||||
Log.d(MyTracksConstants.TAG, "tableId = " + tableId);
|
Log.d(Constants.TAG, "tableId = " + tableId);
|
||||||
} else {
|
} else {
|
||||||
Log.w(MyTracksConstants.TAG, "Unrecognized response: " + lines[0]);
|
Log.w(Constants.TAG, "Unrecognized response: " + lines[0]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d(MyTracksConstants.TAG, "Query failed: " + response.statusMessage + " (" +
|
Log.d(Constants.TAG, "Query failed: " + response.statusMessage + " (" +
|
||||||
response.statusCode + ")");
|
response.statusCode + ")");
|
||||||
throw new GDataWrapper.HttpException(response.statusCode, response.statusMessage);
|
throw new GDataWrapper.HttpException(response.statusCode, response.statusMessage);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,455 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 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.
|
||||||
|
*/
|
||||||
|
package com.google.android.apps.mytracks.io;
|
||||||
|
|
||||||
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
|
import com.google.android.apps.mytracks.Constants;
|
||||||
|
import com.google.android.apps.mytracks.ProgressIndicator;
|
||||||
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
|
import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
|
||||||
|
import com.google.android.apps.mytracks.stats.DoubleBuffer;
|
||||||
|
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||||
|
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||||
|
import com.google.android.apps.mytracks.util.StringUtils;
|
||||||
|
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.Cursor;
|
||||||
|
import android.location.Location;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class used to transmit tracks to Google MyMaps.
|
||||||
|
* A new instance should be used for each upload.
|
||||||
|
*
|
||||||
|
* IMPORTANT: while this code is Apache-licensed, please notice that usage of
|
||||||
|
* the Google Maps servers through this API is only allowed for the My Tracks
|
||||||
|
* application. Other applications looking to upload maps data should look
|
||||||
|
* into using the Fusion Tables API.
|
||||||
|
*
|
||||||
|
* @author Leif Hendrik Wilden
|
||||||
|
*/
|
||||||
|
public class SendToMyMaps implements Runnable {
|
||||||
|
|
||||||
|
public static final String NEW_MAP_ID = "new";
|
||||||
|
private static final int MAX_POINTS_PER_UPLOAD = 2048;
|
||||||
|
|
||||||
|
private final Activity context;
|
||||||
|
private final AuthManager auth;
|
||||||
|
private final long trackId;
|
||||||
|
private final ProgressIndicator progressIndicator;
|
||||||
|
private final OnSendCompletedListener onCompletion;
|
||||||
|
private final StringUtils stringUtils;
|
||||||
|
private final MyTracksProviderUtils providerUtils;
|
||||||
|
private String mapId;
|
||||||
|
|
||||||
|
private MapsFacade mapsClient;
|
||||||
|
|
||||||
|
// Progress status
|
||||||
|
private int totalLocationsRead;
|
||||||
|
private int totalLocationsPrepared;
|
||||||
|
private int totalLocationsUploaded;
|
||||||
|
private int totalLocations;
|
||||||
|
private int totalSegmentsUploaded;
|
||||||
|
|
||||||
|
public interface OnSendCompletedListener {
|
||||||
|
void onSendCompleted(String mapId, boolean success, int statusMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SendToMyMaps(Activity context, String mapId, AuthManager auth,
|
||||||
|
long trackId, ProgressIndicator progressIndicator,
|
||||||
|
OnSendCompletedListener onCompletion) {
|
||||||
|
this.context = context;
|
||||||
|
this.mapId = mapId;
|
||||||
|
this.auth = auth;
|
||||||
|
this.trackId = trackId;
|
||||||
|
this.progressIndicator = progressIndicator;
|
||||||
|
this.onCompletion = onCompletion;
|
||||||
|
this.stringUtils = new StringUtils(context);
|
||||||
|
this.providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Log.d(TAG, "Sending to MyMaps: trackId = " + trackId);
|
||||||
|
doUpload();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doUpload() {
|
||||||
|
int statusMessageId = R.string.error_sending_to_mymap;
|
||||||
|
boolean success = true;
|
||||||
|
try {
|
||||||
|
progressIndicator.setProgressValue(1);
|
||||||
|
progressIndicator.setProgressMessage(
|
||||||
|
R.string.progress_message_reading_track);
|
||||||
|
|
||||||
|
// Get the track meta-data
|
||||||
|
Track track = providerUtils.getTrack(trackId);
|
||||||
|
String originalDescription = track.getDescription();
|
||||||
|
track.setDescription("<p>" + track.getDescription() + "</p><p>"
|
||||||
|
+ stringUtils.generateTrackDescription(track, null, null) + "</p>");
|
||||||
|
|
||||||
|
mapsClient = new MapsFacade(context, auth);
|
||||||
|
|
||||||
|
// Create a new map if necessary:
|
||||||
|
boolean isNewMap = mapId.equals(NEW_MAP_ID);
|
||||||
|
if (isNewMap) {
|
||||||
|
SharedPreferences preferences = context.getSharedPreferences(
|
||||||
|
Constants.SETTINGS_NAME, 0);
|
||||||
|
boolean mapPublic = true;
|
||||||
|
if (preferences != null) {
|
||||||
|
mapPublic = preferences.getBoolean(
|
||||||
|
context.getString(R.string.default_map_public_key), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
progressIndicator.setProgressMessage(
|
||||||
|
R.string.progress_message_creating_map);
|
||||||
|
|
||||||
|
StringBuilder mapIdBuilder = new StringBuilder();
|
||||||
|
success = mapsClient.createNewMap(
|
||||||
|
track.getName(), track.getCategory(), originalDescription, mapPublic, mapIdBuilder);
|
||||||
|
mapId = mapIdBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload all of the segments of the track plus start/end markers
|
||||||
|
if (success) {
|
||||||
|
success = uploadAllTrackPoints(track, originalDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put waypoints.
|
||||||
|
if (success) {
|
||||||
|
Cursor c = providerUtils.getWaypointsCursor(
|
||||||
|
track.getId(), 0,
|
||||||
|
Constants.MAX_LOADED_WAYPOINTS_POINTS);
|
||||||
|
if (c != null) {
|
||||||
|
try {
|
||||||
|
if (c.getCount() > 1 && c.moveToFirst()) {
|
||||||
|
// This will skip the 1st waypoint (it carries the stats for the
|
||||||
|
// last segment).
|
||||||
|
ArrayList<Waypoint> waypoints = new ArrayList<Waypoint>(c.getCount() - 1);
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
Waypoint wpt = providerUtils.createWaypoint(c);
|
||||||
|
waypoints.add(wpt);
|
||||||
|
}
|
||||||
|
|
||||||
|
success = mapsClient.uploadWaypoints(mapId, waypoints);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
Log.w(TAG, "SendToMyMaps: upload waypoints failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
statusMessageId = isNewMap
|
||||||
|
? R.string.status_new_mymap_has_been_created
|
||||||
|
: R.string.status_tracks_have_been_uploaded;
|
||||||
|
}
|
||||||
|
Log.d(TAG, "SendToMyMaps: Done: " + success);
|
||||||
|
progressIndicator.setProgressValue(100);
|
||||||
|
} finally {
|
||||||
|
if (mapsClient != null) {
|
||||||
|
mapsClient.cleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean finalSuccess = success;
|
||||||
|
final int finalStatusMessageId = statusMessageId;
|
||||||
|
context.runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (onCompletion != null) {
|
||||||
|
onCompletion.onSendCompleted(
|
||||||
|
mapId, finalSuccess, finalStatusMessageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean uploadAllTrackPoints(
|
||||||
|
final Track track, String originalDescription) {
|
||||||
|
SharedPreferences preferences = context.getSharedPreferences(
|
||||||
|
Constants.SETTINGS_NAME, 0);
|
||||||
|
boolean metricUnits = true;
|
||||||
|
if (preferences != null) {
|
||||||
|
metricUnits =
|
||||||
|
preferences.getBoolean(context.getString(R.string.metric_units_key),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor locationsCursor =
|
||||||
|
providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
|
||||||
|
try {
|
||||||
|
if (!locationsCursor.moveToFirst()) {
|
||||||
|
Log.w(TAG, "Unable to get any points to upload");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
totalLocationsRead = 0;
|
||||||
|
totalLocationsPrepared = 0;
|
||||||
|
totalLocationsUploaded = 0;
|
||||||
|
totalLocations = locationsCursor.getCount();
|
||||||
|
totalSegmentsUploaded = 0;
|
||||||
|
|
||||||
|
// Limit the number of elevation readings. Ideally we would want around 250.
|
||||||
|
int elevationSamplingFrequency =
|
||||||
|
Math.max(1, (int) (totalLocations / 250.0));
|
||||||
|
Log.d(TAG,
|
||||||
|
"Using elevation sampling factor: " + elevationSamplingFrequency
|
||||||
|
+ " on " + totalLocations);
|
||||||
|
double totalDistance = 0;
|
||||||
|
|
||||||
|
Vector<Double> distances = new Vector<Double>();
|
||||||
|
Vector<Double> elevations = new Vector<Double>();
|
||||||
|
DoubleBuffer elevationBuffer =
|
||||||
|
new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
|
||||||
|
|
||||||
|
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
|
||||||
|
progressIndicator.setProgressMessage(
|
||||||
|
R.string.progress_message_reading_track);
|
||||||
|
Location lastLocation = null;
|
||||||
|
do {
|
||||||
|
if (totalLocationsRead % 100 == 0) {
|
||||||
|
updateProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
Location loc = providerUtils.createLocation(locationsCursor);
|
||||||
|
locations.add(loc);
|
||||||
|
|
||||||
|
if (totalLocationsRead == 0) {
|
||||||
|
// Put a marker at the first point of the first valid segment:
|
||||||
|
mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(), loc, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to the elevation profile.
|
||||||
|
if (loc != null && LocationUtils.isValidLocation(loc)) {
|
||||||
|
// All points go into the smoothing buffer...
|
||||||
|
elevationBuffer.setNext(metricUnits ? loc.getAltitude()
|
||||||
|
: loc.getAltitude() * UnitConversions.M_TO_FT);
|
||||||
|
if (lastLocation != null) {
|
||||||
|
double dist = lastLocation.distanceTo(loc);
|
||||||
|
totalDistance += dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...but only a few points are really used to keep the url short.
|
||||||
|
if (totalLocationsRead % elevationSamplingFrequency == 0) {
|
||||||
|
distances.add(totalDistance);
|
||||||
|
elevations.add(elevationBuffer.getAverage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the location was not valid, it's a segment split, so make sure the
|
||||||
|
// distance between the previous segment and the new one is not accounted
|
||||||
|
// for in the next iteration.
|
||||||
|
lastLocation = loc;
|
||||||
|
|
||||||
|
// Every now and then, upload the accumulated points
|
||||||
|
if (totalLocationsRead % MAX_POINTS_PER_UPLOAD
|
||||||
|
== MAX_POINTS_PER_UPLOAD - 1) {
|
||||||
|
if (!prepareAndUploadPoints(track, locations)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
totalLocationsRead++;
|
||||||
|
} while (locationsCursor.moveToNext());
|
||||||
|
|
||||||
|
// Do a final upload with what's left
|
||||||
|
if (!prepareAndUploadPoints(track, locations)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put an end marker at the last point of the last valid segment:
|
||||||
|
if (lastLocation != null) {
|
||||||
|
track.setDescription("<p>" + originalDescription + "</p><p>"
|
||||||
|
+ stringUtils.generateTrackDescription(
|
||||||
|
track, distances, elevations)
|
||||||
|
+ "</p>");
|
||||||
|
return mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(),
|
||||||
|
lastLocation, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} finally {
|
||||||
|
locationsCursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean prepareAndUploadPoints(Track track, List<Location> locations) {
|
||||||
|
progressIndicator.setProgressMessage(
|
||||||
|
R.string.progress_message_preparing_track);
|
||||||
|
updateProgress();
|
||||||
|
|
||||||
|
int numLocations = locations.size();
|
||||||
|
if (numLocations < 2) {
|
||||||
|
Log.d(TAG, "Not preparing/uploading too few points");
|
||||||
|
totalLocationsUploaded += numLocations;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare/pre-process the points
|
||||||
|
ArrayList<Track> splitTracks = prepareLocations(track, locations);
|
||||||
|
|
||||||
|
// Start uploading them
|
||||||
|
progressIndicator.setProgressMessage(
|
||||||
|
R.string.progress_message_sending_mymaps);
|
||||||
|
for (Track splitTrack : splitTracks) {
|
||||||
|
if (totalSegmentsUploaded > 1) {
|
||||||
|
splitTrack.setName(splitTrack.getName() + " "
|
||||||
|
+ String.format(
|
||||||
|
context.getString(R.string.part), totalSegmentsUploaded));
|
||||||
|
}
|
||||||
|
totalSegmentsUploaded++;
|
||||||
|
Log.d(TAG,
|
||||||
|
"SendToMyMaps: Prepared feature for upload w/ "
|
||||||
|
+ splitTrack.getLocations().size() + " points.");
|
||||||
|
|
||||||
|
// Transmit tracks via GData feed:
|
||||||
|
// -------------------------------
|
||||||
|
Log.d(TAG,
|
||||||
|
"SendToMyMaps: Uploading to map " + mapId + " w/ auth " + auth);
|
||||||
|
if (!mapsClient.uploadTrackPoints(mapId, splitTrack.getName(), splitTrack.getLocations())) {
|
||||||
|
Log.e(TAG, "Uploading failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
locations.clear();
|
||||||
|
totalLocationsUploaded += numLocations;
|
||||||
|
updateProgress();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares a buffer of locations for transmission to google maps.
|
||||||
|
*
|
||||||
|
* @param track the original track with meta data
|
||||||
|
* @param buffer a buffer of locations on the track
|
||||||
|
* @return an array of tracks each with a sub section of the points in the
|
||||||
|
* original buffer
|
||||||
|
*/
|
||||||
|
private ArrayList<Track> prepareLocations(
|
||||||
|
Track track, Iterable<Location> locations) {
|
||||||
|
ArrayList<Track> splitTracks = new ArrayList<Track>();
|
||||||
|
|
||||||
|
// Create segments from each full track:
|
||||||
|
Track segment = new Track();
|
||||||
|
TripStatistics segmentStats = segment.getStatistics();
|
||||||
|
TripStatistics trackStats = track.getStatistics();
|
||||||
|
segment.setId(track.getId());
|
||||||
|
segment.setName(track.getName());
|
||||||
|
segment.setDescription(/* track.getDescription() */ "");
|
||||||
|
segment.setCategory(track.getCategory());
|
||||||
|
segmentStats.setStartTime(trackStats.getStartTime());
|
||||||
|
segmentStats.setStopTime(trackStats.getStopTime());
|
||||||
|
boolean startNewTrackSegment = false;
|
||||||
|
for (Location loc : locations) {
|
||||||
|
if (totalLocationsPrepared % 100 == 0) {
|
||||||
|
updateProgress();
|
||||||
|
}
|
||||||
|
if (loc.getLatitude() > 90) {
|
||||||
|
startNewTrackSegment = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startNewTrackSegment) {
|
||||||
|
// Close up the last segment.
|
||||||
|
prepareTrackSegment(segment, splitTracks);
|
||||||
|
|
||||||
|
Log.d(TAG,
|
||||||
|
"MyTracksSendToMyMaps: Starting new track segment...");
|
||||||
|
startNewTrackSegment = false;
|
||||||
|
segment = new Track();
|
||||||
|
segment.setId(track.getId());
|
||||||
|
segment.setName(track.getName());
|
||||||
|
segment.setDescription(/* track.getDescription() */ "");
|
||||||
|
segment.setCategory(track.getCategory());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loc.getLatitude() <= 90) {
|
||||||
|
segment.addLocation(loc);
|
||||||
|
if (segmentStats.getStartTime() < 0) {
|
||||||
|
segmentStats.setStartTime(loc.getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalLocationsPrepared++;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareTrackSegment(segment, splitTracks);
|
||||||
|
|
||||||
|
return splitTracks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares a track segment for sending to google maps.
|
||||||
|
* The main steps are:
|
||||||
|
* - correcting end time
|
||||||
|
* - decimating locations
|
||||||
|
* - splitting into smaller tracks.
|
||||||
|
*
|
||||||
|
* The final track pieces will be put in the array list splitTracks.
|
||||||
|
*
|
||||||
|
* @param segment the original segment of the track
|
||||||
|
* @param splitTracks an array of smaller track segments
|
||||||
|
*/
|
||||||
|
private void prepareTrackSegment(
|
||||||
|
Track segment, ArrayList<Track> splitTracks) {
|
||||||
|
TripStatistics segmentStats = segment.getStatistics();
|
||||||
|
if (segmentStats.getStopTime() < 0
|
||||||
|
&& segment.getLocations().size() > 0) {
|
||||||
|
segmentStats.setStopTime(segment.getLocations().size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decimate to 2 meter precision. Mapshop doesn't like too many
|
||||||
|
* points:
|
||||||
|
*/
|
||||||
|
LocationUtils.decimate(segment, 2.0);
|
||||||
|
|
||||||
|
/* It the track still has > 500 points, split it in pieces: */
|
||||||
|
if (segment.getLocations().size() > 500) {
|
||||||
|
splitTracks.addAll(LocationUtils.split(segment, 500));
|
||||||
|
} else if (segment.getLocations().size() >= 2) {
|
||||||
|
splitTracks.add(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current upload progress.
|
||||||
|
*/
|
||||||
|
private void updateProgress() {
|
||||||
|
// The percent of the total that represents the completed part of this
|
||||||
|
// segment.
|
||||||
|
int totalPercentage =
|
||||||
|
(totalLocationsRead + totalLocationsPrepared + totalLocationsUploaded)
|
||||||
|
/ (totalLocations * 3);
|
||||||
|
totalPercentage = Math.min(99, totalPercentage);
|
||||||
|
progressIndicator.setProgressValue(totalPercentage);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
package com.google.android.apps.mytracks.io.backup;
|
package com.google.android.apps.mytracks.io.backup;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracks;
|
import com.google.android.apps.mytracks.MyTracks;
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.util.FileUtils;
|
import com.google.android.apps.mytracks.util.FileUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ public class BackupActivityHelper {
|
|||||||
backup.writeToDefaultFile();
|
backup.writeToDefaultFile();
|
||||||
showToast(R.string.io_write_finished);
|
showToast(R.string.io_write_finished);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Failed to write backup", e);
|
Log.e(Constants.TAG, "Failed to write backup", e);
|
||||||
showToast(R.string.io_write_failed);
|
showToast(R.string.io_write_failed);
|
||||||
} finally {
|
} finally {
|
||||||
dismissDialog(progressDialog);
|
dismissDialog(progressDialog);
|
||||||
@@ -199,7 +199,7 @@ public class BackupActivityHelper {
|
|||||||
backup.restoreFromDate(date);
|
backup.restoreFromDate(date);
|
||||||
showToast(R.string.io_read_finished);
|
showToast(R.string.io_read_finished);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Failed to restore backup", e);
|
Log.e(Constants.TAG, "Failed to restore backup", e);
|
||||||
showToast(R.string.io_read_failed);
|
showToast(R.string.io_read_failed);
|
||||||
} finally {
|
} finally {
|
||||||
dismissDialog(progressDialog);
|
dismissDialog(progressDialog);
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io.backup;
|
package com.google.android.apps.mytracks.io.backup;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.MyTracksSettings;
|
|
||||||
import com.google.android.apps.mytracks.content.TrackPointsColumns;
|
import com.google.android.apps.mytracks.content.TrackPointsColumns;
|
||||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||||
import com.google.android.apps.mytracks.content.WaypointsColumns;
|
import com.google.android.apps.mytracks.content.WaypointsColumns;
|
||||||
@@ -88,7 +87,7 @@ class ExternalFileBackup {
|
|||||||
private File getBackupsDirectory(boolean create) {
|
private File getBackupsDirectory(boolean create) {
|
||||||
String dirName = fileUtils.buildExternalDirectoryPath(BACKUPS_SUBDIR);
|
String dirName = fileUtils.buildExternalDirectoryPath(BACKUPS_SUBDIR);
|
||||||
final File dir = new File(dirName);
|
final File dir = new File(dirName);
|
||||||
Log.d(MyTracksConstants.TAG, "Dir: " + dir.getAbsolutePath());
|
Log.d(Constants.TAG, "Dir: " + dir.getAbsolutePath());
|
||||||
if (create) {
|
if (create) {
|
||||||
// Try to create - if that fails, return null
|
// Try to create - if that fails, return null
|
||||||
return fileUtils.ensureDirectoryExists(dir) ? dir : null;
|
return fileUtils.ensureDirectoryExists(dir) ? dir : null;
|
||||||
@@ -147,7 +146,7 @@ class ExternalFileBackup {
|
|||||||
* Synchronously writes a backup to the given file.
|
* Synchronously writes a backup to the given file.
|
||||||
*/
|
*/
|
||||||
private void writeToFile(File outputFile) throws IOException {
|
private void writeToFile(File outputFile) throws IOException {
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"Writing backup to file " + outputFile.getAbsolutePath());
|
"Writing backup to file " + outputFile.getAbsolutePath());
|
||||||
|
|
||||||
// Create all the auxiliary classes that will do the writing
|
// Create all the auxiliary classes that will do the writing
|
||||||
@@ -201,7 +200,7 @@ class ExternalFileBackup {
|
|||||||
|
|
||||||
// Dump preferences
|
// Dump preferences
|
||||||
SharedPreferences preferences =
|
SharedPreferences preferences =
|
||||||
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||||
preferencesHelper.exportPreferences(preferences, outWriter);
|
preferencesHelper.exportPreferences(preferences, outWriter);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// We tried to delete the partially created file, but do nothing
|
// We tried to delete the partially created file, but do nothing
|
||||||
@@ -219,7 +218,7 @@ class ExternalFileBackup {
|
|||||||
* Synchronously restores the backup from the given file.
|
* Synchronously restores the backup from the given file.
|
||||||
*/
|
*/
|
||||||
private void restoreFromFile(File inputFile) throws IOException {
|
private void restoreFromFile(File inputFile) throws IOException {
|
||||||
Log.d(MyTracksConstants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"Restoring from file " + inputFile.getAbsolutePath());
|
"Restoring from file " + inputFile.getAbsolutePath());
|
||||||
|
|
||||||
PreferenceBackupHelper preferencesHelper = new PreferenceBackupHelper();
|
PreferenceBackupHelper preferencesHelper = new PreferenceBackupHelper();
|
||||||
@@ -253,7 +252,7 @@ class ExternalFileBackup {
|
|||||||
|
|
||||||
// Restore preferences
|
// Restore preferences
|
||||||
SharedPreferences preferences =
|
SharedPreferences preferences =
|
||||||
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||||
preferencesHelper.importPreferences(reader, preferences);
|
preferencesHelper.importPreferences(reader, preferences);
|
||||||
} finally {
|
} finally {
|
||||||
compressedStream.close();
|
compressedStream.close();
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io.backup;
|
package com.google.android.apps.mytracks.io.backup;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.MyTracksSettings;
|
|
||||||
|
|
||||||
import android.app.backup.BackupAgent;
|
import android.app.backup.BackupAgent;
|
||||||
import android.app.backup.BackupDataInput;
|
import android.app.backup.BackupDataInput;
|
||||||
@@ -40,12 +39,12 @@ public class MyTracksBackupAgent extends BackupAgent {
|
|||||||
@Override
|
@Override
|
||||||
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||||
ParcelFileDescriptor newState) throws IOException {
|
ParcelFileDescriptor newState) throws IOException {
|
||||||
Log.i(MyTracksConstants.TAG, "Performing backup");
|
Log.i(Constants.TAG, "Performing backup");
|
||||||
SharedPreferences preferences = this.getSharedPreferences(
|
SharedPreferences preferences = this.getSharedPreferences(
|
||||||
MyTracksSettings.SETTINGS_NAME, 0);
|
Constants.SETTINGS_NAME, 0);
|
||||||
|
|
||||||
backupPreferences(data, preferences);
|
backupPreferences(data, preferences);
|
||||||
Log.i(MyTracksConstants.TAG, "Backup complete");
|
Log.i(Constants.TAG, "Backup complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void backupPreferences(BackupDataOutput data,
|
private void backupPreferences(BackupDataOutput data,
|
||||||
@@ -63,18 +62,18 @@ public class MyTracksBackupAgent extends BackupAgent {
|
|||||||
@Override
|
@Override
|
||||||
public void onRestore(BackupDataInput data, int appVersionCode,
|
public void onRestore(BackupDataInput data, int appVersionCode,
|
||||||
ParcelFileDescriptor newState) throws IOException {
|
ParcelFileDescriptor newState) throws IOException {
|
||||||
Log.i(MyTracksConstants.TAG, "Restoring from backup");
|
Log.i(Constants.TAG, "Restoring from backup");
|
||||||
while (data.readNextHeader()) {
|
while (data.readNextHeader()) {
|
||||||
String key = data.getKey();
|
String key = data.getKey();
|
||||||
Log.d(MyTracksConstants.TAG, "Restoring entity " + key);
|
Log.d(Constants.TAG, "Restoring entity " + key);
|
||||||
if (key.equals(PREFERENCES_ENTITY)) {
|
if (key.equals(PREFERENCES_ENTITY)) {
|
||||||
restorePreferences(data);
|
restorePreferences(data);
|
||||||
} else {
|
} else {
|
||||||
Log.e(MyTracksConstants.TAG, "Found unknown backup entity: " + key);
|
Log.e(Constants.TAG, "Found unknown backup entity: " + key);
|
||||||
data.skipEntityData();
|
data.skipEntityData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.i(MyTracksConstants.TAG, "Done restoring from backup");
|
Log.i(Constants.TAG, "Done restoring from backup");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,7 +91,7 @@ public class MyTracksBackupAgent extends BackupAgent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SharedPreferences preferences = this.getSharedPreferences(
|
SharedPreferences preferences = this.getSharedPreferences(
|
||||||
MyTracksSettings.SETTINGS_NAME, 0);
|
Constants.SETTINGS_NAME, 0);
|
||||||
PreferenceBackupHelper importer = createPreferenceBackupHelper();
|
PreferenceBackupHelper importer = createPreferenceBackupHelper();
|
||||||
importer.importPreferences(dataBuffer, preferences);
|
importer.importPreferences(dataBuffer, preferences);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io.docs;
|
package com.google.android.apps.mytracks.io.docs;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.io.AuthManager;
|
import com.google.android.apps.mytracks.io.AuthManager;
|
||||||
import com.google.android.apps.mytracks.io.gdata.GDataWrapper;
|
import com.google.android.apps.mytracks.io.gdata.GDataWrapper;
|
||||||
@@ -144,7 +144,7 @@ public class DocsHelper {
|
|||||||
|
|
||||||
String id = result.substring(
|
String id = result.substring(
|
||||||
idStringStart + DOCS_SPREADSHEET_URL.length(), idTagCloseIndex);
|
idStringStart + DOCS_SPREADSHEET_URL.length(), idTagCloseIndex);
|
||||||
Log.i(MyTracksConstants.TAG, "Created new spreadsheet: " + id);
|
Log.i(Constants.TAG, "Created new spreadsheet: " + id);
|
||||||
idSaver.set(id);
|
idSaver.set(id);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ public class DocsHelper {
|
|||||||
while (listParser.hasMoreData()) {
|
while (listParser.hasMoreData()) {
|
||||||
Entry entry = listParser.readNextEntry(null);
|
Entry entry = listParser.readNextEntry(null);
|
||||||
String entryTitle = entry.getTitle();
|
String entryTitle = entry.getTitle();
|
||||||
Log.i(MyTracksConstants.TAG, "Found docs entry: " + entryTitle);
|
Log.i(Constants.TAG, "Found docs entry: " + entryTitle);
|
||||||
if (entryTitle.equals(title)) {
|
if (entryTitle.equals(title)) {
|
||||||
String entryId = entry.getId();
|
String entryId = entry.getId();
|
||||||
int lastSlash = entryId.lastIndexOf('/');
|
int lastSlash = entryId.lastIndexOf('/');
|
||||||
@@ -233,7 +233,7 @@ public class DocsHelper {
|
|||||||
trixWrapper.getAuthManager().getAuthToken());
|
trixWrapper.getAuthManager().getAuthToken());
|
||||||
sheetParser.init();
|
sheetParser.init();
|
||||||
if (!sheetParser.hasMoreData()) {
|
if (!sheetParser.hasMoreData()) {
|
||||||
Log.i(MyTracksConstants.TAG, "Found no worksheets");
|
Log.i(Constants.TAG, "Found no worksheets");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +308,7 @@ public class DocsHelper {
|
|||||||
|
|
||||||
if (track.getMapId().length() > 0) {
|
if (track.getMapId().length() > 0) {
|
||||||
tagBuilder.append("map", String.format("%s?msa=0&msid=%s",
|
tagBuilder.append("map", String.format("%s?msa=0&msid=%s",
|
||||||
MyTracksConstants.MAPSHOP_BASE_URL, track.getMapId()));
|
Constants.MAPSHOP_BASE_URL, track.getMapId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String postText = new StringBuilder()
|
String postText = new StringBuilder()
|
||||||
@@ -319,14 +319,14 @@ public class DocsHelper {
|
|||||||
.append("</entry>")
|
.append("</entry>")
|
||||||
.toString();
|
.toString();
|
||||||
|
|
||||||
Log.i(MyTracksConstants.TAG,
|
Log.i(Constants.TAG,
|
||||||
"Inserting at: " + spreadsheetId + " => " + worksheetUri);
|
"Inserting at: " + spreadsheetId + " => " + worksheetUri);
|
||||||
|
|
||||||
Log.i(MyTracksConstants.TAG, postText);
|
Log.i(Constants.TAG, postText);
|
||||||
|
|
||||||
writeRowData(trixAuth, worksheetUri, postText);
|
writeRowData(trixAuth, worksheetUri, postText);
|
||||||
|
|
||||||
Log.i(MyTracksConstants.TAG, "Post finished.");
|
Log.i(Constants.TAG, "Post finished.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -358,7 +358,7 @@ public class DocsHelper {
|
|||||||
String line;
|
String line;
|
||||||
while ((line = rd.readLine()) != null) {
|
while ((line = rd.readLine()) != null) {
|
||||||
// Process line.
|
// Process line.
|
||||||
Log.i(MyTracksConstants.TAG, "r: " + line);
|
Log.i(Constants.TAG, "r: " + line);
|
||||||
}
|
}
|
||||||
wr.close();
|
wr.close();
|
||||||
rd.close();
|
rd.close();
|
||||||
|
|||||||
+2
-2
@@ -13,11 +13,11 @@
|
|||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io.file;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
|
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
|
||||||
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
|
|
||||||
+6
-6
@@ -13,13 +13,13 @@
|
|||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io.file;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
|
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
|
||||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||||
import com.google.android.apps.mytracks.util.StringUtils;
|
import com.google.android.apps.mytracks.util.StringUtils;
|
||||||
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
@@ -174,7 +174,7 @@ public class GpxImporter extends DefaultHandler {
|
|||||||
parser.parse(is, handler);
|
parser.parse(is, handler);
|
||||||
|
|
||||||
long end = System.currentTimeMillis();
|
long end = System.currentTimeMillis();
|
||||||
Log.d(MyTracksConstants.TAG, "Total import time: " + (end - start) + "ms");
|
Log.d(Constants.TAG, "Total import time: " + (end - start) + "ms");
|
||||||
|
|
||||||
trackIds = handler.getImportedTrackIds();
|
trackIds = handler.getImportedTrackIds();
|
||||||
} finally {
|
} finally {
|
||||||
@@ -362,7 +362,7 @@ public class GpxImporter extends DefaultHandler {
|
|||||||
* @throws SAXException - thrown if track point is invalid
|
* @throws SAXException - thrown if track point is invalid
|
||||||
*/
|
*/
|
||||||
private void onTrackPointElementEnd() throws SAXException {
|
private void onTrackPointElementEnd() throws SAXException {
|
||||||
if (MyTracksUtils.isValidLocation(location)) {
|
if (LocationUtils.isValidLocation(location)) {
|
||||||
if (statsBuilder == null) {
|
if (statsBuilder == null) {
|
||||||
// first point did not have a time, start stats builder without it
|
// first point did not have a time, start stats builder without it
|
||||||
statsBuilder = new TripStatisticsBuilder(0);
|
statsBuilder = new TripStatisticsBuilder(0);
|
||||||
@@ -462,7 +462,7 @@ public class GpxImporter extends DefaultHandler {
|
|||||||
|
|
||||||
// check for negative time change
|
// check for negative time change
|
||||||
if (timeDifference < 0) {
|
if (timeDifference < 0) {
|
||||||
Log.w(MyTracksConstants.TAG, "Found negative time change.");
|
Log.w(Constants.TAG, "Found negative time change.");
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// We don't have a speed and bearing in GPX, make something up from
|
// We don't have a speed and bearing in GPX, make something up from
|
||||||
+30
-18
@@ -13,11 +13,11 @@
|
|||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io.file;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
|
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
|
||||||
import com.google.android.apps.mytracks.util.StringUtils;
|
import com.google.android.apps.mytracks.util.StringUtils;
|
||||||
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
@@ -25,9 +25,10 @@ import android.location.Location;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.text.NumberFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,22 +37,33 @@ import java.util.TimeZone;
|
|||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
*/
|
*/
|
||||||
public class GpxTrackWriter implements TrackFormatWriter {
|
public class GpxTrackWriter implements TrackFormatWriter {
|
||||||
|
private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
|
||||||
|
|
||||||
private static final int LATLONG_FORMAT = Location.FORMAT_DEGREES;
|
private final NumberFormat elevationFormatter;
|
||||||
private static final DecimalFormat ELEVATION_FORMATTER =
|
private final NumberFormat coordinateFormatter;
|
||||||
new DecimalFormat("#.#");
|
private final SimpleDateFormat timestampFormatter;
|
||||||
private static final SimpleDateFormat TIMESTAMP_FORMATTER =
|
|
||||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
|
||||||
static {
|
|
||||||
TIMESTAMP_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private PrintWriter pw = null;
|
private PrintWriter pw = null;
|
||||||
private Track track;
|
private Track track;
|
||||||
|
|
||||||
|
public GpxTrackWriter() {
|
||||||
|
// GPX readers expect to see fractional numbers with US-style punctuation.
|
||||||
|
// That is, they want periods for decimal points, rather than commas.
|
||||||
|
elevationFormatter = NumberFormat.getInstance(Locale.US);
|
||||||
|
elevationFormatter.setMaximumFractionDigits(1);
|
||||||
|
elevationFormatter.setGroupingUsed(false);
|
||||||
|
|
||||||
|
coordinateFormatter = NumberFormat.getInstance(Locale.US);
|
||||||
|
coordinateFormatter.setMaximumFractionDigits(5);
|
||||||
|
coordinateFormatter.setMaximumIntegerDigits(3);
|
||||||
|
coordinateFormatter.setGroupingUsed(false);
|
||||||
|
|
||||||
|
timestampFormatter = new SimpleDateFormat(TIMESTAMP_FORMAT);
|
||||||
|
timestampFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
|
}
|
||||||
|
|
||||||
private String formatLocation(Location l) {
|
private String formatLocation(Location l) {
|
||||||
return "lat=\"" + Location.convert(l.getLatitude(), LATLONG_FORMAT)
|
return "lat=\"" + coordinateFormatter.format(l.getLatitude())
|
||||||
+ "\" lon=\"" + Location.convert(l.getLongitude(), LATLONG_FORMAT) + "\"";
|
+ "\" lon=\"" + coordinateFormatter.format(l.getLongitude()) + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -129,8 +141,8 @@ public class GpxTrackWriter implements TrackFormatWriter {
|
|||||||
if (pw != null) {
|
if (pw != null) {
|
||||||
pw.println("<trkpt " + formatLocation(l) + ">");
|
pw.println("<trkpt " + formatLocation(l) + ">");
|
||||||
Date d = new Date(l.getTime());
|
Date d = new Date(l.getTime());
|
||||||
pw.println("<ele>" + ELEVATION_FORMATTER.format(l.getAltitude()) + "</ele>");
|
pw.println("<ele>" + elevationFormatter.format(l.getAltitude()) + "</ele>");
|
||||||
pw.println("<time>" + TIMESTAMP_FORMATTER.format(d) + "</time>");
|
pw.println("<time>" + timestampFormatter.format(d) + "</time>");
|
||||||
pw.println("</trkpt>");
|
pw.println("</trkpt>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,8 +161,8 @@ public class GpxTrackWriter implements TrackFormatWriter {
|
|||||||
Location l = waypoint.getLocation();
|
Location l = waypoint.getLocation();
|
||||||
if (l != null) {
|
if (l != null) {
|
||||||
pw.println("<wpt " + formatLocation(l) + ">");
|
pw.println("<wpt " + formatLocation(l) + ">");
|
||||||
pw.println("<ele>" + ELEVATION_FORMATTER.format(l.getAltitude()) + "</ele>");
|
pw.println("<ele>" + elevationFormatter.format(l.getAltitude()) + "</ele>");
|
||||||
pw.println("<time>" + TIMESTAMP_FORMATTER.format(l.getTime()) + "</time>");
|
pw.println("<time>" + timestampFormatter.format(l.getTime()) + "</time>");
|
||||||
pw.println("<name>" + StringUtils.stringAsCData(waypoint.getName())
|
pw.println("<name>" + StringUtils.stringAsCData(waypoint.getName())
|
||||||
+ "</name>");
|
+ "</name>");
|
||||||
pw.println("<desc>"
|
pw.println("<desc>"
|
||||||
+2
-2
@@ -13,11 +13,11 @@
|
|||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io.file;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
|
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
|
||||||
import com.google.android.apps.mytracks.util.StringUtils;
|
import com.google.android.apps.mytracks.util.StringUtils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
+83
-26
@@ -13,15 +13,17 @@
|
|||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io.file;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||||
import com.google.android.apps.mytracks.content.Sensor;
|
import com.google.android.apps.mytracks.content.Sensor;
|
||||||
|
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
|
||||||
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
|
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
@@ -30,6 +32,7 @@ import java.io.PrintWriter;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,20 +40,35 @@ import java.util.TimeZone;
|
|||||||
* As defined by:
|
* As defined by:
|
||||||
* http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2
|
* http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2
|
||||||
*
|
*
|
||||||
|
* The TCX file written by this class has been verified as compatible with
|
||||||
|
* Garmin Training Center 3.5.3.
|
||||||
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
*/
|
*/
|
||||||
public class TcxTrackWriter implements TrackFormatWriter {
|
public class TcxTrackWriter implements TrackFormatWriter {
|
||||||
|
protected static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
|
||||||
|
|
||||||
|
// These are the only sports allowed by the TCX v2 specification for fields
|
||||||
|
// of type Sport_t.
|
||||||
|
private static final String TCX_SPORT_BIKING = "Biking";
|
||||||
|
private static final String TCX_SPORT_RUNNING = "Running";
|
||||||
|
private static final String TCX_SPORT_OTHER = "Other";
|
||||||
|
|
||||||
|
// Values for fields of type Build_t/Type.
|
||||||
|
private static final String TCX_TYPE_RELEASE = "Release";
|
||||||
|
private static final String TCX_TYPE_INTERNAL = "Internal";
|
||||||
|
|
||||||
|
private final SimpleDateFormat timestampFormatter;
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
private PrintWriter pw = null;
|
private PrintWriter pw = null;
|
||||||
private Track track;
|
private Track track;
|
||||||
|
|
||||||
static final SimpleDateFormat TIMESTAMP_FORMAT =
|
public TcxTrackWriter(Context context) {
|
||||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
this.context = context;
|
||||||
static {
|
|
||||||
TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public TcxTrackWriter() {
|
timestampFormatter = new SimpleDateFormat(TIMESTAMP_FORMAT);
|
||||||
|
timestampFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -93,16 +111,13 @@ public class TcxTrackWriter implements TrackFormatWriter {
|
|||||||
if (pw == null) {
|
if (pw == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String startTime = timestampFormatter.format(track.getStatistics().getStartTime());
|
||||||
|
|
||||||
pw.println(" <Activities>");
|
pw.println(" <Activities>");
|
||||||
pw.print(" <Activity Sport=\"");
|
pw.format(" <Activity Sport=\"%s\">\n", categoryToTcxSport(track.getCategory()));
|
||||||
if (track.getCategory() != null) {
|
pw.format(" <Id>%s</Id>\n", startTime);
|
||||||
pw.print(track.getCategory());
|
pw.format(" <Lap StartTime=\"%s\">\n", startTime);
|
||||||
}
|
|
||||||
pw.println("\">");
|
|
||||||
pw.print(" <Id>");
|
|
||||||
pw.print(TIMESTAMP_FORMAT.format(track.getStatistics().getStartTime()));
|
|
||||||
pw.println("</Id>");
|
|
||||||
pw.println(" <Lap>");
|
|
||||||
pw.print(" <TotalTimeSeconds>");
|
pw.print(" <TotalTimeSeconds>");
|
||||||
pw.print(track.getStatistics().getTotalTime() / 1000);
|
pw.print(track.getStatistics().getTotalTime() / 1000);
|
||||||
pw.println("</TotalTimeSeconds>");
|
pw.println("</TotalTimeSeconds>");
|
||||||
@@ -113,7 +128,7 @@ public class TcxTrackWriter implements TrackFormatWriter {
|
|||||||
// Calories are a required element just put in 0.
|
// Calories are a required element just put in 0.
|
||||||
pw.print("<Calories>0</Calories>");
|
pw.print("<Calories>0</Calories>");
|
||||||
pw.println("<Intensity>Active</Intensity>");
|
pw.println("<Intensity>Active</Intensity>");
|
||||||
pw.println("<TriggerMethod>Manual</TriggerMethod>)");
|
pw.println("<TriggerMethod>Manual</TriggerMethod>");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -130,7 +145,7 @@ public class TcxTrackWriter implements TrackFormatWriter {
|
|||||||
}
|
}
|
||||||
pw.println(" <Trackpoint>");
|
pw.println(" <Trackpoint>");
|
||||||
Date d = new Date(location.getTime());
|
Date d = new Date(location.getTime());
|
||||||
pw.println(" <Time>" + TIMESTAMP_FORMAT.format(d) + "</Time>");
|
pw.println(" <Time>" + timestampFormatter.format(d) + "</Time>");
|
||||||
pw.println(" <Position>");
|
pw.println(" <Position>");
|
||||||
|
|
||||||
pw.print(" <LatitudeDegrees>");
|
pw.print(" <LatitudeDegrees>");
|
||||||
@@ -194,10 +209,18 @@ public class TcxTrackWriter implements TrackFormatWriter {
|
|||||||
}
|
}
|
||||||
pw.println(" </Lap>");
|
pw.println(" </Lap>");
|
||||||
pw.print(" <Creator xsi:type=\"Device_t\">");
|
pw.print(" <Creator xsi:type=\"Device_t\">");
|
||||||
pw.print("<Name>");
|
pw.format("<Name>%s</Name>\n", Build.MODEL);
|
||||||
pw.print(Build.MODEL);
|
|
||||||
pw.print("</Name>");
|
// The following code is correct. ID is inconsistently capitalized in the
|
||||||
pw.println("</Creator>)");
|
// TCX schema.
|
||||||
|
pw.println("<UnitId>0</UnitId>");
|
||||||
|
pw.println("<ProductID>0</ProductID>");
|
||||||
|
|
||||||
|
pw.println("<Version>");
|
||||||
|
pw.println("<VersionMajor>0</VersionMajor>");
|
||||||
|
pw.println("<VersionMinor>0</VersionMinor>");
|
||||||
|
pw.println("</Version>");
|
||||||
|
pw.println("</Creator>");
|
||||||
pw.println(" </Activity>");
|
pw.println(" </Activity>");
|
||||||
pw.println(" </Activities>");
|
pw.println(" </Activities>");
|
||||||
}
|
}
|
||||||
@@ -207,8 +230,31 @@ public class TcxTrackWriter implements TrackFormatWriter {
|
|||||||
if (pw == null) {
|
if (pw == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pw.print(" <Author xsi:type=\"Application_t\">");
|
pw.println(" <Author xsi:type=\"Application_t\">");
|
||||||
pw.print("<Name>My Tracks by Google</Name>");
|
|
||||||
|
// We put the version in the name because there isn't a better place for
|
||||||
|
// it. The TCX schema tightly defined the Version tag, so we can't put it
|
||||||
|
// there. They've similarly constrained the PartNumber tag, so it can't go
|
||||||
|
// there either.
|
||||||
|
pw.format("<Name>My Tracks %s by Google</Name>\n", SystemUtils.getMyTracksVersion(context));
|
||||||
|
|
||||||
|
pw.println("<Build>");
|
||||||
|
|
||||||
|
// The TCX spec for the Version tag is too strict to allow us to use our
|
||||||
|
// user-visible version number, so we use our version code instead. We
|
||||||
|
// also set the minor version to 1 if this is a development build to
|
||||||
|
// signify that this build is newer than the one associated with the
|
||||||
|
// version code given in VersionMajor.
|
||||||
|
pw.println("<Version>");
|
||||||
|
pw.format("<VersionMajor>%s</VersionMajor>\n", SystemUtils.getMyTracksVersion(context));
|
||||||
|
pw.format("<VersionMinor>%d</VersionMinor>\n", SystemUtils.isRelease(context) ? 0 : 1);
|
||||||
|
pw.println("</Version>");
|
||||||
|
|
||||||
|
pw.format("<Type>%s</Type>\n", SystemUtils.isRelease(context) ? TCX_TYPE_RELEASE
|
||||||
|
: TCX_TYPE_INTERNAL);
|
||||||
|
pw.println("</Build>");
|
||||||
|
pw.format("<LangID>%s</LangID>\n", Locale.getDefault().getLanguage());
|
||||||
|
pw.println("<PartNumber>000-00000-00</PartNumber>");
|
||||||
pw.println("</Author>");
|
pw.println("</Author>");
|
||||||
pw.println("</TrainingCenterDatabase>");
|
pw.println("</TrainingCenterDatabase>");
|
||||||
}
|
}
|
||||||
@@ -217,4 +263,15 @@ public class TcxTrackWriter implements TrackFormatWriter {
|
|||||||
public void writeWaypoint(Waypoint waypoint) {
|
public void writeWaypoint(Waypoint waypoint) {
|
||||||
// TODO Write out the waypoints somewhere.
|
// TODO Write out the waypoints somewhere.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String categoryToTcxSport(String category) {
|
||||||
|
category = category.trim();
|
||||||
|
if (category.equalsIgnoreCase(TCX_SPORT_RUNNING)) {
|
||||||
|
return TCX_SPORT_RUNNING;
|
||||||
|
} else if (category.equalsIgnoreCase(TCX_SPORT_BIKING)) {
|
||||||
|
return TCX_SPORT_BIKING;
|
||||||
|
} else {
|
||||||
|
return TCX_SPORT_OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -13,7 +13,7 @@
|
|||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io.file;
|
||||||
|
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
|
||||||
+3
-3
@@ -13,7 +13,7 @@
|
|||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io.file;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
@@ -54,7 +54,7 @@ public interface TrackFormatWriter {
|
|||||||
void prepare(Track track, OutputStream out);
|
void prepare(Track track, OutputStream out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The file extentsion (i.e. gpx, kml, ...)
|
* @return The file extension (i.e. gpx, kml, ...)
|
||||||
*/
|
*/
|
||||||
String getExtension();
|
String getExtension();
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ public interface TrackFormatWriter {
|
|||||||
*
|
*
|
||||||
* @param location the location to write
|
* @param location the location to write
|
||||||
*/
|
*/
|
||||||
void writeLocation(Location location);
|
void writeLocation(Location location) throws InterruptedException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a way point.
|
* Write a way point.
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 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.
|
||||||
|
*/
|
||||||
|
package com.google.android.apps.mytracks.io.file;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementations of this class export tracks to the SD card. This class is
|
||||||
|
* intended to be format-neutral - it handles creating the output file and
|
||||||
|
* reading the track to be exported, but requires an instance of
|
||||||
|
* {@link TrackFormatWriter} to actually format the data.
|
||||||
|
*
|
||||||
|
* @author Sandor Dornbush
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public interface TrackWriter {
|
||||||
|
/** This listener is used to signal completion of track write */
|
||||||
|
public interface OnCompletionListener {
|
||||||
|
public void onComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This listener is used to signal track writes. */
|
||||||
|
public interface OnWriteListener {
|
||||||
|
/**
|
||||||
|
* This method is invoked whenever a location within a track is written.
|
||||||
|
* @param number the location number
|
||||||
|
* @param max the maximum number of locations, for calculation of
|
||||||
|
* completion percentage
|
||||||
|
*/
|
||||||
|
public void onWrite(int number, int max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets listener to be invoked when the writer has finished.
|
||||||
|
*/
|
||||||
|
void setOnCompletionListener(OnCompletionListener onCompletionListener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a listener to be invoked for each location writer.
|
||||||
|
*/
|
||||||
|
void setOnWriteListener(OnWriteListener onWriteListener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a custom directory where the file will be written.
|
||||||
|
*/
|
||||||
|
void setDirectory(File directory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the absolute path to the file which was created.
|
||||||
|
*/
|
||||||
|
String getAbsolutePath();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given track id to the SD card.
|
||||||
|
* This is non-blocking.
|
||||||
|
*/
|
||||||
|
void writeTrackAsync();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given track id to the SD card.
|
||||||
|
* This is blocking.
|
||||||
|
*/
|
||||||
|
void writeTrack();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop any in-progress writes
|
||||||
|
*/
|
||||||
|
void stopWriteTrack();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the write completed successfully.
|
||||||
|
*/
|
||||||
|
boolean wasSuccess();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the error message (if any) generated by a writer failure.
|
||||||
|
*/
|
||||||
|
int getErrorMessage();
|
||||||
|
}
|
||||||
+3
-3
@@ -14,7 +14,7 @@
|
|||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io.file;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
@@ -53,7 +53,7 @@ public class TrackWriterFactory {
|
|||||||
TCX {
|
TCX {
|
||||||
@Override
|
@Override
|
||||||
public TrackFormatWriter newFormatWriter(Context context) {
|
public TrackFormatWriter newFormatWriter(Context context) {
|
||||||
return new TcxTrackWriter();
|
return new TcxTrackWriter(context);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ public class TrackWriterFactory {
|
|||||||
MyTracksProviderUtils providerUtils,
|
MyTracksProviderUtils providerUtils,
|
||||||
Track track, TrackFileFormat format) {
|
Track track, TrackFileFormat format) {
|
||||||
TrackFormatWriter writer = format.newFormatWriter(context);
|
TrackFormatWriter writer = format.newFormatWriter(context);
|
||||||
return new TrackWriter(context, providerUtils, track, writer);
|
return new TrackWriterImpl(context, providerUtils, track, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TrackWriterFactory() { }
|
private TrackWriterFactory() { }
|
||||||
+91
-48
@@ -13,16 +13,16 @@
|
|||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io;
|
package com.google.android.apps.mytracks.io.file;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
|
||||||
import com.google.android.apps.mytracks.util.FileUtils;
|
import com.google.android.apps.mytracks.util.FileUtils;
|
||||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@@ -37,28 +37,29 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class which exports tracks to the SD card.
|
* This class exports tracks to the SD card. It is intended to be format-
|
||||||
* This writer is format-neutral - it handles creating the output file
|
* neutral -- it handles creating the output file and reading the track to be
|
||||||
* and reading the track to be exported, but requires an instance of
|
* exported, but requires an instance of {@link TrackFormatWriter} to actually
|
||||||
* {@link TrackFormatWriter} to actually format the data.
|
* format the data.
|
||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
* @author Rodrigo Damazio
|
* @author Rodrigo Damazio
|
||||||
*/
|
*/
|
||||||
public class TrackWriter {
|
class TrackWriterImpl implements TrackWriter {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final MyTracksProviderUtils providerUtils;
|
private final MyTracksProviderUtils providerUtils;
|
||||||
private final Track track;
|
private final Track track;
|
||||||
private final TrackFormatWriter writer;
|
private final TrackFormatWriter writer;
|
||||||
private final FileUtils fileUtils;
|
private final FileUtils fileUtils;
|
||||||
private Runnable onCompletion = null;
|
|
||||||
private boolean success = false;
|
private boolean success = false;
|
||||||
private int errorMessage = -1;
|
private int errorMessage = -1;
|
||||||
private File directory = null;
|
private File directory = null;
|
||||||
private File file = null;
|
private File file = null;
|
||||||
|
private OnCompletionListener onCompletionListener;
|
||||||
|
private OnWriteListener onWriteListener;
|
||||||
|
private Thread writeThread;
|
||||||
|
|
||||||
public TrackWriter(Context context, MyTracksProviderUtils providerUtils,
|
TrackWriterImpl(Context context, MyTracksProviderUtils providerUtils,
|
||||||
Track track, TrackFormatWriter writer) {
|
Track track, TrackFormatWriter writer) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.providerUtils = providerUtils;
|
this.providerUtils = providerUtils;
|
||||||
@@ -67,60 +68,88 @@ public class TrackWriter {
|
|||||||
this.fileUtils = new FileUtils();
|
this.fileUtils = new FileUtils();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets a completion callback.
|
public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
|
||||||
*
|
this.onCompletionListener = onCompletionListener;
|
||||||
* @param onCompletion Runnable that will be executed when finished
|
|
||||||
*/
|
|
||||||
public void setOnCompletion(Runnable onCompletion) {
|
|
||||||
this.onCompletion = onCompletion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets a custom directory where the file will be written.
|
public void setOnWriteListener(OnWriteListener onWriteListener) {
|
||||||
*/
|
this.onWriteListener = onWriteListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setDirectory(File directory) {
|
public void setDirectory(File directory) {
|
||||||
this.directory = directory;
|
this.directory = directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getAbsolutePath() {
|
public String getAbsolutePath() {
|
||||||
return file.getAbsolutePath();
|
return file.getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Writes the given track id to the SD card.
|
|
||||||
* This is non-blocking.
|
|
||||||
*/
|
|
||||||
public void writeTrackAsync() {
|
public void writeTrackAsync() {
|
||||||
Thread t = new Thread() {
|
writeThread = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
writeTrack();
|
doWriteTrack();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
t.start();
|
writeThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Writes the given track id to the SD card.
|
|
||||||
* This is blocking.
|
|
||||||
*/
|
|
||||||
public void writeTrack() {
|
public void writeTrack() {
|
||||||
|
writeTrackAsync();
|
||||||
|
try {
|
||||||
|
writeThread.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(Constants.TAG, "Interrupted waiting for write to complete", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doWriteTrack() {
|
||||||
// Open the input and output
|
// Open the input and output
|
||||||
success = false;
|
success = false;
|
||||||
errorMessage = R.string.error_track_does_not_exist;
|
errorMessage = R.string.error_track_does_not_exist;
|
||||||
if (track != null) {
|
if (track != null) {
|
||||||
if (openFile()) {
|
if (openFile()) {
|
||||||
writeDocument();
|
try {
|
||||||
|
writeDocument();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.i(Constants.TAG, "The track write was interrupted");
|
||||||
|
if (file != null) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
success = false;
|
||||||
|
errorMessage = R.string.error_operation_cancelled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finished();
|
finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stopWriteTrack() {
|
||||||
|
if (writeThread != null && writeThread.isAlive()) {
|
||||||
|
Log.i(Constants.TAG, "Attempting to stop track write");
|
||||||
|
writeThread.interrupt();
|
||||||
|
|
||||||
|
try {
|
||||||
|
writeThread.join();
|
||||||
|
Log.i(Constants.TAG, "Track write stopped");
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(Constants.TAG, "Failed to wait for writer to stop", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getErrorMessage() {
|
public int getErrorMessage() {
|
||||||
return errorMessage;
|
return errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean wasSuccess() {
|
public boolean wasSuccess() {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@@ -131,8 +160,13 @@ public class TrackWriter {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private void finished() {
|
private void finished() {
|
||||||
if (onCompletion != null) {
|
if (onCompletionListener != null) {
|
||||||
runOnUiThread(onCompletion);
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
onCompletionListener.onComplete();
|
||||||
|
}
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,16 +194,16 @@ public class TrackWriter {
|
|||||||
String fileName = fileUtils.buildUniqueFileName(
|
String fileName = fileUtils.buildUniqueFileName(
|
||||||
directory, track.getName(), writer.getExtension());
|
directory, track.getName(), writer.getExtension());
|
||||||
if (fileName == null) {
|
if (fileName == null) {
|
||||||
Log.e(MyTracksConstants.TAG,
|
Log.e(Constants.TAG,
|
||||||
"Unable to get a unique filename for " + fileName);
|
"Unable to get a unique filename for " + fileName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(MyTracksConstants.TAG, "Writing track to: " + fileName);
|
Log.i(Constants.TAG, "Writing track to: " + fileName);
|
||||||
try {
|
try {
|
||||||
writer.prepare(track, newOutputStream(fileName));
|
writer.prepare(track, newOutputStream(fileName));
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Failed to open output file.", e);
|
Log.e(Constants.TAG, "Failed to open output file.", e);
|
||||||
errorMessage = R.string.io_write_failed;
|
errorMessage = R.string.io_write_failed;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -187,12 +221,12 @@ public class TrackWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!fileUtils.isSdCardAvailable()) {
|
if (!fileUtils.isSdCardAvailable()) {
|
||||||
Log.i(MyTracksConstants.TAG, "Could not find SD card.");
|
Log.i(Constants.TAG, "Could not find SD card.");
|
||||||
errorMessage = R.string.io_no_external_storage_found;
|
errorMessage = R.string.io_no_external_storage_found;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!fileUtils.ensureDirectoryExists(directory)) {
|
if (!fileUtils.ensureDirectoryExists(directory)) {
|
||||||
Log.i(MyTracksConstants.TAG, "Could not create export directory.");
|
Log.i(Constants.TAG, "Could not create export directory.");
|
||||||
errorMessage = R.string.io_create_dir_failed;
|
errorMessage = R.string.io_create_dir_failed;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -230,7 +264,7 @@ public class TrackWriter {
|
|||||||
// same time.
|
// same time.
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
cursor = providerUtils.getWaypointsCursor(trackId, 0,
|
cursor = providerUtils.getWaypointsCursor(trackId, 0,
|
||||||
MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS);
|
Constants.MAX_LOADED_WAYPOINTS_POINTS);
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
try {
|
try {
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
@@ -252,19 +286,19 @@ public class TrackWriter {
|
|||||||
/**
|
/**
|
||||||
* Does the actual work of writing the track to the now open file.
|
* Does the actual work of writing the track to the now open file.
|
||||||
*/
|
*/
|
||||||
void writeDocument() {
|
void writeDocument() throws InterruptedException {
|
||||||
Log.d(MyTracksConstants.TAG, "Started writing track.");
|
Log.d(Constants.TAG, "Started writing track.");
|
||||||
writer.writeHeader();
|
writer.writeHeader();
|
||||||
writeWaypoints(track.getId());
|
writeWaypoints(track.getId());
|
||||||
writeLocations();
|
writeLocations();
|
||||||
writer.writeFooter();
|
writer.writeFooter();
|
||||||
writer.close();
|
writer.close();
|
||||||
success = true;
|
success = true;
|
||||||
Log.d(MyTracksConstants.TAG, "Done writing track.");
|
Log.d(Constants.TAG, "Done writing track.");
|
||||||
errorMessage = R.string.io_write_finished;
|
errorMessage = R.string.io_write_finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeLocations() {
|
private void writeLocations() throws InterruptedException {
|
||||||
boolean wroteFirst = false;
|
boolean wroteFirst = false;
|
||||||
boolean segmentOpen = false;
|
boolean segmentOpen = false;
|
||||||
boolean isLastValid = false;
|
boolean isLastValid = false;
|
||||||
@@ -296,13 +330,19 @@ public class TrackWriter {
|
|||||||
locationFactory);
|
locationFactory);
|
||||||
try {
|
try {
|
||||||
if (!it.hasNext()) {
|
if (!it.hasNext()) {
|
||||||
Log.w(MyTracksConstants.TAG, "Unable to get any points to write");
|
Log.w(Constants.TAG, "Unable to get any points to write");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int pointNumber = 0;
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Location loc = it.next();
|
Location loc = it.next();
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
throw new InterruptedException();
|
||||||
|
}
|
||||||
|
|
||||||
boolean isValid = MyTracksUtils.isValidLocation(loc);
|
pointNumber++;
|
||||||
|
|
||||||
|
boolean isValid = LocationUtils.isValidLocation(loc);
|
||||||
boolean validSegment = isValid && isLastValid;
|
boolean validSegment = isValid && isLastValid;
|
||||||
if (!wroteFirst && validSegment) {
|
if (!wroteFirst && validSegment) {
|
||||||
// Found the first two consecutive points which are valid
|
// Found the first two consecutive points which are valid
|
||||||
@@ -322,6 +362,9 @@ public class TrackWriter {
|
|||||||
|
|
||||||
// Write the current point
|
// Write the current point
|
||||||
writer.writeLocation(loc);
|
writer.writeLocation(loc);
|
||||||
|
if (onWriteListener != null) {
|
||||||
|
onWriteListener.onWrite(pointNumber, track.getNumberOfPoints());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (segmentOpen) {
|
if (segmentOpen) {
|
||||||
writer.writeCloseSegment();
|
writer.writeCloseSegment();
|
||||||
@@ -187,6 +187,7 @@ public class AndroidGDataClient implements GDataClient {
|
|||||||
while (redirectsLeft > 0) {
|
while (redirectsLeft > 0) {
|
||||||
|
|
||||||
HttpUriRequest request = creator.createRequest(uri);
|
HttpUriRequest request = creator.createRequest(uri);
|
||||||
|
request.addHeader("User-Agent", "Android-GData");
|
||||||
request.addHeader("Accept-Encoding", "gzip");
|
request.addHeader("Accept-Encoding", "gzip");
|
||||||
|
|
||||||
// only add the auth token if not null (to allow for GData feeds that do
|
// only add the auth token if not null (to allow for GData feeds that do
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io.gdata;
|
package com.google.android.apps.mytracks.io.gdata;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.wireless.gdata.client.GDataClient;
|
import com.google.wireless.gdata.client.GDataClient;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -43,7 +43,7 @@ public class GDataClientFactory {
|
|||||||
} catch (LinkageError e) {
|
} catch (LinkageError e) {
|
||||||
// On all other platforms use the client implementation packaged in the
|
// On all other platforms use the client implementation packaged in the
|
||||||
// apk.
|
// apk.
|
||||||
Log.i(MyTracksConstants.TAG, "Using mytracks AndroidGDataClient.", e);
|
Log.i(Constants.TAG, "Using mytracks AndroidGDataClient.", e);
|
||||||
return new com.google.android.apps.mytracks.io.gdata.AndroidGDataClient();
|
return new com.google.android.apps.mytracks.io.gdata.AndroidGDataClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.io.gdata;
|
package com.google.android.apps.mytracks.io.gdata;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.io.AuthManager;
|
import com.google.android.apps.mytracks.io.AuthManager;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -173,14 +173,14 @@ public class GDataWrapper<C> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(MyTracksConstants.TAG, "GData error encountered: " + errorMessage);
|
Log.d(Constants.TAG, "GData error encountered: " + errorMessage);
|
||||||
if (errorType == ERROR_AUTH && auth != null) {
|
if (errorType == ERROR_AUTH && auth != null) {
|
||||||
if (!retryOnAuthFailure || !invalidateAndRefreshAuthToken()) {
|
if (!retryOnAuthFailure || !invalidateAndRefreshAuthToken()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(MyTracksConstants.TAG, "retrying function/query");
|
Log.d(Constants.TAG, "retrying function/query");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -206,11 +206,11 @@ public class GDataWrapper<C> {
|
|||||||
errorMessage = null;
|
errorMessage = null;
|
||||||
|
|
||||||
} catch (AuthenticationException e) {
|
} catch (AuthenticationException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "AuthenticationException", e);
|
Log.e(Constants.TAG, "AuthenticationException", e);
|
||||||
errorType = ERROR_AUTH;
|
errorType = ERROR_AUTH;
|
||||||
errorMessage = e.getMessage();
|
errorMessage = e.getMessage();
|
||||||
} catch (HttpException e) {
|
} catch (HttpException e) {
|
||||||
Log.e(MyTracksConstants.TAG,
|
Log.e(Constants.TAG,
|
||||||
"HttpException, code " + e.getStatusCode() + " message " + e.getMessage(), e);
|
"HttpException, code " + e.getStatusCode() + " message " + e.getMessage(), e);
|
||||||
errorMessage = e.getMessage();
|
errorMessage = e.getMessage();
|
||||||
if (e.getStatusCode() == 401) {
|
if (e.getStatusCode() == 401) {
|
||||||
@@ -219,11 +219,11 @@ public class GDataWrapper<C> {
|
|||||||
errorType = ERROR_CONNECTION;
|
errorType = ERROR_CONNECTION;
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Exception", e);
|
Log.e(Constants.TAG, "Exception", e);
|
||||||
errorType = ERROR_AUTH;
|
errorType = ERROR_AUTH;
|
||||||
errorMessage = e.getMessage();
|
errorMessage = e.getMessage();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Exception", e);
|
Log.e(Constants.TAG, "Exception", e);
|
||||||
errorMessage = e.getMessage();
|
errorMessage = e.getMessage();
|
||||||
if (errorMessage != null && errorMessage.contains("503")) {
|
if (errorMessage != null && errorMessage.contains("503")) {
|
||||||
errorType = ERROR_INTERNAL;
|
errorType = ERROR_INTERNAL;
|
||||||
@@ -231,11 +231,11 @@ public class GDataWrapper<C> {
|
|||||||
errorType = ERROR_CONNECTION;
|
errorType = ERROR_CONNECTION;
|
||||||
}
|
}
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Exception", e);
|
Log.e(Constants.TAG, "Exception", e);
|
||||||
errorType = ERROR_LOCAL;
|
errorType = ERROR_LOCAL;
|
||||||
errorMessage = e.getMessage();
|
errorMessage = e.getMessage();
|
||||||
} catch (ConflictDetectedException e) {
|
} catch (ConflictDetectedException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Exception", e);
|
Log.e(Constants.TAG, "Exception", e);
|
||||||
errorType = ERROR_CONFLICT;
|
errorType = ERROR_CONFLICT;
|
||||||
errorMessage = e.getMessage();
|
errorMessage = e.getMessage();
|
||||||
}
|
}
|
||||||
@@ -249,7 +249,7 @@ public class GDataWrapper<C> {
|
|||||||
* times out.
|
* times out.
|
||||||
*/
|
*/
|
||||||
private boolean invalidateAndRefreshAuthToken() {
|
private boolean invalidateAndRefreshAuthToken() {
|
||||||
Log.d(MyTracksConstants.TAG, "Retrying due to auth failure");
|
Log.d(Constants.TAG, "Retrying due to auth failure");
|
||||||
// This FutureTask doesn't do anything -- it exists simply to be
|
// This FutureTask doesn't do anything -- it exists simply to be
|
||||||
// blocked upon using get().
|
// blocked upon using get().
|
||||||
FutureTask<?> whenFinishedFuture = new FutureTask<Object>(new Runnable() {
|
FutureTask<?> whenFinishedFuture = new FutureTask<Object>(new Runnable() {
|
||||||
@@ -259,18 +259,18 @@ public class GDataWrapper<C> {
|
|||||||
auth.invalidateAndRefresh(whenFinishedFuture);
|
auth.invalidateAndRefresh(whenFinishedFuture);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Log.d(MyTracksConstants.TAG, "waiting for invalidate");
|
Log.d(Constants.TAG, "waiting for invalidate");
|
||||||
whenFinishedFuture.get(AUTH_TOKEN_INVALIDATE_REFRESH_TIMEOUT,
|
whenFinishedFuture.get(AUTH_TOKEN_INVALIDATE_REFRESH_TIMEOUT,
|
||||||
TimeUnit.MILLISECONDS);
|
TimeUnit.MILLISECONDS);
|
||||||
Log.d(MyTracksConstants.TAG, "invalidate finished");
|
Log.d(Constants.TAG, "invalidate finished");
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Failed to invalidate", e);
|
Log.e(Constants.TAG, "Failed to invalidate", e);
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Failed to invalidate", e);
|
Log.e(Constants.TAG, "Failed to invalidate", e);
|
||||||
} catch (TimeoutException e) {
|
} catch (TimeoutException e) {
|
||||||
Log.e(MyTracksConstants.TAG, "Invalidate didn't complete in time", e);
|
Log.e(Constants.TAG, "Invalidate didn't complete in time", e);
|
||||||
} finally {
|
} finally {
|
||||||
whenFinishedFuture.cancel(false);
|
whenFinishedFuture.cancel(false);
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user