Merge from head

This commit is contained in:
Rodrigo Damazio
2010-12-24 05:27:56 -02:00
25 changed files with 1544 additions and 307 deletions
+1 -1
View File
@@ -161,7 +161,7 @@ limitations under the License.
<uses-feature android:name="android.hardware.location" android:required="true"/>
<uses-feature android:name="android.hardware.location.gps" android:required="true"/>
<uses-feature android:name="android.hardware.touchscreen" android:required="true"/>
<!-- Features optional -->
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
<uses-feature android:name="android.hardware.location.network" android:required="false"/>
+5
View File
@@ -58,6 +58,11 @@ limitations under the License.
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/about_bart"
android:textSize="20sp" />
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
+292
View File
@@ -0,0 +1,292 @@
<?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>Inactiu</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 (recomanat)</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 (recomanat)</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 (recomanat)</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 (recomanat)</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>poca precisió (adaptable)</item>
<item>gran precisió (adaptable)</item>
<item>el millor (recomanat)</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 (senyal GPS excel·lent)</item>
<item>20 m</item>
<item>50 m</item>
<item>100 m</item>
<item>200 m (recomanat)</item>
<item>500 m</item>
<item>1000 m</item>
<item>2000 m</item>
<item>5000 m (senyal GPS pobre)</item>
</string-array>
<string-array name="min_required_accuracy_options_ft">
<item>33 ft (senyal GPS excel·lent)</item>
<item>66 ft</item>
<item>165 ft</item>
<item>328 ft</item>
<item>656 ft (recomanat)</item>
<item>1640 ft</item>
<item>0.6 miles</item>
<item>1.2 miles</item>
<item>3.1 miles (senyal GPS pobre)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>Sense divisió</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>No splitting</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>
<!-- Auto-resume track timeout -->
<string-array name="auto_resume_track_timeout_options">
<item>Mai</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>Always</item>
</string-array>
<!-- Other non-preference arrays -->
<array name="activity_types">
<item>desconegut</item>
<item>tipus barrejats</item>
<item>altre</item>
<item>córrer</item>
<item>córrer al carrer</item>
<item>pista d\'atletisme</item>
<item>córrer en ruta</item>
<item>a peu</item>
<item>caminar de presa</item>
<item>senderisme</item>
<item>ruta de senderisme</item>
<item>senderisme fora de ruta</item>
<item>escalada</item>
<item>ciclisme</item>
<item>bici al carrer</item>
<item>bici de muntanya</item>
<item>ruta de bici</item>
<item>patinatge</item>
<item>patinatge en línia</item>
<item>skate</item>
<item>snow shoeing</item>
<item>skiing</item>
<item>snow boarding</item>
<item>sled</item>
<item>ice sailing</item>
<item>pesca</item>
<item>rem</item>
<item>caiac</item>
<item>rem</item>
<item>llanxa motora</item>
<item>ferry</item>
<item>RC boat</item>
<item>surf</item>
<item>windsurf</item>
<item>kitesurf</item>
<item>esquí aquàtic</item>
<item>wakeboard</item>
<item>avió</item>
<item>hidroavió</item>
<item>avió comercial</item>
<item>helicòpter</item>
<item>globus aerostàtic</item>
<item>dirigible</item>
<item>avió RC</item>
<item>helicòpter RC</item>
<item>salt d\'esquí</item>
<item>vol sense motor</item>
<item>ala delta</item>
<item>parapent</item>
<item>riding</item>
<item>horse back riding</item>
<item>donkey back riding</item>
<item>conducció d\'automòbil</item>
<item>conducció de bus</item>
<item>tren</item>
<item>moto</item>
<item>dirtbike</item>
<item>ATV</item>
<item>landsailing</item>
<item>frisbee</item>
<item>ultimate frisbee</item>
</array>
<array name="waypoint_types">
<item>ATM</item>
<item>banc</item>
<item>bar</item>
<item>barbeque</item>
<item>edifici</item>
<item>parada de bús</item>
<item>cafeteria</item>
<item>acampada</item>
<item>càmping</item>
<item>església</item>
<item>cafeteria</item>
<item>botiga de conveniència</item>
<item>aigua potable</item>
<item>caiguda de roques</item>
<item>ferry</item>
<item>llar de foc</item>
<item>estació de bombers</item>
<item>pesca</item>
<item>benzinera</item>
<item>camp de golf</item>
<item>botiga de queviures</item>
<item>perruqueria</item>
<item>port</item>
<item>ruta de senderisme</item>
<item>hotel</item>
<item>casa</item>
<item>informació</item>
<item>intersecció</item>
<item>bústia</item>
<item>mercat</item>
<item>punt de trobada</item>
<item>opera</item>
<item>parking</item>
<item>oficina de correus</item>
<item>sot</item>
<item>comissaria dels mossos</item>
<item>encreuament ferroviari</item>
<item>restaurant</item>
<item>compres</item>
<item>vista</item>
<item>magatzem</item>
<item>piscina</item>
<item>telèfon</item>
<item>teatre</item>
<item>serveis</item>
<item>informació turística</item>
<item>túnel</item>
<item>arbre</item>
<item>cascada</item>
<item>font d\'aigua</item>
<item>punt de referència</item>
</array>
<array name="sensor_type_options">
<item>Cap</item>
<item>Zephyr Bluetooth</item>
</array>
</resources>
+449
View File
@@ -0,0 +1,449 @@
<?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">Enregistra la ruta</string>
<string name="stop_recording">Atura l\'enregistrament</string>
<string name="switch_to_sat">Mode de satèl·lit</string>
<string name="switch_to_map">Mode de mapa</string>
<string name="mylocation">La meva ubicació</string>
<string name="list_tracks">Rutes</string>
<string name="list_markers">Marcadors</string>
<string name="delete_all_tracks">Elimina totes les rutes</string>
<string name="settings">Paràmetres</string>
<string name="elevation">Elevació</string>
<string name="choose_track_message">Seleccioneu la ruta que es visualitzarà</string>
<string name="current_track">Ruta actual</string>
<string name="current_segment">Darrer segment</string>
<string name="sensor_state">Estat del sensor</string>
<string name="aggregated_stats">Estadístiques agregades</string>
<!-- Error messages -->
<string name="error_no_location_manager">No s\'ha trobat cap gestor d\'ubicacions en aquest dispositiu.</string>
<string name="error_no_gps_location_provider">No s\'ha trobat cap proveïdor d\'ubicació GPS en aquest dispositiu.</string>
<string name="error_sending_to_mymap">S\'ha produït un error quan s\'enviava la ruta a Google My Map. Proveu més tard.</string>
<string name="error_sending_to_docs">S\'ha prdouït un error quan s\'enviava la ruta a Google Docs. Proveu més tard.</string>
<string name="error_unable_to_start_recording">No es pot iniciar l\'enregistrament. Proveu de nou.</string>
<string name="error_unable_to_stop_recording">No es pot aturar l\'enregistrament. Proveu de nou.</string>
<string name="error_unable_to_read_file">No es pot llegir des del fitxer.</string>
<string name="error_invalid_gpx_format">El fitxer no conté un format GPX vàlid.</string>
<string name="error_generic">S\'ha produït un error. Proveu de nou.</string>
<string name="error_track_does_not_exist">No existeix la ruta.</string>
<string name="error_out_of_memory">Aquest fitxer és massa gran (ha d\'ésser inferior a 500KB. S\'està cancel·lant.</string>
<string name="error_unable_to_insert_marker">No es pot inserir un marcador. No hi ha cap ubicació fixa disponible.</string>
<!-- Status messages -->
<string name="wait_for_fix">S\'està esperant per tenir una posició GPS fixa. Assegureu-vos que el cel és visible.</string>
<string name="status_now_recording">Ara s\'està enregistrant una ruta nova.</string>
<string name="status_stopped_recording">S\'ha aturat l\'enregistrament de la ruta.</string>
<string name="status_new_mymap_has_been_created">S\'ha creat un Google My Map nou a maps.google.com.</string>
<string name="status_tracks_have_been_uploaded">S\'ha enviat la ruta a maps.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">S\'ha enviat la ruta a un full de càlcul a docs.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_docs">S\'ha enviat la ruta a docs.google.com.</string>
<string name="status_mymap_info">Poden passar uns minuts abans que les rutes noves apareguin.</string>
<string name="status_enable_gps">Piqueu aquí per anar als paràmetres de seguretat i ubicació i activeu \'habilita els satèl·lits GPS\'. Premeu el botó d\'anar enrere per tornar.</string>
<string name="status_approximate_location">Nota: Es mostra una ubicació determinada a partir de les xarxes sense fils i antenes telefòniques.</string>
<string name="status_no_location">No es pot determinar la ubicació. Habiliteu més fonts d\'ubicació (vegeu els paràmetres de seguretat i ubicació) i assegureu-vos que el cel és visible. Proveu de nou més tard.</string>
<string name="status_waypoint_inserted">S\'ha inserit un marcader de punt de ruta.</string>
<string name="status_statistics_inserted">S\'ha inserit un marcador d\'estadístiques.</string>
<!-- Progress dialog -->
<string name="progress_title">Espereu...</string>
<string name="progress_message">S\'està enviant la ruta a Google.</string>
<string name="progress_message_reading_track">S\'està llegint la ruta...</string>
<string name="progress_message_preparing_track">S\'està preparant la ruta...</string>
<string name="progress_message_authenticating_mymaps">S\'està to Google Maps...</string>
<string name="progress_message_authenticating_docs">S\'està autenticant a Google Docs...</string>
<string name="progress_message_sending_docs">S\'està enviant la ruta a Google Docs...</string>
<string name="progress_message_sending_mymaps">S\'està enviant a Google Maps...</string>
<string name="progress_message_creating_map">S\'està creant un My Map nou...</string>
<string name="import_progress_message">S\'està imporant una ruta GPS. Això pot trigar una estona.</string>
<string name="write_progress_message">S\'està escrivint a la targeta SD. Això pot trigar una estona.</string>
<string name="progress_message_updating_track">S\'estan actualitzant les estadístiques de la ruta...</string>
<!-- Used by DeleteAllDataHandler -->
<string name="are_you_sure_question">Esteu segur?</string>
<string name="all_data_will_be_permanently_deleted">Tots els marcadors i rutes s\'eliminaran d\'aquest telèfon.</string>
<string name="track_will_be_permanently_deleted">La ruta i els seus marcadors s\'eliminaran de forma permanent d\'aquest telèfon.</string>
<string name="marker_will_be_permanently_deleted">El marcador s\'eliminarà de forma permanent d\'aquest telèfon.</string>
<!-- Text and links when uploading to Google My Maps -->
<string name="new_map_description">Creat per My Tracks a l\'Android.</string>
<string name="my_map_link">Creat per &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; a l\'Android.</string>
<string name="new_map_title">Mapa nou</string>
<!-- Formatting of track and marker descriptions -->
<string name="points">Punts</string>
<string name="recorded_date">Enregistrat</string>
<string name="category">Tipus d\'activitat</string>
<string name="waypoint_category">Tipus de marcador</string>
<string name="part">(Part %d)</string>
<!-- Used by the track recording service -->
<string name="recording_your_track">S\'està enregistrant la ruta...</string>
<string name="new_track">Ruta %d</string>
<!-- Common -->
<string name="no">No</string>
<string name="yes">Sí</string>
<string name="ok">D\'acord</string>
<string name="error">Error</string>
<string name="success">Fet</string>
<string name="waypoint">Punt de referència</string>
<!-- Placemark labels for start and end of track -->
<string name="start">(Inici)</string>
<string name="end">(Fi)</string>
<!-- TrackList -->
<string name="tracklist_show_track">Mostra</string>
<string name="tracklist_send_to_mymaps">Envia a Google My Maps</string>
<string name="tracklist_send_to_new_mymap">Envia a un Google My Map nou</string>
<string name="tracklist_send_to_docs">Envia a Google Docs</string>
<string name="tracklist_send_to_google">Envia a Google...</string>
<string name="tracklist_delete_track">Elimina del telèfon...</string>
<string name="tracklist_edit_track">Edita els detalls</string>
<string name="tracklist_write_to_sd">Escriu a la targeta SD...</string>
<string name="tracklist_save_as_gpx">Anomena i desa com un fitxer GPX</string>
<string name="tracklist_save_as_kml">Anomena i desa com un fitxer KML</string>
<string name="tracklist_save_as_csv">Anomena i desa com un fitxer CSV</string>
<string name="tracklist_save_as_tcx">Anomena i desa com un fitxer TCX</string>
<string name="tracklist_btn_send_all_to_mymaps">Envia a Google My Maps</string>
<string name="tracklist_btn_delete_all">Elimina totes les rutes</string>
<!-- Export All -->
<string name="tracklist_btn_export_all">Exporta totes les rutes</string>
<string name="export_done">Exporta les finalitzades</string>
<string name="tracklist_pick_one">Seleccioneu una ruta. Mantingueu el dit per veure més opcions.</string>
<string name="tracklist_all_tracks">Totes les rutes:</string>
<string name="tracklist_this_track">Aquesta ruta</string>
<string name="tracklist_share_track">Comparteix amb amics...</string>
<string name="tracklist_share_link">Un enllaç a Google My Map</string>
<string name="tracklist_share_gpx_file">Un fitxer GPX</string>
<string name="tracklist_share_kml_file">Un fitxer KML</string>
<string name="tracklist_share_csv_file">Un fitxer CSV</string>
<string name="tracklist_share_tcx_file">Un fitxer TCX</string>
<string name="tracklist_clear_map">Neteja el mapa</string>
<!-- Waypoints list -->
<string name="waypointslist_btn_delete_all">Elimina tots els marcadors</string>
<string name="waypointslist_this_waypoint">Aquest marcador</string>
<string name="waypointslist_delete_waypoint">Elimina</string>
<string name="waypointslist_edit_waypoint">Edita els detalls</string>
<string name="waypointslist_show_waypoint">Mostra al mapa</string>
<string name="waypointslist_btn_insert_waypoint">Insereix un punt de referència</string>
<string name="waypointslist_btn_insert_statistics">Insereix estadístiques</string>
<string name="waypointslist_pick_one">Seleccioneu un marcador. Mantingueu el dit per veure més opcions.</string>
<!-- MyTracks Details -->
<string name="trackdetails_title">Detalls de la ruta</string>
<string name="trackdetails_name">Nom de la ruta</string>
<string name="trackdetails_description">Descripció de la ruta</string>
<string name="trackdetails_category">Tipus d\'activitat (p.e. senderisme, bicicleta, còrrer, escalada...)</string>
<!-- MyTracks Waypoint Details -->
<string name="waypointdetails_title">Detalls del marcador</string>
<string name="waypointdetails_name">Nom del marcador</string>
<string name="waypointdetails_description">Descripció del marcador</string>
<string name="waypointdetails_category">Tipus de marcador (e.g. edifici, sot, vista...)</string>
<!-- MyTracks Settings -->
<string name="mytracks_settings">Paràmetres de My Tracks</string>
<string name="settings_display">Visualització</string>
<string name="settings_recording">Enregistrament</string>
<string name="settings_sharing">Compartició</string>
<string name="settings_not_available_summary">No es troba disponible a la vostra versió de l\'Android</string>
<string name="settings_announcement_frequency">Freqüència d\'avís</string>
<string name="settings_announcement_frequency_summary">Temps mínin entre dos avisos de veu</string>
<string name="settings_min_recording_distance">Distància mínima entre punts</string>
<string name="settings_min_recording_distance_summary">La distància més petita entre dos punts enregistrats de la vostra posició</string>
<string name="settings_max_recording_distance">Distància màxima entre punts</string>
<string name="settings_max_recording_distance_summary">Si dos punts estan més lluny d\'això, es dividirà la ruta</string>
<string name="settings_min_recording_interval">Temps mínim entre punts</string>
<string name="settings_min_recording_interval_summary">Interval de temps mínim entre dos enregistraments de la vostra posició</string>
<string name="settings_min_required_accuracy">Precisió míima</string>
<string name="settings_min_required_accuracy_summary">S\'aturarà l\'enregistrament si la vostra posició no és així de precisa com a mínim</string>
<string name="settings_metric_units">Fes servir unitats mètriques</string>
<string name="settings_metric_units_summary_on">Totes les distàncies es mostraran en unitats mètriques</string>
<string name="settings_metric_units_summary_off">Totes les distàncies es mostraran en unitats imperials</string>
<string name="settings_map_public">Fes el mapa públic</string>
<string name="settings_map_public_summary_on">Els mapes pujats seran visibles per tothom a maps.google.com</string>
<string name="settings_map_public_summary_off">Els mapes pujats no es llistaran públicament a maps.google.com</string>
<string name="settings_report_speed_or_pace">Mostra la velocitat</string>
<string name="settings_report_speed_or_pace_summary_on">Es mostrarà la velocitat</string>
<string name="settings_report_speed_or_pace_summary_off">Es mostrarà el ritme de pas</string>
<string name="settings_share_url_only">Comparteix només l\'URL</string>
<string name="settings_share_url_only_summary_on">Només s\'enviarà l\'URL del mapa quan es comparteixi</string>
<string name="settings_share_url_only_summary_off">També s\'inclouran els continguts de la ruta quan es comparteixi</string>
<string name="settings_split_frequency">Freqüència de divisió</string>
<string name="settings_split_frequency_summary">Temps o distància màxima a partir de la qual s\'insertarà un marcador de divisió nou</string>
<string name="settings_auto_resume_track_timeout">Temps d\'espera per reprende la ruta</string>
<string name="settings_auto_resume_track_timeout_summary">Temps màxim en minuts a partir del qual l\'anterior ruta enregistrada no es reprendrà en actualitzar el telèfon</string>
<string name="settings_timestamp_track_name">Data i hora com a nom de la ruta</string>
<string name="settings_timestamp_track_name_summary_on">El nom per defecte de la ruta serà la data i hora en que s\'ha iniciat.</string>
<string name="settings_timestamp_track_name_summary_off">Els noms de les rutes seran números que s\'incrementaran per a cada nova ruta.</string>
<string name="pace_label">Ritme de pas</string>
<string name="eclair_required">Suportat només en Android 2.0 i superior</string>
<string name="settings_sensor_type">Tipus de sensor</string>
<string name="settings_sensor_type_summary">El tipus de sensor al qual es connecta.</string>
<string name="settings_sensor_id">Identificador del sensor</string>
<string name="settings_sensor_id_summary">L\'identificador enviat als sensors.</string>
<string name="sensor_id_malformed">L\'identificador ha de ser un valor sencer.</string>
<string name="bluetooth_sensor_title">Sensor bluetooth</string>
<string name="bluetooth_sensor_summary">El sensor bluetooth al qual es connecta.</string>
<string name="settings_modular_stats_display_title">Pantalla d\'estadístiques modulars</string>
<string name="settings_modular_stats_display_summary_on">La pantalla d\'estadístiques es divideix en mòduls diferents.</string>
<string name="settings_modular_stats_display_summary_off">Mostra totes les estadístiques en una sola pantalla.</string>
<string name="settings_backup">Còpia de seguretat (BETA)</string>
<string name="settings_sd_backup">Còpia de seguretat a la targeta SD</string>
<string name="settings_backup_to_sd">Fes la còpia ara</string>
<string name="settings_backup_to_sd_summary">Escriu una còpia completa de totes les rutes i els paràmetres a la targeta SD</string>
<string name="settings_restore_from_sd">Restaura ara</string>
<string name="settings_restore_from_sd_summary">Restaura totes les rutes i els paràmetres des de la targeta SD.</string>
<string name="settings_no_backup_while_recording">No es poden gestionar les còpies de seguretat mentre s\'enregistra una ruta.</string>
<!-- Backups -->
<string name="restore_overwrites_warning">La restauració d\'una còpia de seguretat des de la targeta SD sobreescriurà totes les rutes i paràmetres. Esteu segur?</string>
<string name="select_backup_to_restore">Seleccioneu la còpia que es restaurarà</string>
<string name="no_backups">No s\'ha trobat cap còpia de seguretat.</string>
<string name="backup_write_progress_message">S\'estan escrivint totes les rutes i els paràmetres a la targeta SD. Això pot trigar una estona...</string>
<string name="backup_import_progress_message">S\'estan llegint totes les rutes i els paràmetres de la targeta SD. Això pot trigar una estona...</string>
<!-- MyTracksSky -->
<string name="mytracks_sky">Satèl·lits GPS</string>
<!-- My Maps -->
<string name="select_map_message">Seleccioneu un mapa del vostre compte:</string>
<string name="create_new_map">Crea un mapa nou...</string>
<string name="map_list_title">Envia a Google My Maps</string>
<string name="maps_list_loading">S\'estan carregant els mapes...</string>
<string name="maps_list_failed">No s\'han pogut carregar els vostres mapes en aquest moment</string>
<string name="open_map">Selecciona aquest mapa</string>
<string name="edit_map_details">Edita els detalls del mapa</string>
<string name="share_map">Comparteix el mapa amb amics</string>
<string name="share_track">Comparteix la ruta amb amics</string>
<string name="delete_map">Elimina el mapa del vostre compte</string>
<string name="map_title">Títol del mapa:</string>
<string name="map_description">Descripció del mapa:</string>
<string name="map_searchable_edit">Fes que aquest mapa i els seus continguts apareguen als resultats de cerca</string>
<string name="map_not_searchable_edit">No permetis que aquest mapa ni els seus continguts es mostrin als resultats de cerca, tot i que sí es podrà visualitzar per altres amb l\'adreça URL directa</string>
<string name="map_searchable">Aquest mapa i els seus continguts es mostraran als resultats de cerca</string>
<string name="map_not_searchable">Ni els mapes ni els seus continguts es mostraran als resultats de cerca, però podran visualitzar-se per altres a través d\'un enllaç directe.</string>
<string name="close">Tanca</string>
<string name="edit">Edita</string>
<string name="cancel">Cancel·la</string>
<string name="save">Desa</string>
<!-- Sharing -->
<string name="share_map_subject">M\'agradaria compartir un mapa amb tu</string>
<string name="share_map_body_format">Crec que estaràs interessat en aquest mapa:
%s</string>
<string name="send_track_subject">M\'agradaria compartir una ruta amb tu</string>
<string name="send_track_body_format">Crec que estaràs interessat en aquesta ruta.
Per verue aquesta ruta fes servir Google Earth o altre programari de mapes.</string>
<!-- Visibility -->
<string name="public_map">Públic</string>
<string name="unlisted_map">No llistat</string>
<string name="mapslist_no_maps_available">Encara no teniu cap mapa.</string>
<!-- Statistics View -->
<!-- Average Moving -->
<string name="average_moving_speed_label">Average Moving Speed</string>
<string name="average_moving_pace_label">Average Moving Pace</string>
<!-- Average -->
<string name="average_speed_label">Velocitat mitjana</string>
<string name="average_pace_label">Ritme de pas mitjà</string>
<string name="elevation_chart_name">Gràfic d\'elevació</string>
<string name="elevation_gain_label">Guany d\'elevació</string>
<string name="elevation_label">Elevació</string>
<string name="latitude_label">Latitud</string>
<string name="longitude_label">Longitud</string>
<!-- Min -->
<string name="min_elevation_label">Elevació mínima</string>
<string name="min_grade_label">Grau mínim</string>
<string name="min_pace_label">Ritme de pas mínima</string>
<!-- Max -->
<string name="max_elevation_label">Elevació màxima</string>
<string name="max_grade_label">Grau màxim</string>
<string name="max_speed_label">Velocitat màxima</string>
<string name="loading_track">S\'està carregant la ruta...</string>
<!-- Chart Settings -->
<string name="chart_settings">Configuració del gràfic</string>
<!-- X Axis -->
<string name="x_axis">Eix X</string>
<string name="by_distance">Per distància</string>
<string name="by_time">Per temps</string>
<!-- Y Axis -->
<string name="y_axis">Eix Y</string>
<!-- Units -->
<!-- Time -->
<string name="hour">hora</string>
<string name="hours">hores</string>
<string name="minute">minut</string>
<string name="minutes">minuts</string>
<string name="second">segon</string>
<string name="seconds">segons</string>
<!-- Distance -->
<string name="kilometers_long">kilòmetres</string>
<string name="miles_long">milles</string>
<!-- Speed and Pace -->
<string name="kilometer_per_hour_long">kilòmetres per hora</string>
<string name="per_kilometer">per kilòmetre</string>
<string name="mile_per_hour_long">milles per hora</string>
<string name="per_mile">per milla</string>
<!-- Stats Labels -->
<string name="moving_time_label">Temps en moviment</string>
<string name="total_time_label">Temps total</string>
<string name="time_label">Temps</string>
<string name="sd_unavail">La targeta SD no està disponible</string>
<string name="speed">Velocitat</string>
<string name="start_trip">Heu d\'iniciar la marxa.</string>
<string name="statistics">Estadístiques</string>
<string name="total_distance_label">Distància total</string>
<string name="distance_label">Distància</string>
<string name="power">Energia</string>
<string name="cadence">Cadència</string>
<string name="heart_rate">Freqüència cardíaca</string>
<string name="max_heart_rate">Freqüència cardíaca màxima</string>
<string name="waiting">S\'està esperant...</string>
<!-- End User License Agreement -->
<string name="eula_title">Acord de llicencia d\'usuari final</string>
<string name="accept">Accepta</string>
<string name="decline">Rebutja</string>
<!-- About -->
<string name="about">Quant a</string>
<string name="help">Ajuda</string>
<string name="about_team">Equip:</string>
<string name="about_version">Versió:</string>
<string name="about_email">Assistència</string>
<string name="about_support">Assistència:</string>
<!-- Send to Google -->
<string name="sendtogoogle_title">Envia a...</string>
<string name="sendtogoogle_send_now">Envia ara</string>
<string name="sendtogoogle_create_new_map">Crea un mapa nou</string>
<string name="sendtogoogle_pick_existing_map">Seleccioneu un mapa existent</string>
<string name="sendtogoogle_send_stats">Envia les estadístiques de la ruta</string>
<string name="sendtogoogle_send_stats_and_points">Envia les estadístiques i els punts</string>
<!-- Getting the account to upload to. -->
<string name="no_account_found_title">No s\'ha trobat cap compte</string>
<string name="no_account_found">No s\'ha trobat cap compte on pujar les rutes.</string>
<string name="choose_account_title">Trieu un compte</string>
<!-- SD card -->
<string name="io_no_external_storage_found">No s\'ha trobat cap dispositiu d\'emmagatzematge extern. Assegureu-vos que la targeta SD està inserida i que el telèfon no està connectat a un ordinador.</string>
<string name="io_write_failed">No es pot escriure a un fitxer.</string>
<string name="io_read_failed">No es pot llegir des del fitxer.</string>
<string name="io_create_dir_failed">No es pot crear el directori a la targeta SD.</string>
<string name="io_write_finished">S\'ha finalitzat l\'escriptura a la targeta SD.</string>
<string name="io_read_finished">S\'ha finalitzat la lectura a la targeta SD.</string>
<!-- VersionChecker -->
<string name="version_check_title">Comprovació d\'actualitzacions</string>
<string name="version_check_upgrade_button">Actualitza ara</string>
<string name="version_check_continue_button">Continua sense actualitzar</string>
<string name="upgrade_required">La vostra versió de %1$s podria no funcionar correctament a partir d\'ara i no està suportada. Actualitzeu per continuar fent servir %1$s.</string>
<string name="upgrade_recommended">La vostra versió de %1$s podria no funcionar correctament a partir d\'ara. Heu d\'actualitzar-la ara o continuar fent-la servir pel vostre compte. Algunes funcionalitats com la sincronització podrien no funcionar fins que no actualitzeu.</string>
<string name="upgrade_available">Hi ha una nova versió disponible de %1$s. Podeu continuar fent servir la vostra versió sense cap problema, però no aconseguireu les darreres funcionalitats fins que no actualitzeu.</string>
<!-- Welcome -->
<string name="welcome">Benvingut</string>
<string name="welcome_read_later">D\'acord</string>
<string name="welcome_about">Quant a My Tracks</string>
<!-- Announcement -->
<string name="announce_no_distance">Sense distància 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 en %4$s at %5$s %6$s</string>
<!-- Check Units -->
<string name="check_units_title">Avís de les unitats de mesura</string>
<string name="check_units_message">Les unitats són mètriques per defecte. Voleu canviar aquest paràmetre?</string>
<!-- Signal Strength -->
<string name="error_rate"> Rati d\'error: %1$d</string>
<string name="signal_to_noise_ratio"> Relació senyal/soroll: %1$d</string>
<string name="ecio"> Ec/lo: %1$.1f dB</string>
<string name="gsm_strength">Intensistat GSM: %1$d</string>
<string name="cdma_strength">Intensitat CDMA: %1$d dBm</string>
<string name="evdo_strength">Intensitat EVDO: %1$d dBm</string>
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
<string name="bluetooth_options">Opcions del Bluetooth</string>
<string name="bluetooth_pairing">Associació de dispositius</string>
<string name="bluetooth_pairing_summary">Obriu els paràmetres de bluetooth de l\'Android per associar un dispositiu</string>
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
<string name="sensor_options">Opcions del sensor</string>
<!-- Bluetooth Sensor -->
<string name="bluetooth_connected">Connectat a %s</string>
<string name="bluetooth_connecting">Connexió del sensor bluetooth...</string>
<string name="bluetooth_not_connected">El sensor bluetooth no està connectat</string>
<!-- Sensor State -->
<string name="sensor_data_time">Dades del sensor de temps</string>
<string name="power_meter_enabled">S\'ha habilitat el mesurador de potència</string>
<string name="heart_rate_monitor_enabled">S\'ha habilitat el monitor de la freqüència cardíaca</string>
<string name="no_sensor_manager">Cap gestor de sensors</string>
<string name="enabled">Habilitat</string>
<string name="connecting">S\'està connectant</string>
<string name="connected">S\'ha connectat</string>
<string name="disconnected">S\'ha desconnectat</string>
<string name="no_sensor_service">Cap servei de sensor</string>
<string name="searching">S\'està cercant</string>
<string name="sending">S\'està enviant</string>
</resources>
+2
View File
@@ -361,6 +361,8 @@ limitations under the License.
<string name="about_version">Wersja:</string>
<string name="about_email">Wsparcie</string>
<string name="about_support">Wsparcie:</string>
<string name="about_bart">Bartłomiej Niechwiej</string>
<!-- Send to Google -->
<string name="sendtogoogle_title">Wyślij do...</string>
+1
View File
@@ -388,6 +388,7 @@ limitations under the License.
<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>
<string name="about_bart">Bartlomiej Niechwiej</string>
<string name="about_dylan">Dylan Casey</string>
<string name="about_leif">Leif Hendrik Wilden</string>
<string name="about_rdamazio">Rodrigo Damazio Bovendorp</string>
+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- DO NOT TRANSLATE -->
<string name="waypoint_icon_url">http://maps.google.com/mapfiles/ms/micons/blue-pushpin.png</string>
<string name="stats_icon_url">http://maps.google.com/mapfiles/ms/micons/ylw-pushpin.png</string>
</resources>
@@ -25,7 +25,7 @@ import com.google.android.apps.mymaps.MyMapsConstants;
import com.google.android.apps.mymaps.MyMapsList;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.io.AuthManager;
import com.google.android.apps.mytracks.io.AuthManagerFactory;
import com.google.android.apps.mytracks.io.GpxImporter;
@@ -63,6 +63,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -93,9 +94,6 @@ import org.xml.sax.SAXException;
public class MyTracks extends TabActivity implements OnTouchListener,
OnSharedPreferenceChangeListener, ProgressIndicator {
private static final String WAYPOINT_ICON_URL =
"http://maps.google.com/mapfiles/ms/micons/blue-pushpin.png";
/**
* Singleton instance
*/
@@ -432,7 +430,13 @@ public class MyTracks extends TabActivity implements OnTouchListener,
public boolean onTrackballEvent(MotionEvent event) {
if (isRecording()) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
insertStatisticsMarker();
try {
insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
} catch (RemoteException e) {
Log.e(MyTracksConstants.TAG, "Cannot insert statistics marker.", e);
} catch (IllegalStateException e) {
Log.e(MyTracksConstants.TAG, "Cannot insert statistics marker.", e);
}
return true;
}
}
@@ -888,90 +892,25 @@ public class MyTracks extends TabActivity implements OnTouchListener,
/**
* Inserts a waypoint marker.
*
* @return the id of the inserted statistics marker, or
* -1 unable to find location
* -2 track recording service is not running?
* -3 remote exception when contacting track recording service
* -4 inserting marker into provider failed
* @return Id of the inserted statistics marker.
* @throws RemoteException If the call on the service failed.
*/
public long insertWaypointMarker() {
Location location = getCurrentLocation();
if (location == null) {
public long insertWaypoint(WaypointCreationRequest request) throws RemoteException {
if (trackRecordingService == null) {
throw new IllegalStateException("The recording service is not bound.");
}
try {
long waypointId = trackRecordingService.insertWaypoint(request);
if (waypointId >= 0) {
Toast.makeText(this, R.string.status_statistics_inserted,
Toast.LENGTH_LONG).show();
}
return waypointId;
} catch (RemoteException e) {
Toast.makeText(this, R.string.error_unable_to_insert_marker,
Toast.LENGTH_LONG).show();
return -1;
throw e;
}
if (trackRecordingService != null) {
try {
Waypoint wpt = new Waypoint();
wpt.setName(getString(R.string.waypoint));
wpt.setType(Waypoint.TYPE_WAYPOINT);
wpt.setTrackId(recordingTrackId);
wpt.setIcon(WAYPOINT_ICON_URL);
wpt.setLocation(location);
long waypointId = trackRecordingService.insertWaypointMarker(wpt);
if (waypointId >= 0) {
Toast.makeText(this, R.string.status_waypoint_inserted,
Toast.LENGTH_LONG).show();
return waypointId;
} else {
Toast.makeText(this, R.string.error_unable_to_insert_marker,
Toast.LENGTH_LONG).show();
Log.e(MyTracksConstants.TAG, "Cannot insert waypoint marker?");
return -4;
}
// TODO: We catch Exception, because after eliminating the service process
// all exceptions it may throw are no longer wrapped in a RemoteException.
} catch (Exception e) {
Toast.makeText(this, R.string.error_unable_to_insert_marker,
Toast.LENGTH_LONG).show();
Log.e(MyTracksConstants.TAG, "Cannot insert waypoint marker.", e);
}
return -3;
}
return -2;
}
/**
* Inserts a statistics marker.
*
* @return the id of the inserted statistics marker, or
* -1 unable to find location
* -2 track recording service is not running?
* -3 remote exception when contacting track recording service
* -4 inserting marker into provider failed
*/
public long insertStatisticsMarker() {
Location location = getLastLocation();
if (location == null) {
Toast.makeText(this, R.string.error_unable_to_insert_marker,
Toast.LENGTH_LONG).show();
return -1;
}
if (trackRecordingService != null) {
try {
long waypointId =
trackRecordingService.insertStatisticsMarker(location);
if (waypointId >= 0) {
Toast.makeText(this, R.string.status_statistics_inserted,
Toast.LENGTH_LONG).show();
return waypointId;
} else {
Toast.makeText(this, R.string.error_unable_to_insert_marker,
Toast.LENGTH_LONG).show();
Log.e(MyTracksConstants.TAG, "Cannot insert statistics marker?");
return -4;
}
// TODO: We catch Exception, because after eliminating the service process
// all exceptions it may throw are no longer wrapped in a RemoteException.
} catch (Exception e) {
Toast.makeText(this, R.string.error_unable_to_insert_marker,
Toast.LENGTH_LONG).show();
Log.e(MyTracksConstants.TAG, "Cannot insert statistics marker?", e);
}
return -3;
}
return -2;
}
/**
@@ -42,6 +42,8 @@ import android.widget.ImageView;
public class MyTracksWaypointDetails extends Activity
implements OnClickListener {
public static final String WAYPOINT_ID_EXTRA = "com.google.android.apps.mytracks.WAYPOINT_ID";
/**
* The id of the way point being edited (taken from bundle, "waypointid")
*/
@@ -78,7 +80,7 @@ public class MyTracksWaypointDetails extends Activity
}
// Required extra when launching this intent:
waypointId = getIntent().getLongExtra("waypointid", -1);
waypointId = getIntent().getLongExtra(WAYPOINT_ID_EXTRA, -1);
if (waypointId < 0) {
Log.d(MyTracksConstants.TAG,
"MyTracksWaypointsDetails intent was launched w/o waypoint id.");
@@ -17,6 +17,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.WaypointCreationRequest;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.maps.mytracks.R;
@@ -28,6 +29,8 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
@@ -87,7 +90,7 @@ public class MyTracksWaypointsList extends ListActivity
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent result = new Intent();
result.putExtra("trackid", trackId);
result.putExtra("waypointid", id);
result.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, id);
setResult(MyTracksConstants.EDIT_WAYPOINT, result);
finish();
}
@@ -103,7 +106,7 @@ public class MyTracksWaypointsList extends ListActivity
case MyTracksConstants.MENU_EDIT: {
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
intent.putExtra("trackid", trackId);
intent.putExtra("waypointid", waypointId);
intent.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, waypointId);
startActivity(intent);
return true;
}
@@ -165,27 +168,34 @@ public class MyTracksWaypointsList extends ListActivity
@Override
public void onClick(View v) {
WaypointCreationRequest request;
switch (v.getId()) {
case R.id.waypointslist_btn_insert_waypoint: {
long id = MyTracks.getInstance().insertWaypointMarker();
if (id >= 0) {
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
intent.putExtra("waypointid", id);
startActivity(intent);
}
case R.id.waypointslist_btn_insert_waypoint:
request = WaypointCreationRequest.DEFAULT_MARKER;
break;
}
case R.id.waypointslist_btn_insert_statistics: {
long id = MyTracks.getInstance().insertStatisticsMarker();
if (id >= 0) {
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
intent.putExtra("waypointid", id);
startActivity(intent);
}
case R.id.waypointslist_btn_insert_statistics:
request = WaypointCreationRequest.DEFAULT_STATISTICS;
break;
}
default:
return;
}
long id;
try {
id = MyTracks.getInstance().insertWaypoint(request);
} catch (RemoteException e) {
Log.e(MyTracksConstants.TAG, "Cannot insert marker.", e);
return;
} catch (IllegalStateException e) {
Log.e(MyTracksConstants.TAG, "Cannot insert marker.", e);
return;
}
if (id < 0) {
Log.e(MyTracksConstants.TAG, "Failed to insert marker.");
return;
}
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
intent.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, id);
startActivity(intent);
}
private void setListAdapter() {
@@ -16,6 +16,7 @@
package com.google.android.apps.mytracks.services;
import com.google.android.apps.mytracks.MyTracksConstants;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.util.UnitConversions;
import android.util.Log;
@@ -111,7 +112,7 @@ public class SplitManager {
}
if (distance > this.nextSplitDistance) {
service.insertStatisticsMarker(service.getLastLocation());
service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
calculateNextSplit();
}
}
@@ -16,6 +16,9 @@
package com.google.android.apps.mytracks.services;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
/**
* A simple task to insert statistics markers every n minutes.
* @author Sandor Dornbush
@@ -24,7 +27,7 @@ public class TimeSplitTask implements PeriodicTask {
@Override
public void run(TrackRecordingService service) {
service.insertStatisticsMarker(service.getLastLocation());
service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
}
@Override
@@ -26,6 +26,7 @@ import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.services.sensors.SensorManager;
@@ -70,9 +71,6 @@ import java.util.TimerTask;
*/
public class TrackRecordingService extends Service implements LocationListener {
private static final String STATISTICS_ICON_URL =
"http://maps.google.com/mapfiles/ms/micons/ylw-pushpin.png";
static final int MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS = 3;
private NotificationManager notificationManager;
@@ -429,7 +427,7 @@ public class TrackRecordingService extends Service implements LocationListener {
lastValidLocation = null;
Waypoint waypoint = providerUtils.getFirstWaypoint(recordingTrackId);
if (waypoint != null) {
if (waypoint != null && waypoint.getStatistics() != null) {
currentWaypointId = waypoint.getId();
waypointStatsBuilder = new TripStatisticsBuilder(
waypoint.getStatistics());
@@ -860,50 +858,62 @@ public class TrackRecordingService extends Service implements LocationListener {
return isRecording;
}
public long insertWaypointMarker(Waypoint waypoint) {
public long insertWaypoint(WaypointCreationRequest request) {
if (!isRecording()) {
throw new IllegalStateException(
"Unable to insert waypoint marker while not recording!");
}
if (waypoint.getLocation() == null) {
if (lastValidLocation == null) {
Log.w(MyTracksConstants.TAG, "Cannot insert waypoint with no location");
return -1;
}
waypoint.setLocation(lastValidLocation);
if (request == null) {
request = WaypointCreationRequest.DEFAULT_MARKER;
}
if (waypoint.getTrackId() < 0) {
waypoint.setTrackId(recordingTrackId);
Waypoint wpt = new Waypoint();
switch (request.getType()) {
case MARKER:
buildMarker(wpt, request);
break;
case STATISTICS:
buildStatisticsMarker(wpt);
break;
}
waypoint.setLength(length);
waypoint.setDuration(waypoint.getLocation().getTime()
- statsBuilder.getStatistics().getStartTime());
Uri uri = providerUtils.insertWaypoint(waypoint);
wpt.setTrackId(recordingTrackId);
wpt.setLength(length);
if (lastValidLocation != null) {
// A null location is ok, and expected on track start.
wpt.setLocation(lastLocation);
wpt.setDuration(lastLocation.getTime()
- statsBuilder.getStatistics().getStartTime());
}
Uri uri = providerUtils.insertWaypoint(wpt);
return Long.parseLong(uri.getLastPathSegment());
}
private void buildMarker(Waypoint wpt, WaypointCreationRequest request) {
wpt.setType(Waypoint.TYPE_WAYPOINT);
if (request.getIconUrl() == null) {
wpt.setIcon(getString(R.string.waypoint_icon_url));
} else {
wpt.setIcon(request.getIconUrl());
}
if (request.getName() == null) {
wpt.setName(getString(R.string.waypoint));
} else {
wpt.setName(request.getName());
}
if (request.getDescription() != null) {
wpt.setDescription(request.getDescription());
}
}
/**
* Inserts a statistics marker. A statistics marker holds the stats for the
* last segment up to this marker.
* Build a statistics marker.
* A statistics marker holds the stats for the* last segment up to this marker.
*
* @param location the location where to insert
* @param Waypoint The waypoint which will be populated with stats data.
* @return the unique id of the inserted marker
*/
public long insertStatisticsMarker(Location location) {
if (!isRecording()) {
throw new IllegalStateException(
"Unable to insert statistics marker while not recording!");
}
private void buildStatisticsMarker(Waypoint waypoint) {
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);
@@ -913,24 +923,18 @@ public class TrackRecordingService extends Service implements LocationListener {
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));
waypoint.setName(getString(R.string.statistics));
waypoint.setStatistics(waypointStatsBuilder.getStatistics());
waypoint.setDescription(utils.generateWaypointDescription(waypoint));
waypoint.setLocation(location);
waypoint.setIcon(STATISTICS_ICON_URL);
waypoint.setLength(length);
waypoint.setIcon(getString(R.string.stats_icon_url));
waypoint.setStartId(providerUtils.getLastLocationId(recordingTrackId));
Uri uri = providerUtils.insertWaypoint(waypoint);
// Create a new stats keeper for the next marker
// Create a new stats keeper for the next marker.
waypointStatsBuilder = new TripStatisticsBuilder(time);
updateCurrentWaypoint();
return Long.parseLong(uri.getLastPathSegment());
}
private ServiceBinder binder = new ServiceBinder(this);
/**
@@ -961,79 +965,54 @@ public class TrackRecordingService extends Service implements LocationListener {
@Override
public boolean isRecording() {
checkService();
return service.isRecording();
}
private void checkService() {
if (service == null) {
throw new IllegalStateException("The service has been already detached!");
}
return service.isRecording();
}
@Override
public long getRecordingTrackId() {
if (service == null) {
throw new IllegalStateException("The service has been already detached!");
}
checkService();
return service.recordingTrackId;
}
@Override
public boolean hasRecorded() {
if (service == null) {
throw new IllegalStateException("The service has been already detached!");
}
checkService();
return service.providerUtils.getLastTrackId() >= 0;
}
@Override
public long startNewTrack() {
if (service == null) {
throw new IllegalStateException("The service has been already detached!");
}
checkService();
return service.startNewTrack();
}
/**
* Insert the given waypoint marker. Users can insert waypoint markers
* to tag locations with a name, description, category etc.
* Inserts a waypoint marker in the track being recorded.
*
* @param waypoint a waypoint
* @return the unique id of the inserted marker
* @param request Details of the waypoint to insert
* @return the unique ID of the inserted marker
*/
@Override
public long insertWaypointMarker(Waypoint waypoint) {
if (service == null) {
throw new IllegalStateException("The service has been already detached!");
}
return service.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
*/
@Override
public long insertStatisticsMarker(Location location) {
if (service == null) {
throw new IllegalStateException("The service has been already detached!");
}
return service.insertStatisticsMarker(location);
public long insertWaypoint(WaypointCreationRequest request) {
checkService();
return service.insertWaypoint(request);
}
@Override
public void endCurrentTrack() {
if (service == null) {
throw new IllegalStateException("The service has been already detached!");
}
checkService();
service.endCurrentTrack();
}
@Override
public void deleteAllTracks() {
if (service == null) {
throw new IllegalStateException("The service has been already detached!");
}
checkService();
if (isRecording()) {
throw new IllegalStateException("Cannot delete all tracks while recording!");
}
@@ -1042,14 +1021,13 @@ public class TrackRecordingService extends Service implements LocationListener {
@Override
public void recordLocation(Location loc) {
if (service == null) {
throw new IllegalStateException("The service has been already detached!");
}
checkService();
service.onLocationChanged(loc);
}
@Override
public byte[] getSensorData() {
checkService();
if (service.sensorManager == null) {
Log.d(MyTracksConstants.TAG, "No sensor manager for data.");
return null;
@@ -1063,6 +1041,7 @@ public class TrackRecordingService extends Service implements LocationListener {
@Override
public int getSensorState() {
checkService();
if (service.sensorManager == null) {
Log.d(MyTracksConstants.TAG, "No sensor manager for data.");
return Sensor.SensorState.NONE.getNumber();
@@ -1095,7 +1074,7 @@ public class TrackRecordingService extends Service implements LocationListener {
providerUtils.updateTrack(track);
statsBuilder = new TripStatisticsBuilder(startTime);
waypointStatsBuilder = new TripStatisticsBuilder(startTime);
currentWaypointId = insertStatisticsMarker(null);
currentWaypointId = insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
setUpAnnouncer();
length = 0;
showNotification();
@@ -21,6 +21,7 @@ import android.database.Cursor;
import android.location.Location;
import android.net.Uri;
import java.util.Iterator;
import java.util.List;
/**
@@ -309,6 +310,87 @@ public interface MyTracksProviderUtils {
* @return a new waypoint object
*/
Waypoint createWaypoint(Cursor cursor);
/**
* A lightweight wrapper around the original {@link Cursor} with a method to clean up.
*/
interface LocationIterator extends Iterator<Location> {
/**
* Returns ID of the most recently retrieved track point through a call to {@link #next()}.
*
* @return the ID of the most recent track point ID.
*/
long getLocationId();
/**
* Should be called in case the underlying iterator hasn't reached the last record.
*/
void close();
}
/**
* A factory for creating new {@class Location}s.
*/
interface LocationFactory {
/**
* Creates a new {@link Location} object to be populated from the underlying database record.
* It's up to the implementing class to decide whether to create a new instance or reuse
* existing to optimize for speed.
*
* @return a {@link Location} to be populated from the database.
*/
Location createLocation();
}
/**
* The default {@class Location}s factory, which creates a new location of 'gps' type.
*/
LocationFactory DEFAULT_LOCATION_FACTORY = new LocationFactory() {
@Override
public Location createLocation() {
return new Location("gps");
}
};
/**
* Creates a new read-only iterator over all track points for the given track. It provides
* a lightweight way of iterating over long tracks without failing due to the underlying cursor
* limitations. Since it's a read-only iterator, {@link Iterator#remove()} always throws
* {@class UnsupportedOperationException}.
*
* Each call to {@link LocationIterator#next()} may advance to the next DB record, and if so,
* the iterator calls {@link LocationFactory#createLocation()} and populates it with information
* retrieved from the record.
*
* When done with iteration, you must call {@link LocationIterator#close()} to make sure that all
* resources are properly deallocated.
*
* Example use:
* <code>
* ...
* LocationIterator it = providerUtils.getLocationIterator(
* 1, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
* try {
* for (Location loc : it) {
* ... // Do something useful with the location.
* }
* } finally {
* it.close();
* }
* ...
* </code>
*
* @param trackId the ID of a track to retrieve locations for.
* @param startTrackPointId the ID of the first track point to load, or -1 to start from
* the first point.
* @param descending if true the results will be returned in descending ID
* order (latest location first).
* @param locationFactory the factory for creating new locations.
*
* @return the read-only iterator over the given track's points.
*/
LocationIterator getLocationIterator(long trackId, long startTrackPointId, boolean descending,
LocationFactory locationFactory);
/**
* A factory which can produce instances of {@link MyTracksProviderUtils},
@@ -15,7 +15,7 @@
*/
package com.google.android.apps.mytracks.content;
import static com.google.android.apps.mytracks.lib.MyTracksLibConstants.*;
import static com.google.android.apps.mytracks.lib.MyTracksLibConstants.TAG;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.protobuf.InvalidProtocolBufferException;
@@ -29,6 +29,7 @@ import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
/**
* Helper class providing easy access to locations and tracks in the
@@ -39,6 +40,8 @@ import java.util.List;
public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
private final ContentResolver contentResolver;
private int defaultCursorBatchSize = 2000;
public MyTracksProviderUtilsImpl(ContentResolver contentResolver) {
this.contentResolver = contentResolver;
@@ -124,7 +127,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
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) {
@@ -138,21 +140,24 @@ 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, stats.getStartTime());
values.put(WaypointsColumns.STARTID, waypoint.getStartId());
values.put(WaypointsColumns.STOPID, waypoint.getStopId());
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());
TripStatistics stats = waypoint.getStatistics();
if (stats != null) {
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());
values.put(WaypointsColumns.STARTTIME, stats.getStartTime());
}
Location location = waypoint.getLocation();
if (location != null) {
@@ -184,55 +189,78 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
fillLocation(cursor, location);
return location;
}
/**
* A cache of track column indices.
*/
private static class CachedTrackColumnIndices {
public final int idxId;
public final int idxLatitude;
public final int idxLongitude;
public final int idxAltitude;
public final int idxTime;
public final int idxBearing;
public final int idxAccuracy;
public final int idxSpeed;
public final int idxSensor;
@Override
public void fillLocation(Cursor cursor, Location location) {
public CachedTrackColumnIndices(Cursor cursor) {
idxId = cursor.getColumnIndex(TrackPointsColumns._ID);
idxLatitude = cursor.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE);
idxLongitude = cursor.getColumnIndexOrThrow(TrackPointsColumns.LONGITUDE);
idxAltitude = cursor.getColumnIndexOrThrow(TrackPointsColumns.ALTITUDE);
idxTime = cursor.getColumnIndexOrThrow(TrackPointsColumns.TIME);
idxBearing = cursor.getColumnIndexOrThrow(TrackPointsColumns.BEARING);
idxAccuracy = cursor.getColumnIndexOrThrow(TrackPointsColumns.ACCURACY);
idxSpeed = cursor.getColumnIndexOrThrow(TrackPointsColumns.SPEED);
idxSensor = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR);
}
}
private void fillLocation(Cursor cursor, CachedTrackColumnIndices columnIndices,
Location location) {
location.reset();
int idxLatitude = cursor.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE);
int idxLongitude =
cursor.getColumnIndexOrThrow(TrackPointsColumns.LONGITUDE);
int idxAltitude = cursor.getColumnIndexOrThrow(TrackPointsColumns.ALTITUDE);
int idxTime = cursor.getColumnIndexOrThrow(TrackPointsColumns.TIME);
int idxBearing = cursor.getColumnIndexOrThrow(TrackPointsColumns.BEARING);
int idxAccuracy = cursor.getColumnIndexOrThrow(TrackPointsColumns.ACCURACY);
int idxSpeed = cursor.getColumnIndexOrThrow(TrackPointsColumns.SPEED);
int idxSensor = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR);
if (!cursor.isNull(idxLatitude)) {
location.setLatitude(1. * cursor.getInt(idxLatitude) / 1E6);
if (!cursor.isNull(columnIndices.idxLatitude)) {
location.setLatitude(1. * cursor.getInt(columnIndices.idxLatitude) / 1E6);
}
if (!cursor.isNull(idxLongitude)) {
location.setLongitude(1. * cursor.getInt(idxLongitude) / 1E6);
if (!cursor.isNull(columnIndices.idxLongitude)) {
location.setLongitude(1. * cursor.getInt(columnIndices.idxLongitude) / 1E6);
}
if (!cursor.isNull(idxAltitude)) {
location.setAltitude(cursor.getFloat(idxAltitude));
if (!cursor.isNull(columnIndices.idxAltitude)) {
location.setAltitude(cursor.getFloat(columnIndices.idxAltitude));
}
if (!cursor.isNull(idxTime)) {
location.setTime(cursor.getLong(idxTime));
if (!cursor.isNull(columnIndices.idxTime)) {
location.setTime(cursor.getLong(columnIndices.idxTime));
}
if (!cursor.isNull(idxBearing)) {
location.setBearing(cursor.getFloat(idxBearing));
if (!cursor.isNull(columnIndices.idxBearing)) {
location.setBearing(cursor.getFloat(columnIndices.idxBearing));
}
if (!cursor.isNull(idxSpeed)) {
location.setSpeed(cursor.getFloat(idxSpeed));
if (!cursor.isNull(columnIndices.idxSpeed)) {
location.setSpeed(cursor.getFloat(columnIndices.idxSpeed));
}
if (!cursor.isNull(idxAccuracy)) {
location.setAccuracy(cursor.getFloat(idxAccuracy));
if (!cursor.isNull(columnIndices.idxAccuracy)) {
location.setAccuracy(cursor.getFloat(columnIndices.idxAccuracy));
}
if (location instanceof MyTracksLocation &&
!cursor.isNull(idxSensor)) {
!cursor.isNull(columnIndices.idxSensor)) {
MyTracksLocation mtLocation = (MyTracksLocation) location;
// TODO get the right buffer.
Sensor.SensorDataSet sensorData;
try {
sensorData = Sensor.SensorDataSet.parseFrom(cursor.getBlob(idxSensor));
sensorData = Sensor.SensorDataSet.parseFrom(cursor.getBlob(columnIndices.idxSensor));
mtLocation.setSensorData(sensorData);
} catch (InvalidProtocolBufferException e) {
Log.w(TAG, "Failed to parse sensor data.", e);
}
}
}
@Override
public void fillLocation(Cursor cursor, Location location) {
CachedTrackColumnIndices columnIndicies = new CachedTrackColumnIndices(cursor);
fillLocation(cursor, columnIndicies, location);
}
@Override
public Track createTrack(Cursor cursor) {
@@ -378,7 +406,6 @@ 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));
@@ -407,41 +434,57 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
if (!cursor.isNull(idxDuration)) {
waypoint.setDuration(cursor.getLong(idxDuration));
}
if (!cursor.isNull(idxStartTime)) {
stats.setStartTime(cursor.getLong(idxStartTime));
}
if (!cursor.isNull(idxStartId)) {
waypoint.setStartId(cursor.getLong(idxStartId));
}
if (!cursor.isNull(idxStopId)) {
waypoint.setStopId(cursor.getLong(idxStopId));
}
TripStatistics stats = new TripStatistics();
boolean hasStats = false;
if (!cursor.isNull(idxStartTime)) {
stats.setStartTime(cursor.getLong(idxStartTime));
hasStats = true;
}
if (!cursor.isNull(idxTotalDistance)) {
stats.setTotalDistance(cursor.getFloat(idxTotalDistance));
hasStats = true;
}
if (!cursor.isNull(idxTotalTime)) {
stats.setTotalTime(cursor.getLong(idxTotalTime));
hasStats = true;
}
if (!cursor.isNull(idxMovingTime)) {
stats.setMovingTime(cursor.getLong(idxMovingTime));
hasStats = true;
}
if (!cursor.isNull(idxMaxSpeed)) {
stats.setMaxSpeed(cursor.getFloat(idxMaxSpeed));
hasStats = true;
}
if (!cursor.isNull(idxMinElevation)) {
stats.setMinElevation(cursor.getFloat(idxMinElevation));
hasStats = true;
}
if (!cursor.isNull(idxMaxElevation)) {
stats.setMaxElevation(cursor.getFloat(idxMaxElevation));
hasStats = true;
}
if (!cursor.isNull(idxElevationGain)) {
stats.setTotalElevationGain(cursor.getFloat(idxElevationGain));
hasStats = true;
}
if (!cursor.isNull(idxMinGrade)) {
stats.setMinGrade(cursor.getFloat(idxMinGrade));
hasStats = true;
}
if (!cursor.isNull(idxMaxGrade)) {
stats.setMaxGrade(cursor.getFloat(idxMaxGrade));
hasStats = true;
}
if (hasStats) {
waypoint.setStatistics(stats);
}
Location location = new Location("");
@@ -775,13 +818,12 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
public Cursor getLocationsCursor(long trackId, long minTrackPointId,
int maxLocations, boolean descending) {
String selection;
if (minTrackPointId > 0) {
selection = String.format("%s=%d AND %s>=%d",
TrackPointsColumns.TRACKID, trackId,
TrackPointsColumns._ID, minTrackPointId);
if (minTrackPointId >= 0) {
selection = String.format("%s=%d AND %s%s%d",
TrackPointsColumns.TRACKID, trackId, TrackPointsColumns._ID,
descending ? "<=" : ">=", minTrackPointId);
} else {
selection = String.format("%s=%d",
TrackPointsColumns.TRACKID, trackId);
selection = String.format("%s=%d", TrackPointsColumns.TRACKID, trackId);
}
String sortOrder = "_id " + (descending ? "DESC" : "ASC");
@@ -789,8 +831,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
sortOrder += " LIMIT " + maxLocations;
}
return contentResolver.query(
TrackPointsColumns.CONTENT_URI, null, selection, null, sortOrder);
return contentResolver.query(TrackPointsColumns.CONTENT_URI, null, selection, null, sortOrder);
}
@Override
@@ -938,4 +979,85 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
contentResolver.update(TracksColumns.CONTENT_URI,
createContentValues(track), "_id=" + track.getId(), null);
}
@Override
public LocationIterator getLocationIterator(final long trackId, final long startTrackPointId,
final boolean descending, final LocationFactory locationFactory) {
if (locationFactory == null) {
throw new IllegalArgumentException("Expecting non-null locationFactory");
}
return new LocationIterator() {
private long lastTrackPointId = startTrackPointId;
private Cursor cursor = getCursor(startTrackPointId);
private final CachedTrackColumnIndices columnIndices = cursor != null ?
new CachedTrackColumnIndices(cursor) : null;
private Cursor getCursor(long trackPointId) {
return getLocationsCursor(trackId, trackPointId, defaultCursorBatchSize, descending);
}
private boolean advanceCursorToNextBatch() {
long pointId = lastTrackPointId + (descending ? -1 : 1);
Log.d(TAG, "Advancing cursor point ID: " + pointId);
cursor.close();
cursor = getCursor(pointId);
return cursor != null;
}
@Override
public long getLocationId() {
return lastTrackPointId;
}
@Override
public boolean hasNext() {
if (cursor == null) {
return false;
}
if (cursor.isAfterLast()) {
return false;
}
if (cursor.isLast()) {
// If the current batch size was less that max, we can safely return, otherwise
// we need to advance to the next batch.
return cursor.getCount() == defaultCursorBatchSize &&
advanceCursorToNextBatch() && !cursor.isAfterLast();
}
return true;
}
@Override
public Location next() {
if (cursor == null ||
!(cursor.moveToNext() || advanceCursorToNextBatch() || cursor.moveToNext())) {
throw new NoSuchElementException();
}
lastTrackPointId = cursor.getLong(columnIndices.idxId);
Location location = locationFactory.createLocation();
fillLocation(cursor, columnIndices, location);
return location;
}
@Override
public void close() {
if (cursor != null) {
cursor.close();
cursor = null;
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
// @VisibleForTesting
void setDefaultCursorBatchSize(int defaultCursorBatchSize) {
this.defaultCursorBatchSize = defaultCursorBatchSize;
}
}
@@ -85,7 +85,7 @@ public final class Waypoint implements Parcelable {
/** Stop track point id */
private long stopId = -1;
private TripStatistics stats = new TripStatistics();
private TripStatistics stats;
/** The length of the track, without smoothing. */
private double length;
@@ -0,0 +1,2 @@
package com.google.android.apps.mytracks.content;
parcelable WaypointCreationRequest;
@@ -0,0 +1,105 @@
/*
* 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.content;
import android.os.Parcel;
import android.os.Parcelable;
/**
* A request for the service to create a waypoint at the current location.
*
* @author Sandor Dornbush
*/
public class WaypointCreationRequest implements Parcelable {
public static enum WaypointType {
MARKER,
STATISTICS;
}
private WaypointType type;
private String name;
private String description;
private String iconUrl;
public final static WaypointCreationRequest DEFAULT_MARKER =
new WaypointCreationRequest(WaypointType.MARKER);
public final static WaypointCreationRequest DEFAULT_STATISTICS =
new WaypointCreationRequest(WaypointType.STATISTICS);
private WaypointCreationRequest(WaypointType type) {
this.type = type;
}
public WaypointCreationRequest(WaypointType type, String name,
String description, String iconUrl) {
this.type = type;
this.name = name;
this.description = description;
this.iconUrl = iconUrl;
}
public static class Creator implements Parcelable.Creator<WaypointCreationRequest> {
@Override
public WaypointCreationRequest createFromParcel(Parcel source) {
int i = source.readInt();
if (i > WaypointType.values().length) {
throw new IllegalArgumentException("Could not find waypoint type: " + i);
}
WaypointCreationRequest request = new WaypointCreationRequest(WaypointType.values()[i]);
request.description = source.readString();
request.iconUrl = source.readString();
request.name = source.readString();
return request;
}
public WaypointCreationRequest[] newArray(int size) {
return new WaypointCreationRequest[size];
}
}
public static final Creator CREATOR = new Creator();
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int arg1) {
parcel.writeInt(type.ordinal());
parcel.writeString(description);
parcel.writeString(iconUrl);
parcel.writeString(name);
}
public WaypointType getType() {
return type;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public String getIconUrl() {
return iconUrl;
}
}
@@ -15,7 +15,7 @@
*/
package com.google.android.apps.mytracks.services;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
/**
* MyTracks service.
@@ -45,18 +45,10 @@ interface ITrackRecordingService {
/**
* Inserts a waypoint marker in the track being recorded.
*
* @param waypoint the waypoint to insert
* @param request Details for the waypoint to be inserted.
* @return the unique ID of the inserted marker
*/
long insertWaypointMarker(in Waypoint waypoint);
/**
* Inserts a statistics marker in the track being recorded.
*
* @param location the location at which to insert the marker
* @return the unique ID of the inserted marker
*/
long insertStatisticsMarker(in Location location);
long insertWaypoint(in WaypointCreationRequest request);
/**
* Inserts a location in the track being recorded.
@@ -0,0 +1,171 @@
/*
* 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.content;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
import android.content.Context;
import android.location.Location;
import android.test.AndroidTestCase;
import android.test.RenamingDelegatingContext;
import android.test.mock.MockContentResolver;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A unit test for {@link MyTracksProviderUtilsImpl}.
*
* @author Bartlomiej Niechwiej
*/
public class MyTracksProviderUtilsImplTest extends AndroidTestCase {
private Context context;
private MyTracksProviderUtils providerUtils;
@Override
protected void setUp() throws Exception {
super.setUp();
MockContentResolver mockContentResolver = new MockContentResolver();
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
getContext(), getContext(), "test.");
context = new MockContext(mockContentResolver, targetContext);
MyTracksProvider provider = new MyTracksProvider();
provider.attachInfo(context, null);
mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider);
setContext(context);
providerUtils = MyTracksProviderUtils.Factory.get(context);
}
public void testLocationIterator_noPoints() {
testIterator(1, 0, 1, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
public void testLocationIterator_customFactory() {
final Location location = new Location("test_location");
final AtomicInteger counter = new AtomicInteger();
testIterator(1, 15, 4, false, new LocationFactory() {
@Override
public Location createLocation() {
counter.incrementAndGet();
return location;
}
});
// Make sure we were called exactly as many times as we had track points.
assertEquals(15, counter.get());
}
public void testLocationIterator_nullFactory() {
try {
testIterator(1, 15, 4, false, null);
fail("Expecting IllegalArgumentException");
} catch (IllegalArgumentException e) {
// Expected.
}
}
public void testLocationIterator_noBatchAscending() {
testIterator(1, 50, 100, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
testIterator(2, 50, 50, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
public void testLocationIterator_noBatchDescending() {
testIterator(1, 50, 100, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
testIterator(2, 50, 50, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
public void testLocationIterator_batchAscending() {
testIterator(1, 50, 11, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
testIterator(2, 50, 25, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
public void testLocationIterator_batchDescending() {
testIterator(1, 50, 11, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
testIterator(2, 50, 25, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
public void testLocationIterator_largeTrack() {
testIterator(1, 20000, 2000, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
private List<Location> testIterator(long trackId, int numPoints, int batchSize,
boolean descending, LocationFactory locationFactory) {
long lastPointId = initializeTrack(trackId, numPoints);
((MyTracksProviderUtilsImpl) providerUtils).setDefaultCursorBatchSize(batchSize);
List<Location> locations = new ArrayList<Location>(numPoints);
LocationIterator it = providerUtils.getLocationIterator(trackId, -1, descending, locationFactory);
try {
while (it.hasNext()) {
Location loc = it.next();
assertNotNull(loc);
locations.add(loc);
// Make sure the IDs are returned in the right order.
assertEquals(descending ? lastPointId - locations.size() + 1
: lastPointId - numPoints + locations.size(), it.getLocationId());
}
assertEquals(numPoints, locations.size());
} finally {
it.close();
}
return locations;
}
private long initializeTrack(long id, int numPoints) {
Track track = new Track();
track.setId(id);
track.setName("Test: " + id);
track.setNumberOfPoints(numPoints);
providerUtils.insertTrack(track);
track = providerUtils.getTrack(id);
assertNotNull(track);
Location[] locations = new Location[numPoints];
for (int i = 0; i < numPoints; ++i) {
Location loc = new Location("test");
loc.setLatitude(37.0 + (double) i / 10000.0);
loc.setLongitude(57.0 - (double) i / 10000.0);
loc.setAccuracy((float) i / 100.0f);
loc.setAltitude(i * 2.5);
locations[i] = loc;
}
providerUtils.bulkInsertTrackPoints(locations, numPoints, id);
// Load all inserted locations.
long lastPointId = -1;
int counter = 0;
LocationIterator it = providerUtils.getLocationIterator(id, -1, false,
MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
try {
while (it.hasNext()) {
it.next();
lastPointId = it.getLocationId();
counter++;
}
} finally {
it.close();
}
assertTrue(numPoints == 0 || lastPointId > 0);
assertEquals(numPoints, track.getNumberOfPoints());
assertEquals(numPoints, counter);
return lastPointId;
}
}
@@ -0,0 +1,55 @@
/*
* 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.content;
import com.google.android.apps.mytracks.content.WaypointCreationRequest.WaypointType;
import android.os.Parcel;
import android.test.AndroidTestCase;
/**
* Tests for the WaypointCreationRequest class.
* {@link WaypointCreationRequest}
*
* @author Sandor Dornbush
*/
public class WaypointCreationRequestTest extends AndroidTestCase {
public void testTypeParceling() {
WaypointCreationRequest original = WaypointCreationRequest.DEFAULT_MARKER;
Parcel p = Parcel.obtain();
original.writeToParcel(p, 0);
p.setDataPosition(0);
WaypointCreationRequest copy = WaypointCreationRequest.CREATOR.createFromParcel(p);
assertEquals(original.getType(), copy.getType());
assertNull(copy.getName());
assertNull(copy.getDescription());
assertNull(copy.getIconUrl());
}
public void testAllAttributesParceling() {
WaypointCreationRequest original =
new WaypointCreationRequest(WaypointType.MARKER, "name", "description", "img.png");
Parcel p = Parcel.obtain();
original.writeToParcel(p, 0);
p.setDataPosition(0);
WaypointCreationRequest copy = WaypointCreationRequest.CREATOR.createFromParcel(p);
assertEquals(original.getType(), copy.getType());
assertEquals("name", copy.getName());
assertEquals("description", copy.getDescription());
assertEquals("img.png", copy.getIconUrl());
}
}
@@ -22,6 +22,7 @@ import com.google.android.apps.mytracks.content.MyTracksProvider;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.maps.mytracks.R;
@@ -77,9 +78,11 @@ public class TrackRecordingServiceTest
}
/**
* A context wrapper with the user provided {@link ContentResolver}.
* A context wrapper with the user provided {@link ContentResolver}.
*
* TODO: Move to test utils package.
*/
private static class MockContext extends ContextWrapper {
public static class MockContext extends ContextWrapper {
private final ContentResolver contentResolver;
public MockContext(ContentResolver contentResolver, Context base) {
@@ -546,9 +549,8 @@ public class TrackRecordingServiceTest
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertFalse(service.isRecording());
Location loc = new Location("gps");
try {
service.insertStatisticsMarker(loc);
service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
fail("Expecting IllegalStateException");
} catch (IllegalStateException e) {
// Expected.
@@ -562,11 +564,22 @@ public class TrackRecordingServiceTest
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertTrue(service.isRecording());
Location loc = new Location("gps");
assertEquals(1, service.insertStatisticsMarker(loc));
assertEquals(2, service.insertStatisticsMarker(loc));
assertEquals(1, service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS));
assertEquals(2, service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS));
// TODO: Add more checks.
Waypoint wpt = providerUtils.getWaypoint(1);
assertEquals(getContext().getString(R.string.stats_icon_url),
wpt.getIcon());
assertEquals(getContext().getString(R.string.statistics),
wpt.getName());
assertEquals(Waypoint.TYPE_STATISTICS, wpt.getType());
assertEquals(123, wpt.getTrackId());
assertEquals(0.0, wpt.getLength());
assertNotNull(wpt.getLocation());
assertNotNull(wpt.getStatistics());
// TODO check the rest of the params.
// TODO: Check waypoint 2.
}
@MediumTest
@@ -574,29 +587,14 @@ public class TrackRecordingServiceTest
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertFalse(service.isRecording());
Location loc = new Location("gps");
Waypoint waypoint = new Waypoint();
waypoint.setId(1);
waypoint.setLocation(loc);
try {
service.insertWaypointMarker(waypoint);
service.insertWaypoint(WaypointCreationRequest.DEFAULT_MARKER);
fail("Expecting IllegalStateException");
} catch (IllegalStateException e) {
// Expected.
}
}
@MediumTest
public void testInsertWaypointMarker_invalidWaypoint() throws Exception {
createDummyTrack(123, -1, true);
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertTrue(service.isRecording());
Waypoint waypoint = new Waypoint();
assertEquals(-1, service.insertWaypointMarker(waypoint));
}
@MediumTest
public void testInsertWaypointMarker_validWaypoint() throws Exception {
createDummyTrack(123, -1, true);
@@ -604,11 +602,17 @@ public class TrackRecordingServiceTest
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertTrue(service.isRecording());
Location loc = new Location("gps");
Waypoint waypoint = new Waypoint();
waypoint.setId(1);
waypoint.setLocation(loc);
assertEquals(1, service.insertWaypointMarker(waypoint));
assertEquals(1, service.insertWaypoint(WaypointCreationRequest.DEFAULT_MARKER));
Waypoint wpt = providerUtils.getWaypoint(1);
assertEquals(getContext().getString(R.string.waypoint_icon_url),
wpt.getIcon());
assertEquals(getContext().getString(R.string.waypoint),
wpt.getName());
assertEquals(Waypoint.TYPE_WAYPOINT, wpt.getType());
assertEquals(123, wpt.getTrackId());
assertEquals(0.0, wpt.getLength());
assertNotNull(wpt.getLocation());
assertNull(wpt.getStatistics());
}
@MediumTest
@@ -804,11 +808,9 @@ public class TrackRecordingServiceTest
service.recordLocation(loc);
if (i % 10 == 0) {
service.insertStatisticsMarker(loc);
service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
} else if (i % 7 == 0) {
Waypoint waypoint = new Waypoint();
waypoint.setLocation(loc);
service.insertWaypointMarker(waypoint);
service.insertWaypoint(WaypointCreationRequest.DEFAULT_MARKER);
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="src" path="MyTracksLib_src"/>
<classpathentry exported="true" kind="lib" path="/MyTracksLib/libs/protobuf-java-2.3.0-lite.jar"/>
<classpathentry kind="src" path="MyTracksLib_src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -17,7 +17,10 @@ package com.google.android.apps.mytracks.signalstrength;
import static com.google.android.apps.mytracks.signalstrength.SignalStrengthConstants.*;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtilsImpl;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.services.ITrackRecordingService;
import com.google.android.apps.mytracks.signalstrength.SignalStrengthListener.SignalStrengthCallback;
@@ -53,6 +56,7 @@ public class SignalStrengthService extends Service
private ITrackRecordingService mytracksService;
private long lastSamplingTime;
private long samplingPeriod;
private MyTracksProviderUtils utils;
@Override
public void onCreate() {
@@ -63,6 +67,7 @@ public class SignalStrengthService extends Service
getString(R.string.mytracks_service_class));
preferences = PreferenceManager.getDefaultSharedPreferences(this);
signalListenerFactory = new SignalStrengthListenerFactory();
utils = new MyTracksProviderUtilsImpl(this.getContentResolver());
}
@Override
@@ -154,13 +159,6 @@ public class SignalStrengthService extends Service
return;
}
// We don't set location or track id - My Tracks can fill those
Waypoint wpt = new Waypoint();
wpt.setName("Signal Strength");
wpt.setType(Waypoint.TYPE_WAYPOINT);
wpt.setIcon(icon);
wpt.setDescription(description);
try {
long waypointId;
synchronized (this) {
@@ -169,7 +167,11 @@ public class SignalStrengthService extends Service
return;
}
waypointId = mytracksService.insertWaypointMarker(wpt);
// Create a waypoint.
WaypointCreationRequest request =
new WaypointCreationRequest(WaypointCreationRequest.WaypointType.MARKER,
"Signal Strength", icon, description);
waypointId = mytracksService.insertWaypoint(request);
}
if (waypointId >= 0) {
+2 -2
View File
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry combineaccessrules="false" exported="true" kind="src" path="/SignalStrengthSampler"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry combineaccessrules="false" kind="src" path="/SignalStrengthSampler"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="lib" path="libs/AndroidMockRuntime.jar"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin"/>
</classpath>