Compare commits

...

67 Commits

Author SHA1 Message Date
Rodrigo Damazio e35e8bcdce Updating version number to 1.0.16 in preparation for release. 2010-08-30 18:42:48 -03:00
Rodrigo Damazio 5f953aa47f Fixing version display (missed merge). 2010-08-30 18:36:16 -03:00
Sandor Dornbush 3b3641c69e Merging changes from head. 2010-08-27 17:21:33 -07:00
Rodrigo Damazio 56ccd518d6 Adding missing Eclipse configuration files for developers - these have to be manually imported 2010-08-24 22:48:49 -03:00
Rodrigo Damazio 0e119950c2 Merging Sandor's changes 2010-08-24 17:02:36 -03:00
Sandor Dornbush 4be4467fc6 Fix NPE. 2010-08-24 12:20:18 -07:00
Sandor Dornbush 06636b2a28 Fix test access modifier. 2010-08-23 09:12:12 -07:00
Sandor Dornbush 71a36d1b25 Address Rodrigo's comments. 2010-08-23 09:05:55 -07:00
Sandor Dornbush 9ba93ff8d2 Fix javadoc. 2010-08-23 08:03:54 -07:00
Sandor Dornbush 4059308dd7 Added comments and license to pref mgr.
Removed sampling from track overlay.
2010-08-22 12:51:40 -07:00
sandordornbush 9f43dd2db5 Reverting classpath changes. 2010-08-20 16:11:36 -07:00
sandordornbush 28d868985e One more minor bug fix for a NPE. 2010-08-20 13:32:53 -07:00
sandordornbush cf1be26da2 Two minor bug fixes from the developer console. 2010-08-20 10:51:09 -07:00
Sandor Dornbush 1de9b73aa0 Address Rodrigo's comments.
Add service preference manager.
2010-08-18 22:05:01 -07:00
Sandor Dornbush beddc8e1ea Add Track Writer test.
Fix total time bug in stats activity.
Fix track segments on the map overlay.
2010-08-16 17:16:43 -07:00
Rodrigo Damazio e0c34d20a8 Removing DO NOT TRANSLATE values from Japanese translation 2010-08-16 00:57:03 -03:00
Rodrigo Damazio cc6db5b5cc Merging japanese translation 2010-08-16 00:54:44 -03:00
Rodrigo Damazio c38df03add Ignoring eclipse workspace metadata if present 2010-08-13 13:03:58 -03:00
Rodrigo Damazio 63402358d1 Fixing empty method comment 2010-08-13 04:53:07 -03:00
Rodrigo Damazio 3ae1de735e Removing overlooked debug lines 2010-08-13 04:52:14 -03:00
Rodrigo Damazio a701eb0e4f Fixing 24-hour format mistake 2010-08-13 04:37:37 -03:00
Rodrigo Damazio 09caf017a9 Adding support for segments 2010-08-13 04:37:14 -03:00
Rodrigo Damazio 32b8b2093d REAL performance improvement in importer - using a bulk insertion 2010-08-13 03:50:55 -03:00
Rodrigo Damazio c84a4f1aa8 Moving androidmock to the right directory and making eclipse use it properly 2010-08-12 22:16:38 -03:00
Rodrigo Damazio d90c0b5431 Optimizing the importer a little 2010-08-12 22:14:47 -03:00
Rodrigo Damazio 94f6785f0d Removing no longer used provider utility methods 2010-08-12 22:06:58 -03:00
Rodrigo Damazio f01c382807 Style fixing SAX importer contribution 2010-08-12 20:22:54 -03:00
Rodrigo Damazio 6d42803dd8 Updating statistics object usage in SAX importer 2010-08-12 19:43:27 -03:00
Rodrigo Damazio 61e908ccb5 Merge SAX GPX importer contribution 2010-08-12 18:37:38 -03:00
Sandor Dornbush 7bae8c34a7 Integrate most of Rodrigo's comments. 2010-08-11 22:02:49 -07:00
Sandor Dornbush 3960341640 Revert classpath 2010-08-09 16:45:36 -07:00
Sandor Dornbush 06e453dd05 Merging changes from realtime branch into mainline. 2010-08-07 10:38:41 -07:00
boiledorange73 361b1cbad4 Reverted "DO NOT TRANSLATE" entries 2010-08-04 19:51:00 +09:00
boiledorange73 56a866fca7 Modified bits of values-ja files. 2010-08-04 17:13:35 +09:00
boiledorange73 49e0d68374 res/values-ja added 2010-08-04 14:35:30 +09:00
Sandor Dornbush c9ffd0b4bb Exporting the TrackRecordingService. 2010-07-27 16:34:13 -07:00
Steffen Horlacher 6fd4294391 Bugfix for empty total time in trip statistics and missing first location in exported files 2010-06-06 23:31:03 +02:00
Rodrigo Damazio 88b2b85f2a Making Track and Waypoint use the TripStatisticsData class.
This grealy simplifies those classes since the fields are the same.
There's certainly more cleanup to do on top of this, but I thought this
was already more than enough for a single change.

The only *functional* change expected from this is that the average
speed is now calculated over the time until the last known position,
which IMHO makes sense since the distance used in that calculation only
includes up to that position. The visible effect is that having no GPS
signal doesn't make the speed decrease.

