mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-24 03:05:17 +02:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 38de0e352f | |||
| 053fb403c5 | |||
| 1d70d4bca0 | |||
| bba04ba1bd | |||
| 1588c25fba | |||
| da928fb549 | |||
| f657c2f1d1 | |||
| d00c92ef99 | |||
| cb75c6fbe6 |
@@ -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="28"
|
||||||
android:versionName="1.1.1">
|
android:versionName="1.1.5">
|
||||||
<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>
|
||||||
@@ -105,7 +110,7 @@ limitations under the License.
|
|||||||
|
|
||||||
<!-- Permissions to initialize service -->
|
<!-- Permissions to initialize service -->
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
|
||||||
<!-- Permissions for recording tracks and showing maps -->
|
<!-- Permissions for recording tracks and showing maps -->
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
@@ -122,6 +127,7 @@ limitations under the License.
|
|||||||
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
|
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
|
||||||
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
||||||
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
|
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
|
||||||
|
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.fusiontables" />
|
||||||
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.local" />
|
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.local" />
|
||||||
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.wise" />
|
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.wise" />
|
||||||
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.writely" />
|
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.writely" />
|
||||||
@@ -158,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>
|
||||||
@@ -50,6 +50,12 @@ limitations under the License.
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"/>
|
android:layout_weight="1"/>
|
||||||
|
<Button android:id="@+id/tracklist_btn_import_all"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="48dip"
|
||||||
|
android:layout_gravity="left|top"
|
||||||
|
android:text="@string/tracklist_btn_import_all"
|
||||||
|
android:textSize="14dip"/>
|
||||||
<Button android:id="@+id/tracklist_btn_export_all"
|
<Button android:id="@+id/tracklist_btn_export_all"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="48dip"
|
android:layout_height="48dip"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ limitations under the License.
|
|||||||
<string name="status_tracks_have_been_uploaded">S\'ha enviat la ruta a maps.google.com.</string>
|
<string name="status_tracks_have_been_uploaded">S\'ha enviat la ruta a maps.google.com.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_new_doc">S\'ha enviat la ruta a un full de càlcul a docs.google.com.</string>
|
<string name="status_tracks_have_been_uploaded_to_new_doc">S\'ha enviat la ruta a un full de càlcul a docs.google.com.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_docs">S\'ha enviat la ruta a docs.google.com.</string>
|
<string name="status_tracks_have_been_uploaded_to_docs">S\'ha enviat la ruta a docs.google.com.</string>
|
||||||
<string name="status_enable_gps">Piqueu aquí per anar als paràmetres de seguretat i ubicació i activeu \'habilita els satèl·lits GPS\'. Premeu el botó d\'anar enrere per tornar.</string>
|
<string name="status_enable_gps">Toqueu aquí per anar als paràmetres de seguretat i ubicació i activeu \'habilita els satèl·lits GPS\'. Premeu el botó d\'anar enrere per tornar.</string>
|
||||||
<string name="status_approximate_location">Nota: Es mostra una ubicació determinada a partir de les xarxes sense fils i antenes telefòniques.</string>
|
<string name="status_approximate_location">Nota: Es mostra una ubicació determinada a partir de les xarxes sense fils i antenes telefòniques.</string>
|
||||||
<string name="status_no_location">No es pot determinar la ubicació. Habiliteu més fonts d\'ubicació (vegeu els paràmetres de seguretat i ubicació) i assegureu-vos que el cel és visible. Proveu de nou més tard.</string>
|
<string name="status_no_location">No es pot determinar la ubicació. Habiliteu més fonts d\'ubicació (vegeu els paràmetres de seguretat i ubicació) i assegureu-vos que el cel és visible. Proveu de nou més tard.</string>
|
||||||
<string name="status_waypoint_inserted">S\'ha inserit un marcader de punt de ruta.</string>
|
<string name="status_waypoint_inserted">S\'ha inserit un marcader de punt de ruta.</string>
|
||||||
@@ -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>
|
||||||
@@ -171,7 +170,7 @@ limitations under the License.
|
|||||||
<string name="settings_not_available_summary">No es troba disponible a la vostra versió de l\'Android</string>
|
<string name="settings_not_available_summary">No es troba disponible a la vostra versió de l\'Android</string>
|
||||||
|
|
||||||
<string name="settings_announcement_frequency">Freqüència d\'avís</string>
|
<string name="settings_announcement_frequency">Freqüència d\'avís</string>
|
||||||
<string name="settings_announcement_frequency_summary">Temps mínin entre dos avisos de veu</string>
|
<string name="settings_announcement_frequency_summary">Temps mínim entre dos avisos de veu</string>
|
||||||
|
|
||||||
<string name="settings_min_recording_distance">Distància mínima entre punts</string>
|
<string name="settings_min_recording_distance">Distància mínima entre punts</string>
|
||||||
<string name="settings_min_recording_distance_summary">La distància més petita entre dos punts enregistrats de la vostra posició</string>
|
<string name="settings_min_recording_distance_summary">La distància més petita entre dos punts enregistrats de la vostra posició</string>
|
||||||
@@ -182,7 +181,7 @@ limitations under the License.
|
|||||||
<string name="settings_min_recording_interval">Temps mínim entre punts</string>
|
<string name="settings_min_recording_interval">Temps mínim entre punts</string>
|
||||||
<string name="settings_min_recording_interval_summary">Interval de temps mínim entre dos enregistraments de la vostra posició</string>
|
<string name="settings_min_recording_interval_summary">Interval de temps mínim entre dos enregistraments de la vostra posició</string>
|
||||||
|
|
||||||
<string name="settings_min_required_accuracy">Precisió míima</string>
|
<string name="settings_min_required_accuracy">Precisió mínima</string>
|
||||||
<string name="settings_min_required_accuracy_summary">S\'aturarà l\'enregistrament si la vostra posició no és així de precisa com a mínim</string>
|
<string name="settings_min_required_accuracy_summary">S\'aturarà l\'enregistrament si la vostra posició no és així de precisa com a mínim</string>
|
||||||
|
|
||||||
<string name="settings_metric_units">Fes servir unitats mètriques</string>
|
<string name="settings_metric_units">Fes servir unitats mètriques</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>
|
||||||
@@ -240,13 +238,13 @@ limitations under the License.
|
|||||||
|
|
||||||
<!-- Sharing -->
|
<!-- Sharing -->
|
||||||
<string name="share_map_subject">M\'agradaria compartir un mapa amb tu</string>
|
<string name="share_map_subject">M\'agradaria compartir un mapa amb tu</string>
|
||||||
<string name="share_map_body_format">Crec que estaràs interessat en aquest mapa:
|
<string name="share_map_body_format">Em sembla que estaràs interessat en aquest mapa:
|
||||||
|
|
||||||
%s</string>
|
%s</string>
|
||||||
<string name="send_track_subject">M\'agradaria compartir una ruta amb tu</string>
|
<string name="send_track_subject">M\'agradaria compartir una ruta amb tu</string>
|
||||||
<string name="send_track_body_format">Crec que estaràs interessat en aquesta ruta.
|
<string name="send_track_body_format">Em sembla que estaràs interessat en aquesta ruta.
|
||||||
|
|
||||||
Per verue aquesta ruta fes servir Google Earth o altre programari de mapes.</string>
|
Per veure aquesta ruta fes servir Google Earth o altre programari de mapes.</string>
|
||||||
<string name="share_track">Comparteix la ruta amb amics</string>
|
<string name="share_track">Comparteix la ruta amb amics</string>
|
||||||
|
|
||||||
<!-- Visibility -->
|
<!-- Visibility -->
|
||||||
@@ -256,8 +254,8 @@ limitations under the License.
|
|||||||
|
|
||||||
<!-- Statistics View -->
|
<!-- Statistics View -->
|
||||||
<!-- Average Moving -->
|
<!-- Average Moving -->
|
||||||
<string name="average_moving_speed_label">Average Moving Speed</string>
|
<string name="average_moving_speed_label">Velocitat mitjana en moviment</string>
|
||||||
<string name="average_moving_pace_label">Average Moving Pace</string>
|
<string name="average_moving_pace_label">Ritme mitjà en moviment</string>
|
||||||
|
|
||||||
<!-- Average -->
|
<!-- Average -->
|
||||||
<string name="average_speed_label">Velocitat mitjana</string>
|
<string name="average_speed_label">Velocitat mitjana</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>
|
||||||
|
|||||||
+394
-369
@@ -1,255 +1,259 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright 2010 Google Inc.
|
Copyright 2010 Google Inc.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Used by the Menu -->
|
<!-- Used by the Menu -->
|
||||||
<string name="start_recording">Track aufzeichnen</string>
|
<string name="start_recording">Track aufzeichnen</string>
|
||||||
<string name="stop_recording">Aufzeichnung anhalten</string>
|
<string name="stop_recording">Aufzeichnung anhalten</string>
|
||||||
<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>
|
||||||
<string name="elevation">Höhe</string>
|
<string name="elevation">Höhe</string>
|
||||||
<string name="choose_track_message">Bitte wähle einen Track zur Ansicht aus</string>
|
<string name="choose_track_message">Bitte wähle einen Track zur Ansicht aus</string>
|
||||||
<string name="current_track">Aktueller Track</string>
|
<string name="current_track">Aktueller Track</string>
|
||||||
<string name="current_segment">Letztes Segment</string>
|
<string name="current_segment">Letztes Segment</string>
|
||||||
<string name="sensor_state">Sensorstatus</string>
|
<string name="sensor_state">Sensorstatus</string>
|
||||||
<string name="aggregated_stats">Aggregierte Statistiken</string>
|
<string name="aggregated_stats">Aggregierte Statistiken</string>
|
||||||
|
|
||||||
<!-- Error messages -->
|
<!-- Error messages -->
|
||||||
<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>
|
||||||
<string name="error_invalid_gpx_format">Datei ist nicht im GPX-Format.</string>
|
<string name="error_invalid_gpx_format">Datei ist nicht im GPX-Format.</string>
|
||||||
<string name="error_generic">Ein Fehler ist aufgetreten. Bitte versuche es noch einmal.</string>
|
<string name="error_generic">Ein Fehler ist aufgetreten. Bitte versuche es noch einmal.</string>
|
||||||
<string name="error_track_does_not_exist">Track existiert nicht.</string>
|
<string name="error_track_does_not_exist">Track existiert nicht.</string>
|
||||||
<string name="error_out_of_memory">Die Datei ist zu groß (maximal 500 KB). Operation abgebrochen.</string>
|
<string name="error_out_of_memory">Die Datei ist zu groß (maximal 500 KB). Operation abgebrochen.</string>
|
||||||
<string name="error_unable_to_insert_marker">Der Wegpunkt kann nicht einfügt werden. Keine Positionsbestimmung möglich.</string>
|
<string name="error_unable_to_insert_marker">Der Wegpunkt kann nicht einfügt werden. Keine Positionsbestimmung möglich.</string>
|
||||||
|
|
||||||
<!-- Status messages -->
|
<!-- Status messages -->
|
||||||
<string name="wait_for_fix">Warte auf ein besseres GPS-Signal. Bitte stelle sicher, dass der Himmel sichtbar ist.</string>
|
<string name="wait_for_fix">Warte auf ein besseres GPS-Signal. Bitte stelle sicher, dass der Himmel sichtbar ist.</string>
|
||||||
<string name="status_now_recording">Ein neuer Track wird aufgezeichnet.</string>
|
<string name="status_now_recording">Ein neuer Track wird aufgezeichnet.</string>
|
||||||
<string name="status_stopped_recording">Die Aufzeichnung wurde angehalten.</string>
|
<string name="status_stopped_recording">Die Aufzeichnung wurde angehalten.</string>
|
||||||
<string name="status_new_fusiontable_has_been_created">Eine neue Tabelle wurde auf google.com/fusiontables erstellt.</string>
|
<string name="status_new_fusiontable_has_been_created">Eine neue Tabelle wurde auf google.com/fusiontables erstellt.</string>
|
||||||
<string name="status_tracks_have_been_uploaded">Dein Track wurde auf maps.google.com gespeichert.</string>
|
<string name="status_tracks_have_been_uploaded">Dein Track wurde auf maps.google.com gespeichert.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_new_doc">Dein Track wurde in einer neuen Tabelle bei docs.google.com gespeichert.</string>
|
<string name="status_tracks_have_been_uploaded_to_new_doc">Dein Track wurde in einer neuen Tabelle bei docs.google.com gespeichert.</string>
|
||||||
<string name="status_tracks_have_been_uploaded_to_docs">Dein Track wurde an docs.google.com gesendet.</string>
|
<string name="status_tracks_have_been_uploaded_to_docs">Dein Track wurde an docs.google.com gesendet.</string>
|
||||||
<string name="status_enable_gps">Hier berühren, um zu den Sicherheits- und Positionseinstellungen zu gelangen. Aktiviere \'GPS-Satelliten\'. Drücke dann den Zurück-Knopf, um hierher zurückzukehren.</string>
|
<string name="status_enable_gps">Hier berühren, um zu den Sicherheits- und Positionseinstellungen zu gelangen. Aktiviere \'GPS-Satelliten\'. Drücke dann den Zurück-Knopf, um hierher zurückzukehren.</string>
|
||||||
<string name="status_approximate_location">Anmerkung: Eine ungefähre Position wird angezeigt, bestimmt mittels Mobilfunkstationen und WiFi-Netzwerken.</string>
|
<string name="status_approximate_location">Anmerkung: Eine ungefähre Position wird angezeigt, bestimmt mittels Mobilfunkstationen und WiFi-Netzwerken.</string>
|
||||||
<string name="status_no_location">Die Position kann derzeit nicht bestimmt werden. Aktiviere mehr Positionsquellen (siehe Sicherheits- und Positionseinstellungen) und stelle sicher, dass der Himmel sichtbar ist.</string>
|
<string name="status_no_location">Die Position kann derzeit nicht bestimmt werden. Aktiviere mehr Positionsquellen (siehe Sicherheits- und Positionseinstellungen) und stelle sicher, dass der Himmel sichtbar ist.</string>
|
||||||
<string name="status_waypoint_inserted">Ein Wegpunkt wurde eingefügt.</string>
|
<string name="status_waypoint_inserted">Ein Wegpunkt wurde eingefügt.</string>
|
||||||
<string name="status_statistics_inserted">Ein Statistikwegpunkt wurde eingefügt.</string>
|
<string name="status_statistics_inserted">Ein Statistikwegpunkt wurde eingefügt.</string>
|
||||||
|
|
||||||
<!-- Progress dialog -->
|
<!-- Progress dialog -->
|
||||||
<string name="progress_title">Bitte warten…</string>
|
<string name="progress_title">Bitte warten…</string>
|
||||||
<string name="progress_message">Dein Track wird an Google gesendet...</string>
|
<string name="progress_message">Dein Track wird an Google gesendet...</string>
|
||||||
<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>
|
||||||
<string name="write_progress_message">Schreibe Datei auf SD-Karte. Das kann ein wenig dauern.</string>
|
<string name="write_progress_message">Schreibe Datei auf SD-Karte. Das kann ein wenig dauern.</string>
|
||||||
<string name="progress_message_updating_track">Aktualisiere Trackstatistik...</string>
|
<string name="progress_message_updating_track">Aktualisiere Trackstatistik...</string>
|
||||||
|
|
||||||
<!-- Used by DeleteAllDataHandler -->
|
<!-- Used by DeleteAllDataHandler -->
|
||||||
<string name="are_you_sure_question">Bist Du Dir wirklich sicher?</string>
|
<string name="are_you_sure_question">Bist Du Dir wirklich sicher?</string>
|
||||||
<string name="all_data_will_be_permanently_deleted">Alle Tracks und Wegpunkte werden endgültig von diesem Gerät gelöscht.</string>
|
<string name="all_data_will_be_permanently_deleted">Alle Tracks und Wegpunkte werden endgültig von diesem Gerät gelöscht.</string>
|
||||||
<string name="track_will_be_permanently_deleted">Dieser Track und seine Wegpunkte werden endgültig von diesem Gerät gelöscht.</string>
|
<string name="track_will_be_permanently_deleted">Dieser Track und seine Wegpunkte werden endgültig von diesem Gerät gelöscht.</string>
|
||||||
<string name="marker_will_be_permanently_deleted">Dieser Wegpunkt wird endgültig von diesem Gerät gelöscht.</string>
|
<string name="marker_will_be_permanently_deleted">Dieser Wegpunkt wird endgültig von diesem Gerät gelöscht.</string>
|
||||||
|
|
||||||
<!-- Text and links when uploading to Google Fusion Tables -->
|
<!-- Text and links when uploading to Google Fusion Tables -->
|
||||||
<string name="new_map_description">Erstellt von My Tracks für Android.</string>
|
<string name="new_map_description">Erstellt von My Tracks für Android.</string>
|
||||||
<string name="fusiontable_link">Erstellt von <a href=\'http://mytracks.appspot.com\'>My Tracks</a> für Android.</string>
|
<string name="fusiontable_link">Erstellt von <a href=\'http://mytracks.appspot.com\'>My Tracks</a> für Android.</string>
|
||||||
|
|
||||||
<!-- Formatting of track and marker descriptions -->
|
<!-- Formatting of track and marker descriptions -->
|
||||||
<string name="points">Punkte</string>
|
<string name="points">Punkte</string>
|
||||||
<string name="recorded_date">Aufgezeichnet am</string>
|
<string name="recorded_date">Aufgezeichnet am</string>
|
||||||
<string name="category">Aktivität</string>
|
<string name="category">Aktivität</string>
|
||||||
<string name="waypoint_category">Art des Wegpunktes</string>
|
<string name="waypoint_category">Art des Wegpunktes</string>
|
||||||
<string name="part">(Teil %d)</string>
|
<string name="part">(Teil %d)</string>
|
||||||
|
|
||||||
<!-- 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 -->
|
|
||||||
<string name="no">Nein</string>
|
<!-- Common -->
|
||||||
<string name="yes">Ja</string>
|
<string name="no">Nein</string>
|
||||||
<string name="error">Fehler</string>
|
<string name="yes">Ja</string>
|
||||||
<string name="success">Erfolgreich</string>
|
<!--string name="ok">OK</string-->
|
||||||
<string name="waypoint">Wegpunkt</string>
|
<string name="error">Fehler</string>
|
||||||
|
<string name="success">Erfolgreich</string>
|
||||||
|
<string name="waypoint">Wegpunkt</string>
|
||||||
<string name="license">Lizenz</string>
|
<string name="license">Lizenz</string>
|
||||||
<string name="cancel">Abbrechen</string>
|
<string name="cancel">Abbrechen</string>
|
||||||
<string name="close">Schließen</string>
|
<string name="close">Schließen</string>
|
||||||
<string name="edit">Bearbeiten</string>
|
<string name="edit">Bearbeiten</string>
|
||||||
<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="end">(Ende)</string>
|
<!--string name="start">(Start)</string-->
|
||||||
|
<string name="end">(Ende)</string>
|
||||||
<!-- TrackList -->
|
|
||||||
<string name="tracklist_show_track">Anzeigen</string>
|
<!-- TrackList -->
|
||||||
|
<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>
|
||||||
<string name="tracklist_write_to_sd">Auf SD-Karte speichern…</string>
|
<string name="tracklist_write_to_sd">Auf SD-Karte speichern…</string>
|
||||||
<string name="tracklist_save_as_gpx">GPX-Datei exportieren</string>
|
<string name="tracklist_save_as_gpx">GPX-Datei exportieren</string>
|
||||||
<string name="tracklist_save_as_kml">KML-Datei exportieren</string>
|
<string name="tracklist_save_as_kml">KML-Datei exportieren</string>
|
||||||
<string name="tracklist_save_as_csv">CSV-Datei exportieren</string>
|
<string name="tracklist_save_as_csv">CSV-Datei exportieren</string>
|
||||||
<string name="tracklist_save_as_tcx">TCX-Datei exportieren</string>
|
<string name="tracklist_save_as_tcx">TCX-Datei exportieren</string>
|
||||||
<string name="tracklist_btn_send_all_to_fusiontables">An Google Fusion Tables senden</string>
|
<string name="tracklist_btn_send_all_to_fusiontables">An Google Fusion Tables senden</string>
|
||||||
<string name="tracklist_btn_delete_all">Alle Tracks löschen</string>
|
<string name="tracklist_btn_delete_all">Alle Tracks löschen</string>
|
||||||
<!-- Export All -->
|
<!-- Export All -->
|
||||||
<string name="tracklist_btn_export_all">Alle Tracks exportieren</string>
|
<string name="tracklist_btn_export_all">Alle Tracks exportieren</string>
|
||||||
<string name="export_done">Exportieren beendet</string>
|
<string name="export_done">Exportieren beendet</string>
|
||||||
<string name="tracklist_pick_one">Einen Track auswählen. Lange berühren für mehr Optionen.</string>
|
<string name="tracklist_pick_one">Einen Track auswählen. Lange berühren für mehr Optionen.</string>
|
||||||
<string name="tracklist_all_tracks">Alle Tracks</string>
|
<string name="tracklist_all_tracks">Alle Tracks</string>
|
||||||
<string name="tracklist_this_track">Dieser Track</string>
|
<string name="tracklist_this_track">Dieser Track</string>
|
||||||
<string name="tracklist_share_track">Mit Freunden teilen…</string>
|
<string name="tracklist_share_track">Mit Freunden teilen…</string>
|
||||||
<string name="tracklist_share_linkfusion">Ein Link zur Google Fusion Tables-Karte</string>
|
<string name="tracklist_share_linkfusion">Ein Link zur Google Fusion Tables-Karte</string>
|
||||||
<string name="tracklist_share_gpx_file">Eine GPX-Datei</string>
|
<string name="tracklist_share_gpx_file">Eine GPX-Datei</string>
|
||||||
<string name="tracklist_share_kml_file">Eine KML-Datei</string>
|
<string name="tracklist_share_kml_file">Eine KML-Datei</string>
|
||||||
<string name="tracklist_share_csv_file">Eine CSV-Datei</string>
|
<string name="tracklist_share_csv_file">Eine CSV-Datei</string>
|
||||||
<string name="tracklist_share_tcx_file">Eine TCX-Datei</string>
|
<string name="tracklist_share_tcx_file">Eine TCX-Datei</string>
|
||||||
<string name="tracklist_clear_map">Karte zurücksetzen.</string>
|
<string name="tracklist_clear_map">Karte zurücksetzen.</string>
|
||||||
|
|
||||||
<!-- Waypoints list -->
|
<!-- Waypoints list -->
|
||||||
<string name="waypointslist_btn_delete_all">Alle Wegpunkte löschen</string>
|
<string name="waypointslist_btn_delete_all">Alle Wegpunkte löschen</string>
|
||||||
<string name="waypointslist_this_waypoint">Dieser Wegpunkt</string>
|
<string name="waypointslist_this_waypoint">Dieser Wegpunkt</string>
|
||||||
<string name="waypointslist_delete_waypoint">Löschen</string>
|
<string name="waypointslist_delete_waypoint">Löschen</string>
|
||||||
<string name="waypointslist_edit_waypoint">Details bearbeiten</string>
|
<string name="waypointslist_edit_waypoint">Details bearbeiten</string>
|
||||||
<string name="waypointslist_show_waypoint">Auf der Karte zeigen</string>
|
<string name="waypointslist_show_waypoint">Auf der Karte zeigen</string>
|
||||||
<string name="waypointslist_btn_insert_waypoint">Wegpunkt einfügen</string>
|
<string name="waypointslist_btn_insert_waypoint">Wegpunkt einfügen</string>
|
||||||
<string name="waypointslist_btn_insert_statistics">Statistik einfügen</string>
|
<string name="waypointslist_btn_insert_statistics">Statistik einfügen</string>
|
||||||
<string name="waypointslist_pick_one">Wegpunkt auswählen. Lange berühren für mehr Optionen.</string>
|
<string name="waypointslist_pick_one">Wegpunkt auswählen. Lange berühren für mehr Optionen.</string>
|
||||||
|
|
||||||
<!-- MyTracks Details -->
|
<!-- MyTracks Details -->
|
||||||
<string name="trackdetails_title">Trackdetails</string>
|
<string name="trackdetails_title">Trackdetails</string>
|
||||||
<string name="trackdetails_name">Name</string>
|
<string name="trackdetails_name">Name</string>
|
||||||
<string name="trackdetails_description">Beschreibung</string>
|
<string name="trackdetails_description">Beschreibung</string>
|
||||||
<string name="trackdetails_category">Aktivität (z. B. Wandern, Fahrradfahren, Laufen, Klettern…)</string>
|
<string name="trackdetails_category">Aktivität (z. B. Wandern, Fahrradfahren, Laufen, Klettern…)</string>
|
||||||
|
|
||||||
<!-- MyTracks Waypoint Details -->
|
<!-- MyTracks Waypoint Details -->
|
||||||
<string name="waypointdetails_title">Wegpunktdetails</string>
|
<string name="waypointdetails_title">Wegpunktdetails</string>
|
||||||
<string name="waypointdetails_name">Wegpunktname</string>
|
<string name="waypointdetails_name">Wegpunktname</string>
|
||||||
<string name="waypointdetails_description">Wegpunktbeschreibung</string>
|
<string name="waypointdetails_description">Wegpunktbeschreibung</string>
|
||||||
<string name="waypointdetails_category">Art des Wegpunktes (z. B. Gebäude, Schlagloch, Sehenswürdigkeit…)</string>
|
<string name="waypointdetails_category">Art des Wegpunktes (z. B. Gebäude, Schlagloch, Sehenswürdigkeit…)</string>
|
||||||
|
|
||||||
<!-- MyTracks Settings -->
|
<!-- MyTracks Settings -->
|
||||||
<string name="mytracks_settings">Einstellungen für My Tracks</string>
|
<string name="mytracks_settings">Einstellungen für My Tracks</string>
|
||||||
<string name="settings_display">Anzeige</string>
|
<string name="settings_display">Anzeige</string>
|
||||||
<string name="settings_recording">Aufzeichnung</string>
|
<string name="settings_recording">Aufzeichnung</string>
|
||||||
<string name="settings_sharing">Mit Freunden teilen</string>
|
<string name="settings_sharing">Mit Freunden teilen</string>
|
||||||
|
|
||||||
<string name="settings_not_available_summary">In dieser Android-Version nicht verfügbar</string>
|
<string name="settings_not_available_summary">In dieser Android-Version nicht verfügbar</string>
|
||||||
|
|
||||||
<string name="settings_announcement_frequency">Dauer zwischen Ansagen</string>
|
<string name="settings_announcement_frequency">Dauer zwischen Ansagen</string>
|
||||||
<string name="settings_announcement_frequency_summary">Kürzeste Zeit zwischen zwei Ansagen</string>
|
<string name="settings_announcement_frequency_summary">Kürzeste Zeit zwischen zwei Ansagen</string>
|
||||||
|
|
||||||
<string name="settings_min_recording_distance">Kleinste Entfernung zwischen Punkten</string>
|
<string name="settings_min_recording_distance">Kleinste Entfernung zwischen Punkten</string>
|
||||||
<string name="settings_min_recording_distance_summary">Kleinste Entfernung zwischen zwei Positionsaufzeichnungen</string>
|
<string name="settings_min_recording_distance_summary">Kleinste Entfernung zwischen zwei Positionsaufzeichnungen</string>
|
||||||
|
|
||||||
<string name="settings_max_recording_distance">Neues Segment, wenn Punkte weiter entfernt als</string>
|
<string name="settings_max_recording_distance">Neues Segment, wenn Punkte weiter entfernt als</string>
|
||||||
<string name="settings_max_recording_distance_summary">Der Track wird in zwei geteilt, wenn zwei folgende Punkte weiter entfernt sind als hier angegeben.</string>
|
<string name="settings_max_recording_distance_summary">Der Track wird in zwei geteilt, wenn zwei folgende Punkte weiter entfernt sind als hier angegeben.</string>
|
||||||
|
|
||||||
<string name="settings_min_recording_interval">Aufzeichnungsfrequenz</string>
|
<string name="settings_min_recording_interval">Aufzeichnungsfrequenz</string>
|
||||||
<string name="settings_min_recording_interval_summary">Kürzeste Zeit zwischen zwei Positionsaufzeichnungen</string>
|
<string name="settings_min_recording_interval_summary">Kürzeste Zeit zwischen zwei Positionsaufzeichnungen</string>
|
||||||
|
|
||||||
<string name="settings_min_required_accuracy">Aufzeichnung pausieren, wenn Genauigkeit kleiner als</string>
|
<string name="settings_min_required_accuracy">Aufzeichnung pausieren, wenn Genauigkeit kleiner als</string>
|
||||||
<string name="settings_min_required_accuracy_summary">Die Aufzeichnung wird kurzfristig angehalten, wenn Deine Position nicht genauer als hier angegeben ermittelt werden kann.</string>
|
<string name="settings_min_required_accuracy_summary">Die Aufzeichnung wird kurzfristig angehalten, wenn Deine Position nicht genauer als hier angegeben ermittelt werden kann.</string>
|
||||||
|
|
||||||
<string name="settings_metric_units">Entfernungen in metrischen Einheiten anzeigen</string>
|
<string name="settings_metric_units">Entfernungen in metrischen Einheiten anzeigen</string>
|
||||||
<string name="settings_metric_units_summary_on">Alle Entfernungen werden in metrischen Einheiten angezeigt.</string>
|
<string name="settings_metric_units_summary_on">Alle Entfernungen werden in metrischen Einheiten angezeigt.</string>
|
||||||
<string name="settings_metric_units_summary_off">Alle Entfernungen werden in imperialen Längeneinheiten angezeigt.</string>
|
<string name="settings_metric_units_summary_off">Alle Entfernungen werden in imperialen Längeneinheiten angezeigt.</string>
|
||||||
|
|
||||||
<string name="settings_map_public">Karten auf maps.google.com veröffentlichen</string>
|
<string name="settings_map_public">Karten auf maps.google.com veröffentlichen</string>
|
||||||
<string name="settings_map_public_summary_on">Hochgeladene Karten auf maps.google.com sind für alle sichtbar.</string>
|
<string name="settings_map_public_summary_on">Hochgeladene Karten auf maps.google.com sind für alle sichtbar.</string>
|
||||||
<string name="settings_map_public_summary_off">Hochgeladene Karten auf maps.google.com werden nicht öffentlich sichtbar aufgelistet.</string>
|
<string name="settings_map_public_summary_off">Hochgeladene Karten auf maps.google.com werden nicht öffentlich sichtbar aufgelistet.</string>
|
||||||
|
|
||||||
<string name="settings_report_speed_or_pace">Geschwindigkeitsanzeige</string>
|
<string name="settings_report_speed_or_pace">Geschwindigkeitsanzeige</string>
|
||||||
<string name="settings_report_speed_or_pace_summary_on">Geschwindigkeit wird angezeigt.</string>
|
<string name="settings_report_speed_or_pace_summary_on">Geschwindigkeit wird angezeigt.</string>
|
||||||
<string name="settings_report_speed_or_pace_summary_off">Pace wird angezeigt.</string>
|
<string name="settings_report_speed_or_pace_summary_off">Pace wird angezeigt.</string>
|
||||||
|
|
||||||
<string name="settings_share_url_only">Nur URL als Einladung zum Teilen senden</string>
|
<string name="settings_share_url_only">Nur URL als Einladung zum Teilen senden</string>
|
||||||
<string name="settings_share_url_only_summary_on">Beim Teilen mit Freunden wird nur die Karten-URL gesendet.</string>
|
<string name="settings_share_url_only_summary_on">Beim Teilen mit Freunden wird nur die Karten-URL gesendet.</string>
|
||||||
<string name="settings_share_url_only_summary_off">Beim Teilen mit Freunden wird der GPS-Track selbst gesendet.</string>
|
<string name="settings_share_url_only_summary_off">Beim Teilen mit Freunden wird der GPS-Track selbst gesendet.</string>
|
||||||
|
|
||||||
<string name="settings_split_frequency">Zerteilungsfrequenz</string>
|
<string name="settings_split_frequency">Zerteilungsfrequenz</string>
|
||||||
<string name="settings_split_frequency_summary">Längste Dauer oder Entfernung, nach der automatisch ein Marker eingefügt wird.</string>
|
<string name="settings_split_frequency_summary">Längste Dauer oder Entfernung, nach der automatisch ein Marker eingefügt wird.</string>
|
||||||
|
|
||||||
<string name="settings_auto_resume_track_timeout">Zeitbegrenzung der Auto-Wiederaufnahme</string>
|
<string name="settings_auto_resume_track_timeout">Zeitbegrenzung der Auto-Wiederaufnahme</string>
|
||||||
<string name="settings_auto_resume_track_timeout_summary">Maximale Zeit in Minuten, nach der eine abgebrochene Aufzeichnung nach einem Telefonneustart wiederaufgenommen wird.</string>
|
<string name="settings_auto_resume_track_timeout_summary">Maximale Zeit in Minuten, nach der eine abgebrochene Aufzeichnung nach einem Telefonneustart wiederaufgenommen wird.</string>
|
||||||
|
|
||||||
<string name="settings_timestamp_track_name">Zeitstempel als Trackname</string>
|
<string name="settings_timestamp_track_name">Zeitstempel als Trackname</string>
|
||||||
<string name="settings_timestamp_track_name_summary_on">Der Trackname wird aus Datum und Zeit zum Aufzeichnungsbeginn zusammengesetzt.</string>
|
<string name="settings_timestamp_track_name_summary_on">Der Trackname wird aus Datum und Zeit zum Aufzeichnungsbeginn zusammengesetzt.</string>
|
||||||
<string name="settings_timestamp_track_name_summary_off">Tracknamen erhalten eine fortlaufende Nummer.</string>
|
<string name="settings_timestamp_track_name_summary_off">Tracknamen erhalten eine fortlaufende Nummer.</string>
|
||||||
|
|
||||||
<string name="pace_label">Pace</string>
|
<string name="pace_label">Pace</string>
|
||||||
|
|
||||||
<string name="eclair_required">Wird nur unter Android 2.0 oder höher unterstützt</string>
|
<string name="eclair_required">Wird nur unter Android 2.0 oder höher unterstützt</string>
|
||||||
<string name="settings_sensor_type">Sensortyp</string>
|
<string name="settings_sensor_type">Sensortyp</string>
|
||||||
<string name="settings_sensor_type_summary">Der Typ des zu verbindenden Sensors</string>
|
<string name="settings_sensor_type_summary">Der Typ des zu verbindenden Sensors</string>
|
||||||
<string name="settings_heart_rate_ant_sensor_id">Verbindung mit ANT Herzqrequenzmesser aufheben</string>
|
<string name="settings_heart_rate_ant_sensor_id">Verbindung mit ANT Herzqrequenzmesser aufheben</string>
|
||||||
<string name="settings_power_ant_sensor_id">Verbindung mit ANT Kraftmesser aufheben</string>
|
<string name="settings_power_ant_sensor_id">Verbindung mit ANT Kraftmesser aufheben</string>
|
||||||
<string name="settings_srm_bridge_ant_sensor_id">Verbindung mit ANT srm bridge aufheben</string>
|
<string name="settings_srm_bridge_ant_sensor_id">Verbindung mit ANT srm bridge aufheben</string>
|
||||||
<string name="settings_ant_not_paired">ANT-Sensor nicht verbunden</string>
|
<string name="settings_ant_not_paired">ANT-Sensor nicht verbunden</string>
|
||||||
<string name="settings_ant_paired">ANT-Sensor verbunden mit: %d</string>
|
<string name="settings_ant_paired">ANT-Sensor verbunden mit: %d</string>
|
||||||
<string name="bluetooth_sensor_title">Bluetooth-Sensor</string>
|
<string name="bluetooth_sensor_title">Bluetooth-Sensor</string>
|
||||||
<string name="bluetooth_sensor_summary">Der zu verbindende Bluetoothsensor</string>
|
<string name="bluetooth_sensor_summary">Der zu verbindende Bluetoothsensor</string>
|
||||||
<string name="settings_modular_stats_display_title">Art der Datenanzeige</string>
|
<string name="settings_modular_stats_display_title">Art der Datenanzeige</string>
|
||||||
|
|
||||||
<!-- Backups -->
|
|
||||||
<string name="settings_backup">Datensicherung (BETA)</string>
|
|
||||||
<string name="settings_sd_backup">SD-Karten-Sicherung</string>
|
|
||||||
<string name="settings_backup_to_sd">Jetzt sichern</string>
|
|
||||||
<string name="settings_backup_to_sd_summary">Eine Kopie aller Deiner Tracks und Einstellungen auf die SD-Karte schreiben</string>
|
|
||||||
<string name="settings_restore_from_sd">Jetzt wiederherstellen</string>
|
|
||||||
<string name="settings_restore_from_sd_summary">Alle Tracks und Einstellungen von der SD-Karte holen.</string>
|
|
||||||
<string name="settings_no_backup_while_recording">Während ein Track aufgezeichnet wird, kann nicht mit der Datensicherung gearbeitet werden.</string>
|
|
||||||
|
|
||||||
<string name="restore_overwrites_warning">Eine Wiederherstellung von der SD-Karte ÜBERSCHREIBT alle vorhandenen Tracks und Einstellungen. Willst Du das wirklich?</string>
|
|
||||||
<string name="select_backup_to_restore">Wähle die wiederherzustellende Datensicherung aus</string>
|
|
||||||
<string name="no_backups">Keine Datensicherungen gefunden.</string>
|
|
||||||
<string name="backup_write_progress_message">Schreibe alle Tracks und Einstellungen auf die SD-Karte. Dies kann eine Weile dauern...</string>
|
|
||||||
<string name="backup_import_progress_message">Lese alle Tracks und Einstellungen von der SD-Karte. Dies kann eine Weile dauern...</string>
|
|
||||||
|
|
||||||
<!-- MyTracksSky -->
|
|
||||||
<string name="mytracks_sky">GPS-Satelliten</string>
|
|
||||||
|
|
||||||
<!-- Sharing -->
|
<!-- Backups -->
|
||||||
|
<string name="settings_backup">Datensicherung (BETA)</string>
|
||||||
|
<string name="settings_sd_backup">SD-Karten-Sicherung</string>
|
||||||
|
<string name="settings_backup_to_sd">Jetzt sichern</string>
|
||||||
|
<string name="settings_backup_to_sd_summary">Eine Kopie aller Deiner Tracks und Einstellungen auf die SD-Karte schreiben</string>
|
||||||
|
<string name="settings_restore_from_sd">Jetzt wiederherstellen</string>
|
||||||
|
<string name="settings_restore_from_sd_summary">Alle Tracks und Einstellungen von der SD-Karte holen.</string>
|
||||||
|
<string name="settings_no_backup_while_recording">Während ein Track aufgezeichnet wird, kann nicht mit der Datensicherung gearbeitet werden.</string>
|
||||||
|
|
||||||
|
<string name="restore_overwrites_warning">Eine Wiederherstellung von der SD-Karte ÜBERSCHREIBT alle vorhandenen Tracks und Einstellungen. Willst Du das wirklich?</string>
|
||||||
|
<string name="select_backup_to_restore">Wähle die wiederherzustellende Datensicherung aus</string>
|
||||||
|
<string name="no_backups">Keine Datensicherungen gefunden.</string>
|
||||||
|
<string name="backup_write_progress_message">Schreibe alle Tracks und Einstellungen auf die SD-Karte. Dies kann eine Weile dauern...</string>
|
||||||
|
<string name="backup_import_progress_message">Lese alle Tracks und Einstellungen von der SD-Karte. Dies kann eine Weile dauern...</string>
|
||||||
|
|
||||||
|
<!-- MyTracksSky -->
|
||||||
|
<string name="mytracks_sky">GPS-Satelliten</string>
|
||||||
|
|
||||||
|
<!-- Sharing -->
|
||||||
<string name="share_map">Karte mit Freunden teilen</string>
|
<string name="share_map">Karte mit Freunden teilen</string>
|
||||||
<string name="share_map_subject">Ich möchte gerne eine Karte mit Dir teilen.</string>
|
<string name="share_map_subject">Ich möchte gerne eine Karte mit Dir teilen.</string>
|
||||||
<string name="share_map_body_format">Vielleicht interessierst Du Dich für diese Karte:
|
<string name="share_map_body_format">Vielleicht interessierst Du Dich für diese Karte:
|
||||||
|
|
||||||
%s</string>
|
%s</string>
|
||||||
<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 -->
|
||||||
@@ -257,126 +261,145 @@ limitations under the License.
|
|||||||
<string name="unlisted_map">Nicht in Suchergebnissen enthalten.</string>
|
<string name="unlisted_map">Nicht in Suchergebnissen enthalten.</string>
|
||||||
<string name="mapslist_no_maps_available">Du hast noch keine Karten.</string>
|
<string name="mapslist_no_maps_available">Du hast noch keine Karten.</string>
|
||||||
|
|
||||||
<!-- Statistics View -->
|
<!-- Statistics View -->
|
||||||
<!-- Average Moving -->
|
<!-- Average Moving -->
|
||||||
<string name="average_moving_speed_label">Durchschnitt in Bew.</string>
|
<string name="average_moving_speed_label">Durchschnitt in Bew.</string>
|
||||||
<string name="average_moving_pace_label">Pace in Bew.</string>
|
<string name="average_moving_pace_label">Pace in Bew.</string>
|
||||||
|
|
||||||
<!-- Average -->
|
<!-- Average -->
|
||||||
<string name="average_speed_label">Durchschnittsgeschw.</string>
|
<string name="average_speed_label">Durchschnittsgeschw.</string>
|
||||||
<string name="average_pace_label">Durchschnitts-Pace</string>
|
<string name="average_pace_label">Durchschnitts-Pace</string>
|
||||||
|
|
||||||
<string name="elevation_chart_name">Höhenprofil</string>
|
<string name="elevation_chart_name">Höhenprofil</string>
|
||||||
<string name="elevation_gain_label">Höhengewinn</string>
|
<string name="elevation_gain_label">Höhengewinn</string>
|
||||||
<string name="elevation_label">Höhe</string>
|
<string name="elevation_label">Höhe</string>
|
||||||
<string name="latitude_label">Breitengrad</string>
|
<string name="latitude_label">Breitengrad</string>
|
||||||
<string name="longitude_label">Längengrad</string>
|
<string name="longitude_label">Längengrad</string>
|
||||||
|
|
||||||
<!-- Min -->
|
<!-- Min -->
|
||||||
<string name="min_elevation_label">Niedrigste Höhenlage</string>
|
<string name="min_elevation_label">Niedrigste Höhenlage</string>
|
||||||
<string name="min_grade_label">Minimale Steigung</string>
|
<string name="min_grade_label">Minimale Steigung</string>
|
||||||
<string name="min_pace_label">Minimaler Pace</string>
|
<string name="min_pace_label">Minimaler Pace</string>
|
||||||
|
|
||||||
<!-- Max -->
|
<!-- Max -->
|
||||||
<string name="max_elevation_label">Höchste Höhenlage</string>
|
<string name="max_elevation_label">Höchste Höhenlage</string>
|
||||||
<string name="max_grade_label">Maximale Steigung</string>
|
<string name="max_grade_label">Maximale Steigung</string>
|
||||||
<string name="max_speed_label">Max. Geschwindigkeit</string>
|
<string name="max_speed_label">Max. Geschwindigkeit</string>
|
||||||
|
|
||||||
<string name="loading_track">Lade Track…</string>
|
<string name="loading_track">Lade Track…</string>
|
||||||
|
|
||||||
<!-- Chart Settings -->
|
<!-- Chart Settings -->
|
||||||
<string name="chart_settings">Diagramm-Einstellungen</string>
|
<string name="chart_settings">Diagramm-Einstellungen</string>
|
||||||
<!-- X Axis -->
|
<!-- X Axis -->
|
||||||
<string name="x_axis">X-Achse</string>
|
<string name="x_axis">X-Achse</string>
|
||||||
<string name="by_distance">Nach Entfernung</string>
|
<string name="by_distance">Nach Entfernung</string>
|
||||||
<string name="by_time">Nach Zeit</string>
|
<string name="by_time">Nach Zeit</string>
|
||||||
|
|
||||||
<!-- Y Axis -->
|
<!-- Y Axis -->
|
||||||
<string name="y_axis">Y-Achse</string>
|
<string name="y_axis">Y-Achse</string>
|
||||||
|
|
||||||
<!-- Units -->
|
<!-- Units -->
|
||||||
<!-- Time -->
|
<!-- Time -->
|
||||||
<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="minute">Minute</string>
|
<string name="min">Min</string>
|
||||||
<string name="minutes">Minuten</string>
|
<string name="minute">Minute</string>
|
||||||
<string name="second">Sekunde</string>
|
<string name="minutes">Minuten</string>
|
||||||
<string name="seconds">Sekunden</string>
|
<string name="second">Sekunde</string>
|
||||||
|
<string name="seconds">Sekunden</string>
|
||||||
<!-- Distance -->
|
<!--string name="milliseconds">ms</string-->
|
||||||
|
|
||||||
|
<!-- 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="miles_long">Meilen</string>
|
<!--string name="mile">mi</string-->
|
||||||
|
<string name="miles_long">Meilen</string>
|
||||||
<!-- Speed and Pace -->
|
|
||||||
<string name="kilometer_per_hour_long">Kilometer pro Stunde</string>
|
|
||||||
<string name="per_kilometer">pro Kilometer</string>
|
|
||||||
<string name="mile_per_hour_long">Meilen pro Stunde</string>
|
|
||||||
<string name="per_mile">pro Meile</string>
|
|
||||||
|
|
||||||
<!-- Stats Labels -->
|
<!-- Speed and Pace -->
|
||||||
<string name="moving_time_label">Zeit in Bewegung</string>
|
<!--string name="kilometer_per_hour">km/h</string-->
|
||||||
<string name="total_time_label">Gesamtzeit</string>
|
<string name="kilometer_per_hour_long">Kilometer pro Stunde</string>
|
||||||
<string name="time_label">Zeit</string>
|
<!--string name="min_per_kilometer">min/km</string-->
|
||||||
<string name="sd_unavail">SD-Karte nicht verfügbar</string>
|
<string name="per_kilometer">pro Kilometer</string>
|
||||||
<string name="speed">Geschwindigkeit</string>
|
<!--string name="mile_per_hour">mi/h</string-->
|
||||||
<string name="start_trip">Du musst erst eine Aufzeichnung beginnen.</string>
|
<string name="mile_per_hour_long">Meilen pro Stunde</string>
|
||||||
<string name="statistics">Statistik</string>
|
<!--string name="min_per_mile">min/mi</string-->
|
||||||
<string name="total_distance_label">Gesamtentfernung</string>
|
<string name="per_mile">pro Meile</string>
|
||||||
<string name="distance_label">Entfernung</string>
|
|
||||||
<string name="power">Kraft</string>
|
<!-- Sensors -->
|
||||||
<string name="cadence">Kadenz</string>
|
<!--string name="watts">W</string-->
|
||||||
<string name="heart_rate">Herzfrequenz</string>
|
|
||||||
<string name="max_heart_rate">Höchste Herzfrequenz</string>
|
<!--string name="revolutions_per_minute">rpm</string-->
|
||||||
<string name="waiting">Bitte warten…</string>
|
<!--string name="bpm">bpm</string-->
|
||||||
|
|
||||||
<!-- End User License Agreement -->
|
<!-- Stats Labels -->
|
||||||
<string name="eula_title">Lizenzvereinbarung für Endverbraucher</string>
|
<string name="moving_time_label">Zeit in Bewegung</string>
|
||||||
<string name="accept">Akzeptieren</string>
|
<string name="total_time_label">Gesamtzeit</string>
|
||||||
<string name="decline">Ablehnen</string>
|
<string name="time_label">Zeit</string>
|
||||||
|
<string name="sd_unavail">SD-Karte nicht verfügbar</string>
|
||||||
<!-- About -->
|
<string name="speed">Geschwindigkeit</string>
|
||||||
<string name="about">Über</string>
|
<string name="start_trip">Du musst erst eine Aufzeichnung beginnen.</string>
|
||||||
<string name="help">Hilfe</string>
|
<string name="statistics">Statistik</string>
|
||||||
|
<string name="total_distance_label">Gesamtentfernung</string>
|
||||||
|
<string name="distance_label">Entfernung</string>
|
||||||
|
<string name="power">Kraft</string>
|
||||||
|
<string name="cadence">Kadenz</string>
|
||||||
|
<string name="heart_rate">Herzfrequenz</string>
|
||||||
|
<string name="max_heart_rate">Höchste Herzfrequenz</string>
|
||||||
|
<!--string name="unknown">-</string-->
|
||||||
|
<string name="waiting">Bitte warten…</string>
|
||||||
|
|
||||||
|
<!-- End User License Agreement -->
|
||||||
|
<string name="eula_title">Lizenzvereinbarung für Endverbraucher</string>
|
||||||
|
<string name="accept">Akzeptieren</string>
|
||||||
|
<string name="decline">Ablehnen</string>
|
||||||
|
|
||||||
|
<!-- About -->
|
||||||
|
<string name="about">Über</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>
|
||||||
<string name="sendtogoogle_send_stats_and_points">Statistik und Punkte senden</string>
|
<string name="sendtogoogle_send_stats_and_points">Statistik und Punkte senden</string>
|
||||||
|
|
||||||
<!-- Getting the account to upload to. -->
|
<!-- Getting the account to upload to. -->
|
||||||
<string name="no_account_found_title">Kein Konto vorhanden</string>
|
<string name="no_account_found_title">Kein Konto vorhanden</string>
|
||||||
<string name="no_account_found">Kein Konto gefunden, um Tracks zu versenden.</string>
|
<string name="no_account_found">Kein Konto gefunden, um Tracks zu versenden.</string>
|
||||||
<string name="choose_account_title">Wähle ein Konto</string>
|
<string name="choose_account_title">Wähle ein Konto</string>
|
||||||
|
|
||||||
<!-- SD card -->
|
<!-- SD card -->
|
||||||
<string name="io_no_external_storage_found">Keine externes Speichermedium verfügbar. Stelle sicher, dass eine SD-Karte vorhanden ist und nicht bereits von einem Computer darauf zugegriffen wird.</string>
|
<string name="io_no_external_storage_found">Keine externes Speichermedium verfügbar. Stelle sicher, dass eine SD-Karte vorhanden ist und nicht bereits von einem Computer darauf zugegriffen wird.</string>
|
||||||
<string name="io_write_failed">Die Datei kann nicht geschrieben werden.</string>
|
<string name="io_write_failed">Die Datei kann nicht geschrieben werden.</string>
|
||||||
<string name="io_read_failed">Die Datei konnte nicht gelesen werden.</string>
|
<string name="io_read_failed">Die Datei konnte nicht gelesen werden.</string>
|
||||||
<string name="io_create_dir_failed">Das Verzeichnis auf der SD-Karte kann nicht erstellt werden.</string>
|
<string name="io_create_dir_failed">Das Verzeichnis auf der SD-Karte kann nicht erstellt werden.</string>
|
||||||
<string name="io_write_finished">Der Track wurde auf die SD-Karte geschrieben.</string>
|
<string name="io_write_finished">Der Track wurde auf die SD-Karte geschrieben.</string>
|
||||||
<string name="io_read_finished">Lesen von der SD-Karte beendet.</string>
|
<string name="io_read_finished">Lesen von der SD-Karte beendet.</string>
|
||||||
|
|
||||||
<!-- VersionChecker -->
|
<!-- VersionChecker -->
|
||||||
<string name="version_check_title">Suche nach neuer Version</string>
|
<string name="version_check_title">Suche nach neuer Version</string>
|
||||||
<string name="version_check_upgrade_button">Jetzt aktualisieren</string>
|
<string name="version_check_upgrade_button">Jetzt aktualisieren</string>
|
||||||
<string name="version_check_continue_button">Fortfahren, ohne zu aktualisieren</string>
|
<string name="version_check_continue_button">Fortfahren, ohne zu aktualisieren</string>
|
||||||
<string name="upgrade_required">Deine Version von %1$s funktioniert möglicherweise nicht mehr richtig und wird nicht mehr unterstützt. Bitte aktualisiere %1$s.</string>
|
<string name="upgrade_required">Deine Version von %1$s funktioniert möglicherweise nicht mehr richtig und wird nicht mehr unterstützt. Bitte aktualisiere %1$s.</string>
|
||||||
<string name="upgrade_recommended">Deine Version von %1$s funktioniert möglicherweise nicht mehr richtig. Du kannst sie jetzt aktualisieren, oder auf sie auf eigene Gefahr weiterverwenden. Einige Funktionen wie Datenaustausch mit Google-Diensten werden möglicherweise nicht mehr funktionieren, solange Du die Software nicht aktualisierst.</string>
|
<string name="upgrade_recommended">Deine Version von %1$s funktioniert möglicherweise nicht mehr richtig. Du kannst sie jetzt aktualisieren, oder auf sie auf eigene Gefahr weiterverwenden. Einige Funktionen wie Datenaustausch mit Google-Diensten werden möglicherweise nicht mehr funktionieren, solange Du die Software nicht aktualisierst.</string>
|
||||||
<string name="upgrade_available">Eine neue Version von %1$s ist jetzt verfügbar. Du kannst Deine installierte Version ohne Probleme weiterverwenden, aber um die neuesten Funktionen in Anspruch nehmen zu können, musst Du die Software aktualisieren.</string>
|
<string name="upgrade_available">Eine neue Version von %1$s ist jetzt verfügbar. Du kannst Deine installierte Version ohne Probleme weiterverwenden, aber um die neuesten Funktionen in Anspruch nehmen zu können, musst Du die Software aktualisieren.</string>
|
||||||
|
|
||||||
<!-- Welcome -->
|
<!-- Welcome -->
|
||||||
<string name="welcome">Willkommen</string>
|
<string name="welcome">Willkommen</string>
|
||||||
<string name="welcome_read_later">OK</string>
|
<string name="welcome_read_later">OK</string>
|
||||||
<string name="welcome_about">Über My Tracks</string>
|
<string name="welcome_about">Über My Tracks</string>
|
||||||
|
|
||||||
<!-- Announcement -->
|
<!-- Announcement -->
|
||||||
<string name="announce_no_distance">My Tracks keine Entfernung</string>
|
<string name="announce_no_distance">My Tracks keine Entfernung</string>
|
||||||
<!-- Format:
|
<!-- Format:
|
||||||
$1 : Distance label
|
$1 : Distance label
|
||||||
$2 : Distance value (5)
|
$2 : Distance value (5)
|
||||||
@@ -384,42 +407,44 @@ limitations under the License.
|
|||||||
$4 : Time description (10 minutes 5 seconds)
|
$4 : Time description (10 minutes 5 seconds)
|
||||||
$5 : Speed value (5.6) : Pace value (5 minutes 6 seconds)
|
$5 : Speed value (5.6) : Pace value (5 minutes 6 seconds)
|
||||||
$6 : Speed units (mph) : Pace units (per mile)
|
$6 : Speed units (mph) : Pace units (per mile)
|
||||||
-->
|
-->
|
||||||
<string name="announce_template">My Tracks %1$s %2$.2f %3$s in %4$s mit %5$s %6$s</string>
|
<string name="announce_template">My Tracks %1$s %2$.2f %3$s in %4$s mit %5$s %6$s</string>
|
||||||
|
|
||||||
<!-- Check Units -->
|
<!-- Check Units -->
|
||||||
<string name="check_units_title">Einheitenbenachrichtigung</string>
|
<string name="check_units_title">Einheitenbenachrichtigung</string>
|
||||||
<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="bluetooth_options">Bluetooth-Einstellungen</string>
|
<string name="method_bluetooth">Bluetooth</string>
|
||||||
<string name="bluetooth_pairing">Geräteverbindung</string>
|
<string name="bluetooth_options">Bluetooth-Einstellungen</string>
|
||||||
<string name="bluetooth_pairing_summary">Öffnet Androids Bluetooth-Einstellungen, um Geräte zu verbinden.</string>
|
<string name="bluetooth_pairing">Geräteverbindung</string>
|
||||||
<string name="sensor_options">Sensor-Einstellungen</string>
|
<string name="bluetooth_pairing_summary">Öffnet Androids Bluetooth-Einstellungen, um Geräte zu verbinden.</string>
|
||||||
|
<!--string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string-->
|
||||||
<!-- Bluetooth Sensor -->
|
<string name="sensor_options">Sensor-Einstellungen</string>
|
||||||
<string name="bluetooth_connected">Verbunden mit %s</string>
|
|
||||||
<string name="bluetooth_connecting">Verbinde mit Bluetooth-Sensor ...</string>
|
<!-- Bluetooth Sensor -->
|
||||||
<string name="bluetooth_not_connected">Bluetooth-Sensor nicht verbunden.</string>
|
<string name="bluetooth_connected">Verbunden mit %s</string>
|
||||||
|
<string name="bluetooth_connecting">Verbinde mit Bluetooth-Sensor ...</string>
|
||||||
<!-- Sensor State -->
|
<string name="bluetooth_not_connected">Bluetooth-Sensor nicht verbunden.</string>
|
||||||
<string name="sensor_data_time">Uhrzeit</string>
|
|
||||||
<string name="power_meter_enabled">Kraftmesser aktiviert</string>
|
<!-- Sensor State -->
|
||||||
<string name="heart_rate_monitor_enabled">Herzfrequenzmessung aktiviert</string>
|
<string name="sensor_data_time">Uhrzeit</string>
|
||||||
<string name="no_sensor_manager">Keine Sensoren verfügbar</string>
|
<string name="power_meter_enabled">Kraftmesser aktiviert</string>
|
||||||
<string name="enabled">Aktiviert</string>
|
<string name="heart_rate_monitor_enabled">Herzfrequenzmessung aktiviert</string>
|
||||||
<string name="connecting">Verbinde...</string>
|
<string name="no_sensor_manager">Keine Sensoren verfügbar</string>
|
||||||
<string name="connected">Verbunden</string>
|
<string name="enabled">Aktiviert</string>
|
||||||
<string name="disconnected">Getrennt</string>
|
<string name="connecting">Verbinde...</string>
|
||||||
<string name="no_sensor_service">Kein Sensor-Dienst</string>
|
<string name="connected">Verbunden</string>
|
||||||
<string name="searching">Suche...</string>
|
<string name="disconnected">Getrennt</string>
|
||||||
<string name="sending">Sende...</string>
|
<string name="no_sensor_service">Kein Sensor-Dienst</string>
|
||||||
|
<string name="searching">Suche...</string>
|
||||||
<!-- Manifest description (not seen inside the app) -->
|
<string name="sending">Sende...</string>
|
||||||
<string name="notification_permission_label">Track-Aufzeichnungs-Benachrichtigungen empfangen</string>
|
|
||||||
<string name="read_tracks_permission_label">Aufgezeichnete Trackdaten lesen</string>
|
<!-- Manifest description (not seen inside the app) -->
|
||||||
<string name="write_tracks_permission_label">Aufgezeichnete Trackdaten schreiben, Starten/Anhalten des Aufzeichnens von Tracks</string>
|
<string name="notification_permission_label">Track-Aufzeichnungs-Benachrichtigungen empfangen</string>
|
||||||
<string name="notification_permission_description">Werde benachrichtigt, wenn die Aufzeichnung eines Tracks beginnt oder anhält.</string>
|
<string name="read_tracks_permission_label">Aufgezeichnete Trackdaten lesen</string>
|
||||||
<string name="read_tracks_permission_description">Ermöglicht das Lesen von Trackdaten wie Messpunkten oder Wegpunkten.</string>
|
<string name="write_tracks_permission_label">Aufgezeichnete Trackdaten schreiben, Starten/Anhalten des Aufzeichnens von Tracks</string>
|
||||||
<string name="write_tracks_permission_description">Ermöglicht das Schreiben von Trackdaten wie beim Starten der Aufzeichnung oder beim Hinzufügen von Wegpunkten.</string>
|
<string name="notification_permission_description">Werde benachrichtigt, wenn die Aufzeichnung eines Tracks beginnt oder anhält.</string>
|
||||||
</resources>
|
<string name="read_tracks_permission_description">Ermöglicht das Lesen von Trackdaten wie Messpunkten oder Wegpunkten.</string>
|
||||||
|
<string name="write_tracks_permission_description">Ermöglicht das Schreiben von Trackdaten wie beim Starten der Aufzeichnung oder beim Hinzufügen von Wegpunkten.</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -310,5 +297,5 @@ limitations under the License.
|
|||||||
<item>Pont SRM ANT+</item>
|
<item>Pont SRM ANT+</item>
|
||||||
<item>Bluetooth Zephyr</item>
|
<item>Bluetooth Zephyr</item>
|
||||||
</array>
|
</array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -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,32 @@ 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>
|
||||||
|
<!-- 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 +214,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 +255,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 +265,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 +372,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 +389,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 +405,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 +438,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 +466,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>
|
||||||
@@ -146,7 +134,7 @@ limitations under the License.
|
|||||||
<item>2 min</item>
|
<item>2 min</item>
|
||||||
<item>1 min</item>
|
<item>1 min</item>
|
||||||
</string-array>
|
</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>Nigdy</item>
|
<item>Nigdy</item>
|
||||||
@@ -162,7 +150,7 @@ limitations under the License.
|
|||||||
<item>typ mieszany</item>
|
<item>typ mieszany</item>
|
||||||
<item>inny</item>
|
<item>inny</item>
|
||||||
|
|
||||||
<item>bieanie</item>
|
<item>bieganie</item>
|
||||||
<item>bieganie uliczne</item>
|
<item>bieganie uliczne</item>
|
||||||
<item>bieganie na torze</item>
|
<item>bieganie na torze</item>
|
||||||
<item>bieganie terenowe</item>
|
<item>bieganie terenowe</item>
|
||||||
@@ -182,10 +170,10 @@ limitations under the License.
|
|||||||
<item>łyżwiarstwo torowe</item>
|
<item>łyżwiarstwo torowe</item>
|
||||||
<item>deskorolka</item>
|
<item>deskorolka</item>
|
||||||
|
|
||||||
<item>wędrówka po sniegu</item>
|
<item>wędrówka po śniegu</item>
|
||||||
<item>narciarstwo</item>
|
<item>narciarstwo</item>
|
||||||
<item>snowboard</item>
|
<item>snowboard</item>
|
||||||
<item>saneczkastwo</item>
|
<item>saneczkarstwo</item>
|
||||||
<item>żeglarstwo lodowe</item>
|
<item>żeglarstwo lodowe</item>
|
||||||
|
|
||||||
<item>żeglowanie</item>
|
<item>żeglowanie</item>
|
||||||
@@ -249,7 +237,7 @@ limitations under the License.
|
|||||||
<item>kominek</item>
|
<item>kominek</item>
|
||||||
<item>remiza strażacka</item>
|
<item>remiza strażacka</item>
|
||||||
<item>baza wędkarska</item>
|
<item>baza wędkarska</item>
|
||||||
<item>stcja paliw</item>
|
<item>stacja paliw</item>
|
||||||
<item>pole golfowe</item>
|
<item>pole golfowe</item>
|
||||||
<item>sklep spożywczy</item>
|
<item>sklep spożywczy</item>
|
||||||
<item>fryzjer</item>
|
<item>fryzjer</item>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ limitations under the License.
|
|||||||
<string name="error_invalid_gpx_format">Plik nie jest poprawnym plikiem GPX.</string>
|
<string name="error_invalid_gpx_format">Plik nie jest poprawnym plikiem GPX.</string>
|
||||||
<string name="error_generic">Wystąpił błąd. Spróbuj ponownie.</string>
|
<string name="error_generic">Wystąpił błąd. Spróbuj ponownie.</string>
|
||||||
<string name="error_track_does_not_exist">Trasa nie istnieje.</string>
|
<string name="error_track_does_not_exist">Trasa nie istnieje.</string>
|
||||||
<string name="error_out_of_memory">Plik jest za duży (musi być mniejszy nić 500 KB). Przerywam.</string>
|
<string name="error_out_of_memory">Plik jest za duży (musi być mniejszy niż 500 KB). Przerywam.</string>
|
||||||
<string name="error_unable_to_insert_marker">Nie można wstawić markera. Brak poprawnych danych o lokalizacji.</string>
|
<string name="error_unable_to_insert_marker">Nie można wstawić markera. Brak poprawnych danych o lokalizacji.</string>
|
||||||
|
|
||||||
<!-- Status messages -->
|
<!-- Status messages -->
|
||||||
@@ -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>
|
||||||
@@ -336,7 +334,6 @@ limitations under the License.
|
|||||||
<string name="about_team">Zespół:</string>
|
<string name="about_team">Zespół:</string>
|
||||||
<string name="about_version">Wersja:</string>
|
<string name="about_version">Wersja:</string>
|
||||||
<string name="about_support">Wsparcie:</string>
|
<string name="about_support">Wsparcie:</string>
|
||||||
<string name="about_bart">Bartłomiej Niechwiej</string>
|
|
||||||
|
|
||||||
<!-- Send to Google -->
|
<!-- Send to Google -->
|
||||||
<string name="sendtogoogle_title">Wyślij do...</string>
|
<string name="sendtogoogle_title">Wyślij do...</string>
|
||||||
@@ -387,4 +384,31 @@ limitations under the License.
|
|||||||
<!-- Check Units -->
|
<!-- Check Units -->
|
||||||
<string name="check_units_title">Jednostki miary</string>
|
<string name="check_units_title">Jednostki miary</string>
|
||||||
<string name="check_units_message">Domyślnie używane są jednostki metryczne. Chcesz to zmienić?</string>
|
<string name="check_units_message">Domyślnie używane są jednostki metryczne. Chcesz to zmienić?</string>
|
||||||
|
|
||||||
|
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
|
||||||
|
<string name="method_bluetooth">Bluetooth</string>
|
||||||
|
<string name="bluetooth_options">Opcje Bluetooth</string>
|
||||||
|
<string name="bluetooth_pairing">Parowanie urządzenia</string>
|
||||||
|
<string name="bluetooth_pairing_summary">Przejdź do ustawień Bluetooth Androida aby sparować urządzenie</string>
|
||||||
|
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
|
||||||
|
<string name="ant_options">Opce ANT</string>
|
||||||
|
<string name="sensor_options">Opcje Czujników</string>
|
||||||
|
|
||||||
|
<!-- Bluetooth Sensor -->
|
||||||
|
<string name="bluetooth_connected">Połączony z %s</string>
|
||||||
|
<string name="bluetooth_connecting">Łączenie urządzenia Bluetooth w toku...</string>
|
||||||
|
<string name="bluetooth_not_connected">Urządzenie Bluetooth niepołączone</string>
|
||||||
|
|
||||||
|
<!-- Sensor State -->
|
||||||
|
<string name="sensor_data_time">Czas Danych Czujnika</string>
|
||||||
|
<string name="power_meter_enabled">Miernik mocy aktywny</string>
|
||||||
|
<string name="heart_rate_monitor_enabled">Pulsometr aktywny</string>
|
||||||
|
<string name="no_sensor_manager">Brak Ustawień Czujników</string>
|
||||||
|
<string name="enabled">Aktywny</string>
|
||||||
|
<string name="connecting">Łączenie</string>
|
||||||
|
<string name="connected">Podłączony</string>
|
||||||
|
<string name="disconnected">Rozłączony</string>
|
||||||
|
<string name="no_sensor_service">Brak Serwisu Czujników</string>
|
||||||
|
<string name="searching">Wykrywanie</string>
|
||||||
|
<string name="sending">Przesyłanie</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -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,500 @@
|
|||||||
|
<?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>
|
||||||
|
<!-- 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>
|
||||||
@@ -23,7 +23,7 @@ limitations under the License.
|
|||||||
<string name="about_weburl">mytracks.appspot.com</string>
|
<string name="about_weburl">mytracks.appspot.com</string>
|
||||||
<string name="about_privacy_weburl">m.google.com/privacy</string>
|
<string name="about_privacy_weburl">m.google.com/privacy</string>
|
||||||
<string name="about_copyright_message">Copyright 2009 Google Inc.</string>
|
<string name="about_copyright_message">Copyright 2009 Google Inc.</string>
|
||||||
<string name="about_bart">Bartlomiej Niechwiej</string>
|
<string name="about_bart">Bartłomiej Niechwiej</string>
|
||||||
<string name="about_dylan">Dylan Casey</string>
|
<string name="about_dylan">Dylan Casey</string>
|
||||||
<string name="about_leif">Leif Hendrik Wilden</string>
|
<string name="about_leif">Leif Hendrik Wilden</string>
|
||||||
<string name="about_rdamazio">Rodrigo Damazio Bovendorp</string>
|
<string name="about_rdamazio">Rodrigo Damazio Bovendorp</string>
|
||||||
@@ -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,20 +141,31 @@ 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_delete_all">Delete all tracks</string>
|
<string name="tracklist_btn_send_all_to_mymaps">Send to Google My Maps</string>
|
||||||
|
<string name="tracklist_btn_delete_all">Delete all</string>
|
||||||
<!-- Export All -->
|
<!-- Export All -->
|
||||||
<string name="tracklist_btn_export_all">Export all tracks</string>
|
<string name="tracklist_btn_export_all">Export all</string>
|
||||||
<string name="export_done">Export finished</string>
|
<string name="export_done">Export finished</string>
|
||||||
<string name="tracklist_pick_one">Pick a track. Press&hold for more options.</string>
|
<string name="tracklist_pick_one">Pick a track. Press&hold for more options.</string>
|
||||||
<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>
|
||||||
<string name="tracklist_share_tcx_file">A TCX file</string>
|
<string name="tracklist_share_tcx_file">A TCX file</string>
|
||||||
<string name="tracklist_clear_map">Clear map</string>
|
<string name="tracklist_clear_map">Clear map</string>
|
||||||
|
<!-- Import All -->
|
||||||
|
<string name="tracklist_btn_import_all">Import all</string>
|
||||||
|
<!-- Format:
|
||||||
|
$1 : Successful imports
|
||||||
|
$2 : Attempted imports
|
||||||
|
$3 : MyTracks gpx path
|
||||||
|
-->
|
||||||
|
<string name="import_done">Imported %1$d of %2$d GPX files from %3$s</string>
|
||||||
|
<string name="import_empty">No GPX files found in %s. SD card may be unreadable or directory may not contain GPX files.</string>
|
||||||
|
<string name="import_error">Import error for file %s</string>
|
||||||
|
|
||||||
<!-- Waypoints list -->
|
<!-- Waypoints list -->
|
||||||
<string name="waypointslist_btn_delete_all">Delete all markers</string>
|
<string name="waypointslist_btn_delete_all">Delete all markers</string>
|
||||||
@@ -169,6 +196,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>
|
||||||
@@ -211,6 +239,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>
|
||||||
@@ -218,7 +251,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>
|
||||||
@@ -232,7 +265,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>
|
||||||
@@ -243,6 +275,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>
|
||||||
@@ -253,7 +302,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>
|
||||||
@@ -366,8 +414,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>
|
||||||
|
|
||||||
@@ -419,6 +470,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"
|
||||||
@@ -122,20 +123,22 @@ limitations under the License.
|
|||||||
android:summary="@string/bluetooth_pairing_summary"
|
android:summary="@string/bluetooth_pairing_summary"
|
||||||
android:persistent="false" />
|
android:persistent="false" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<com.google.android.apps.mytracks.AntPreference
|
|
||||||
android:key="@string/ant_heart_rate_sensor_id_key"
|
|
||||||
android:title="@string/settings_heart_rate_ant_sensor_id"/>
|
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/ant_options"
|
||||||
|
android:key="@string/ant_options_key">
|
||||||
|
<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>
|
||||||
|
|||||||
@@ -28,14 +28,6 @@ package com.dsi.ant;
|
|||||||
*/
|
*/
|
||||||
public class AntDefine {
|
public class AntDefine {
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Library Version Information
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final int ANT_LIBRARY_VERSION_CODE = 5;
|
|
||||||
public static final int ANT_LIBRARY_VERSION_MAJOR = 1;
|
|
||||||
public static final int ANT_LIBRARY_VERSION_MINOR = 4;
|
|
||||||
public static final String ANT_LIBRARY_VERSION_NAME = String.valueOf(ANT_LIBRARY_VERSION_MAJOR) + "." + String.valueOf(ANT_LIBRARY_VERSION_MINOR);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
// Valid Configuration Values
|
// Valid Configuration Values
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -22,13 +22,16 @@ package com.dsi.ant;
|
|||||||
*/
|
*/
|
||||||
public interface AntInterfaceIntent {
|
public interface AntInterfaceIntent {
|
||||||
|
|
||||||
public static final String STATUS = "com.dsi.ant.rx.intent.STATUS";
|
public static final String STATUS = "com.dsi.ant.rx.intent.STATUS";
|
||||||
public static final String ANT_MESSAGE = "com.dsi.ant.intent.ANT_MESSAGE";
|
public static final String ANT_MESSAGE = "com.dsi.ant.intent.ANT_MESSAGE";
|
||||||
|
public static final String ANT_INTERFACE_CLAIMED_PID = "com.dsi.ant.intent.ANT_INTERFACE_CLAIMED_PID";
|
||||||
|
|
||||||
public static final String ANT_ENABLED_ACTION = "com.dsi.ant.intent.action.ANT_ENABLED";
|
public static final String ANT_ENABLED_ACTION = "com.dsi.ant.intent.action.ANT_ENABLED";
|
||||||
public static final String ANT_DISABLED_ACTION = "com.dsi.ant.intent.action.ANT_DISABLED";
|
public static final String ANT_DISABLED_ACTION = "com.dsi.ant.intent.action.ANT_DISABLED";
|
||||||
public static final String ANT_RESET_ACTION = "com.dsi.ant.intent.action.ANT_RESET";
|
public static final String ANT_RESET_ACTION = "com.dsi.ant.intent.action.ANT_RESET";
|
||||||
|
|
||||||
|
public static final String ANT_INTERFACE_CLAIMED_ACTION = "com.dsi.ant.intent.action.ANT_INTERFACE_CLAIMED_ACTION";
|
||||||
|
|
||||||
public static final String ANT_RX_MESSAGE_ACTION = "com.dsi.ant.intent.action.ANT_RX_MESSAGE_ACTION";
|
public static final String ANT_RX_MESSAGE_ACTION = "com.dsi.ant.intent.action.ANT_RX_MESSAGE_ACTION";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 Dynastream Innovations 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.dsi.ant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Android Ant API is not finalized, and *will* be updated and expanded.
|
||||||
|
* This is the base level ANT messaging API and gives any application full
|
||||||
|
* control over the ANT radio HW. Caution should be exercised when using
|
||||||
|
* this interface.
|
||||||
|
*
|
||||||
|
* Public API for controlling the Ant Service.
|
||||||
|
*
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
interface IAnt_6 {
|
||||||
|
// Since version 1 (1.0):
|
||||||
|
boolean enable();
|
||||||
|
boolean disable();
|
||||||
|
boolean isEnabled();
|
||||||
|
|
||||||
|
boolean ANTTxMessage(in byte[] message);
|
||||||
|
|
||||||
|
boolean ANTResetSystem();
|
||||||
|
boolean ANTUnassignChannel(byte channelNumber);
|
||||||
|
boolean ANTAssignChannel(byte channelNumber, byte channelType, byte networkNumber);
|
||||||
|
boolean ANTSetChannelId(byte channelNumber, int deviceNumber, byte deviceType, byte txType);
|
||||||
|
boolean ANTSetChannelPeriod(byte channelNumber, int channelPeriod);
|
||||||
|
boolean ANTSetChannelRFFreq(byte channelNumber, byte radioFrequency);
|
||||||
|
boolean ANTSetChannelSearchTimeout(byte channelNumber, byte searchTimeout);
|
||||||
|
boolean ANTSetLowPriorityChannelSearchTimeout(byte channelNumber, byte searchTimeout);
|
||||||
|
boolean ANTSetProximitySearch(byte channelNumber, byte searchThreshold);
|
||||||
|
boolean ANTSetChannelTxPower(byte channelNumber, byte txPower);
|
||||||
|
boolean ANTAddChannelId(byte channelNumber, int deviceNumber, byte deviceType, byte txType, byte listIndex);
|
||||||
|
boolean ANTConfigList(byte channelNumber, byte listSize, byte exclude);
|
||||||
|
|
||||||
|
boolean ANTOpenChannel(byte channelNumber);
|
||||||
|
boolean ANTCloseChannel(byte channelNumber);
|
||||||
|
|
||||||
|
boolean ANTRequestMessage(byte channelNumber, byte messageID);
|
||||||
|
boolean ANTSendBroadcastData(byte channelNumber, in byte[] txBuffer);
|
||||||
|
boolean ANTSendAcknowledgedData(byte channelNumber, in byte[] txBuffer);
|
||||||
|
|
||||||
|
boolean ANTSendBurstTransferPacket(byte control, in byte[] txBuffer);
|
||||||
|
|
||||||
|
int ANTSendBurstTransfer(byte channelNumber, in byte[] txBuffer);
|
||||||
|
int ANTTransmitBurst(byte channelNumber, in byte[] txBuffer, int initialPacket, boolean containsEndOfBurst);
|
||||||
|
|
||||||
|
// Since version 4 (1.3):
|
||||||
|
boolean ANTConfigEventBuffering(int screenOnFlushTimerInterval, int screenOnFlushBufferThreshold, int screenOffFlushTimerInterval, int screenOffFlushBufferThreshold);
|
||||||
|
|
||||||
|
// Since version 2 (1.1):
|
||||||
|
boolean ANTDisableEventBuffering();
|
||||||
|
|
||||||
|
// Since version 3 (1.2):
|
||||||
|
int getServiceLibraryVersionCode();
|
||||||
|
String getServiceLibraryVersionName();
|
||||||
|
|
||||||
|
// Since version 6 (1.5):
|
||||||
|
boolean claimInterface();
|
||||||
|
boolean requestForceClaimInterface(String appName);
|
||||||
|
boolean stopRequestForceClaimInterface();
|
||||||
|
boolean releaseInterface();
|
||||||
|
boolean hasClaimedInterface();
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 Dynastream Innovations 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.dsi.ant;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines version numbers
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class Version {
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
// Library Version Information
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
public static final int ANT_LIBRARY_VERSION_CODE = 6;
|
||||||
|
public static final int ANT_LIBRARY_VERSION_MAJOR = 2;
|
||||||
|
public static final int ANT_LIBRARY_VERSION_MINOR = 0;
|
||||||
|
public static final String ANT_LIBRARY_VERSION_NAME = String.valueOf(ANT_LIBRARY_VERSION_MAJOR) + "." + String.valueOf(ANT_LIBRARY_VERSION_MINOR);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.dsi.ant.exception;
|
||||||
|
|
||||||
|
public class AntInterfaceException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -7278855366167722274L;
|
||||||
|
|
||||||
|
public AntInterfaceException()
|
||||||
|
{
|
||||||
|
this("Unknown ANT Interface error");
|
||||||
|
}
|
||||||
|
|
||||||
|
public AntInterfaceException(String string)
|
||||||
|
{
|
||||||
|
super(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.dsi.ant.exception;
|
||||||
|
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
public class AntRemoteException extends AntInterfaceException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 8950974759973459561L;
|
||||||
|
|
||||||
|
public AntRemoteException(RemoteException e)
|
||||||
|
{
|
||||||
|
this("ANT Interface error, ANT Radio Service remote error: "+e.toString(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AntRemoteException(String string, RemoteException e)
|
||||||
|
{
|
||||||
|
super(string);
|
||||||
|
|
||||||
|
this.initCause(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.dsi.ant.exception;
|
||||||
|
|
||||||
|
public class AntServiceNotConnectedException extends AntInterfaceException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -2085081032170129309L;
|
||||||
|
|
||||||
|
public AntServiceNotConnectedException()
|
||||||
|
{
|
||||||
|
this("ANT Interface error, ANT Radio Service not connected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public AntServiceNotConnectedException(String string)
|
||||||
|
{
|
||||||
|
super(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,28 @@
|
|||||||
*/
|
*/
|
||||||
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.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.TrackDataHub;
|
||||||
import com.google.android.apps.mytracks.content.TrackPointsColumns;
|
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||||
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.TrackDataHub.ListenerDataType;
|
||||||
|
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 +48,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 +85,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 +96,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 +122,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 +136,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
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
unregisterContentObservers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
// Make sure any updates that might have happened are propagated to this
|
|
||||||
// activity:
|
dataHub.registerTrackDataListener(this, EnumSet.of(
|
||||||
observer.onChange(false);
|
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||||
waypointObserver.onChange(false);
|
ListenerDataType.POINT_UPDATES,
|
||||||
registerContentObservers();
|
ListenerDataType.SAMPLED_OUT_POINT_UPDATES,
|
||||||
|
ListenerDataType.WAYPOINT_UPDATES,
|
||||||
|
ListenerDataType.DISPLAY_PREFERENCES));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Register the content observer for the map overlay.
|
protected void onPause() {
|
||||||
*/
|
dataHub.unregisterTrackDataListener(this);
|
||||||
private void registerContentObservers() {
|
|
||||||
getContentResolver().registerContentObserver(TrackPointsColumns.CONTENT_URI,
|
|
||||||
false/* notifyForDescendents */, observer);
|
|
||||||
getContentResolver().registerContentObserver(WaypointsColumns.CONTENT_URI,
|
|
||||||
false/* notifyForDescendents */, waypointObserver);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
super.onPause();
|
||||||
* 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 +173,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 +190,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 +203,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,49 +225,47 @@ 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 / 1000.0;
|
||||||
if (lastLocation != null) {
|
if (lastLocation != null) {
|
||||||
double d = lastLocation.distanceTo(location);
|
double d = lastLocation.distanceTo(location);
|
||||||
if (metricUnits) {
|
if (metricUnits) {
|
||||||
profileLength += d / 1000.0;
|
profileLength += d;
|
||||||
} else {
|
} else {
|
||||||
profileLength += d * UnitConversions.KM_TO_MI / 1000.0;
|
profileLength += d * UnitConversions.KM_TO_MI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -489,16 +274,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 +292,151 @@ 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) {
|
||||||
|
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.
|
if (track == null || track.getStatistics() == null) {
|
||||||
*/
|
trackMaxSpeed = 0.0;
|
||||||
private void readProfile() {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trackMaxSpeed = track.getStatistics().getMaxSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearTrackPoints() {
|
||||||
profileLength = 0;
|
profileLength = 0;
|
||||||
lastLocation = null;
|
lastLocation = null;
|
||||||
startTime = -1;
|
startTime = -1;
|
||||||
if (selectedTrackId < 0) {
|
elevationBuffer.reset();
|
||||||
return;
|
chartView.reset();
|
||||||
}
|
speedBuffer.reset();
|
||||||
Track track = providerUtils.getTrack(selectedTrackId);
|
pendingPoints.clear();
|
||||||
if (track == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lastSeenLocationId = track.getStartId();
|
|
||||||
final ArrayList<double[]> theData = readPointsToList(track);
|
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
chartView.setDataPoints(theData);
|
chartView.resetScroll();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@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)) {
|
boolean changed = metric != this.metricUnits;
|
||||||
lastLocationRead = lastSeenLocationId =
|
if (!changed) return false;
|
||||||
cursor.getLong(idColumnIdx);
|
|
||||||
// TODO Can we be smarter about choosing 3 or 6 entries?
|
this.metricUnits = metric;
|
||||||
double[] point = new double[6];
|
|
||||||
location = getDataPoint(location, track, point);
|
chartView.setMetricUnits(metric);
|
||||||
if (points % chartSamplingFrequency == 0) {
|
|
||||||
result.add(point);
|
return true; // Reload data
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
@Override
|
||||||
} else {
|
public boolean onReportSpeedChanged(boolean reportSpeed) {
|
||||||
lastLocationRead += BUFFER_SIZE;
|
boolean changed = reportSpeed != this.reportSpeed;
|
||||||
}
|
if (!changed) return false;
|
||||||
} else {
|
|
||||||
lastLocationRead += BUFFER_SIZE;
|
this.reportSpeed = reportSpeed;
|
||||||
}
|
|
||||||
cursor.close();
|
chartView.setReportSpeed(reportSpeed, this);
|
||||||
cursor = null;
|
|
||||||
}
|
return true; // Reload data
|
||||||
return result;
|
|
||||||
} finally {
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009 Google Inc.
|
* Copyright 2009 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
* 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
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
* the License at
|
* the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
@@ -48,7 +48,7 @@ public class ChartValueSeries {
|
|||||||
private double spread;
|
private double spread;
|
||||||
private int interval;
|
private int interval;
|
||||||
private boolean enabled = true;
|
private boolean enabled = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class controls how effective min/max values of a {@link ChartValueSeries} are calculated.
|
* This class controls how effective min/max values of a {@link ChartValueSeries} are calculated.
|
||||||
*/
|
*/
|
||||||
@@ -70,10 +70,10 @@ public class ChartValueSeries {
|
|||||||
this.intervals = intervals;
|
this.intervals = intervals;
|
||||||
this.absoluteMin = absoluteMin;
|
this.absoluteMin = absoluteMin;
|
||||||
this.absoluteMax = absoluteMax;
|
this.absoluteMax = absoluteMax;
|
||||||
this.zoomLevels = zoomLevels;
|
this.zoomLevels = zoomLevels;
|
||||||
checkArgs();
|
checkArgs();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkArgs() {
|
private void checkArgs() {
|
||||||
if (intervals <= 0 || zoomLevels == null || zoomLevels.length == 0) {
|
if (intervals <= 0 || zoomLevels == null || zoomLevels.length == 0) {
|
||||||
throw new IllegalArgumentException("Expecing positive intervals and non-empty zoom levels");
|
throw new IllegalArgumentException("Expecing positive intervals and non-empty zoom levels");
|
||||||
@@ -100,12 +100,12 @@ public class ChartValueSeries {
|
|||||||
public int[] getZoomLevels() {
|
public int[] getZoomLevels() {
|
||||||
return zoomLevels;
|
return zoomLevels;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the interval between markings given the min and max values.
|
* Calculates the interval between markings given the min and max values.
|
||||||
* This function attempts to find the smallest zoom level that fits [min,max] after rounding
|
* This function attempts to find the smallest zoom level that fits [min,max] after rounding
|
||||||
* it to the current zoom level.
|
* it to the current zoom level.
|
||||||
*
|
*
|
||||||
* @param min the minimum value in the series
|
* @param min the minimum value in the series
|
||||||
* @param max the maximum value in the series
|
* @param max the maximum value in the series
|
||||||
* @return the calculated interval for the given range
|
* @return the calculated interval for the given range
|
||||||
@@ -136,7 +136,7 @@ public class ChartValueSeries {
|
|||||||
* @param fill The paint for filling the chart
|
* @param fill The paint for filling the chart
|
||||||
* @param stroke The paint for stroking the outside the chart, optional
|
* @param stroke The paint for stroking the outside the chart, optional
|
||||||
* @param zoomSettings The settings related to zooming
|
* @param zoomSettings The settings related to zooming
|
||||||
*
|
*
|
||||||
* TODO: Get rid of Context and inject appropriate values instead.
|
* TODO: Get rid of Context and inject appropriate values instead.
|
||||||
*/
|
*/
|
||||||
public ChartValueSeries(Context context, String formatString, int fillColor, int strokeColor,
|
public ChartValueSeries(Context context, String formatString, int fillColor, int strokeColor,
|
||||||
@@ -207,7 +207,7 @@ public class ChartValueSeries {
|
|||||||
}
|
}
|
||||||
min = Math.min(min, zoomSettings.getAbsoluteMin());
|
min = Math.min(min, zoomSettings.getAbsoluteMin());
|
||||||
max = Math.max(max, zoomSettings.getAbsoluteMax());
|
max = Math.max(max, zoomSettings.getAbsoluteMax());
|
||||||
|
|
||||||
this.interval = zoomSettings.calculateInterval(min, max);
|
this.interval = zoomSettings.calculateInterval(min, max);
|
||||||
// Round it up.
|
// Round it up.
|
||||||
effectiveMax = ((int) (max / interval)) * interval + interval;
|
effectiveMax = ((int) (max / interval)) * interval + interval;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008 Google Inc.
|
* Copyright 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
* 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
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
* the License at
|
* the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
@@ -28,9 +28,9 @@ import android.graphics.Canvas;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.DashPathEffect;
|
import android.graphics.DashPathEffect;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Path;
|
|
||||||
import android.graphics.Paint.Align;
|
import android.graphics.Paint.Align;
|
||||||
import android.graphics.Paint.Style;
|
import android.graphics.Paint.Style;
|
||||||
|
import android.graphics.Path;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.VelocityTracker;
|
import android.view.VelocityTracker;
|
||||||
@@ -66,36 +66,38 @@ public class ChartView extends View {
|
|||||||
private int maxZoomLevel = 10;
|
private int maxZoomLevel = 10;
|
||||||
|
|
||||||
private static final int MAX_INTERVALS = 5;
|
private static final int MAX_INTERVALS = 5;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Borders, margins, dimensions (in pixels):
|
* Borders, margins, dimensions (in pixels):
|
||||||
*/
|
*/
|
||||||
private int leftBorder = -1;
|
private int leftBorder = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unscaled top border of the chart.
|
* Unscaled top border of the chart.
|
||||||
*/
|
*/
|
||||||
private static final int TOP_BORDER = 15;
|
private static final int TOP_BORDER = 15;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Device scaled top border of the chart.
|
* Device scaled top border of the chart.
|
||||||
*/
|
*/
|
||||||
private int topBorder;
|
private int topBorder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unscaled bottom border of the chart.
|
* Unscaled bottom border of the chart.
|
||||||
*/
|
*/
|
||||||
private static final float BOTTOM_BORDER = 40;
|
private static final float BOTTOM_BORDER = 40;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Device scaled bottom border of the chart.
|
* Device scaled bottom border of the chart.
|
||||||
*/
|
*/
|
||||||
private int bottomBorder;
|
private int bottomBorder;
|
||||||
|
|
||||||
private static final int RIGHT_BORDER = 17;
|
private static final int RIGHT_BORDER = 17;
|
||||||
|
|
||||||
/** Space to leave for drawing the unit labels */
|
/** Space to leave for drawing the unit labels */
|
||||||
private static final int UNIT_BORDER = 15;
|
private static final int UNIT_BORDER = 15;
|
||||||
private static final int FONT_HEIGHT = 10;
|
private static final int FONT_HEIGHT = 10;
|
||||||
|
|
||||||
private int w = 0;
|
private int w = 0;
|
||||||
private int h = 0;
|
private int h = 0;
|
||||||
private int effectiveWidth = 0;
|
private int effectiveWidth = 0;
|
||||||
@@ -118,11 +120,11 @@ public class ChartView extends View {
|
|||||||
private ChartValueSeries[] series;
|
private ChartValueSeries[] series;
|
||||||
|
|
||||||
private final ExtremityMonitor xMonitor = new ExtremityMonitor();
|
private final ExtremityMonitor xMonitor = new ExtremityMonitor();
|
||||||
private final NumberFormat xFormat = new DecimalFormat("###,###");
|
private static final NumberFormat X_FORMAT = new DecimalFormat("###,###");
|
||||||
private final NumberFormat xShortFormat = new DecimalFormat("#.0");
|
private static final NumberFormat X_SHORT_FORMAT = new DecimalFormat("#.0");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Paints etc. used when drawing the histogram:
|
* Paints etc. used when drawing the chart:
|
||||||
*/
|
*/
|
||||||
private final Paint borderPaint = new Paint();
|
private final Paint borderPaint = new Paint();
|
||||||
private final Paint labelPaint = new Paint();
|
private final Paint labelPaint = new Paint();
|
||||||
@@ -174,7 +176,7 @@ public class ChartView extends View {
|
|||||||
|
|
||||||
gridBarPaint.set(gridPaint);
|
gridBarPaint.set(gridPaint);
|
||||||
gridBarPaint.setPathEffect(new DashPathEffect(new float[] {3, 2}, 0));
|
gridBarPaint.setPathEffect(new DashPathEffect(new float[] {3, 2}, 0));
|
||||||
|
|
||||||
clearPaint.setStyle(Style.FILL);
|
clearPaint.setStyle(Style.FILL);
|
||||||
clearPaint.setColor(context.getResources().getColor(R.color.white));
|
clearPaint.setColor(context.getResources().getColor(R.color.white));
|
||||||
clearPaint.setAntiAlias(false);
|
clearPaint.setAntiAlias(false);
|
||||||
@@ -271,49 +273,12 @@ public class ChartView extends View {
|
|||||||
: R.string.pace_label));
|
: R.string.pace_label));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the data that is displayed by the chart.
|
|
||||||
*
|
|
||||||
* @return an array list with data points
|
|
||||||
*/
|
|
||||||
public ArrayList<double[]> getData() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the data that is to be displayed by the chart.
|
|
||||||
*
|
|
||||||
* @param theData an array list of data points
|
|
||||||
*/
|
|
||||||
public synchronized void setDataPoints(ArrayList<double[]> theData) {
|
|
||||||
scrollTo(0, 0);
|
|
||||||
zoomLevel = 1;
|
|
||||||
data.clear();
|
|
||||||
xMonitor.reset();
|
|
||||||
for (ChartValueSeries cvs : series) {
|
|
||||||
cvs.reset();
|
|
||||||
}
|
|
||||||
addDataPoints(theData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new data point to the chart.
|
|
||||||
*
|
|
||||||
* @param theData a data point
|
|
||||||
*/
|
|
||||||
public synchronized void addDataPoint(double[] theData) {
|
|
||||||
data.add(theData);
|
|
||||||
addDataPointInternal(theData);
|
|
||||||
updateDimensions();
|
|
||||||
setUpPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addDataPointInternal(double[] theData) {
|
private void addDataPointInternal(double[] theData) {
|
||||||
xMonitor.update(theData[0]);
|
xMonitor.update(theData[0]);
|
||||||
int min = Math.min(series.length, theData.length - 1);
|
int min = Math.min(series.length, theData.length - 1);
|
||||||
for (int i = 0; i < min; i++) {
|
for (int i = 1; i <= min; i++) {
|
||||||
if (!Double.isNaN(theData[i + 1])) {
|
if (!Double.isNaN(theData[i])) {
|
||||||
series[i].update(theData[i + 1]);
|
series[i - 1].update(theData[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fill in the extra's if needed.
|
// Fill in the extra's if needed.
|
||||||
@@ -329,25 +294,32 @@ public class ChartView extends View {
|
|||||||
*
|
*
|
||||||
* @param theData an array list of data points to be added
|
* @param theData an array list of data points to be added
|
||||||
*/
|
*/
|
||||||
public synchronized void addDataPoints(ArrayList<double[]> theData) {
|
public void addDataPoints(ArrayList<double[]> theData) {
|
||||||
data.addAll(theData);
|
synchronized (data) {
|
||||||
for (int i = 0; i < theData.size(); i++) {
|
data.addAll(theData);
|
||||||
double d[] = theData.get(i);
|
for (int i = 0; i < theData.size(); i++) {
|
||||||
addDataPointInternal(d);
|
double d[] = theData.get(i);
|
||||||
|
addDataPointInternal(d);
|
||||||
|
}
|
||||||
|
updateDimensions();
|
||||||
|
setUpPath();
|
||||||
}
|
}
|
||||||
updateDimensions();
|
|
||||||
setUpPath();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all data.
|
* Clears all data.
|
||||||
* Call this only from the UI thread!
|
|
||||||
*/
|
*/
|
||||||
public synchronized void reset() {
|
public void reset() {
|
||||||
data.clear();
|
synchronized (data) {
|
||||||
zoomLevel = 1;
|
data.clear();
|
||||||
|
xMonitor.reset();
|
||||||
|
zoomLevel = 1;
|
||||||
|
updateDimensions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetScroll() {
|
||||||
scrollTo(0, 0);
|
scrollTo(0, 0);
|
||||||
updateDimensions();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -392,13 +364,6 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the current zoom level (1 equals to showing all data points)
|
|
||||||
*/
|
|
||||||
public int getZoomLevel() {
|
|
||||||
return zoomLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiates flinging.
|
* Initiates flinging.
|
||||||
*
|
*
|
||||||
@@ -427,14 +392,6 @@ public class ChartView extends View {
|
|||||||
scrollTo(scrollX, 0);
|
scrollTo(scrollX, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the scroll position of the chart. This will trigger a redraw.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void scrollTo(int x, int y) {
|
|
||||||
super.scrollTo(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the current display mode (by distance, by time)
|
* @return the current display mode (by distance, by time)
|
||||||
*/
|
*/
|
||||||
@@ -527,8 +484,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;
|
||||||
}
|
}
|
||||||
@@ -551,38 +508,82 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected synchronized void onDraw(Canvas c) {
|
protected void onDraw(Canvas c) {
|
||||||
if (w != c.getWidth() || h != c.getHeight()) {
|
synchronized (data) {
|
||||||
// Dimensions have changed (for example due to orientation change).
|
updateEffectiveDimensionsIfChanged(c);
|
||||||
w = c.getWidth();
|
|
||||||
h = c.getHeight();
|
|
||||||
effectiveWidth = Math.max(0, w - leftBorder - RIGHT_BORDER);
|
|
||||||
effectiveHeight = Math.max(0, h - topBorder - bottomBorder);
|
|
||||||
setUpPath();
|
|
||||||
}
|
|
||||||
c.save();
|
|
||||||
c.drawColor(Color.WHITE);
|
|
||||||
if (data.size() < 1) {
|
|
||||||
drawXAxis(c);
|
|
||||||
drawYAxis(c);
|
|
||||||
c.restore();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
c.save();
|
|
||||||
c.clipRect(leftBorder + 1 + getScrollX(), topBorder + 1,
|
|
||||||
w - RIGHT_BORDER + getScrollX() - 1, h - bottomBorder - 1);
|
|
||||||
|
|
||||||
drawGrid(c);
|
// Keep original state.
|
||||||
|
c.save();
|
||||||
// Draw the data series.
|
|
||||||
for (ChartValueSeries cvs : series) {
|
c.drawColor(Color.WHITE);
|
||||||
if (cvs.isEnabled() && cvs.hasData()) {
|
|
||||||
cvs.drawPath(c);
|
if (data.isEmpty()) {
|
||||||
|
// No data, draw only axes
|
||||||
|
drawXAxis(c);
|
||||||
|
drawYAxis(c);
|
||||||
|
c.restore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clip to graph drawing space
|
||||||
|
c.save();
|
||||||
|
clipToGraphSpace(c);
|
||||||
|
|
||||||
|
// Draw the grid and the data on it.
|
||||||
|
drawGrid(c);
|
||||||
|
drawDataSeries(c);
|
||||||
|
drawWaypoints(c);
|
||||||
|
|
||||||
|
// Go back to full canvas drawing.
|
||||||
|
c.restore();
|
||||||
|
|
||||||
|
// Draw the axes and their labels.
|
||||||
|
drawAxesAndLabels(c);
|
||||||
|
|
||||||
|
// Go back to original state.
|
||||||
|
c.restore();
|
||||||
|
|
||||||
|
// Draw the pointer
|
||||||
|
if (showPointer) {
|
||||||
|
drawPointer(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Draw the waypoints.
|
|
||||||
|
/** Clips the given canvas to the area where the graph lines should be drawn. */
|
||||||
|
private void clipToGraphSpace(Canvas c) {
|
||||||
|
c.clipRect(leftBorder + 1 + getScrollX(), topBorder + 1,
|
||||||
|
w - RIGHT_BORDER + getScrollX() - 1, h - bottomBorder - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Draws the axes and their labels into th e given canvas. */
|
||||||
|
private void drawAxesAndLabels(Canvas c) {
|
||||||
|
drawXLabels(c);
|
||||||
|
drawXAxis(c);
|
||||||
|
drawSeriesTitles(c);
|
||||||
|
|
||||||
|
c.translate(getScrollX(), 0);
|
||||||
|
drawYAxis(c);
|
||||||
|
float density = getContext().getResources().getDisplayMetrics().density;
|
||||||
|
final int spacer = (int) (5 * density);
|
||||||
|
int x = leftBorder - spacer;
|
||||||
|
for (ChartValueSeries cvs : series) {
|
||||||
|
if (cvs.isEnabled() && cvs.hasData()) {
|
||||||
|
x -= drawYLabels(cvs, c, x) + spacer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Draws the current pointer into the given canvas. */
|
||||||
|
private void drawPointer(Canvas c) {
|
||||||
|
c.translate(getX(maxX) - pointer.getIntrinsicWidth() / 2,
|
||||||
|
getY(series[0], data.get(data.size() - 1)[1])
|
||||||
|
- pointer.getIntrinsicHeight() / 2 - 12);
|
||||||
|
pointer.draw(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Draws the waypoints into the given canvas. */
|
||||||
|
private void drawWaypoints(Canvas c) {
|
||||||
for (int i = 1; i < waypoints.size(); i++) {
|
for (int i = 1; i < waypoints.size(); i++) {
|
||||||
final Waypoint waypoint = waypoints.get(i);
|
final Waypoint waypoint = waypoints.get(i);
|
||||||
if (waypoint.getLocation() == null) {
|
if (waypoint.getLocation() == null) {
|
||||||
@@ -600,33 +601,18 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
c.restore();
|
c.restore();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.restore();
|
/** Draws the data series into the given canvas. */
|
||||||
|
private void drawDataSeries(Canvas c) {
|
||||||
// Draw the axis and labels.
|
|
||||||
drawXLabels(c);
|
|
||||||
drawXAxis(c);
|
|
||||||
drawSeriesTitles(c);
|
|
||||||
|
|
||||||
c.translate(getScrollX(), 0);
|
|
||||||
drawYAxis(c);
|
|
||||||
float density = getContext().getResources().getDisplayMetrics().density;
|
|
||||||
final int spacer = (int) (5 * density);
|
|
||||||
int x = leftBorder - spacer;
|
|
||||||
for (ChartValueSeries cvs : series) {
|
for (ChartValueSeries cvs : series) {
|
||||||
if (cvs.isEnabled() && cvs.hasData()) {
|
if (cvs.isEnabled() && cvs.hasData()) {
|
||||||
x -= drawYLabels(cvs, c, x) + spacer;
|
cvs.drawPath(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.restore();
|
|
||||||
if (showPointer && !data.isEmpty()) {
|
|
||||||
c.translate(getX(maxX) - pointer.getIntrinsicWidth() / 2,
|
|
||||||
getY(series[0], data.get(data.size() - 1)[1])
|
|
||||||
- pointer.getIntrinsicHeight() / 2 - 12);
|
|
||||||
pointer.draw(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Draws the colored titles for the data series. */
|
||||||
private void drawSeriesTitles(Canvas c) {
|
private void drawSeriesTitles(Canvas c) {
|
||||||
int sections = 1;
|
int sections = 1;
|
||||||
for (ChartValueSeries cvs : series) {
|
for (ChartValueSeries cvs : series) {
|
||||||
@@ -644,17 +630,24 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the path that is used to draw the histogram in onDraw(). The path
|
* Sets up the path that is used to draw the chart in onDraw(). The path
|
||||||
* needs to be updated any time after the data or histogram dimensions change.
|
* needs to be updated any time after the data or histogram dimensions change.
|
||||||
*/
|
*/
|
||||||
private synchronized void setUpPath() {
|
private void setUpPath() {
|
||||||
for (ChartValueSeries cvs : series) {
|
synchronized (data) {
|
||||||
cvs.getPath().reset();
|
for (ChartValueSeries cvs : series) {
|
||||||
}
|
cvs.getPath().reset();
|
||||||
if (data.isEmpty()) {
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!data.isEmpty()) {
|
||||||
|
drawPaths();
|
||||||
|
closePaths();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actually draws the data points as a path. */
|
||||||
|
private void drawPaths() {
|
||||||
// All of the data points to the respective series.
|
// All of the data points to the respective series.
|
||||||
// TODO: Come up with a better sampling than Math.max(1, (maxZoomLevel - zoomLevel + 1) / 2);
|
// TODO: Come up with a better sampling than Math.max(1, (maxZoomLevel - zoomLevel + 1) / 2);
|
||||||
int sampling = 1;
|
int sampling = 1;
|
||||||
@@ -673,7 +666,10 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Closes the drawn path so it looks like a solid graph. */
|
||||||
|
private void closePaths() {
|
||||||
// Close the path.
|
// Close the path.
|
||||||
int yCorner = topBorder + effectiveHeight;
|
int yCorner = topBorder + effectiveHeight;
|
||||||
int xCorner = getX(data.get(0)[0]);
|
int xCorner = getX(data.get(0)[0]);
|
||||||
@@ -692,12 +688,13 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the index of the first point which has a series populated.
|
* Finds the index of the first point which has a series populated.
|
||||||
* @param seriesIndex The index of the value series to search for.
|
*
|
||||||
|
* @param seriesIndex The index of the value series to search for
|
||||||
* @return The index in the first data for the point in the series that has series
|
* @return The index in the first data for the point in the series that has series
|
||||||
* index value populated or -1 if none is found.
|
* index value populated or -1 if none is found
|
||||||
*/
|
*/
|
||||||
private int getFirstPointPopulatedIndex(int seriesIndex) {
|
private int getFirstPointPopulatedIndex(int seriesIndex) {
|
||||||
for (int i = 0; i < data.size(); i++) {
|
for (int i = 0; i < data.size(); i++) {
|
||||||
@@ -709,7 +706,7 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the histogram dimensions.
|
* Updates the chart dimensions.
|
||||||
*/
|
*/
|
||||||
private void updateDimensions() {
|
private void updateDimensions() {
|
||||||
maxX = xMonitor.getMax();
|
maxX = xMonitor.getMax();
|
||||||
@@ -728,12 +725,31 @@ 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;
|
|
||||||
bottomBorder = (int) (density * BOTTOM_BORDER);
|
bottomBorder = (int) (density * BOTTOM_BORDER);
|
||||||
topBorder = (int) (density * TOP_BORDER);
|
topBorder = (int) (density * TOP_BORDER);
|
||||||
effectiveHeight = h - topBorder - bottomBorder;
|
updateEffectiveDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Updates the effective dimensions where the graph will be drawn. */
|
||||||
|
private void updateEffectiveDimensions() {
|
||||||
|
effectiveWidth = Math.max(0, w - leftBorder - RIGHT_BORDER);
|
||||||
|
effectiveHeight = Math.max(0, h - topBorder - bottomBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the effective dimensions where the graph will be drawn, only if the
|
||||||
|
* dimensions of the given canvas have changed since the last call.
|
||||||
|
*/
|
||||||
|
private void updateEffectiveDimensionsIfChanged(Canvas c) {
|
||||||
|
if (w != c.getWidth() || h != c.getHeight()) {
|
||||||
|
// Dimensions have changed (for example due to orientation change).
|
||||||
|
w = c.getWidth();
|
||||||
|
h = c.getHeight();
|
||||||
|
updateEffectiveDimensions();
|
||||||
|
setUpPath();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getX(double distance) {
|
private int getX(double distance) {
|
||||||
@@ -746,6 +762,7 @@ public class ChartView extends View {
|
|||||||
- (int) ((y - cvs.getMin()) * effectiveHeight / effectiveSpread);
|
- (int) ((y - cvs.getMin()) * effectiveHeight / effectiveSpread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Draws the labels on the X axis into the given canvas. */
|
||||||
private void drawXLabels(Canvas c) {
|
private void drawXLabels(Canvas c) {
|
||||||
double interval = (int) (maxX / zoomLevel / 4);
|
double interval = (int) (maxX / zoomLevel / 4);
|
||||||
boolean shortFormat = false;
|
boolean shortFormat = false;
|
||||||
@@ -770,6 +787,7 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Draws the labels on the Y axis into the given canvas. */
|
||||||
private float drawYLabels(ChartValueSeries cvs, Canvas c, int x) {
|
private float drawYLabels(ChartValueSeries cvs, Canvas c, int x) {
|
||||||
int interval = cvs.getInterval();
|
int interval = cvs.getInterval();
|
||||||
float maxTextWidth = 0;
|
float maxTextWidth = 0;
|
||||||
@@ -779,13 +797,14 @@ public class ChartView extends View {
|
|||||||
return maxTextWidth;
|
return maxTextWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Draws a single label on the X axis. */
|
||||||
private void drawXLabel(Canvas c, double x, boolean shortFormat) {
|
private void drawXLabel(Canvas c, double x, boolean shortFormat) {
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String s =
|
String s =
|
||||||
(mode == Mode.BY_DISTANCE)
|
(mode == Mode.BY_DISTANCE)
|
||||||
? (shortFormat ? xShortFormat.format(x) : xFormat.format(x))
|
? (shortFormat ? X_SHORT_FORMAT.format(x) : X_FORMAT.format(x))
|
||||||
: StringUtils.formatTime((long) x);
|
: StringUtils.formatTime((long) x);
|
||||||
c.drawText(s,
|
c.drawText(s,
|
||||||
getX(x),
|
getX(x),
|
||||||
@@ -793,6 +812,7 @@ public class ChartView extends View {
|
|||||||
labelPaint);
|
labelPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Draws a single label on the Y axis. */
|
||||||
private float drawYLabel(ChartValueSeries cvs, Canvas c, int x, int y) {
|
private float drawYLabel(ChartValueSeries cvs, Canvas c, int x, int y) {
|
||||||
int desiredY = (int) ((y - cvs.getMin()) * effectiveHeight /
|
int desiredY = (int) ((y - cvs.getMin()) * effectiveHeight /
|
||||||
(cvs.getInterval() * MAX_INTERVALS));
|
(cvs.getInterval() * MAX_INTERVALS));
|
||||||
@@ -804,6 +824,7 @@ public class ChartView extends View {
|
|||||||
return p.measureText(text);
|
return p.measureText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Draws the actual X axis line and its label. */
|
||||||
private void drawXAxis(Canvas canvas) {
|
private void drawXAxis(Canvas canvas) {
|
||||||
float rightEdge = getX(maxX);
|
float rightEdge = getX(maxX);
|
||||||
final int y = effectiveHeight + topBorder;
|
final int y = effectiveHeight + topBorder;
|
||||||
@@ -815,6 +836,7 @@ public class ChartView extends View {
|
|||||||
canvas.drawText(s, rightEdge, effectiveHeight + .2f * UNIT_BORDER + topBorder, labelPaint);
|
canvas.drawText(s, rightEdge, effectiveHeight + .2f * UNIT_BORDER + topBorder, labelPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Draws the actual Y axis line and its label. */
|
||||||
private void drawYAxis(Canvas canvas) {
|
private void drawYAxis(Canvas canvas) {
|
||||||
canvas.drawRect(0, 0,
|
canvas.drawRect(0, 0,
|
||||||
leftBorder - 1, effectiveHeight + topBorder + UNIT_BORDER + 1,
|
leftBorder - 1, effectiveHeight + topBorder + UNIT_BORDER + 1,
|
||||||
@@ -826,18 +848,15 @@ public class ChartView extends View {
|
|||||||
int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
|
int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
|
||||||
canvas.drawLine(leftBorder - 5, y, leftBorder, y, gridPaint);
|
canvas.drawLine(leftBorder - 5, y, leftBorder, y, gridPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
Context c = getContext();
|
Context c = getContext();
|
||||||
// TODO: This should really show units for all series.
|
// TODO: This should really show units for all series.
|
||||||
String s = metricUnits ? c.getString(R.string.meter) : c.getString(R.string.feet);
|
String s = metricUnits ? c.getString(R.string.meter) : c.getString(R.string.feet);
|
||||||
canvas.drawText(s, leftBorder - UNIT_BORDER * .2f, UNIT_BORDER * .8f + topBorder, labelPaint);
|
canvas.drawText(s, leftBorder - UNIT_BORDER * .2f, UNIT_BORDER * .8f + topBorder, labelPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void drawGrid(Canvas c) {
|
/** Draws the grid for the graph. */
|
||||||
if (data.isEmpty()) {
|
private void drawGrid(Canvas c) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float rightEdge = getX(maxX);
|
float rightEdge = getX(maxX);
|
||||||
for (int i = 1; i < MAX_INTERVALS; ++i) {
|
for (int i = 1; i < MAX_INTERVALS; ++i) {
|
||||||
int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
|
int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+75
-54
@@ -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) {
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010 Google Inc.
|
* Copyright 2010 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
* 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
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
* the License at
|
* the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
@@ -15,20 +15,22 @@
|
|||||||
*/
|
*/
|
||||||
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to handle all dialog related events for My Tracks.
|
* A class to handle all dialog related events for My Tracks.
|
||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
*/
|
*/
|
||||||
public class DialogManager {
|
public class DialogManager {
|
||||||
@@ -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;
|
||||||
@@ -52,7 +50,7 @@ public class DialogManager {
|
|||||||
public DialogManager(MyTracks activity) {
|
public DialogManager(MyTracks activity) {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Dialog onCreateDialog(int id, Bundle args) {
|
protected Dialog onCreateDialog(int id, Bundle args) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case DIALOG_CHART_SETTINGS:
|
case DIALOG_CHART_SETTINGS:
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -146,7 +104,7 @@ public class DialogManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProgressValue(final int percent) {
|
public void setProgressValue(final int percent) {
|
||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -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,21 +17,20 @@ 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.SystemUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.os.PowerManager;
|
|
||||||
import android.os.PowerManager.WakeLock;
|
import android.os.PowerManager.WakeLock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
@@ -72,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);
|
||||||
@@ -114,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) {
|
||||||
acquireWakeLock();
|
wakeLock = SystemUtils.acquireWakeLock(activity, wakeLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we can safely export everything.
|
// Now we can safely export everything.
|
||||||
@@ -131,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,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() {
|
||||||
@@ -187,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();
|
||||||
@@ -211,40 +210,4 @@ public class ExportAllTracks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to acquire a partial wake lock if not already acquired. Logs errors
|
|
||||||
* and gives up trying in case the wake lock cannot be acquired.
|
|
||||||
*/
|
|
||||||
private void acquireWakeLock() {
|
|
||||||
Log.i(MyTracksConstants.TAG, "ExportAllTracks: Aquiring wake lock.");
|
|
||||||
try {
|
|
||||||
PowerManager pm =
|
|
||||||
(PowerManager) activity.getSystemService(Context.POWER_SERVICE);
|
|
||||||
if (pm == null) {
|
|
||||||
Log.e(MyTracksConstants.TAG,
|
|
||||||
"ExportAllTracks: Power manager not found!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (wakeLock == null) {
|
|
||||||
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
|
|
||||||
MyTracksConstants.TAG);
|
|
||||||
if (wakeLock == null) {
|
|
||||||
Log.e(MyTracksConstants.TAG,
|
|
||||||
"ExportAllTracks: Could not create wake lock (null).");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!wakeLock.isHeld()) {
|
|
||||||
wakeLock.acquire();
|
|
||||||
if (!wakeLock.isHeld()) {
|
|
||||||
Log.e(MyTracksConstants.TAG,
|
|
||||||
"ExportAllTracks: Could not acquire wake lock.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
Log.e(MyTracksConstants.TAG,
|
|
||||||
"ExportAllTracks: Caught unexpected exception: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
* 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.MyTracksProviderUtils;
|
||||||
|
import com.google.android.apps.mytracks.io.file.GpxImporter;
|
||||||
|
import com.google.android.apps.mytracks.util.FileUtils;
|
||||||
|
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||||
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.ProgressDialog;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.os.PowerManager.WakeLock;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that will import all GPX tracks in /sdcard/MyTracks/gpx/
|
||||||
|
*
|
||||||
|
* @author David Piggott
|
||||||
|
*/
|
||||||
|
public class ImportAllTracks {
|
||||||
|
|
||||||
|
private final Activity activity;
|
||||||
|
private WakeLock wakeLock;
|
||||||
|
private ProgressDialog progress;
|
||||||
|
private FileUtils fileUtils;
|
||||||
|
private String gpxPath;
|
||||||
|
private int gpxFileCount;
|
||||||
|
private int importSuccessCount;
|
||||||
|
|
||||||
|
public ImportAllTracks(Activity activity) {
|
||||||
|
this.activity = activity;
|
||||||
|
Log.i(Constants.TAG, "ImportAllTracks: Starting");
|
||||||
|
fileUtils = new FileUtils();
|
||||||
|
gpxPath = fileUtils.buildExternalDirectoryPath("gpx");
|
||||||
|
HandlerThread handlerThread;
|
||||||
|
Handler handler;
|
||||||
|
handlerThread = new HandlerThread("ImportAllTracks");
|
||||||
|
handlerThread.start();
|
||||||
|
handler = new Handler(handlerThread.getLooper());
|
||||||
|
handler.post(runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Runnable runner = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
aquireLocksAndImport();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes sure that we keep the phone from sleeping. See if there is a current
|
||||||
|
* track. Acquire a wake lock if there is no current track.
|
||||||
|
*/
|
||||||
|
private void aquireLocksAndImport() {
|
||||||
|
SharedPreferences prefs = activity.getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||||
|
long recordingTrackId = -1;
|
||||||
|
if (prefs != null) {
|
||||||
|
recordingTrackId = prefs.getLong(activity.getString(R.string.recording_track_key), -1);
|
||||||
|
}
|
||||||
|
if (recordingTrackId != -1) {
|
||||||
|
wakeLock = SystemUtils.acquireWakeLock(activity, wakeLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we can safely import everything.
|
||||||
|
importAll();
|
||||||
|
|
||||||
|
// Release the wake lock if we acquired one.
|
||||||
|
// TODO check what happens if we started recording after getting this lock.
|
||||||
|
if (wakeLock != null && wakeLock.isHeld()) {
|
||||||
|
wakeLock.release();
|
||||||
|
Log.i(Constants.TAG, "ImportAllTracks: Releasing wake lock.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(Constants.TAG, "ImportAllTracks: Done");
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
|
if (gpxFileCount == 0) {
|
||||||
|
builder.setMessage(activity.getString(R.string.import_empty, gpxPath + "/"));
|
||||||
|
} else {
|
||||||
|
builder.setMessage(activity.getString(R.string.import_done, importSuccessCount, gpxFileCount,
|
||||||
|
gpxPath + "/"));
|
||||||
|
}
|
||||||
|
builder.setPositiveButton(R.string.ok, null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeProgressDialog(final int trackCount) {
|
||||||
|
String importMsg = activity.getString(R.string.tracklist_btn_import_all);
|
||||||
|
progress = new ProgressDialog(activity);
|
||||||
|
progress.setIcon(android.R.drawable.ic_dialog_info);
|
||||||
|
progress.setTitle(importMsg);
|
||||||
|
progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||||
|
progress.setMax(trackCount);
|
||||||
|
progress.setProgress(0);
|
||||||
|
progress.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually import the tracks. This should be called after the wake locks have
|
||||||
|
* been acquired.
|
||||||
|
*/
|
||||||
|
private void importAll() {
|
||||||
|
MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(activity);
|
||||||
|
|
||||||
|
if (!fileUtils.isSdCardAvailable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<File> gpxFiles = getGpxFiles();
|
||||||
|
gpxFileCount = gpxFiles.size();
|
||||||
|
if (gpxFileCount == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(Constants.TAG, "ImportAllTracks: Importing: " + gpxFileCount + " tracks.");
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
makeProgressDialog(gpxFileCount);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Iterator<File> gpxFilesIterator = gpxFiles.iterator();
|
||||||
|
for (int currentFileNumber = 0; gpxFilesIterator.hasNext(); currentFileNumber++) {
|
||||||
|
File currentFile = gpxFilesIterator.next();
|
||||||
|
final int status = currentFileNumber;
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (progress == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
progress.setProgress(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (importFile(currentFile, providerUtils)) {
|
||||||
|
importSuccessCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress != null) {
|
||||||
|
synchronized (this) {
|
||||||
|
progress.dismiss();
|
||||||
|
progress = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to import a GPX file. Returns true on success, issues error
|
||||||
|
* notifications and returns false on failure.
|
||||||
|
*/
|
||||||
|
private boolean importFile(File gpxFile, MyTracksProviderUtils providerUtils) {
|
||||||
|
Log.i(Constants.TAG, "ImportAllTracks: importing: " + gpxFile.getName());
|
||||||
|
try {
|
||||||
|
GpxImporter.importGPXFile(new FileInputStream(gpxFile), providerUtils);
|
||||||
|
return true;
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Log.w(Constants.TAG, "GPX file wasn't found/went missing: "
|
||||||
|
+ gpxFile.getAbsolutePath(), e);
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
Log.w(Constants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e);
|
||||||
|
} catch (SAXException e) {
|
||||||
|
Log.w(Constants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(Constants.TAG, "Error reading file: " + gpxFile.getAbsolutePath(), e);
|
||||||
|
}
|
||||||
|
Toast.makeText(activity, activity.getString(R.string.import_error, gpxFile.getName()),
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of the GPX Files found in the GPX directory.
|
||||||
|
*/
|
||||||
|
private List<File> getGpxFiles() {
|
||||||
|
List<File> gpxFiles = new LinkedList<File>();
|
||||||
|
File[] gpxFileCandidates = new File(gpxPath).listFiles();
|
||||||
|
if (gpxFileCandidates != null) {
|
||||||
|
for (File file : gpxFileCandidates) {
|
||||||
|
if (!file.isDirectory() && file.getName().endsWith(".gpx")) {
|
||||||
|
gpxFiles.add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gpxFiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,577 @@
|
|||||||
|
/*
|
||||||
|
* 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.content.MyTracksProviderUtils;
|
||||||
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
|
import com.google.android.apps.mytracks.content.TrackDataHub;
|
||||||
|
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
||||||
|
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||||
|
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.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 onResume() {
|
||||||
|
Log.d(TAG, "MapActivity.onStart");
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
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 onPause() {
|
||||||
|
Log.d(TAG, "MapActivity.onStop");
|
||||||
|
|
||||||
|
dataHub.unregisterTrackDataListener(this);
|
||||||
|
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 (mapOverlay == null || mapView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapOverlay.setMyLocation(currentLocation);
|
||||||
|
mapView.postInvalidate();
|
||||||
|
|
||||||
|
if (currentLocation != null && 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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
-14
@@ -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;
|
||||||
@@ -79,20 +79,31 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
private static class CachedLocation {
|
private static class CachedLocation {
|
||||||
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) {
|
||||||
@@ -172,7 +190,7 @@ public class MyTracksOverlay extends Overlay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNumLocations() {
|
public int getNumLocations() {
|
||||||
synchronized (points) {
|
synchronized (points) {
|
||||||
return points.size() + pendingPoints.size();
|
return points.size() + pendingPoints.size();
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ class MenuManager {
|
|||||||
|
|
||||||
public void onPrepareOptionsMenu(Menu menu, boolean hasRecorded,
|
public void onPrepareOptionsMenu(Menu menu, boolean hasRecorded,
|
||||||
boolean isRecording, boolean hasSelectedTrack) {
|
boolean isRecording, boolean hasSelectedTrack) {
|
||||||
menu.findItem(R.id.menu_list_tracks).setEnabled(hasRecorded);
|
menu.findItem(R.id.menu_list_tracks);
|
||||||
menu.findItem(R.id.menu_list_markers)
|
menu.findItem(R.id.menu_list_markers)
|
||||||
.setEnabled(hasRecorded && hasSelectedTrack);
|
.setEnabled(hasRecorded && hasSelectedTrack);
|
||||||
menu.findItem(R.id.menu_start_recording)
|
menu.findItem(R.id.menu_start_recording)
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+155
-48
@@ -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(
|
||||||
@@ -115,16 +137,37 @@ 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,10 +266,7 @@ 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
|
||||||
: R.array.min_recording_distance_options_ft);
|
: R.array.min_recording_distance_options_ft);
|
||||||
@@ -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,20 @@
|
|||||||
*/
|
*/
|
||||||
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.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.TrackDataHub;
|
||||||
import com.google.android.apps.mytracks.content.WaypointsColumns;
|
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
||||||
import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
|
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||||
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
|
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
|
||||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
import com.google.android.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 +36,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 +81,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,9 +105,9 @@ 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 =
|
||||||
new StatusAnnouncerFactory(ApiFeatures.getInstance()).getVolumeStream();
|
new StatusAnnouncerFactory(ApiFeatures.getInstance()).getVolumeStream();
|
||||||
@@ -151,40 +118,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);
|
||||||
@@ -193,89 +130,74 @@ public class StatsActivity extends Activity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
unregisterLocationListener();
|
|
||||||
if (thread != null) {
|
|
||||||
thread.interrupt();
|
|
||||||
thread = null;
|
|
||||||
}
|
|
||||||
getContentResolver().unregisterContentObserver(observer);
|
|
||||||
activityOnTop = false;
|
|
||||||
super.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
activityOnTop = true;
|
dataHub.registerTrackDataListener(this, EnumSet.of(
|
||||||
checkLiveTrack();
|
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||||
restoreStats();
|
ListenerDataType.TRACK_UPDATES,
|
||||||
showUnknownLocation();
|
ListenerDataType.LOCATION_UPDATES,
|
||||||
|
ListenerDataType.DISPLAY_PREFERENCES));
|
||||||
|
|
||||||
super.onResume();
|
super.onResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(
|
protected void onPause() {
|
||||||
final SharedPreferences sharedPreferences, final String key) {
|
dataHub.unregisterTrackDataListener(this);
|
||||||
Log.d(MyTracksConstants.TAG,
|
|
||||||
"StatsActivity: onSharedPreferences changed " + key);
|
if (thread != null) {
|
||||||
if (key != null) {
|
thread.interrupt();
|
||||||
runOnUiThread(new Runnable() {
|
thread = null;
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (key.equals(getString(R.string.selected_track_key))) {
|
|
||||||
selectedTrackId =
|
|
||||||
sharedPreferences.getLong(
|
|
||||||
getString(R.string.selected_track_key),
|
|
||||||
-1);
|
|
||||||
checkLiveTrack();
|
|
||||||
restoreStats();
|
|
||||||
showUnknownLocation();
|
|
||||||
} else if (key.equals(getString(R.string.recording_track_key))) {
|
|
||||||
recordingTrackId =
|
|
||||||
sharedPreferences.getLong(
|
|
||||||
getString(R.string.recording_track_key),
|
|
||||||
-1);
|
|
||||||
checkLiveTrack();
|
|
||||||
restoreStats();
|
|
||||||
showUnknownLocation();
|
|
||||||
} else if (key.equals(getString(R.string.metric_units_key))) {
|
|
||||||
metricUnits =
|
|
||||||
sharedPreferences.getBoolean(
|
|
||||||
getString(R.string.metric_units_key), true);
|
|
||||||
utils.setMetricUnits(metricUnits);
|
|
||||||
utils.updateUnits();
|
|
||||||
restoreStats();
|
|
||||||
} else if (key.equals(getString(R.string.report_speed_key))) {
|
|
||||||
displaySpeed =
|
|
||||||
sharedPreferences.getBoolean(
|
|
||||||
getString(R.string.report_speed_key),
|
|
||||||
true);
|
|
||||||
utils.setReportSpeed(displaySpeed);
|
|
||||||
utils.updateUnits();
|
|
||||||
utils.setSpeedLabel(
|
|
||||||
R.id.speed_label, R.string.speed, R.string.pace_label);
|
|
||||||
Log.w(MyTracksConstants.TAG, "Setting speed labels");
|
|
||||||
utils.setSpeedLabels();
|
|
||||||
restoreStats();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super.onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onUnitsChanged(boolean metric) {
|
||||||
|
// Ignore if unchanged.
|
||||||
|
if (metric == utils.isMetricUnits()) return false;
|
||||||
|
|
||||||
|
utils.setMetricUnits(metric);
|
||||||
|
updateLabels();
|
||||||
|
|
||||||
|
return true; // Reload data
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onReportSpeedChanged(boolean displaySpeed) {
|
||||||
|
// Ignore if unchanged.
|
||||||
|
if (displaySpeed == utils.isReportSpeed()) return false;
|
||||||
|
|
||||||
|
utils.setReportSpeed(displaySpeed);
|
||||||
|
updateLabels();
|
||||||
|
|
||||||
|
return true; // Reload data
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLabels() {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
utils.updateUnits();
|
||||||
|
utils.setSpeedLabel(R.id.speed_label, R.string.speed, R.string.pace_label);
|
||||||
|
utils.setSpeedLabels();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 +209,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 +236,122 @@ 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCurrentLocationChanged(final Location loc) {
|
||||||
|
if (dataHub.isRecordingSelected()) {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (loc != null) {
|
||||||
|
showLocation(loc);
|
||||||
|
} else {
|
||||||
|
showUnknownLocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCurrentHeadingChanged(double heading) {
|
||||||
|
// We don't care.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderStateChange(ProviderState state) {
|
||||||
|
switch (state) {
|
||||||
|
case DISABLED:
|
||||||
|
case NO_FIX:
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
showUnknownLocation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrackUpdated(final Track track) {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (track == null || track.getStatistics() == null) {
|
||||||
|
utils.setAllToUnknown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ public class StatsUtilities {
|
|||||||
public void setText(int id, double d, NumberFormat format) {
|
public void setText(int id, double d, NumberFormat format) {
|
||||||
if (!Double.isNaN(d) && !Double.isInfinite(d)) {
|
if (!Double.isNaN(d) && !Double.isInfinite(d)) {
|
||||||
setText(id, format.format(d));
|
setText(id, format.format(d));
|
||||||
|
} else {
|
||||||
|
setUnknown(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +220,7 @@ public class StatsUtilities {
|
|||||||
setGrade(R.id.max_grade_register, maxGrade);
|
setGrade(R.id.max_grade_register, maxGrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAllStats(TripStatistics stats) {
|
public void setAllStats(TripStatistics stats) {
|
||||||
setTime(R.id.moving_time_register, stats.getMovingTime());
|
setTime(R.id.moving_time_register, stats.getMovingTime());
|
||||||
setDistance(R.id.total_distance_register, stats.getTotalDistance() / 1000);
|
setDistance(R.id.total_distance_register, stats.getTotalDistance() / 1000);
|
||||||
setSpeed(R.id.average_speed_register, stats.getAverageSpeed() * 3.6);
|
setSpeed(R.id.average_speed_register, stats.getAverageSpeed() * 3.6);
|
||||||
@@ -235,7 +237,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 +245,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+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;
|
||||||
+39
-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;
|
||||||
}
|
}
|
||||||
@@ -178,6 +178,10 @@ public class MyTracksList extends ListActivity
|
|||||||
new ExportAllTracks(this);
|
new ExportAllTracks(this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case R.id.tracklist_btn_import_all: {
|
||||||
|
new ImportAllTracks(this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,11 +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);
|
||||||
|
|
||||||
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
package com.google.android.apps.mytracks.content;
|
||||||
|
|
||||||
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
|
import android.database.ContentObserver;
|
||||||
|
import android.hardware.Sensor;
|
||||||
|
import android.hardware.SensorEvent;
|
||||||
|
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.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External data source manager, which converts system-level events into My Tracks data events.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
class DataSourceManager {
|
||||||
|
|
||||||
|
/** Single interface for receiving system events that were registered for. */
|
||||||
|
interface DataSourceListener {
|
||||||
|
void notifyTrackUpdated();
|
||||||
|
void notifyWaypointUpdated();
|
||||||
|
void notifyPointsUpdated();
|
||||||
|
void notifyPreferenceChanged(String key);
|
||||||
|
void notifyLocationProviderEnabled(boolean enabled);
|
||||||
|
void notifyLocationChanged(Location loc);
|
||||||
|
void notifyHeadingChanged(float heading);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final DataSourceListener listener;
|
||||||
|
|
||||||
|
/** Observer for when the tracks table is updated. */
|
||||||
|
private class TrackObserver extends ContentObserver {
|
||||||
|
public TrackObserver() {
|
||||||
|
super(contentHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChange(boolean selfChange) {
|
||||||
|
listener.notifyTrackUpdated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Observer for when the waypoints table is updated. */
|
||||||
|
private class WaypointObserver extends ContentObserver {
|
||||||
|
public WaypointObserver() {
|
||||||
|
super(contentHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChange(boolean selfChange) {
|
||||||
|
listener.notifyWaypointUpdated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Observer for when the points table is updated. */
|
||||||
|
private class PointObserver extends ContentObserver {
|
||||||
|
public PointObserver() {
|
||||||
|
super(contentHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChange(boolean selfChange) {
|
||||||
|
listener.notifyPointsUpdated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Listener for when preferences change. */
|
||||||
|
private class HubSharedPreferenceListener implements OnSharedPreferenceChangeListener {
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
|
listener.notifyPreferenceChanged(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Listener for the current location (independent from track data). */
|
||||||
|
private class CurrentLocationListener implements
|
||||||
|
LocationListener {
|
||||||
|
@Override
|
||||||
|
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||||
|
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
|
||||||
|
|
||||||
|
listener.notifyLocationProviderEnabled(status == LocationProvider.AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderEnabled(String provider) {
|
||||||
|
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
|
||||||
|
|
||||||
|
listener.notifyLocationProviderEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderDisabled(String provider) {
|
||||||
|
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
|
||||||
|
|
||||||
|
listener.notifyLocationProviderEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLocationChanged(Location location) {
|
||||||
|
listener.notifyLocationChanged(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Listener for compass readings. */
|
||||||
|
private class CompassListener implements
|
||||||
|
SensorEventListener {
|
||||||
|
@Override
|
||||||
|
public void onSensorChanged(SensorEvent event) {
|
||||||
|
listener.notifyHeadingChanged(event.values[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Wrapper for registering internal listeners. */
|
||||||
|
private final DataSourcesWrapper dataSources;
|
||||||
|
|
||||||
|
// Internal listeners (to receive data from the system)
|
||||||
|
private final Set<ListenerDataType> registeredListeners =
|
||||||
|
EnumSet.noneOf(ListenerDataType.class);
|
||||||
|
private final Handler contentHandler;
|
||||||
|
private final ContentObserver pointObserver;
|
||||||
|
private final ContentObserver waypointObserver;
|
||||||
|
private final ContentObserver trackObserver;
|
||||||
|
private final LocationListener locationListener;
|
||||||
|
private final OnSharedPreferenceChangeListener preferenceListener;
|
||||||
|
private final SensorEventListener compassListener;
|
||||||
|
|
||||||
|
DataSourceManager(DataSourceListener listener, DataSourcesWrapper dataSources) {
|
||||||
|
this.listener = listener;
|
||||||
|
this.dataSources = dataSources;
|
||||||
|
|
||||||
|
contentHandler = new Handler();
|
||||||
|
pointObserver = new PointObserver();
|
||||||
|
waypointObserver = new WaypointObserver();
|
||||||
|
trackObserver = new TrackObserver();
|
||||||
|
|
||||||
|
compassListener = new CompassListener();
|
||||||
|
locationListener = new CurrentLocationListener();
|
||||||
|
preferenceListener = new HubSharedPreferenceListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Updates the internal (sensor, position, etc) listeners. */
|
||||||
|
void updateAllListeners(EnumSet<ListenerDataType> externallyNeededListeners) {
|
||||||
|
EnumSet<ListenerDataType> neededListeners = EnumSet.copyOf(externallyNeededListeners);
|
||||||
|
|
||||||
|
// Special case - map sampled-out points type to points type since they
|
||||||
|
// correspond to the same internal listener.
|
||||||
|
if (neededListeners.contains(ListenerDataType.SAMPLED_OUT_POINT_UPDATES)) {
|
||||||
|
neededListeners.remove(ListenerDataType.SAMPLED_OUT_POINT_UPDATES);
|
||||||
|
neededListeners.add(ListenerDataType.POINT_UPDATES);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "Updating internal listeners to types " + neededListeners);
|
||||||
|
|
||||||
|
// Unnecessary = registered - needed
|
||||||
|
Set<ListenerDataType> unnecessaryListeners = EnumSet.copyOf(registeredListeners);
|
||||||
|
unnecessaryListeners.removeAll(neededListeners);
|
||||||
|
|
||||||
|
// Missing = needed - registered
|
||||||
|
Set<ListenerDataType> missingListeners = EnumSet.copyOf(neededListeners);
|
||||||
|
missingListeners.removeAll(registeredListeners);
|
||||||
|
|
||||||
|
// Remove all unnecessary listeners.
|
||||||
|
for (ListenerDataType type : unnecessaryListeners) {
|
||||||
|
unregisterListener(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all missing listeners.
|
||||||
|
for (ListenerDataType type : missingListeners) {
|
||||||
|
registerListener(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now all needed types are registered.
|
||||||
|
registeredListeners.clear();
|
||||||
|
registeredListeners.addAll(neededListeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerListener(ListenerDataType type) {
|
||||||
|
switch (type) {
|
||||||
|
case COMPASS_UPDATES: {
|
||||||
|
// Listen to compass
|
||||||
|
Sensor compass = dataSources.getSensor(Sensor.TYPE_ORIENTATION);
|
||||||
|
if (compass != null) {
|
||||||
|
Log.d(TAG, "TrackDataHub: Now registering sensor listener.");
|
||||||
|
dataSources.registerSensorListener(compassListener, compass, SensorManager.SENSOR_DELAY_UI);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LOCATION_UPDATES:
|
||||||
|
dataSources.requestLocationUpdates(locationListener);
|
||||||
|
break;
|
||||||
|
case POINT_UPDATES:
|
||||||
|
dataSources.registerContentObserver(
|
||||||
|
TrackPointsColumns.CONTENT_URI, false, pointObserver);
|
||||||
|
break;
|
||||||
|
case TRACK_UPDATES:
|
||||||
|
dataSources.registerContentObserver(TracksColumns.CONTENT_URI, false, trackObserver);
|
||||||
|
break;
|
||||||
|
case WAYPOINT_UPDATES:
|
||||||
|
dataSources.registerContentObserver(
|
||||||
|
WaypointsColumns.CONTENT_URI, false, waypointObserver);
|
||||||
|
break;
|
||||||
|
case DISPLAY_PREFERENCES:
|
||||||
|
dataSources.registerOnSharedPreferenceChangeListener(preferenceListener);
|
||||||
|
break;
|
||||||
|
case SAMPLED_OUT_POINT_UPDATES:
|
||||||
|
throw new IllegalArgumentException("Should have been mapped to point updates");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unregisterListener(ListenerDataType type) {
|
||||||
|
switch (type) {
|
||||||
|
case COMPASS_UPDATES:
|
||||||
|
dataSources.unregisterSensorListener(compassListener);
|
||||||
|
break;
|
||||||
|
case LOCATION_UPDATES:
|
||||||
|
dataSources.removeLocationUpdates(locationListener);
|
||||||
|
break;
|
||||||
|
case POINT_UPDATES:
|
||||||
|
dataSources.unregisterContentObserver(pointObserver);
|
||||||
|
break;
|
||||||
|
case TRACK_UPDATES:
|
||||||
|
dataSources.unregisterContentObserver(trackObserver);
|
||||||
|
break;
|
||||||
|
case WAYPOINT_UPDATES:
|
||||||
|
dataSources.unregisterContentObserver(waypointObserver);
|
||||||
|
break;
|
||||||
|
case DISPLAY_PREFERENCES:
|
||||||
|
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListener);
|
||||||
|
break;
|
||||||
|
case SAMPLED_OUT_POINT_UPDATES:
|
||||||
|
throw new IllegalArgumentException("Should have been mapped to point updates");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unregisters all internal (sensor, position, etc.) listeners. */
|
||||||
|
void unregisterAllListeners() {
|
||||||
|
dataSources.removeLocationUpdates(locationListener);
|
||||||
|
dataSources.unregisterSensorListener(compassListener);
|
||||||
|
dataSources.unregisterContentObserver(trackObserver);
|
||||||
|
dataSources.unregisterContentObserver(waypointObserver);
|
||||||
|
dataSources.unregisterContentObserver(pointObserver);
|
||||||
|
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.content;
|
||||||
|
|
||||||
|
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 registration of external data source listeners.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
interface DataSourcesWrapper {
|
||||||
|
// 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,166 @@
|
|||||||
|
/*
|
||||||
|
* 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.content;
|
||||||
|
|
||||||
|
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.apps.mytracks.Constants;
|
||||||
|
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 DataSourcesWrapperImpl implements DataSourcesWrapper {
|
||||||
|
// System services
|
||||||
|
private final SensorManager sensorManager;
|
||||||
|
private final LocationManager locationManager;
|
||||||
|
private final ContentResolver contentResolver;
|
||||||
|
private final SharedPreferences sharedPreferences;
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
DataSourcesWrapperImpl(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* 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.content;
|
||||||
|
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @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,170 @@
|
|||||||
|
/*
|
||||||
|
* 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.content;
|
||||||
|
|
||||||
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manager for the external data listeners and their listening types.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
class TrackDataListeners {
|
||||||
|
|
||||||
|
/** Internal representation of a listener's registration. */
|
||||||
|
static class ListenerRegistration {
|
||||||
|
final TrackDataListener listener;
|
||||||
|
final EnumSet<ListenerDataType> types;
|
||||||
|
|
||||||
|
// State that was last notified to the listener, for resuming after a pause.
|
||||||
|
long lastTrackId;
|
||||||
|
long lastPointId;
|
||||||
|
int lastSamplingFrequency;
|
||||||
|
int numLoadedPoints;
|
||||||
|
|
||||||
|
public ListenerRegistration(TrackDataListener listener,
|
||||||
|
EnumSet<ListenerDataType> types) {
|
||||||
|
this.listener = listener;
|
||||||
|
this.types = types;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInterestedIn(ListenerDataType type) {
|
||||||
|
return types.contains(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ListenerRegistration [listener=" + listener + ", types=" + types
|
||||||
|
+ ", lastTrackId=" + lastTrackId + ", lastPointId=" + lastPointId
|
||||||
|
+ ", lastSamplingFrequency=" + lastSamplingFrequency
|
||||||
|
+ ", numLoadedPoints=" + numLoadedPoints + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Map of external listener to its registration details. */
|
||||||
|
private final Map<TrackDataListener, ListenerRegistration> registeredListeners =
|
||||||
|
new HashMap<TrackDataListener, ListenerRegistration>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of external paused listener to its registration details.
|
||||||
|
* This will automatically discard listeners which are GCed.
|
||||||
|
*/
|
||||||
|
private final WeakHashMap<TrackDataListener, ListenerRegistration> oldListeners =
|
||||||
|
new WeakHashMap<TrackDataListener, ListenerRegistration>();
|
||||||
|
|
||||||
|
/** Map of data type to external listeners interested in it. */
|
||||||
|
private final Map<ListenerDataType, Set<TrackDataListener>> listenerSetsPerType =
|
||||||
|
new EnumMap<ListenerDataType, Set<TrackDataListener>>(ListenerDataType.class);
|
||||||
|
|
||||||
|
public TrackDataListeners() {
|
||||||
|
// Create sets for all data types at startup.
|
||||||
|
for (ListenerDataType type : ListenerDataType.values()) {
|
||||||
|
listenerSetsPerType.put(type, new LinkedHashSet<TrackDataListener>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a listener to send data to.
|
||||||
|
* It is ok to call this method before {@link start}, and in that case
|
||||||
|
* the data will only be passed to listeners when {@link start} is called.
|
||||||
|
*
|
||||||
|
* @param listener the listener to register
|
||||||
|
* @param dataTypes the type of data that the listener is interested in
|
||||||
|
*/
|
||||||
|
public ListenerRegistration registerTrackDataListener(final TrackDataListener listener, EnumSet<ListenerDataType> dataTypes) {
|
||||||
|
Log.d(TAG, "Registered track data listener: " + listener);
|
||||||
|
if (registeredListeners.containsKey(listener)) {
|
||||||
|
throw new IllegalStateException("Listener already registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
ListenerRegistration registration = oldListeners.remove(listener);
|
||||||
|
if (registration == null) {
|
||||||
|
registration = new ListenerRegistration(listener, dataTypes);
|
||||||
|
}
|
||||||
|
registeredListeners.put(listener, registration);
|
||||||
|
|
||||||
|
for (ListenerDataType type : dataTypes) {
|
||||||
|
// This is guaranteed not to be null.
|
||||||
|
Set<TrackDataListener> typeSet = listenerSetsPerType.get(type);
|
||||||
|
typeSet.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters a listener to send data to.
|
||||||
|
*
|
||||||
|
* @param listener the listener to unregister
|
||||||
|
*/
|
||||||
|
public void unregisterTrackDataListener(TrackDataListener listener) {
|
||||||
|
Log.d(TAG, "Unregistered track data listener: " + listener);
|
||||||
|
// Remove and keep the corresponding registration.
|
||||||
|
ListenerRegistration match = registeredListeners.remove(listener);
|
||||||
|
if (match == null) {
|
||||||
|
Log.w(TAG, "Tried to unregister listener which is not registered.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove it from the per-type sets
|
||||||
|
for (ListenerDataType type : match.types) {
|
||||||
|
listenerSetsPerType.get(type).remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep it around in case it's re-registered soon
|
||||||
|
oldListeners.put(listener, match);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListenerRegistration getRegistration(TrackDataListener listener) {
|
||||||
|
ListenerRegistration registration = registeredListeners.get(listener);
|
||||||
|
if (registration == null) {
|
||||||
|
registration = oldListeners.get(listener);
|
||||||
|
}
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<TrackDataListener> getListenersFor(ListenerDataType type) {
|
||||||
|
return listenerSetsPerType.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnumSet<ListenerDataType> getAllRegisteredTypes() {
|
||||||
|
EnumSet<ListenerDataType> listeners = EnumSet.noneOf(ListenerDataType.class);
|
||||||
|
for (ListenerRegistration registration : this.registeredListeners.values()) {
|
||||||
|
listeners.addAll(registration.types);
|
||||||
|
}
|
||||||
|
return listeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasListeners() {
|
||||||
|
return !registeredListeners.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumListeners() {
|
||||||
|
return registeredListeners.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
@@ -51,6 +51,7 @@ import java.io.IOException;
|
|||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +73,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
public static final String SERVICE_ID = "fusiontables";
|
public static final String SERVICE_ID = "fusiontables";
|
||||||
|
|
||||||
/** The path for viewing a map visualization of a table. */
|
/** The path for viewing a map visualization of a table. */
|
||||||
private static final String FUSIONTABLES_MAP =
|
private static final String FUSIONTABLES_MAP =
|
||||||
"http://www.google.com/fusiontables/embedviz?" +
|
"http://www.google.com/fusiontables/embedviz?" +
|
||||||
"viz=MAP&q=select+col0,+col1,+col2,+col3+from+%s+&h=false&" +
|
"viz=MAP&q=select+col0,+col1,+col2,+col3+from+%s+&h=false&" +
|
||||||
"lat=%f&lng=%f&z=%d&t=1&l=col2";
|
"lat=%f&lng=%f&z=%d&t=1&l=col2";
|
||||||
@@ -84,10 +85,10 @@ public class SendToFusionTables implements Runnable {
|
|||||||
private static final int MAX_POINTS_PER_UPLOAD = 2048;
|
private static final int MAX_POINTS_PER_UPLOAD = 2048;
|
||||||
|
|
||||||
private static final String GDATA_VERSION = "2";
|
private static final String GDATA_VERSION = "2";
|
||||||
|
|
||||||
// This class reports upload status to the user as a completion percentage
|
// This class reports upload status to the user as a completion percentage
|
||||||
// using a progress bar. Progress is defined as follows:
|
// using a progress bar. Progress is defined as follows:
|
||||||
//
|
//
|
||||||
// 0% Getting track metadata
|
// 0% Getting track metadata
|
||||||
// 5% Creating Fusion Table (GData to FT server)
|
// 5% Creating Fusion Table (GData to FT server)
|
||||||
// 10%-90% Uploading the track data to Fusion Tables
|
// 10%-90% Uploading the track data to Fusion Tables
|
||||||
@@ -140,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();
|
||||||
@@ -150,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +161,12 @@ public class SendToFusionTables implements Runnable {
|
|||||||
double latE6 = stats.getBottom() + (stats.getTop() - stats.getBottom()) / 2;
|
double latE6 = stats.getBottom() + (stats.getTop() - stats.getBottom()) / 2;
|
||||||
double lonE6 = stats.getLeft() + (stats.getRight() - stats.getLeft()) / 2;
|
double lonE6 = stats.getLeft() + (stats.getRight() - stats.getLeft()) / 2;
|
||||||
int z = 15;
|
int z = 15;
|
||||||
return String.format(FUSIONTABLES_MAP, track.getTableId(), latE6 / 1.E6, lonE6 / 1.E6, z);
|
|
||||||
|
// We explicitly format with Locale.US because we need the latitude and
|
||||||
|
// longitude to be formatted in a locale-independent manner. Specifically,
|
||||||
|
// we need the decimal separator to be a period rather than a comma.
|
||||||
|
return String.format(Locale.US, FUSIONTABLES_MAP, track.getTableId(),
|
||||||
|
latE6 / 1.E6, lonE6 / 1.E6, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doUpload() {
|
private void doUpload() {
|
||||||
@@ -189,16 +195,16 @@ public class SendToFusionTables implements Runnable {
|
|||||||
if (!uploadAllTrackPoints(track, originalDescription)) {
|
if (!uploadAllTrackPoints(track, originalDescription)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
progressIndicator.setProgressValue(PROGRESS_UPLOAD_WAYPOINTS);
|
progressIndicator.setProgressValue(PROGRESS_UPLOAD_WAYPOINTS);
|
||||||
|
|
||||||
// Upload all the waypoints.
|
// Upload all the waypoints.
|
||||||
if (!uploadWaypoints(track)) {
|
if (!uploadWaypoints(track)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
|
||||||
@@ -222,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);
|
||||||
}
|
}
|
||||||
@@ -253,7 +259,7 @@ public class SendToFusionTables implements Runnable {
|
|||||||
builder.append(')');
|
builder.append(')');
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String sqlEscape(String value) {
|
private static String sqlEscape(String value) {
|
||||||
return value.replaceAll("'", "''");
|
return value.replaceAll("'", "''");
|
||||||
}
|
}
|
||||||
@@ -268,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);
|
||||||
@@ -281,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));
|
||||||
@@ -290,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);
|
||||||
@@ -299,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,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;
|
||||||
@@ -338,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);
|
||||||
@@ -441,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;
|
||||||
}
|
}
|
||||||
@@ -457,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -512,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();
|
||||||
@@ -560,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);
|
||||||
}
|
}
|
||||||
@@ -575,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);
|
||||||
@@ -598,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) {
|
||||||
@@ -615,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 {
|
||||||
@@ -632,8 +638,8 @@ public class SendToFusionTables implements Runnable {
|
|||||||
double totalPercentage =
|
double totalPercentage =
|
||||||
(totalLocationsRead + totalLocationsPrepared + totalLocationsUploaded)
|
(totalLocationsRead + totalLocationsPrepared + totalLocationsUploaded)
|
||||||
/ (totalLocations * 3);
|
/ (totalLocations * 3);
|
||||||
|
|
||||||
double scaledPercentage = totalPercentage
|
double scaledPercentage = totalPercentage
|
||||||
* (PROGRESS_UPLOAD_DATA_MAX - PROGRESS_UPLOAD_DATA_MIN) + PROGRESS_UPLOAD_DATA_MIN;
|
* (PROGRESS_UPLOAD_DATA_MAX - PROGRESS_UPLOAD_DATA_MIN) + PROGRESS_UPLOAD_DATA_MIN;
|
||||||
|
|
||||||
progressIndicator.setProgressValue((int) scaledPercentage);
|
progressIndicator.setProgressValue((int) scaledPercentage);
|
||||||
@@ -650,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)
|
||||||
@@ -665,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();
|
||||||
@@ -680,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,13 +358,13 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IOException newIOException(GDataWrapper wrapper,
|
private static IOException newIOException(GDataWrapper<GDataServiceClient> wrapper,
|
||||||
String message) {
|
String message) {
|
||||||
return new IOException(String.format("%s: %d: %s", message,
|
return new IOException(String.format("%s: %d: %s", message,
|
||||||
wrapper.getErrorType(), wrapper.getErrorMessage()));
|
wrapper.getErrorType(), wrapper.getErrorMessage()));
|
||||||
|
|||||||
+11
-6
@@ -13,16 +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.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;
|
||||||
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.text.NumberFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
@@ -44,9 +45,13 @@ import java.util.TimeZone;
|
|||||||
* @author Rodrigo Damazio
|
* @author Rodrigo Damazio
|
||||||
*/
|
*/
|
||||||
public class CsvTrackWriter implements TrackFormatWriter {
|
public class CsvTrackWriter implements TrackFormatWriter {
|
||||||
|
|
||||||
|
static final NumberFormat SHORT_FORMAT = NumberFormat.getInstance();
|
||||||
static final SimpleDateFormat TIMESTAMP_FORMAT =
|
static final SimpleDateFormat TIMESTAMP_FORMAT =
|
||||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
SHORT_FORMAT.setMaximumFractionDigits(4);
|
||||||
TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
|
TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,8 +99,8 @@ public class CsvTrackWriter implements TrackFormatWriter {
|
|||||||
Double.toString(location.getLongitude()),
|
Double.toString(location.getLongitude()),
|
||||||
Double.toString(location.getAltitude()),
|
Double.toString(location.getAltitude()),
|
||||||
Double.toString(location.getBearing()),
|
Double.toString(location.getBearing()),
|
||||||
Double.toString(location.getAccuracy()),
|
SHORT_FORMAT.format(location.getAccuracy()),
|
||||||
Double.toString(location.getSpeed()),
|
SHORT_FORMAT.format(location.getSpeed()),
|
||||||
null, null,
|
null, null,
|
||||||
Integer.toString(segmentIdx));
|
Integer.toString(segmentIdx));
|
||||||
}
|
}
|
||||||
@@ -110,8 +115,8 @@ public class CsvTrackWriter implements TrackFormatWriter {
|
|||||||
Double.toString(location.getLongitude()),
|
Double.toString(location.getLongitude()),
|
||||||
Double.toString(location.getAltitude()),
|
Double.toString(location.getAltitude()),
|
||||||
Double.toString(location.getBearing()),
|
Double.toString(location.getBearing()),
|
||||||
Double.toString(location.getAccuracy()),
|
SHORT_FORMAT.format(location.getAccuracy()),
|
||||||
Double.toString(location.getSpeed()),
|
SHORT_FORMAT.format(location.getSpeed()),
|
||||||
waypoint.getName(),
|
waypoint.getName(),
|
||||||
waypoint.getDescription(),
|
waypoint.getDescription(),
|
||||||
null);
|
null);
|
||||||
+24
-17
@@ -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 {
|
||||||
@@ -229,7 +229,10 @@ public class GpxImporter extends DefaultHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void endElement(String uri, String localName, String name)
|
public void endElement(String uri, String localName, String name)
|
||||||
throws SAXException {
|
throws SAXException {
|
||||||
if (!isInTrackElement) { return; }
|
if (!isInTrackElement) {
|
||||||
|
content = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// process these elements only as sub-elements of track
|
// process these elements only as sub-elements of track
|
||||||
if (localName.equals(TAG_TRACK_POINT)) {
|
if (localName.equals(TAG_TRACK_POINT)) {
|
||||||
@@ -359,7 +362,11 @@ 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) {
|
||||||
|
// first point did not have a time, start stats builder without it
|
||||||
|
statsBuilder = new TripStatisticsBuilder(0);
|
||||||
|
}
|
||||||
statsBuilder.addLocation(location, location.getTime());
|
statsBuilder.addLocation(location, location.getTime());
|
||||||
|
|
||||||
// insert in db
|
// insert in db
|
||||||
@@ -455,18 +462,18 @@ public class GpxImporter extends DefaultHandler {
|
|||||||
|
|
||||||
// check for negative time change
|
// check for negative time change
|
||||||
if (timeDifference < 0) {
|
if (timeDifference < 0) {
|
||||||
String msg = createErrorMessage("Found negative time change.");
|
Log.w(Constants.TAG, "Found negative time change.");
|
||||||
throw new SAXException(msg);
|
} 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
|
||||||
// the last two points.
|
// the last two points.
|
||||||
// TODO GPS points tend to have some inherent imprecision,
|
// TODO GPS points tend to have some inherent imprecision,
|
||||||
// speed and bearing will likely be off, so the statistics for things like
|
// speed and bearing will likely be off, so the statistics for things like
|
||||||
// max speed will also be off.
|
// max speed will also be off.
|
||||||
float speed = location.distanceTo(lastLocation) * 1000.0f / timeDifference;
|
float speed = location.distanceTo(lastLocation) * 1000.0f / timeDifference;
|
||||||
location.setSpeed(speed);
|
location.setSpeed(speed);
|
||||||
location.setBearing(lastSegmentLocation.bearingTo(location));
|
location.setBearing(lastSegmentLocation.bearingTo(location));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in the time
|
// Fill in the time
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user