This was imported from perforce CL 15953263.
2010-06-04 14:59:09 -03:00
Rodrigo Damazio 2c1dff6ac8 Adding test project files (TODO: replace easymock with android mock) 2010-06-02 19:26:31 -03:00
Rodrigo Damazio 481b42f563 Auto-merge 2010-06-02 16:58:49 -03:00
Rodrigo Damazio 597c321009 Added tag v1.0.15 for changeset e774d13e5b6a 2010-06-02 16:57:46 -03:00
Rodrigo Damazio 76651f75d8 Automated merge with https://tnapierala-mytracks.googlecode.com/hg/ 2010-06-02 16:22:24 -03:00
t napierala 3d8bae55a1 pl_PL - removed some non-translatable strings 2010-06-01 10:00:28 +02:00
Steffen Horlacher 4b6869e367 Added check for negative time changes and bugfix for files with multiple tracks 2010-05-30 20:06:22 +02:00
Steffen Horlacher 477ba7c081 Changes according to comments 2010-05-30 18:10:56 +02:00
johan helin 5b6d9725b8 Removed all strings that should not be translated in the swedish translation of arrays.xml 2010-05-30 14:01:26 +02:00
t napierala 25c3cea115 pl_PL removed colors.xml, removed non-translatable strings as per Issue 68, comment 2 2010-05-30 13:20:08 +02:00
johan helin d90601276f Finnished translating my tracks to swedish 2010-05-29 13:30:20 +02:00
johan helin 4f692bc698 Finnished translating strings.xml and did some more of the strings in arrays.xml 2010-05-29 12:44:30 +02:00
johan helin d8dd02eef0 Further strings translated 2010-05-28 22:38:04 +02:00
johan helin 8ad65ae233 First commit with cleanup from english and some strings translated 2010-05-28 22:22:39 +02:00
t napierala eabbb4569b final translation 2010-05-26 16:34:26 +02:00
t napierala 49888b771d first part of changes 2010-05-26 14:29:40 +02:00
ob 2b1c1cd052 Add a missing string for "Elevation" to the French strings.xml file. 2010-05-24 18:23:39 +01:00
Steffen Horlacher 61884e67ec track rollback: javadoc and some minor other corrections 2010-05-23 12:58:50 +02:00
Steffen Horlacher 9a2f028843 code format 2010-05-23 11:26:41 +02:00
Steffen Horlacher 2b56acf164 code format 2010-05-23 11:21:27 +02:00
Steffen 98b67dcc28 Sax style GPX file importer and tests 2010-05-23 11:08:51 +02:00
Rodrigo Damazio 500dfa3107 Releasing mytracks 1.0.15 2010-05-23 00:00:00 -03:00
Rodrigo Damazio c4efcfd2db Fixing bug in GPX import - we were reading the last point time too soon 2010-05-22 01:17:59 -07:00
Rodrigo Damazio 81ee6bbcf6 Add a few calls back into SendToMyMaps which actually add the stats to the ending waypoint. (imported from perforce) 2010-05-22 00:41:40 -07:00
Rodrigo Damazio e4e2e76e06 Added tag v1.0.14 for changeset 4c02a4515632 2010-05-20 16:53:43 -07:00
Rodrigo Damazio f847862e84 Releasing 1.0.14 (no code changes, just a release mistake) 2010-05-20 16:53:40 -07:00
Rodrigo Damazio 427dbeafde Added tag v1.0.13 for changeset 84cce31f6b83 2010-05-20 12:18:35 -07:00
Rodrigo Damazio 99ac85b40e Releasing 1.0.13 2010-05-20 12:18:29 -07:00
Rodrigo Damazio 020388baed Fixing uploading bug which happened in gzipped responses 2010-05-20 11:21:46 -07:00
Rodrigo Damazio 4ade79de4f Added tag v1.0.12 for changeset 51aa4e7cf7d8 2010-05-20 05:14:00 -03:00
76 changed files with 5691 additions and 2208 deletions
+1
View File
@@ -2,3 +2,4 @@ syntax:glob
*/bin
*/gen/**
.metadata
@@ -0,0 +1,12 @@
#Thu Aug 12 18:54:52 BRT 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
+5 -4
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.maps.mytracks"
android:versionCode="13"
android:versionName="1.0.12">
android:versionCode="17"
android:versionName="1.0.16">
<application android:icon="@drawable/arrow_icon"
android:label="@string/app_name">
<uses-library android:name="com.google.android.maps" />
@@ -69,7 +69,8 @@
android:process=":trackrecord"
android:label="Track Recording Service"
android:icon="@drawable/arrow_320"
android:enabled="true" />
android:enabled="true"
android:exported="true" />
</application>
@@ -89,7 +90,7 @@
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.writely" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="7" />
<uses-sdk android:minSdkVersion="3"/>
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
+1 -1
View File
@@ -10,4 +10,4 @@
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
target=Google Inc.:Google APIs:7
target=Google Inc.:Google APIs:8
+2 -1
View File
@@ -95,8 +95,9 @@ limitations under the License.
android:textSize="20sp" />
<TextView
android:layout_height="wrap_content"
android:id="@+id/about_version_register"
android:layout_width="wrap_content"
android:text="@string/version"
android:text="@string/unknown"
android:textSize="20sp" />
</TableRow>
+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_start_recording"
android:icon="@drawable/menu_record"
android:title="@string/start_recording"/>
<item android:id="@+id/menu_stop_recording"
android:icon="@drawable/menu_stop"
android:title="@string/stop_recording"/>
<item android:id="@+id/menu_list_tracks"
android:icon="@drawable/menu_list_tracks"
android:title="@string/list_tracks"/>
<item android:id="@+id/menu_list_markers"
android:icon="@drawable/menu_marker"
android:title="@string/list_markers"/>
<item android:id="@+id/menu_settings"
android:icon="@android:drawable/ic_menu_preferences"
android:orderInCategory="1001"
android:title="@string/settings"/>
<item android:id="@+id/menu_help"
android:icon="@android:drawable/ic_menu_info_details"
android:orderInCategory="1002"
android:title="@string/help"/>
</menu>
+1
View File
@@ -26,6 +26,7 @@ limitations under the License.
<string name="list_markers">Marqueurs</string>
<string name="delete_all_tracks">Supprimer tous les parcours</string>
<string name="settings">Paramètres</string>
<string name="elevation">Altitude</string>
<string name="choose_track_message">Sélectionnez le parcours à visualiser</string>
<string name="current_track">Parcours actuel</string>
<string name="current_segment">Segment actuel</string>
+282
View File
@@ -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>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>不使用</item>
<item>1 分</item>
<item>2 分</item>
<item>5 分</item>
<item>10 分</item>
<item>15 分</item>
<item>30 分</item>
<item>60 分</item>
</string-array>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
<item>2 m</item>
<item>3 m</item>
<item>4 m</item>
<item>5 m (推奨)</item>
<item>10 m</item>
<item>100 m</item>
</string-array>
<string-array name="min_recording_distance_options_ft">
<item>3 ft</item>
<item>6 ft</item>
<item>10 ft</item>
<item>13 ft</item>
<item>16 ft (推奨)</item>
<item>33 ft</item>
<item>328 ft</item>
</string-array>
<!-- Maximum recording distance -->
<string-array name="max_recording_distance_options">
<item>50 m</item>
<item>100 m</item>
<item>200 m (推奨)</item>
<item>500 m</item>
<item>1000 m</item>
<item>5000 m</item>
</string-array>
<string-array name="max_recording_distance_options_ft">
<item>164 ft</item>
<item>328 ft</item>
<item>656 ft (推奨)</item>
<item>1640 ft</item>
<item>0.6 mi</item>
<item>3.1 mi</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 m (GPS信号強度良好)</item>
<item>20 m</item>
<item>50 m</item>
<item>100 m</item>
<item>200 m (推奨)</item>
<item>500 m</item>
<item>1000 m</item>
<item>2000 m</item>
<item>5000 m (GPS信号強度不良)</item>
</string-array>
<string-array name="min_required_accuracy_options_ft">
<item>33 ft (GPS信号強度良好)</item>
<item>66 ft</item>
<item>165 ft</item>
<item>328 ft</item>
<item>656 ft (推奨)</item>
<item>1640 ft</item>
<item>0.6 mi</item>
<item>1.2 mi</item>
<item>3.1 mi (GPS信号強度不良)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>分割なし</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
<item>10 km</item>
<item>5 km</item>
<item>1 km</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="split_frequency_options_ft">
<item>分割なし</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
<item>10 mi</item>
<item>5 mi</item>
<item>1 mi</item>
<item>60 分</item>
<item>30 分</item>
<item>15 分</item>
<item>10 分</item>
<item>5 分</item>
<item>2 分</item>
<item>1 分</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>ラジコンボート</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="waypoint_types">
<item>ATM</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>
</resources>
+395
View File
@@ -0,0 +1,395 @@
<?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>
<!-- 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_docs">Google Docsへのトラック送信でエラーが発生しました.しばらく待って試して下さい.</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">大きなファイルです(500KB未満でなければなりません).終了します.</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_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">ここをタップして,セキュリティ &amp;位置情報 を開いて,「GPS機能をONにする」にチェックして下さい.バックボタンで戻ってください.</string>
<string name="status_approximate_location">ご注意: 携帯電話中継局とWi-Fiネットワークから大まかな位置を特定します.</string>
<string name="status_no_location">現在位置決定ができません.位置取得源を増やし(セキュリティ&amp;位置情報をご覧ください),空が見えるようにして下さい.もう一度試して下さい.</string>
<string name="status_waypoint_inserted">ウェイポイントマーカを挿入しました.</string>
<string name="status_statistics_inserted">統計マーカを挿入しました.</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_mymaps">Googleマップの認証しています...</string>
<string name="progress_message_authenticating_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="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 My Maps -->
<string name="new_map_description">Android用My Tracksで作成</string>
<string name="my_map_link">Android用&lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt;で作成しました.</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">(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">OK</string>
<string name="error">エラー</string>
<string name="success">成功</string>
<string name="waypoint">ウェイポイント</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 My Mapsへ送信</string>
<string name="tracklist_send_to_new_mymap">新規Googleマイマップへ送信</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_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">CVSファイルの保存</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">Googleマイマップへのリンク</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_clear_map">マップの消去</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_announcement_frequency">定期通知</string>
<string name="settings_announcement_frequency_summary">音声通知間隔の最小時間</string>
<string name="settings_announcement_not_available_summary">お使いのAndroidの版では音声読み上げ機能がありません</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_signal_sampling_frequency">信号サンプリング周波数</string>
<string name="settings_signal_sampling_frequency_summary">端末の信号強度記録の時間間隔</string>
<string name="settings_split_frequency">分割頻度</string>
<string name="settings_split_frequency_summary">分割マーカを挿入する時間または距離の間隔</string>
<string name="pace_label">ペース</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_map">マップの共有</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>
<string name="close">閉じる</string>
<string name="edit">編集</string>
<string name="cancel">キャンセル</string>
<string name="save">保存</string>
<!-- Sharing -->
<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 Earthまたは他のマッピングソフトウェアが必要です.</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>
<!-- Distance -->
<string name="meter">m</string>
<string name="kilometer">km</string>
<string name="kilometers_long">キロメータ</string>
<string name="feet">ft</string>
<string name="mile">mi</string>
<string name="miles_long">マイル</string>
<!-- Speed and Pace -->
<string name="kilometer_per_hour">km/h</string>
<string name="kilometer_per_hour_long">キロメータ毎時</string>
<string name="min_per_kilometer">min/km</string>
<string name="per_kilometer">毎キロメータ</string>
<string name="mile_per_hour">mi/h</string>
<string name="mile_per_hour_long">マイル毎時</string>
<string name="min_per_mile">min/mi</string>
<string name="per_mile">毎マイル</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="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_email">サポート</string>
<string name="about_support">サポート:</string>
<!-- Send to Google -->
<string name="sendtogoogle_title">送信...</string>
<string name="sendtogoogle_google_mymaps">Googleマイマップ</string>
<string name="sendtogoogle_google_docs">Google Docs</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_create_dir_failed">SDカードにディレクトリを作成できません.</string>
<string name="io_write_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 のアップグレードしてください.</string>
<string name="upgrade_recommended">お使いの版では,確実には動作しません.すぐにアップグレードすることをお勧めします.アップグレードされない場合は問題発生の可能性があることをご認識ください. サーバ同期するような機能の中には,アップグレードされるまで機能しないものがあります.</string>
<string name="upgrade_available">%1$s の新しい版が出ています.現版で問題なくご使用になれますが,アップグレードするまで最新の機能をお使いになれません.</string>
<!-- Welcome -->
<string name="welcome">ようこそ</string>
<string name="welcome_read_later">Ok</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">My Tracks %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>
<!-- Signal Strength -->
<string name="error_rate"> 誤り率: %1$d</string>
<string name="signal_to_noise_ratio"> S/N比: %1$d</string>
<string name="ecio"> Ec/Io比: %1$.1f dB</string>
<string name="gsm_strength">GSM 強度: %1$d</string>
<string name="cdma_strength">CDMA 強度: %1$d dBm</string>
<string name="evdo_strength">EVDO 強度: %1$d dBm</string>
</resources>
+278
View File
@@ -0,0 +1,278 @@
<?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>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Brak</item>
<item>1 min</item>
<item>2 min</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
<item>60 min</item>
</string-array>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
<item>2 m</item>
<item>3 m</item>
<item>4 m</item>
<item>5 m (zalecane)</item>
<item>10 m</item>
<item>100 m</item>
</string-array>
<string-array name="min_recording_distance_options_ft">
<item>3 stopy</item>
<item>6 stóp</item>
<item>10 stóp</item>
<item>13 stóp</item>
<item>16 stóp (zalecane)</item>
<item>33 stopy</item>
<item>328 stóp</item>
</string-array>
<!-- Maximum recording distance -->
<string-array name="max_recording_distance_options">
<item>50 m</item>
<item>100 m</item>
<item>200 m (zalecane)</item>
<item>500 m</item>
<item>1000 m</item>
<item>5000 m</item>
</string-array>
<string-array name="max_recording_distance_options_ft">
<item>164 stopy</item>
<item>328 stóp</item>
<item>656 stóp (polecane)</item>
<item>1640 stóp</item>
<item>0.6 mili</item>
<item>3.1 mili</item>
</string-array>
<!-- Minimum recording interval -->
<string-array name="min_recording_interval_options">
<item>oszczędzanie baterii (adaptacyjny)</item>
<item>wysoka dokładność (adaptacyjny)</item>
<item>najwyższa (zalecane)</item>
<item>2 s</item>
<item>3 s</item>
<item>4 s</item>
<item>5 s</item>
<item>10 s</item>
<item>20 s</item>
<item>30 s</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>
</string-array>
<!-- Minimum required accuracy -->
<string-array name="min_required_accuracy_options">
<item>10 m (doskonał sygnał GPS)</item>
<item>20 m</item>
<item>50 m</item>
<item>100 m</item>
<item>200 m (zalecane)</item>
<item>500 m</item>
<item>1000 m</item>
<item>2000 m</item>
<item>5000 m (słaby sygnał GPS)</item>
</string-array>
<string-array name="min_required_accuracy_options_ft">
<item>33 stopy (doskonały sygnał GPS)</item>
<item>66 stóp</item>
<item>165 stóp</item>
<item>328 stóp</item>
<item>656 stóp (zalecany)</item>
<item>1640 ft</item>
<item>0.6 mili</item>
<item>1.2 mili</item>
<item>3.1 mili (słaby sygnał GPS)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>Brak dzielenia</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
<item>10 km</item>
<item>5 km</item>
<item>1 km</item>
<item>60 min</item>
<item>30 min</item>
<item>15 min</item>
<item>10 min</item>
<item>5 min</item>
<item>2 min</item>
<item>1 min</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>Brak dzielenia</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
<item>10 mi</item>
<item>5 mi</item>
<item>1 mi</item>
<item>60 min</item>
<item>30 min</item>
<item>15 min</item>
<item>10 min</item>
<item>5 min</item>
<item>2 min</item>
<item>1 min</item>
</string-array>
<!-- Other non-preference arrays -->
<array name="activity_types">
<item>nieznany</item>
<item>typ mieszany</item>
<item>inny</item>
<item>bieanie</item>
<item>bieganie uliczne</item>
<item>bieganie na torze</item>
<item>bieganie terenowe</item>
<item>spacer</item>
<item>szybki spacer</item>
<item>wędrówka</item>
<item>wędrówka po szlaku</item>
<item>wędrówka poza szlakiem</item>
<item>wspinaczka</item>
<item>jazda rowerem</item>
<item>jazda po szosie</item>
<item>jazda górska</item>
<item>jazda na torze</item>
<item>łyżwiarstwo</item>
<item>łyżwiarstwo torowe</item>
<item>deskorolka</item>
<item>wędrówka po sniegu</item>
<item>narciarstwo</item>
<item>snowboard</item>
<item>saneczkastwo</item>
<item>żeglarstwo lodowe</item>
<item>żeglowanie</item>
<item>paddling</item>
<item>kajak</item>
<item>wioślarstwo</item>
<item>motorówka</item>
<item>prom</item>
<item>łódź zdalnie st.</item>
<item>surfing</item>
<item>wind surfing</item>
<item>kite surfing</item>
<item>narty wodne</item>
<item>wake boarding</item>
<item>samolot</item>
<item>wodolot</item>
<item>commercial airplane</item>
<item>helikopter</item>
<item>balon powietrzny</item>
<item>sterowiec</item>
<item>samolot zdalnie st.</item>
<item>helikopter zalnie st.</item>
<item>sky jumping</item>
<item>szybowiec</item>
<item>hang gliding</item>
<item>para gliding</item>
<item>jeździectwo</item>
<item>jazda konna</item>
<item>jazda na ośle</item>
<item>samochód</item>
<item>autobus</item>
<item>pociąg</item>
<item>motocykl</item>
<item>rower terenowy</item>
<item>ATV</item>
<item>żeglarstwo lądowe</item>
<item>ringo</item>
<item>ultimate ringo</item>
</array>
<array name="waypoint_types">
<item>bankomat</item>
<item>bank</item>
<item>bar</item>
<item>grill</item>
<item>budynek</item>
<item>przystanek autobusowy</item>
<item>kawa</item>
<item>ognisko</item>
<item>kemping</item>
<item>kościół</item>
<item>kawiarnia</item>
<item>delikatesy</item>
<item>woda pitna</item>
<item>spadające skały</item>
<item>prom</item>
<item>kominek</item>
<item>remiza strażacka</item>
<item>baza wędkarska</item>
<item>stcja paliw</item>
<item>pole golfowe</item>
<item>sklep spożywczy</item>
<item>fryzjer</item>
<item>zatoka</item>
<item>szlak</item>
<item>hotel</item>
<item>dom</item>
<item>informacja</item>
<item>skrzyżowanie</item>
<item>skrzynka pocztowa</item>
<item>market</item>
<item>miejsce zbiórki</item>
<item>opera</item>
<item>parking</item>
<item>poczta</item>
<item>grota</item>
<item>posterunek policji</item>
<item>przejazd kolejowy</item>
<item>restauracja</item>
<item>zakupy</item>
<item>widok</item>
<item>sklep</item>
<item>basen</item>
<item>telefon</item>
<item>teatr</item>
<item>toaleta</item>
<item>informacja turystyczna</item>
<item>tunel</item>
<item>drzewo</item>
<item>wodospad</item>
<item>zdrój</item>
<item>punkt orientacyjny</item>
</array>
</resources>
+393
View File
@@ -0,0 +1,393 @@
<?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">Rejestruj trasę</string>
<string name="stop_recording">Zakończ rejestrowanie</string>
<string name="switch_to_sat">Tryb satelitarny</string>
<string name="switch_to_map">Tryb mapy</string>
<string name="mylocation">Moja lokalizacja</string>
<string name="list_tracks">Trasy</string>
<string name="list_markers">Znaczniki</string>
<string name="delete_all_tracks">Usuń wszystkie trasy</string>
<string name="settings">Ustawienia</string>
<string name="elevation">Wysokość n.p.m.</string>
<string name="choose_track_message">Wybierz trasę do podglądu</string>
<string name="current_track">Obecna trasa</string>
<string name="current_segment">Ostatni segment</string>
<!-- Error messages -->
<string name="error_no_location_manager">Brak menedżera lokalizacji na urządzeniu!</string>
<string name="error_no_gps_location_provider">Brak dostawcy lokalizacji GPS na urządzeniu.</string>
<string name="error_sending_to_mymap">Podczas przesyłania pliku do Moich Map Google pojawił się błąd. Spróbuj ponownie później.</string>
<string name="error_sending_to_docs">Podczas przesyłania pliku do Dokumentów Google pojawił się błąd. Spróbuj ponownie później.</string>
<string name="error_unable_to_start_recording">Nie można rozpocząć rejestrowania. Spróbuj ponownie.</string>
<string name="error_unable_to_stop_recording">Nie można zakończyć rejestrowania. Spróbuj ponownie.</string>
<string name="error_unable_to_read_file">Nie można czytać z pliku.</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_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_unable_to_insert_marker">Nie można wstawić markera. Brak poprawnych danych o lokalizacji.</string>
<!-- Status messages -->
<string name="wait_for_fix">Oczekiwanie na lepsze ustalenie pozycji GPS. Upewnij się, że niebo jest widoczne.</string>
<string name="status_now_recording">Rejestrowanie nowej trasy.</string>
<string name="status_stopped_recording">Zatrzymano rejestrowanie nowej trasy.</string>
<string name="status_new_mymap_has_been_created">Utworzona nową Mapę Google na maps.google.com.</string>
<string name="status_tracks_have_been_uploaded">Twoja trasa został wysłana do maps.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">Twoja trasa została wysłana do nowego arkusza na docs.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_docs">Twoja trasa została wysłana do docs.google.com.</string>
<string name="status_mymap_info">Trasa będzie widoczna za kilka minut.</string>
<string name="status_enable_gps">Tapnij tutaj, aby przejść do ustawień Lokalizacji i zabezpieczeń, a następnie zaznacz Użyj satelitów GPS. Naciśnij klawisz Wstecz, aby powrócić.</string>
<string name="status_approximate_location">Uwaga: używana jest przybliżona lokalizacja ustalona za pomocą stacji komórkowych i sieci WIFI.</string>
<string name="status_no_location">Lokalizacja nie może być obecnie ustalona. Włącz wiecej źródeł (zobacz ustawienia Lokalizacji i zabezpieczeń) i upewnij się, że niebo jest widoczne. Spróbuj później.</string>
<string name="status_waypoint_inserted">Wstawiono znacznik punktu orientacyjnego.</string>
<string name="status_statistics_inserted">Wstawiono znacznik statystyk.</string>
<!-- Progress dialog -->
<string name="progress_title">Proszę czekać...</string>
<string name="progress_message">Przesyłanie trasy do Google.</string>
<string name="progress_message_reading_track">Czytanie trasy...</string>
<string name="progress_message_preparing_track">Przygotowywanie trasy...</string>
<string name="progress_message_authenticating_mymaps">Uwierzytelnianie w Mapach Google...</string>
<string name="progress_message_authenticating_docs">Uwierzytelnianie w Dokumentach Google...</string>
<string name="progress_message_sending_docs">Przesyłanie trasy do Dokumentów Google...</string>
<string name="progress_message_sending_mymaps">Przesyłanie trasy do Map Google...</string>
<string name="progress_message_creating_map">Tworzenie nowej Mojej Mapy...</string>
<string name="import_progress_message">Importowanie trasy GPS. Poczekaj chwilę.</string>
<string name="write_progress_message">Zapisywanie pliku na kartę SD. Poczekaj chwilę.</string>
<string name="progress_message_updating_track">Aktualizacja statystyk trasy...</string>
<!-- Used by DeleteAllDataHandler -->
<string name="are_you_sure_question">Jesteś pewien?</string>
<string name="all_data_will_be_permanently_deleted">Wszystkie trasy i znaczniki zostaną usunięte z tego telefonu.</string>
<string name="track_will_be_permanently_deleted">Trasy i ich znaczniki zostaną całkowicie usunięte z tego telefonu.</string>
<string name="marker_will_be_permanently_deleted">Znacznik zostanie całkowicie usunięty z tego telefonu.</string>
<!-- Text and links when uploading to Google My Maps -->
<string name="new_map_description">Utworzono za pomocą My Tracks na Android.</string>
<string name="my_map_link">Utworzona przez &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; na Android.</string>
<string name="new_map_title">Nowa mapa</string>
<!-- Formatting of track and marker descriptions -->
<string name="points">Punkty</string>
<string name="recorded_date">Zapisana</string>
<string name="category">Typ aktywności</string>
<string name="waypoint_category">Typ znacznika</string>
<string name="part">(Część %d)</string>
<!-- Used by the track recording service -->
<string name="recording_your_track">Rejestrowanie twojej trasy...</string>
<string name="new_track">Trasa %d</string>
<!-- Common -->
<string name="no">Nie</string>
<string name="yes">Tak</string>
<string name="ok">OK</string>
<string name="error">Błąd</string>
<string name="success">Powodzenie</string>
<string name="waypoint">Punkt orientacyjny</string>
<!-- Placemark labels for start and end of track -->
<string name="start">(Początek)</string>
<string name="end">(Koniec)</string>
<!-- TrackList -->
<string name="tracklist_show_track">Pokaż</string>
<string name="tracklist_send_to_mymaps">Wyślij do Moich Map Google</string>
<string name="tracklist_send_to_new_mymap">Wyślij do Moich Map Google jako nową mapę</string>
<string name="tracklist_send_to_docs">Wyślij do Dokumentów Google</string>
<string name="tracklist_send_to_google">Wyślij do Google...</string>
<string name="tracklist_delete_track">Usuń z telefonu...</string>
<string name="tracklist_edit_track">Edytuj szczegóły</string>
<string name="tracklist_write_to_sd">Zapisz na karcie SD...</string>
<string name="tracklist_save_as_gpx">Zapisz plik GPX</string>
<string name="tracklist_save_as_kml">Zapisz plik KML</string>
<string name="tracklist_save_as_csv">Zapisz plik CSV</string>
<string name="tracklist_btn_send_all_to_mymaps">Wyślij do Moich Map Google</string>
<string name="tracklist_btn_delete_all">Usuń wszystkie trasy</string>
<!-- Export All -->
<string name="tracklist_btn_export_all">Eksportuj wszystkie trasy</string>
<string name="export_done">Eksport zakończony</string>
<string name="tracklist_pick_one">Wybierz trasę. Naciśnij i przytrzymaj, aby wybrać opcje.</string>
<string name="tracklist_all_tracks">Wszystkie trasy:</string>
<string name="tracklist_this_track">Ta trasa</string>
<string name="tracklist_share_track">Podziel się z przyjaciółmi...</string>
<string name="tracklist_share_link">Link do Moich Map Google</string>
<string name="tracklist_share_gpx_file">Plik GPX</string>
<string name="tracklist_share_kml_file">PLik KML</string>
<string name="tracklist_share_csv_file">Plik CSV</string>
<string name="tracklist_clear_map">Wyczyść mapę</string>
<!-- Waypoints list -->
<string name="waypointslist_btn_delete_all">Wyczyść wszystkie znaczniki</string>
<string name="waypointslist_this_waypoint">Ten znacznik</string>
<string name="waypointslist_delete_waypoint">Usuń</string>
<string name="waypointslist_edit_waypoint">Edytuj szczegóły</string>
<string name="waypointslist_show_waypoint">Pokaż na mapie</string>
<string name="waypointslist_btn_insert_waypoint">Wstaw punkt orientacyjny</string>
<string name="waypointslist_btn_insert_statistics">Wstaw statystyki</string>
<string name="waypointslist_pick_one">Wybierz znacznik. Naciśnij i przytrzymaj, aby wybrać opcje.</string>
<!-- MyTracks Details -->
<string name="trackdetails_title">Szczegóły trasy</string>
<string name="trackdetails_name">Nazwa trasy</string>
<string name="trackdetails_description">Opis trasy</string>
<string name="trackdetails_category">Typ aktywności (np. wspinanie, jazda rowerem, bieganie...)</string>
<!-- MyTracks Waypoint Details -->
<string name="waypointdetails_title">Szczegóły znacznika</string>
<string name="waypointdetails_name">Nazwa znacznika</string>
<string name="waypointdetails_description">Opis znacznika</string>
<string name="waypointdetails_category">Typ znacznika (np. budynek, jaskinia, punkt widokowy...)</string>
<!-- MyTracks Settings -->
<string name="mytracks_settings">Ustawienia My Tracks</string>
<string name="settings_display">Wyświetlanie</string>
<string name="settings_recording">Rejestrowanie</string>
<string name="settings_sharing">Dzielenie</string>
<string name="settings_announcement_frequency">Częstotliwość komunikatów</string>
<string name="settings_announcement_frequency_summary">Minimalny czas między dwoma komunikatami głosowymi</string>
<string name="settings_announcement_not_available_summary">Brak wsparcia dla syntezy mowy w twojej wersji Androida</string>
<string name="settings_min_recording_distance">Min. odległość między punktami</string>
<string name="settings_min_recording_distance_summary">Najmniejsza odległość między dwoma zapisami twojej pozycji</string>
<string name="settings_max_recording_distance">Max. odległość między punktami</string>
<string name="settings_max_recording_distance_summary">Jeśli dwa punkty są dalej niż ta wartość, trasa zostanie podzielona</string>
<string name="settings_min_recording_interval">Min. czas między punktami</string>
<string name="settings_min_recording_interval_summary">Najmniejsza odstęp czasowy między dwoma zapisami twojej pozycji</string>
<string name="settings_min_required_accuracy">Minimalna dokładność</string>
<string name="settings_min_required_accuracy_summary">Zapis zostanie zatrzymany jeśli twoja pozycja jest mniej dokładana niż ta wartość</string>
<string name="settings_metric_units">Używaj jednostek metrycznych</string>
<string name="settings_metric_units_summary_on">Wszystkie odległości będą wyświetlane w jednostkach metrycznych</string>
<string name="settings_metric_units_summary_off">Wszystkie odległości będą wyświetlane w jednostkach imperialnych</string>
<string name="settings_map_public">Ustaw mapy jako publiczne</string>
<string name="settings_map_public_summary_on">Przesłane mapy będą dostępne dla wszystkich na maps.google.com</string>
<string name="settings_map_public_summary_off">Przesłane mapy nie będą dostępne publicznie na maps.google.com</string>
<string name="settings_report_speed_or_pace">Wyświetlanie prędkości</string>
<string name="settings_report_speed_or_pace_summary_on">Prędkość będzie wyświetlana</string>
<string name="settings_report_speed_or_pace_summary_off">Tempo będzie wyświetlane</string>
<string name="settings_share_url_only">Dziel się tylko odnośnikiem</string>
<string name="settings_share_url_only_summary_on">Tylko odnośnik do mapy będzie wysyłany podczas dzielenia się</string>
<string name="settings_share_url_only_summary_off">Zawartość trasy również będzie przesyłana</string>
<string name="settings_signal_sampling_frequency">Częstotliowść próbkowania sygnału</string>
<string name="settings_signal_sampling_frequency_summary">Czas między dwoma zapisami siły sygnału telefonu</string>
<string name="settings_split_frequency">Częstotliwość rozdzielania</string>
<string name="settings_split_frequency_summary">Maksymalny czas lub odległość po którym wstawiony zostanie znacznik rozdzielenia</string>
<string name="pace_label">Tempo</string>
<!-- MyTracksSky -->
<string name="mytracks_sky">Satelity GPS</string>
<!-- My Maps -->
<string name="select_map_message">Wybierz mapę z twojego konta:</string>
<string name="create_new_map">Utwórz nową mapę...</string>
<string name="map_list_title">Wyślij do Moich Map Google</string>
<string name="maps_list_loading">Wczytywanie map...</string>
<string name="maps_list_failed">Nie można wczytać twoich map!</string>
<string name="open_map">Wybierz tę mapę</string>
<string name="edit_map_details">Edytuj szczegóły mapy</string>
<string name="share_map">Podziel się mapą z przyjaciółmi</string>
<string name="share_track">Podziel się trasą z przyjaciółmi</string>
<string name="delete_map">Usuń mapę z twojego konta</string>
<string name="map_title">Tytuł mapy:</string>
<string name="map_description">Opis mapy:</string>
<string name="map_searchable_edit">Pokazuj tę pamę i jej zawartość w wynikach wyszukiwania</string>
<string name="map_not_searchable_edit">Nie pokazuj tej mapy i jej zawartości w wynikach wyszukiwania. Dostęp do mapy będzie ciągle możliwy poprzez odnośnik</string>
<string name="map_searchable">Ta mapa i jej zawartość będzie dostępna w wynikach wyszukiwania</string>
<string name="map_not_searchable">Mapa i jej zawartość nie będzie dostępna w wynikach wyszukiwania, ale będzie dostępna przez bezpośredni odnośnik</string>
<string name="close">Zamknij</string>
<string name="edit">Edytuj</string>
<string name="cancel">Anuluj</string>
<string name="save">Zapisz</string>
<!-- Sharing -->
<string name="share_map_subject">Chciałbym się z Tobą podzielić mapą</string>
<string name="share_map_body_format">Myślę, że może Cię zainteresować ta mapa:
%s</string>
<string name="send_track_subject">Chciałbym się z Tobą podzielić trasą</string>
<string name="send_track_body_format">Myślę, że może Cię zainteresować ta trasa.
Trasę możesz obejrzeć w Google Earth lub innym programie do obsługi map.</string>
<!-- Visibility -->
<string name="public_map">Publiczna</string>
<string name="unlisted_map">Niepubliczna</string>
<string name="mapslist_no_maps_available">Nie masz jeszcze żadnych map.</string>
<!-- Statistics View -->
<!-- Average Moving -->
<string name="average_moving_speed_label">Średnia prędkość poruszania</string>
<string name="average_moving_pace_label">Średnie tempo poruszania</string>
<!-- Average -->
<string name="average_speed_label">Średnia prędkość</string>
<string name="average_pace_label">Średnie tempo</string>
<string name="elevation_chart_name">Wykres wysokości</string>
<string name="elevation_gain_label">Wzrost wysokości</string>
<string name="elevation_label">Wysokość</string>
<string name="latitude_label">Szerokość</string>
<string name="longitude_label">Długość</string>
<!-- Min -->
<string name="min_elevation_label">Min. wysokość</string>
<string name="min_grade_label">Min. nachylenie</string>
<string name="min_pace_label">Min. tempo</string>
<!-- Max -->
<string name="max_elevation_label">Maks. wysokość</string>
<string name="max_grade_label">Maks. nachylenie</string>
<string name="max_speed_label">Maks. prędkość</string>
<string name="loading_track">Wczytywanie trasy...</string>
<!-- Chart Settings -->
<string name="chart_settings">Ustawienia wykresów</string>
<!-- X Axis -->
<string name="x_axis">Oś X</string>
<string name="by_distance">Według odległości</string>
<string name="by_time">Według czasu</string>
<!-- Y Axis -->
<string name="y_axis">Oś Y</string>
<!-- Units -->
<!-- Time -->
<string name="hour">godzina</string>
<string name="hours">godziny</string>
<string name="hr">godz.</string>
<string name="min">min</string>
<string name="minute">minuta</string>
<string name="minutes">minuty</string>
<string name="second">sekunda</string>
<string name="seconds">sekundy</string>
<!-- Distance -->
<string name="meter">m</string>
<string name="kilometer">km</string>
<string name="kilometers_long">kilometerów</string>
<string name="feet">st.</string>
<string name="mile">mi</string>
<string name="miles_long">mil</string>
<!-- Speed and Pace -->
<string name="kilometer_per_hour">km/h</string>
<string name="kilometer_per_hour_long">kilometry na godzinę</string>
<string name="min_per_kilometer">min/km</string>
<string name="per_kilometer">na kilometr</string>
<string name="mile_per_hour">mi/h</string>
<string name="mile_per_hour_long">mile na godzinę</string>
<string name="min_per_mile">min/mi</string>
<string name="per_mile">na milę</string>
<!-- Stats Labels -->
<string name="moving_time_label">Czas w ruchu</string>
<string name="total_time_label">Całkowity czas</string>
<string name="time_label">Czas</string>
<string name="sd_unavail">Karta SD niedostępna</string>
<string name="speed">Prędkość</string>
<string name="start_trip">Musisz rozpocząć podróż.</string>
<string name="statistics">Statystyki</string>
<string name="total_distance_label">Całkowita odległość</string>
<string name="distance_label">Odległość</string>
<string name="unknown">-</string>
<string name="waiting">Oczekiwanie...</string>
<!-- End User License Agreement -->
<string name="eula_title">Licencja użytkownika końcowego</string>
<string name="accept">Zaakceptuj</string>
<string name="decline">Odrzuć</string>
<!-- About -->
<string name="about">O</string>
<string name="help">Pomoc</string>
<string name="about_team">Zespół:</string>
<string name="about_version">Wersja:</string>
<string name="about_email">Wsparcie</string>
<string name="about_support">Wsparcie:</string>
<!-- Send to Google -->
<string name="sendtogoogle_title">Wyślij do...</string>
<string name="sendtogoogle_google_mymaps">Moje Mapy Google</string>
<string name="sendtogoogle_google_docs">Dokumenty Google</string>
<string name="sendtogoogle_send_now">Wyślij teraz</string>
<string name="sendtogoogle_create_new_map">Utwórz nową mapę</string>
<string name="sendtogoogle_pick_existing_map">Wybierz istniejąca mapę</string>
<string name="sendtogoogle_send_stats">Wyślij statystyki trasy</string>
<string name="sendtogoogle_send_stats_and_points">Wyślij statystyki i punkty</string>
<!-- Getting the account to upload to. -->
<string name="no_account_found_title">Znaleziono nowe konto</string>
<string name="no_account_found">Nie znaleziono konta do przesyłu.</string>
<string name="choose_account_title">Wybierz konto</string>
<!-- SD card -->
<string name="io_no_external_storage_found">Nie znaleziono zewnętrznej pamięci. Upewniej się, że karta SD jest w telefonie i nie jest podłączona do komputera.</string>
<string name="io_write_failed">Nie można zapisać pliku.</string>
<string name="io_create_dir_failed">Nie można utworzyć katalogu na karcie SD.</string>
<string name="io_write_finished">Zakończono zapisywanie trasy na karcie SD.</string>
<!-- VersionChecker -->
<string name="version_check_title">Sprawdzanie aktualizacji</string>
<string name="version_check_upgrade_button">Aktualizuj</string>
<string name="version_check_continue_button">Kontynuuj bez aktualizacji</string>
<string name="upgrade_required">Twoja wersja %1$s może nie działać poprawnie i nie jest już wspierana. Jeśli chcesz nadal używać %1$s zaktualizuj program.</string>
<string name="upgrade_recommended">Twoja wersja %1$s może nie działać poprawnie. MOżesz zaktualizować program lub używać obecnej wersji na własne ryzyko. Niektóre funkcje, takie jak synchronizacja z serwerem nie będą działać dopóki nie zaktualizujesz programu.</string>
<string name="upgrade_available">Dostępna jest nowa wersja %1$s is available. Możesz nadal używać obecnej wersji bez problemów, nie będziesz miał jednak dostępu do najnowszych funkcji.</string>
<!-- Welcome -->
<string name="welcome">Witamy</string>
<string name="welcome_read_later">Ok</string>
<string name="welcome_about">O My Tracks</string>
<!-- Announcement -->
<string name="announce_no_distance">My Tracks brak odległości</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">My Tracks %1$s %2$.2f %3$s w %4$s w tempie %5$s %6$s</string>
<!-- Check Units -->
<string name="check_units_title">Jednostki miary</string>
<string name="check_units_message">Domyślnie używane są jednostki metryczne. Chcesz to zmienić?</string>
<!-- Signal Strength -->
<string name="error_rate"> Poziom błędów: %1$d</string>
<string name="signal_to_noise_ratio"> Stosunek sygnału do szumu: %1$d</string>
<string name="ecio"> Ec/lo: %1$.1f dB</string>
<string name="gsm_strength">Siła GSM: %1$d</string>
<string name="cdma_strength">Siła CDMA: %1$d dBm</string>
<string name="evdo_strength">Siła EVDO: %1$d dBm</string>
</resources>
+278
View File
@@ -0,0 +1,278 @@
<?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>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Av</item>
<item>1 min</item>
<item>2 min</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
<item>60 min</item>
</string-array>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
<item>2 m</item>
<item>3 m</item>
<item>4 m</item>
<item>5 m (rekommenderad)</item>
<item>10 m</item>
<item>100 m</item>
</string-array>
<string-array name="min_recording_distance_options_ft">
<item>3 ft</item>
<item>6 ft</item>
<item>10 ft</item>
<item>13 ft</item>
<item>16 ft (rekommenderad)</item>
<item>33 ft</item>
<item>328 ft</item>
</string-array>
<!-- Maximum recording distance -->
<string-array name="max_recording_distance_options">
<item>50 m</item>
<item>100 m</item>
<item>200 m (rekommenderad)</item>
<item>500 m</item>
<item>1000 m</item>
<item>5000 m</item>
</string-array>
<string-array name="max_recording_distance_options_ft">
<item>164 ft</item>
<item>328 ft</item>
<item>656 ft (rekommenderad)</item>
<item>1640 ft</item>
<item>0.6 miles</item>
<item>3.1 miles</item>
</string-array>
<!-- Minimum recording interval -->
<string-array name="min_recording_interval_options">
<item>batterioptimerad (anpassningsbar)</item>
<item>hög precision (anpassningsbar)</item>
<item>högsta (rekommenderad)</item>
<item>2 s</item>
<item>3 s</item>
<item>4 s</item>
<item>5 s</item>
<item>10 s</item>
<item>20 s</item>
<item>30 s</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>
</string-array>
<!-- Minimum required accuracy -->
<string-array name="min_required_accuracy_options">
<item>10 m (bra GPS-signal)</item>
<item>20 m</item>
<item>50 m</item>
<item>100 m</item>
<item>200 m (rekommenderad)</item>
<item>500 m</item>
<item>1000 m</item>
<item>2000 m</item>
<item>5000 m (dålig GPS-signal)</item>
</string-array>
<string-array name="min_required_accuracy_options_ft">
<item>33 ft (bra GPS-signal)</item>
<item>66 ft</item>
<item>165 ft</item>
<item>328 ft</item>
<item>656 ft (rekommenderad)</item>
<item>1640 ft</item>
<item>0.6 miles</item>
<item>1.2 miles</item>
<item>3.1 miles (dålig GPS-signal)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>Ingen delning</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
<item>10 km</item>
<item>5 km</item>
<item>1 km</item>
<item>60 min</item>
<item>30 min</item>
<item>15 min</item>
<item>10 min</item>
<item>5 min</item>
<item>2 min</item>
<item>1 min</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>Ingen delning</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
<item>10 mi</item>
<item>5 mi</item>
<item>1 mi</item>
<item>60 min</item>
<item>30 min</item>
<item>15 min</item>
<item>10 min</item>
<item>5 min</item>
<item>2 min</item>
<item>1 min</item>
</string-array>
<!-- Other non-preference arrays -->
<array name="activity_types">
<item>okänd</item>
<item>blandat</item>
<item>annat</item>
<item>löpning</item>
<item>väglöpning</item>
<item>banlöpning</item>
<item>spårlöpning</item>
<item>gång</item>
<item>gångsport</item>
<item>vandring</item>
<item>spårvandring</item>
<item>vildmarksvandring</item>
<item>klättring</item>
<item>cykling</item>
<item>vägcyckling</item>
<item>mountainbikeåkning</item>
<item>bancyckling</item>
<item>skridskoåkning</item>
<item>inlineåkning</item>
<item>skateboardåkning</item>
<item>snöskovandring</item>
<item>skidåkning</item>
<item>snowboardåkning</item>
<item>kälke</item>
<item>issegling</item>
<item>segling</item>
<item>paddling</item>
<item>kayakpaddling</item>
<item>rodd</item>
<item>motorbåtsåkning</item>
<item>färja</item>
<item>RC båt</item>
<item>surfning</item>
<item>vindsurfning</item>
<item>kite surfing</item>
<item>vattenskidåkning</item>
<item>wakeboardåkning</item>
<item>flygplan</item>
<item>sjöflygplan</item>
<item>kommersiellt flygplan</item>
<item>helikopter</item>
<item>varmlyftsballong</item>
<item>luftskepp</item>
<item>RC flygplan</item>
<item>RC helicopter</item>
<item>falskärmshoppning</item>
<item>segelflygning</item>
<item>hängflygning</item>
<item>skärmflygning</item>
<item>ridning</item>
<item>hästridning</item>
<item>åsneridning</item>
<item>köra bil</item>
<item>köra buss</item>
<item>tåg</item>
<item>motorcykel</item>
<item>motorcross</item>
<item>fyrhjuling</item>
<item>landsegling</item>
<item>frisbee</item>
<item>ultimate frisbee</item>
</array>
<array name="waypoint_types">
<item>bankomat</item>
<item>bank</item>
<item>bar</item>
<item>barbeque</item>
<item>byggnad</item>
<item>bushållplats</item>
<item>café</item>
<item>lägereld</item>
<item>kampingklatts</item>
<item>kyrka</item>
<item>kaffestuga</item>
<item>närbutik</item>
<item>driksvatten</item>
<item>fallande stenar</item>
<item>färja</item>
<item>äldplats</item>
<item>brandstation</item>
<item>fiske</item>
<item>bensinstation</item>
<item>golfbana</item>
<item>mataffär</item>
<item>hårfrissör</item>
<item>hamn</item>
<item>vandringsled</item>
<item>hotel</item>
<item>hus</item>
<item>information</item>
<item>korsning</item>
<item>postlåda</item>
<item>marknad</item>
<item>mötesplats</item>
<item>opera</item>
<item>parkering</item>
<item>postkontor</item>
<item>grop</item>
<item>polisstation</item>
<item>järnvägskorssning</item>
<item>restaurant</item>
<item>shopping</item>
<item>sevärdhet</item>
<item>affär</item>
<item>simbassäng</item>
<item>telefon</item>
<item>teater</item>
<item>toalett</item>
<item>turistinformation</item>
<item>tunnel</item>
<item>träd</item>
<item>vatenfall</item>
<item>wattenfontän</item>
<item>etappmål</item>
</array>
</resources>
+394
View File
@@ -0,0 +1,394 @@
<?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">Spela in spår</string>
<string name="stop_recording">Stoppa inspelning</string>
<string name="switch_to_sat">Satellitläge</string>
<string name="switch_to_map">Kartläge</string>
<string name="mylocation">Min plats</string>
<string name="list_tracks">Spår</string>
<string name="list_markers">Markörer</string>
<string name="delete_all_tracks">Ta bort alla spår</string>
<string name="settings">Inställningar</string>
<string name="elevation">Höjd</string>
<string name="choose_track_message">Välj ett spår att visa</string>
<string name="current_track">Nuvarande spår</string>
<string name="current_segment">Senaste segmentet</string>
<!-- Error messages -->
<string name="error_no_location_manager">Ingen platshanterare hittades på denna enhet!</string>
<string name="error_no_gps_location_provider">Ingen GPS-positioneringstjänst hittades på denna enhet.</string>
<string name="error_sending_to_mymap">Det uppstod ett fel i sändningen av ditt spår till Google My Map. Försök igen senare.</string>
<string name="error_sending_to_docs">Det uppstod ett fel i sändningen av ditt spår till Google Docs. Försök igen senare.</string>
<string name="error_unable_to_start_recording">Kan inte starta inspelningen. Försök igen.</string>
<string name="error_unable_to_stop_recording">Kan inte stoppa inspelningen. Försök igen.</string>
<string name="error_unable_to_read_file">Kan inte läsa från fil.</string>
<string name="error_invalid_gpx_format">Filen har inte ett giltigt GPX-format.</string>
<string name="error_generic">Ett fel uppstod. Försök igen.</string>
<string name="error_track_does_not_exist">Spåret finns inte.</string>
<string name="error_out_of_memory">Den här filen är för stor (måste vara mindre än 500 KB). Avbryter.</string>
<string name="error_unable_to_insert_marker">Kan inte skapa markör. Ingen possition tillgänglig.</string>
<!-- Status messages -->
<string name="wait_for_fix">Väntar på bättre GPS-posstion. Se till att himlen är synlig.</string>
<string name="status_now_recording">Spelar nu in ett nytt spår.</string>
<string name="status_stopped_recording">Stoppade inspelning av ditt spår.</string>
<string name="status_new_mymap_has_been_created">En ny Google My Map har skapats på maps.google.com.</string>
<string name="status_tracks_have_been_uploaded">Ditt spår har skickats till maps.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">Ditt spår har skockats till ett nytt kalkylblad på docs.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_docs">Ditt spår har skickats till docs.google.com.</string>
<string name="status_mymap_info">Det kan ibland ta några minuter innan nya spår visas.</string>
<string name="status_enable_gps">Klicka här för att gå till Säkerhet och Platsinställningar och kryssa i \'aktivera gps-satteliter\'. Tryck på tillbakaknappen för att återgå.</string>
<string name="status_approximate_location">OBS: En ungerfärlig position som avgörs från mobilmaster och WIFI-nät visas.</string>
<string name="status_no_location">En position kan för närvarande inte fastställas. Aktivera mer platskällor (se Säkerhet och Platsinställningar) och se till att himlen är synlig. Försök igen senare.</string>
<string name="status_waypoint_inserted">En positionsmarkör har lagts in.</string>
<string name="status_statistics_inserted">En statistikmarkör har lagts in.</string>
<!-- Progress dialog -->
<string name="progress_title">Var god vänta...</string>
<string name="progress_message">Skickar ditt spår till Google.</string>
<string name="progress_message_reading_track">Läser spår...</string>
<string name="progress_message_preparing_track">Förbereder spår...</string>
<string name="progress_message_authenticating_mymaps">Autentiserar till Google Maps...</string>
<string name="progress_message_authenticating_docs">Autentiserar till Google Docs...</string>
<string name="progress_message_sending_docs">Skickar spår till Google Docs...</string>
<string name="progress_message_sending_mymaps">Skickar spår till Google Maps...</string>
<string name="progress_message_creating_map">Skapar en ny My Map...</string>
<string name="import_progress_message">Importerar ett GPS-spår. Detta kan ta en stund.</string>
<string name="write_progress_message">Skriver til till SD-kortet. Detta kan ta en stund.</string>
<string name="progress_message_updating_track">Uppdaterar spårstatistik...</string>
<!-- Used by DeleteAllDataHandler -->
<string name="are_you_sure_question">Är du säker?</string>
<string name="all_data_will_be_permanently_deleted">Alla spår och markörer kommer att tas bort från telefonen.</string>
<string name="track_will_be_permanently_deleted">Spåret och dess markörer kommer att permanent tas bort från telefonen.</string>
<string name="marker_will_be_permanently_deleted">Markören kommer att permanent tas bort från telefonen.</string>
<!-- Text and links when uploading to Google My Maps -->
<string name="new_map_description">Skapad av My Tracks på Android.</string>
<string name="my_map_link">Skapad av &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; på Android.</string>
<string name="new_map_title">Ny karta</string>
<!-- Formatting of track and marker descriptions -->
<string name="points">Punkter</string>
<string name="recorded_date">Inspelad</string>
<string name="category">Aktivitetstyp</string>
<string name="waypoint_category">Markörtyp</string>
<string name="part">(Del %d)</string>
<!-- Used by the track recording service -->
<string name="recording_your_track">Spelar in ditt spår...</string>
<string name="new_track">Spår %d</string>
<!-- Common -->
<string name="no">Nej</string>
<string name="yes">Ja</string>
<string name="ok">OK</string>
<string name="error">Fel</string>
<string name="success">Lyckades</string>
<string name="waypoint">Positionsmärke</string>
<!-- Placemark labels for start and end of track -->
<string name="start">(Start)</string>
<string name="end">(Slut)</string>
<!-- TrackList -->
<string name="tracklist_show_track">Visa</string>
<string name="tracklist_send_to_mymaps">Skicka till Google My Maps</string>
<string name="tracklist_send_to_new_mymap">Skicka till New Google My Map</string>
<string name="tracklist_send_to_docs">Skicka till Google Docs</string>
<string name="tracklist_send_to_google">Skicka till Google...</string>
<string name="tracklist_delete_track">Ta bort från telefonen...</string>
<string name="tracklist_edit_track">Ändra detaljer</string>
<string name="tracklist_write_to_sd">Skriv till SD-kort...</string>
<string name="tracklist_save_as_gpx">Spara en GPX-fil</string>
<string name="tracklist_save_as_kml">Spara en KML-fil</string>
<string name="tracklist_save_as_csv">Spara en CSV-fil</string>
<string name="tracklist_btn_send_all_to_mymaps">Skicka till Google My Maps</string>
<string name="tracklist_btn_delete_all">Ta bort alla spår</string>
<!-- Export All -->
<string name="tracklist_btn_export_all">Exportera alla spår</string>
<string name="export_done">Exporteringen slutfördes</string>
<string name="tracklist_pick_one">Välj ett spår. TryckPress&amp;håll för fler alternativ.</string>
<string name="tracklist_all_tracks">Alla spår:</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_link">En länk till Google My Map</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_csv_file">En CSV-fil</string>
<string name="tracklist_clear_map">Rensa karta</string>
<!-- Waypoints list -->
<string name="waypointslist_btn_delete_all">Ta bort alla markörer</string>
<string name="waypointslist_this_waypoint">Den här markören</string>
<string name="waypointslist_delete_waypoint">Ta bort</string>
<string name="waypointslist_edit_waypoint">Ändra detaljer</string>
<string name="waypointslist_show_waypoint">Visa på karta</string>
<string name="waypointslist_btn_insert_waypoint">Infoga positionspunkt</string>
<string name="waypointslist_btn_insert_statistics">Infoga statistik</string>
<string name="waypointslist_pick_one">Välj en markör. TryckPress&amp;håll för fler alternativ.</string>
<!-- MyTracks Details -->
<string name="trackdetails_title">Spårdetaljer</string>
<string name="trackdetails_name">Spårnamn</string>
<string name="trackdetails_description">Spårbeskrivning</string>
<string name="trackdetails_category">Aktivitetstyp (t ex vandring, cyckling, låpning, klättring...)</string>
<!-- MyTracks Waypoint Details -->
<string name="waypointdetails_title">Markördetaljer</string>
<string name="waypointdetails_name">Markörnamn</string>
<string name="waypointdetails_description">Markörbeskrivning</string>
<string name="waypointdetails_category">Markörtyp (e.g. byggnad, grop, sevärdhet...)</string>
<!-- MyTracks Settings -->
<string name="mytracks_settings">My Tracks inställningar</string>
<string name="settings_display">Visning</string>
<string name="settings_recording">Inspelning</string>
<string name="settings_sharing">Delning</string>
<string name="settings_announcement_frequency">Meddelandefrekvens</string>
<string name="settings_announcement_frequency_summary">Minimumtid mellan två röstmeddelanden</string>
<string name="settings_announcement_not_available_summary">Text-till-talmeddelanden är inte tillgängligt i din version av Android</string>
<string name="settings_min_recording_distance">Min distans mellan två punkter</string>
<string name="settings_min_recording_distance_summary">Minsta distans mellan två inspelningar av din position</string>
<string name="settings_max_recording_distance">Max distans mellan punter</string>
<string name="settings_max_recording_distance_summary">Om två punkter är längre bort än det här, kommer spåret att delas</string>
<string name="settings_min_recording_interval">Min tid mellan punkter</string>
<string name="settings_min_recording_interval_summary">Minsta tidsintervall mellan två inspelningar av din position</string>
<string name="settings_min_required_accuracy">Minsta precision</string>
<string name="settings_min_required_accuracy_summary">Inspelningen kommer att pausas om din position inte är minst så här precis</string>
<string name="settings_metric_units">Använd metersystemet</string>
<string name="settings_metric_units_summary_on">Alla distanser kommer att visas i metriska enheter</string>
<string name="settings_metric_units_summary_off">Alla distanser kommer att visas i brittiska enheter</string>
<string name="settings_map_public">Gör kartor offentliga</string>
<string name="settings_map_public_summary_on">Uppladdade kartor kommer att vara synliga för alla på maps.google.com</string>
<string name="settings_map_public_summary_off">Uppladdad kartor kommer inte att visas offentligt på maps.google.com</string>
<string name="settings_report_speed_or_pace">Visa hastighet</string>
<string name="settings_report_speed_or_pace_summary_on">Hastighet kommer att visas</string>
<string name="settings_report_speed_or_pace_summary_off">Tempo kommer att visas</string>
<string name="settings_share_url_only">Dela bara länk</string>
<string name="settings_share_url_only_summary_on">Bara länken till kartan kommer att skickas vid delning</string>
<string name="settings_share_url_only_summary_off">Innehållet i spåret kommer också att inkluderas vid delning</string>
<string name="settings_signal_sampling_frequency">Signalprovsfrekvens</string>
<string name="settings_signal_sampling_frequency_summary">Tid mellan två inspelningar av telefonens signalstyrka</string>
<string name="settings_split_frequency">Delningsfrekvens</string>
<string name="settings_split_frequency_summary">Maximala tiden eller distansen varefter en ny delnginsmarkör kommer infogas</string>
<string name="pace_label">Tempo</string>
<!-- MyTracksSky -->
<string name="mytracks_sky">GPS-satteliter</string>
<!-- My Maps -->
<string name="select_map_message">Välje en karta från ditt konto:</string>
<string name="create_new_map">Skapa en ny karta...</string>
<string name="map_list_title">Skicka till Google My Maps</string>
<string name="maps_list_loading">Laddar kartor...</string>
<string name="maps_list_failed">Din kartor kunde inte laddas just nu!</string>
<string name="open_map">Välj den här kartan</string>
<string name="edit_map_details">Ändra kartdetaljer</string>
<string name="share_map">Dela kartan med vänner</string>
<string name="share_track">Dela spår med vänner</string>
<string name="delete_map">Ta bort kartan från ditt konto</string>
<string name="map_title">Karttitel:</string>
<string name="map_description">Kartbeskrivning:</string>
<string name="map_searchable_edit">Gör så att kartan och dess innehåll visas i sökresultat</string>
<string name="map_not_searchable_edit">Låt inte kartan och dess innehåll visas i sökresultat, men de kan ändå ses av andra genom en direktlänken</string>
<string name="map_searchable">Kartan och dess innehåll kommer att visas i sökresultat</string>
<string name="map_not_searchable">Varken kartan eller dess innehåll visas i sökresultat, men de kan ändå ses av andra genom en direktlänk</string>
<string name="close">Stäng</string>
<string name="edit">Ändra</string>
<string name="cancel">Avbryt</string>
<string name="save">Spara</string>
<!-- Sharing -->
<string name="share_map_subject">Jag vill dela en karta med dig</string>
<string name="share_map_body_format">Jag tror att du skulle vara intresserad av den här kartan:
%s</string>
<string name="send_track_subject">Jag vill dela ett spår med dig</string>
<string name="send_track_body_format">Jag tror att du skulle vara intresserad av det här spåret.
För att se det här spåret använd Google Earth eller något annat kartprogram.</string>
<!-- Visibility -->
<string name="public_map">Publik</string>
<string name="unlisted_map">Olistat</string>
<string name="mapslist_no_maps_available">Du har inge kartor än.</string>
<!-- Statistics View -->
<!-- Average Moving -->
<string name="average_moving_speed_label">Genomsnittlig rörlig hastighet</string>
<string name="average_moving_pace_label">Genomsnittlig rörligt tempo</string>
<!-- Average -->
<string name="average_speed_label">Genomsnittlig hastighet</string>
<string name="average_pace_label">Genomsnittligt tempo</string>
<string name="elevation_chart_name">Höjddiagram</string>
<string name="elevation_gain_label">Höjdvinst</string>
<string name="elevation_label">Höjt</string>
<string name="latitude_label">Latitud</string>
<string name="longitude_label">Longitud</string>
<!-- Min -->
<string name="min_elevation_label">Min höjd</string>
<string name="min_grade_label">Min lutning</string>
<string name="min_pace_label">Min tempo</string>
<!-- Max -->
<string name="max_elevation_label">Maxhöjd</string>
<string name="max_grade_label">Maxlutning</string>
<string name="max_speed_label">Maxhastighet</string>
<string name="loading_track">Laddar spår...</string>
<!-- Chart Settings -->
<string name="chart_settings">Diagraminställningar</string>
<!-- X Axis -->
<string name="x_axis">X Axel</string>
<string name="by_distance">Efter distans</string>
<string name="by_time">Efter tid</string>
<!-- Y Axis -->
<string name="y_axis">Y Axel</string>
<!-- Units -->
<!-- Time -->
<string name="hour">timme</string>
<string name="hours">timmar</string>
<string name="hr">tim</string>
<string name="min">min</string>
<string name="minute">minut</string>
<string name="minutes">minuter</string>
<string name="second">sekund</string>
<string name="seconds">sekunder</string>
<!-- Distance -->
<string name="meter">m</string>
<string name="kilometer">km</string>
<string name="kilometers_long">kilometer</string>
<string name="feet">ft</string>
<string name="mile">mi</string>
<string name="miles_long">miles</string>
<!-- Speed and Pace -->
<string name="kilometer_per_hour">km/h</string>
<string name="kilometer_per_hour_long">kilometer per timme</string>
<string name="min_per_kilometer">min/km</string>
<string name="per_kilometer">per kilometer</string>
<string name="mile_per_hour">mi/h</string>
<string name="mile_per_hour_long">miles per timme</string>
<string name="min_per_mile">min/mi</string>
<string name="per_mile">per mile</string>
<!-- Stats Labels -->
<string name="moving_time_label">Rörelsetid</string>
<string name="total_time_label">Total tid</string>
<string name="time_label">Tid</string>
<string name="sd_unavail">SD otillgängligt</string>
<string name="speed">Hastighet</string>
<string name="start_trip">Du måste starta en tur.</string>
<string name="statistics">Statistik</string>
<string name="total_distance_label">Total distans</string>
<string name="distance_label">Distans</string>
<string name="unknown">-</string>
<string name="waiting">Väntar...</string>
<!-- End User License Agreement -->
<string name="eula_title">Licensavtal för slutanvändare</string>
<string name="accept">Acceptera</string>
<string name="decline">Avböj</string>
<!-- About -->
<string name="about">Om</string>
<string name="help">Hjälp</string>
<string name="about_team">Team:</string>
<string name="about_version">Version:</string>
<string name="about_email">Support</string>
<string name="about_support">Support:</string>
<!-- Send to Google -->
<string name="sendtogoogle_title">Skicka till...</string>
<string name="sendtogoogle_google_mymaps">Google My Maps</string>
<string name="sendtogoogle_google_docs">Google Docs</string>
<string name="sendtogoogle_send_now">Skicka nu</string>
<string name="sendtogoogle_create_new_map">Skapa en ny karta</string>
<string name="sendtogoogle_pick_existing_map">Välj en befintlig karta</string>
<string name="sendtogoogle_send_stats">Skicka spårstatistik</string>
<string name="sendtogoogle_send_stats_and_points">Skicka statistik och punkter</string>
<!-- Getting the account to upload to. -->
<string name="no_account_found_title">Inget konto hittades</string>
<string name="no_account_found">Inget konto hittades att ladda upp spåret till.</string>
<string name="choose_account_title">Välj konto</string>
<!-- SD card -->
<string name="io_no_external_storage_found">Ingen extern lagring hittades. Se till att ett SD-kort sitter i och att telefonen inte är monterad till en dator.</string>
<string name="io_write_failed">Kan inte skriva till filen.</string>
<string name="io_create_dir_failed">Kunde inte skapa katalog på SD-kort.</string>
<string name="io_write_finished">Slutförde skrivningen av spåret till SD-kort.</string>
<!-- VersionChecker -->
<string name="version_check_title">Uppgraderingskoll</string>
<string name="version_check_upgrade_button">Uppgradera nu</string>
<string name="version_check_continue_button">Fortsätt utan att uppgradera</string>
<string name="upgrade_required">Din version av %1$s kanske inte fungerar korrekt längre, och stöds inte längre. Uppgradera för att fortsätta använda %1$s.</string>
<string name="upgrade_recommended">Din version av %1$s kanske inte fungerar korrekt längre. Du kan uppgradera den nu, eller fortsätta att använda den på egen risk. Vissa funktioner såsom synkronisering kanske inte fungerar förrän du uppgraderar.</string>
<string name="upgrade_available">En ny version av %1$s finns tillgänglig. Du kan fortsätta använda din nuvarande version utan problem, men du kommer inte få de senaste funktionerna förrän du uppgraderar.</string>
<!-- Welcome -->
<string name="welcome">Välkommen</string>
<string name="welcome_read_later">Ok</string>
<string name="welcome_about">Om My Tracks</string>
<!-- Announcement -->
<string name="announce_no_distance">My Tracks ingen distans</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">My Tracks %1$s %2$.2f %3$s på %4$s i %5$s %6$s</string>
<!-- Check Units -->
<string name="check_units_title">Mätenheter</string>
<string name="check_units_message">Som standard är enheterna metriska. Vill du ändra den inställningen?</string>
<!-- Signal Strength -->
<string name="error_rate"> Felfrekvens: %1$d</string>
<string name="signal_to_noise_ratio"> Signal / brus-förhållande: %1$d</string>
<string name="ecio"> Ec/lo: %1$.1f dB</string>
<string name="gsm_strength">GSM styrka: %1$d</string>
<string name="cdma_strength">CDMA styrka: %1$d dBm</string>
<string name="evdo_strength">EVDO styrka: %1$d dBm</string>
</resources>
+1
View File
@@ -370,5 +370,6 @@ limitations under the License.
<item>GPX</item>
<item>KML</item>
<item>CSV</item>
<item>TCX</item>
</array>
</resources>
+42
View File
@@ -0,0 +1,42 @@
<?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>
<!-- These are constants used internally for preferences - DO NOT TRANSLATE -->
<string name="announcement_frequency_key">announcementFrequency</string>
<string name="bluetooth_device_key">bluetoothDevice</string>
<string name="bluetooth_pairing_key">bluetoothPairing</string>
<string name="bluetooth_sensor_key">bluetoothSensor</string>
<string name="default_map_public_key">defaultMapPublic</string>
<string name="max_recording_distance_key">maxRecordingDistance</string>
<string name="metric_units_key">metricUnits</string>
<string name="min_recording_distance_key">minRecordingDistance</string>
<string name="min_recording_interval_key">minRecordingInterval</string>
<string name="min_required_accuracy_key">minRequiredAccuracy</string>
<string name="modular_stats_display_key">modularStatsDisplay</string>
<string name="pick_existing_map_key">pickExistingMap</string>
<string name="recording_track_key">recordingTrack</string>
<string name="report_speed_key">reportSpeed</string>
<string name="selected_track_key">selectedTrack</string>
<string name="send_stats_and_points_key">sendStatsAndPoints</string>
<string name="send_to_docs_key">sendToDocs</string>
<string name="send_to_my_maps_key">sendToMyMaps</string>
<string name="sensor_id_key">sensorId</string>
<string name="sensor_type_key">sensorType</string>
<string name="share_url_only_key">shareUrlOnly</string>
<string name="signal_sampling_frequency_key">signalSamplingFrequency</string>
<string name="split_frequency_key">splitFrequency</string>
</resources>
+53 -1
View File
@@ -122,6 +122,7 @@ limitations under the License.
<string name="tracklist_save_as_gpx">Save a GPX file</string>
<string name="tracklist_save_as_kml">Save a KML 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_btn_send_all_to_mymaps">Send to Google My Maps</string>
<string name="tracklist_btn_delete_all">Delete all tracks</string>
<!-- Export All -->
@@ -135,6 +136,7 @@ limitations under the License.
<string name="tracklist_share_gpx_file">A GPX 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_tcx_file">A TCX file</string>
<string name="tracklist_clear_map">Clear map</string>
<!-- Waypoints list -->
@@ -204,6 +206,21 @@ limitations under the License.
<string name="settings_split_frequency_summary">Maximum time or distance after which a new split marker will be inserted</string>
<string name="pace_label">Pace</string>
<string name="eclair_required">Only supported in Android 2.0 or above</string>
<string name="settings_sensor_type">Sensor Type</string>
<string name="settings_sensor_type_summary">The type of sensor to connect to.</string>
<string name="settings_sensor_id">Sensor Id</string>
<string name="settings_sensor_id_summary">The Id sent to sensors.</string>
<string name="sensor_id_malformed">The Id must be an integer value.</string>
<string name="bluetooth_sensor_title">Bluetooth sensor</string>
<string name="bluetooth_sensor_summary">The bluetooth sensor to connect to.</string>
<string name="settings_modular_stats_display_title">Modular Stats Display</string>
<string name="settings_modular_stats_display_summary_on">The stats screen is split in various modes.</string>
<string name="settings_modular_stats_display_summary_off">Display all stats on one screen</string>
<!-- MyTracksSky -->
<string name="mytracks_sky">GPS Satellites</string>
@@ -291,6 +308,7 @@ limitations under the License.
<string name="minutes">minutes</string>
<string name="second">second</string>
<string name="seconds">seconds</string>
<string name="milliseconds">ms</string>
<!-- Distance -->
<string name="meter">m</string>
@@ -310,6 +328,12 @@ limitations under the License.
<string name="min_per_mile">min/mi</string>
<string name="per_mile">per mile</string>
<!-- Power -->
<string name="watts">W</string>
<string name="revolutions_per_minute">rpm</string>
<string name="bpm">bpm</string>
<!-- Stats Labels -->
<string name="moving_time_label">Moving Time</string>
<string name="total_time_label">Total Time</string>
@@ -320,6 +344,10 @@ limitations under the License.
<string name="statistics">Statistics</string>
<string name="total_distance_label">Total Distance</string>
<string name="distance_label">Distance</string>
<string name="power">Power</string>
<string name="cadence">Cadence</string>
<string name="heart_rate">Heart Rate</string>
<string name="max_heart_rate">Max Heart Rate</string>
<string name="unknown">-</string>
<string name="waiting">Waiting...</string>
@@ -337,7 +365,6 @@ limitations under the License.
<string name="about_support">Support:</string>
<!-- DO NOT TRANSLATE -->
<string name="version">1.0.12</string>
<string name="about_googlegroups">mytracks@googlegroups.com</string>
<string name="about_weburl">mytracks.appspot.com</string>
<string name="about_copyright_message">Copyright 2009 Google Inc.</string>
@@ -403,4 +430,29 @@ limitations under the License.
<string name="gsm_strength">GSM Strength: %1$d</string>
<string name="cdma_strength">CDMA Strength: %1$d dBm</string>
<string name="evdo_strength">EVDO Strength: %1$d dBm</string>
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
<string name="method_bluetooth">Bluetooth</string>
<string name="bluetooth_options">Bluetooth options</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="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
<string name="sensor_options">Sensor Options</string>
<!-- Sensor Types => DO NOT TRANSLATE -->
<string name="none">NONE</string>
<string name="ant_sensor_type">ANT</string>
<string name="srm_sensor_type">SRM</string>
<string name="athlosoft_sensor_type">ATHLOSOFT</string>
<!-- Bluetooth Sensor -->
<string name="bluetooth_connected">Connected to %s</string>
<string name="bluetooth_connecting">Bluetooth sensor connecting ...</string>
<string name="bluetooth_not_connected">Bluetooth sensor not connected</string>
<!-- Sensor State -->
<string name="sensor_data_time">Sensor Data Time</string>
<string name="power_meter_enabled">Power meter enabled</string>
<string name="heart_rate_monitor_enabled">Heart rate monitor enabled</string>
</resources>
+17 -17
View File
@@ -18,26 +18,26 @@ limitations under the License.
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Display settings -->
<PreferenceCategory android:title="@string/settings_display">
<PreferenceScreen android:title="@string/settings_display">
<CheckBoxPreference
android:key="metricUnits"
android:key="@string/metric_units_key"
android:title="@string/settings_metric_units"
android:summaryOn="@string/settings_metric_units_summary_on"
android:summaryOff="@string/settings_metric_units_summary_off"
android:defaultValue="true" />
<CheckBoxPreference
android:key="reportSpeed"
android:key="@string/report_speed_key"
android:title="@string/settings_report_speed_or_pace"
android:summaryOn="@string/settings_report_speed_or_pace_summary_on"
android:summaryOff="@string/settings_report_speed_or_pace_summary_off"
android:defaultValue="true" />
</PreferenceCategory>
</PreferenceScreen>
<!-- Recording settings -->
<PreferenceCategory android:title="@string/settings_recording">
<PreferenceScreen android:title="@string/settings_recording">
<com.google.android.apps.mytracks.IntegerListPreference
android:key="announcementFrequency"
android:key="@string/announcement_frequency_key"
android:title="@string/settings_announcement_frequency"
android:summary="@string/settings_announcement_frequency_summary"
android:entries="@array/task_frequency_options"
@@ -45,7 +45,7 @@ limitations under the License.
android:defaultValue="-1" />
<com.google.android.apps.mytracks.IntegerListPreference
android:key="splitFrequency"
android:key="@string/split_frequency_key"
android:title="@string/settings_split_frequency"
android:summary="@string/settings_split_frequency_summary"
android:entries="@array/split_frequency_options"
@@ -53,7 +53,7 @@ limitations under the License.
android:defaultValue="0" />
<com.google.android.apps.mytracks.IntegerListPreference
android:key="minRecordingInterval"
android:key="@string/min_recording_interval_key"
android:title="@string/settings_min_recording_interval"
android:summary="@string/settings_min_recording_interval_summary"
android:entries="@array/min_recording_interval_options"
@@ -61,7 +61,7 @@ limitations under the License.
android:defaultValue="0" />
<com.google.android.apps.mytracks.IntegerListPreference
android:key="minRecordingDistance"
android:key="@string/min_recording_distance_key"
android:title="@string/settings_min_recording_distance"
android:summary="@string/settings_min_recording_distance_summary"
android:entries="@array/min_recording_distance_options"
@@ -69,7 +69,7 @@ limitations under the License.
android:defaultValue="5" />
<com.google.android.apps.mytracks.IntegerListPreference
android:key="maxRecordingDistance"
android:key="@string/max_recording_distance_key"
android:title="@string/settings_max_recording_distance"
android:summary="@string/settings_max_recording_distance_summary"
android:entries="@array/max_recording_distance_options"
@@ -77,7 +77,7 @@ limitations under the License.
android:defaultValue="200" />
<com.google.android.apps.mytracks.IntegerListPreference
android:key="minRequiredAccuracy"
android:key="@string/min_required_accuracy_key"
android:title="@string/settings_min_required_accuracy"
android:summary="@string/settings_min_required_accuracy_summary"
android:entries="@array/min_required_accuracy_options"
@@ -85,28 +85,28 @@ limitations under the License.
android:defaultValue="200" />
<com.google.android.apps.mytracks.IntegerListPreference
android:key="signalSamplingFrequency"
android:key="@string/signal_sampling_frequency_key"
android:title="@string/settings_signal_sampling_frequency"
android:summary="@string/settings_signal_sampling_frequency_summary"
android:entries="@array/task_frequency_options"
android:entryValues="@array/task_frequency_values"
android:defaultValue="-1" />
</PreferenceCategory>
</PreferenceScreen>
<!-- Sharing settings -->
<PreferenceCategory android:title="@string/settings_sharing">
<PreferenceScreen android:title="@string/settings_sharing">
<CheckBoxPreference
android:key="defaultMapPublic"
android:key="@string/default_map_public_key"
android:title="@string/settings_map_public"
android:summaryOn="@string/settings_map_public_summary_on"
android:summaryOff="@string/settings_map_public_summary_off"
android:defaultValue="true" />
<CheckBoxPreference
android:key="shareUrlOnly"
android:key="@string/share_url_only_key"
android:title="@string/settings_share_url_only"
android:summaryOn="@string/settings_share_url_only_summary_on"
android:summaryOff="@string/settings_share_url_only_summary_off"
android:defaultValue="false" />
</PreferenceCategory>
</PreferenceScreen>
</PreferenceScreen>
@@ -114,7 +114,7 @@ public class MyMapsGDataWrapper {
} catch (HttpException e) {
Log.e(MyTracksConstants.TAG, "HttpException", e);
errorMessage = e.getMessage();
if (errorMessage.contains("401")) {
if (errorMessage != null && errorMessage.contains("401")) {
errorType = ERROR_AUTH;
} else {
errorType = ERROR_CONNECTION;
@@ -122,7 +122,7 @@ public class MyMapsGDataWrapper {
} catch (IOException e) {
Log.e(MyTracksConstants.TAG, "Exception", e);
errorMessage = e.getMessage();
if (errorMessage.contains("503")) {
if (errorMessage != null && errorMessage.contains("503")) {
errorType = ERROR_INTERNAL;
} else {
errorType = ERROR_CONNECTION;
@@ -29,6 +29,9 @@ import android.app.Dialog;
import android.app.TabActivity;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
@@ -80,7 +83,17 @@ public class VersionChecker {
final boolean newVersion; // Returned new version available
final boolean newVersionRecommended; // Returned new version recommended
final boolean newVersionRequired; // Returned new version required
String currentVersion = parentActivity.getString(R.string.version);
String currentVersion = "";
try {
PackageInfo pi =
parentActivity.getPackageManager().getPackageInfo(
"com.google.android.maps.mytracks",
PackageManager.GET_META_DATA);
currentVersion = pi.versionName;
} catch (NameNotFoundException e) {
Log.w(MyTracksConstants.TAG, "Failed to get version info.", e);
return;
}
GDataParser parser = client.getParserForFeed(
Entry.class,
@@ -1,12 +1,12 @@
/*
* Copyright 2009 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
@@ -22,7 +22,7 @@ import com.google.android.apps.mytracks.content.TrackPointsColumns;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.apps.mytracks.stats.DoubleBuffer;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
@@ -49,7 +49,7 @@ import java.util.ArrayList;
/**
* An activity that displays a chart from the track point provider.
*
*
* @author Sandor Dornbush
*/
public class ChartActivity extends Activity implements
@@ -204,23 +204,27 @@ public class ChartActivity extends Activity implements
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key != null) {
if (key.equals(MyTracksSettings.SELECTED_TRACK)) {
if (key.equals(getString(R.string.selected_track_key))) {
selectedTrackId =
sharedPreferences.getLong(MyTracksSettings.SELECTED_TRACK, -1);
sharedPreferences.getLong(getString(R.string.selected_track_key),
-1);
readProfileAsync();
} else if (key.equals(MyTracksSettings.METRIC_UNITS)) {
} else if (key.equals(getString(R.string.metric_units_key))) {
metricUnits =
sharedPreferences.getBoolean(MyTracksSettings.METRIC_UNITS, true);
sharedPreferences.getBoolean(getString(R.string.metric_units_key),
true);
cv.setMetricUnits(metricUnits);
readProfileAsync();
} else if (key.equals(MyTracksSettings.REPORT_SPEED)) {
} else if (key.equals(getString(R.string.report_speed_key))) {
reportSpeed =
sharedPreferences.getBoolean(MyTracksSettings.REPORT_SPEED, true);
sharedPreferences.getBoolean(getString(R.string.report_speed_key),
true);
cv.setReportSpeed(reportSpeed, this);
readProfileAsync();
} else if (key.equals(MyTracksSettings.RECORDING_TRACK)) {
} else if (key.equals(getString(R.string.recording_track_key))) {
recordingTrackId =
sharedPreferences.getLong(MyTracksSettings.RECORDING_TRACK, -1);
sharedPreferences.getLong(getString(R.string.recording_track_key),
-1);
runOnUiThread(updateChart);
}
}
@@ -246,12 +250,14 @@ public class ChartActivity extends Activity implements
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (preferences != null) {
selectedTrackId =
preferences.getLong(MyTracksSettings.SELECTED_TRACK, -1);
preferences.getLong(getString(R.string.selected_track_key), -1);
recordingTrackId =
preferences.getLong(MyTracksSettings.RECORDING_TRACK, -1);
metricUnits = preferences.getBoolean(MyTracksSettings.METRIC_UNITS, true);
preferences.getLong(getString(R.string.recording_track_key), -1);
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key),
true);
cv.setMetricUnits(metricUnits);
reportSpeed = preferences.getBoolean(MyTracksSettings.REPORT_SPEED, true);
reportSpeed = preferences.getBoolean(getString(R.string.report_speed_key),
true);
cv.setReportSpeed(reportSpeed, this);
preferences.registerOnSharedPreferenceChangeListener(this);
}
@@ -450,7 +456,7 @@ public class ChartActivity extends Activity implements
* data[0] = the time or distance
* data[1] = the elevation
* data[2] = the speed
*
*
* @param location a location
* @return the data point
*/
@@ -488,10 +494,10 @@ public class ChartActivity extends Activity implements
if (Math.abs(location.getSpeed() - 128) > 1) {
speedBuffer.setNext(location.getSpeed());
}
} else if (TripStatistics.isValidSpeed(
} else if (TripStatisticsBuilder.isValidSpeed(
location.getTime(), location.getSpeed(), lastLocation.getTime(),
lastLocation.getSpeed(), speedBuffer)
&& (location.getSpeed() <= track.getMaxSpeed())) {
&& (location.getSpeed() <= track.getStatistics().getMaxSpeed())) {
speedBuffer.setNext(location.getSpeed());
}
result[2] = speedBuffer.getAverage() * 3.6;
@@ -109,7 +109,8 @@ public class ExportAllTracks {
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
long recordingTrackId = -1;
if (prefs != null) {
recordingTrackId = prefs.getLong(MyTracksSettings.RECORDING_TRACK, -1);
recordingTrackId =
prefs.getLong(context.getString(R.string.recording_track_key), -1);
}
if (recordingTrackId != -1) {
acquireWakeLock();
@@ -0,0 +1,93 @@
/*
* 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.
*/
package com.google.android.apps.mytracks;
import com.google.android.maps.mytracks.R;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
/**
* Manage the application menus.
*
* @author Sandor Dornbush
*/
class MenuManager {
private MyTracks activity;
public MenuManager(MyTracks activity) {
this.activity = activity;
}
public boolean onCreateOptionsMenu(Menu menu) {
activity.getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void onPrepareOptionsMenu(Menu menu, boolean hasRecorded,
boolean isRecording, boolean hasSelectedTrack) {
menu.findItem(R.id.menu_list_tracks).setEnabled(hasRecorded);
menu.findItem(R.id.menu_list_markers)
.setEnabled(hasRecorded && hasSelectedTrack);
MenuItem startRecording = menu.findItem(R.id.menu_start_recording);
startRecording.setEnabled(!isRecording);
startRecording.setVisible(!isRecording);
MenuItem stopRecording = menu.findItem(R.id.menu_stop_recording);
stopRecording.setEnabled(isRecording);
stopRecording.setVisible(isRecording);
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_start_recording: {
activity.startRecording();
return true;
}
case R.id.menu_stop_recording: {
activity.stopRecording();
return true;
}
case R.id.menu_list_tracks: {
Intent startIntent = new Intent(activity, MyTracksList.class);
activity.startActivityForResult(startIntent, MyTracksConstants.SHOW_TRACK);
return true;
}
case R.id.menu_list_markers: {
Intent startIntent = new Intent(activity, MyTracksWaypointsList.class);
startIntent.putExtra("trackid", activity.getSelectedTrack());
activity.startActivityForResult(startIntent, MyTracksConstants.SHOW_WAYPOINT);
return true;
}
case R.id.menu_settings: {
Intent startIntent = new Intent(activity, MyTracksSettings.class);
activity.startActivity(startIntent);
return true;
}
case R.id.menu_help: {
Intent startIntent = new Intent(activity, WelcomeActivity.class);
activity.startActivity(startIntent);
return true;
}
case MyTracksConstants.MENU_CLEAR_MAP: {
activity.setSelectedTrack(-1);
return true;
}
}
return false;
}
}
@@ -24,7 +24,7 @@ import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.AuthManager;
import com.google.android.apps.mytracks.io.AuthManagerFactory;
import com.google.android.apps.mytracks.io.GpxImport;
import com.google.android.apps.mytracks.io.GpxImporter;
import com.google.android.apps.mytracks.io.SendToDocs;
import com.google.android.apps.mytracks.io.SendToMyMaps;
import com.google.android.apps.mytracks.io.TrackWriter;
@@ -62,24 +62,25 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager.BadTokenException;
import android.widget.RelativeLayout;
import android.widget.TabHost;
import android.widget.Toast;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Random;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
/**
* The super activity that embeds our sub activities.
*
@@ -133,15 +134,9 @@ public class MyTracks extends TabActivity implements OnTouchListener,
private ChartSettingsDialog chartSettingsDialog;
/*
* Menu items:
* Menu manager.
*/
private MenuItem startRecording;
private MenuItem stopRecording;
private MenuItem listTracks;
private MenuItem listMarkers;
private MenuItem settings;
private MenuItem help;
private MenuManager menuManager;
/*
* Information on upload success to MyMaps/Docs.
@@ -282,6 +277,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
super.onCreate(savedInstanceState);
instance = this;
providerUtils = MyTracksProviderUtils.Factory.get(this);
menuManager = new MenuManager(this);
// The volume we want to control is the Text-To-Speech volume
setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
@@ -320,8 +316,10 @@ public class MyTracks extends TabActivity implements OnTouchListener,
SharedPreferences prefs =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (prefs != null) {
selectedTrackId = prefs.getLong(MyTracksSettings.SELECTED_TRACK, -1);
recordingTrackId = prefs.getLong(MyTracksSettings.RECORDING_TRACK, -1);
selectedTrackId =
prefs.getLong(getString(R.string.selected_track_key), -1);
recordingTrackId =
prefs.getLong(getString(R.string.recording_track_key), -1);
prefs.registerOnSharedPreferenceChangeListener(this);
}
@@ -415,81 +413,21 @@ public class MyTracks extends TabActivity implements OnTouchListener,
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
startRecording = menu.add(0, MyTracksConstants.MENU_START_RECORDING, 0,
R.string.start_recording);
startRecording.setIcon(R.drawable.menu_record);
stopRecording = menu.add(0, MyTracksConstants.MENU_STOP_RECORDING, 0,
R.string.stop_recording);
stopRecording.setIcon(R.drawable.menu_stop);
listTracks = menu.add(0, MyTracksConstants.MENU_LIST_TRACKS, 0,
R.string.list_tracks);
listTracks.setIcon(R.drawable.menu_list_tracks);
listMarkers = menu.add(0, MyTracksConstants.MENU_LIST_MARKERS, 0,
R.string.list_markers);
listMarkers.setIcon(R.drawable.menu_marker);
settings = menu.add(0, MyTracksConstants.MENU_SETTINGS, 10001,
R.string.settings);
settings.setIcon(android.R.drawable.ic_menu_preferences);
help = menu.add(0, MyTracksConstants.MENU_HELP, 10002, R.string.help);
help.setIcon(android.R.drawable.ic_menu_info_details);
return true;
return menuManager.onCreateOptionsMenu(menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean hasRecorded = providerUtils.getLastTrack() != null;
boolean isRecording = isRecording();
listTracks = menu.findItem(MyTracksConstants.MENU_LIST_TRACKS);
listTracks.setEnabled(hasRecorded);
listMarkers = menu.findItem(MyTracksConstants.MENU_LIST_MARKERS);
listMarkers.setEnabled(hasRecorded && selectedTrackId >= 0);
startRecording = menu.findItem(MyTracksConstants.MENU_START_RECORDING);
startRecording.setEnabled(!isRecording);
startRecording.setVisible(!isRecording);
stopRecording = menu.findItem(MyTracksConstants.MENU_STOP_RECORDING);
stopRecording.setEnabled(isRecording);
stopRecording.setVisible(isRecording);
menuManager.onPrepareOptionsMenu(menu, providerUtils.getLastTrack() != null,
isRecording(), selectedTrackId >= 0);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MyTracksConstants.MENU_START_RECORDING: {
startRecording();
return true;
}
case MyTracksConstants.MENU_STOP_RECORDING: {
stopRecording();
return true;
}
case MyTracksConstants.MENU_LIST_TRACKS: {
Intent startIntent = new Intent(this, MyTracksList.class);
startActivityForResult(startIntent, MyTracksConstants.SHOW_TRACK);
return true;
}
case MyTracksConstants.MENU_LIST_MARKERS: {
Intent startIntent = new Intent(this, MyTracksWaypointsList.class);
startIntent.putExtra("trackid", selectedTrackId);
startActivityForResult(startIntent, MyTracksConstants.SHOW_WAYPOINT);
return true;
}
case MyTracksConstants.MENU_SETTINGS: {
Intent startIntent = new Intent(this, MyTracksSettings.class);
startActivity(startIntent);
return true;
}
case MyTracksConstants.MENU_HELP: {
Intent startIntent = new Intent(this, WelcomeActivity.class);
startActivity(startIntent);
return true;
}
case MyTracksConstants.MENU_CLEAR_MAP: {
setSelectedTrack(-1);
return true;
}
}
return super.onOptionsItemSelected(item);
return (menuManager.onOptionsItemSelected(item)
? true
: super.onOptionsItemSelected(item));
}
/*
@@ -786,8 +724,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
case MyTracksConstants.SAVE_KML_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.KML; }
//$FALL-THROUGH$
case MyTracksConstants.SAVE_CSV_FILE: {
case MyTracksConstants.SAVE_CSV_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.CSV; }
//$FALL-THROUGH$
case MyTracksConstants.SAVE_TCX_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; }
if (results != null && resultCode == Activity.RESULT_OK) {
final long trackId = results.getLongExtra("trackid", selectedTrackId);
@@ -796,7 +737,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
}
}
break;
}
case MyTracksConstants.SHARE_LINK: {
Track selectedTrack = providerUtils.getTrack(selectedTrackId);
if (selectedTrack != null) {
@@ -810,15 +750,21 @@ public class MyTracks extends TabActivity implements OnTouchListener,
break;
}
case MyTracksConstants.SHARE_GPX_FILE:
case MyTracksConstants.SHARE_KML_FILE: {
if (results != null && resultCode == RESULT_OK) {
long trackId = results.getLongExtra("trackid", selectedTrackId);
if (exportFormat == null) { exportFormat = TrackFileFormat.GPX; }
//$FALL-THROUGH$
case MyTracksConstants.SHARE_KML_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.KML; }
//$FALL-THROUGH$
case MyTracksConstants.SHARE_CSV_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.CSV; }
//$FALL-THROUGH$
case MyTracksConstants.SHARE_TCX_FILE: {
if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; }
if (results != null && resultCode == Activity.RESULT_OK) {
final long trackId = results.getLongExtra("trackid", selectedTrackId);
if (trackId >= 0) {
TrackFileFormat format =
(requestCode == MyTracksConstants.SHARE_GPX_FILE)
? TrackFileFormat.GPX
: TrackFileFormat.KML;
sendTrack(trackId, format);
sendTrack(trackId, exportFormat);
}
}
break;
@@ -861,9 +807,9 @@ public class MyTracks extends TabActivity implements OnTouchListener,
+ "to shared preferences: ", e);
}
}
if (key != null && key.equals(MyTracksSettings.SELECTED_TRACK)) {
if (key != null && key.equals(getString(R.string.selected_track_key))) {
selectedTrackId =
sharedPreferences.getLong(MyTracksSettings.SELECTED_TRACK, -1);
sharedPreferences.getLong(getString(R.string.selected_track_key), -1);
}
}
@@ -950,13 +896,14 @@ public class MyTracks extends TabActivity implements OnTouchListener,
Thread t = new Thread() {
@Override
public void run() {
boolean success = false;
ArrayList<Track> tracks = new ArrayList<Track>();
int message = R.string.success;
long[] trackIdsImported = null;
try {
try {
GpxImport.importGPXFile(fileName, tracks);
success = true;
InputStream is = new FileInputStream(fileName);
trackIdsImported = GpxImporter.importGPXFile(is, providerUtils);
} catch (SAXException e) {
Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e);
message = R.string.error_generic;
@@ -973,15 +920,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e);
message = R.string.error_out_of_memory;
}
if (success) {
long trackId = -1;
for (Track track : tracks) {
Uri uri = providerUtils.insertTrackAndTrackPoints(track);
trackId = Long.parseLong(uri.getLastPathSegment());
}
setSelectedTrack(trackId);
if (trackIdsImported != null && trackIdsImported.length > 0) {
// select last track from import file
setSelectedTrack(trackIdsImported[trackIdsImported.length - 1]);
} else {
MyTracks.this.showMessageDialog(message, false/*success*/);
MyTracks.this.showMessageDialog(message, false/* success */);
}
} finally {
runOnUiThread(new Runnable() {
@@ -1071,7 +1014,8 @@ public class MyTracks extends TabActivity implements OnTouchListener,
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
boolean shareUrlOnly = true;
if (prefs != null) {
shareUrlOnly = prefs.getBoolean(MyTracksSettings.SHARE_URL_ONLY, false);
shareUrlOnly =
prefs.getBoolean(getString(R.string.share_url_only_key), false);
}
String url = MyMapsConstants.MAPSHOP_BASE_URL + "?msa=0&msid=" + mapId;
@@ -1294,7 +1238,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
* Starts the track recording service (if not already running) and binds to
* it. Starts recording a new track.
*/
private void startRecording() {
public void startRecording() {
if (trackRecordingService == null) {
startNewTrackRequested = true;
Intent startIntent = new Intent(this, TrackRecordingService.class);
@@ -1320,7 +1264,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
* Stops the track recording service and unbinds from it. Will display a toast
* "Stopped recording" and pop up the Track Details activity.
*/
private void stopRecording() {
public void stopRecording() {
if (trackRecordingService != null) {
try {
trackRecordingService.endCurrentTrack();
@@ -1379,18 +1323,22 @@ public class MyTracks extends TabActivity implements OnTouchListener,
*
* @param trackId the id of the track
*/
private void setSelectedTrack(final long trackId) {
public void setSelectedTrack(final long trackId) {
runOnUiThread(new Runnable() {
public void run() {
SharedPreferences prefs =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putLong(MyTracksSettings.SELECTED_TRACK, trackId);
editor.putLong(getString(R.string.selected_track_key), trackId);
editor.commit();
}
});
}
protected long getSelectedTrack() {
return selectedTrackId;
}
/**
* Writes the recording track id to the shared preferences.
* Executed on the UI thread.
@@ -1403,7 +1351,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
SharedPreferences prefs =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putLong(MyTracksSettings.RECORDING_TRACK, trackId);
editor.putLong(getString(R.string.recording_track_key), trackId);
editor.commit();
}
});
@@ -1421,8 +1369,8 @@ public class MyTracks extends TabActivity implements OnTouchListener,
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (prefs != null) {
SharedPreferences.Editor editor = prefs.edit();
editor.putLong(MyTracksSettings.SELECTED_TRACK, theSelectedTrackId);
editor.putLong(MyTracksSettings.RECORDING_TRACK, theRecordingTrackId);
editor.putLong(getString(R.string.selected_track_key), theSelectedTrackId);
editor.putLong(getString(R.string.recording_track_key), theRecordingTrackId);
editor.commit();
}
}
@@ -54,29 +54,25 @@ public abstract class MyTracksConstants {
public static final int SHARE_GPX_FILE = 15;
public static final int SHARE_KML_FILE = 16;
public static final int SHARE_CSV_FILE = 17;
public static final int EDIT_DETAILS = 18;
public static final int SAVE_GPX_FILE = 19;
public static final int SAVE_KML_FILE = 20;
public static final int SAVE_CSV_FILE = 21;
public static final int CLEAR_MAP = 22;
public static final int SHOW_WAYPOINT = 23;
public static final int EDIT_WAYPOINT = 24;
public static final int WELCOME = 25;
public static final int SHARE_TCX_FILE = 18;
public static final int EDIT_DETAILS = 19;
public static final int SAVE_GPX_FILE = 20;
public static final int SAVE_KML_FILE = 21;
public static final int SAVE_CSV_FILE = 22;
public static final int SAVE_TCX_FILE = 23;
public static final int CLEAR_MAP = 24;
public static final int SHOW_WAYPOINT = 25;
public static final int EDIT_WAYPOINT = 26;
public static final int WELCOME = 27;
/*
* Menu ids:
*/
public static final int MENU_START_RECORDING = 1;
public static final int MENU_STOP_RECORDING = 2;
public static final int MENU_LIST_TRACKS = 3;
public static final int MENU_LIST_MARKERS = 4;
public static final int MENU_SETTINGS = 5;
public static final int MENU_MY_LOCATION = 6;
public static final int MENU_TOGGLE_LAYERS = 7;
public static final int MENU_CHART_SETTINGS = 8;
public static final int MENU_HELP = 9;
public static final int MENU_CURRENT_SEGMENT = 10;
public static final int MENU_MY_LOCATION = 1;
public static final int MENU_TOGGLE_LAYERS = 2;
public static final int MENU_CHART_SETTINGS = 3;
public static final int MENU_CURRENT_SEGMENT = 4;
/*
* Context menu ids:
@@ -91,11 +87,13 @@ public abstract class MyTracksConstants {
public static final int MENU_SHARE_GPX_FILE = 201;
public static final int MENU_SHARE_KML_FILE = 202;
public static final int MENU_SHARE_CSV_FILE = 203;
public static final int MENU_WRITE_TO_SD_CARD = 204;
public static final int MENU_SAVE_GPX_FILE = 205;
public static final int MENU_SAVE_KML_FILE = 206;
public static final int MENU_SAVE_CSV_FILE = 207;
public static final int MENU_CLEAR_MAP = 208;
public static final int MENU_SHARE_TCX_FILE = 204;
public static final int MENU_WRITE_TO_SD_CARD = 205;
public static final int MENU_SAVE_GPX_FILE = 206;
public static final int MENU_SAVE_KML_FILE = 207;
public static final int MENU_SAVE_CSV_FILE = 208;
public static final int MENU_SAVE_TCX_FILE = 209;
public static final int MENU_CLEAR_MAP = 210;
/**
* The number of distance readings to smooth to get a stable signal.
@@ -123,6 +121,12 @@ public abstract class MyTracksConstants {
*/
public static final int MAX_DISPLAYED_TRACK_POINTS = 10000;
/**
* Target number of track points displayed by the map overlay.
* We may display more than this number of points.
*/
public static final int TARGET_DISPLAYED_TRACK_POINTS = 5000;
/**
* Maximum number of track points ever loaded at once from the provider into
* memory.
@@ -179,12 +183,16 @@ public abstract class MyTracksConstants {
return MyTracksConstants.SHARE_GPX_FILE;
case MyTracksConstants.MENU_SHARE_CSV_FILE:
return MyTracksConstants.SHARE_CSV_FILE;
case MyTracksConstants.MENU_SHARE_TCX_FILE:
return MyTracksConstants.SHARE_TCX_FILE;
case MyTracksConstants.MENU_SAVE_GPX_FILE:
return MyTracksConstants.SAVE_GPX_FILE;
case MyTracksConstants.MENU_SAVE_KML_FILE:
return MyTracksConstants.SAVE_KML_FILE;
case MyTracksConstants.MENU_SAVE_CSV_FILE:
return MyTracksConstants.SAVE_CSV_FILE;
case MyTracksConstants.MENU_SAVE_TCX_FILE:
return MyTracksConstants.SAVE_TCX_FILE;
case MyTracksConstants.MENU_CLEAR_MAP:
return MyTracksConstants.CLEAR_MAP;
default:
+1 -1
View File
@@ -62,7 +62,7 @@ public class MyTracksDeleteAllTracks extends Handler {
SharedPreferences prefs =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putLong(MyTracksSettings.SELECTED_TRACK, -1);
editor.putLong(context.getString(R.string.selected_track_key), -1);
editor.commit();
if (done != null) {
Handler h = new Handler();
@@ -90,6 +90,8 @@ public class MyTracksList extends ListActivity
R.string.tracklist_share_kml_file);
share.add(0, MyTracksConstants.MENU_SHARE_CSV_FILE, 0,
R.string.tracklist_share_csv_file);
share.add(0, MyTracksConstants.MENU_SHARE_TCX_FILE, 0,
R.string.tracklist_share_tcx_file);
SubMenu save = menu.addSubMenu(0,
MyTracksConstants.MENU_WRITE_TO_SD_CARD, 0,
R.string.tracklist_write_to_sd);
@@ -99,6 +101,8 @@ public class MyTracksList extends ListActivity
R.string.tracklist_save_as_kml);
save.add(0, MyTracksConstants.MENU_SAVE_CSV_FILE, 0,
R.string.tracklist_save_as_csv);
save.add(0, MyTracksConstants.MENU_SAVE_TCX_FILE, 0,
R.string.tracklist_save_as_tcx);
menu.add(0, MyTracksConstants.MENU_DELETE, 0,
R.string.tracklist_delete_track);
}
@@ -111,14 +115,16 @@ public class MyTracksList extends ListActivity
if (key == null) {
return;
}
if (key.equals(MyTracksSettings.METRIC_UNITS)) {
metricUnits = sharedPreferences.getBoolean(MyTracksSettings.METRIC_UNITS, true);
if (key.equals(getString(R.string.metric_units_key))) {
metricUnits = sharedPreferences.getBoolean(
getString(R.string.metric_units_key), true);
if (tracksCursor != null && !tracksCursor.isClosed()) {
tracksCursor.requery();
}
}
if (key.equals(MyTracksSettings.RECORDING_TRACK)) {
recordingTrackId = sharedPreferences.getLong(MyTracksSettings.RECORDING_TRACK, -1);
if (key.equals(getString(R.string.recording_track_key))) {
recordingTrackId = sharedPreferences.getLong(
getString(R.string.recording_track_key), -1);
}
}
@@ -193,9 +199,10 @@ public class MyTracksList extends ListActivity
SharedPreferences preferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
preferences.registerOnSharedPreferenceChangeListener(this);
metricUnits = preferences.getBoolean(MyTracksSettings.METRIC_UNITS, true);
metricUnits =
preferences.getBoolean(getString(R.string.metric_units_key), true);
recordingTrackId =
preferences.getLong(MyTracksSettings.RECORDING_TRACK, -1);
preferences.getLong(getString(R.string.recording_track_key), -1);
tracksCursor = getContentResolver().query(
TracksColumns.CONTENT_URI, null, null, null, "_id DESC");
+89 -45
View File
@@ -21,6 +21,7 @@ import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TrackPointsColumns;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
@@ -135,6 +136,11 @@ public class MyTracksMap extends MapActivity
private Handler updateTrackHandler;
private MyTracksProviderUtils providerUtils;
/**
* This value is used to decide how many points to display.
*/
private int samplingFrequency = 1;
/**
* A runnable that updates the track from the provider (looking for points
@@ -146,35 +152,7 @@ public class MyTracksMap extends MapActivity
if (selectedTrack == null) {
return;
}
Cursor cursor = null;
try {
cursor = providerUtils.getLocationsCursor(
recordingTrackId,
lastSeenLocationId + 1,
MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS
- selectedTrack.getLocations().size(),
true);
if (cursor != null) {
if (cursor.moveToLast()) {
final int idColumnIdx =
cursor.getColumnIndexOrThrow(TrackPointsColumns._ID);
do {
lastSeenLocationId = cursor.getLong(idColumnIdx);
Location location = providerUtils.createLocation(cursor);
if (location != null) {
selectedTrack.addLocation(location);
}
} while (cursor.moveToPrevious());
}
}
} catch (RuntimeException e) {
Log.w(MyTracksConstants.TAG, "Caught an unexpected exception: ", e);
} finally {
if (cursor != null) {
cursor.close();
}
mapView.postInvalidate();
}
readAllNewTrackPoints();
}
};
@@ -187,9 +165,9 @@ public class MyTracksMap extends MapActivity
if (selectedTrack == null) {
return;
}
lastSeenLocationId = providerUtils.getTrackPoints(selectedTrack,
MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS);
mapView.postInvalidate();
mapOverlay.clearPoints();
lastSeenLocationId = selectedTrack.getStartId();
readAllNewTrackPoints();
}
};
@@ -379,12 +357,12 @@ public class MyTracksMap extends MapActivity
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (preferences != null) {
minRequiredAccuracy = preferences.getInt(
MyTracksSettings.MIN_REQUIRED_ACCURACY,
getString(R.string.min_required_accuracy_key),
MyTracksSettings.DEFAULT_MIN_REQUIRED_ACCURACY);
recordingTrackId =
preferences.getLong(MyTracksSettings.RECORDING_TRACK, -1);
preferences.getLong(getString(R.string.recording_track_key), -1);
long selectedTrackId =
preferences.getLong(MyTracksSettings.SELECTED_TRACK, -1);
preferences.getLong(getString(R.string.selected_track_key), -1);
if (selectedTrackId >= 0) {
setSelectedTrack(selectedTrackId);
}
@@ -657,14 +635,15 @@ public class MyTracksMap extends MapActivity
if (track == null || mapView == null || track.getNumberOfPoints() < 2) {
return;
}
int latSpanE6 = track.getTop() - track.getBottom();
int lonSpanE6 = track.getRight() - track.getLeft();
TripStatistics stats = track.getStatistics();
int latSpanE6 = stats.getTop() - stats.getBottom();
int lonSpanE6 = stats.getRight() - stats.getLeft();
if (latSpanE6 > 0 && latSpanE6 < 180E6 && lonSpanE6 > 0
&& lonSpanE6 < 180E6) {
keepMyLocationVisible = false;
GeoPoint center = new GeoPoint(
track.getBottom() + latSpanE6 / 2,
track.getLeft() + lonSpanE6 / 2);
stats.getBottom() + latSpanE6 / 2,
stats.getLeft() + lonSpanE6 / 2);
if (MyTracksUtils.isValidGeoPoint(center)) {
mapView.getController().setCenter(center);
mapView.getController().zoomToSpan(latSpanE6, lonSpanE6);
@@ -781,6 +760,8 @@ public class MyTracksMap extends MapActivity
R.string.tracklist_share_kml_file);
share.add(0, MyTracksConstants.MENU_SHARE_CSV_FILE, 0,
R.string.tracklist_share_csv_file);
share.add(0, MyTracksConstants.MENU_SHARE_TCX_FILE, 0,
R.string.tracklist_share_tcx_file);
SubMenu save = menu.addSubMenu(0,
MyTracksConstants.MENU_WRITE_TO_SD_CARD, 0,
R.string.tracklist_write_to_sd);
@@ -790,6 +771,8 @@ public class MyTracksMap extends MapActivity
R.string.tracklist_save_as_kml);
save.add(0, MyTracksConstants.MENU_SAVE_CSV_FILE, 0,
R.string.tracklist_save_as_csv);
save.add(0, MyTracksConstants.MENU_SAVE_TCX_FILE, 0,
R.string.tracklist_save_as_tcx);
menu.add(0, MyTracksConstants.MENU_CLEAR_MAP, 0,
R.string.tracklist_clear_map);
menu.add(0, MyTracksConstants.MENU_DELETE, 0,
@@ -886,17 +869,19 @@ public class MyTracksMap extends MapActivity
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key != null) {
if (key.equals(MyTracksSettings.MIN_REQUIRED_ACCURACY)) {
if (key.equals(getString(R.string.min_required_accuracy_key))) {
minRequiredAccuracy = sharedPreferences.getInt(
MyTracksSettings.MIN_REQUIRED_ACCURACY,
getString(R.string.min_required_accuracy_key),
MyTracksSettings.DEFAULT_MIN_REQUIRED_ACCURACY);
} else if (key.equals(MyTracksSettings.SELECTED_TRACK)) {
} else if (key.equals(getString(R.string.selected_track_key))) {
long selectedTrackId =
sharedPreferences.getLong(MyTracksSettings.SELECTED_TRACK, -1);
sharedPreferences.getLong(getString(R.string.selected_track_key),
-1);
setSelectedTrack(selectedTrackId);
} else if (key.equals(MyTracksSettings.RECORDING_TRACK)) {
} else if (key.equals(getString(R.string.recording_track_key))) {
recordingTrackId =
sharedPreferences.getLong(MyTracksSettings.RECORDING_TRACK, -1);
sharedPreferences.getLong(getString(R.string.recording_track_key),
-1);
if (selectedTrack != null) {
mapOverlay.setShowEndMarker(
selectedTrack.getId() != recordingTrackId);
@@ -975,4 +960,63 @@ public class MyTracksMap extends MapActivity
public void onAccuracyChanged(Sensor s, int accuracy) {
// do nothing
}
/**
* Set the sampling frequency from the total number of points in the track.
*
* @param track The track to read the total number of points from.
*/
private void setSamplingFrequency(Track track) {
long totalLocations = track.getStopId() - track.getStartId();
// Limit the number of map points readings.
samplingFrequency =
(int) (1 +
totalLocations / MyTracksConstants.TARGET_DISPLAYED_TRACK_POINTS);
Log.i(MyTracksConstants.TAG, "Sampling locations: " + samplingFrequency);
}
private void readAllNewTrackPoints() {
Cursor cursor = null;
// Refetch the track to get the latest StopId
selectedTrack = providerUtils.getTrack(selectedTrack.getId());
long totalLocations = selectedTrack.getStopId() -
selectedTrack.getStartId();
setSamplingFrequency(selectedTrack);
int bufferSize = 1024;
int points = 0;
while (lastSeenLocationId < selectedTrack.getStopId()) {
cursor = providerUtils.getLocationsCursor(
selectedTrack.getId(), lastSeenLocationId, bufferSize, false);
if (cursor != null && cursor.moveToFirst()) {
final int idColumnIdx = cursor.getColumnIndexOrThrow(
TrackPointsColumns._ID);
while (cursor.moveToNext()) {
points++;
Location location = providerUtils.createLocation(cursor);
lastSeenLocationId = cursor.getLong(idColumnIdx);
// Include a point if it fits one of the following criteria:
// - Has the mod for the sampling frequency.
// - Is the first point.
// - Is the last point and we are not recording this track.
if (!MyTracksUtils.isValidLocation(location) ||
points % samplingFrequency == 0 ||
points == 0 ||
(recordingTrackId != selectedTrack.getId() &&
points == (totalLocations - 1))) {
mapOverlay.addLocation(location);
}
}
} else {
lastSeenLocationId += bufferSize;
}
cursor.close();
cursor = null;
}
if (cursor != null) {
cursor.close();
}
mapView.postInvalidate();
}
}
+26 -32
View File
@@ -1,12 +1,12 @@
/*
* 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
@@ -55,6 +55,7 @@ public class MyTracksOverlay extends Overlay {
private final Paint errorCirclePaint;
private final Context context;
private final ArrayList<Waypoint> waypoints = new ArrayList<Waypoint>();
private final ArrayList<Location> points = new ArrayList<Location>(1024);
private Track selectedTrack;
private int lastHeading = 0;
@@ -128,6 +129,17 @@ public class MyTracksOverlay extends Overlay {
return selectedTrack;
}
/**
* Add a location to the map overlay.
*
* NOTE: this method takes ownership of this location and may change it.
*
* @param l the location to add
*/
public void addLocation(Location l) {
points.add(l);
}
public void addWaypoint(Waypoint wpt) {
waypoints.add(wpt);
}
@@ -136,6 +148,10 @@ public class MyTracksOverlay extends Overlay {
waypoints.clear();
}
public void clearPoints() {
points.clear();
}
public void setShowEndMarker(boolean showEndMarker) {
this.showEndMarker = showEndMarker;
}
@@ -153,7 +169,11 @@ public class MyTracksOverlay extends Overlay {
// Draw the waypoints:
ArrayList<Waypoint> currentWaypoints = waypoints;
for (int i = 1; i < currentWaypoints.size(); i++) {
Location loc = currentWaypoints.get(i).getLocation();
Waypoint wpt = currentWaypoints.get(i);
if (wpt == null) {
continue;
}
Location loc = wpt.getLocation();
if (loc == null) {
continue;
}
@@ -162,7 +182,7 @@ public class MyTracksOverlay extends Overlay {
mapView.getProjection().toPixels(geoPoint, pt);
canvas.save();
canvas.translate(pt.x - (markerWidth / 2) + 3, pt.y - (markerHeight));
if (currentWaypoints.get(i).getType() == Waypoint.TYPE_STATISTICS) {
if (wpt.getType() == Waypoint.TYPE_STATISTICS) {
statsMarker.draw(canvas);
} else {
waypointMarker.draw(canvas);
@@ -196,7 +216,6 @@ public class MyTracksOverlay extends Overlay {
if (track == null) {
return;
}
ArrayList<Location> points = track.getLocations();
if (points.size() < 2) {
return;
}
@@ -206,7 +225,7 @@ public class MyTracksOverlay extends Overlay {
int h = mapView.getLatitudeSpan();
int cx = mapView.getMapCenter().getLongitudeE6();
int cy = mapView.getMapCenter().getLatitudeE6();
Rect rect = new Rect(cx - w / 2, cy - h / 2, cx + w / 2, cy + h / 2);
Rect rect = new Rect(cx - w, cy - h, cx + w, cy + h);
Point pt = new Point();
GeoPoint geoPoint;
@@ -222,14 +241,6 @@ public class MyTracksOverlay extends Overlay {
int lastLocLon = (int) (points.get(0).getLongitude() * 1E6);
int lastLocLat = (int) (points.get(0).getLatitude() * 1E6);
// Line decimation for dummies:
// Skip di additional points, where di depends on zoom level:
int di = 0;
int dl = 17 - mapView.getZoomLevel();
if (dl > 0) {
di += (dl * dl);
}
// Loop over track points:
path = new Path();
for (int i = 1; i < points.size(); i++) {
@@ -241,23 +252,6 @@ public class MyTracksOverlay extends Overlay {
locLon = (int) (loc.getLongitude() * 1E6);
locLat = (int) (loc.getLatitude() * 1E6);
// Skip to every n-th point (depends on zoom level, see above):
for (int j = 0; j < di && i < points.size() - 1; j++) {
// TODO Check the thread synchronization.
// There is no reason that points.get(i + 1) should be null but users
// have reported it causing null pointer exceptions.
if ((locLat > 90E6) ||
(lastLocLat > 90E6) ||
(points.get(i + 1) == null) ||
(points.get(i + 1).getLatitude() > 90)) {
break;
}
i++;
loc = points.get(i);
locLon = (int) (loc.getLongitude() * 1E6);
locLat = (int) (loc.getLatitude() * 1E6);
}
// Draw a line segment if it's inside the viewing window:
if (locLat < 90E6 && lastLocLat < 90E6) {
lastValidLocation = loc;
@@ -1,12 +1,12 @@
/*
* 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
@@ -37,26 +37,6 @@ public class MyTracksSettings extends PreferenceActivity {
public static final String SETTINGS_NAME = "MyTracksSettings";
public static final String ANNOUNCEMENT_FREQUENCY = "announcementFrequency";
public static final String DEFAULT_MAP_PUBLIC = "defaultMapPublic";
public static final String MAX_RECORDING_DISTANCE = "maxRecordingDistance";
public static final String METRIC_UNITS = "metricUnits";
public static final String MIN_RECORDING_DISTANCE = "minRecordingDistance";
public static final String MIN_RECORDING_INTERVAL = "minRecordingInterval";
public static final String MIN_REQUIRED_ACCURACY = "minRequiredAccuracy";
public static final String PICK_EXISTING_MAP = "pickExistingMap";
public static final String RECORDING_TRACK = "recordingTrack";
public static final String REPORT_SPEED = "reportSpeed";
public static final String SELECTED_TRACK = "selectedTrack";
public static final String SEND_STATS_AND_POINTS = "sendStatsAndPoints";
public static final String SEND_TO_DOCS = "sendToDocs";
public static final String SEND_TO_MYMAPS = "sendToMyMaps";
public static final String SHARE_URL_ONLY = "shareUrlOnly";
public static final String SIGNAL_SAMPLING_FREQUENCY =
"signalSamplingFrequency";
public static final String SPLIT_FREQUENCY = "splitFrequency";
public static final String WRITE_TO_SD_CARD = "writeToSdCard";
/*
* Default values - keep in sync with those in preferences.xml.
*/
@@ -96,7 +76,7 @@ public class MyTracksSettings extends PreferenceActivity {
// Hook up switching of displayed list entries between metric and imperial
// units
CheckBoxPreference metricUnitsPreference =
(CheckBoxPreference) findPreference(METRIC_UNITS);
(CheckBoxPreference) findPreference(getString(R.string.metric_units_key));
metricUnitsPreference.setOnPreferenceChangeListener(
new OnPreferenceChangeListener() {
@Override
@@ -112,7 +92,8 @@ public class MyTracksSettings extends PreferenceActivity {
// Disable TTS announcement preference if not available
if (!mTTSAvailable) {
IntegerListPreference announcementFrequency =
(IntegerListPreference) findPreference(ANNOUNCEMENT_FREQUENCY);
(IntegerListPreference) findPreference(
getString(R.string.announcement_frequency_key));
announcementFrequency.setEnabled(false);
announcementFrequency.setValue("-1");
announcementFrequency.setSummary(
@@ -128,13 +109,17 @@ public class MyTracksSettings extends PreferenceActivity {
*/
private void updatePreferenceUnits(boolean isMetric) {
final ListPreference minRecordingDistance =
(ListPreference) findPreference(MIN_RECORDING_DISTANCE);
(ListPreference) findPreference(
getString(R.string.min_recording_distance_key));
final ListPreference maxRecordingDistance =
(ListPreference) findPreference(MAX_RECORDING_DISTANCE);
(ListPreference) findPreference(
getString(R.string.max_recording_distance_key));
final ListPreference minRequiredAccuracy =
(ListPreference) findPreference(MIN_REQUIRED_ACCURACY);
(ListPreference) findPreference(
getString(R.string.min_required_accuracy_key));
final ListPreference splitFrequency =
(ListPreference) findPreference(SPLIT_FREQUENCY);
(ListPreference) findPreference(
getString(R.string.split_frequency_key));
minRecordingDistance.setEntries(isMetric
? R.array.min_recording_distance_options
@@ -18,6 +18,7 @@ package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
@@ -65,11 +66,11 @@ public class MyTracksWaypointDetails extends Activity
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (preferences != null) {
boolean useMetric =
preferences.getBoolean(MyTracksSettings.METRIC_UNITS, true);
preferences.getBoolean(getString(R.string.metric_units_key), true);
utils.setMetricUnits(useMetric);
boolean displaySpeed =
preferences.getBoolean(MyTracksSettings.REPORT_SPEED, true);
preferences.getBoolean(getString(R.string.report_speed_key), true);
utils.setReportSpeed(displaySpeed);
utils.updateWaypointUnits();
@@ -132,8 +133,9 @@ public class MyTracksWaypointDetails extends Activity
detailsView.setVisibility(View.GONE);
statsView.setVisibility(View.VISIBLE);
iconId = R.drawable.ylw_pushpin;
utils.setAllStats(waypoint);
utils.setTime(R.id.total_time_register, waypoint.getTotalTime());
TripStatistics waypointStats = waypoint.getStatistics();
utils.setAllStats(waypointStats);
utils.setTime(R.id.total_time_register, waypointStats.getTotalTime());
utils.setAltitude(
R.id.elevation_register, waypoint.getLocation().getAltitude());
break;
@@ -139,9 +139,9 @@ public class MyTracksWaypointsList extends ListActivity
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (preferences != null) {
recordingTrackId =
preferences.getLong(MyTracksSettings.RECORDING_TRACK, -1);
preferences.getLong(getString(R.string.recording_track_key), -1);
selectedTrackId =
preferences.getLong(MyTracksSettings.SELECTED_TRACK, -1);
preferences.getLong(getString(R.string.selected_track_key), -1);
}
boolean selectedRecording = selectedTrackId > 0
&& selectedTrackId == recordingTrackId;
@@ -168,16 +168,20 @@ public class MyTracksWaypointsList extends ListActivity
switch (v.getId()) {
case R.id.waypointslist_btn_insert_waypoint: {
long id = MyTracks.getInstance().insertWaypointMarker();
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
intent.putExtra("waypointid", id);
startActivity(intent);
if (id >= 0) {
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
intent.putExtra("waypointid", id);
startActivity(intent);
}
break;
}
case R.id.waypointslist_btn_insert_statistics: {
long id = MyTracks.getInstance().insertStatisticsMarker();
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
intent.putExtra("waypointid", id);
startActivity(intent);
if (id >= 0) {
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
intent.putExtra("waypointid", id);
startActivity(intent);
}
break;
}
@@ -105,17 +105,25 @@ public class SendToGoogleDialog extends Dialog {
getContext().getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (prefs != null) {
sendToMyMapsCheckBox.setChecked(
prefs.getBoolean(MyTracksSettings.SEND_TO_MYMAPS, true));
prefs.getBoolean(
getContext().getString(R.string.send_to_my_maps_key), true));
sendToDocsCheckBox.setChecked(
prefs.getBoolean(MyTracksSettings.SEND_TO_DOCS, true));
prefs.getBoolean(
getContext().getString(R.string.send_to_docs_key), true));
pickMapRadioButton.setChecked(
prefs.getBoolean(MyTracksSettings.PICK_EXISTING_MAP, false));
prefs.getBoolean(
getContext().getString(R.string.pick_existing_map_key), false));
createNewMapRadioButton.setChecked(
!prefs.getBoolean(MyTracksSettings.PICK_EXISTING_MAP, false));
!prefs.getBoolean(
getContext().getString(R.string.pick_existing_map_key), false));
sendStatsAndPointsRadioButton.setChecked(
prefs.getBoolean(MyTracksSettings.SEND_STATS_AND_POINTS, false));
prefs.getBoolean(
getContext().getString(R.string.send_stats_and_points_key),
false));
sendStatsRadioButton.setChecked(
!prefs.getBoolean(MyTracksSettings.SEND_STATS_AND_POINTS, false));
!prefs.getBoolean(
getContext().getString(R.string.send_stats_and_points_key),
false));
}
}
@@ -127,13 +135,16 @@ public class SendToGoogleDialog extends Dialog {
Editor editor = prefs.edit();
if (editor != null) {
editor.putBoolean(
MyTracksSettings.SEND_TO_MYMAPS, sendToMyMapsCheckBox.isChecked());
getContext().getString(R.string.send_to_my_maps_key),
sendToMyMapsCheckBox.isChecked());
editor.putBoolean(
MyTracksSettings.SEND_TO_DOCS, sendToDocsCheckBox.isChecked());
getContext().getString(R.string.send_to_docs_key),
sendToDocsCheckBox.isChecked());
editor.putBoolean(
MyTracksSettings.PICK_EXISTING_MAP, pickMapRadioButton.isChecked());
getContext().getString(R.string.pick_existing_map_key),
pickMapRadioButton.isChecked());
editor.putBoolean(
MyTracksSettings.SEND_STATS_AND_POINTS,
getContext().getString(R.string.send_stats_and_points_key),
sendStatsAndPointsRadioButton.isChecked());
editor.commit();
}
@@ -1,12 +1,12 @@
/*
* 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
@@ -15,6 +15,9 @@
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtilsImpl;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.maps.mytracks.R;
@@ -24,7 +27,6 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.database.Cursor;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
@@ -48,23 +50,6 @@ import android.widget.Toast;
public class StatsActivity extends Activity
implements OnSharedPreferenceChangeListener, LocationListener {
/**
* Columns we need from the provider
*/
private static final String[] PROJECTION_COLUMNS = {
TracksColumns._ID,
TracksColumns.STARTTIME,
TracksColumns.TOTALTIME,
TracksColumns.MOVINGTIME,
TracksColumns.TOTALDISTANCE,
TracksColumns.AVGSPEED,
TracksColumns.AVGMOVINGSPEED,
TracksColumns.MAXSPEED,
TracksColumns.MINELEVATION,
TracksColumns.MAXELEVATION,
TracksColumns.ELEVATIONGAIN,
TracksColumns.MINGRADE,
TracksColumns.MAXGRADE };
private final StatsUtilities utils;
private UIUpdateThread thread;
@@ -109,6 +94,9 @@ public class StatsActivity extends Activity
*/
private boolean showCurrentSegment = false;
private final MyTracksProviderUtils providerUtils;
private Track track = null;
/**
* A runnable for posting to the UI thread. Will update the total time field.
*/
@@ -147,7 +135,8 @@ public class StatsActivity extends Activity
}
public StatsActivity() {
this.utils = new StatsUtilities(this);
utils = new StatsUtilities(this);
providerUtils = new MyTracksProviderUtilsImpl(this);
}
/** Called when the activity is first created. */
@@ -176,20 +165,20 @@ public class StatsActivity extends Activity
SharedPreferences preferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (preferences != null) {
selectedTrackId = preferences.getLong(MyTracksSettings.SELECTED_TRACK,
-1);
recordingTrackId = preferences.getLong(MyTracksSettings.RECORDING_TRACK,
-1);
metricUnits = preferences.getBoolean(MyTracksSettings.METRIC_UNITS,
true);
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(MyTracksSettings.REPORT_SPEED, true);
preferences.getBoolean(getString(R.string.report_speed_key), true);
checkLiveTrack();
restoreStats();
updateLocation(null);
preferences.registerOnSharedPreferenceChangeListener(this);
}
locationManager =
locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
utils.setMetricUnits(metricUnits);
utils.setReportSpeed(displaySpeed);
@@ -231,27 +220,31 @@ public class StatsActivity extends Activity
Log.d(MyTracksConstants.TAG,
"StatsActivity: onSharedPreferences changed " + key);
if (key != null) {
if (key.equals(MyTracksSettings.SELECTED_TRACK)) {
if (key.equals(getString(R.string.selected_track_key))) {
selectedTrackId =
sharedPreferences.getLong(MyTracksSettings.SELECTED_TRACK, -1);
sharedPreferences.getLong(getString(R.string.selected_track_key),
-1);
checkLiveTrack();
restoreStats();
updateLocation(null);
} else if (key.equals(MyTracksSettings.RECORDING_TRACK)) {
} else if (key.equals(getString(R.string.recording_track_key))) {
recordingTrackId =
sharedPreferences.getLong(MyTracksSettings.RECORDING_TRACK, -1);
sharedPreferences.getLong(getString(R.string.recording_track_key),
-1);
checkLiveTrack();
restoreStats();
updateLocation(null);
} else if (key.equals(MyTracksSettings.METRIC_UNITS)) {
} else if (key.equals(getString(R.string.metric_units_key))) {
metricUnits =
sharedPreferences.getBoolean(MyTracksSettings.METRIC_UNITS, true);
sharedPreferences.getBoolean(
getString(R.string.metric_units_key), true);
utils.setMetricUnits(metricUnits);
utils.updateUnits();
restoreStats();
} else if (key.equals(MyTracksSettings.REPORT_SPEED)) {
} else if (key.equals(getString(R.string.report_speed_key))) {
displaySpeed =
sharedPreferences.getBoolean(MyTracksSettings.REPORT_SPEED, true);
sharedPreferences.getBoolean(getString(R.string.report_speed_key),
true);
utils.setReportSpeed(displaySpeed);
utils.updateUnits();
utils.setSpeedLabel(
@@ -359,60 +352,13 @@ public class StatsActivity extends Activity
return;
}
Cursor cursor = null;
try {
cursor = getContentResolver().query(
showCurrentSegment
? WaypointsColumns.CONTENT_URI
: TracksColumns.CONTENT_URI,
PROJECTION_COLUMNS,
showCurrentSegment
? WaypointsColumns.TRACKID + "=" + selectedTrackId
: "_id=" + selectedTrackId,
null,
"_id LIMIT 1");
if (cursor != null && cursor.moveToFirst()) {
final int idxStartTime =
cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME);
final int idxTotalTime =
cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
final int idxMovingTime =
cursor.getColumnIndexOrThrow(TracksColumns.MOVINGTIME);
final int idxTotalDistance =
cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
final int idxAverageSpeed =
cursor.getColumnIndexOrThrow(TracksColumns.AVGSPEED);
final int idxAverageMovingSpeed =
cursor.getColumnIndexOrThrow(TracksColumns.AVGMOVINGSPEED);
final int idxMaxSpeed =
cursor.getColumnIndexOrThrow(TracksColumns.MAXSPEED);
final int idxMinElevation =
cursor.getColumnIndexOrThrow(TracksColumns.MINELEVATION);
final int idxMaxElevation =
cursor.getColumnIndexOrThrow(TracksColumns.MAXELEVATION);
final int idxElevationGain =
cursor.getColumnIndexOrThrow(TracksColumns.ELEVATIONGAIN);
final int idxMinGrade =
cursor.getColumnIndexOrThrow(TracksColumns.MINGRADE);
final int idxMaxGrade =
cursor.getColumnIndexOrThrow(TracksColumns.MAXGRADE);
startTime = cursor.getLong(idxStartTime);
if (!selectedTrackIsRecording()) {
utils.setTime(R.id.total_time_register, cursor.getLong(idxTotalTime));
}
utils.setAllStats(cursor.getLong(idxMovingTime),
cursor.getFloat(idxTotalDistance), cursor.getFloat(idxAverageSpeed),
cursor.getFloat(idxAverageMovingSpeed),
cursor.getFloat(idxMaxSpeed), cursor.getFloat(idxMinElevation),
cursor.getFloat(idxMaxElevation), cursor.getFloat(idxElevationGain),
cursor.getFloat(idxMinGrade), cursor.getFloat(idxMaxGrade));
}
} finally {
if (cursor != null) {
cursor.close();
}
track = providerUtils.getTrack(selectedTrackId);
startTime = track.getStatistics().getStartTime();
if(!selectedTrackIsRecording()) {
utils.setTime(R.id.total_time_register,
track.getStatistics().getTotalTime());
}
utils.setAllStats(track.getStatistics());
}
/**
@@ -15,8 +15,7 @@
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
@@ -219,32 +218,18 @@ public class StatsUtilities {
setGrade(R.id.max_grade_register, maxGrade);
}
public void setAllStats(Waypoint wpt) {
setTime(R.id.moving_time_register, wpt.getMovingTime());
setDistance(R.id.total_distance_register, wpt.getTotalDistance() / 1000);
setSpeed(R.id.average_speed_register, wpt.getAverageSpeed() * 3.6);
public void setAllStats(TripStatistics stats) {
setTime(R.id.moving_time_register, stats.getMovingTime());
setDistance(R.id.total_distance_register, stats.getTotalDistance() / 1000);
setSpeed(R.id.average_speed_register, stats.getAverageSpeed() * 3.6);
setSpeed(R.id.average_moving_speed_register,
wpt.getAverageMovingSpeed() * 3.6);
setSpeed(R.id.max_speed_register, wpt.getMaxSpeed() * 3.6);
setAltitude(R.id.min_elevation_register, wpt.getMinElevation());
setAltitude(R.id.max_elevation_register, wpt.getMaxElevation());
setAltitude(R.id.elevation_gain_register, wpt.getTotalElevationGain());
setGrade(R.id.min_grade_register, wpt.getMinGrade());
setGrade(R.id.max_grade_register, wpt.getMaxGrade());
}
public void setAllStats(Track track) {
setTime(R.id.moving_time_register, track.getMovingTime());
setDistance(R.id.total_distance_register, track.getTotalDistance() / 1000);
setSpeed(R.id.average_speed_register, track.getAverageSpeed() * 3.6);
setSpeed(R.id.average_moving_speed_register,
track.getAverageMovingSpeed() * 3.6);
setSpeed(R.id.max_speed_register, track.getMaxSpeed() * 3.6);
setAltitude(R.id.min_elevation_register, track.getMinElevation());
setAltitude(R.id.max_elevation_register, track.getMaxElevation());
setAltitude(R.id.elevation_gain_register, track.getTotalElevationGain());
setGrade(R.id.min_grade_register, track.getMinGrade());
setGrade(R.id.max_grade_register, track.getMaxGrade());
stats.getAverageMovingSpeed() * 3.6);
setSpeed(R.id.max_speed_register, stats.getMaxSpeed() * 3.6);
setAltitude(R.id.min_elevation_register, stats.getMinElevation());
setAltitude(R.id.max_elevation_register, stats.getMaxElevation());
setAltitude(R.id.elevation_gain_register, stats.getTotalElevationGain());
setGrade(R.id.min_grade_register, stats.getMinGrade());
setGrade(R.id.max_grade_register, stats.getMaxGrade());
}
public void setSpeedLabel(int id, int speedString, int paceString) {
@@ -19,12 +19,17 @@ import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.webkit.WebView;
import android.widget.TextView;
/**
* An activity that displays a welcome screen.
@@ -72,5 +77,16 @@ public class WelcomeActivity extends Activity {
builder.setIcon(R.drawable.arrow_icon);
AlertDialog dialog = builder.create();
dialog.show();
// Get the version from the manifest.
try {
PackageInfo pi =
getPackageManager().getPackageInfo("com.google.android.maps.mytracks",
PackageManager.GET_META_DATA);
((TextView) dialog.findViewById(R.id.about_version_register)).
setText(pi.versionName);
} catch (NameNotFoundException e) {
Log.w(MyTracksConstants.TAG, "Failed to get version info.", e);
}
}
}
@@ -167,24 +167,25 @@ public class MyTracksProvider extends ContentProvider {
@Override
public int delete(Uri url, String where, String[] selectionArgs) {
if (urlMatcher.match(url) == TRACKPOINTS) {
Log.w(MyTracksProvider.TAG, "provider trackpoints delete!");
int count = db.delete(TRACKPOINTS_TABLE, where, selectionArgs);
getContext().getContentResolver().notifyChange(url, null, true);
return count;
} else if (urlMatcher.match(url) == TRACKS) {
Log.w(MyTracksProvider.TAG, "provider track delete!");
int count = db.delete(TRACKS_TABLE, where, selectionArgs);
getContext().getContentResolver().notifyChange(url, null, true);
return count;
} else if (urlMatcher.match(url) == WAYPOINTS) {
Log.w(MyTracksProvider.TAG, "provider waypoint delete!");
int count = db.delete(WAYPOINTS_TABLE, where, selectionArgs);
getContext().getContentResolver().notifyChange(url, null, true);
return count;
} else {
throw new IllegalArgumentException("Unknown URL " + url);
String table;
switch (urlMatcher.match(url)) {
case TRACKPOINTS:
table = TRACKPOINTS_TABLE;
break;
case TRACKS:
table = TRACKS_TABLE;
break;
case WAYPOINTS:
table = WAYPOINTS_TABLE;
break;
default:
throw new IllegalArgumentException("Unknown URL " + url);
}
Log.w(MyTracksProvider.TAG, "provider delete in " + table + "!");
int count = db.delete(table, where, selectionArgs);
getContext().getContentResolver().notifyChange(url, null, true);
return count;
}
@Override
@@ -216,19 +217,49 @@ public class MyTracksProvider extends ContentProvider {
} else {
values = new ContentValues();
}
if (urlMatcher.match(url) == TRACKPOINTS) {
return insertTrackPoint(url, values);
} else if (urlMatcher.match(url) == TRACKS) {
return insertTrack(url, values);
} else if (urlMatcher.match(url) == WAYPOINTS) {
return insertWaypoint(url, values);
} else {
throw new IllegalArgumentException("Unknown URL " + url);
int urlMatchType = urlMatcher.match(url);
return insertType(url, urlMatchType, values);
}
private Uri insertType(Uri url, int urlMatchType, ContentValues values) {
switch (urlMatchType) {
case TRACKPOINTS:
return insertTrackPoint(url, values);
case TRACKS:
return insertTrack(url, values);
case WAYPOINTS:
return insertWaypoint(url, values);
default:
throw new IllegalArgumentException("Unknown URL " + url);
}
}
@Override
public int bulkInsert(Uri url, ContentValues[] valuesBulk) {
Log.d(MyTracksProvider.TAG, "MyTracksProvider.bulkInsert");
int numInserted = 0;
try {
// Use a transaction in order to make the insertions run as a single batch
db.beginTransaction();
int urlMatch = urlMatcher.match(url);
for (numInserted = 0; numInserted < valuesBulk.length; numInserted++) {
ContentValues values = valuesBulk[numInserted];
if (values == null) { values = new ContentValues(); }
insertType(url, urlMatch, values);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
return numInserted;
}
private Uri insertTrackPoint(Uri url, ContentValues values) {
Log.d(MyTracksProvider.TAG, "MyTracksProvider.insertTrackPoint");
boolean hasLat = values.containsKey(TrackPointsColumns.LATITUDE);
boolean hasLong = values.containsKey(TrackPointsColumns.LONGITUDE);
boolean hasTime = values.containsKey(TrackPointsColumns.TIME);
@@ -232,6 +232,17 @@ public interface MyTracksProviderUtils {
*/
Uri insertTrackPoint(Location location, long trackId);
/**
* Inserts multiple track points in a single operation.
*
* @param locations an array of locations to insert
* @param length the number of locations (from the beginning of the array)
* to actually insert, or -1 for all of them
* @param trackId the ID of the track to insert the points into
* @return the number of points inserted
*/
int bulkInsertTrackPoints(Location[] locations, int length, long trackId);
/**
* Inserts a waypoint in the provider.
*
@@ -240,14 +251,6 @@ public interface MyTracksProviderUtils {
*/
Uri insertWaypoint(Waypoint waypoint);
/**
* Inserts a track including its track points in the provider.
*
* @param track the track to insert
* @return the content provider URI for the inserted track
*/
Uri insertTrackAndTrackPoints(Track track);
/**
* Tests if a track with given id exists.
*
@@ -270,7 +273,7 @@ public interface MyTracksProviderUtils {
* @param cursor a cursor pointing at a db or provider with locations
* @return a new location object
*/
public Location createLocation(Cursor cursor);
Location createLocation(Cursor cursor);
/**
* Creates a waypoint object from a given cursor.
@@ -278,7 +281,7 @@ public interface MyTracksProviderUtils {
* @param cursor a cursor pointing at a db or provider with waypoints.
* @return a new waypoint object
*/
public Waypoint createWaypoint(Cursor cursor);
Waypoint createWaypoint(Cursor cursor);
/**
* A factory which can produce instances of {@link MyTracksProviderUtils},
@@ -15,6 +15,8 @@
*/
package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.stats.TripStatistics;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -82,6 +84,8 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
*/
private static ContentValues createContentValues(Track track) {
ContentValues values = new ContentValues();
TripStatistics stats = track.getStatistics();
// Values id < 0 indicate no id is available:
if (track.getId() >= 0) {
values.put(TracksColumns._ID, track.getId());
@@ -92,29 +96,31 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
values.put(TracksColumns.CATEGORY, track.getCategory());
values.put(TracksColumns.NUMPOINTS, track.getNumberOfPoints());
values.put(TracksColumns.STARTID, track.getStartId());
values.put(TracksColumns.STARTTIME, track.getStartTime());
values.put(TracksColumns.STOPTIME, track.getStopTime());
values.put(TracksColumns.STARTTIME, stats.getStartTime());
values.put(TracksColumns.STOPTIME, stats.getStopTime());
values.put(TracksColumns.STOPID, track.getStopId());
values.put(TracksColumns.TOTALDISTANCE, track.getTotalDistance());
values.put(TracksColumns.TOTALTIME, track.getTotalTime());
values.put(TracksColumns.MOVINGTIME, track.getMovingTime());
values.put(TracksColumns.MAXLAT, track.getTop());
values.put(TracksColumns.MINLAT, track.getBottom());
values.put(TracksColumns.MAXLON, track.getRight());
values.put(TracksColumns.MINLON, track.getLeft());
values.put(TracksColumns.AVGSPEED, track.getAverageSpeed());
values.put(TracksColumns.AVGMOVINGSPEED, track.getAverageMovingSpeed());
values.put(TracksColumns.MAXSPEED, track.getMaxSpeed());
values.put(TracksColumns.MINELEVATION, track.getMinElevation());
values.put(TracksColumns.MAXELEVATION, track.getMaxElevation());
values.put(TracksColumns.ELEVATIONGAIN, track.getTotalElevationGain());
values.put(TracksColumns.MINGRADE, track.getMinGrade());
values.put(TracksColumns.MAXGRADE, track.getMaxGrade());
values.put(TracksColumns.TOTALDISTANCE, stats.getTotalDistance());
values.put(TracksColumns.TOTALTIME, stats.getTotalTime());
values.put(TracksColumns.MOVINGTIME, stats.getMovingTime());
values.put(TracksColumns.MAXLAT, stats.getTop());
values.put(TracksColumns.MINLAT, stats.getBottom());
values.put(TracksColumns.MAXLON, stats.getRight());
values.put(TracksColumns.MINLON, stats.getLeft());
values.put(TracksColumns.AVGSPEED, stats.getAverageSpeed());
values.put(TracksColumns.AVGMOVINGSPEED, stats.getAverageMovingSpeed());
values.put(TracksColumns.MAXSPEED, stats.getMaxSpeed());
values.put(TracksColumns.MINELEVATION, stats.getMinElevation());
values.put(TracksColumns.MAXELEVATION, stats.getMaxElevation());
values.put(TracksColumns.ELEVATIONGAIN, stats.getTotalElevationGain());
values.put(TracksColumns.MINGRADE, stats.getMinGrade());
values.put(TracksColumns.MAXGRADE, stats.getMaxGrade());
return values;
}
private static ContentValues createContentValues(Waypoint waypoint) {
ContentValues values = new ContentValues();
TripStatistics stats = waypoint.getStatistics();
// Values id < 0 indicate no id is available:
if (waypoint.getId() >= 0) {
values.put(WaypointsColumns._ID, waypoint.getId());
@@ -127,23 +133,21 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
values.put(WaypointsColumns.TYPE, waypoint.getType());
values.put(WaypointsColumns.LENGTH, waypoint.getLength());
values.put(WaypointsColumns.DURATION, waypoint.getDuration());
values.put(WaypointsColumns.STARTTIME, waypoint.getStartTime());
values.put(WaypointsColumns.STARTTIME, stats.getStartTime());
values.put(WaypointsColumns.STARTID, waypoint.getStartId());
values.put(WaypointsColumns.STOPID, waypoint.getStopId());
values.put(WaypointsColumns.TOTALDISTANCE, waypoint.getTotalDistance());
values.put(WaypointsColumns.TOTALTIME, waypoint.getTotalTime());
values.put(WaypointsColumns.MOVINGTIME, waypoint.getMovingTime());
values.put(WaypointsColumns.AVGSPEED, waypoint.getAverageSpeed());
values.put(WaypointsColumns.AVGMOVINGSPEED,
waypoint.getAverageMovingSpeed());
values.put(WaypointsColumns.MAXSPEED, waypoint.getMaxSpeed());
values.put(WaypointsColumns.MINELEVATION, waypoint.getMinElevation());
values.put(WaypointsColumns.MAXELEVATION, waypoint.getMaxElevation());
values.put(WaypointsColumns.ELEVATIONGAIN,
waypoint.getTotalElevationGain());
values.put(WaypointsColumns.MINGRADE, waypoint.getMinGrade());
values.put(WaypointsColumns.MAXGRADE, waypoint.getMaxGrade());
values.put(WaypointsColumns.TOTALDISTANCE, stats.getTotalDistance());
values.put(WaypointsColumns.TOTALTIME, stats.getTotalTime());
values.put(WaypointsColumns.MOVINGTIME, stats.getMovingTime());
values.put(WaypointsColumns.AVGSPEED, stats.getAverageSpeed());
values.put(WaypointsColumns.AVGMOVINGSPEED, stats.getAverageMovingSpeed());
values.put(WaypointsColumns.MAXSPEED, stats.getMaxSpeed());
values.put(WaypointsColumns.MINELEVATION, stats.getMinElevation());
values.put(WaypointsColumns.MAXELEVATION, stats.getMaxElevation());
values.put(WaypointsColumns.ELEVATIONGAIN, stats.getTotalElevationGain());
values.put(WaypointsColumns.MINGRADE, stats.getMinGrade());
values.put(WaypointsColumns.MAXGRADE, stats.getMaxGrade());
Location location = waypoint.getLocation();
if (location != null) {
@@ -232,9 +236,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
int idxTotalTime = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
int idxMovingTime = cursor.getColumnIndexOrThrow(TracksColumns.MOVINGTIME);
int idxAverageSpeed = cursor.getColumnIndexOrThrow(TracksColumns.AVGSPEED);
int idxAverageMovingSpeed =
cursor.getColumnIndexOrThrow(TracksColumns.AVGMOVINGSPEED);
int idxMaxSpeed = cursor.getColumnIndexOrThrow(TracksColumns.MAXSPEED);
int idxMinElevation =
cursor.getColumnIndexOrThrow(TracksColumns.MINELEVATION);
@@ -246,6 +247,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
int idxMaxGrade = cursor.getColumnIndexOrThrow(TracksColumns.MAXGRADE);
Track track = new Track();
TripStatistics stats = track.getStatistics();
if (!cursor.isNull(idxId)) {
track.setId(cursor.getLong(idxId));
}
@@ -265,10 +267,10 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
track.setStartId(cursor.getInt(idxStartId));
}
if (!cursor.isNull(idxStartTime)) {
track.setStartTime(cursor.getLong(idxStartTime));
stats.setStartTime(cursor.getLong(idxStartTime));
}
if (!cursor.isNull(idxStopTime)) {
track.setStopTime(cursor.getLong(idxStopTime));
stats.setStopTime(cursor.getLong(idxStopTime));
}
if (!cursor.isNull(idxStopId)) {
track.setStopId(cursor.getInt(idxStopId));
@@ -277,13 +279,13 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
track.setNumberOfPoints(cursor.getInt(idxNumPoints));
}
if (!cursor.isNull(idxTotalDistance)) {
track.setTotalDistance(cursor.getFloat(idxTotalDistance));
stats.setTotalDistance(cursor.getFloat(idxTotalDistance));
}
if (!cursor.isNull(idxTotalTime)) {
track.setTotalTime(cursor.getLong(idxTotalTime));
stats.setTotalTime(cursor.getLong(idxTotalTime));
}
if (!cursor.isNull(idxMovingTime)) {
track.setMovingTime(cursor.getLong(idxMovingTime));
stats.setMovingTime(cursor.getLong(idxMovingTime));
}
if (!cursor.isNull(idxMaxlat)
&& !cursor.isNull(idxMinlat)
@@ -293,31 +295,25 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
int bottom = cursor.getInt(idxMinlat);
int right = cursor.getInt(idxMaxlon);
int left = cursor.getInt(idxMinlon);
track.setBounds(left, top, right, bottom);
}
if (!cursor.isNull(idxAverageSpeed)) {
track.setAverageSpeed(cursor.getFloat(idxAverageSpeed));
}
if (!cursor.isNull(idxAverageMovingSpeed)) {
track.setAverageMovingSpeed(cursor.getFloat(idxAverageMovingSpeed));
stats.setBounds(left, top, right, bottom);
}
if (!cursor.isNull(idxMaxSpeed)) {
track.setMaxSpeed(cursor.getFloat(idxMaxSpeed));
stats.setMaxSpeed(cursor.getFloat(idxMaxSpeed));
}
if (!cursor.isNull(idxMinElevation)) {
track.setMinElevation(cursor.getFloat(idxMinElevation));
stats.setMinElevation(cursor.getFloat(idxMinElevation));
}
if (!cursor.isNull(idxMaxElevation)) {
track.setMaxElevation(cursor.getFloat(idxMaxElevation));
stats.setMaxElevation(cursor.getFloat(idxMaxElevation));
}
if (!cursor.isNull(idxElevationGain)) {
track.setTotalElevationGain(cursor.getFloat(idxElevationGain));
stats.setTotalElevationGain(cursor.getFloat(idxElevationGain));
}
if (!cursor.isNull(idxMinGrade)) {
track.setMinGrade(cursor.getFloat(idxMinGrade));
stats.setMinGrade(cursor.getFloat(idxMinGrade));
}
if (!cursor.isNull(idxMaxGrade)) {
track.setMaxGrade(cursor.getFloat(idxMaxGrade));
stats.setMaxGrade(cursor.getFloat(idxMaxGrade));
}
return track;
}
@@ -343,10 +339,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
int idxTotalTime = cursor.getColumnIndexOrThrow(WaypointsColumns.TOTALTIME);
int idxMovingTime =
cursor.getColumnIndexOrThrow(WaypointsColumns.MOVINGTIME);
int idxAverageSpeed =
cursor.getColumnIndexOrThrow(WaypointsColumns.AVGSPEED);
int idxAverageMovingSpeed =
cursor.getColumnIndexOrThrow(WaypointsColumns.AVGMOVINGSPEED);
int idxMaxSpeed = cursor.getColumnIndexOrThrow(WaypointsColumns.MAXSPEED);
int idxMinElevation =
cursor.getColumnIndexOrThrow(WaypointsColumns.MINELEVATION);
@@ -366,6 +358,8 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
int idxSpeed = cursor.getColumnIndexOrThrow(WaypointsColumns.SPEED);
Waypoint waypoint = new Waypoint();
TripStatistics stats = waypoint.getStatistics();
if (!cursor.isNull(idxId)) {
waypoint.setId(cursor.getLong(idxId));
}
@@ -394,7 +388,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
waypoint.setDuration(cursor.getLong(idxDuration));
}
if (!cursor.isNull(idxStartTime)) {
waypoint.setStartTime(cursor.getLong(idxStartTime));
stats.setStartTime(cursor.getLong(idxStartTime));
}
if (!cursor.isNull(idxStartId)) {
waypoint.setStartId(cursor.getLong(idxStartId));
@@ -403,37 +397,31 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
waypoint.setStopId(cursor.getLong(idxStopId));
}
if (!cursor.isNull(idxTotalDistance)) {
waypoint.setTotalDistance(cursor.getFloat(idxTotalDistance));
stats.setTotalDistance(cursor.getFloat(idxTotalDistance));
}
if (!cursor.isNull(idxTotalTime)) {
waypoint.setTotalTime(cursor.getLong(idxTotalTime));
stats.setTotalTime(cursor.getLong(idxTotalTime));
}
if (!cursor.isNull(idxMovingTime)) {
waypoint.setMovingTime(cursor.getLong(idxMovingTime));
}
if (!cursor.isNull(idxAverageSpeed)) {
waypoint.setAverageSpeed(cursor.getFloat(idxAverageSpeed));
}
if (!cursor.isNull(idxAverageMovingSpeed)) {
waypoint.setAverageMovingSpeed(cursor.getFloat(idxAverageMovingSpeed));
stats.setMovingTime(cursor.getLong(idxMovingTime));
}
if (!cursor.isNull(idxMaxSpeed)) {
waypoint.setMaxSpeed(cursor.getFloat(idxMaxSpeed));
stats.setMaxSpeed(cursor.getFloat(idxMaxSpeed));
}
if (!cursor.isNull(idxMinElevation)) {
waypoint.setMinElevation(cursor.getFloat(idxMinElevation));
stats.setMinElevation(cursor.getFloat(idxMinElevation));
}
if (!cursor.isNull(idxMaxElevation)) {
waypoint.setMaxElevation(cursor.getFloat(idxMaxElevation));
stats.setMaxElevation(cursor.getFloat(idxMaxElevation));
}
if (!cursor.isNull(idxElevationGain)) {
waypoint.setTotalElevationGain(cursor.getFloat(idxElevationGain));
stats.setTotalElevationGain(cursor.getFloat(idxElevationGain));
}
if (!cursor.isNull(idxMinGrade)) {
waypoint.setMinGrade(cursor.getFloat(idxMinGrade));
stats.setMinGrade(cursor.getFloat(idxMinGrade));
}
if (!cursor.isNull(idxMaxGrade)) {
waypoint.setMaxGrade(cursor.getFloat(idxMaxGrade));
stats.setMaxGrade(cursor.getFloat(idxMaxGrade));
}
Location location = new Location("");
@@ -494,7 +482,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
if (nextWaypoint != null) {
Log.d(MyTracksProvider.TAG, "Correcting marker " + nextWaypoint.getId()
+ " after deleted marker " + deletedWaypoint.getId());
nextWaypoint.combine(deletedWaypoint);
nextWaypoint.getStatistics().merge(deletedWaypoint.getStatistics());
nextWaypoint.setDescription(
descriptionGenerator.generateWaypointDescription(nextWaypoint));
if (!updateWaypoint(nextWaypoint)) {
@@ -852,8 +840,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
Cursor cursor = getLocationsCursor(track.getId(),
startingPoint,
buffer.getSize(), false);
final int idColumnIdx =
cursor.getColumnIndexOrThrow(TrackPointsColumns._ID);
if (cursor == null) {
Log.w(MyTracksProvider.TAG, "Cannot get a locations cursor!");
buffer.setInvalid();
@@ -872,13 +858,16 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
return;
}
while (cursor.moveToNext()) {
final int idColumnIdx =
cursor.getColumnIndexOrThrow(TrackPointsColumns._ID);
do {
Location location = createLocation(cursor);
if (location == null) {
continue;
}
buffer.add(location, cursor.getLong(idColumnIdx));
}
} while (cursor.moveToNext());
if (buffer.getLocationsLoaded() == 0) {
Log.w(MyTracksProvider.TAG, "No locations read.");
buffer.resetAt(startingPoint + buffer.getSize());
@@ -911,6 +900,18 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
createContentValues(location, trackId));
}
@Override
public int bulkInsertTrackPoints(Location[] locations, int length, long trackId) {
if (length == -1) { length = locations.length; }
ContentValues[] values = new ContentValues[length];
for (int i = 0; i < length; i++) {
values[i] = createContentValues(locations[i], trackId);
}
return context.getContentResolver().bulkInsert(TrackPointsColumns.CONTENT_URI, values);
}
@Override
public Uri insertWaypoint(Waypoint waypoint) {
Log.d(MyTracksProvider.TAG, "MyTracksProviderUtilsImpl.insertWaypoint");
@@ -919,31 +920,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
createContentValues(waypoint));
}
@Override
public Uri insertTrackAndTrackPoints(Track track) {
// Insert the track right away to have its ID
Uri trackUri = insertTrack(track);
long trackId = Long.parseLong(trackUri.getLastPathSegment());
track.setId(trackId);
// Insert all the points (associated with the track ID)
boolean firstPoint = true;
long pointId = -1;
for (Location location : track.getLocations()) {
Uri pointUri = insertTrackPoint(location, trackId);
pointId = Long.parseLong(pointUri.getLastPathSegment());
if (firstPoint) {
track.setStartId(pointId);
firstPoint = false;
}
}
track.setStopId(pointId);
// Update the track with the start and end point IDs
updateTrack(track);
return trackUri;
}
@Override
public boolean trackExists(long id) {
Cursor cursor = null;
@@ -15,6 +15,8 @@
*/
package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.stats.TripStatistics;
import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
@@ -24,7 +26,10 @@ import java.util.ArrayList;
/**
* A class representing a (GPS) Track.
*
* TODO: hashCode and equals
*
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
public class Track implements Parcelable {
@@ -34,6 +39,7 @@ public class Track implements Parcelable {
public static class Creator implements Parcelable.Creator<Track> {
public Track createFromParcel(Parcel source) {
ClassLoader classLoader = getClass().getClassLoader();
Track track = new Track();
track.id = source.readLong();
track.name = source.readString();
@@ -42,28 +48,14 @@ public class Track implements Parcelable {
track.category = source.readString();
track.startId = source.readLong();
track.stopId = source.readLong();
track.startTime = source.readLong();
track.stopTime = source.readLong();
track.totalDistance = source.readDouble();
track.totalTime = source.readLong();
track.movingTime = source.readLong();
track.averageSpeed = source.readDouble();
track.averageMovingSpeed = source.readDouble();
track.maxSpeed = source.readDouble();
track.minElevation = source.readDouble();
track.maxElevation = source.readDouble();
track.totalElevationGain = source.readDouble();
track.minGrade = source.readDouble();
track.maxGrade = source.readDouble();
track.left = source.readInt();
track.top = source.readInt();
track.right = source.readInt();
track.bottom = source.readInt();
track.stats = source.readParcelable(classLoader);
track.numberOfPoints = source.readInt();
for (int i = 0; i < track.numberOfPoints; ++i) {
Location loc = source.readParcelable(null);
Location loc = source.readParcelable(classLoader);
track.locations.add(loc);
}
return track;
}
@@ -75,10 +67,16 @@ public class Track implements Parcelable {
public static final Creator CREATOR = new Creator();
/**
* The track points.
* The track points (which may not have been loaded).
*/
private ArrayList<Location> locations = new ArrayList<Location>();
/**
* The number of location points (present even if the points themselves were
* not loaded).
*/
private int numberOfPoints = 0;
private long id = -1;
private String name = "";
private String description = "";
@@ -87,34 +85,9 @@ public class Track implements Parcelable {
private long stopId = -1;
private String category = "";
// Fields derived from locations. Use setDerivedFields() to set them:
//-------------------------------------------------------------------
private long startTime = -1;
private long stopTime = -1;
private int numberOfPoints = 0;
private double totalDistance = 0;
private long totalTime = 0;
private long movingTime = 0;
private int left;
private int top;
private int right;
private int bottom;
private double averageSpeed = 0;
private double averageMovingSpeed = 0;
private double maxSpeed = 0;
private double minElevation = 0;
private double maxElevation = 0;
private double totalElevationGain = 0;
private double minGrade = 0;
private double maxGrade = 0;
private TripStatistics stats = new TripStatistics();
public Track() {
left = Integer.MAX_VALUE;
top = Integer.MIN_VALUE;
right = Integer.MIN_VALUE;
bottom = Integer.MAX_VALUE;
}
public void writeToParcel(Parcel dest, int flags) {
@@ -125,23 +98,8 @@ public class Track implements Parcelable {
dest.writeString(category);
dest.writeLong(startId);
dest.writeLong(stopId);
dest.writeLong(startTime);
dest.writeLong(stopTime);
dest.writeDouble(totalDistance);
dest.writeLong(totalTime);
dest.writeLong(movingTime);
dest.writeDouble(averageSpeed);
dest.writeDouble(averageMovingSpeed);
dest.writeDouble(maxSpeed);
dest.writeDouble(minElevation);
dest.writeDouble(maxElevation);
dest.writeDouble(totalElevationGain);
dest.writeDouble(minGrade);
dest.writeDouble(maxGrade);
dest.writeInt(left);
dest.writeInt(top);
dest.writeInt(right);
dest.writeInt(bottom);
dest.writeParcelable(stats, 0);
dest.writeInt(numberOfPoints);
for (int i = 0; i < numberOfPoints; ++i) {
dest.writeParcelable(locations.get(i), 0);
@@ -151,29 +109,6 @@ public class Track implements Parcelable {
// Getters and setters:
//---------------------
public int getLeft() {
return left;
}
public int getTop() {
return top;
}
public int getRight() {
return right;
}
public int getBottom() {
return bottom;
}
public void setBounds(int aLeft, int aTop, int aRight, int aBottom) {
left = aLeft;
top = aTop;
right = aRight;
bottom = aBottom;
}
public int describeContents() {
return 0;
}
@@ -186,46 +121,6 @@ public class Track implements Parcelable {
this.id = id;
}
public double getTotalDistance() {
return totalDistance;
}
public void setTotalDistance(double totalDistance) {
this.totalDistance = totalDistance;
}
public long getTotalTime() {
return totalTime;
}
public void setTotalTime(long totalTime) {
this.totalTime = totalTime;
}
public long getMovingTime() {
return movingTime;
}
public void setMovingTime(long movingTime) {
this.movingTime = movingTime;
}
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getStopTime() {
return stopTime;
}
public void setStopTime(long stopTime) {
this.stopTime = stopTime;
}
public String getName() {
return name;
}
@@ -274,70 +169,6 @@ public class Track implements Parcelable {
this.category = category;
}
public double getAverageSpeed() {
return averageSpeed;
}
public void setAverageSpeed(double averageSpeed) {
this.averageSpeed = averageSpeed;
}
public double getAverageMovingSpeed() {
return averageMovingSpeed;
}
public void setAverageMovingSpeed(double averageMovingSpeed) {
this.averageMovingSpeed = averageMovingSpeed;
}
public double getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(double maxSpeed) {
this.maxSpeed = maxSpeed;
}
public double getMinElevation() {
return minElevation;
}
public void setMinElevation(double minElevation) {
this.minElevation = minElevation;
}
public double getMaxElevation() {
return maxElevation;
}
public void setMaxElevation(double maxElevation) {
this.maxElevation = maxElevation;
}
public double getTotalElevationGain() {
return totalElevationGain;
}
public void setTotalElevationGain(double totalElevationGain) {
this.totalElevationGain = totalElevationGain;
}
public double getMinGrade() {
return minGrade;
}
public void setMinGrade(double minGrade) {
this.minGrade = minGrade;
}
public double getMaxGrade() {
return maxGrade;
}
public void setMaxGrade(double maxGrade) {
this.maxGrade = maxGrade;
}
public int getNumberOfPoints() {
return numberOfPoints;
}
@@ -357,4 +188,12 @@ public class Track implements Parcelable {
public void setLocations(ArrayList<Location> locations) {
this.locations = locations;
}
public TripStatistics getStatistics() {
return stats;
}
public void setStatistics(TripStatistics stats) {
this.stats = stats;
}
}
@@ -15,6 +15,8 @@
*/
package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.stats.TripStatistics;
import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
@@ -23,16 +25,20 @@ import android.os.Parcelable;
* A way point. It has a location, meta data such as name, description,
* category, and icon, plus it can store track statistics for a "sub-track".
*
* TODO: hashCode and equals
*
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
public final class Waypoint implements Parcelable {
/**
* Creator for a Waypoint object
* Creator for a Waypoint object
*/
public static class Creator implements Parcelable.Creator<Waypoint> {
public Waypoint createFromParcel(Parcel source) {
ClassLoader classLoader = getClass().getClassLoader();
Waypoint waypoint = new Waypoint();
waypoint.id = source.readLong();
waypoint.name = source.readString();
@@ -41,26 +47,13 @@ public final class Waypoint implements Parcelable {
waypoint.icon = source.readString();
waypoint.trackId = source.readLong();
waypoint.type = source.readInt();
waypoint.length = source.readDouble();
waypoint.duration = source.readLong();
waypoint.startTime = source.readLong();
waypoint.startId = source.readLong();
waypoint.stopId = source.readLong();
waypoint.stats = source.readParcelable(classLoader);
byte hasLocation = source.readByte();
if (hasLocation > 0) {
waypoint.location = source.readParcelable(null);
waypoint.location = source.readParcelable(classLoader);
}
waypoint.totalDistance = source.readDouble();
waypoint.totalTime = source.readLong();
waypoint.movingTime = source.readLong();
waypoint.averageSpeed = source.readDouble();
waypoint.averageMovingSpeed = source.readDouble();
waypoint.maxSpeed = source.readDouble();
waypoint.minElevation = source.readDouble();
waypoint.maxElevation = source.readDouble();
waypoint.totalElevationGain = source.readDouble();
waypoint.minGrade = source.readDouble();
waypoint.maxGrade = source.readDouble();
return waypoint;
}
@@ -84,28 +77,18 @@ public final class Waypoint implements Parcelable {
private Location location;
/** Length along the track in meters. */
private double length = 0;
/** Time along the track in seconds. */
private long duration = 0;
/** Start time of a segment */
private long startTime = -1;
/** Start track point id */
private long startId = -1;
/** Stop track point id */
private long stopId = -1;
private double totalDistance = 0;
private long totalTime = 0;
private long movingTime = 0;
private double averageSpeed = 0;
private double averageMovingSpeed = 0;
private double maxSpeed = 0;
private double minElevation = 0;
private double maxElevation = 0;
private double totalElevationGain = 0;
private double minGrade = 0;
private double maxGrade = 0;
private TripStatistics stats = new TripStatistics();
/** The length of the track, without smoothing. */
private double length;
/** The total duration of the track (not from the last waypoint) */
private long duration;
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
@@ -115,46 +98,13 @@ public final class Waypoint implements Parcelable {
dest.writeString(icon);
dest.writeLong(trackId);
dest.writeInt(type);
dest.writeDouble(length);
dest.writeLong(duration);
dest.writeLong(startTime);
dest.writeLong(startId);
dest.writeLong(stopId);
dest.writeParcelable(stats, 0);
dest.writeByte(location == null ? (byte) 0 : (byte) 1);
if (location != null) {
dest.writeParcelable(location, 0);
}
dest.writeDouble(totalDistance);
dest.writeLong(totalTime);
dest.writeLong(movingTime);
dest.writeDouble(averageSpeed);
dest.writeDouble(averageMovingSpeed);
dest.writeDouble(maxSpeed);
dest.writeDouble(minElevation);
dest.writeDouble(maxElevation);
dest.writeDouble(totalElevationGain);
dest.writeDouble(minGrade);
dest.writeDouble(maxGrade);
}
/**
* Combines the statistics from another (earlier) waypoint with this one.
* This is needed when the user deletes a statistic waypoint.
*
* @param other the other waypoint
*/
public void combine(Waypoint other) {
totalTime += other.totalTime;
movingTime += other.movingTime;
totalDistance += other.totalDistance;
totalElevationGain += other.totalElevationGain;
averageSpeed = totalDistance / totalTime;
averageMovingSpeed = totalDistance / movingTime;
maxSpeed = Math.max(maxSpeed, other.maxSpeed);
minElevation = Math.min(minElevation, other.minElevation);
maxElevation = Math.max(maxElevation, other.maxElevation);
minGrade = Math.min(minGrade, other.minGrade);
maxGrade = Math.max(maxGrade, other.maxGrade);
}
// Getters and setters:
@@ -188,30 +138,6 @@ public final class Waypoint implements Parcelable {
this.id = id;
}
public double getTotalDistance() {
return totalDistance;
}
public void setTotalDistance(double totalDistance) {
this.totalDistance = totalDistance;
}
public long getTotalTime() {
return totalTime;
}
public void setTotalTime(long totalTime) {
this.totalTime = totalTime;
}
public long getMovingTime() {
return movingTime;
}
public void setMovingTime(long movingTime) {
this.movingTime = movingTime;
}
public String getName() {
return name;
}
@@ -232,30 +158,6 @@ public final class Waypoint implements Parcelable {
this.type = type;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public long getDuration() {
return duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getStartId() {
return startId;
}
@@ -288,71 +190,34 @@ public final class Waypoint implements Parcelable {
this.category = category;
}
public double getAverageSpeed() {
return averageSpeed;
}
public void setAverageSpeed(double averageSpeed) {
this.averageSpeed = averageSpeed;
}
public double getAverageMovingSpeed() {
return averageMovingSpeed;
}
public void setAverageMovingSpeed(double averageMovingSpeed) {
this.averageMovingSpeed = averageMovingSpeed;
}
public double getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(double maxSpeed) {
this.maxSpeed = maxSpeed;
}
public double getMinElevation() {
return minElevation;
}
public void setMinElevation(double minElevation) {
this.minElevation = minElevation;
}
public double getMaxElevation() {
return maxElevation;
}
public void setMaxElevation(double maxElevation) {
this.maxElevation = maxElevation;
}
public double getTotalElevationGain() {
return totalElevationGain;
}
public void setTotalElevationGain(double totalElevationGain) {
this.totalElevationGain = totalElevationGain;
}
public double getMinGrade() {
return minGrade;
}
public void setMinGrade(double minGrade) {
this.minGrade = minGrade;
}
public double getMaxGrade() {
return maxGrade;
}
public void setMaxGrade(double maxGrade) {
this.maxGrade = maxGrade;
}
public void setLocation(Location location) {
this.location = location;
}
public TripStatistics getStatistics() {
return stats;
}
public void setStatistics(TripStatistics stats) {
this.stats = stats;
}
// WARNING: These fields are used for internal state keeping. You probably
// want to look at getStatistics instead.
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public long getDuration() {
return duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
}
@@ -1,237 +0,0 @@
/*
* 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 com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import android.location.Location;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
/**
* Helper class to parse a GPX file or string and convert it into a track
* object.
*
* TODO: See if we can use a SAX style parser as the DOM style
* parsing uses too much memory and will not allow import of very large GPX
* files (limit currently set to 500KB).
*
* @author Leif Hendrik Wilden
*/
public class GpxImport {
private static final SimpleDateFormat DATE_FORMAT1 =
new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ");
private static final SimpleDateFormat DATE_FORMAT2 =
new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
private static final SimpleDateFormat DATE_FORMAT3 =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
/**
* Reads GPS tracks from a GPX file and append tracks and their coordinates to
* the given list of tracks.
*
* @param tracks a list of tracks
* @param filename a file name
* @throws SAXException a parsing error
* @throws ParserConfigurationException internal error
* @throws IOException a file reading problem
*/
public static void importGPXFile(
final String filename, final ArrayList<Track> tracks)
throws SAXException, ParserConfigurationException, IOException,
OutOfMemoryError {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
File file = new File(filename);
if (file.length() > 500 * 1024) {
// Better to throw an error now then, to let the VM do it. If the VM does
// it, it will throw another exception while throwing the OutOfMemoryError
// and that will kill out app with a nasty error message. In that way we
// can at least display a reasonable message to the user and let her know
// what the problem is.
throw new OutOfMemoryError();
}
Document doc = builder.parse(file);
importGPXDocument(tracks, doc);
}
/**
* This is a utility class with only static members.
*/
private GpxImport() {
}
/**
* Reads GPS tracks from a GPX document and append then to the given list of
* tracks.
*
* TODO: Break this method down into smaller ones
*
* @param tracks an array list of tracks
* @param doc a document
*/
public static void importGPXDocument(
final ArrayList<Track> tracks, final Document doc) {
NodeList trackNodes = doc.getElementsByTagName("trk");
for (int n = 0; n < trackNodes.getLength(); n++) {
Track track = new Track();
tracks.add(track);
ArrayList<Location> locations = track.getLocations();
Location lastLocation = null;
Node trkNode = trackNodes.item(n);
NodeList segmentNodes = trkNode.getChildNodes();
ArrayList<Node> nodes = new ArrayList<Node>();
int nSegments = 0;
for (int k = 0; k < segmentNodes.getLength(); k++) {
Node segmentNode = segmentNodes.item(k);
if (segmentNode.getNodeName().equals("name")) {
track.setName(segmentNode.getFirstChild().getNodeValue());
} else if (segmentNode.getNodeName().equals("description")) {
track.setDescription(segmentNode.getFirstChild().getNodeValue());
} else if (segmentNode.getNodeName().equals("trkseg")) {
long pointTime = locations.get(locations.size() - 1).getTime();
if (nSegments > 0) {
// Add a segment separator:
Location location = new Location("gps");
location.setLatitude(100.0);
location.setLongitude(100.0);
location.setAltitude(0);
if (locations.size() > 0) {
location.setTime(pointTime);
}
track.addLocation(location);
lastLocation = null;
}
nSegments++;
NodeList segmentChildren = segmentNode.getChildNodes();
nodes.clear();
for (int j = 0; j < segmentChildren.getLength(); j++) {
Node child = segmentChildren.item(j);
if (child.getNodeName().equals("trkpt")) {
nodes.add(child);
}
}
for (int i = 0; i < nodes.size(); i++) {
NamedNodeMap namedNodes = nodes.get(i).getAttributes();
double lat = Double.parseDouble(namedNodes.getNamedItem("lat")
.getNodeValue());
double lon = Double.parseDouble(namedNodes.getNamedItem("lon")
.getNodeValue());
NodeList children = nodes.get(i).getChildNodes();
Node elementNode = null;
Node timeNode = null;
for (int j = 0; j < children.getLength(); j++) {
Node child = children.item(j);
if (child.getNodeName().equals("ele")) {
elementNode = child;
} else if (child.getNodeName().equals("time")) {
timeNode = child;
}
}
String altitudeStr = null;
if (elementNode != null) {
altitudeStr = elementNode.getFirstChild().getNodeValue();
} else {
altitudeStr = "0";
}
String timeContents = null;
if (timeNode != null) {
timeContents = timeNode.getFirstChild().getNodeValue();
} else {
timeContents = "";
}
double altitude = Double.parseDouble(altitudeStr);
long t = -1;
try {
// 1st try with time zone at end a la "+0000"
t = DATE_FORMAT1.parse(timeContents).getTime();
} catch (ParseException e) {
// if that fails, try with a literal "Z" at the end (this is not
// according to xml standard, but some gpx files are like that):
try {
t = DATE_FORMAT2.parse(timeContents).getTime();
} catch (ParseException ex) {
// some gpx timestamps have 3 additional digits at the end.
try {
t = DATE_FORMAT3.parse(timeContents).getTime();
} catch (ParseException exc) {
t = 0;
}
}
}
Location location = new Location("gps");
location.setLatitude(lat);
location.setLongitude(lon);
location.setAltitude(altitude);
location.setTime(t);
// We don't have a speed and bearing in GPX, make something up from
// the last two points:
if (lastLocation != null) {
final long dt = location.getTime() - lastLocation.getTime();
if (dt > 0) {
final float speed =
location.distanceTo(lastLocation) / (dt / 1000);
location.setSpeed(speed);
}
location.setBearing(lastLocation.bearingTo(location));
}
lastLocation = location;
if (MyTracksUtils.isValidLocation(location)) {
track.addLocation(location);
}
}
if (locations.size() > 0) {
long startTime = locations.get(0).getTime();
track.setStartTime(startTime);
// Calculate statistics for the imported track
int numberOfPoints = locations.size();
TripStatistics stats = new TripStatistics(startTime);
for (Location location : locations) {
if (MyTracksUtils.isValidLocation(location)) {
/* Any time works here. The totalTime will be set by "pauseAt" later: */
stats.addLocation(location, location.getTime());
}
}
stats.pauseAt(pointTime);
track.setStopTime(pointTime);
stats.fillStatisticsForTrack(track);
}
}
}
}
}
}
@@ -0,0 +1,574 @@
/*
* 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.
*/
package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.MyTracksConstants;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.SimpleTimeZone;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Imports GPX XML files to the my tracks provider.
*
* TODO: Show progress indication to the user.
*
* @author Leif Hendrik Wilden
* @author Steffen Horlacher
* @author Rodrigo Damazio
*/
public class GpxImporter extends DefaultHandler {
/*
* Different date formats used in GPX files
*/
static final SimpleDateFormat DATE_FORMAT1 = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZ");
static final SimpleDateFormat DATE_FORMAT2 = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'");
static final SimpleDateFormat DATE_FORMAT3 = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSSZ");
static final SimpleTimeZone UTC_TIMEZONE = new SimpleTimeZone(0, "UTC");
/*
* GPX-XML tag names and attributes.
*/
private static final String TAG_TRACK = "trk";
private static final String TAG_TRACK_POINT = "trkpt";
private static final Object TAG_TRACK_SEGMENT = "trkseg";
private static final String TAG_NAME = "name";
private static final String TAG_DESCRIPTION = "desc";
private static final String TAG_ALTITUDE = "ele";
private static final String TAG_TIME = "time";
private static final String ATT_LAT = "lat";
private static final String ATT_LON = "lon";
/**
* The maximum number of locations to buffer for bulk-insertion into the database.
*/
private static final int MAX_BUFFERED_LOCATIONS = 512;
/**
* Utilities for accessing the contnet provider.
*/
private final MyTracksProviderUtils providerUtils;
/**
* List of track ids written in the database. Only contains successfully
* written tracks.
*/
private final List<Long> tracksWritten;
/**
* Contains the current elements content.
*/
private String content;
/**
* Currently reading location.
*/
private Location location;
/**
* Previous location, required for calculations.
*/
private Location lastLocation;
/**
* Currently reading track.
*/
private Track track;
/**
* Statistics builder for the current track.
*/
private TripStatisticsBuilder statsBuilder;
/**
* Buffer of locations to be bulk-inserted into the database.
*/
private Location[] bufferedPointInserts = new Location[MAX_BUFFERED_LOCATIONS];
/**
* Number of locations buffered to be inserted into the database.
*/
private int numBufferedPointInserts = 0;
/**
* Number of locations already processed.
*/
private int numberOfLocations;
/**
* Number of segments already processed.
*/
private int numberOfSegments;
/**
* Used to identify if a track was written to the database but not yet
* finished successfully.
*/
private boolean isCurrentTrackRollbackable;
/**
* Flag to indicate if we're inside a track's xml element.
* Some sub elements like name may be used in other parts of the gpx file,
* and we use this to ignore them.
*/
private boolean isInTrackElement;
/**
* Counter to find out which child level of track we are processing.
*/
private int trackChildDepth;
/**
* SAX-Locator to get current line information.
*/
private Locator locator;
private Location lastSegmentLocation;
/**
* Reads GPS tracks from a GPX file and writes tracks and their coordinates to
* the database.
*
* @param tracks a list of tracks
* @param is a input steam with gpx-xml data
* @return long[] array of track ids written in the database
* @throws SAXException a parsing error
* @throws ParserConfigurationException internal error
* @throws IOException a file reading problem
*/
public static long[] importGPXFile(final InputStream is,
final MyTracksProviderUtils providerUtils)
throws ParserConfigurationException, SAXException, IOException {
SAXParserFactory factory = SAXParserFactory.newInstance();
GpxImporter handler = new GpxImporter(providerUtils);
SAXParser parser = factory.newSAXParser();
long[] trackIds = null;
try {
long start = System.currentTimeMillis();
parser.parse(is, handler);
long end = System.currentTimeMillis();
Log.d(MyTracksConstants.TAG, "Total import time: " + (end - start) + "ms");
trackIds = handler.getImportedTrackIds();
} finally {
// delete track if not finished
handler.rollbackUnfinishedTracks();
}
return trackIds;
}
/**
* Constructor, requires providerUtils for writing tracks the database.
*/
public GpxImporter(MyTracksProviderUtils providerUtils) {
this.providerUtils = providerUtils;
tracksWritten = new ArrayList<Long>();
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String newContent = new String(ch, start, length);
if (content == null) {
content = newContent;
} else {
// In 99% of the cases, a single call to this method will be made for each
// sequence of characters we're interested in, so we'll rarely be
// concatenating strings, thus not justifying the use of a StringBuilder.
content += newContent;
}
}
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
if (isInTrackElement) {
trackChildDepth++;
if (localName.equals(TAG_TRACK_POINT)) {
onTrackPointElementStart(attributes);
} else if (localName.equals(TAG_TRACK_SEGMENT)) {
onTrackSegmentElementStart();
} else if (localName.equals(TAG_TRACK)) {
String msg = createErrorMessage("Invalid GPX-XML detected");
throw new SAXException(msg);
}
} else if (localName.equals(TAG_TRACK)) {
isInTrackElement = true;
trackChildDepth = 0;
onTrackElementStart();
}
}
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
if (!isInTrackElement) { return; }
// process these elements only as sub-elements of track
if (localName.equals(TAG_TRACK_POINT)) {
onTrackPointElementEnd();
} else if (localName.equals(TAG_ALTITUDE)) {
onAltitudeElementEnd();
} else if (localName.equals(TAG_TIME)) {
onTimeElementEnd();
} else if (localName.equals(TAG_NAME)) {
// we are only interested in the first level name element
if (trackChildDepth == 1) {
onNameElementEnd();
}
} else if (localName.equals(TAG_DESCRIPTION)) {
// we are only interested in the first level description element
if (trackChildDepth == 1) {
onDescriptionElementEnd();
}
} else if (localName.equals(TAG_TRACK_SEGMENT)) {
onTrackSegmentElementEnd();
} else if (localName.equals(TAG_TRACK)) {
onTrackElementEnd();
isInTrackElement = false;
trackChildDepth = 0;
}
trackChildDepth--;
// reset element content
content = null;
}
@Override
public void setDocumentLocator(Locator locator) {
this.locator = locator;
}
/**
* Create a new Track object and insert empty track in database. Track will be
* updated with missing values later.
*/
private void onTrackElementStart() {
track = new Track();
numberOfLocations = 0;
Uri trackUri = providerUtils.insertTrack(track);
long trackId = Long.parseLong(trackUri.getLastPathSegment());
track.setId(trackId);
isCurrentTrackRollbackable = true;
}
private void onDescriptionElementEnd() {
track.setDescription(content.toString().trim());
}
private void onNameElementEnd() {
track.setName(content.toString().trim());
}
/**
* Track segment started.
*/
private void onTrackSegmentElementStart() {
if (numberOfSegments > 0) {
// Add a segment separator:
location = new Location(LocationManager.GPS_PROVIDER);
location.setLatitude(100.0);
location.setLongitude(100.0);
location.setAltitude(0);
if (lastLocation != null) {
location.setTime(lastLocation.getTime());
}
insertTrackPoint(location);
lastLocation = location;
lastSegmentLocation = null;
location = null;
}
numberOfSegments++;
}
/**
* Reads trackpoint attributes and assigns them to the current location.
*
* @param attributes xml attributes
*/
private void onTrackPointElementStart(Attributes attributes) throws SAXException {
if (location != null) {
String errorMsg = createErrorMessage("Found a track point inside another one.");
throw new SAXException(errorMsg);
}
location = createLocationFromAttributes(attributes);
}
/**
* Creates and returns a location with the position parsed from the given
* attributes.
*
* @param attributes the attributes to parse
* @return the created location
* @throws SAXException if the attributes cannot be parsed
*/
private Location createLocationFromAttributes(Attributes attributes) throws SAXException {
String latitude = attributes.getValue(ATT_LAT);
String longitude = attributes.getValue(ATT_LON);
if (latitude == null || longitude == null) {
throw new SAXException(createErrorMessage("Point with no longitude or latitude"));
}
// create new location and set attributes
Location loc = new Location(LocationManager.GPS_PROVIDER);
loc.setLatitude(Double.parseDouble(latitude));
loc.setLongitude(Double.parseDouble(longitude));
return loc;
}
/**
* Track point finished, write in database.
*
* @throws SAXException - thrown if track point is invalid
*/
private void onTrackPointElementEnd() throws SAXException {
if (MyTracksUtils.isValidLocation(location)) {
statsBuilder.addLocation(location, location.getTime());
// insert in db
insertTrackPoint(location);
// first track point?
if (lastLocation == null && numberOfSegments == 1) {
track.setStartId(getLastPointId());
}
lastLocation = location;
lastSegmentLocation = location;
location = null;
} else {
// invalid location - abort import
String msg = createErrorMessage("Invalid location detected: " + location);
throw new SAXException(msg);
}
}
private void insertTrackPoint(Location loc) {
bufferedPointInserts[numBufferedPointInserts] = loc;
numBufferedPointInserts++;
numberOfLocations++;
if (numBufferedPointInserts >= MAX_BUFFERED_LOCATIONS) {
flushPointInserts();
}
}
private void flushPointInserts() {
if (numBufferedPointInserts <= 0) { return; }
providerUtils.bulkInsertTrackPoints(bufferedPointInserts, numBufferedPointInserts, track.getId());
numBufferedPointInserts = 0;
}
/**
* Track segment finished.
*/
private void onTrackSegmentElementEnd() {
// Nothing to be done
}
/**
* Track finished - update in database.
*/
private void onTrackElementEnd() {
if (lastLocation != null) {
flushPointInserts();
// Calculate statistics for the imported track and update
statsBuilder.pauseAt(lastLocation.getTime());
track.setStopId(getLastPointId());
track.setNumberOfPoints(numberOfLocations);
track.setStatistics(statsBuilder.getStatistics());
providerUtils.updateTrack(track);
tracksWritten.add(track.getId());
isCurrentTrackRollbackable = false;
lastSegmentLocation = null;
lastLocation = null;
statsBuilder = null;
} else {
// track contains no track points makes no real
// sense to import it as we have no location
// information -> roll back
rollbackUnfinishedTracks();
}
}
/**
* Setting time and doing additional calculations as this is the last value
* required. Also sets the start time for track and statistics as there is no
* start time in the track root element.
*
* @throws SAXException on parsing errors
*/
private void onTimeElementEnd() throws SAXException {
if (location == null) { return; }
long time = parseTimeForAllFormats(content);
if (lastSegmentLocation != null) {
long timeDifference = time - lastSegmentLocation.getTime();
// check for negative time change
if (timeDifference < 0) {
String msg = createErrorMessage("Found negative time change.");
throw new SAXException(msg);
}
// We don't have a speed and bearing in GPX, make something up from
// the last two points.
// TODO GPS points tend to have some inherent imprecision,
// speed and bearing will likely be off, so the statistics for things like
// max speed will also be off.
float speed = location.distanceTo(lastLocation) * 1000.0f / timeDifference;
location.setSpeed(speed);
location.setBearing(lastSegmentLocation.bearingTo(location));
}
location.setTime(time);
// initialize start time with time of first track point
if (statsBuilder == null) {
statsBuilder = new TripStatisticsBuilder();
statsBuilder.resumeAt(time);
}
}
private void onAltitudeElementEnd() {
if (location != null) {
location.setAltitude(Double.parseDouble(content));
}
}
/**
* Deletes the last track if it was not completely imported.
*/
public void rollbackUnfinishedTracks() {
if (isCurrentTrackRollbackable) {
providerUtils.deleteTrack(track.getId());
isCurrentTrackRollbackable = false;
}
}
/**
* Get all track ids of the tracks created by this importer run.
*
* @return array of track ids
*/
private long[] getImportedTrackIds() {
// Convert from java.lang.Long for convenience
long[] result = new long[tracksWritten.size()];
for (int i = 0; i < result.length; i++) {
result[i] = tracksWritten.get(i);
}
return result;
}
/**
* Parse time trying different formats used in GPX files.
*
* @param timeContents string with time information
* @return time as long
* @throws SAXException on time parsing errors
*/
private long parseTimeForAllFormats(String timeContents) throws SAXException {
long time;
timeContents = timeContents.trim();
// 1st try with time zone at end a la "+0000"
time = parseTime(timeContents, DATE_FORMAT1);
if (time > -1) { return time; }
// if that fails, try with a literal "Z" at the end
// (this is not according to xml standard, but some gpx files are like
// that):
time = parseTime(timeContents, DATE_FORMAT2);
if (time > -1) { return time; }
// some gpx timestamps have 3 additional digits at the end.
time = parseTime(timeContents, DATE_FORMAT3);
if (time > -1) { return time; }
// everything failed - abort the import
String msg = createErrorMessage("Invalid time format: " + timeContents);
throw new SAXException(msg);
}
private long parseTime(String timeContents, SimpleDateFormat formatParam) {
SimpleDateFormat format = formatParam;
try {
format.setTimeZone(UTC_TIMEZONE);
return format.parse(timeContents).getTime();
} catch (ParseException ex) {
return -1;
}
}
/**
* Returns the ID of the last point inserted into the database.
*/
private long getLastPointId() {
flushPointInserts();
return providerUtils.getLastLocationId(track.getId());
}
/**
* Builds a parsing error message with current line information.
*
* @param details details about the error, will be appended
* @return error message string with current line information
*/
private String createErrorMessage(String details) {
StringBuffer msg = new StringBuffer();
msg.append("Parsing error at line: ");
msg.append(locator.getLineNumber());
msg.append(" column: ");
msg.append(locator.getColumnNumber());
msg.append(". ");
msg.append(details);
return msg.toString();
}
}
@@ -24,6 +24,7 @@ import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.gdata.GDataClientFactory;
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.stats.TripStatistics;
import com.google.android.apps.mytracks.util.ResourceUtils;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
@@ -111,7 +112,9 @@ public class SendToDocs {
SharedPreferences preferences = activity.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0);
if (preferences != null) {
metricUnits = preferences.getBoolean(MyTracksSettings.METRIC_UNITS, true);
metricUnits =
preferences.getBoolean(activity.getString(R.string.metric_units_key),
true);
} else {
metricUnits = true;
}
@@ -429,6 +432,7 @@ public class SendToDocs {
String worksheetId) throws IOException {
String worksheetUri = String.format(DOCS_SPREADSHEET_URL_FORMAT,
spreadsheetId, worksheetId);
TripStatistics stats = track.getStatistics();
/* Prepare the Post-Text we are going to send. */
StringBuilder sb = new StringBuilder();
@@ -437,29 +441,29 @@ public class SendToDocs {
+ "2006/extended'>");
appendTag("name", track.getName(), sb);
appendTag("description", track.getDescription(), sb);
appendTag("date", String.format("%tc", track.getStartTime()), sb);
appendTag("date", String.format("%tc", stats.getStartTime()), sb);
appendTag("totaltime", StringUtils.formatTimeAlwaysShowingHours(
track.getTotalTime()), sb);
stats.getTotalTime()), sb);
appendTag("movingtime", StringUtils.formatTimeAlwaysShowingHours(
track.getMovingTime()), sb);
appendLargeUnitsTag("distance", track.getTotalDistance() / 1000, sb);
stats.getMovingTime()), sb);
appendLargeUnitsTag("distance", stats.getTotalDistance() / 1000, sb);
appendTag("distanceunit",
metricUnits
? activity.getString(R.string.kilometer)
: activity.getString(R.string.mile),
sb);
appendLargeUnitsTag("averagespeed", track.getAverageSpeed() * 3.6, sb);
appendLargeUnitsTag("averagespeed", stats.getAverageSpeed() * 3.6, sb);
appendLargeUnitsTag("averagemovingspeed",
track.getAverageMovingSpeed() * 3.6, sb);
appendLargeUnitsTag("maxspeed", track.getMaxSpeed() * 3.6, sb);
stats.getAverageMovingSpeed() * 3.6, sb);
appendLargeUnitsTag("maxspeed", stats.getMaxSpeed() * 3.6, sb);
appendTag("speedunit",
metricUnits
? activity.getString(R.string.kilometer_per_hour)
: activity.getString(R.string.mile_per_hour),
sb);
appendSmallUnitsTag("elevationgain", track.getTotalElevationGain(), sb);
appendSmallUnitsTag("minelevation", track.getMinElevation(), sb);
appendSmallUnitsTag("maxelevation", track.getMaxElevation(), sb);
appendSmallUnitsTag("elevationgain", stats.getTotalElevationGain(), sb);
appendSmallUnitsTag("minelevation", stats.getMinElevation(), sb);
appendSmallUnitsTag("maxelevation", stats.getMaxElevation(), sb);
appendTag("elevationunit",
metricUnits
? activity.getString(R.string.meter)
@@ -28,6 +28,7 @@ import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TrackBuffer;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.stats.DoubleBuffer;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
@@ -105,12 +106,14 @@ public class SendToMyMaps {
// 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());
segment.setStartTime(track.getStartTime());
segment.setStopTime(track.getStopTime());
segmentStats.setStartTime(trackStats.getStartTime());
segmentStats.setStopTime(trackStats.getStopTime());
boolean startNewTrackSegment = false;
for (int i = 0; i < buffer.getLocationsLoaded(); ++i) {
Location loc = buffer.get(i);
@@ -134,8 +137,8 @@ public class SendToMyMaps {
if (loc.getLatitude() <= 90) {
segment.addLocation(loc);
if (segment.getStartTime() < 0) {
segment.setStartTime(loc.getTime());
if (segmentStats.getStartTime() < 0) {
segmentStats.setStartTime(loc.getTime());
}
}
}
@@ -159,8 +162,10 @@ public class SendToMyMaps {
*/
private void prepareTrackSegment(
Track segment, ArrayList<Track> splitTracks) {
if (segment.getStopTime() < 0 && segment.getLocations().size() > 0) {
segment.setStopTime(segment.getLocations().size() - 1);
TripStatistics segmentStats = segment.getStatistics();
if (segmentStats.getStopTime() < 0
&& segment.getLocations().size() > 0) {
segmentStats.setStopTime(segment.getLocations().size() - 1);
}
/*
@@ -259,7 +264,9 @@ public class SendToMyMaps {
MyTracksSettings.SETTINGS_NAME, 0);
boolean metricUnits = true;
if (preferences != null) {
metricUnits = preferences.getBoolean(MyTracksSettings.METRIC_UNITS, true);
metricUnits =
preferences.getBoolean(context.getString(R.string.metric_units_key),
true);
}
// For the progress monitor:
@@ -385,7 +392,7 @@ public class SendToMyMaps {
boolean mapPublic = true;
if (preferences != null) {
mapPublic = preferences.getBoolean(
MyTracksSettings.DEFAULT_MAP_PUBLIC, true);
context.getString(R.string.default_map_public_key), true);
}
metaData.setSearchable(mapPublic);
Entry entry = MyMapsGDataConverter.getMapEntryForMetadata(metaData);
@@ -662,6 +669,7 @@ public class SendToMyMaps {
+ (isStart ? context.getString(R.string.start)
: context.getString(R.string.end));
myMapsFeature.setTitle(name);
myMapsFeature.setDescription(isStart ? "" : track.getDescription());
return myMapsFeature;
}
@@ -684,6 +692,7 @@ public class SendToMyMaps {
} else {
myMapsFeature.setTitle(wpt.getName());
}
myMapsFeature.setDescription(wpt.getDescription().replaceAll("\n", "<br>"));
return myMapsFeature;
}
}
@@ -0,0 +1,191 @@
/*
* 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.
*/
package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
import android.location.Location;
import android.os.Build;
import android.os.Environment;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
/**
* Write out a a track in the Garmin training center database, tcx format.
* As defined by:
* http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2
*
* @author Sandor Dornbush
*/
public class TcxTrackWriter implements TrackFormatWriter {
private PrintWriter pw = null;
private Track track;
static final SimpleDateFormat TIMESTAMP_FORMAT =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
{
TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
}
public TcxTrackWriter() {
}
@Override
public void prepare(Track track, OutputStream out) {
this.track = track;
this.pw = new PrintWriter(out);
}
@Override
public void close() {
if (pw != null) {
pw.close();
pw = null;
}
}
@Override
public String getDefaultDirectory() {
return Environment.getExternalStorageDirectory()
+ System.getProperty("file.separator") + getExtension();
}
@Override
public String getExtension() {
return TrackFileFormat.TCX.getExtension();
}
@Override
public void writeHeader() {
if (pw == null) {
return;
}
pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>");
pw.print("<TrainingCenterDatabase ");
pw.print("xmlns=\"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2\" ");
pw.print("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
pw.print("xsi:schemaLocation=\"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 ");
pw.println("http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd\">");
pw.println();
}
@Override
public void writeBeginTrack(Location firstPoint) {
if (pw == null) {
return;
}
pw.println(" <Activities>");
pw.print(" <Activity Sport=\"");
if (track.getCategory() != null) {
pw.print(track.getCategory());
}
pw.println("\">");
pw.print(" <Id>");
pw.print(TIMESTAMP_FORMAT.format(track.getStatistics().getStartTime()));
pw.println("</Id>");
pw.println(" <Lap>");
pw.print(" <TotalTimeSeconds>");
pw.print(track.getStatistics().getTotalTime() / 1000);
pw.println("</TotalTimeSeconds>");
pw.print(" <DistanceMeters>");
pw.print(track.getStatistics().getTotalDistance());
pw.println("</DistanceMeters>");
// TODO max speed etc.
// Calories are a required element just put in 0.
pw.print("<Calories>0</Calories>");
pw.println("<Intensity>Active</Intensity>");
pw.println("<TriggerMethod>Manual</TriggerMethod>)");
}
@Override
public void writeOpenSegment() {
if (pw != null) {
pw.println(" <Track>");
}
}
@Override
public void writeLocation(Location location) {
if (pw == null) {
return;
}
pw.println(" <Trackpoint>");
Date d = new Date(location.getTime());
pw.println(" <Time>" + TIMESTAMP_FORMAT.format(d) + "</Time>");
pw.println(" <Position>");
pw.print(" <LatitudeDegrees>");
pw.print(location.getLatitude());
pw.println("</LatitudeDegrees>");
pw.print(" <LongitudeDegrees>");
pw.print(location.getLongitude());
pw.println("</LongitudeDegrees>");
pw.println(" </Position>");
pw.print(" <AltitudeMeters>");
pw.print(location.getAltitude());
pw.println("</AltitudeMeters>");
pw.println(" </Trackpoint>");
}
@Override
public void writeCloseSegment() {
if (pw != null) {
pw.println(" </Track>");
}
}
@Override
public void writeEndTrack(Location lastPoint) {
if (pw == null) {
return;
}
pw.println(" </Lap>");
pw.print(" <Creator xsi:type=\"Device_t\">");
pw.print("<Name>");
pw.print(Build.MODEL);
pw.print("</Name>");
pw.println("</Creator>)");
pw.println(" </Activity>");
pw.println(" </Activities>");
}
@Override
public void writeFooter() {
if (pw == null) {
return;
}
pw.print(" <Author xsi:type=\"Application_t\">");
pw.print("<Name>My Tracks by Google</Name>");
pw.println("</Author>");
pw.println("</TrainingCenterDatabase>");
}
@Override
public void writeWaypoint(Waypoint waypoint) {
// TODO Write out the waypoints somewhere.
}
}
@@ -49,6 +49,12 @@ public class TrackWriterFactory {
public TrackFormatWriter newFormatWriter(Context context) {
return new CsvTrackWriter();
}
},
TCX {
@Override
public TrackFormatWriter newFormatWriter(Context context) {
return new TcxTrackWriter();
}
};
/**
@@ -35,7 +35,7 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.AbstractHttpEntity;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.DefaultHttpClient;
@@ -46,6 +46,7 @@ import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.zip.GZIPInputStream;
/**
* Implementation of a GDataClient using GoogleHttpClient to make HTTP requests.
@@ -186,6 +187,7 @@ public class AndroidGDataClient implements GDataClient {
while (redirectsLeft > 0) {
HttpUriRequest request = creator.createRequest(uri);
request.addHeader("Accept-Encoding", "gzip");
// only add the auth token if not null (to allow for GData feeds that do
// not require
@@ -197,9 +199,6 @@ public class AndroidGDataClient implements GDataClient {
for (Header h : request.getAllHeaders()) {
Log.v(TAG, h.getName() + ": " + h.getValue());
}
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Executing " + request.getRequestLine().toString());
}
@@ -229,6 +228,10 @@ public class AndroidGDataClient implements GDataClient {
HttpEntity entity = response.getEntity();
if ((status >= 200) && (status < 300) && entity != null) {
return getUngzippedContent(entity);
}
// TODO: handle 301, 307?
// TODO: let the http client handle the redirects, if we can be sure we'll
// never get a
@@ -295,6 +298,34 @@ public class AndroidGDataClient implements GDataClient {
throw new HttpException(exceptionMessage, status, null /* InputStream */);
}
/**
* Gets the input stream from a response entity. If the entity is gzipped
* then this will get a stream over the uncompressed data.
*
* @param entity the entity whose content should be read
* @return the input stream to read from
* @throws IOException
*/
private static InputStream getUngzippedContent(HttpEntity entity)
throws IOException {
InputStream responseStream = entity.getContent();
if (responseStream == null) {
return responseStream;
}
Header header = entity.getContentEncoding();
if (header == null) {
return responseStream;
}
String contentEncoding = header.getValue();
if (contentEncoding == null) {
return responseStream;
}
if (contentEncoding.contains("gzip")){
responseStream = new GZIPInputStream(responseStream);
}
return responseStream;
}
/*
* (non-Javadoc)
*
@@ -422,7 +453,7 @@ public class AndroidGDataClient implements GDataClient {
}
}
AbstractHttpEntity entity = new BasicHttpEntity();
AbstractHttpEntity entity = new ByteArrayEntity(entryBytes);
entity.setContentType(entry.getContentType());
return entity;
}
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks.services;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.stats.TripStatisticsData;
/**
* MyTracks service.
@@ -0,0 +1,142 @@
/*
* 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.
*/
package com.google.android.apps.mytracks.services;
import android.content.SharedPreferences;
import android.util.Log;
import com.google.android.apps.mytracks.MyTracksConstants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.maps.mytracks.R;
/**
* A class that manages reading the shared preferences for the service.
*
* @author Sandor Dornbush
*/
public class PreferenceManager {
private TrackRecordingService service;
private String announcement_frequency_key;
private String max_recording_distance_key;
private String metric_units_key;
private String min_recording_distance_key;
private String min_recording_interval_key;
private String min_required_accuracy_key;
private String signal_sampling_frequency_key;
private String split_frequency_key;
public PreferenceManager(TrackRecordingService service) {
this.service = service;
announcement_frequency_key =
service.getString(R.string.announcement_frequency_key);
max_recording_distance_key =
service.getString(R.string.max_recording_distance_key);
metric_units_key =
service.getString(R.string.metric_units_key);
min_recording_distance_key =
service.getString(R.string.min_recording_distance_key);
min_recording_interval_key =
service.getString(R.string.min_recording_interval_key);
min_required_accuracy_key =
service.getString(R.string.min_required_accuracy_key);
split_frequency_key =
service.getString(R.string.split_frequency_key);
signal_sampling_frequency_key =
service.getString(R.string.signal_sampling_frequency_key);
}
/**
* Notifies that preferences have changed.
* Call this with key == null to update all preferences in one call.
*
* @param key the key that changed (may be null to update all preferences)
*/
public void onSharedPreferenceChanged(String key) {
SharedPreferences sharedPreferences =
service.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (sharedPreferences == null) {
Log.w(MyTracksConstants.TAG,
"TrackRecordingService: Couldn't get shared preferences.");
return;
}
if (key == null || key.equals(min_recording_distance_key)) {
service.setMinRecordingDistance(
sharedPreferences.getInt(
min_recording_distance_key,
MyTracksSettings.DEFAULT_MIN_RECORDING_DISTANCE));
Log.d(MyTracksConstants.TAG,
"TrackRecordingService: minRecordingDistance = "
+ service.getMinRecordingDistance());
}
if (key == null || key.equals(max_recording_distance_key)) {
service.setMaxRecordingDistance(
sharedPreferences.getInt(
max_recording_distance_key,
MyTracksSettings.DEFAULT_MAX_RECORDING_DISTANCE));
}
if (key == null || key.equals(min_recording_interval_key)) {
int minRecordingInterval = sharedPreferences.getInt(
min_recording_interval_key,
MyTracksSettings.DEFAULT_MIN_RECORDING_INTERVAL);
switch (minRecordingInterval) {
case -2:
// Battery Miser
// min: 30 seconds
// max: 5 minutes
// minDist: 5 meters Choose battery life over moving time accuracy.
service.setLocationListenerPolicy(
new AdaptiveLocationListenerPolicy(30000, 300000, 5));
break;
case -1:
// High Accuracy
// min: 1 second
// max: 30 seconds
// minDist: 0 meters get all updates to properly measure moving time.
service.setLocationListenerPolicy(
new AdaptiveLocationListenerPolicy(1000, 30000, 0));
break;
default:
service.setLocationListenerPolicy(
new AbsoluteLocationListenerPolicy(minRecordingInterval * 1000));
}
}
if (key == null || key.equals(min_required_accuracy_key)) {
service.setMinRequiredAccuracy(
sharedPreferences.getInt(
min_required_accuracy_key,
MyTracksSettings.DEFAULT_MIN_REQUIRED_ACCURACY));
}
if (key == null || key.equals(announcement_frequency_key)) {
service.setAnnouncementFrequency(
sharedPreferences.getInt(announcement_frequency_key,
-1));
}
if (key == null || key.equals(split_frequency_key)) {
service.getSplitManager().setSplitFrequency(
sharedPreferences.getInt(split_frequency_key, 0));
}
if (key == null || key.equals(signal_sampling_frequency_key)) {
service.getSignalManager().setFrequency(
sharedPreferences.getInt(
signal_sampling_frequency_key, -1), service);
}
if (key == null || key.equals(metric_units_key)) {
service.getSplitManager().setMetricUnits(sharedPreferences.getBoolean(
metric_units_key, true));
}
}
}
@@ -116,10 +116,12 @@ public class StatusAnnouncerTask
boolean metricUnits = true;
boolean reportSpeed = true;
if (preferences != null) {
metricUnits = preferences.getBoolean(MyTracksSettings.METRIC_UNITS,
true);
reportSpeed = preferences.getBoolean(MyTracksSettings.REPORT_SPEED,
true);
metricUnits =
preferences.getBoolean(context.getString(R.string.metric_units_key),
true);
reportSpeed =
preferences.getBoolean(context.getString(R.string.report_speed_key),
true);
}
double d = stats.getTotalDistance() / 1000;
@@ -1,12 +1,12 @@
/*
* 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
@@ -24,6 +24,7 @@ import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.maps.mytracks.R;
@@ -55,7 +56,7 @@ import java.util.TimerTask;
/**
* A background service that registers a location listener and records track
* points. Track points are saved to the MyTracksProvider.
*
*
* @author Leif Hendrik Wilden
*/
public class TrackRecordingService extends Service implements LocationListener {
@@ -67,8 +68,6 @@ public class TrackRecordingService extends Service implements LocationListener {
private LocationManager locationManager;
private WakeLock wakeLock;
private int minRecordingInterval =
MyTracksSettings.DEFAULT_MIN_RECORDING_INTERVAL;
private int minRecordingDistance =
MyTracksSettings.DEFAULT_MIN_RECORDING_DISTANCE;
private int maxRecordingDistance =
@@ -92,8 +91,8 @@ public class TrackRecordingService extends Service implements LocationListener {
*/
private MyTracksProviderUtils providerUtils;
private TripStatistics stats = new TripStatistics();
private TripStatistics waypointStats = new TripStatistics();
private TripStatisticsBuilder statsBuilder = new TripStatisticsBuilder();
private TripStatisticsBuilder waypointStatsBuilder = new TripStatisticsBuilder();
/**
* Current length of the recorded track. This length is calculated from the
@@ -109,8 +108,10 @@ public class TrackRecordingService extends Service implements LocationListener {
private TaskExecuterManager signalManager;
private SplitManager splitManager;
private PreferenceManager prefManager;
/**
* The interval in milliseconds that we have requested to be notfied of gps
* The interval in milliseconds that we have requested to be notified of gps
* readings.
*/
private long currentRecordingInterval = 0;
@@ -125,7 +126,7 @@ public class TrackRecordingService extends Service implements LocationListener {
* Task invoked by a timer periodically to make sure the location listener is
* still registered.
*/
private TimerTask checkLocationListener = new TimerTask() {
private final TimerTask checkLocationListener = new TimerTask() {
@Override
public void run() {
if (!onCreateWasCalled) {
@@ -197,7 +198,7 @@ public class TrackRecordingService extends Service implements LocationListener {
/**
* Inserts a new location in the track points db and updates the corresponding
* track in the track db.
*
*
* @param recordingTrack the track that is currently being recorded
* @param location the location to be inserted
* @param lastRecordedLocation the last recorded location before this one (or
@@ -229,6 +230,7 @@ public class TrackRecordingService extends Service implements LocationListener {
if (lastRecordedLocation != null
&& lastRecordedLocation.getLatitude() < 90) {
ContentValues values = new ContentValues();
TripStatistics stats = statsBuilder.getStatistics();
if (recordingTrack.getStartId() < 0) {
values.put(TracksColumns.STARTID, pointId);
recordingTrack.setStartId(pointId);
@@ -271,10 +273,11 @@ public class TrackRecordingService extends Service implements LocationListener {
private void updateCurrentWaypoint() {
if (currentWaypointId >= 0) {
ContentValues values = new ContentValues();
TripStatistics waypointStats = waypointStatsBuilder.getStatistics();
values.put(WaypointsColumns.STARTTIME, waypointStats.getStartTime());
values.put(WaypointsColumns.LENGTH, length);
values.put(WaypointsColumns.DURATION,
System.currentTimeMillis() - stats.getStartTime());
values.put(WaypointsColumns.DURATION, System.currentTimeMillis()
- statsBuilder.getStatistics().getStartTime());
values.put(WaypointsColumns.TOTALDISTANCE,
waypointStats.getTotalDistance());
values.put(WaypointsColumns.TOTALTIME, waypointStats.getTotalTime());
@@ -397,7 +400,9 @@ public class TrackRecordingService extends Service implements LocationListener {
return;
}
stats = new TripStatistics(track.getStartTime());
TripStatistics stats = track.getStatistics();
statsBuilder = new TripStatisticsBuilder();
statsBuilder.resumeAt(stats.getStartTime());
if (executer != null) {
executer.scheduleTask(announcementFrequency * 60000);
}
@@ -410,10 +415,11 @@ public class TrackRecordingService extends Service implements LocationListener {
Waypoint waypoint = providerUtils.getFirstWaypoint(recordingTrackId);
if (waypoint != null) {
currentWaypointId = waypoint.getId();
waypointStats = new TripStatistics(waypoint);
waypointStatsBuilder = new TripStatisticsBuilder(waypoint.getStatistics());
} else {
// This should never happen, but we got to do something so life goes on:
waypointStats = new TripStatistics(track.getStartTime());
waypointStatsBuilder = new TripStatisticsBuilder();
waypointStatsBuilder.resumeAt(stats.getStartTime());
currentWaypointId = -1;
}
@@ -427,7 +433,7 @@ public class TrackRecordingService extends Service implements LocationListener {
do {
Location location = providerUtils.createLocation(cursor);
if (MyTracksUtils.isValidLocation(location)) {
stats.addLocation(location, location.getTime());
statsBuilder.addLocation(location, location.getTime());
if (lastValidLocation != null) {
length += location.distanceTo(lastValidLocation);
}
@@ -435,9 +441,9 @@ public class TrackRecordingService extends Service implements LocationListener {
}
} while (cursor.moveToPrevious());
}
stats.setMovingTime(track.getMovingTime());
stats.pauseAt(track.getStopTime());
stats.resume();
statsBuilder.getStatistics().setMovingTime(stats.getMovingTime());
statsBuilder.pauseAt(stats.getStopTime());
statsBuilder.resume();
} else {
Log.e(MyTracksConstants.TAG, "Could not get track points cursor.");
}
@@ -469,8 +475,7 @@ public class TrackRecordingService extends Service implements LocationListener {
}
// This should never happen, but just in case (we really don't want the
// service
// to crash):
// service to crash):
if (location == null) {
Log.w(MyTracksConstants.TAG,
"Location changed, but location is null.");
@@ -494,12 +499,12 @@ public class TrackRecordingService extends Service implements LocationListener {
if (MyTracksUtils.isValidLocation(location)) {
long now = System.currentTimeMillis();
stats.addLocation(location, now);
waypointStats.addLocation(location, now);
statsBuilder.addLocation(location, now);
waypointStatsBuilder.addLocation(location, now);
}
// Update the idle time if needed.
locationListenerPolicy.updateIdleTime(stats.getIdleTime());
locationListenerPolicy.updateIdleTime(statsBuilder.getIdleTime());
if (currentRecordingInterval
!= locationListenerPolicy.getDesiredPollingInterval()) {
registerLocationListener();
@@ -553,8 +558,7 @@ public class TrackRecordingService extends Service implements LocationListener {
}
// If separation from last recorded point is too large insert a
// separator
// to indicate end of a segment:
// separator to indicate end of a segment:
boolean startNewSegment =
lastRecordedLocation != null
&& lastRecordedLocation.getLatitude() < 90
@@ -614,7 +618,7 @@ public class TrackRecordingService extends Service implements LocationListener {
*/
/**
* Notifies that preferences have changed.
* Notifies that preferences have changed.
* Call this with key == null to update all preferences in one call.
*
* @param key the key that changed (may be null to update all preferences)
@@ -622,93 +626,7 @@ public class TrackRecordingService extends Service implements LocationListener {
public void onSharedPreferenceChanged(String key) {
Log.d(MyTracksConstants.TAG,
"TrackRecordingService.onSharedPreferenceChanged");
SharedPreferences sharedPreferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (sharedPreferences == null) {
Log.w(MyTracksConstants.TAG,
"TrackRecordingService: Couldn't get shared preferences.");
return;
}
if (key == null || key.equals(MyTracksSettings.MIN_RECORDING_DISTANCE)) {
minRecordingDistance = sharedPreferences.getInt(
MyTracksSettings.MIN_RECORDING_DISTANCE,
MyTracksSettings.DEFAULT_MIN_RECORDING_DISTANCE);
Log.d(MyTracksConstants.TAG,
"TrackRecordingService: minRecordingDistance = "
+ minRecordingDistance);
}
if (key == null || key.equals(MyTracksSettings.MAX_RECORDING_DISTANCE)) {
maxRecordingDistance = sharedPreferences.getInt(
MyTracksSettings.MAX_RECORDING_DISTANCE,
MyTracksSettings.DEFAULT_MAX_RECORDING_DISTANCE);
}
if (key == null || key.equals(MyTracksSettings.MIN_RECORDING_INTERVAL)) {
minRecordingInterval = sharedPreferences.getInt(
MyTracksSettings.MIN_RECORDING_INTERVAL,
MyTracksSettings.DEFAULT_MIN_RECORDING_INTERVAL);
switch (minRecordingInterval) {
case -2:
// Battery Miser
// min: 30 seconds
// max: 5 minutes
// minDist: 5 meters Choose battery life over moving time accuracy.
locationListenerPolicy =
new AdaptiveLocationListenerPolicy(30000, 300000, 5);
break;
case -1:
// High Accuracy
// min: 1 second
// max: 30 seconds
// minDist: 0 meters get all updates to properly measure moving time.
locationListenerPolicy =
new AdaptiveLocationListenerPolicy(1000, 30000, 0);
break;
default:
locationListenerPolicy =
new AbsoluteLocationListenerPolicy(minRecordingInterval * 1000);
}
}
if (key == null || key.equals(MyTracksSettings.MIN_REQUIRED_ACCURACY)) {
minRequiredAccuracy = sharedPreferences.getInt(
MyTracksSettings.MIN_REQUIRED_ACCURACY,
MyTracksSettings.DEFAULT_MIN_REQUIRED_ACCURACY);
}
if (key == null || key.equals(MyTracksSettings.RECORDING_TRACK)) {
recordingTrackId =
sharedPreferences.getLong(MyTracksSettings.RECORDING_TRACK, -1);
}
if (key == null || key.equals(MyTracksSettings.ANNOUNCEMENT_FREQUENCY)) {
announcementFrequency =
sharedPreferences.getInt(MyTracksSettings.ANNOUNCEMENT_FREQUENCY, -1);
if (mTTSAvailable) {
if (announcementFrequency == -1) {
if (executer != null) {
executer.shutdown();
executer = null;
}
} else {
if (executer == null) {
SafeStatusAnnouncerTask announcer =
new SafeStatusAnnouncerTask(this);
executer = new PeriodicTaskExecuter(announcer, this);
}
executer.scheduleTask(announcementFrequency * 60000);
}
}
}
if (key == null || key.equals(MyTracksSettings.SPLIT_FREQUENCY)) {
splitManager.setSplitFrequency(
sharedPreferences.getInt(MyTracksSettings.SPLIT_FREQUENCY, 0));
}
if (key == null || key.equals(MyTracksSettings.SIGNAL_SAMPLING_FREQUENCY)) {
signalManager.setFrequency(sharedPreferences.getInt(
MyTracksSettings.SIGNAL_SAMPLING_FREQUENCY, -1), this);
}
if (key == null || key.equals(MyTracksSettings.METRIC_UNITS)) {
splitManager.setMetricUnits(
sharedPreferences.getBoolean(MyTracksSettings.METRIC_UNITS, true));
}
prefManager.onSharedPreferenceChanged(key);
if (isRecording) {
registerLocationListener();
@@ -724,7 +642,6 @@ public class TrackRecordingService extends Service implements LocationListener {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.onCreate");
super.onCreate();
onCreateWasCalled = true;
setForeground(true);
providerUtils = MyTracksProviderUtils.Factory.get(this);
notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
@@ -742,6 +659,7 @@ public class TrackRecordingService extends Service implements LocationListener {
signalManager =
new TaskExecuterManager(-1, new SignalStrengthTask(this), this);
}
prefManager = new PreferenceManager(this);
onSharedPreferenceChanged(null);
restoreStats();
registerLocationListener();
@@ -798,8 +716,8 @@ public class TrackRecordingService extends Service implements LocationListener {
public long insertWaypointMarker(Waypoint waypoint) {
if (waypoint.getLocation() != null) {
waypoint.setLength(length);
waypoint.setDuration(
waypoint.getLocation().getTime() - stats.getStartTime());
waypoint.setDuration(waypoint.getLocation().getTime()
- statsBuilder.getStatistics().getStartTime());
Uri uri = providerUtils.insertWaypoint(waypoint);
return Long.parseLong(uri.getLastPathSegment());
}
@@ -809,27 +727,40 @@ public class TrackRecordingService extends Service implements LocationListener {
/**
* Inserts a statistics marker. A statistics marker holds the stats for the
* last segment up to this marker.
*
*
* @param location the location where to insert
* @return the unique id of the inserted marker
*/
public long insertStatisticsMarker(Location location) {
StringUtils utils = new StringUtils(TrackRecordingService.this);
// Create a new waypoint to save
Waypoint waypoint = new Waypoint();
// Set stop and total time in the stats data
final long time = System.currentTimeMillis();
waypointStatsBuilder.pauseAt(time);
// Override the duration - it's not the duration from the last waypoint, but
// the duration from the beginning of the whole track
waypoint.setDuration(time - statsBuilder.getStatistics().getStartTime());
// Set the rest of the waypoint data
waypoint.setTrackId(recordingTrackId);
waypoint.setType(Waypoint.TYPE_STATISTICS);
waypoint.setName(TrackRecordingService.this.getString(R.string.statistics));
waypointStats.fillStatisticsForWaypoint(waypoint);
StringUtils utils = new StringUtils(TrackRecordingService.this);
waypoint.setStatistics(waypointStatsBuilder.getStatistics());
waypoint.setDescription(utils.generateWaypointDescription(waypoint));
waypoint.setLocation(location);
waypoint.setIcon(STATISTICS_ICON_URL);
waypoint.setLength(length);
final long time = System.currentTimeMillis();
waypoint.setDuration(time - stats.getStartTime());
waypoint.setStartTime(waypointStats.getStartTime());
waypoint.setStartId(providerUtils.getLastLocationId(recordingTrackId));
Uri uri = providerUtils.insertWaypoint(waypoint);
waypointStats = new TripStatistics(time);
// Create a new stats keeper for the next marker
waypointStatsBuilder = new TripStatisticsBuilder();
waypointStatsBuilder.resumeAt(time);
updateCurrentWaypoint();
return Long.parseLong(uri.getLastPathSegment());
}
@@ -853,13 +784,15 @@ public class TrackRecordingService extends Service implements LocationListener {
public boolean hasRecorded() {
return providerUtils.getLastTrackId() >= 0;
}
@Override
public long startNewTrack() {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.startNewTrack");
Track track = new Track();
TripStatistics trackStats = track.getStatistics();
track.setName("new");
track.setStartTime(System.currentTimeMillis());
long startTime = System.currentTimeMillis();
trackStats.setStartTime(startTime);
track.setStartId(-1);
Uri trackUri = providerUtils.insertTrack(track);
long trackId = Long.parseLong(trackUri.getLastPathSegment());
@@ -870,7 +803,8 @@ public class TrackRecordingService extends Service implements LocationListener {
currentWaypointId = insertStatisticsMarker(null);
isRecording = true;
isMoving = true;
stats = new TripStatistics(track.getStartTime());
statsBuilder = new TripStatisticsBuilder();
statsBuilder.resumeAt(startTime);
if (announcementFrequency != -1 && executer != null) {
executer.scheduleTask(announcementFrequency * 60000);
}
@@ -881,11 +815,11 @@ public class TrackRecordingService extends Service implements LocationListener {
signalManager.restore();
return trackId;
}
/**
* Insert the given waypoint marker. Users can insert waypoint markers
* to tag locations with a name, description, category etc.
*
*
* @param waypoint a waypoint
* @return the unique id of the inserted marker
*/
@@ -893,11 +827,11 @@ public class TrackRecordingService extends Service implements LocationListener {
public long insertWaypointMarker(Waypoint waypoint) {
return TrackRecordingService.this.insertWaypointMarker(waypoint);
}
/**
* Insert a statistics marker. A statistics marker holds the stats for
* the last segment up to this marker.
*
*
* @param location the location where to insert
* @return the unique id of the inserted marker
*/
@@ -905,16 +839,16 @@ public class TrackRecordingService extends Service implements LocationListener {
public long insertStatisticsMarker(Location location) {
return TrackRecordingService.this.insertStatisticsMarker(location);
}
@Override
public void endCurrentTrack() {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.endCurrentTrack");
isRecording = false;
Track recordingTrack = providerUtils.getTrack(recordingTrackId);
if (recordingTrack != null) {
recordingTrack.setStopTime(System.currentTimeMillis());
recordingTrack.setTotalTime(
recordingTrack.getStopTime() - recordingTrack.getStartTime());
TripStatistics stats = recordingTrack.getStatistics();
stats.setStopTime(System.currentTimeMillis());
stats.setTotalTime(stats.getStopTime() - stats.getStartTime());
long lastRecordedLocationId =
providerUtils.getLastLocationId(recordingTrackId);
ContentValues values = new ContentValues();
@@ -922,26 +856,26 @@ public class TrackRecordingService extends Service implements LocationListener {
&& recordingTrack.getStopId() >= 0) {
values.put(TracksColumns.STOPID, lastRecordedLocationId);
}
values.put(TracksColumns.STOPTIME, recordingTrack.getStopTime());
values.put(TracksColumns.TOTALTIME, recordingTrack.getTotalTime());
values.put(TracksColumns.STOPTIME, stats.getStopTime());
values.put(TracksColumns.TOTALTIME, stats.getTotalTime());
getContentResolver().update(TracksColumns.CONTENT_URI, values,
"_id=" + recordingTrack.getId(), null);
}
showNotification();
recordingTrackId = -1;
}
@Override
public void deleteAllTracks() {
endCurrentTrack();
providerUtils.deleteAllTracks();
}
@Override
public void recordLocation(Location loc) {
onLocationChanged(loc);
}
@Override
public void sharedPreferenceChanged(String key) {
Log.d(MyTracksConstants.TAG,
@@ -951,7 +885,7 @@ public class TrackRecordingService extends Service implements LocationListener {
};
TripStatistics getTripStatistics() {
return stats;
return statsBuilder.getStatistics();
}
Location getLastLocation() {
@@ -961,4 +895,68 @@ public class TrackRecordingService extends Service implements LocationListener {
long getRecordingTrackId() {
return recordingTrackId;
}
public int getAnnouncementFrequency() {
return announcementFrequency;
}
public void setAnnouncementFrequency(int announcementFrequency) {
this.announcementFrequency = announcementFrequency;
if (mTTSAvailable) {
if (announcementFrequency == -1) {
if (executer != null) {
executer.shutdown();
executer = null;
}
} else {
if (executer == null) {
SafeStatusAnnouncerTask announcer =
new SafeStatusAnnouncerTask(this);
executer = new PeriodicTaskExecuter(announcer, this);
}
executer.scheduleTask(announcementFrequency * 60000);
}
}
}
public int getMaxRecordingDistance() {
return maxRecordingDistance;
}
public void setMaxRecordingDistance(int maxRecordingDistance) {
this.maxRecordingDistance = maxRecordingDistance;
}
public int getMinRecordingDistance() {
return minRecordingDistance;
}
public void setMinRecordingDistance(int minRecordingDistance) {
this.minRecordingDistance = minRecordingDistance;
}
public int getMinRequiredAccuracy() {
return minRequiredAccuracy;
}
public void setMinRequiredAccuracy(int minRequiredAccuracy) {
this.minRequiredAccuracy = minRequiredAccuracy;
}
public LocationListenerPolicy getLocationListenerPolicy() {
return locationListenerPolicy;
}
public void setLocationListenerPolicy(
LocationListenerPolicy locationListenerPolicy) {
this.locationListenerPolicy = locationListenerPolicy;
}
public SplitManager getSplitManager() {
return splitManager;
}
public TaskExecuterManager getSignalManager() {
return signalManager;
}
}
View File
@@ -84,10 +84,23 @@ public class ExtremityMonitor {
/**
* Sets the minimum and maximum values.
* Useful when restoring state.
*/
public void set(double min, double max) {
this.min = min;
this.max = max;
}
/**
* Sets the minimum value.
*/
public void setMin(double min) {
this.min = min;
}
/**
* Sets the maximum value.
*/
public void setMax(double max) {
this.max = max;
}
}
@@ -1,2 +1,2 @@
package com.google.android.apps.mytracks.stats;
parcelable TripStatisticsData;
parcelable TripStatistics;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,371 @@
/*
* Copyright 2009 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.stats;
import com.google.android.apps.mytracks.MyTracksConstants;
import android.location.Location;
import android.util.Log;
/**
* Statistics keeper for a trip.
*
* @author Sandor Dornbush
* @author Rodrigo Damazio
*/
public class TripStatisticsBuilder {
/**
* Statistical data about the trip, which can be displayed to the user.
*/
private final TripStatistics data;
/**
* The last location that the gps reported.
*/
private Location lastLocation = null;
/**
* The last location that contributed to the stats. It is also the last
* location the user was found to be moving.
*/
private Location lastMovingLocation = null;
/**
* The current speed in meters/second as reported by the gps.
*/
private double currentSpeed;
/**
* The current grade. This value is very noisy and not reported to the user.
*/
private double currentGrade;
/**
* Is the trip currently paused?
* All trips start paused.
*/
private boolean paused = true;
/**
* A buffer of the last speed readings in meters/second.
*/
private final DoubleBuffer speedBuffer =
new DoubleBuffer(MyTracksConstants.SPEED_SMOOTHING_FACTOR);
/**
* A buffer of the recent elevation readings in meters.
*/
private final DoubleBuffer elevationBuffer =
new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
/**
* A buffer of the distance between recent gps readings in meters.
*/
private final DoubleBuffer distanceBuffer =
new DoubleBuffer(MyTracksConstants.DISTANCE_SMOOTHING_FACTOR);
/**
* A buffer of the recent grade calculations.
*/
private final DoubleBuffer gradeBuffer =
new DoubleBuffer(MyTracksConstants.GRADE_SMOOTHING_FACTOR);
/**
* The total number of locations in this trip.
*/
private long totalLocations = 0;
/**
* Creates a new trip starting at the current system time.
*/
public TripStatisticsBuilder() {
data = new TripStatistics();
}
/**
* Creates a new trip, starting with existing statistics data.
*
* @param statsData the statistics data to copy and start from
*/
public TripStatisticsBuilder(TripStatistics statsData) {
data = new TripStatistics(statsData);
}
/**
* Adds a location to the current trip. This will update all of the internal
* variables with this new location.
*
* @param currentLocation the current gps location
* @param systemTime the time used for calculation of totalTime. This should
* be the phone's time (not GPS time)
* @return true if the person is moving
*/
public boolean addLocation(Location currentLocation, long systemTime) {
if (paused) {
Log.w(MyTracksConstants.TAG,
"Tried to account for location while track is paused");
return false;
}
totalLocations++;
double elevationDifference = updateElevation(currentLocation.getAltitude());
// Update the "instant" values:
data.setTotalTime(systemTime - data.getStartTime());
currentSpeed = currentLocation.getSpeed();
// This was the 1st location added, remember it and do nothing else:
if (lastLocation == null) {
lastLocation = currentLocation;
lastMovingLocation = currentLocation;
return false;
}
updateBounds(currentLocation);
// Don't do anything if we didn't move since last fix:
double distance = lastLocation.distanceTo(currentLocation);
if (distance < MyTracksConstants.MAX_NO_MOVEMENT_DISTANCE
&& currentSpeed < MyTracksConstants.MAX_NO_MOVEMENT_SPEED) {
lastLocation = currentLocation;
return false;
}
data.addTotalDistance(lastMovingLocation.distanceTo(currentLocation));
updateSpeed(currentLocation.getTime(), currentSpeed,
lastLocation.getTime(), lastLocation.getSpeed());
updateGrade(distance, elevationDifference);
lastLocation = currentLocation;
lastMovingLocation = currentLocation;
return true;
}
/**
* Updates the track's bounding box to include the given location.
*/
private void updateBounds(Location location) {
data.updateLatitudeExtremities(location.getLatitude());
data.updateLongitudeExtremities(location.getLongitude());
}
/**
* Updates the elevation measurements.
*
* @param elevation the current elevation
*/
// @VisibleForTesting
double updateElevation(double elevation) {
double oldSmoothedElevation = getSmoothedElevation();
elevationBuffer.setNext(elevation);
double smoothedElevation = getSmoothedElevation();
data.updateElevationExtremities(smoothedElevation);
double elevationDifference = elevationBuffer.isFull()
? smoothedElevation - oldSmoothedElevation
: 0.0;
if (elevationDifference > 0) {
data.addTotalElevationGain(elevationDifference);
}
return elevationDifference;
}
/**
* Updates the speed measurements.
*
* @param updateTime the time of the speed update
* @param speed the current speed
* @param lastLocationTime the time of the last speed update
* @param lastLocationSpeed the speed of the last update
*/
// @VisibleForTesting
void updateSpeed(long updateTime, double speed, long lastLocationTime,
double lastLocationSpeed) {
// We are now sure the user is moving.
long timeDifference = updateTime - lastLocationTime;
if (timeDifference < 0) {
Log.e(MyTracksConstants.TAG,
"Found negative time change: " + timeDifference);
}
data.addMovingTime(timeDifference);
if (isValidSpeed(updateTime, speed, lastLocationTime, lastLocationSpeed,
speedBuffer)) {
speedBuffer.setNext(speed);
if (speed > data.getMaxSpeed()) {
data.setMaxSpeed(speed);
}
double movingSpeed = data.getAverageMovingSpeed();
if (speedBuffer.isFull() && (movingSpeed > data.getMaxSpeed())) {
data.setMaxSpeed(movingSpeed);
}
} else {
Log.d(MyTracksConstants.TAG,
"TripStatistics ignoring big change: Raw Speed: " + speed
+ " old: " + lastLocationSpeed + " [" + toString() + "]");
}
}
/**
* Checks to see if this is a valid speed.
*
* @param updateTime The time at the current reading
* @param speed The current speed
* @param lastLocationTime The time at the last location
* @param lastLocationSpeed Speed at the last location
* @param speedBuffer A buffer of recent readings
* @return True if this is likely a valid speed
*/
public static boolean isValidSpeed(long updateTime, double speed,
long lastLocationTime, double lastLocationSpeed,
DoubleBuffer speedBuffer) {
// We don't want to count 0 towards the speed.
if (speed == 0) {
return false;
}
// We are now sure the user is moving.
long timeDifference = updateTime - lastLocationTime;
// There are a lot of noisy speed readings.
// Do the cheapest checks first, most expensive last.
// The following code will ignore unlikely to be real readings.
// - 128 m/s seems to be an internal android error code.
if (Math.abs(speed - 128) < 1) {
return false;
}
// Another check for a spurious reading. See if the path seems physically
// likely. Ignore any speeds that imply accelaration greater than 2g's
// Really who can accelerate faster?
double speedDifference = Math.abs(lastLocationSpeed - speed);
if (speedDifference > MyTracksConstants.MAX_ACCELERATION * timeDifference) {
return false;
}
// There are three additional checks if the reading gets this far:
// - Only use the speed if the buffer is full
// - Check that the current speed is less than 10x the recent smoothed speed
// - Double check that the current speed does not imply crazy acceleration
double smoothedSpeed = speedBuffer.getAverage();
double smoothedDiff = Math.abs(smoothedSpeed - speed);
return !speedBuffer.isFull() ||
(speed < smoothedSpeed * 10
&& smoothedDiff < MyTracksConstants.MAX_ACCELERATION * timeDifference);
}
/**
* Updates the grade measurements.
*
* @param distance the distance the user just traveled
* @param elevationDifference the elevation difference between the current
* reading and the previous reading
*/
// @VisibleForTesting
void updateGrade(double distance, double elevationDifference) {
distanceBuffer.setNext(distance);
double smoothedDistance = distanceBuffer.getAverage();
// With the error in the altitude measurement it is dangerous to divide
// by anything less than 5.
if (!elevationBuffer.isFull() || !distanceBuffer.isFull()
|| smoothedDistance < 5.0) {
return;
}
currentGrade = elevationDifference / smoothedDistance;
gradeBuffer.setNext(currentGrade);
data.updateGradeExtremities(gradeBuffer.getAverage());
}
/**
* Pauses the track at the current time.
*/
public void pause() {
pauseAt(System.currentTimeMillis());
}
/**
* Pauses the track at the given time.
*
* @param time the time to pause at
*/
public void pauseAt(long time) {
if (paused) { return; }
data.setStopTime(time);
data.setTotalTime(time - data.getStartTime());
lastLocation = null; // Make sure the counter restarts.
paused = true;
}
/**
* Resumes the current track at the current time.
*/
public void resume() {
resumeAt(System.currentTimeMillis());
}
/**
* Resumes the current track at the given time.
*
* @param time the time to resume at
*/
public void resumeAt(long time) {
if (!paused) { return; }
// TODO: The times are bogus if the track is paused then resumed again
data.setStartTime(time);
data.setStopTime(-1);
paused = false;
}
@Override
public String toString() {
return "TripStatistics { Data: " + data.toString()
+ "; Total Locations: " + totalLocations
+ "; Paused: " + paused
+ "; Current speed: " + currentSpeed
+ "; Current grade: " + currentGrade
+ "}";
}
/**
* Returns the amount of time the user has been idle or 0 if they are moving.
*/
public long getIdleTime() {
if (lastLocation == null || lastMovingLocation == null)
return 0;
return lastLocation.getTime() - lastMovingLocation.getTime();
}
/**
* Gets the current elevation smoothed over several readings. The elevation
* data is very noisy so it is better to use the smoothed elevation than the
* raw elevation for many tasks.
*
* @return The elevation smoothed over several readings
*/
public double getSmoothedElevation() {
return elevationBuffer.getAverage();
}
public TripStatistics getStatistics() {
// Take a snapshot - we do't want anyone messing with our internals
return new TripStatistics(data);
}
}
@@ -1,309 +0,0 @@
/*
* 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.
*/
package com.google.android.apps.mytracks.stats;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Statistical data about a trip.
* The data in this class should be filled out by {@link TripStatistics}.
*
* TODO: Remove delegate methods from TripStatistics
* (detail is getTotalTime)
* TODO: Make Waypoint and Track use this instead of having the same fields
*
* @author Rodrigo Damazio
*/
public class TripStatisticsData implements Parcelable {
/**
* The start time for the trip. This is system time which might not match gps
* time.
*/
long startTime;
/**
* The total time that we believe the user was traveling in milliseconds.
*/
long movingTime;
/**
* The total time of the trip in milliseconds.
* This is only updated when new points are received, so it may be stale.
*/
long totalTime;
/**
* The total distance in meters that the user traveled on this trip.
*/
double totalDistance;
/**
* The total elevation gained on this trip in meters.
*/
double totalElevationGain;
/**
* The maximum speed in meters/second reported that we believe to be a valid
* speed.
*/
double maxSpeed;
/**
* The current speed in meters/second as reported by the gps.
*/
double currentSpeed;
/**
* The current grade. This value is very noisy and not reported to the user.
*/
double currentGrade;
/**
* The min and max latitude values seen in this trip.
*/
final ExtremityMonitor latitudeExtremities = new ExtremityMonitor();
/**
* The min and max longitude values seen in this trip.
*/
final ExtremityMonitor longitudeExtremities = new ExtremityMonitor();
/**
* The min and max elevation seen on this trip in meters.
*/
final ExtremityMonitor elevationExtremities = new ExtremityMonitor();
/**
* The minimum and maximum grade calculations on this trip.
*/
final ExtremityMonitor gradeExtremities = new ExtremityMonitor();
/**
* Gets the time that this track started.
*
* @return The number of milliseconds since epoch to the time when this track
* started
*/
public long getStartTime() {
return startTime;
}
/**
* Gets the total time that this track has been active.
*
* @return The total number of milliseconds the track was active
*/
public long getTotalTime() {
return totalTime;
}
/**
* Gets the total distance the user traveled.
*
* @return The total distance traveled in meters
*/
public double getTotalDistance() {
return totalDistance;
}
/**
* Gets the the maximum speed for this track.
*
* @return The maximum speed in m/s.
*/
public double getMaxSpeed() {
return maxSpeed;
}
/**
* Gets the the current speed for this track.
*
* @return The current speed in m/s
*/
public double getCurrentSpeed() {
return currentSpeed;
}
/**
* Gets the moving time.
*
* @return The total number of milliseconds the user was moving
*/
public long getMovingTime() {
return movingTime;
}
/**
* Gets the total elevation gain for this trip. This is calculated as the sum
* of all positive differences in the smoothed elevation.
*
* @return The elevation gain in meters for this trip
*/
public double getTotalElevationGain() {
return totalElevationGain;
}
/**
* Gets the current grade.
*
* @return The current grade
*/
public double getCurrentGrade() {
return currentGrade;
}
/**
* Returns the leftmost position (lowest longitude) of the track.
*/
public int getLeft() {
return (int) (longitudeExtremities.getMin() * 1E6);
}
/**
* Returns the rightmost position (highest longitude) of the track.
*/
public int getRight() {
return (int) (longitudeExtremities.getMax() * 1E6);
}
/**
* Returns the bottommost position (lowest latitude) of the track.
*/
public int getBottom() {
return (int) (latitudeExtremities.getMin() * 1E6);
}
/**
* Returns the topmost position (highest latitude) of the track.
*/
public int getTop() {
return (int) (latitudeExtremities.getMax() * 1E6);
}
/**
* Gets the minimum elevation seen on this trip. This is calculated from the
* smoothed elevation so this can actually be more than the current elevation.
*
* @return The smallest elevation reading for this trip
*/
public double getMinElevation() {
return elevationExtremities.getMin();
}
/**
* Gets the maximum elevation seen on this trip. This is calculated from the
* smoothed elevation so this can actually be less than the current elevation.
*
* @return The largest elevation reading for this trip
*/
public double getMaxElevation() {
return elevationExtremities.getMax();
}
/**
* Gets the maximum grade for this trip.
*
* @return The maximum grade for this trip
*/
public double getMaxGrade() {
return gradeExtremities.getMax();
}
/**
* Gets the minimum grade for this trip.
*
* @return The minimum grade for this trip
*/
public double getMinGrade() {
return gradeExtremities.getMin();
}
// Parcelable interface and creator
/**
* Creator of statistics data from parcels.
*/
public static class Creator
implements Parcelable.Creator<TripStatisticsData> {
@Override
public TripStatisticsData createFromParcel(Parcel source) {
TripStatisticsData data = new TripStatisticsData();
data.startTime = source.readLong();
data.movingTime = source.readLong();
data.totalTime = source.readLong();
data.totalDistance = source.readDouble();
data.totalElevationGain = source.readDouble();
data.maxSpeed = source.readDouble();
data.currentSpeed = source.readDouble();
data.currentGrade = source.readDouble();
double minLat = source.readDouble();
double maxLat = source.readDouble();
data.latitudeExtremities.set(minLat, maxLat);
double minLong = source.readDouble();
double maxLong = source.readDouble();
data.longitudeExtremities.set(minLong, maxLong);
double minElev = source.readDouble();
double maxElev = source.readDouble();
data.elevationExtremities.set(minElev, maxElev);
double minGrade = source.readDouble();
double maxGrade = source.readDouble();
data.gradeExtremities.set(minGrade, maxGrade);
return data;
}
@Override
public TripStatisticsData[] newArray(int size) {
return new TripStatisticsData[size];
}
}
public static final Creator CREATOR = new Creator();
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(startTime);
dest.writeLong(movingTime);
dest.writeLong(totalTime);
dest.writeDouble(totalDistance);
dest.writeDouble(totalElevationGain);
dest.writeDouble(maxSpeed);
dest.writeDouble(currentSpeed);
dest.writeDouble(currentGrade);
dest.writeDouble(latitudeExtremities.getMin());
dest.writeDouble(latitudeExtremities.getMax());
dest.writeDouble(longitudeExtremities.getMin());
dest.writeDouble(longitudeExtremities.getMax());
dest.writeDouble(elevationExtremities.getMin());
dest.writeDouble(elevationExtremities.getMax());
dest.writeDouble(gradeExtremities.getMin());
dest.writeDouble(gradeExtremities.getMax());
}
}
@@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.mytracks.R;
import android.content.Context;
@@ -52,7 +53,8 @@ public class ChartURLGenerator {
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
boolean metricUnits = true;
if (preferences != null) {
metricUnits = preferences.getBoolean(MyTracksSettings.METRIC_UNITS, true);
metricUnits = preferences.getBoolean(
context.getString(R.string.metric_units_key), true);
}
return getChartUrl(distances, elevations, track,
@@ -82,18 +84,19 @@ public class ChartURLGenerator {
}
// Round it up.
TripStatistics stats = track.getStatistics();
double effectiveMaxY = metricUnits
? track.getMaxElevation()
: track.getMaxElevation() * UnitConversions.M_TO_FT;
? stats.getMaxElevation()
: stats.getMaxElevation() * UnitConversions.M_TO_FT;
effectiveMaxY = ((int) (effectiveMaxY / 100)) * 100 + 100;
// Round it down.
double effectiveMinY = 0;
double minElevation = metricUnits
? track.getMinElevation()
: track.getMinElevation() * UnitConversions.M_TO_FT;
? stats.getMinElevation()
: stats.getMinElevation() * UnitConversions.M_TO_FT;
effectiveMinY = ((int) (minElevation / 100)) * 100;
if (track.getMinElevation() < 0) {
if (stats.getMinElevation() < 0) {
effectiveMinY -= 100;
}
double ySpread = effectiveMaxY - effectiveMinY;
@@ -108,7 +111,7 @@ public class ChartURLGenerator {
// Labels
sb.append("&chxt=x,y");
double distKM = track.getTotalDistance() / 1000.0;
double distKM = stats.getTotalDistance() / 1000.0;
double distDisplay =
metricUnits ? distKM : (distKM * UnitConversions.KM_TO_MI);
int xInterval = ((int) (distDisplay / 6));
@@ -162,11 +165,11 @@ public class ChartURLGenerator {
return sb.toString();
}
protected static double getNormalizedDistance(double d, Track track) {
return d / track.getTotalDistance();
private static double getNormalizedDistance(double d, Track track) {
return d / track.getStatistics().getTotalDistance();
}
protected static double getNormalizedElevation(
private static double getNormalizedElevation(
double d, double effectiveMinY, double ySpread) {
return (d - effectiveMinY) / ySpread;
}
@@ -17,6 +17,7 @@ package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.MyTracksConstants;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.GeoPoint;
@@ -181,6 +182,7 @@ public class MyTracksUtils {
Track piece = null;
do {
piece = new Track();
TripStatistics pieceStats = piece.getStatistics();
piece.setId(track.getId());
piece.setName(track.getName());
piece.setDescription(track.getDescription());
@@ -191,8 +193,8 @@ public class MyTracksUtils {
}
int nPointsPiece = pieceLocations.size();
if (nPointsPiece >= 2) {
piece.setStartTime(pieceLocations.get(0).getTime());
piece.setStopTime(pieceLocations.get(nPointsPiece - 1).getTime());
pieceStats.setStartTime(pieceLocations.get(0).getTime());
pieceStats.setStopTime(pieceLocations.get(nPointsPiece - 1).getTime());
result.add(piece);
}
n += (pieceLocations.size() - 1);
@@ -19,6 +19,7 @@ import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.DescriptionGenerator;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.mytracks.R;
import android.content.Context;
@@ -172,26 +173,27 @@ public class StringUtils implements DescriptionGenerator {
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (preferences != null) {
displaySpeed =
preferences.getBoolean(MyTracksSettings.REPORT_SPEED, true);
preferences.getBoolean(context.getString(R.string.report_speed_key), true);
}
final double distanceInKm = track.getTotalDistance() / 1000;
TripStatistics trackStats = track.getStatistics();
final double distanceInKm = trackStats.getTotalDistance() / 1000;
final double distanceInMiles = distanceInKm * UnitConversions.KM_TO_MI;
final long minElevationInMeters = Math.round(track.getMinElevation());
final long minElevationInMeters = Math.round(trackStats.getMinElevation());
final long minElevationInFeet =
Math.round(track.getMinElevation() * UnitConversions.M_TO_FT);
final long maxElevationInMeters = Math.round(track.getMaxElevation());
Math.round(trackStats.getMinElevation() * UnitConversions.M_TO_FT);
final long maxElevationInMeters = Math.round(trackStats.getMaxElevation());
final long maxElevationInFeet =
Math.round(track.getMaxElevation() * UnitConversions.M_TO_FT);
Math.round(trackStats.getMaxElevation() * UnitConversions.M_TO_FT);
final long elevationGainInMeters =
Math.round(track.getTotalElevationGain());
final long elevationGainInFeet =
Math.round(track.getTotalElevationGain() * UnitConversions.M_TO_FT);
Math.round(trackStats.getTotalElevationGain());
final long elevationGainInFeet = Math.round(
trackStats.getTotalElevationGain() * UnitConversions.M_TO_FT);
long minGrade = 0;
long maxGrade = 0;
double trackMaxGrade = track.getMaxGrade();
double trackMinGrade = track.getMinGrade();
double trackMaxGrade = trackStats.getMaxGrade();
double trackMinGrade = trackStats.getMinGrade();
if (!Double.isNaN(trackMaxGrade)
&& !Double.isInfinite(trackMaxGrade)) {
maxGrade = Math.round(trackMaxGrade * 100);
@@ -207,19 +209,19 @@ public class StringUtils implements DescriptionGenerator {
}
String averageSpeed =
getSpeedString(track.getAverageSpeed(),
getSpeedString(trackStats.getAverageSpeed(),
R.string.average_speed_label,
R.string.average_pace_label,
displaySpeed);
String averageMovingSpeed =
getSpeedString(track.getAverageMovingSpeed(),
getSpeedString(trackStats.getAverageMovingSpeed(),
R.string.average_moving_speed_label,
R.string.average_moving_pace_label,
displaySpeed);
String maxSpeed =
getSpeedString(track.getMaxSpeed(),
getSpeedString(trackStats.getMaxSpeed(),
R.string.max_speed_label,
R.string.min_pace_label,
displaySpeed);
@@ -248,11 +250,11 @@ public class StringUtils implements DescriptionGenerator {
// Line 3
context.getString(R.string.total_time_label),
StringUtils.formatTime(track.getTotalTime()),
StringUtils.formatTime(trackStats.getTotalTime()),
// Line 4
context.getString(R.string.moving_time_label),
StringUtils.formatTime(track.getMovingTime()),
StringUtils.formatTime(trackStats.getMovingTime()),
// Line 5
averageSpeed, averageMovingSpeed, maxSpeed,
@@ -280,7 +282,7 @@ public class StringUtils implements DescriptionGenerator {
// Line 11
context.getString(R.string.recorded_date),
new Date(track.getStartTime()),
new Date(trackStats.getStartTime()),
// Line 12
context.getString(R.string.category), category,
@@ -322,35 +324,39 @@ public class StringUtils implements DescriptionGenerator {
* @return a track description
*/
public String generateWaypointDescription(Waypoint waypoint) {
final double distanceInKm = waypoint.getTotalDistance() / 1000;
TripStatistics stats = waypoint.getStatistics();
final double distanceInKm = stats.getTotalDistance() / 1000;
final double distanceInMiles = distanceInKm * UnitConversions.KM_TO_MI;
final double averageSpeedInKmh = waypoint.getAverageSpeed() * 3.6;
final double averageSpeedInKmh = stats.getAverageSpeed() * 3.6;
final double averageSpeedInMph =
averageSpeedInKmh * UnitConversions.KMH_TO_MPH;
final double movingSpeedInKmh = waypoint.getAverageMovingSpeed() * 3.6;
final double movingSpeedInKmh = stats.getAverageMovingSpeed() * 3.6;
final double movingSpeedInMph =
movingSpeedInKmh * UnitConversions.KMH_TO_MPH;
final double maxSpeedInKmh = waypoint.getMaxSpeed() * 3.6;
final double maxSpeedInKmh = stats.getMaxSpeed() * 3.6;
final double maxSpeedInMph = maxSpeedInKmh * UnitConversions.KMH_TO_MPH;
final long minElevationInMeters = Math.round(waypoint.getMinElevation());
final long minElevationInMeters = Math.round(stats.getMinElevation());
final long minElevationInFeet =
Math.round(waypoint.getMinElevation() * UnitConversions.M_TO_FT);
final long maxElevationInMeters = Math.round(waypoint.getMaxElevation());
Math.round(stats.getMinElevation() * UnitConversions.M_TO_FT);
final long maxElevationInMeters = Math.round(stats.getMaxElevation());
final long maxElevationInFeet =
Math.round(waypoint.getMaxElevation() * UnitConversions.M_TO_FT);
Math.round(stats.getMaxElevation() * UnitConversions.M_TO_FT);
final long elevationGainInMeters =
Math.round(waypoint.getTotalElevationGain());
final long elevationGainInFeet = Math.round(waypoint.getTotalElevationGain()
* UnitConversions.M_TO_FT);
Math.round(stats.getTotalElevationGain());
final long elevationGainInFeet = Math.round(
stats.getTotalElevationGain() * UnitConversions.M_TO_FT);
long theMinGrade = 0;
long theMaxGrade = 0;
if (!Double.isNaN(waypoint.getMaxGrade()) &&
!Double.isInfinite(waypoint.getMaxGrade())) {
theMaxGrade = Math.round(waypoint.getMaxGrade() * 100);
double maxGrade = stats.getMaxGrade();
double minGrade = stats.getMinGrade();
if (!Double.isNaN(maxGrade) &&
!Double.isInfinite(maxGrade)) {
theMaxGrade = Math.round(maxGrade * 100);
}
if (!Double.isNaN(waypoint.getMinGrade()) &&
!Double.isInfinite(waypoint.getMinGrade())) {
theMinGrade = Math.round(waypoint.getMinGrade() * 100);
if (!Double.isNaN(minGrade) &&
!Double.isInfinite(minGrade)) {
theMinGrade = Math.round(minGrade * 100);
}
final String percent = "%";
@@ -370,9 +376,9 @@ public class StringUtils implements DescriptionGenerator {
distanceInKm, context.getString(R.string.kilometer),
distanceInMiles, context.getString(R.string.mile),
context.getString(R.string.time_label),
StringUtils.formatTime(waypoint.getTotalTime()),
StringUtils.formatTime(stats.getTotalTime()),
context.getString(R.string.moving_time_label),
StringUtils.formatTime(waypoint.getMovingTime()),
StringUtils.formatTime(stats.getMovingTime()),
context.getString(R.string.average_speed_label),
averageSpeedInKmh, context.getString(R.string.kilometer_per_hour),
averageSpeedInMph, context.getString(R.string.mile_per_hour),
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry combineaccessrules="false" kind="src" path="/MyTracks"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="lib" path="libs/AndroidMockRuntime.jar"/>
<classpathentry kind="src" path=".apt_generated">
<attributes>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>
+4
View File
@@ -0,0 +1,4 @@
<factorypath>
<factorypathentry kind="PLUGIN" id="org.eclipse.jst.ws.annotations.core" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="WKSPJAR" id="/MyTracksTest/libs/AndroidMockGenerator.jar" enabled="true" runInBatchMode="false"/>
</factorypath>
+34
View File
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MyTracksTest</name>
<comment></comment>
<projects>
<project>MyTracks</project>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -0,0 +1,7 @@
#Thu Aug 12 19:30:48 BRT 2010
eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=true
org.eclipse.jdt.apt.genSrcDir=.apt_generated
org.eclipse.jdt.apt.processorOptions/bin_dir=MyTracksTest/bin
org.eclipse.jdt.apt.processorOptions/logfile=MyTracksTest/annotations.log
org.eclipse.jdt.apt.reconcileEnabled=false
@@ -0,0 +1,13 @@
#Thu Aug 12 19:30:48 BRT 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.processAnnotations=enabled
org.eclipse.jdt.core.compiler.source=1.6
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.maps.mytracks.test"
android:versionCode="1"
android:versionName="1.0"
android:debuggable="true">
<application android:icon="@android:drawable/sym_def_app_icon"
android:label="My Tracks Tests">
<uses-library android:name="android.test.runner" />
</application>
<uses-sdk android:minSdkVersion="3" />
<instrumentation android:targetPackage="com.google.android.maps.mytracks"
android:name="android.test.InstrumentationTestRunner" />
</manifest>
+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.android.ide.eclipse.adt.junit.launchConfigurationType">
<stringAttribute key="com.android.ide.eclipse.adt.commandline" value=""/>
<intAttribute key="com.android.ide.eclipse.adt.delay" value="0"/>
<stringAttribute key="com.android.ide.eclipse.adt.instrumentation" value="android.test.InstrumentationTestRunner"/>
<booleanAttribute key="com.android.ide.eclipse.adt.nobootanim" value="true"/>
<intAttribute key="com.android.ide.eclipse.adt.speed" value="0"/>
<booleanAttribute key="com.android.ide.eclipse.adt.target" value="true"/>
<booleanAttribute key="com.android.ide.eclipse.adt.wipedata" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/MyTracksTests"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=MyTracksTests"/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="MyTracksTests"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value=""/>
</launchConfiguration>
+13
View File
@@ -0,0 +1,13 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
target=Google Inc.:Google APIs:8
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,258 @@
/*
* 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.
*/
package com.google.android.apps.mytracks.io;
import static com.google.android.testing.mocking.AndroidMock.eq;
import static com.google.android.testing.mocking.AndroidMock.expect;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
import android.content.ContentUris;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.test.AndroidTestCase;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import javax.xml.parsers.ParserConfigurationException;
import org.easymock.Capture;
import org.easymock.IArgumentMatcher;
import org.xml.sax.SAXException;
/**
* Tests for the GPX importer.
*
* @author Steffen Horlacher
*/
public class GpxImporterTest extends AndroidTestCase {
private static final String TRACK_NAME = "blablub";
private static final String TRACK_DESC = "s'Laebe isch koi Schlotzer";
private static final String TRACK_LAT_1 = "48.768364";
private static final String TRACK_LON_1 = "9.177886";
private static final String TRACK_ELE_1 = "324.0";
private static final String TRACK_TIME_1 = "2010-04-22T18:21:00Z";
private static final String TRACK_LAT_2 = "48.768374";
private static final String TRACK_LON_2 = "9.177816";
private static final String TRACK_ELE_2 = "333.0";
private static final String TRACK_TIME_2 = "2010-04-22T18:21:50Z";
// TODO use real files from different sources with more track points
private static final String VALID_TEST_GPX = "<gpx><trk><name><![CDATA["
+ TRACK_NAME + "]]></name><desc><![CDATA[" + TRACK_DESC
+ "]]></desc><trkseg>" + "<trkpt lat=\"" + TRACK_LAT_1 + "\" lon=\""
+ TRACK_LON_1 + "\"><ele>" + TRACK_ELE_1 + "</ele><time>" + TRACK_TIME_1
+ "</time></trkpt> +" + "<trkpt lat=\"" + TRACK_LAT_2 + "\" lon=\""
+ TRACK_LON_2 + "\"><ele>" + TRACK_ELE_2 + "</ele><time>" + TRACK_TIME_2
+ "</time></trkpt>" + "</trkseg></trk></gpx>";
// invalid xml
private static final String INVALID_XML_TEST_GPX = VALID_TEST_GPX.substring(
0, VALID_TEST_GPX.length() - 50);
private static final String INVALID_LOCATION_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_LAT_1, "1000.0");
private static final String INVALID_TIME_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_TIME_1, "invalid");
private static final long TRACK_ID = 1;
private static final long TRACK_POINT_ID_1 = 1;
private static final long TRACK_POINT_ID_2 = 2;
private static final Uri TRACK_ID_URI = ContentUris.appendId(
TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID).build();
private MyTracksProviderUtils providerUtils;
private Factory oldProviderUtilsFactory;
@UsesMocks(MyTracksProviderUtils.class)
@Override
protected void setUp() throws Exception {
super.setUp();
providerUtils = AndroidMock.createMock(MyTracksProviderUtils.class);
oldProviderUtilsFactory =
TestingProviderUtilsFactory.installWithInstance(providerUtils);
}
@Override
protected void tearDown() throws Exception {
TestingProviderUtilsFactory.restoreOldFactory(oldProviderUtilsFactory);
super.tearDown();
}
/**
* Test import success
*/
public void testImportSuccess() throws Exception {
Capture<Track> trackParam = new Capture<Track>();
SimpleDateFormat format = GpxImporter.DATE_FORMAT2;
Location loc1 = new Location(LocationManager.GPS_PROVIDER);
loc1.setTime(format.parse(TRACK_TIME_1).getTime());
loc1.setLatitude(Double.parseDouble(TRACK_LAT_1));
loc1.setLongitude(Double.parseDouble(TRACK_LON_1));
loc1.setAltitude(Double.parseDouble(TRACK_ELE_1));
Location loc2 = new Location(LocationManager.GPS_PROVIDER);
loc2.setTime(format.parse(TRACK_TIME_2).getTime());
loc2.setLatitude(Double.parseDouble(TRACK_LAT_2));
loc2.setLongitude(Double.parseDouble(TRACK_LON_2));
loc2.setAltitude(Double.parseDouble(TRACK_ELE_2));
expect(providerUtils.insertTrack(AndroidMock.capture(trackParam)))
.andReturn(TRACK_ID_URI);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(TRACK_POINT_ID_1).andReturn(TRACK_POINT_ID_2);
// A flush happens after the first insertion to get the starting point ID,
// which is why we get two calls
expect(providerUtils.bulkInsertTrackPoints(LocationsMatcher.eqLoc(loc1),
eq(1), eq(TRACK_ID))).andReturn(1);
expect(providerUtils.bulkInsertTrackPoints(LocationsMatcher.eqLoc(loc2),
eq(1), eq(TRACK_ID))).andReturn(1);
providerUtils.updateTrack(AndroidMock.capture(trackParam));
AndroidMock.replay(providerUtils);
InputStream is = new ByteArrayInputStream(VALID_TEST_GPX.getBytes());
GpxImporter.importGPXFile(is, providerUtils);
AndroidMock.verify(providerUtils);
// verify track parameter
Track track = trackParam.getValue();
assertEquals(TRACK_NAME, track.getName());
assertEquals(TRACK_DESC, track.getDescription());
assertEquals(format.parse(TRACK_TIME_1).getTime(), track.getStatistics()
.getStartTime());
assertNotSame(-1, track.getStartId());
assertNotSame(-1, track.getStopId());
}
/**
* Test with invalid location - track should be deleted
*/
public void testImportLocationFailure() throws ParserConfigurationException,
SAXException, IOException {
testInvalidXML(INVALID_LOCATION_TEST_GPX);
}
/**
* Test with invalid time - track should be deleted
*/
public void testImportTimeFailure() throws ParserConfigurationException,
SAXException, IOException {
testInvalidXML(INVALID_TIME_TEST_GPX);
}
/**
* Test with invalid xml - track should be deleted
*/
public void testImportXMLFailure() throws ParserConfigurationException,
SAXException, IOException {
testInvalidXML(INVALID_XML_TEST_GPX);
}
private void testInvalidXML(String xml) throws ParserConfigurationException,
IOException {
expect(providerUtils.insertTrack((Track) AndroidMock.anyObject()))
.andReturn(TRACK_ID_URI);
expect(providerUtils.bulkInsertTrackPoints((Location[]) AndroidMock.anyObject(),
AndroidMock.anyInt(), AndroidMock.anyLong())).andStubReturn(1);
expect(providerUtils.getLastLocationId(TRACK_ID)).andStubReturn(TRACK_POINT_ID_1);
providerUtils.deleteTrack(TRACK_ID);
AndroidMock.replay(providerUtils);
InputStream is = new ByteArrayInputStream(xml.getBytes());
try {
GpxImporter.importGPXFile(is, providerUtils);
} catch (SAXException e) {
// expected exception
}
AndroidMock.verify(providerUtils);
}
/**
* Workaround because of capture bug 2617107 in easymock:
* http://sourceforge.net
* /tracker/?func=detail&aid=2617107&group_id=82958&atid=567837
*/
private static class LocationsMatcher implements IArgumentMatcher {
private final Location[] matchLocs;
private LocationsMatcher(Location[] expected) {
this.matchLocs = expected;
}
public static Location[] eqLoc(Location[] expected) {
IArgumentMatcher matcher = new LocationsMatcher(expected);
AndroidMock.reportMatcher(matcher);
return null;
}
public static Location[] eqLoc(Location expected) {
return eqLoc(new Location[] { expected});
}
@Override
public void appendTo(StringBuffer buf) {
buf.append("eqLoc(").append(Arrays.toString(matchLocs)).append(")");
}
@Override
public boolean matches(Object obj) {
if (! (obj instanceof Location[])) { return false; }
Location[] locs = (Location[]) obj;
if (locs.length < matchLocs.length) { return false; }
// Only check the first elements (those that will be taken into account)
for (int i = 0; i < matchLocs.length; i++) {
if (!locationsMatch(locs[i], matchLocs[i])) {
return false;
}
}
return true;
}
private boolean locationsMatch(Location loc1, Location loc2) {
return (loc1.getTime() == loc2.getTime()) &&
(loc1.getLatitude() == loc2.getLatitude()) &&
(loc1.getLongitude() == loc2.getLongitude()) &&
(loc1.getAltitude() == loc2.getAltitude());
}
}
}
@@ -0,0 +1,66 @@
// Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io;
import android.location.Location;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.util.Date;
import java.util.List;
/**
* Tests for the GPX track exporter.
*
* @author Sandor Dornbush
*/
public class TcxTrackWriterTest extends TrackFormatWriterTest {
public void testXmlOutput() throws Exception {
TrackFormatWriter writer = new TcxTrackWriter();
String result = writeTrack(writer);
Document doc = parseXmlDocument(result);
Element root = getChildElement(doc, "TrainingCenterDatabase");
Element activitiesTag = getChildElement(root, "Activities");
Element activityTag = getChildElement(activitiesTag, "Activity");
Element lapTag = getChildElement(activityTag, "Lap");
List<Element> segmentTags = getChildElements(lapTag, "Track", 2);
Element segment1Tag = segmentTags.get(0);
Element segment2Tag = segmentTags.get(1);
List<Element> seg1PointTags = getChildElements(segment1Tag, "Trackpoint", 2);
List<Element> seg2PointTags = getChildElements(segment2Tag, "Trackpoint", 2);
assertTagsMatchPoints(seg1PointTags, location1, location2);
assertTagsMatchPoints(seg2PointTags, location3, location4);
}
/**
* Asserts that the given tags describe the given points, in the same order.
*/
private void assertTagsMatchPoints(List<Element> tags, Location... locs) {
assertEquals(locs.length, tags.size());
for (int i = 0; i < locs.length; i++) {
Element tag = tags.get(i);
Location loc = locs[i];
assertTagMatchesLocation(tag, loc);
}
}
/**
* Asserts that the given tag describes the given location.
*/
private void assertTagMatchesLocation(Element tag, Location loc) {
Element posTag = getChildElement(tag, "Position");
assertEquals(Double.toString(loc.getLatitude()),
getChildTextValue(posTag, "LatitudeDegrees"));
assertEquals(Double.toString(loc.getLongitude()),
getChildTextValue(posTag, "LongitudeDegrees"));
assertEquals(
TcxTrackWriter.TIMESTAMP_FORMAT.format(new Date(loc.getTime())),
getChildTextValue(tag, "Time"));
assertEquals(Double.toString(loc.getAltitude()),
getChildTextValue(tag, "AltitudeMeters"));
}
}
@@ -9,24 +9,27 @@ import android.location.Location;
import junit.framework.TestCase;
/**
* Test the the function of the TripStatistics class.
* Test the the function of the TripStatisticsBuilder class.
*
* @author Sandor Dornbush
*/
public class TripStatisticsTest extends TestCase {
public class TripStatisticsBuilderTest extends TestCase {
private TripStatistics stats = null;
private TripStatisticsBuilder builder = null;
@Override
protected void setUp() throws Exception {
super.setUp();
stats = new TripStatistics();
builder = new TripStatisticsBuilder();
builder.resume();
}
public void testAddLocationSimple() throws Exception {
stats = new TripStatistics(1000);
builder = new TripStatisticsBuilder();
builder.resumeAt(1000);
TripStatistics stats = builder.getStatistics();
assertEquals(0.0, stats.getSmoothedElevation());
assertEquals(0.0, builder.getSmoothedElevation());
assertEquals(Double.POSITIVE_INFINITY, stats.getMinElevation());
assertEquals(Double.NEGATIVE_INFINITY, stats.getMaxElevation());
assertEquals(0.0, stats.getMaxSpeed());
@@ -48,19 +51,20 @@ public class TripStatisticsTest extends TestCase {
// Each time slice is 10 seconds.
long time = 1000 + 10000 * i;
l.setTime(time);
boolean moving = stats.addLocation(l, time);
boolean moving = builder.addLocation(l, time);
assertEquals((i != 0), moving);
stats = builder.getStatistics();
assertEquals(10000 * i, stats.getTotalTime());
System.out.println("i: " + i + "\nLocation: " + l + "\nStats: " + stats);
assertEquals(10000 * i, stats.getMovingTime());
assertEquals(i, stats.getSmoothedElevation(),
assertEquals(i, builder.getSmoothedElevation(),
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR / 2);
assertEquals(0.0, stats.getMinElevation());
assertEquals(i , stats.getMaxElevation(),
assertEquals(i, stats.getMaxElevation(),
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR / 2);
assertEquals(i, stats.getTotalElevationGain(),
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
if (i > MyTracksConstants.SPEED_SMOOTHING_FACTOR) {
assertEquals(11.1f, stats.getMaxSpeed(), 0.1);
}
@@ -80,13 +84,15 @@ public class TripStatisticsTest extends TestCase {
*/
public void testElevationSimple() throws Exception {
for (double elevation = 0; elevation < 1000; elevation += 10) {
stats = new TripStatistics();
builder = new TripStatisticsBuilder();
builder.resume();
for (int j = 0; j < 100; j++) {
assertEquals(0.0, stats.updateElevation(elevation));
assertEquals(elevation, stats.getSmoothedElevation());
assertEquals(elevation, stats.getMinElevation());
assertEquals(elevation, stats.getMaxElevation());
assertEquals(0.0, stats.getTotalElevationGain());
assertEquals(0.0, builder.updateElevation(elevation));
assertEquals(elevation, builder.getSmoothedElevation());
TripStatistics data = builder.getStatistics();
assertEquals(elevation, data.getMinElevation());
assertEquals(elevation, data.getMaxElevation());
assertEquals(0.0, data.getTotalElevationGain());
}
}
}
@@ -102,12 +108,13 @@ public class TripStatisticsTest extends TestCase {
expectedGain = 1.0;
}
assertEquals(expectedGain,
stats.updateElevation(i));
assertEquals(i, stats.getSmoothedElevation(), 20);
assertEquals(0.0, stats.getMinElevation(), 0.0);
assertEquals(i, stats.getMaxElevation(),
builder.updateElevation(i));
assertEquals(i, builder.getSmoothedElevation(), 20);
TripStatistics data = builder.getStatistics();
assertEquals(0.0, data.getMinElevation(), 0.0);
assertEquals(i, data.getMaxElevation(),
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
assertEquals(i, stats.getTotalElevationGain(),
assertEquals(i, data.getTotalElevationGain(),
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
}
}
@@ -116,23 +123,23 @@ public class TripStatisticsTest extends TestCase {
for (double i = 0; i < 1000; i++) {
// The value of the elevation does not matter. This is just to fill the
// buffer.
stats.updateElevation(i);
stats.updateGrade(100, 100);
builder.updateElevation(i);
builder.updateGrade(100, 100);
if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR)
&& (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) {
assertEquals(1.0, stats.getMaxGrade());
assertEquals(1.0, stats.getMinGrade());
assertEquals(1.0, builder.getStatistics().getMaxGrade());
assertEquals(1.0, builder.getStatistics().getMinGrade());
}
}
for (double i = 0; i < 1000; i++) {
// The value of the elevation does not matter. This is just to fill the
// buffer.
stats.updateElevation(i);
stats.updateGrade(100, -100);
builder.updateElevation(i);
builder.updateGrade(100, -100);
if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR)
&& (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) {
assertEquals(1.0, stats.getMaxGrade());
assertEquals(-1.0, stats.getMinGrade());
assertEquals(1.0, builder.getStatistics().getMaxGrade());
assertEquals(-1.0, builder.getStatistics().getMinGrade());
}
}
}
@@ -141,39 +148,39 @@ public class TripStatisticsTest extends TestCase {
for (double i = 0; i < 100; i++) {
// The value of the elevation does not matter. This is just to fill the
// buffer.
stats.updateElevation(i);
stats.updateGrade(1, 100);
assertEquals(Double.NEGATIVE_INFINITY, stats.getMaxGrade());
assertEquals(Double.POSITIVE_INFINITY, stats.getMinGrade());
builder.updateElevation(i);
builder.updateGrade(1, 100);
assertEquals(Double.NEGATIVE_INFINITY, builder.getStatistics().getMaxGrade());
assertEquals(Double.POSITIVE_INFINITY, builder.getStatistics().getMinGrade());
}
}
public void testUpdateSpeedIncludeZero() {
for (int i = 0; i < 1000; i++) {
stats.updateSpeed(i + 1000, 0.0, i, 4.0);
assertEquals(0.0, stats.getMaxSpeed());
assertEquals((i + 1) * 1000, stats.getMovingTime());
builder.updateSpeed(i + 1000, 0.0, i, 4.0);
assertEquals(0.0, builder.getStatistics().getMaxSpeed());
assertEquals((i + 1) * 1000, builder.getStatistics().getMovingTime());
}
}
public void testUpdateSpeedIngoreErrorCode() {
stats.updateSpeed(12345000, 128.0, 12344000, 0.0);
assertEquals(0.0, stats.getMaxSpeed());
assertEquals(1000, stats.getMovingTime());
builder.updateSpeed(12345000, 128.0, 12344000, 0.0);
assertEquals(0.0, builder.getStatistics().getMaxSpeed());
assertEquals(1000, builder.getStatistics().getMovingTime());
}
public void testUpdateSpeedIngoreLargeAcceleration() {
stats.updateSpeed(12345000, 100.0, 12344000, 1.0);
assertEquals(0.0, stats.getMaxSpeed());
assertEquals(1000, stats.getMovingTime());
builder.updateSpeed(12345000, 100.0, 12344000, 1.0);
assertEquals(0.0, builder.getStatistics().getMaxSpeed());
assertEquals(1000, builder.getStatistics().getMovingTime());
}
public void testUpdateSpeed() {
for (int i = 0; i < 1000; i++) {
stats.updateSpeed(i + 1000, 4.0, i, 4.0);
assertEquals((i + 1) * 1000, stats.getMovingTime());
builder.updateSpeed(i + 1000, 4.0, i, 4.0);
assertEquals((i + 1) * 1000, builder.getStatistics().getMovingTime());
if (i > MyTracksConstants.SPEED_SMOOTHING_FACTOR) {
assertEquals(4.0, stats.getMaxSpeed());
assertEquals(4.0, builder.getStatistics().getMaxSpeed());
}
}
}
@@ -3,6 +3,7 @@
package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics;
import junit.framework.TestCase;
@@ -19,9 +20,10 @@ public class ChartURLGeneratorTest extends TestCase {
Vector<Double> distances = new Vector<Double>();
Vector<Double> elevations = new Vector<Double>();
Track t = new Track();
t.setMinElevation(0);
t.setMaxElevation(2000);
t.setTotalDistance(100);
TripStatistics stats = t.getStatistics();
stats.setMinElevation(0);
stats.setMaxElevation(2000);
stats.setTotalDistance(100);
distances.add(0.0);
elevations.add(10.0);
+269
View File
@@ -0,0 +1,269 @@
<?xml version="1.0" encoding="UTF-8"?>
<profiles version="11">
<profile kind="CodeFormatterProfile" name="MyTracks" version="11">
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
</profile>
</profiles>
+7
View File
@@ -0,0 +1,7 @@
#Organize Import Order
#Fri May 28 03:20:44 BRT 2010
4=org
3=javax
2=java
1=android
0=com