mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-02 17:43:06 +02:00
Merging Fusion Tables changes.
This commit is contained in:
+2
-1
@@ -6,7 +6,8 @@
|
||||
<classpathentry kind="lib" path="libs/accounts.jar"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="src" path="MyTracksLib_src"/>
|
||||
<classpathentry exported="true" kind="lib" path="/MyTracksLib/libs/protobuf-java-2.3.0-lite.jar"/>
|
||||
<classpathentry kind="lib" path="libs/google-api-client-1.2.1-alpha.jar"/>
|
||||
<classpathentry kind="src" path="MyTracksLib_src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
||||
@@ -56,11 +56,6 @@ limitations under the License.
|
||||
android:label="MyTracks"
|
||||
android:exported="false" />
|
||||
|
||||
<activity android:name="com.google.android.apps.mymaps.MyMapsList"
|
||||
android:label="@string/map_list_title"
|
||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|fontScale"
|
||||
android:exported="false" />
|
||||
|
||||
<activity android:name="com.google.android.apps.mytracks.MyTracksList"
|
||||
android:label="Recorded Tracks" />
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<launchConfiguration type="com.android.ide.eclipse.adt.debug.LaunchConfigType">
|
||||
<intAttribute key="com.android.ide.eclipse.adt.action" value="0"/>
|
||||
<stringAttribute key="com.android.ide.eclipse.adt.commandline" value=""/>
|
||||
@@ -16,8 +16,8 @@
|
||||
<listEntry value="1"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
|
||||
</listAttribute>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.ALLOW_TERMINATE" value="true"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="MyTracks"/>
|
||||
|
||||
Binary file not shown.
@@ -1,103 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2010 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apl/res/com.google.android.maps"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/list_bar"
|
||||
android:layout_weight="0"
|
||||
android:padding="3dip">
|
||||
<TextView android:id="@+id/message"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16dip"
|
||||
android:textColor="#fff"
|
||||
android:text="@string/select_map_message"
|
||||
android:layout_weight="0"/>
|
||||
</LinearLayout>
|
||||
<ListView android:id="@+id/maplist"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
<TextView android:id="@+id/mapslist_empty"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="3dip"
|
||||
android:textSize="16dip"
|
||||
android:textColor="#c00"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/mapslist_no_maps_available"
|
||||
android:visibility="gone"/>
|
||||
<TextView android:id="@+id/failed"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="3dip"
|
||||
android:textSize="16dip"
|
||||
android:textColor="#c00"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/maps_list_failed"
|
||||
android:visibility="gone"/>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/list_bar"
|
||||
android:layout_weight="0"
|
||||
android:padding="3dip">
|
||||
<LinearLayout android:id="@+id/loading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="3dip"
|
||||
android:layout_gravity="center">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
<ProgressBar
|
||||
android:layout_height="20dip"
|
||||
android:layout_width="20dip"
|
||||
android:layout_gravity="center"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:paddingLeft="3dip"
|
||||
android:textSize="16dip"
|
||||
android:textColor="#fff"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/maps_list_loading"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -42,7 +42,7 @@ limitations under the License.
|
||||
android:layout_marginTop="5dip"
|
||||
android:layout_marginLeft="5dip">
|
||||
<TableRow>
|
||||
<ImageView android:src="@drawable/mymaps_icon"
|
||||
<ImageView android:src="@drawable/googledocs_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<LinearLayout
|
||||
@@ -50,24 +50,12 @@ limitations under the License.
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginLeft="10dip">
|
||||
<CheckBox android:id="@+id/sendtogoogle_google_mymaps"
|
||||
<CheckBox android:id="@+id/sendtogoogle_google_fusiontables"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sendtogoogle_google_mymaps"
|
||||
android:text="@string/sendtogoogle_google_fusiontables"
|
||||
android:textSize="20dip"
|
||||
android:checked="true"/>
|
||||
<RadioGroup android:id="@+id/sendtogoogle_group_mymaps"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<RadioButton android:id="@+id/sendtogoogle_create_new_map"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sendtogoogle_create_new_map"/>
|
||||
<RadioButton android:id="@+id/sendtogoogle_pick_existing_map"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sendtogoogle_pick_existing_map"/>
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
|
||||
@@ -54,7 +54,6 @@ limitations under the License.
|
||||
<string name="status_tracks_have_been_uploaded">S\'ha enviat la ruta a maps.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_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>
|
||||
@@ -104,6 +103,10 @@ limitations under the License.
|
||||
<string name="error">Error</string>
|
||||
<string name="success">Fet</string>
|
||||
<string name="waypoint">Punt de referència</string>
|
||||
<string name="cancel">Cancel·la</string>
|
||||
<string name="close">Tanca</string>
|
||||
<string name="edit">Edita</string>
|
||||
<string name="save">Desa</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(Inici)</string>
|
||||
@@ -241,28 +244,6 @@ limitations under the License.
|
||||
<!-- 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:
|
||||
@@ -272,6 +253,7 @@ limitations under the License.
|
||||
<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>
|
||||
<string name="share_track">Comparteix la ruta amb amics</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">Públic</string>
|
||||
|
||||
@@ -35,7 +35,7 @@ limitations under the License.
|
||||
<!-- Error messages -->
|
||||
<string name="error_no_location_manager">Es wurde kein Dienst zur Positionsermittlung auf diesem Gerät gefunden.</string>
|
||||
<string name="error_no_gps_location_provider">Es wurde kein GPS-Empfänger auf diesem Gerät gefunden.</string>
|
||||
<string name="error_sending_to_mymap">Beim Senden des Tracks an Google MyMaps ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
|
||||
<string name="error_sending_to_fusiontables">Beim Senden des Tracks an Google Fusion Tables ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
|
||||
<string name="error_sending_to_docs">Beim Senden des Tracks an Google Docs ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
|
||||
<string name="error_unable_to_start_recording">Start der Aufzeichnung fehlgeschlagen. Bitte versuche es noch einmal.</string>
|
||||
<string name="error_unable_to_stop_recording">Anhalten unmöglich. Bitte versuche es noch einmal.</string>
|
||||
@@ -50,11 +50,10 @@ limitations under the License.
|
||||
<string name="wait_for_fix">Warte auf ein besseres GPS-Signal. Bitte stelle sicher, dass der Himmel sichtbar ist.</string>
|
||||
<string name="status_now_recording">Ein neuer Track wird aufgezeichnet.</string>
|
||||
<string name="status_stopped_recording">Die Aufzeichnung wurde angehalten.</string>
|
||||
<string name="status_new_mymap_has_been_created">Eine neue Karte wurde auf maps.google.com erstellt.</string>
|
||||
<string name="status_new_fusiontable_has_been_created">Eine neue Tabelle wurde auf google.com/fusiontables erstellt.</string>
|
||||
<string name="status_tracks_have_been_uploaded">Dein Track wurde auf maps.google.com gespeichert.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_new_doc">Dein Track wurde in einer neuen Tabelle bei docs.google.com gespeichert.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_docs">Dein Track wurde an docs.google.com gesendet.</string>
|
||||
<string name="status_mymap_info">Manchmal dauert es ein paar Minuten, bis neue Tracks bei maps.google.com erscheinen.</string>
|
||||
<string name="status_enable_gps">Hier berühren, um zu den Sicherheits- und Positionseinstellungen zu gelangen. Aktiviere \'GPS-Satelliten\'. Drücke dann den Zurück-Knopf, um hierher zurückzukehren.</string>
|
||||
<string name="status_approximate_location">Anmerkung: Eine ungefähre Position wird angezeigt, bestimmt mittels Mobilfunkstationen und WiFi-Netzwerken.</string>
|
||||
<string name="status_no_location">Die Position kann derzeit nicht bestimmt werden. Aktiviere mehr Positionsquellen (siehe Sicherheits- und Positionseinstellungen) und stelle sicher, dass der Himmel sichtbar ist.</string>
|
||||
@@ -66,11 +65,11 @@ limitations under the License.
|
||||
<string name="progress_message">Dein Track wird an Google gesendet...</string>
|
||||
<string name="progress_message_reading_track">Lese Track...</string>
|
||||
<string name="progress_message_preparing_track">Bereite Track vor...</string>
|
||||
<string name="progress_message_authenticating_mymaps">Anmeldung bei Google Maps...</string>
|
||||
<string name="progress_message_authenticating_fusiontables">Anmeldung bei Google Fusion Tables...</string>
|
||||
<string name="progress_message_authenticating_docs">Anmeldung bei Google Docs...</string>
|
||||
<string name="progress_message_sending_docs">Track wird an Google Docs gesendet...</string>
|
||||
<string name="progress_message_sending_mymaps">Track wird an Google Maps gesendet...</string>
|
||||
<string name="progress_message_creating_map">Neue \'Meine Karte\' wird erstellt...</string>
|
||||
<string name="progress_message_sending_fusiontables">Track wird an Google Fusion Tables gesendet...</string>
|
||||
<string name="progress_message_creating_fusiontable">Neue \'Fusion Tabelle\' wird erstellt...</string>
|
||||
<string name="import_progress_message">Importiere GPS-Track. Das kann ein wenig dauern.</string>
|
||||
<string name="write_progress_message">Schreibe Datei auf SD-Karte. Das kann ein wenig dauern.</string>
|
||||
<string name="progress_message_updating_track">Aktualisiere Trackstatistik...</string>
|
||||
@@ -81,7 +80,7 @@ limitations under the License.
|
||||
<string name="track_will_be_permanently_deleted">Dieser Track und seine Wegpunkte werden endgültig von diesem Gerät gelöscht.</string>
|
||||
<string name="marker_will_be_permanently_deleted">Dieser Wegpunkt wird endgültig von diesem Gerät gelöscht.</string>
|
||||
|
||||
<!-- Text and links when uploading to Google MyMaps -->
|
||||
<!-- Text and links when uploading to Google Fusion Tables -->
|
||||
<string name="new_map_description">Erstellt von My Tracks für Android.</string>
|
||||
<string name="my_map_link">Erstellt von <a href=\'http://mytracks.appspot.com\'>My Tracks</a> für Android.</string>
|
||||
<string name="new_map_title">Neue Karte</string>
|
||||
@@ -102,7 +101,10 @@ limitations under the License.
|
||||
<string name="error">Fehler</string>
|
||||
<string name="success">Erfolgreich</string>
|
||||
<string name="waypoint">Wegpunkt</string>
|
||||
|
||||
<string name="cancel">Abbrechen</string>
|
||||
<string name="edit">Bearbeiten</string>
|
||||
<string name="save">Sichern</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(Beginn)</string>
|
||||
<string name="end">(Ende)</string>
|
||||
@@ -129,7 +131,7 @@ limitations under the License.
|
||||
<string name="tracklist_all_tracks">Alle Tracks</string>
|
||||
<string name="tracklist_this_track">Dieser Track</string>
|
||||
<string name="tracklist_share_track">Mit Freunden teilen…</string>
|
||||
<string name="tracklist_share_link">Ein Link zur Google MyMaps-Karte</string>
|
||||
<string name="tracklist_share_linkfusion">Ein Link zur Google Fusion Tables-Karte</string>
|
||||
<string name="tracklist_share_gpx_file">Eine GPX-Datei</string>
|
||||
<string name="tracklist_share_kml_file">Eine KML-Datei</string>
|
||||
<string name="tracklist_share_csv_file">Eine CSV-Datei</string>
|
||||
@@ -236,30 +238,9 @@ limitations under the License.
|
||||
|
||||
<!-- MyTracksSky -->
|
||||
<string name="mytracks_sky">GPS-Satelliten</string>
|
||||
|
||||
<!-- MyMaps -->
|
||||
<string name="select_map_message">Wähle eine Karte von Deinem Konto aus</string>
|
||||
<string name="create_new_map">Neue Karte erstellen…</string>
|
||||
<string name="map_list_title">An Google My Maps senden</string>
|
||||
<string name="maps_list_loading">Karten werden geladen…</string>
|
||||
<string name="maps_list_failed">Deine Karten konnten im Augenblick nicht geladen werden!</string>
|
||||
<string name="open_map">Diese Karte auswählen</string>
|
||||
<string name="edit_map_details">Kartendetails bearbeiten</string>
|
||||
<string name="share_map">Karte mit Freunden teilen</string>
|
||||
<string name="share_track">Track mit Freunden teilen</string>
|
||||
<string name="delete_map">Karte vom Konto löschen</string>
|
||||
<string name="map_title">Kartentitel</string>
|
||||
<string name="map_description">Trackbeschreibung</string>
|
||||
<string name="map_searchable_edit">Diese Karte und ihren Inhalt in Suchergebnissen sichtbar machen.</string>
|
||||
<string name="map_not_searchable_edit">Diese Karte und ihren Inhalt nicht in Suchergebnissen sichtbar machen.</string>
|
||||
<string name="map_searchable">Diese Karte und ihr Inhalt sind in Suchergebnissen sichtbar.</string>
|
||||
<string name="map_not_searchable">Weder diese Karte noch ihr Inhalt sind in Suchergebnissen sichtbar, allerdings kann sie trotzdem von anderen durch einen direkten Link angezeigt werden.</string>
|
||||
<string name="close">Schließen</string>
|
||||
<string name="edit">Bearbeiten</string>
|
||||
<string name="cancel">Abbrechen</string>
|
||||
<string name="save">Sichern</string>
|
||||
|
||||
|
||||
<!-- Sharing -->
|
||||
<string name="share_map">Karte mit Freunden teilen</string>
|
||||
<string name="share_map_subject">Ich möchte gerne eine Karte mit Dir teilen.</string>
|
||||
<string name="share_map_body_format">Vielleicht interessierst Du Dich für diese Karte:
|
||||
|
||||
@@ -267,13 +248,14 @@ limitations under the License.
|
||||
<string name="send_track_subject">Ich möchte einen GPS-Track mit Dir teilen</string>
|
||||
<string name="send_track_body_format">Vielleicht interessierst Du Dich für diese Track:
|
||||
|
||||
%s.</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">Öffentlich</string>
|
||||
<string name="unlisted_map">Nicht in Suchergebnissen enthalten.</string>
|
||||
<string name="mapslist_no_maps_available">Du hast noch keine Karten.</string>
|
||||
|
||||
%s.</string>
|
||||
<string name="share_track">Track mit Freunden teilen</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">Öffentlich</string>
|
||||
<string name="unlisted_map">Nicht in Suchergebnissen enthalten.</string>
|
||||
<string name="mapslist_no_maps_available">Du hast noch keine Karten.</string>
|
||||
|
||||
<!-- Statistics View -->
|
||||
<!-- Average Moving -->
|
||||
<string name="average_moving_speed_label">Durchschnitt in Bew.</string>
|
||||
@@ -361,8 +343,6 @@ limitations under the License.
|
||||
<!-- Send to Google -->
|
||||
<string name="sendtogoogle_title">Senden an…</string>
|
||||
<string name="sendtogoogle_send_now">Jetzt senden</string>
|
||||
<string name="sendtogoogle_create_new_map">Neue Karte erstellen</string>
|
||||
<string name="sendtogoogle_pick_existing_map">Eine Karte auswählen</string>
|
||||
<string name="sendtogoogle_send_stats">Trackstatistik senden</string>
|
||||
<string name="sendtogoogle_send_stats_and_points">Statistik und Punkte senden</string>
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ limitations under the License.
|
||||
<string name="status_tracks_have_been_uploaded">Su recorrido ha sido enviado a maps.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_new_doc">Su recorrido ha sido enviado a una nueva hoja de cálculo en docs.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_docs">Su recorrido ha sido enviado a docs.google.com.</string>
|
||||
<string name="status_mymap_info">A veces nuevos recorridos pueden tardar algunos minutos en aparecer.</string>
|
||||
<string name="status_enable_gps">Por favor presione aquí para ir al menú de Seguridad y Ubicación y asegúrese que el GPS esté habilitado. Presione el botón de regreso para regresar.</string>
|
||||
<string name="status_approximate_location">Nota: Una ubicación aproximada es mostrada, basada en informacion de torres de telefonía celular y red WIFI.</string>
|
||||
<string name="status_no_location">La ubicación actual no puede ser determinada. Habilite más fuentes de datos (vea configuraciones de Seguridad y Ubicación) y asegúrese que el cielo sea visible. Inténtelo mas tarde.</string>
|
||||
@@ -98,6 +97,7 @@ limitations under the License.
|
||||
<string name="yes">Sí</string>
|
||||
<string name="success">Éxito</string>
|
||||
<string name="waypoint">Señal de recorrido</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(Inicio)</string>
|
||||
@@ -193,30 +193,10 @@ limitations under the License.
|
||||
|
||||
<!-- MyTracksSky -->
|
||||
<string name="mytracks_sky">Satélites GPS</string>
|
||||
|
||||
<!-- My Maps -->
|
||||
<string name="select_map_message">Elija un mapa de su cuenta:</string>
|
||||
<string name="create_new_map">Crear mapa nuevo...</string>
|
||||
<string name="map_list_title">Enviar a Google My Maps</string>
|
||||
<string name="maps_list_loading">Cargando mapas...</string>
|
||||
<string name="maps_list_failed">Sus mapas no pudieron ser cargados en este momento!</string>
|
||||
<string name="open_map">Seleccione este mapa</string>
|
||||
<string name="edit_map_details">Editar detalles del mapa</string>
|
||||
<string name="share_map">Compartir mapa con amigos</string>
|
||||
<string name="share_track">Compartir recorrido con amigos</string>
|
||||
<string name="delete_map">Borrar mapa de su cuenta</string>
|
||||
<string name="map_title">Título del mapa:</string>
|
||||
<string name="map_description">Descripción del mapa:</string>
|
||||
<string name="map_searchable_edit">Permitir que este mapa y su contenido sean mostrados en resultados de búsqueda</string>
|
||||
<string name="map_not_searchable_edit">No permitir que este mapa y su contenido sean mostrados en resultados de búsqueda, pero permitir acceso directo mediante su URL</string>
|
||||
<string name="map_searchable">Este mapa y su contenido serán mostrados en resultados de búsqueda</string>
|
||||
<string name="map_not_searchable">No mostrar ni este mapa ni sus contenidos en resultados de búsqueda, pero permitir acceso directo mediante su URL</string>
|
||||
<string name="close">Cerrar</string>
|
||||
<string name="edit">Editar</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="save">Guardar</string>
|
||||
|
||||
<!-- Sharing -->
|
||||
<string name="share_map">Compartir mapa con amigos</string>
|
||||
<string name="share_map_subject">Me gustaría compartir un mapa contigo</string>
|
||||
<string name="share_map_body_format">Creo que este mapa pudiera interesarte:
|
||||
|
||||
@@ -225,6 +205,7 @@ limitations under the License.
|
||||
<string name="send_track_body_format">Creo que este recorrido pudiera interesarte.
|
||||
|
||||
Para ver este recorrido usa Google Earth o algún otro software de mapeo.</string>
|
||||
<string name="share_track">Compartir recorrido con amigos</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">Público</string>
|
||||
@@ -315,8 +296,6 @@ limitations under the License.
|
||||
<!-- Send to Google -->
|
||||
<string name="sendtogoogle_title">Enviar a...</string>
|
||||
<string name="sendtogoogle_send_now">Enviar ahora</string>
|
||||
<string name="sendtogoogle_create_new_map">Crear un nuevo mapa</string>
|
||||
<string name="sendtogoogle_pick_existing_map">Escoja un mapa existente</string>
|
||||
<string name="sendtogoogle_send_stats">Enviar estadísticas de recorrido</string>
|
||||
<string name="sendtogoogle_send_stats_and_points">Enviar estadísticas y puntos</string>
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ limitations under the License.
|
||||
<string name="status_tracks_have_been_uploaded">Votre parcours a été envoyé à maps.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_new_doc">Votre parcours a été envoyé dans un tableur à docs.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_docs">Votre parcours a été envoyé à docs.google.com.</string>
|
||||
<string name="status_mymap_info">Votre parcours peut prendre quelques minutes avant d\'être visible.</string>
|
||||
<string name="status_enable_gps">Cliquez ici et allez dans \'Paramètres\', \'Sécurité et Localisation\' et selectionnez \'Activer les satellites GPS\'. Appuyez sur le bouton de retour pour revenir au menu.</string>
|
||||
<string name="status_approximate_location">Note : Votre position est approximative, elle a été déterminée par les antennes de téléphonie ou le réseau WiFi.</string>
|
||||
<string name="status_no_location">Votre position ne peut être déterminée. Vérifiez votre configuration dans \'Paramètres\', \'Sécurité et Localisation\'. Assurez-vous également que le ciel soit bien visible.</string>
|
||||
@@ -100,6 +99,10 @@ limitations under the License.
|
||||
<string name="yes">Oui</string>
|
||||
<string name="error">Erreur</string>
|
||||
<string name="waypoint">Point de passage</string>
|
||||
<string name="cancel">Annuler</string>
|
||||
<string name="close">Fermer</string>
|
||||
<string name="edit">Modifier</string>
|
||||
<string name="save">Enregistrer</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(Début)</string>
|
||||
@@ -194,29 +197,8 @@ limitations under the License.
|
||||
<!-- MyTracksSky -->
|
||||
<string name="mytracks_sky">Satellites GPS</string>
|
||||
|
||||
<!-- MyMaps -->
|
||||
<string name="select_map_message">Choisissez une carte de votre compte :</string>
|
||||
<string name="create_new_map">Création d\'une nouvelle carte en cours...</string>
|
||||
<string name="map_list_title">Envoyer à Google Mes cartes</string>
|
||||
<string name="maps_list_loading">Chargements de vos cartes...</string>
|
||||
<string name="maps_list_failed">Vos cartes n\'ont pu être chargées</string>
|
||||
<string name="open_map">Sélectionnez la carte</string>
|
||||
<string name="edit_map_details">Consulter les détails de la carte</string>
|
||||
<string name="share_map">Partager.</string>
|
||||
<string name="share_track">Partager des parcours.</string>
|
||||
<string name="delete_map">Supprimer la carte de votre compte.</string>
|
||||
<string name="map_title">Titre de la carte :</string>
|
||||
<string name="map_description">Description de la carte :</string>
|
||||
<string name="map_searchable_edit">Rendre cette carte et son contenu visibles dans les résultats de recherche.</string>
|
||||
<string name="map_not_searchable_edit">Ne pas inclure cette carte et sont contenu dans les résultats de recherche. Ils seront cependant consultables par d\'autres utilisateurs en utilisant l\'adresse URL exacte</string>
|
||||
<string name="map_searchable">Cette carte et son contenu seront visibles dans les résultats de recherche</string>
|
||||
<string name="map_not_searchable">Ni cette carte, ni son contenu seront visible dans les résultats de recherche, mais ils seront consultables en utilisant l\'adresse URL exacte</string>
|
||||
<string name="close">Fermer</string>
|
||||
<string name="edit">Modifier</string>
|
||||
<string name="cancel">Annuler</string>
|
||||
<string name="save">Enregistrer</string>
|
||||
|
||||
<!-- Sharing -->
|
||||
<string name="share_map">Partager.</string>
|
||||
<string name="share_map_subject">Je voudrais partager ma carte avec vous</string>
|
||||
<string name="share_map_body_format">Je pense que cette carte vous intéressera :
|
||||
|
||||
@@ -225,6 +207,7 @@ limitations under the License.
|
||||
<string name="send_track_body_format">Je pense que ce parcours vous intéressera.
|
||||
|
||||
Pour voir ce parcours, utilisez Google Earth ou tout autre logiciel de cartographie.</string>
|
||||
<string name="share_track">Partager des parcours.</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="unlisted_map">Carte non listée</string>
|
||||
|
||||
@@ -54,7 +54,6 @@ limitations under the License.
|
||||
<string name="status_tracks_have_been_uploaded">Il tuo percorso è stato inviato a maps.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_new_doc">Il tuo percorso è stato inviato ad un nuovo foglio di calcolo su docs.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_docs">Il tuo percorso è stato inviato a docs.google.com.</string>
|
||||
<string name="status_mymap_info">Potrebbe essere necessario aspettare qualche minuto prima che i nuovi percorsi siano visibili.</string>
|
||||
<string name="status_enable_gps">Premi qui per andare a «Impostazioni di posizione e protezione» e attiva «Utilizza satelliti GPS». Poi premi il tasto di ritorno per tornare qui.</string>
|
||||
<string name="status_approximate_location">Nota: la posizione indicata è un\'approssimazione determinata in base alle antenne cellulari e reti WIFI vicine.</string>
|
||||
<string name="status_no_location">La posizione non può essere determinata. Attiva più fonti di posizione (vedi «Impostazioni di posizione e protezione») e eccertati che il cielo sia visibile. Riprova più tardi.</string>
|
||||
@@ -104,6 +103,10 @@ limitations under the License.
|
||||
<string name="error">Errore</string>
|
||||
<string name="success">Successo</string>
|
||||
<string name="waypoint">Punto di passaggio</string>
|
||||
<string name="cancel">Annulla</string>
|
||||
<string name="close">Chiudi</string>
|
||||
<string name="edit">Modifica</string>
|
||||
<string name="save">Salva</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(Inizio)</string>
|
||||
@@ -200,28 +203,6 @@ limitations under the License.
|
||||
<!-- MyTracksSky -->
|
||||
<string name="mytracks_sky">Satelliti GPS</string>
|
||||
|
||||
<!-- My Maps -->
|
||||
<string name="select_map_message">Scegli una mappa dal tuo account:</string>
|
||||
<string name="create_new_map">Crea una nuova mappa...</string>
|
||||
<string name="map_list_title">Invia a «Le mie mappe» di Google</string>
|
||||
<string name="maps_list_loading">Caricamento mappe in corso...</string>
|
||||
<string name="maps_list_failed">Le tue mappe non possono momentaneamente essere caricate!</string>
|
||||
<string name="open_map">Scegli questa mappa</string>
|
||||
<string name="edit_map_details">Modifica dettagli della mappa</string>
|
||||
<string name="share_map">Condividi la mappa con amici</string>
|
||||
<string name="share_track">Condividi il percorso con amici</string>
|
||||
<string name="delete_map">Elimina la mappa dal tuo account</string>
|
||||
<string name="map_title">Titolo della mappa:</string>
|
||||
<string name="map_description">Descrizione della mappa:</string>
|
||||
<string name="map_searchable_edit">Rendi questa mappa e il suo contenuto visibili fra i risultati di ricerche</string>
|
||||
<string name="map_not_searchable_edit">Rendi questa mappa e il suo contenuto invisibili fra i risultati di ricerche. Resteranno comunque visibili ad altri utilizzando l\'indirizzo URL esatto</string>
|
||||
<string name="map_searchable">Questa mappa e il suo contenuto saranno visibili fra i risultati di ricerche</string>
|
||||
<string name="map_not_searchable">Né questa mappa né il suo contenuto saranno visibili in risultati di ricerche, ma saranno comunque visibili ad altri tramite un link diretto.</string>
|
||||
<string name="close">Chiudi</string>
|
||||
<string name="edit">Modifica</string>
|
||||
<string name="cancel">Annulla</string>
|
||||
<string name="save">Salva</string>
|
||||
|
||||
<!-- Sharing -->
|
||||
<string name="share_map_subject">Vorrei condividere una mappa con te</string>
|
||||
<string name="share_map_body_format">Credo che questa mappa potrebbe interessarti:
|
||||
@@ -231,6 +212,7 @@ limitations under the License.
|
||||
<string name="send_track_body_format">Credo che questo percorso potrebbe interessarti.
|
||||
|
||||
Per vedere questo percorso, usa Google Earth o un altro software di cartografia.</string>
|
||||
<string name="share_track">Condividi il percorso con amici</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">Pubblica</string>
|
||||
|
||||
@@ -52,7 +52,6 @@ limitations under the License.
|
||||
<string name="status_tracks_have_been_uploaded">トラックを maps.google.com に送信しました.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_new_doc">トラックを docs.google.com の新しいスプレッドシートに送信しました.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_docs">トラックを docs.google.com に送信しました.</string>
|
||||
<string name="status_mymap_info">新しいトラックが見えるようになるまで数分程度かかります.</string>
|
||||
<string name="status_enable_gps">ここをタップして,セキュリティ &位置情報 を開いて,「GPS機能をONにする」にチェックして下さい.バックボタンで戻ってください.</string>
|
||||
<string name="status_approximate_location">ご注意: 携帯電話中継局とWi-Fiネットワークから大まかな位置を特定します.</string>
|
||||
<string name="status_no_location">現在位置決定ができません.位置取得源を増やし(セキュリティ&位置情報をご覧ください),空が見えるようにして下さい.もう一度試して下さい.</string>
|
||||
@@ -102,6 +101,10 @@ limitations under the License.
|
||||
<string name="error">エラー</string>
|
||||
<string name="success">成功</string>
|
||||
<string name="waypoint">ウェイポイント</string>
|
||||
<string name="cancel">キャンセル</string>
|
||||
<string name="close">閉じる</string>
|
||||
<string name="edit">編集</string>
|
||||
<string name="save">保存</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(開始)</string>
|
||||
@@ -201,30 +204,6 @@ limitations under the License.
|
||||
<!-- 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">このマップに興味を持って頂けると思います:
|
||||
@@ -234,6 +213,7 @@ limitations under the License.
|
||||
<string name="send_track_body_format">このトラックに興味を持って頂けると思います.
|
||||
|
||||
このトラックを閲覧するには,Google Earthまたは他のマッピングソフトウェアが必要です.</string>
|
||||
<string name="share_track">トラックの共有</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">公開</string>
|
||||
|
||||
@@ -53,7 +53,6 @@ limitations under the License.
|
||||
<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>
|
||||
@@ -103,6 +102,10 @@ limitations under the License.
|
||||
<string name="error">Błąd</string>
|
||||
<string name="success">Powodzenie</string>
|
||||
<string name="waypoint">Punkt orientacyjny</string>
|
||||
<string name="cancel">Anuluj</string>
|
||||
<string name="close">Zamknij</string>
|
||||
<string name="edit">Edytuj</string>
|
||||
<string name="save">Zapisz</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(Początek)</string>
|
||||
@@ -233,28 +236,6 @@ limitations under the License.
|
||||
<!-- 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:
|
||||
@@ -264,6 +245,7 @@ limitations under the License.
|
||||
<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>
|
||||
<string name="share_track">Podziel się trasą z przyjaciółmi</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">Publiczna</string>
|
||||
|
||||
@@ -52,7 +52,6 @@ limitations under the License.
|
||||
<string name="status_tracks_have_been_uploaded">Seu caminho foi enviado para maps.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_new_doc">Seu caminho foi enviado para uma nova planilha em docs.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_docs">Seu caminho foi enviado para docs.google.com.</string>
|
||||
<string name="status_mymap_info">"Pode demorar alguns minutor para que novos caminhos apareçam.</string>
|
||||
<string name="status_enable_gps">"Por favor pressione aqui para ir aos ajustes de segurança e localização e verifique que o GPS esteja habilitado. Pressione o botão de voltar para retornar."</string>
|
||||
<string name="status_approximate_location">Nota: Uma localização aproximada, determinada por torres de telefonia celular, está sendo mostrada.</string>
|
||||
<string name="status_no_location">Sua localização não pôde ser determinada. Habilite fontes adicionais de localização (veja configurações de Segurança e Localização) e assegure-se de que o céu está visível.</string>
|
||||
@@ -101,6 +100,10 @@ limitations under the License.
|
||||
<string name="error">Erro</string>
|
||||
<string name="success">Successo</string>
|
||||
<string name="waypoint">Ponto de passagem</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="close">Fechar</string>
|
||||
<string name="edit">Editar</string>
|
||||
<string name="save">Salvar</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(Início)</string>
|
||||
@@ -184,28 +187,6 @@ limitations under the License.
|
||||
<!-- MyTracksSky -->
|
||||
<string name="mytracks_sky">Satélites de GPS</string>
|
||||
|
||||
<!-- My Maps -->
|
||||
<string name="select_map_message">Escolha um mapa da sua conta:</string>
|
||||
<string name="create_new_map">Criar novo mapa...</string>
|
||||
<string name="map_list_title">Enviar para o Google Meus Mapas</string>
|
||||
<string name="maps_list_loading">Carregando mapas...</string>
|
||||
<string name="maps_list_failed">Seus mapas não puderam ser carregados neste momento!</string>
|
||||
<string name="open_map">Selecionar este Mapa</string>
|
||||
<string name="edit_map_details">Editar detalhes do mapa</string>
|
||||
<string name="share_map">Compartilhar mapa com amigos</string>
|
||||
<string name="share_track">Compartilhar caminho com amigos</string>
|
||||
<string name="delete_map">Apagar mapa da sua conta</string>
|
||||
<string name="map_title">Título do Mapa:</string>
|
||||
<string name="map_description">Descrição do Mapa:</string>
|
||||
<string name="map_searchable_edit">Fazer com que o conteúdo deste mapa apareça em resultados de buscas</string>
|
||||
<string name="map_not_searchable_edit">Não permitir que este mapa ou seu conteúdo apareçam em resultados de buscas, porém ele ainda pode ser visto por sua URL direta</string>
|
||||
<string name="map_searchable">Este mapa e seu conteúdo vão aparecer em resultados de buscas</string>
|
||||
<string name="map_not_searchable">Nem este mapa nem seu conteúdo vão aparecer em resultados de buscas, porém outras pessoas ainda podem vê-los se obtiverem sua URL direta</string>
|
||||
<string name="close">Fechar</string>
|
||||
<string name="edit">Editar</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="save">Salvar</string>
|
||||
|
||||
<!-- Sharing -->
|
||||
<string name="share_map_subject">Eu gostaria de compartilhar um mapa com você</string>
|
||||
<string name="share_map_body_format">Eu acredito que você pode se interessar por este mapa:
|
||||
@@ -215,6 +196,7 @@ limitations under the License.
|
||||
<string name="send_track_body_format">Eu acredito que você pode se interesasr por este caminho.
|
||||
|
||||
Para visualizar este caminho, use o Google Earth ou outro software de mapas.</string>
|
||||
<string name="share_track">Compartilhar caminho com amigos</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">Público</string>
|
||||
|
||||
@@ -53,7 +53,6 @@ limitations under the License.
|
||||
<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 skickats 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 ungefä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>
|
||||
@@ -103,6 +102,10 @@ limitations under the License.
|
||||
<string name="error">Fel</string>
|
||||
<string name="success">Lyckades</string>
|
||||
<string name="waypoint">Positionsmärke</string>
|
||||
<string name="cancel">Avbryt</string>
|
||||
<string name="close">Stäng</string>
|
||||
<string name="edit">Ändra</string>
|
||||
<string name="save">Spara</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(Start)</string>
|
||||
@@ -202,28 +205,6 @@ limitations under the License.
|
||||
<!-- MyTracksSky -->
|
||||
<string name="mytracks_sky">GPS-satelliter</string>
|
||||
|
||||
<!-- My Maps -->
|
||||
<string name="select_map_message">Välj 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 Mina Kartor</string>
|
||||
<string name="maps_list_loading">Laddar kartor...</string>
|
||||
<string name="maps_list_failed">Dina 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änk</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:
|
||||
@@ -233,6 +214,7 @@ limitations under the License.
|
||||
<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>
|
||||
<string name="share_track">Dela spår med vänner</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">Publik</string>
|
||||
|
||||
@@ -56,7 +56,6 @@ limitations under the License.
|
||||
<string name="status_tracks_have_been_uploaded">你的轨迹已经发送到 maps.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_new_doc">你的轨迹已经作为新的电子表格发送到 docs.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_docs">你的轨迹已经发送到 docs.google.com.</string>
|
||||
<string name="status_mymap_info">新增的轨迹可能需要等待一段时间才会显示到页面上.</string>
|
||||
<string name="status_enable_gps">请点击这里进入\'安全和位置设置\'并勾选上\'启用 GPS 卫星\'. 然后用后退键返回.</string>
|
||||
<string name="status_approximate_location">注意: 当前显示的位置是根据无线信号和无线网络计算的近似位置.</string>
|
||||
<string name="status_no_location">目前无法定位. 请启用更多的位置来源 (在\'安全和位置设置\'中) 并确认天空是可见的. 再重试.</string>
|
||||
@@ -106,6 +105,10 @@ limitations under the License.
|
||||
<string name="error">错误</string>
|
||||
<string name="success">成功</string>
|
||||
<string name="waypoint">路点</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="close">关闭</string>
|
||||
<string name="edit">编辑</string>
|
||||
<string name="save">保存</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(开始)</string>
|
||||
@@ -239,28 +242,6 @@ limitations under the License.
|
||||
<!-- 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 My Maps</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">不允许地图及其内容出现在搜索结果中, 但它的内容依然可以通过网址直接访问</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">我想你可能会对这个地图感兴趣:
|
||||
@@ -270,6 +251,7 @@ limitations under the License.
|
||||
<string name="send_track_body_format">我想你可能会对这条轨迹感兴趣.
|
||||
|
||||
请用 Google Earth 或其它地图软件查看此轨迹.</string>
|
||||
<string name="share_track">与朋友分享轨迹</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">公开</string>
|
||||
|
||||
@@ -35,7 +35,7 @@ limitations under the License.
|
||||
<!-- Error messages -->
|
||||
<string name="error_no_location_manager">No location manager was found on this device!</string>
|
||||
<string name="error_no_gps_location_provider">No GPS location provider was found on this device.</string>
|
||||
<string name="error_sending_to_mymap">There was an error while sending your track to Google My Map. Please try again later.</string>
|
||||
<string name="error_sending_to_fusiontables">There was an error while sending your track to Google Fusion Tables. Please try again later.</string>
|
||||
<string name="error_sending_to_docs">There was an error while sending your track to Google Docs. Please try again later.</string>
|
||||
<string name="error_unable_to_start_recording">Unable to start recording. Try again.</string>
|
||||
<string name="error_unable_to_stop_recording">Unable to stop recording. Try again.</string>
|
||||
@@ -50,11 +50,10 @@ limitations under the License.
|
||||
<string name="wait_for_fix">Waiting for a better GPS fix. Make sure the sky is visible.</string>
|
||||
<string name="status_now_recording">Now recording a new track.</string>
|
||||
<string name="status_stopped_recording">Stopped recording your track.</string>
|
||||
<string name="status_new_mymap_has_been_created">A new Google My Map has been created at maps.google.com.</string>
|
||||
<string name="status_new_fusiontable_has_been_created">A new Google Fusion table has been created at google.com/fusiontables.</string>
|
||||
<string name="status_tracks_have_been_uploaded">Your track has been sent to maps.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_new_doc">Your track has been sent to a new spreadsheet at docs.google.com.</string>
|
||||
<string name="status_tracks_have_been_uploaded_to_docs">Your track has been sent to docs.google.com.</string>
|
||||
<string name="status_mymap_info">It may sometimes take a few minutes before new tracks appear.</string>
|
||||
<string name="status_enable_gps">Please tap here to go to Security and Location Settings and check \'enable GPS satellites\'. Press back button to return.</string>
|
||||
<string name="status_approximate_location">Note: An approximate location as determined from cell towers and WIFI networks is shown.</string>
|
||||
<string name="status_no_location">A location can currently not be determined. Enable more location sources (see Security and Location Settings) and make sure the sky is visible. Try again later.</string>
|
||||
@@ -66,11 +65,11 @@ limitations under the License.
|
||||
<string name="progress_message">Sending your track to Google.</string>
|
||||
<string name="progress_message_reading_track">Reading track...</string>
|
||||
<string name="progress_message_preparing_track">Preparing track...</string>
|
||||
<string name="progress_message_authenticating_mymaps">Authenticating to Google Maps...</string>
|
||||
<string name="progress_message_authenticating_fusiontables">Authenticating to Google Fusion Tables...</string>
|
||||
<string name="progress_message_authenticating_docs">Authenticating to Google Docs...</string>
|
||||
<string name="progress_message_sending_docs">Sending track to Google Docs...</string>
|
||||
<string name="progress_message_sending_mymaps">Sending track to Google Maps...</string>
|
||||
<string name="progress_message_creating_map">Creating new My Map...</string>
|
||||
<string name="progress_message_sending_fusiontables">Sending track to Fusion Tables...</string>
|
||||
<string name="progress_message_creating_fusiontable">Creating new Fusion table...</string>
|
||||
<string name="import_progress_message">Importing a GPS track. This may take a while.</string>
|
||||
<string name="write_progress_message">Writing file to SD card. This may take a while.</string>
|
||||
<string name="progress_message_updating_track">Updating track statistics...</string>
|
||||
@@ -81,10 +80,9 @@ limitations under the License.
|
||||
<string name="track_will_be_permanently_deleted">The track and its markers will be permanently deleted from this phone.</string>
|
||||
<string name="marker_will_be_permanently_deleted">The marker will be permanently deleted from this phone.</string>
|
||||
|
||||
<!-- Text and links when uploading to Google My Maps -->
|
||||
<!-- Text and links when uploading to Google Fusion Tables -->
|
||||
<string name="new_map_description">Created by My Tracks on Android.</string>
|
||||
<string name="my_map_link">Created by <a href=\'http://mytracks.appspot.com\'>My Tracks</a> on Android.</string>
|
||||
<string name="new_map_title">New map</string>
|
||||
<string name="fusiontable_link">Created by <a href=\'http://mytracks.appspot.com\'>My Tracks</a> on Android.</string>
|
||||
|
||||
<!-- Formatting of track and marker descriptions -->
|
||||
<string name="points">Points</string>
|
||||
@@ -105,6 +103,10 @@ limitations under the License.
|
||||
<string name="success">Success</string>
|
||||
<string name="waypoint">Waypoint</string>
|
||||
<string name="license">License</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="edit">Edit</string>
|
||||
<string name="save">Save</string>
|
||||
|
||||
<!-- Placemark labels for start and end of track -->
|
||||
<string name="start">(Start)</string>
|
||||
@@ -112,8 +114,8 @@ limitations under the License.
|
||||
|
||||
<!-- TrackList -->
|
||||
<string name="tracklist_show_track">Show</string>
|
||||
<string name="tracklist_send_to_mymaps">Send to Google My Maps</string>
|
||||
<string name="tracklist_send_to_new_mymap">Send to New Google My Map</string>
|
||||
<string name="tracklist_send_to_fusiontables">Send to Google Fusion Tables</string>
|
||||
<string name="tracklist_send_to_new_fusiontable">Send to New Google Fusion Table</string>
|
||||
<string name="tracklist_send_to_docs">Send to Google Docs</string>
|
||||
<string name="tracklist_send_to_google">Send to Google...</string>
|
||||
<string name="tracklist_delete_track">Delete from phone...</string>
|
||||
@@ -123,7 +125,7 @@ limitations under the License.
|
||||
<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_send_all_to_fusiontables">Send to Google Fusion Tables</string>
|
||||
<string name="tracklist_btn_delete_all">Delete all tracks</string>
|
||||
<!-- Export All -->
|
||||
<string name="tracklist_btn_export_all">Export all tracks</string>
|
||||
@@ -132,7 +134,7 @@ limitations under the License.
|
||||
<string name="tracklist_all_tracks">All Tracks:</string>
|
||||
<string name="tracklist_this_track">This Track</string>
|
||||
<string name="tracklist_share_track">Share with Friends...</string>
|
||||
<string name="tracklist_share_link">A link to Google My Map</string>
|
||||
<string name="tracklist_share_linkfusion">A link to Google Fusion Tables</string>
|
||||
<string name="tracklist_share_gpx_file">A GPX file</string>
|
||||
<string name="tracklist_share_kml_file">A KML file</string>
|
||||
<string name="tracklist_share_csv_file">A CSV file</string>
|
||||
@@ -242,37 +244,17 @@ limitations under the License.
|
||||
<!-- MyTracksSky -->
|
||||
<string name="mytracks_sky">GPS Satellites</string>
|
||||
|
||||
<!-- My Maps -->
|
||||
<string name="select_map_message">Pick a map from your account:</string>
|
||||
<string name="create_new_map">Create new map...</string>
|
||||
<string name="map_list_title">Send to Google My Maps</string>
|
||||
<string name="maps_list_loading">Loading maps...</string>
|
||||
<string name="maps_list_failed">Your maps could not be loaded at this time!</string>
|
||||
<string name="open_map">Select this Map</string>
|
||||
<string name="edit_map_details">Edit Map Details</string>
|
||||
<string name="share_map">Share Map with Friends</string>
|
||||
<string name="share_track">Share Track with Friends</string>
|
||||
<string name="delete_map">Delete Map from your Account</string>
|
||||
<string name="map_title">Map Title:</string>
|
||||
<string name="map_description">Map Description:</string>
|
||||
<string name="map_searchable_edit">Make this map and its contents show up in search results</string>
|
||||
<string name="map_not_searchable_edit">Do not let this map or its contents show up in search results, though they may still be viewed be others through the direct URL</string>
|
||||
<string name="map_searchable">This map and its contents will show in search results</string>
|
||||
<string name="map_not_searchable">Neither this map nor its contents will show in search results, but they may still be viewed by others through a direct link</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="edit">Edit</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="save">Save</string>
|
||||
|
||||
<!-- Sharing -->
|
||||
<string name="share_map_subject">I would like to share a map with you</string>
|
||||
<string name="share_map_body_format">I think you might be interested in this map:
|
||||
<string name="share_map">Share map with friends</string>
|
||||
<string name="share_map_subject">I would like to share a track with you</string>
|
||||
<string name="share_map_body_format">I think you might be interested in this track:
|
||||
|
||||
%s</string>
|
||||
<string name="send_track_subject">I would like to share a track with you</string>
|
||||
<string name="send_track_body_format">I think you might be interested in this track.
|
||||
|
||||
To view this track use Google Earth or other mapping software.</string>
|
||||
<string name="share_track">Share track with friends</string>
|
||||
|
||||
<!-- Visibility -->
|
||||
<string name="public_map">Public</string>
|
||||
@@ -384,11 +366,9 @@ limitations under the License.
|
||||
|
||||
<!-- Send to Google -->
|
||||
<string name="sendtogoogle_title">Send to...</string>
|
||||
<string name="sendtogoogle_google_mymaps">Google My Maps</string>
|
||||
<string name="sendtogoogle_google_fusiontables">Google Fusion Tables</string>
|
||||
<string name="sendtogoogle_google_docs">Google Docs</string>
|
||||
<string name="sendtogoogle_send_now">Send now</string>
|
||||
<string name="sendtogoogle_create_new_map">Create a new map</string>
|
||||
<string name="sendtogoogle_pick_existing_map">Pick an existing map</string>
|
||||
<string name="sendtogoogle_send_stats">Send track statistics</string>
|
||||
<string name="sendtogoogle_send_stats_and_points">Send statistics and points</string>
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.mymaps;
|
||||
|
||||
import com.google.wireless.gdata.maps.MapsClient;
|
||||
|
||||
/**
|
||||
* Constants for My Maps.
|
||||
*/
|
||||
public class MyMapsConstants {
|
||||
public static final String MAPSHOP_BASE_URL =
|
||||
"http://maps.google.com/maps/ms";
|
||||
public static final String MAPSHOP_SERVICE = MapsClient.SERVICE;
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private MyMapsConstants() { }
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* 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.mymaps;
|
||||
|
||||
import com.google.android.maps.GeoPoint;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* MyMapsFeature contains all of the data associated with a feature in My Maps,
|
||||
* where a feature is a marker, line, or shape. Some of the data is stored in a
|
||||
* {@link MyMapsFeatureMetadata} object so that it can be more efficiently
|
||||
* transmitted to other activities.
|
||||
*/
|
||||
public class MyMapsFeature implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8439035544430497236L;
|
||||
|
||||
/** A marker feature displays an icon at a single point on the map. */
|
||||
public static final int MARKER = 0;
|
||||
|
||||
/**
|
||||
* A line feature displays a line connecting a set of points on the map.
|
||||
*/
|
||||
public static final int LINE = 1;
|
||||
|
||||
/**
|
||||
* A shape feature displays a border defined by connecting a set of points,
|
||||
* including connecting the last to the first, and displays the area
|
||||
* confined by this border.
|
||||
*/
|
||||
public static final int SHAPE = 2;
|
||||
|
||||
/** The local feature id for this feature, if needed. */
|
||||
private String androidId;
|
||||
|
||||
/**
|
||||
* The latitudes of the points of this feature in order, specified in
|
||||
* millionths of a degree north.
|
||||
*/
|
||||
private final Vector<Integer> latitudeE6 = new Vector<Integer>();
|
||||
|
||||
/**
|
||||
* The longitudes of the points of this feature in order, specified in
|
||||
* millionths of a degree east.
|
||||
*/
|
||||
private final Vector<Integer> longitudeE6 = new Vector<Integer>();
|
||||
|
||||
/** The metadata of this feature in a format efficient for transmission. */
|
||||
private MyMapsFeatureMetadata featureInfo = new MyMapsFeatureMetadata();
|
||||
|
||||
/**
|
||||
* Initializes a valid but empty feature. It will default to a
|
||||
* {@link #MARKER} with a blue placemark with a dot as an icon at the
|
||||
* location (0, 0).
|
||||
*/
|
||||
public MyMapsFeature() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new point to the end of this feature.
|
||||
*
|
||||
* @param point The new point to add
|
||||
*/
|
||||
public synchronized void addPoint(GeoPoint point) {
|
||||
latitudeE6.add(point.getLatitudeE6());
|
||||
longitudeE6.add(point.getLongitudeE6());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new local id for this feature based on the current time and
|
||||
* a random number.
|
||||
*/
|
||||
public synchronized void generateAndroidId() {
|
||||
Long time = System.currentTimeMillis();
|
||||
Integer random = (int) (Math.random() * 10000);
|
||||
androidId = time.toString() + "." + random.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current local id for this feature if one is available.
|
||||
*
|
||||
* @return The local id for this feature
|
||||
*/
|
||||
public String getAndroidId() {
|
||||
return androidId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current (html) description of this feature. The description
|
||||
* is stored in the feature metadata.
|
||||
*
|
||||
* @return The description of this feature
|
||||
*/
|
||||
public String getDescription() {
|
||||
return featureInfo.getDescription();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description of this feature. That description is stored in the
|
||||
* feature metadata.
|
||||
*
|
||||
* @param description The new description of this feature
|
||||
*/
|
||||
public synchronized void setDescription(String description) {
|
||||
featureInfo.setDescription(description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the point at the given index for this feature.
|
||||
*
|
||||
* @param index The index of the point desired
|
||||
* @return A {@link GeoPoint} representing the point or null if that point
|
||||
* doesn't exist
|
||||
*/
|
||||
public GeoPoint getPoint(int index) {
|
||||
if (latitudeE6.size() <= index) {
|
||||
return null;
|
||||
}
|
||||
return new GeoPoint(latitudeE6.get(index), longitudeE6.get(index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of points in this feature and return that count.
|
||||
*
|
||||
* @return The number of points in this feature
|
||||
*/
|
||||
public int getPointCount() {
|
||||
return latitudeE6.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the title of this feature. That title is stored in the feature
|
||||
* metadata.
|
||||
*
|
||||
* @return the current title of this feature
|
||||
*/
|
||||
public String getTitle() {
|
||||
return featureInfo.getTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the type of this feature. That type is stored in the feature
|
||||
* metadata.
|
||||
*
|
||||
* @return One of {@link #MARKER}, {@link #LINE}, or {@link #SHAPE}
|
||||
* identifying the type of this feature
|
||||
*/
|
||||
public int getType() {
|
||||
return featureInfo.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current color of this feature as an ARGB color integer.
|
||||
* That color is stored in the feature metadata.
|
||||
*
|
||||
* @return The ARGB color of this feature
|
||||
*/
|
||||
public int getColor() {
|
||||
return featureInfo.getColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current line width of this feature. That line width is
|
||||
* stored in the feature metadata.
|
||||
*
|
||||
* @return The line width of this feature
|
||||
*/
|
||||
public int getLineWidth() {
|
||||
return featureInfo.getLineWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current fill color of this feature as an ARGB color
|
||||
* integer. That color is stored in the feature metadata.
|
||||
*
|
||||
* @return The ARGB fill color of this feature
|
||||
*/
|
||||
public int getFillColor() {
|
||||
return featureInfo.getFillColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current icon url of this feature. That icon url is stored
|
||||
* in the feature metadata.
|
||||
*
|
||||
* @return The icon url for this feature
|
||||
*/
|
||||
public String getIconUrl() {
|
||||
return featureInfo.getIconUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the title of this feature. That title is stored in the feature
|
||||
* metadata.
|
||||
*
|
||||
* @param title The new title of this feature
|
||||
*/
|
||||
public synchronized void setTitle(String title) {
|
||||
featureInfo.setTitle(title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of this feature. That type is stored in the feature
|
||||
* metadata.
|
||||
*
|
||||
* @param type The new type of the feature. That type must be one of
|
||||
* {@link #MARKER}, {@link #LINE}, or {@link #SHAPE}
|
||||
*/
|
||||
public synchronized void setType(int type) {
|
||||
featureInfo.setType(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ARGB color of this feature. That color is stored in the feature
|
||||
* metadata.
|
||||
*
|
||||
* @param color The new ARGB color of this feature
|
||||
*/
|
||||
public synchronized void setColor(int color) {
|
||||
featureInfo.setColor(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the icon url of this feature. That icon url is stored in the feature
|
||||
* metadata.
|
||||
*
|
||||
* @param url The new icon url of the feature
|
||||
*/
|
||||
public synchronized void setIconUrl(String url) {
|
||||
featureInfo.setIconUrl(url);
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* 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.mymaps;
|
||||
|
||||
/**
|
||||
* Metadata about a maps feature.
|
||||
*/
|
||||
public class MyMapsFeatureMetadata {
|
||||
|
||||
private static final String BLUE_DOT_URL =
|
||||
"http://maps.google.com/mapfiles/ms/micons/blue-dot.png";
|
||||
private static final int DEFAULT_COLOR = 0x800000FF;
|
||||
private static final int DEFAULT_FILL_COLOR = 0xC00000FF;
|
||||
|
||||
private String title;
|
||||
private String description;
|
||||
private int type;
|
||||
private int color;
|
||||
private int lineWidth;
|
||||
private int fillColor;
|
||||
private String iconUrl;
|
||||
|
||||
public MyMapsFeatureMetadata() {
|
||||
title = "";
|
||||
description = "";
|
||||
type = MyMapsFeature.MARKER;
|
||||
color = DEFAULT_COLOR;
|
||||
lineWidth = 5;
|
||||
fillColor = DEFAULT_FILL_COLOR;
|
||||
iconUrl = BLUE_DOT_URL;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public int getLineWidth() {
|
||||
return lineWidth;
|
||||
}
|
||||
|
||||
public void setLineWidth(int width) {
|
||||
lineWidth = width;
|
||||
}
|
||||
|
||||
public int getFillColor() {
|
||||
return fillColor;
|
||||
}
|
||||
|
||||
public void setFillColor(int color) {
|
||||
fillColor = color;
|
||||
}
|
||||
|
||||
public String getIconUrl() {
|
||||
return iconUrl;
|
||||
}
|
||||
|
||||
public void setIconUrl(String url) {
|
||||
iconUrl = new String(url);
|
||||
}
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
/*
|
||||
* 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.mymaps;
|
||||
|
||||
import com.google.wireless.gdata.data.Entry;
|
||||
import com.google.wireless.gdata.data.StringUtils;
|
||||
import com.google.wireless.gdata.maps.MapFeatureEntry;
|
||||
import com.google.wireless.gdata.maps.MapsClient;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.util.Log;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* Converter from GData objects to MyMaps objects.
|
||||
*/
|
||||
public class MyMapsGDataConverter {
|
||||
|
||||
private final XmlSerializer xmlSerializer;
|
||||
|
||||
public MyMapsGDataConverter() throws XmlPullParserException {
|
||||
xmlSerializer = XmlPullParserFactory.newInstance().newSerializer();
|
||||
}
|
||||
|
||||
public static MyMapsMapMetadata getMapMetadataForEntry(
|
||||
MapFeatureEntry entry) {
|
||||
MyMapsMapMetadata metadata = new MyMapsMapMetadata();
|
||||
if ("public".equals(entry.getPrivacy())) {
|
||||
metadata.setSearchable(true);
|
||||
} else {
|
||||
metadata.setSearchable(false);
|
||||
}
|
||||
metadata.setTitle(entry.getTitle());
|
||||
|
||||
String desc = entry.getContent();
|
||||
if (desc.length() > 12) {
|
||||
metadata.setDescription(desc.substring(9, desc.length() - 3));
|
||||
}
|
||||
metadata.setGDataEditUri(entry.getEditUri());
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public static String getMapidForEntry(Entry entry) {
|
||||
return MapsClient.getMapIdFromMapEntryId(entry.getId());
|
||||
}
|
||||
|
||||
public static Entry getMapEntryForMetadata(MyMapsMapMetadata metadata) {
|
||||
MapFeatureEntry entry = new MapFeatureEntry();
|
||||
entry.setEditUri(metadata.getGDataEditUri());
|
||||
entry.setTitle(metadata.getTitle());
|
||||
entry.setContent(metadata.getDescription());
|
||||
entry.setPrivacy(metadata.getSearchable() ? "public" : "unlisted");
|
||||
entry.setAuthor("android");
|
||||
entry.setEmail("nobody@google.com");
|
||||
return entry;
|
||||
}
|
||||
|
||||
public MapFeatureEntry getEntryForFeature(MyMapsFeature feature) {
|
||||
MapFeatureEntry entry = new MapFeatureEntry();
|
||||
entry.setTitle(feature.getTitle());
|
||||
entry.setAuthor("android");
|
||||
entry.setEmail("nobody@google.com");
|
||||
entry.setCategoryScheme("http://schemas.google.com/g/2005#kind");
|
||||
entry.setCategory("http://schemas.google.com/g/2008#mapfeature");
|
||||
entry.setEditUri("");
|
||||
if (!StringUtils.isEmpty(feature.getAndroidId())) {
|
||||
entry.setAttribute("_androidId", feature.getAndroidId());
|
||||
}
|
||||
try {
|
||||
StringWriter writer = new StringWriter();
|
||||
xmlSerializer.setOutput(writer);
|
||||
xmlSerializer.startTag(null, "Placemark");
|
||||
xmlSerializer.attribute(null, "xmlns", "http://earth.google.com/kml/2.2");
|
||||
xmlSerializer.startTag(null, "Style");
|
||||
if (feature.getType() == MyMapsFeature.MARKER) {
|
||||
xmlSerializer.startTag(null, "IconStyle");
|
||||
xmlSerializer.startTag(null, "Icon");
|
||||
xmlSerializer.startTag(null, "href");
|
||||
xmlSerializer.text(feature.getIconUrl());
|
||||
xmlSerializer.endTag(null, "href");
|
||||
xmlSerializer.endTag(null, "Icon");
|
||||
xmlSerializer.endTag(null, "IconStyle");
|
||||
} else {
|
||||
xmlSerializer.startTag(null, "LineStyle");
|
||||
xmlSerializer.startTag(null, "color");
|
||||
int color = feature.getColor();
|
||||
// Reverse the color because KML is ABGR and Android is ARGB
|
||||
xmlSerializer.text(Integer.toHexString(
|
||||
Color.argb(Color.alpha(color), Color.blue(color),
|
||||
Color.green(color), Color.red(color))));
|
||||
xmlSerializer.endTag(null, "color");
|
||||
xmlSerializer.startTag(null, "width");
|
||||
xmlSerializer.text(Integer.toString(feature.getLineWidth()));
|
||||
xmlSerializer.endTag(null, "width");
|
||||
xmlSerializer.endTag(null, "LineStyle");
|
||||
|
||||
if (feature.getType() == MyMapsFeature.SHAPE) {
|
||||
xmlSerializer.startTag(null, "PolyStyle");
|
||||
xmlSerializer.startTag(null, "color");
|
||||
int fcolor = feature.getFillColor();
|
||||
// Reverse the color because KML is ABGR and Android is ARGB
|
||||
xmlSerializer.text(Integer.toHexString(Color.argb(Color.alpha(fcolor),
|
||||
Color.blue(fcolor), Color.green(fcolor), Color.red(fcolor))));
|
||||
xmlSerializer.endTag(null, "color");
|
||||
xmlSerializer.startTag(null, "fill");
|
||||
xmlSerializer.text("1");
|
||||
xmlSerializer.endTag(null, "fill");
|
||||
xmlSerializer.startTag(null, "outline");
|
||||
xmlSerializer.text("1");
|
||||
xmlSerializer.endTag(null, "outline");
|
||||
xmlSerializer.endTag(null, "PolyStyle");
|
||||
}
|
||||
}
|
||||
xmlSerializer.endTag(null, "Style");
|
||||
xmlSerializer.startTag(null, "name");
|
||||
xmlSerializer.text(feature.getTitle());
|
||||
xmlSerializer.endTag(null, "name");
|
||||
xmlSerializer.startTag(null, "description");
|
||||
xmlSerializer.cdsect(feature.getDescription());
|
||||
xmlSerializer.endTag(null, "description");
|
||||
StringBuilder pointBuilder = new StringBuilder();
|
||||
for (int i = 0; i < feature.getPointCount(); ++i) {
|
||||
if (i > 0) {
|
||||
pointBuilder.append('\n');
|
||||
}
|
||||
pointBuilder.append(feature.getPoint(i).getLongitudeE6() / 1e6);
|
||||
pointBuilder.append(',');
|
||||
pointBuilder.append(feature.getPoint(i).getLatitudeE6() / 1e6);
|
||||
pointBuilder.append(",0.000000");
|
||||
}
|
||||
String pointString = pointBuilder.toString();
|
||||
if (feature.getType() == MyMapsFeature.MARKER) {
|
||||
xmlSerializer.startTag(null, "Point");
|
||||
xmlSerializer.startTag(null, "coordinates");
|
||||
xmlSerializer.text(pointString);
|
||||
xmlSerializer.endTag(null, "coordinates");
|
||||
xmlSerializer.endTag(null, "Point");
|
||||
} else if (feature.getType() == MyMapsFeature.LINE) {
|
||||
xmlSerializer.startTag(null, "LineString");
|
||||
xmlSerializer.startTag(null, "tessellate");
|
||||
xmlSerializer.text("1");
|
||||
xmlSerializer.endTag(null, "tessellate");
|
||||
xmlSerializer.startTag(null, "coordinates");
|
||||
xmlSerializer.text(pointString);
|
||||
xmlSerializer.endTag(null, "coordinates");
|
||||
xmlSerializer.endTag(null, "LineString");
|
||||
} else {
|
||||
xmlSerializer.startTag(null, "Polygon");
|
||||
xmlSerializer.startTag(null, "outerBoundaryIs");
|
||||
xmlSerializer.startTag(null, "LinearRing");
|
||||
xmlSerializer.startTag(null, "tessellate");
|
||||
xmlSerializer.text("1");
|
||||
xmlSerializer.endTag(null, "tessellate");
|
||||
xmlSerializer.startTag(null, "coordinates");
|
||||
xmlSerializer.text(pointString + "\n"
|
||||
+ Double.toString(feature.getPoint(0).getLongitudeE6() / 1e6)
|
||||
+ ","
|
||||
+ Double.toString(feature.getPoint(0).getLatitudeE6() / 1e6)
|
||||
+ ",0.000000");
|
||||
xmlSerializer.endTag(null, "coordinates");
|
||||
xmlSerializer.endTag(null, "LinearRing");
|
||||
xmlSerializer.endTag(null, "outerBoundaryIs");
|
||||
xmlSerializer.endTag(null, "Polygon");
|
||||
}
|
||||
xmlSerializer.endTag(null, "Placemark");
|
||||
xmlSerializer.flush();
|
||||
entry.setContent(writer.toString());
|
||||
Log.d("My Google Maps", "Generated kml:\n" + entry.getContent());
|
||||
Log.d("My Google Maps", "Edit URI: " + entry.getEditUri());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
@@ -1,190 +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.mymaps;
|
||||
|
||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
||||
import com.google.android.apps.mytracks.io.AuthManager;
|
||||
import com.google.android.apps.mytracks.io.gdata.GDataClientFactory;
|
||||
import com.google.android.common.gdata.AndroidXmlParserFactory;
|
||||
import com.google.wireless.gdata.client.GDataClient;
|
||||
import com.google.wireless.gdata.client.HttpException;
|
||||
import com.google.wireless.gdata.maps.MapsClient;
|
||||
import com.google.wireless.gdata.maps.xml.XmlMapsGDataParserFactory;
|
||||
import com.google.wireless.gdata.parser.xml.SimplePullParser.ParseException;
|
||||
import com.google.wireless.gdata2.ConflictDetectedException;
|
||||
import com.google.wireless.gdata2.client.AuthenticationException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* MyMapsGDataWrapper provides a wrapper around GData operations that maintains
|
||||
* the GData client, and provides a method to run gdata queries with proper
|
||||
* error handling. After a query is run, the wrapper can be queried about the
|
||||
* error that occurred.
|
||||
*/
|
||||
public class MyMapsGDataWrapper {
|
||||
/**
|
||||
* A QueryFunction is passed in when executing a query. The query function
|
||||
* of the class is called with the GData client as a parameter. The
|
||||
* function should execute whatever operations it desires on the client
|
||||
* without concern for whether the client will throw an error.
|
||||
*/
|
||||
public interface QueryFunction {
|
||||
public abstract void query(MapsClient client)
|
||||
throws AuthenticationException, IOException, ParseException,
|
||||
ConflictDetectedException, Exception;
|
||||
}
|
||||
|
||||
// The types of error that may be encountered
|
||||
/** No error occurred. */
|
||||
public static final int ERROR_NO_ERROR = 0;
|
||||
/** There was an authentication error, the auth token may be invalid. */
|
||||
public static final int ERROR_AUTH = 1;
|
||||
/** There was an internal error on the server side. */
|
||||
public static final int ERROR_INTERNAL = 2;
|
||||
/** There was an error connecting to the server. */
|
||||
public static final int ERROR_CONNECTION = 3;
|
||||
/** The item queried did not exit. */
|
||||
public static final int ERROR_NOT_FOUND = 4;
|
||||
/** There was an error parsing or serializing locally. */
|
||||
public static final int ERROR_LOCAL = 5;
|
||||
/** There was a conflict, update the entry and try again. */
|
||||
public static final int ERROR_CONFLICT = 6;
|
||||
/**
|
||||
* A query was run after cleaning up the wrapper, so the client was invalid.
|
||||
*/
|
||||
public static final int ERROR_CLEANED_UP = 7;
|
||||
/** An unknown error occurred. */
|
||||
public static final int ERROR_UNKNOWN = 100;
|
||||
|
||||
private final GDataClient androidGdataClient;
|
||||
private final MapsClient client;
|
||||
|
||||
private String errorMessage;
|
||||
private int errorType;
|
||||
private AuthManager auth;
|
||||
private boolean retryOnAuthFailure;
|
||||
private int retriesPending;
|
||||
private boolean cleanupCalled;
|
||||
|
||||
public MyMapsGDataWrapper(Context context) {
|
||||
androidGdataClient = GDataClientFactory.getGDataClient(context);
|
||||
client =
|
||||
new MapsClient(androidGdataClient, new XmlMapsGDataParserFactory(
|
||||
new AndroidXmlParserFactory()));
|
||||
errorType = ERROR_NO_ERROR;
|
||||
errorMessage = null;
|
||||
auth = null;
|
||||
retryOnAuthFailure = false;
|
||||
retriesPending = 0;
|
||||
cleanupCalled = false;
|
||||
}
|
||||
|
||||
public boolean runQuery(final QueryFunction query) {
|
||||
if (client == null) {
|
||||
errorType = ERROR_CLEANED_UP;
|
||||
errorMessage = "GData Wrapper has already been cleaned up!";
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
query.query(client);
|
||||
errorType = ERROR_NO_ERROR;
|
||||
errorMessage = null;
|
||||
return true;
|
||||
} catch (AuthenticationException e) {
|
||||
Log.e(MyTracksConstants.TAG, "Exception", e);
|
||||
errorType = ERROR_AUTH;
|
||||
errorMessage = e.getMessage();
|
||||
} catch (HttpException e) {
|
||||
Log.e(MyTracksConstants.TAG, "HttpException", e);
|
||||
errorMessage = e.getMessage();
|
||||
if (errorMessage != null && errorMessage.contains("401")) {
|
||||
errorType = ERROR_AUTH;
|
||||
} else {
|
||||
errorType = ERROR_CONNECTION;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(MyTracksConstants.TAG, "Exception", e);
|
||||
errorMessage = e.getMessage();
|
||||
if (errorMessage != null && errorMessage.contains("503")) {
|
||||
errorType = ERROR_INTERNAL;
|
||||
} else {
|
||||
errorType = ERROR_CONNECTION;
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
Log.e(MyTracksConstants.TAG, "Exception", e);
|
||||
errorType = ERROR_LOCAL;
|
||||
errorMessage = e.getMessage();
|
||||
} catch (ConflictDetectedException e) {
|
||||
Log.e(MyTracksConstants.TAG, "Exception", e);
|
||||
errorType = ERROR_CONFLICT;
|
||||
errorMessage = e.getMessage();
|
||||
} catch (Exception e) {
|
||||
Log.e(MyTracksConstants.TAG, "Exception", e);
|
||||
errorType = ERROR_UNKNOWN;
|
||||
errorMessage = e.getMessage();
|
||||
e.printStackTrace();
|
||||
}
|
||||
Log.d(MyTracksConstants.TAG, "GData error encountered: " + errorMessage);
|
||||
if (errorType == ERROR_AUTH && auth != null) {
|
||||
Runnable whenFinished = null;
|
||||
if (retryOnAuthFailure) {
|
||||
retriesPending++;
|
||||
whenFinished = new Runnable() {
|
||||
public void run() {
|
||||
retriesPending--;
|
||||
retryOnAuthFailure = false;
|
||||
runQuery(query);
|
||||
if (cleanupCalled && retriesPending == 0) {
|
||||
cleanUp();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
auth.invalidateAndRefresh(whenFinished);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getErrorType() {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
// cleanUp must be called when done using this wrapper to close the client.
|
||||
// Note that the cleanup will be delayed if auth failure retries were
|
||||
// requested and there is a pending retry.
|
||||
public void cleanUp() {
|
||||
if (retriesPending == 0 && !cleanupCalled) {
|
||||
androidGdataClient.close();
|
||||
}
|
||||
cleanupCalled = true;
|
||||
}
|
||||
|
||||
public void setAuthManager(AuthManager newAuth) {
|
||||
this.auth = newAuth;
|
||||
}
|
||||
|
||||
public void setRetryOnAuthFailure(boolean retry) {
|
||||
retryOnAuthFailure = retry;
|
||||
}
|
||||
}
|
||||
@@ -1,350 +0,0 @@
|
||||
/*
|
||||
* 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.mymaps;
|
||||
|
||||
import com.google.android.accounts.Account;
|
||||
import com.google.android.apps.mymaps.MyMapsGDataWrapper.QueryFunction;
|
||||
import com.google.android.apps.mytracks.AccountChooser;
|
||||
import com.google.android.apps.mytracks.MyTracks;
|
||||
import com.google.android.apps.mytracks.io.AuthManager;
|
||||
import com.google.android.apps.mytracks.io.AuthManagerFactory;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.wireless.gdata.maps.MapFeatureEntry;
|
||||
import com.google.wireless.gdata.maps.MapsClient;
|
||||
import com.google.wireless.gdata.parser.GDataParser;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.database.DataSetObserver;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnCreateContextMenuListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Activity which displays the list of "my maps" maps.
|
||||
*/
|
||||
public class MyMapsList extends Activity implements ListAdapter {
|
||||
|
||||
private static final int MENU_OPEN = 0;
|
||||
private static final int MENU_SHARE = 2;
|
||||
private static final int GET_LOGIN = 1;
|
||||
|
||||
private LookupThread listLookup;
|
||||
private Vector<String[]> mapsList;
|
||||
private Vector<Boolean> publicList;
|
||||
private Set<DataSetObserver> observerSet;
|
||||
private Handler loadHandler;
|
||||
private int contextPosition;
|
||||
private AuthManager auth;
|
||||
|
||||
/**
|
||||
* Thread which looks up the maps list.
|
||||
*/
|
||||
private class LookupThread extends Thread {
|
||||
private boolean finished = false;
|
||||
private boolean success = true;
|
||||
|
||||
private GDataParser listParser;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
finished = false;
|
||||
listParser = null;
|
||||
MyMapsGDataWrapper wrapper = new MyMapsGDataWrapper(MyMapsList.this);
|
||||
wrapper.setAuthManager(auth);
|
||||
wrapper.setRetryOnAuthFailure(true);
|
||||
|
||||
success = wrapper.runQuery(new QueryFunction() {
|
||||
public void query(MapsClient client) throws IOException, Exception {
|
||||
listParser = client.getParserForFeed(
|
||||
MapFeatureEntry.class, MapsClient.getMapsFeed(),
|
||||
auth.getAuthToken());
|
||||
listParser.init();
|
||||
while (listParser.hasMoreData()) {
|
||||
MapFeatureEntry entry =
|
||||
(MapFeatureEntry) listParser.readNextEntry(null);
|
||||
MyMapsMapMetadata metadata =
|
||||
MyMapsGDataConverter.getMapMetadataForEntry(entry);
|
||||
String mapid = MyMapsGDataConverter.getMapidForEntry(entry);
|
||||
synchronized (mapsList) {
|
||||
// Search through the maps list to see if it has the mapid and
|
||||
// remove it if so, so that we can replace it with updated info
|
||||
for (int i = 0; i < mapsList.size(); ++i) {
|
||||
if (mapid.equals(mapsList.get(i)[0])) {
|
||||
mapsList.remove(i);
|
||||
publicList.remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
mapsList.add(new String[] {
|
||||
mapid, metadata.getTitle(), metadata.getDescription() });
|
||||
publicList.add(metadata.getSearchable());
|
||||
}
|
||||
}
|
||||
listParser.close();
|
||||
listParser = null;
|
||||
success = true;
|
||||
finished = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (listParser != null) {
|
||||
listParser.close();
|
||||
}
|
||||
wrapper.cleanUp();
|
||||
if (success || wrapper.getErrorType() != MyMapsGDataWrapper.ERROR_AUTH) {
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return finished;
|
||||
}
|
||||
|
||||
public boolean succeeded() {
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable checkLoaded = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (listLookup.isFinished()) {
|
||||
findViewById(R.id.loading).setVisibility(View.GONE);
|
||||
if (!listLookup.succeeded()) {
|
||||
findViewById(R.id.failed).setVisibility(View.VISIBLE);
|
||||
}
|
||||
TextView emptyView = (TextView) findViewById(R.id.mapslist_empty);
|
||||
ListView list = (ListView) findViewById(R.id.maplist);
|
||||
list.setEmptyView(emptyView);
|
||||
} else {
|
||||
loadHandler.postDelayed(checkLoaded, 500);
|
||||
}
|
||||
Iterator<DataSetObserver> iter = observerSet.iterator();
|
||||
while (iter.hasNext()) {
|
||||
iter.next().onChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final OnItemClickListener clickListener = new OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View v, int position,
|
||||
long id) {
|
||||
Intent result = new Intent();
|
||||
result.putExtra("mapid", (String) getItem(position));
|
||||
MyMapsList.this.setResult(RESULT_OK, result);
|
||||
finish();
|
||||
}
|
||||
};
|
||||
|
||||
private final OnCreateContextMenuListener contextMenuListener =
|
||||
new OnCreateContextMenuListener() {
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
AdapterView.AdapterContextMenuInfo info =
|
||||
(AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||
contextPosition = info.position;
|
||||
menu.add(0, MENU_OPEN, 0, R.string.open_map);
|
||||
menu.add(0, MENU_SHARE, 0, R.string.share_map);
|
||||
}
|
||||
};
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
auth = AuthManagerFactory.getAuthManager(this, GET_LOGIN, null, true,
|
||||
MapsClient.SERVICE);
|
||||
|
||||
setContentView(R.layout.list);
|
||||
|
||||
ListView list = (ListView) findViewById(R.id.maplist);
|
||||
list.setOnItemClickListener(clickListener);
|
||||
list.setOnCreateContextMenuListener(contextMenuListener);
|
||||
|
||||
mapsList = new Vector<String[]>();
|
||||
publicList = new Vector<Boolean>();
|
||||
|
||||
listLookup = new LookupThread();
|
||||
// TODO fix this for non-froyo devices.
|
||||
if (AuthManagerFactory.useModernAuthManager()) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MyTracks.getInstance().getAccountChooser().chooseAccount(
|
||||
MyMapsList.this,
|
||||
new AccountChooser.AccountHandler() {
|
||||
@Override
|
||||
public void handleAccountSelected(Account account) {
|
||||
if (account != null) {
|
||||
// The user did not quit and there was a valid google
|
||||
// account.
|
||||
doLogin(account);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
doLogin(null);
|
||||
}
|
||||
|
||||
observerSet = new HashSet<DataSetObserver>();
|
||||
|
||||
list.setAdapter(this);
|
||||
|
||||
loadHandler = new Handler();
|
||||
loadHandler.postDelayed(checkLoaded, 500);
|
||||
}
|
||||
|
||||
private void doLogin(final Account account) {
|
||||
auth.doLogin(new Runnable() {
|
||||
public void run() {
|
||||
listLookup.start();
|
||||
}
|
||||
}, account);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode,
|
||||
Intent data) {
|
||||
if (requestCode == GET_LOGIN) {
|
||||
auth.authResult(resultCode, data);
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_OPEN:
|
||||
clickListener.onItemClick(null, null, contextPosition, 0);
|
||||
return true;
|
||||
case MENU_SHARE:
|
||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType("text/plain");
|
||||
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
|
||||
getText(R.string.share_map_subject));
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, String.format(
|
||||
getText(R.string.share_map_body_format).toString(),
|
||||
mapsList.get(contextPosition)[1],
|
||||
MyMapsConstants.MAPSHOP_BASE_URL + "?msa=0&msid="
|
||||
+ mapsList.get(contextPosition)[0]));
|
||||
startActivity(Intent.createChooser(shareIntent,
|
||||
getText(R.string.share_map).toString()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areAllItemsEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mapsList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return mapsList.get(position)[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView =
|
||||
getLayoutInflater().inflate(R.layout.listitem, parent, false);
|
||||
}
|
||||
|
||||
String[] map = mapsList.get(position);
|
||||
((TextView) convertView.findViewById(R.id.maplistitem)).setText(map[1]);
|
||||
((TextView) convertView.findViewById(R.id.maplistdesc)).setText(map[2]);
|
||||
TextView publicUnlisted =
|
||||
(TextView) convertView.findViewById(R.id.maplistpublic);
|
||||
if (publicList.get(position)) {
|
||||
publicUnlisted.setTextColor(Color.RED);
|
||||
publicUnlisted.setText(R.string.public_map);
|
||||
} else {
|
||||
publicUnlisted.setTextColor(Color.GREEN);
|
||||
publicUnlisted.setText(R.string.unlisted_map);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return mapsList.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDataSetObserver(DataSetObserver observer) {
|
||||
observerSet.add(observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterDataSetObserver(DataSetObserver observer) {
|
||||
observerSet.remove(observer);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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.mymaps;
|
||||
|
||||
/**
|
||||
* Metadata about a "my maps" map.
|
||||
*/
|
||||
public class MyMapsMapMetadata {
|
||||
|
||||
private String title;
|
||||
private String description;
|
||||
private String gdataEditUri;
|
||||
private boolean searchable;
|
||||
|
||||
public MyMapsMapMetadata() {
|
||||
title = "";
|
||||
description = "";
|
||||
gdataEditUri = "";
|
||||
searchable = false;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = new String(title);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = new String(description);
|
||||
}
|
||||
|
||||
public boolean getSearchable() {
|
||||
return searchable;
|
||||
}
|
||||
|
||||
public void setSearchable(boolean searchable) {
|
||||
this.searchable = searchable;
|
||||
}
|
||||
|
||||
public String getGDataEditUri() {
|
||||
return gdataEditUri;
|
||||
}
|
||||
|
||||
public void setGDataEditUri(String editUri) {
|
||||
this.gdataEditUri = new String(editUri);
|
||||
}
|
||||
}
|
||||
@@ -85,13 +85,13 @@ public class DialogManager {
|
||||
builder.setTitle("Title");
|
||||
builder.setMessage("Message");
|
||||
builder.setPositiveButton(activity.getString(R.string.ok), null);
|
||||
builder.setNeutralButton(activity.getString(R.string.share_map),
|
||||
builder.setNeutralButton(activity.getString(R.string.share_track),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
activity.shareLinkToMyMap(activity.getSendToMyMapsMapId());
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
activity.shareLinkToFusionTable(activity.sendToTrackId);
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
sendToGoogleResultDialog = builder.create();
|
||||
return sendToGoogleResultDialog;
|
||||
case DIALOG_WRITE_PROGRESS:
|
||||
@@ -119,9 +119,9 @@ public class DialogManager {
|
||||
sendToGoogleResultDialog.setIcon(success
|
||||
? android.R.drawable.ic_dialog_info
|
||||
: android.R.drawable.ic_dialog_alert);
|
||||
sendToGoogleResultDialog.setMessage(activity.getMapsResultMessage());
|
||||
sendToGoogleResultDialog.setMessage(activity.getFusionTablesResultMessage());
|
||||
|
||||
boolean canShare = activity.getSendToMyMapsMapId() != null;
|
||||
boolean canShare = activity.getSendToFusionTablesTableId() != null;
|
||||
View share =
|
||||
sendToGoogleResultDialog.findViewById(android.R.id.button3);
|
||||
if (share != null) {
|
||||
|
||||
@@ -21,20 +21,18 @@ import static com.google.android.apps.mytracks.DialogManager.DIALOG_SEND_TO_GOOG
|
||||
import static com.google.android.apps.mytracks.DialogManager.DIALOG_WRITE_PROGRESS;
|
||||
|
||||
import com.google.android.accounts.Account;
|
||||
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.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;
|
||||
import com.google.android.apps.mytracks.io.SendToMyMaps;
|
||||
import com.google.android.apps.mytracks.io.SendToDocs;
|
||||
import com.google.android.apps.mytracks.io.SendToFusionTables;
|
||||
import com.google.android.apps.mytracks.io.TempFileCleaner;
|
||||
import com.google.android.apps.mytracks.io.TrackWriter;
|
||||
import com.google.android.apps.mytracks.io.TrackWriterFactory;
|
||||
import com.google.android.apps.mytracks.io.SendToDocs;
|
||||
import com.google.android.apps.mytracks.io.SendToMyMaps.OnSendCompletedListener;
|
||||
import com.google.android.apps.mytracks.io.SendToFusionTables.OnSendCompletedListener;
|
||||
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.services.ITrackRecordingService;
|
||||
import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
|
||||
@@ -123,10 +121,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
* Used by SendToGoogleResultDialog.
|
||||
*/
|
||||
|
||||
public boolean sendToMyMapsSuccess = false;
|
||||
public long sendToTrackId = -1;
|
||||
public boolean sendToFusionTablesSuccess = false;
|
||||
public boolean sendToDocsSuccess = false;
|
||||
public String sendToMyMapsMapId;
|
||||
public String sendToMyMapsMessage = "";
|
||||
public String sendToFusionTablesTableId;
|
||||
public String sendToFusionTablesMessage = "";
|
||||
public String sendToDocsMessage = "";
|
||||
|
||||
/**
|
||||
@@ -147,9 +146,9 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
*/
|
||||
private long selectedTrackId = -1;
|
||||
|
||||
/**
|
||||
* Does the user want to share the current track.
|
||||
*/
|
||||
/**
|
||||
* Does the user want to share the current track.
|
||||
*/
|
||||
private boolean shareRequested = false;
|
||||
|
||||
/**
|
||||
@@ -450,13 +449,13 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
case MyTracksConstants.GET_MAP: {
|
||||
if (resultCode == RESULT_OK) {
|
||||
results.putExtra("trackid", selectedTrackId);
|
||||
if (results.hasExtra("mapid")) {
|
||||
sendToMyMapsMapId = results.getStringExtra("mapid");
|
||||
if (results.hasExtra("tableid")) {
|
||||
sendToFusionTablesTableId = results.getStringExtra("tableid");
|
||||
}
|
||||
setProgressMessage(
|
||||
R.string.progress_message_authenticating_mymaps);
|
||||
R.string.progress_message_authenticating_fusiontables);
|
||||
authenticate(results, MyTracksConstants.SEND_TO_GOOGLE,
|
||||
MyMapsConstants.MAPSHOP_SERVICE);
|
||||
SendToFusionTables.SERVICE_ID);
|
||||
} else {
|
||||
dialogManager.dismissDialogSafely(DIALOG_PROGRESS);
|
||||
}
|
||||
@@ -550,6 +549,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
final SendToDocs sender = new SendToDocs(this,
|
||||
authMap.get(SendToDocs.GDATA_SERVICE_NAME_TRIX),
|
||||
authMap.get(SendToDocs.GDATA_SERVICE_NAME_DOCLIST), trackId);
|
||||
sendToTrackId = trackId;
|
||||
Runnable onCompletion = new Runnable() {
|
||||
public void run() {
|
||||
setProgressValue(100);
|
||||
@@ -558,7 +558,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
public void run() {
|
||||
sendToDocsMessage = sender.getStatusMessage();
|
||||
sendToDocsSuccess = sender.wasSuccess();
|
||||
handleMapsFinish();
|
||||
handleFusionTablesFinish(trackId);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -571,42 +571,35 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
break;
|
||||
}
|
||||
case MyTracksConstants.SEND_TO_GOOGLE_DIALOG: {
|
||||
shareRequested = false;
|
||||
shareRequested = false;
|
||||
dialogManager.showDialogSafely(DIALOG_SEND_TO_GOOGLE);
|
||||
break;
|
||||
}
|
||||
case MyTracksConstants.SEND_TO_GOOGLE: {
|
||||
if (results != null && resultCode == RESULT_OK) {
|
||||
final String mapId;
|
||||
final long trackId;
|
||||
if (results.hasExtra("mapid")) {
|
||||
mapId = results.getStringExtra("mapid");
|
||||
} else {
|
||||
mapId = "new";
|
||||
}
|
||||
if (results.hasExtra("trackid")) {
|
||||
trackId = results.getLongExtra("trackid", -1);
|
||||
} else {
|
||||
trackId = selectedTrackId;
|
||||
}
|
||||
|
||||
OnSendCompletedListener onCompletion = new OnSendCompletedListener() {
|
||||
@Override
|
||||
public void onSendCompleted(String mapId, boolean success,
|
||||
public void onSendCompleted(String tableId, boolean success,
|
||||
int statusMessage) {
|
||||
sendToMyMapsMessage = getString(statusMessage);
|
||||
sendToMyMapsSuccess = success;
|
||||
if (sendToMyMapsSuccess) {
|
||||
sendToMyMapsMapId = mapId;
|
||||
// Update the map id for this track:
|
||||
sendToFusionTablesMessage = getString(statusMessage);
|
||||
sendToFusionTablesSuccess = success;
|
||||
if (sendToFusionTablesSuccess) {
|
||||
sendToFusionTablesTableId = tableId;
|
||||
// Update the table id for this track:
|
||||
try {
|
||||
Track track = providerUtils.getTrack(trackId);
|
||||
track.setMapId(mapId);
|
||||
track.setTableId(tableId);
|
||||
providerUtils.updateTrack(track);
|
||||
} catch (RuntimeException e) {
|
||||
// If that fails whatever reasons we'll just log an error, but
|
||||
// continue.
|
||||
Log.w(MyTracksConstants.TAG, "Updating map id failed.", e);
|
||||
Log.w(MyTracksConstants.TAG, "Updating table id failed.", e);
|
||||
}
|
||||
}
|
||||
if (dialogManager.getSendToGoogleDialog().getSendToDocs()) {
|
||||
@@ -616,16 +609,17 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
dialogManager.dismissDialogSafely(DIALOG_PROGRESS);
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
handleMapsFinish();
|
||||
handleFusionTablesFinish(trackId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
final SendToMyMaps sender = new SendToMyMaps(this, mapId, auth,
|
||||
sendToTrackId = trackId;
|
||||
final SendToFusionTables sender = new SendToFusionTables(this, auth,
|
||||
trackId, this/*progressIndicator*/, onCompletion);
|
||||
|
||||
HandlerThread handlerThread = new HandlerThread("SendToMyMaps");
|
||||
HandlerThread handlerThread = new HandlerThread("SendToFusionTables");
|
||||
handlerThread.start();
|
||||
Handler handler = new Handler(handlerThread.getLooper());
|
||||
handler.post(sender);
|
||||
@@ -656,8 +650,8 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
case MyTracksConstants.SHARE_LINK: {
|
||||
Track selectedTrack = providerUtils.getTrack(selectedTrackId);
|
||||
if (selectedTrack != null) {
|
||||
if (selectedTrack.getMapId().length() > 0) {
|
||||
shareLinkToMyMap(selectedTrack.getMapId());
|
||||
if (selectedTrack.getTableId().length() > 0) {
|
||||
shareLinkToFusionTable(selectedTrackId);
|
||||
} else {
|
||||
shareRequested = true;
|
||||
dialogManager.showDialogSafely(DIALOG_SEND_TO_GOOGLE);
|
||||
@@ -726,11 +720,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
* Resets status information for sending to MyMaps/Docs.
|
||||
*/
|
||||
public void resetSendToGoogleStatus() {
|
||||
sendToMyMapsMessage = "";
|
||||
sendToMyMapsSuccess = true;
|
||||
sendToFusionTablesMessage = "";
|
||||
sendToFusionTablesSuccess = true;
|
||||
sendToDocsMessage = "";
|
||||
sendToDocsSuccess = true;
|
||||
sendToMyMapsMapId = null;
|
||||
sendToFusionTablesTableId = null;
|
||||
}
|
||||
|
||||
private void importGpxFile(final String fileName) {
|
||||
@@ -798,10 +792,10 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
}
|
||||
|
||||
/**
|
||||
* Shares a link to a My Map via external app (email, gmail, ...)
|
||||
* Shares a link to a fusion table via external app (email, gmail, ...)
|
||||
* A chooser with apps that support text/plain will be shown to the user.
|
||||
*/
|
||||
public void shareLinkToMyMap(String mapId) {
|
||||
public void shareLinkToFusionTable(long trackId) {
|
||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType("text/plain");
|
||||
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
|
||||
@@ -813,7 +807,8 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
getString(R.string.share_url_only_key), false);
|
||||
}
|
||||
|
||||
String url = MyMapsConstants.MAPSHOP_BASE_URL + "?msa=0&msid=" + mapId;
|
||||
Track track = providerUtils.getTrack(trackId);
|
||||
String url = SendToFusionTables.getMapVisualizationUrl(track);
|
||||
String msg = shareUrlOnly ? url : String.format(
|
||||
getResources().getText(R.string.share_map_body_format).toString(), url);
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, msg);
|
||||
@@ -1042,17 +1037,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
setProgressValue(0);
|
||||
clearProgressMessage();
|
||||
dialogManager.showDialogSafely(DIALOG_PROGRESS);
|
||||
if (sendToGoogleDialog.getSendToMyMaps()) {
|
||||
if (!sendToGoogleDialog.getCreateNewMap()) {
|
||||
Intent listIntent = new Intent(this, MyMapsList.class);
|
||||
startActivityForResult(listIntent, MyTracksConstants.GET_MAP);
|
||||
} else {
|
||||
setProgressValue(0);
|
||||
setProgressMessage(
|
||||
R.string.progress_message_authenticating_mymaps);
|
||||
authenticate(new Intent(), MyTracksConstants.SEND_TO_GOOGLE,
|
||||
MyMapsConstants.MAPSHOP_SERVICE);
|
||||
}
|
||||
if (sendToGoogleDialog.getSendToFusionTables()) {
|
||||
setProgressValue(0);
|
||||
setProgressMessage(R.string.progress_message_authenticating_fusiontables);
|
||||
authenticate(new Intent(), MyTracksConstants.SEND_TO_GOOGLE,
|
||||
SendToFusionTables.SERVICE_ID);
|
||||
} else {
|
||||
onActivityResult(MyTracksConstants.AUTHENTICATE_TO_DOCLIST, RESULT_OK,
|
||||
new Intent());
|
||||
@@ -1169,25 +1158,24 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies that uploading to maps is finished.
|
||||
* Notifies that uploading to fusion tables is finished.
|
||||
*/
|
||||
private void handleMapsFinish() {
|
||||
if (shareRequested && sendToMyMapsSuccess) {
|
||||
private void handleFusionTablesFinish(long trackId) {
|
||||
if (shareRequested && sendToFusionTablesSuccess) {
|
||||
// Just share
|
||||
Toast.makeText(this, getMapsResultMessage(), Toast.LENGTH_LONG).show();
|
||||
shareLinkToMyMap(sendToMyMapsMapId);
|
||||
Toast.makeText(this, getFusionTablesResultMessage(), Toast.LENGTH_LONG).show();
|
||||
shareLinkToFusionTable(trackId);
|
||||
} else {
|
||||
dialogManager.showDialogSafely(
|
||||
DialogManager.DIALOG_SEND_TO_GOOGLE_RESULT);
|
||||
dialogManager.showDialogSafely(DialogManager.DIALOG_SEND_TO_GOOGLE_RESULT);
|
||||
}
|
||||
}
|
||||
|
||||
public String getMapsResultMessage() {
|
||||
public String getFusionTablesResultMessage() {
|
||||
StringBuilder message = new StringBuilder();
|
||||
SendToGoogleDialog sendToGoogleDialog =
|
||||
dialogManager.getSendToGoogleDialog();
|
||||
if (sendToGoogleDialog.getSendToMyMaps()) {
|
||||
message.append(sendToMyMapsMessage);
|
||||
if (sendToGoogleDialog.getSendToFusionTables()) {
|
||||
message.append(sendToFusionTablesMessage);
|
||||
}
|
||||
if (sendToGoogleDialog.getSendToDocs()) {
|
||||
if (message.length() > 0) {
|
||||
@@ -1195,10 +1183,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
}
|
||||
message.append(sendToDocsMessage);
|
||||
}
|
||||
if (sendToMyMapsSuccess && sendToDocsSuccess) {
|
||||
message.append(' ');
|
||||
message.append(getString(R.string.status_mymap_info));
|
||||
}
|
||||
return message.toString();
|
||||
}
|
||||
|
||||
@@ -1218,12 +1202,12 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
return dialogManager;
|
||||
}
|
||||
|
||||
public String getSendToMyMapsMapId() {
|
||||
return sendToMyMapsMapId;
|
||||
public String getSendToFusionTablesTableId() {
|
||||
return sendToFusionTablesTableId;
|
||||
}
|
||||
|
||||
public boolean getSendToGoogleSuccess() {
|
||||
return sendToMyMapsSuccess && sendToDocsSuccess;
|
||||
return sendToFusionTablesSuccess && sendToDocsSuccess;
|
||||
}
|
||||
|
||||
// @VisibleForTesting
|
||||
|
||||
@@ -213,6 +213,9 @@ public abstract class MyTracksConstants {
|
||||
}
|
||||
}
|
||||
|
||||
public static final String MAPSHOP_BASE_URL =
|
||||
"http://maps.google.com/maps/ms";
|
||||
|
||||
/**
|
||||
* This is an abstract utility class.
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
import com.google.android.apps.mymaps.GeoRect;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TrackPointsColumns;
|
||||
@@ -24,6 +23,7 @@ import com.google.android.apps.mytracks.content.WaypointsColumns;
|
||||
import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
||||
import com.google.android.apps.mytracks.util.GeoRect;
|
||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
||||
import com.google.android.maps.GeoPoint;
|
||||
import com.google.android.maps.MapActivity;
|
||||
@@ -789,7 +789,7 @@ public class MyTracksMap extends MapActivity
|
||||
SubMenu share = menu.addSubMenu(0, MyTracksConstants.MENU_SHARE, 0,
|
||||
R.string.tracklist_share_track);
|
||||
share.add(0, MyTracksConstants.MENU_SHARE_LINK, 0,
|
||||
R.string.tracklist_share_link);
|
||||
R.string.tracklist_share_linkfusion);
|
||||
share.add(0, MyTracksConstants.MENU_SHARE_GPX_FILE, 0,
|
||||
R.string.tracklist_share_gpx_file);
|
||||
share.add(0, MyTracksConstants.MENU_SHARE_KML_FILE, 0,
|
||||
|
||||
@@ -29,7 +29,6 @@ import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
|
||||
/**
|
||||
* A dialog where the user can choose where to send the tracks to, i.e.
|
||||
@@ -39,10 +38,7 @@ import android.widget.RadioGroup;
|
||||
*/
|
||||
public class SendToGoogleDialog extends Dialog {
|
||||
|
||||
private RadioGroup groupMyMaps;
|
||||
private RadioButton createNewMapRadioButton;
|
||||
private RadioButton pickMapRadioButton;
|
||||
private CheckBox sendToMyMapsCheckBox;
|
||||
private CheckBox sendToFusionTablesCheckBox;
|
||||
private CheckBox sendToDocsCheckBox;
|
||||
private RadioButton sendStatsRadioButton;
|
||||
private RadioButton sendStatsAndPointsRadioButton;
|
||||
@@ -76,26 +72,19 @@ public class SendToGoogleDialog extends Dialog {
|
||||
OnCheckedChangeListener checkBoxListener = new OnCheckedChangeListener() {
|
||||
public void onCheckedChanged(CompoundButton button, boolean checked) {
|
||||
sendButton.setEnabled(
|
||||
sendToMyMapsCheckBox.isChecked() ||
|
||||
sendToFusionTablesCheckBox.isChecked() ||
|
||||
sendToDocsCheckBox.isChecked());
|
||||
groupMyMaps.setVisibility(
|
||||
sendToMyMapsCheckBox.isChecked() ? View.VISIBLE : View.INVISIBLE);
|
||||
//groupDocs.setVisibility(
|
||||
// sendToDocsCheckBox.isChecked() ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
};
|
||||
|
||||
sendButton = (Button) findViewById(R.id.sendtogoogle_send_now);
|
||||
groupMyMaps = (RadioGroup) findViewById(R.id.sendtogoogle_group_mymaps);
|
||||
sendToMyMapsCheckBox =
|
||||
(CheckBox) findViewById(R.id.sendtogoogle_google_mymaps);
|
||||
sendToMyMapsCheckBox.setOnCheckedChangeListener(checkBoxListener);
|
||||
sendToFusionTablesCheckBox =
|
||||
(CheckBox) findViewById(R.id.sendtogoogle_google_fusiontables);
|
||||
sendToFusionTablesCheckBox.setOnCheckedChangeListener(checkBoxListener);
|
||||
sendToDocsCheckBox = (CheckBox) findViewById(R.id.sendtogoogle_google_docs);
|
||||
sendToDocsCheckBox.setOnCheckedChangeListener(checkBoxListener);
|
||||
createNewMapRadioButton =
|
||||
(RadioButton) findViewById(R.id.sendtogoogle_create_new_map);
|
||||
pickMapRadioButton =
|
||||
(RadioButton) findViewById(R.id.sendtogoogle_pick_existing_map);
|
||||
sendStatsRadioButton =
|
||||
(RadioButton) findViewById(R.id.sendtogoogle_send_stats);
|
||||
sendStatsAndPointsRadioButton = (RadioButton) findViewById(
|
||||
@@ -104,18 +93,12 @@ public class SendToGoogleDialog extends Dialog {
|
||||
SharedPreferences prefs =
|
||||
getContext().getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
||||
if (prefs != null) {
|
||||
sendToMyMapsCheckBox.setChecked(
|
||||
sendToFusionTablesCheckBox.setChecked(
|
||||
prefs.getBoolean(
|
||||
getContext().getString(R.string.send_to_my_maps_key), true));
|
||||
sendToDocsCheckBox.setChecked(
|
||||
prefs.getBoolean(
|
||||
getContext().getString(R.string.send_to_docs_key), true));
|
||||
pickMapRadioButton.setChecked(
|
||||
prefs.getBoolean(
|
||||
getContext().getString(R.string.pick_existing_map_key), false));
|
||||
createNewMapRadioButton.setChecked(
|
||||
!prefs.getBoolean(
|
||||
getContext().getString(R.string.pick_existing_map_key), false));
|
||||
sendStatsAndPointsRadioButton.setChecked(
|
||||
prefs.getBoolean(
|
||||
getContext().getString(R.string.send_stats_and_points_key),
|
||||
@@ -136,13 +119,10 @@ public class SendToGoogleDialog extends Dialog {
|
||||
if (editor != null) {
|
||||
editor.putBoolean(
|
||||
getContext().getString(R.string.send_to_my_maps_key),
|
||||
sendToMyMapsCheckBox.isChecked());
|
||||
sendToFusionTablesCheckBox.isChecked());
|
||||
editor.putBoolean(
|
||||
getContext().getString(R.string.send_to_docs_key),
|
||||
sendToDocsCheckBox.isChecked());
|
||||
editor.putBoolean(
|
||||
getContext().getString(R.string.pick_existing_map_key),
|
||||
pickMapRadioButton.isChecked());
|
||||
editor.putBoolean(
|
||||
getContext().getString(R.string.send_stats_and_points_key),
|
||||
sendStatsAndPointsRadioButton.isChecked());
|
||||
@@ -152,18 +132,14 @@ public class SendToGoogleDialog extends Dialog {
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
public boolean getSendToMyMaps() {
|
||||
return sendToMyMapsCheckBox.isChecked();
|
||||
public boolean getSendToFusionTables() {
|
||||
return sendToFusionTablesCheckBox.isChecked();
|
||||
}
|
||||
|
||||
public boolean getSendToDocs() {
|
||||
return sendToDocsCheckBox.isChecked();
|
||||
}
|
||||
|
||||
public boolean getCreateNewMap() {
|
||||
return createNewMapRadioButton.isChecked();
|
||||
}
|
||||
|
||||
public boolean getSendStatsAndPoints() {
|
||||
return sendStatsAndPointsRadioButton.isChecked();
|
||||
}
|
||||
|
||||
@@ -15,16 +15,13 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
import com.google.android.apps.mytracks.util.MyTracksUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
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;
|
||||
@@ -84,16 +81,7 @@ 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);
|
||||
}
|
||||
((TextView) dialog.findViewById(R.id.about_version_register)).
|
||||
setText(MyTracksUtils.getMyTracksVersion(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,8 @@ public class MyTracksProvider extends ContentProvider {
|
||||
+ TracksColumns.ELEVATIONGAIN + " FLOAT, "
|
||||
+ TracksColumns.MINGRADE + " FLOAT, "
|
||||
+ TracksColumns.MAXGRADE + " FLOAT, "
|
||||
+ TracksColumns.MAPID + " STRING);");
|
||||
+ TracksColumns.MAPID + " STRING, "
|
||||
+ TracksColumns.TABLEID + " STRING);");
|
||||
db.execSQL("CREATE TABLE " + WAYPOINTS_TABLE + " ("
|
||||
+ WaypointsColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
+ WaypointsColumns.NAME + " STRING, "
|
||||
@@ -146,13 +147,15 @@ public class MyTracksProvider extends ContentProvider {
|
||||
} else {
|
||||
// Incremental updates go here.
|
||||
// Each time you increase the DB version, add a corresponding if clause.
|
||||
|
||||
|
||||
// Sensor data.
|
||||
if (oldVersion <= 17) {
|
||||
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
|
||||
+ newVersion + ", adding sensor column.");
|
||||
+ newVersion + ", adding sensor and tableid columns.");
|
||||
db.execSQL("ALTER TABLE " + TRACKPOINTS_TABLE
|
||||
+ " ADD " + TrackPointsColumns.SENSOR + " BLOB");
|
||||
db.execSQL("ALTER TABLE " + TRACKS_TABLE
|
||||
+ " ADD " + TracksColumns.TABLEID + " STRING");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.google.wireless.gdata.client.GDataClient;
|
||||
import com.google.wireless.gdata.docs.DocumentsClient;
|
||||
import com.google.wireless.gdata.docs.SpreadsheetsClient;
|
||||
import com.google.wireless.gdata.maps.xml.XmlMapsGDataParserFactory;
|
||||
import com.google.wireless.gdata.client.GDataServiceClient;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
@@ -158,11 +159,11 @@ public class SendToDocs {
|
||||
* @param track the track
|
||||
*/
|
||||
private boolean uploadToDocs(Track track) {
|
||||
GDataWrapper docListWrapper = new GDataWrapper();
|
||||
GDataWrapper<GDataServiceClient> docListWrapper = new GDataWrapper<GDataServiceClient>();
|
||||
docListWrapper.setAuthManager(docListAuth);
|
||||
docListWrapper.setRetryOnAuthFailure(true);
|
||||
|
||||
GDataWrapper trixWrapper = new GDataWrapper();
|
||||
GDataWrapper<GDataServiceClient> trixWrapper = new GDataWrapper<GDataServiceClient>();
|
||||
trixWrapper.setAuthManager(trixAuth);
|
||||
trixWrapper.setRetryOnAuthFailure(true);
|
||||
|
||||
@@ -304,5 +305,4 @@ public class SendToDocs {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,658 @@
|
||||
/*
|
||||
* 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.MyTracksSettings;
|
||||
import com.google.android.apps.mytracks.ProgressIndicator;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.io.gdata.GDataWrapper;
|
||||
import com.google.android.apps.mytracks.io.gdata.GDataWrapper.QueryFunction;
|
||||
import com.google.android.apps.mytracks.stats.DoubleBuffer;
|
||||
import com.google.android.apps.mytracks.stats.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;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.api.client.googleapis.GoogleHeaders;
|
||||
import com.google.api.client.googleapis.GoogleTransport;
|
||||
import com.google.api.client.http.GenericUrl;
|
||||
import com.google.api.client.http.HttpRequest;
|
||||
import com.google.api.client.http.HttpResponse;
|
||||
import com.google.api.client.http.HttpResponseException;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.api.client.http.InputStreamContent;
|
||||
import com.google.api.client.util.Strings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* A helper class used to transmit tracks to Google Fusion Tables.
|
||||
* A new instance should be used for each upload.
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
*/
|
||||
public class SendToFusionTables implements Runnable {
|
||||
|
||||
/**
|
||||
* Listener invoked when sending to fusion tables completes.
|
||||
*/
|
||||
public interface OnSendCompletedListener {
|
||||
void onSendCompleted(String tableId, boolean success, int statusMessage);
|
||||
}
|
||||
|
||||
/** The GData service id for Fusion Tables. */
|
||||
public static final String SERVICE_ID = "fusiontables";
|
||||
|
||||
/** The path for viewing a map visualization of a table. */
|
||||
private static final String FUSIONTABLES_MAP =
|
||||
"http://www.google.com/fusiontables/embedviz?" +
|
||||
"viz=MAP&q=select+col0,+col1,+col2,+col3+from+%s+&h=false&" +
|
||||
"lat=%f&lng=%f&z=%d&t=1&l=col2";
|
||||
|
||||
/** Standard base feed url for Fusion Tables. */
|
||||
private static final String FUSIONTABLES_BASE_FEED_URL =
|
||||
"http://www.google.com/fusiontables/api/query";
|
||||
|
||||
private static final int MAX_POINTS_PER_UPLOAD = 2048;
|
||||
|
||||
private static final String GDATA_VERSION = "2";
|
||||
|
||||
private final Activity context;
|
||||
private final AuthManager auth;
|
||||
private final long trackId;
|
||||
private final ProgressIndicator progressIndicator;
|
||||
private final OnSendCompletedListener onCompletion;
|
||||
private final StringUtils stringUtils;
|
||||
private final MyTracksProviderUtils providerUtils;
|
||||
|
||||
// Progress status
|
||||
private int totalLocationsRead;
|
||||
private int totalLocationsPrepared;
|
||||
private int totalLocationsUploaded;
|
||||
private int totalLocations;
|
||||
private int totalSegmentsUploaded;
|
||||
|
||||
private HttpTransport transport;
|
||||
private String tableId;
|
||||
|
||||
private static String MARKER_TYPE_START = "large_green";
|
||||
private static String MARKER_TYPE_END = "large_red";
|
||||
private static String MARKER_TYPE_WAYPOINT = "large_yellow";
|
||||
|
||||
public SendToFusionTables(Activity context, AuthManager auth,
|
||||
long trackId, ProgressIndicator progressIndicator,
|
||||
OnSendCompletedListener onCompletion) {
|
||||
this.context = context;
|
||||
this.auth = auth;
|
||||
this.trackId = trackId;
|
||||
this.progressIndicator = progressIndicator;
|
||||
this.onCompletion = onCompletion;
|
||||
this.stringUtils = new StringUtils(context);
|
||||
this.providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
transport = GoogleTransport.create();
|
||||
GoogleHeaders headers = (GoogleHeaders) transport.defaultHeaders;
|
||||
headers.setApplicationName("Google-MyTracks-" + MyTracksUtils.getMyTracksVersion(context));
|
||||
headers.gdataVersion = GDATA_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d(MyTracksConstants.TAG, "Sending to Fusion tables: trackId = " + trackId);
|
||||
doUpload();
|
||||
}
|
||||
|
||||
public static String getMapVisualizationUrl(Track track) {
|
||||
// TODO(leifhendrik): Determine correct bounding box and zoom level that will show the entire track.
|
||||
TripStatistics stats = track.getStatistics();
|
||||
double latE6 = stats.getBottom() + (stats.getTop() - stats.getBottom()) / 2;
|
||||
double lonE6 = stats.getLeft() + (stats.getRight() - stats.getLeft()) / 2;
|
||||
int z = 15;
|
||||
return String.format(FUSIONTABLES_MAP, track.getTableId(), latE6 / 1.E6, lonE6 / 1.E6, z);
|
||||
}
|
||||
|
||||
private void doUpload() {
|
||||
((GoogleHeaders) transport.defaultHeaders).setGoogleLogin(auth.getAuthToken());
|
||||
int statusMessageId = R.string.error_sending_to_fusiontables;
|
||||
boolean success = true;
|
||||
try {
|
||||
progressIndicator.setProgressValue(1);
|
||||
progressIndicator.setProgressMessage(R.string.progress_message_reading_track);
|
||||
|
||||
// Get the track meta-data
|
||||
Track track = providerUtils.getTrack(trackId);
|
||||
String originalDescription = track.getDescription();
|
||||
|
||||
// Create a new table:
|
||||
progressIndicator.setProgressMessage(R.string.progress_message_creating_fusiontable);
|
||||
success = createNewTable(track);
|
||||
|
||||
if (success) {
|
||||
success = makeTableUnlisted(tableId);
|
||||
}
|
||||
|
||||
// Upload all of the segments of the track plus start/end markers
|
||||
if (success) {
|
||||
success = uploadAllTrackPoints(track, originalDescription);
|
||||
}
|
||||
|
||||
// Upload all the waypoints.
|
||||
if (success) {
|
||||
success = uploadWaypoints(track);
|
||||
statusMessageId = R.string.status_new_fusiontable_has_been_created;
|
||||
}
|
||||
Log.d(MyTracksConstants.TAG, "SendToFusionTables: Done: " + success);
|
||||
progressIndicator.setProgressValue(100);
|
||||
} finally {
|
||||
|
||||
final boolean finalSuccess = success;
|
||||
final int finalStatusMessageId = statusMessageId;
|
||||
context.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if (onCompletion != null) {
|
||||
onCompletion.onSendCompleted(
|
||||
tableId, finalSuccess, finalStatusMessageId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new table.
|
||||
* If successful sets {@link #tableId}.
|
||||
*
|
||||
* @return true in case of success.
|
||||
*/
|
||||
private boolean createNewTable(Track track) {
|
||||
Log.d(MyTracksConstants.TAG, "Creating a new fusion table.");
|
||||
String query = "CREATE TABLE '" + track.getName() +
|
||||
"' (name:STRING,description:STRING,geometry:LOCATION,marker:STRING)";
|
||||
return runUpdate(query);
|
||||
}
|
||||
|
||||
private boolean makeTableUnlisted(String tableId) {
|
||||
Log.d(MyTracksConstants.TAG, "Setting visibility to unlisted.");
|
||||
String query = "UPDATE TABLE " + tableId + " SET VISIBILITY = unlisted";
|
||||
return runUpdate(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats given values SQL style. Escapes single quotes with a backslash.
|
||||
*
|
||||
* @param values the values to format
|
||||
* @return the values formatted as: ('value1','value2',...,'value_n').
|
||||
*/
|
||||
private static String values(String... values) {
|
||||
StringBuilder builder = new StringBuilder("(");
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (i > 0) {
|
||||
builder.append(',');
|
||||
}
|
||||
builder.append('\'');
|
||||
builder.append(values[i].replaceAll("'", "''"));
|
||||
builder.append('\'');
|
||||
}
|
||||
builder.append(')');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new row representing a marker.
|
||||
*
|
||||
* @param name the marker name
|
||||
* @param description the marker description
|
||||
* @param the marker location
|
||||
* @return true in case of success.
|
||||
*/
|
||||
private boolean createNewPoint(String name, String description, Location location,
|
||||
String marker) {
|
||||
Log.d(MyTracksConstants.TAG, "Creating a new row with a point.");
|
||||
String query = "INSERT INTO " + tableId + " (name,description,geometry,marker) VALUES "
|
||||
+ values(name, description, getKmlPoint(location), marker);
|
||||
return runUpdate(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new row representing a line segment.
|
||||
*
|
||||
* @param track the track/segment to draw
|
||||
* @return true in case of success.
|
||||
*/
|
||||
private boolean createNewLineString(Track track) {
|
||||
Log.d(MyTracksConstants.TAG, "Creating a new row with a point.");
|
||||
String query = "INSERT INTO " + tableId
|
||||
+ " (name,description,geometry) VALUES "
|
||||
+ values(track.getName(), track.getDescription(), getKmlLineString(track));
|
||||
return runUpdate(query);
|
||||
}
|
||||
|
||||
private boolean uploadAllTrackPoints(final Track track, String originalDescription) {
|
||||
|
||||
SharedPreferences preferences = context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
|
||||
boolean metricUnits = true;
|
||||
if (preferences != null) {
|
||||
metricUnits = preferences.getBoolean(context.getString(R.string.metric_units_key), true);
|
||||
}
|
||||
|
||||
Cursor locationsCursor = providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
|
||||
try {
|
||||
if (!locationsCursor.moveToFirst()) {
|
||||
Log.w(MyTracksConstants.TAG, "Unable to get any points to upload");
|
||||
return false;
|
||||
}
|
||||
|
||||
totalLocationsRead = 0;
|
||||
totalLocationsPrepared = 0;
|
||||
totalLocationsUploaded = 0;
|
||||
totalLocations = locationsCursor.getCount();
|
||||
totalSegmentsUploaded = 0;
|
||||
|
||||
// Limit the number of elevation readings. Ideally we would want around 250.
|
||||
int elevationSamplingFrequency =
|
||||
Math.max(1, (int) (totalLocations / 250.0));
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"Using elevation sampling factor: " + elevationSamplingFrequency
|
||||
+ " on " + totalLocations);
|
||||
double totalDistance = 0;
|
||||
|
||||
Vector<Double> distances = new Vector<Double>();
|
||||
Vector<Double> elevations = new Vector<Double>();
|
||||
DoubleBuffer elevationBuffer = new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
|
||||
|
||||
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
|
||||
progressIndicator.setProgressMessage(R.string.progress_message_reading_track);
|
||||
Location lastLocation = null;
|
||||
do {
|
||||
if (totalLocationsRead % 100 == 0) {
|
||||
updateProgress();
|
||||
}
|
||||
|
||||
Location loc = providerUtils.createLocation(locationsCursor);
|
||||
locations.add(loc);
|
||||
|
||||
if (totalLocationsRead == 0) {
|
||||
// Put a marker at the first point of the first valid segment:
|
||||
String name = track.getName() + " " + context.getString(R.string.start);
|
||||
createNewPoint(name, "", loc, MARKER_TYPE_START);
|
||||
}
|
||||
|
||||
// Add to the elevation profile.
|
||||
if (loc != null && MyTracksUtils.isValidLocation(loc)) {
|
||||
// All points go into the smoothing buffer...
|
||||
elevationBuffer.setNext(metricUnits ? loc.getAltitude()
|
||||
: loc.getAltitude() * UnitConversions.M_TO_FT);
|
||||
if (lastLocation != null) {
|
||||
double dist = lastLocation.distanceTo(loc);
|
||||
totalDistance += dist;
|
||||
}
|
||||
|
||||
// ...but only a few points are really used to keep the url short.
|
||||
if (totalLocationsRead % elevationSamplingFrequency == 0) {
|
||||
distances.add(totalDistance);
|
||||
elevations.add(elevationBuffer.getAverage());
|
||||
}
|
||||
}
|
||||
|
||||
// If the location was not valid, it's a segment split, so make sure the
|
||||
// distance between the previous segment and the new one is not accounted
|
||||
// for in the next iteration.
|
||||
lastLocation = loc;
|
||||
|
||||
// Every now and then, upload the accumulated points
|
||||
if (totalLocationsRead % MAX_POINTS_PER_UPLOAD == MAX_POINTS_PER_UPLOAD - 1) {
|
||||
if (!prepareAndUploadPoints(track, locations)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
totalLocationsRead++;
|
||||
} while (locationsCursor.moveToNext());
|
||||
|
||||
// Do a final upload with what's left
|
||||
if (!prepareAndUploadPoints(track, locations)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Put an end marker at the last point of the last valid segment:
|
||||
if (lastLocation != null) {
|
||||
track.setDescription("<p>" + originalDescription + "</p><p>"
|
||||
+ stringUtils.generateTrackDescription(track, distances, elevations)
|
||||
+ "</p>");
|
||||
String name = track.getName() + " " + context.getString(R.string.end);
|
||||
return createNewPoint(name, track.getDescription(), lastLocation, MARKER_TYPE_END);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
locationsCursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the given location to the string in the format:
|
||||
* longitude,latitude[,altitude]
|
||||
*
|
||||
* @param location the location to be added
|
||||
* @param builder the string builder to use
|
||||
*/
|
||||
private void appendCoordinate(Location location, StringBuilder builder) {
|
||||
builder
|
||||
.append(location.getLongitude())
|
||||
.append(",")
|
||||
.append(location.getLatitude());
|
||||
if (location.hasAltitude()) {
|
||||
builder.append(",");
|
||||
builder.append(location.getAltitude());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a KML Point tag for the given location.
|
||||
*
|
||||
* @param location The location.
|
||||
* @return the kml.
|
||||
*/
|
||||
private String getKmlPoint(Location location) {
|
||||
StringBuilder builder = new StringBuilder("<Point><coordinates>");
|
||||
appendCoordinate(location, builder);
|
||||
builder.append("</coordinates></Point>");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a KML Point tag for the given location.
|
||||
*
|
||||
* @param location The location.
|
||||
* @return the kml.
|
||||
*/
|
||||
private String getKmlLineString(Track track) {
|
||||
StringBuilder builder = new StringBuilder("<LineString><coordinates>");
|
||||
for (Location location : track.getLocations()) {
|
||||
appendCoordinate(location, builder);
|
||||
builder.append(' ');
|
||||
}
|
||||
builder.append("</coordinates></LineString>");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private boolean prepareAndUploadPoints(Track track, List<Location> locations) {
|
||||
progressIndicator.setProgressMessage(R.string.progress_message_preparing_track);
|
||||
updateProgress();
|
||||
|
||||
int numLocations = locations.size();
|
||||
if (numLocations < 2) {
|
||||
Log.d(MyTracksConstants.TAG, "Not preparing/uploading too few points");
|
||||
totalLocationsUploaded += numLocations;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Prepare/pre-process the points
|
||||
ArrayList<Track> splitTracks = prepareLocations(track, locations);
|
||||
|
||||
// Start uploading them
|
||||
progressIndicator.setProgressMessage(R.string.progress_message_sending_fusiontables);
|
||||
for (Track splitTrack : splitTracks) {
|
||||
if (totalSegmentsUploaded > 1) {
|
||||
splitTrack.setName(splitTrack.getName() + " "
|
||||
+ String.format(
|
||||
context.getString(R.string.part), totalSegmentsUploaded));
|
||||
}
|
||||
totalSegmentsUploaded++;
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"SendToFusionTables: Prepared feature for upload w/ "
|
||||
+ splitTrack.getLocations().size() + " points.");
|
||||
|
||||
// Transmit tracks via GData feed:
|
||||
// -------------------------------
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"SendToFusionTables: Uploading to table " + tableId + " w/ auth " + auth);
|
||||
if (!uploadTrackPoints(splitTrack)) {
|
||||
Log.e(MyTracksConstants.TAG, "Uploading failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
locations.clear();
|
||||
totalLocationsUploaded += numLocations;
|
||||
updateProgress();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a buffer of locations for transmission to google fusion tables.
|
||||
*
|
||||
* @param track the original track with meta data
|
||||
* @param buffer a buffer of locations on the track
|
||||
* @return an array of tracks each with a sub section of the points in the
|
||||
* original buffer
|
||||
*/
|
||||
private ArrayList<Track> prepareLocations(
|
||||
Track track, Iterable<Location> locations) {
|
||||
ArrayList<Track> splitTracks = new ArrayList<Track>();
|
||||
|
||||
// Create segments from each full track:
|
||||
Track segment = new Track();
|
||||
TripStatistics segmentStats = segment.getStatistics();
|
||||
TripStatistics trackStats = track.getStatistics();
|
||||
segment.setId(track.getId());
|
||||
segment.setName(track.getName());
|
||||
segment.setDescription(/* track.getDescription() */ "");
|
||||
segment.setCategory(track.getCategory());
|
||||
segmentStats.setStartTime(trackStats.getStartTime());
|
||||
segmentStats.setStopTime(trackStats.getStopTime());
|
||||
boolean startNewTrackSegment = false;
|
||||
for (Location loc : locations) {
|
||||
if (totalLocationsPrepared % 100 == 0) {
|
||||
updateProgress();
|
||||
}
|
||||
if (loc.getLatitude() > 90) {
|
||||
startNewTrackSegment = true;
|
||||
}
|
||||
|
||||
if (startNewTrackSegment) {
|
||||
// Close up the last segment.
|
||||
prepareTrackSegment(segment, splitTracks);
|
||||
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"MyTracksSendToFusionTables: Starting new track segment...");
|
||||
startNewTrackSegment = false;
|
||||
segment = new Track();
|
||||
segment.setId(track.getId());
|
||||
segment.setName(track.getName());
|
||||
segment.setDescription(/* track.getDescription() */ "");
|
||||
segment.setCategory(track.getCategory());
|
||||
}
|
||||
|
||||
if (loc.getLatitude() <= 90) {
|
||||
segment.addLocation(loc);
|
||||
if (segmentStats.getStartTime() < 0) {
|
||||
segmentStats.setStartTime(loc.getTime());
|
||||
}
|
||||
}
|
||||
totalLocationsPrepared++;
|
||||
}
|
||||
|
||||
prepareTrackSegment(segment, splitTracks);
|
||||
|
||||
return splitTracks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a track segment for sending to google fusion tables.
|
||||
* The main steps are:
|
||||
* - correcting end time
|
||||
* - decimating locations
|
||||
* - splitting into smaller tracks.
|
||||
*
|
||||
* The final track pieces will be put in the array list splitTracks.
|
||||
*
|
||||
* @param segment the original segment of the track
|
||||
* @param splitTracks an array of smaller track segments
|
||||
*/
|
||||
private void prepareTrackSegment(
|
||||
Track segment, ArrayList<Track> splitTracks) {
|
||||
TripStatistics segmentStats = segment.getStatistics();
|
||||
if (segmentStats.getStopTime() < 0
|
||||
&& segment.getLocations().size() > 0) {
|
||||
segmentStats.setStopTime(segment.getLocations().size() - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decimate to 2 meter precision. Fusion tables doesn't like too many
|
||||
* points:
|
||||
*/
|
||||
MyTracksUtils.decimate(segment, 2.0);
|
||||
|
||||
/* If the track still has > 2500 points, split it in pieces: */
|
||||
final int maxPoints = 2500;
|
||||
if (segment.getLocations().size() > maxPoints) {
|
||||
splitTracks.addAll(MyTracksUtils.split(segment, maxPoints));
|
||||
} else if (segment.getLocations().size() >= 2) {
|
||||
splitTracks.add(segment);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean uploadTrackPoints(Track splitTrack) {
|
||||
int numLocations = splitTrack.getLocations().size();
|
||||
if (numLocations < 2) {
|
||||
// Need at least two points for a polyline:
|
||||
Log.w(MyTracksConstants.TAG, "Not uploading too few points");
|
||||
return true;
|
||||
}
|
||||
return createNewLineString(splitTrack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads all of the waypoints associated with this track to a table.
|
||||
*
|
||||
* @param track The track to upload waypoints for.
|
||||
*
|
||||
* @return True on success.
|
||||
*/
|
||||
private boolean uploadWaypoints(final Track track) {
|
||||
// TODO: Stream through the waypoints in chunks.
|
||||
// I am leaving the number of waypoints very high which should not be a
|
||||
// problem because we don't try to load them into objects all at the
|
||||
// same time.
|
||||
boolean success = true;
|
||||
Cursor c = null;
|
||||
c = providerUtils.getWaypointsCursor(
|
||||
track.getId(), 0,
|
||||
MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS);
|
||||
if (c != null) {
|
||||
if (c.moveToFirst()) {
|
||||
// This will skip the 1st waypoint (it carries the stats for the
|
||||
// last segment).
|
||||
while (c.moveToNext()) {
|
||||
Waypoint wpt = providerUtils.createWaypoint(c);
|
||||
Log.d(MyTracksConstants.TAG, "SendToFusionTables: Creating waypoint.");
|
||||
success = createNewPoint(wpt.getName(), wpt.getDescription(), wpt.getLocation(),
|
||||
MARKER_TYPE_WAYPOINT);
|
||||
if (!success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
Log.w(MyTracksConstants.TAG, "SendToFusionTables: upload waypoints failed.");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current upload progress.
|
||||
*/
|
||||
private void updateProgress() {
|
||||
// The percent of the total that represents the completed part of this
|
||||
// segment.
|
||||
int totalPercentage =
|
||||
(totalLocationsRead + totalLocationsPrepared + totalLocationsUploaded)
|
||||
/ (totalLocations * 3);
|
||||
totalPercentage = Math.min(99, totalPercentage);
|
||||
progressIndicator.setProgressValue(totalPercentage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs an update query. Handles authentication.
|
||||
*
|
||||
* @param query The given SQL like query
|
||||
* @return true in case of success
|
||||
*/
|
||||
private boolean runUpdate(final String query) {
|
||||
GDataWrapper<HttpTransport> wrapper = new GDataWrapper<HttpTransport>();
|
||||
wrapper.setAuthManager(auth);
|
||||
wrapper.setRetryOnAuthFailure(true);
|
||||
wrapper.setClient(transport);
|
||||
Log.d(MyTracksConstants.TAG, "GData connection prepared: " + this.auth);
|
||||
wrapper.runQuery(new QueryFunction<HttpTransport>() {
|
||||
@Override
|
||||
public void query(HttpTransport client)
|
||||
throws IOException, GDataWrapper.ParseException, GDataWrapper.HttpException,
|
||||
GDataWrapper.AuthenticationException {
|
||||
HttpRequest request = transport.buildPostRequest();
|
||||
request.headers.contentType = "application/x-www-form-urlencoded";
|
||||
GenericUrl url = new GenericUrl(FUSIONTABLES_BASE_FEED_URL);
|
||||
request.url = url;
|
||||
InputStreamContent isc = new InputStreamContent();
|
||||
String sql = "sql=" + URLEncoder.encode(query, "UTF-8");
|
||||
isc.inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql));
|
||||
request.content = isc;
|
||||
Log.d(MyTracksConstants.TAG, "Running update query " + url.toString() + ": " + sql);
|
||||
try {
|
||||
HttpResponse response = request.execute();
|
||||
boolean success = response.isSuccessStatusCode;
|
||||
if (success) {
|
||||
byte[] result = new byte[1024];
|
||||
response.getContent().read(result);
|
||||
String s = Strings.fromBytesUtf8(result);
|
||||
String[] lines = s.split(Strings.LINE_SEPARATOR);
|
||||
if (lines[0].equals("tableid")) {
|
||||
tableId = lines[1];
|
||||
Log.d(MyTracksConstants.TAG, "tableId = " + tableId);
|
||||
} else {
|
||||
Log.w(MyTracksConstants.TAG, "Unrecognized response: " + lines[0]);
|
||||
}
|
||||
} else {
|
||||
Log.d(MyTracksConstants.TAG, "Query failed: " + response.statusMessage + " (" +
|
||||
response.statusCode + ")");
|
||||
throw new GDataWrapper.HttpException(response.statusCode, response.statusMessage);
|
||||
}
|
||||
} catch (HttpResponseException e) {
|
||||
if (e.response.statusCode == 401) {
|
||||
throw new GDataWrapper.AuthenticationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
return wrapper.getErrorType() == GDataWrapper.ERROR_NO_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -1,689 +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.mymaps.MyMapsFeature;
|
||||
import com.google.android.apps.mymaps.MyMapsGDataConverter;
|
||||
import com.google.android.apps.mymaps.MyMapsGDataWrapper;
|
||||
import com.google.android.apps.mymaps.MyMapsGDataWrapper.QueryFunction;
|
||||
import com.google.android.apps.mymaps.MyMapsMapMetadata;
|
||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
||||
import com.google.android.apps.mytracks.MyTracksSettings;
|
||||
import com.google.android.apps.mytracks.ProgressIndicator;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.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;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.wireless.gdata.client.HttpException;
|
||||
import com.google.wireless.gdata.data.Entry;
|
||||
import com.google.wireless.gdata.maps.MapsClient;
|
||||
import com.google.wireless.gdata.parser.ParseException;
|
||||
import com.google.wireless.gdata2.client.AuthenticationException;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
/**
|
||||
* A helper class used to transmit tracks to Google MyMaps.
|
||||
* A new instance should be used for each upload.
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
*/
|
||||
public class SendToMyMaps implements Runnable {
|
||||
|
||||
public static final String NEW_MAP_ID = "new";
|
||||
private static final String END_ICON_URL =
|
||||
"http://maps.google.com/mapfiles/ms/micons/red-dot.png";
|
||||
private static final String START_ICON_URL =
|
||||
"http://maps.google.com/mapfiles/ms/micons/green-dot.png";
|
||||
private static final int MAX_POINTS_PER_UPLOAD = 2048;
|
||||
|
||||
private final Activity context;
|
||||
private final AuthManager auth;
|
||||
private final long trackId;
|
||||
private final ProgressIndicator progressIndicator;
|
||||
private final OnSendCompletedListener onCompletion;
|
||||
private final StringUtils stringUtils;
|
||||
private final MyTracksProviderUtils providerUtils;
|
||||
private String mapId;
|
||||
|
||||
// GData service
|
||||
private MyMapsGDataWrapper wrapper;
|
||||
private MyMapsGDataConverter gdataConverter;
|
||||
|
||||
// Progress status
|
||||
private int totalLocationsRead;
|
||||
private int totalLocationsPrepared;
|
||||
private int totalLocationsUploaded;
|
||||
private int totalLocations;
|
||||
private int totalSegmentsUploaded;
|
||||
|
||||
public interface OnSendCompletedListener {
|
||||
void onSendCompleted(String mapId, boolean success, int statusMessage);
|
||||
}
|
||||
|
||||
public SendToMyMaps(Activity context, String mapId, AuthManager auth,
|
||||
long trackId, ProgressIndicator progressIndicator,
|
||||
OnSendCompletedListener onCompletion) {
|
||||
this.context = context;
|
||||
this.mapId = mapId;
|
||||
this.auth = auth;
|
||||
this.trackId = trackId;
|
||||
this.progressIndicator = progressIndicator;
|
||||
this.onCompletion = onCompletion;
|
||||
this.stringUtils = new StringUtils(context);
|
||||
this.providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d(MyTracksConstants.TAG, "Sending to MyMaps: trackId = " + trackId);
|
||||
doUpload();
|
||||
}
|
||||
|
||||
private void doUpload() {
|
||||
int statusMessageId = R.string.error_sending_to_mymap;
|
||||
boolean success = true;
|
||||
try {
|
||||
gdataConverter = new MyMapsGDataConverter();
|
||||
|
||||
progressIndicator.setProgressValue(1);
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_reading_track);
|
||||
|
||||
// Get the track meta-data
|
||||
Track track = providerUtils.getTrack(trackId);
|
||||
String originalDescription = track.getDescription();
|
||||
track.setDescription("<p>" + track.getDescription() + "</p><p>"
|
||||
+ stringUtils.generateTrackDescription(track, null, null) + "</p>");
|
||||
wrapper = new MyMapsGDataWrapper(context);
|
||||
wrapper.setAuthManager(auth);
|
||||
wrapper.setRetryOnAuthFailure(true);
|
||||
|
||||
// Create a new map if necessary:
|
||||
boolean isNewMap = mapId.equals(NEW_MAP_ID);
|
||||
if (isNewMap) {
|
||||
success = createNewMap(track, originalDescription);
|
||||
}
|
||||
|
||||
// Upload all of the segments of the track plus start/end markers
|
||||
if (success) {
|
||||
success = uploadAllTrackPoints(track, originalDescription);
|
||||
}
|
||||
|
||||
// Put waypoints.
|
||||
if (success) {
|
||||
success = uploadWaypoints(track);
|
||||
if (!success) {
|
||||
Log.w(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: upload waypoints failed.");
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
statusMessageId = isNewMap
|
||||
? R.string.status_new_mymap_has_been_created
|
||||
: R.string.status_tracks_have_been_uploaded;
|
||||
}
|
||||
Log.d(MyTracksConstants.TAG, "SendToMyMaps: Done: " + success);
|
||||
progressIndicator.setProgressValue(100);
|
||||
} catch (XmlPullParserException e) {
|
||||
Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e);
|
||||
} finally {
|
||||
if (wrapper != null) {
|
||||
wrapper.cleanUp();
|
||||
}
|
||||
|
||||
final boolean finalSuccess = success;
|
||||
final int finalStatusMessageId = statusMessageId;
|
||||
context.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if (onCompletion != null) {
|
||||
onCompletion.onSendCompleted(
|
||||
mapId, finalSuccess, finalStatusMessageId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map for the given track.
|
||||
*
|
||||
* @param track The track that will be uploaded to this map
|
||||
* @return True on success.
|
||||
*/
|
||||
private boolean createNewMap(final Track track, final String description) {
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_creating_map);
|
||||
return wrapper.runQuery(new QueryFunction() {
|
||||
@Override
|
||||
public void query(MapsClient client) throws IOException, Exception {
|
||||
Log.d(MyTracksConstants.TAG, "Creating a new map.");
|
||||
String mapFeed = MapsClient.getMapsFeed();
|
||||
Log.d(MyTracksConstants.TAG, "Map feed is " + mapFeed);
|
||||
MyMapsMapMetadata metaData = new MyMapsMapMetadata();
|
||||
metaData.setTitle(track.getName());
|
||||
metaData.setDescription(description + " - "
|
||||
+ track.getCategory() + " - "
|
||||
+ context.getString(R.string.new_map_description));
|
||||
SharedPreferences preferences = context.getSharedPreferences(
|
||||
MyTracksSettings.SETTINGS_NAME, 0);
|
||||
boolean mapPublic = true;
|
||||
if (preferences != null) {
|
||||
mapPublic = preferences.getBoolean(
|
||||
context.getString(R.string.default_map_public_key), true);
|
||||
}
|
||||
metaData.setSearchable(mapPublic);
|
||||
Entry entry = MyMapsGDataConverter.getMapEntryForMetadata(metaData);
|
||||
Log.d(MyTracksConstants.TAG, "Title: " + entry.getTitle());
|
||||
Entry map = client.createEntry(mapFeed, auth.getAuthToken(), entry);
|
||||
mapId = MapsClient.getMapIdFromMapEntryId(map.getId());
|
||||
Log.d(MyTracksConstants.TAG, "New map id is: " + mapId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean uploadAllTrackPoints(
|
||||
final Track track, String originalDescription) {
|
||||
SharedPreferences preferences = context.getSharedPreferences(
|
||||
MyTracksSettings.SETTINGS_NAME, 0);
|
||||
boolean metricUnits = true;
|
||||
if (preferences != null) {
|
||||
metricUnits =
|
||||
preferences.getBoolean(context.getString(R.string.metric_units_key),
|
||||
true);
|
||||
}
|
||||
|
||||
Cursor locationsCursor =
|
||||
providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
|
||||
try {
|
||||
if (!locationsCursor.moveToFirst()) {
|
||||
Log.w(MyTracksConstants.TAG, "Unable to get any points to upload");
|
||||
return false;
|
||||
}
|
||||
|
||||
totalLocationsRead = 0;
|
||||
totalLocationsPrepared = 0;
|
||||
totalLocationsUploaded = 0;
|
||||
totalLocations = locationsCursor.getCount();
|
||||
totalSegmentsUploaded = 0;
|
||||
|
||||
// Limit the number of elevation readings. Ideally we would want around 250.
|
||||
int elevationSamplingFrequency =
|
||||
Math.max(1, (int) (totalLocations / 250.0));
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"Using elevation sampling factor: " + elevationSamplingFrequency
|
||||
+ " on " + totalLocations);
|
||||
double totalDistance = 0;
|
||||
|
||||
Vector<Double> distances = new Vector<Double>();
|
||||
Vector<Double> elevations = new Vector<Double>();
|
||||
DoubleBuffer elevationBuffer =
|
||||
new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
|
||||
|
||||
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_reading_track);
|
||||
Location lastLocation = null;
|
||||
do {
|
||||
if (totalLocationsRead % 100 == 0) {
|
||||
updateProgress();
|
||||
}
|
||||
|
||||
Location loc = providerUtils.createLocation(locationsCursor);
|
||||
locations.add(loc);
|
||||
|
||||
if (totalLocationsRead == 0) {
|
||||
// Put a marker at the first point of the first valid segment:
|
||||
uploadMarker(track, loc, true);
|
||||
}
|
||||
|
||||
// Add to the elevation profile.
|
||||
if (loc != null && MyTracksUtils.isValidLocation(loc)) {
|
||||
// All points go into the smoothing buffer...
|
||||
elevationBuffer.setNext(metricUnits ? loc.getAltitude()
|
||||
: loc.getAltitude() * UnitConversions.M_TO_FT);
|
||||
if (lastLocation != null) {
|
||||
double dist = lastLocation.distanceTo(loc);
|
||||
totalDistance += dist;
|
||||
}
|
||||
|
||||
// ...but only a few points are really used to keep the url short.
|
||||
if (totalLocationsRead % elevationSamplingFrequency == 0) {
|
||||
distances.add(totalDistance);
|
||||
elevations.add(elevationBuffer.getAverage());
|
||||
}
|
||||
}
|
||||
|
||||
// If the location was not valid, it's a segment split, so make sure the
|
||||
// distance between the previous segment and the new one is not accounted
|
||||
// for in the next iteration.
|
||||
lastLocation = loc;
|
||||
|
||||
// Every now and then, upload the accumulated points
|
||||
if (totalLocationsRead % MAX_POINTS_PER_UPLOAD
|
||||
== MAX_POINTS_PER_UPLOAD - 1) {
|
||||
if (!prepareAndUploadPoints(track, locations)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
totalLocationsRead++;
|
||||
} while (locationsCursor.moveToNext());
|
||||
|
||||
// Do a final upload with what's left
|
||||
if (!prepareAndUploadPoints(track, locations)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Put an end marker at the last point of the last valid segment:
|
||||
if (lastLocation != null) {
|
||||
track.setDescription("<p>" + originalDescription + "</p><p>"
|
||||
+ stringUtils.generateTrackDescription(
|
||||
track, distances, elevations)
|
||||
+ "</p>");
|
||||
return uploadMarker(track, lastLocation, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
locationsCursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean uploadMarker(final Track track,
|
||||
final Location location,
|
||||
final boolean isStart) {
|
||||
boolean okay = wrapper.runQuery(new QueryFunction() {
|
||||
@Override
|
||||
public void query(MapsClient client)
|
||||
throws AuthenticationException, IOException, Exception {
|
||||
String featureFeed = MapsClient.getFeaturesFeed(mapId);
|
||||
insertMarker(context, client, featureFeed, track, location, isStart);
|
||||
}
|
||||
});
|
||||
return okay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a place mark. Second try if 1st try fails. Will throw exception on
|
||||
* 2nd failure.
|
||||
*/
|
||||
private void insertMarker(Context context, MapsClient client,
|
||||
String featureFeed, Track track, Location loc,
|
||||
boolean isStart) throws IOException, Exception {
|
||||
Entry entry = gdataConverter.getEntryForFeature(
|
||||
buildMyMapsPlacemarkFeature(context, track, loc, isStart));
|
||||
Log.d(MyTracksConstants.TAG, "SendToMyMaps: Creating placemark "
|
||||
+ entry.getTitle());
|
||||
try {
|
||||
client.createEntry(featureFeed, auth.getAuthToken(), entry);
|
||||
Log.d(MyTracksConstants.TAG, "SendToMyMaps: createEntry success!");
|
||||
} catch (IOException e) {
|
||||
Log.w(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: createEntry 1st try failed. Trying again.");
|
||||
// Retry once (often IOException is thrown on a timeout):
|
||||
client.createEntry(featureFeed, auth.getAuthToken(), entry);
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: createEntry success on 2nd try!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a placemark MyMapsFeature from a track.
|
||||
*
|
||||
* @param track the track
|
||||
* @param isStart true if it's the start of the track, or false for end
|
||||
* @return a MyMapsFeature
|
||||
*/
|
||||
private static MyMapsFeature buildMyMapsPlacemarkFeature(Context context,
|
||||
Track track, Location loc, boolean isStart) {
|
||||
MyMapsFeature myMapsFeature = new MyMapsFeature();
|
||||
myMapsFeature.generateAndroidId();
|
||||
myMapsFeature.setType(MyMapsFeature.MARKER);
|
||||
if (isStart) {
|
||||
myMapsFeature.setIconUrl(START_ICON_URL);
|
||||
} else {
|
||||
myMapsFeature.setIconUrl(END_ICON_URL);
|
||||
}
|
||||
myMapsFeature.addPoint(MyTracksUtils.getGeoPoint(loc));
|
||||
String name = track.getName() + " "
|
||||
+ (isStart ? context.getString(R.string.start)
|
||||
: context.getString(R.string.end));
|
||||
myMapsFeature.setTitle(name);
|
||||
myMapsFeature.setDescription(isStart ? "" : track.getDescription());
|
||||
return myMapsFeature;
|
||||
}
|
||||
|
||||
private boolean prepareAndUploadPoints(Track track, List<Location> locations) {
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_preparing_track);
|
||||
updateProgress();
|
||||
|
||||
int numLocations = locations.size();
|
||||
if (numLocations < 2) {
|
||||
Log.d(MyTracksConstants.TAG, "Not preparing/uploading too few points");
|
||||
totalLocationsUploaded += numLocations;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Prepare/pre-process the points
|
||||
ArrayList<Track> splitTracks = prepareLocations(track, locations);
|
||||
|
||||
// Start uploading them
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_sending_mymaps);
|
||||
for (Track splitTrack : splitTracks) {
|
||||
if (totalSegmentsUploaded > 1) {
|
||||
splitTrack.setName(splitTrack.getName() + " "
|
||||
+ String.format(
|
||||
context.getString(R.string.part), totalSegmentsUploaded));
|
||||
}
|
||||
totalSegmentsUploaded++;
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: Prepared feature for upload w/ "
|
||||
+ splitTrack.getLocations().size() + " points.");
|
||||
|
||||
// Transmit tracks via GData feed:
|
||||
// -------------------------------
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: Uploading to map " + mapId + " w/ auth " + auth);
|
||||
if (!uploadTrackPoints(splitTrack)) {
|
||||
Log.e(MyTracksConstants.TAG, "Uploading failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
locations.clear();
|
||||
totalLocationsUploaded += numLocations;
|
||||
updateProgress();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a buffer of locations for transmission to google maps.
|
||||
*
|
||||
* @param track the original track with meta data
|
||||
* @param buffer a buffer of locations on the track
|
||||
* @return an array of tracks each with a sub section of the points in the
|
||||
* original buffer
|
||||
*/
|
||||
private ArrayList<Track> prepareLocations(
|
||||
Track track, Iterable<Location> locations) {
|
||||
ArrayList<Track> splitTracks = new ArrayList<Track>();
|
||||
|
||||
// Create segments from each full track:
|
||||
Track segment = new Track();
|
||||
TripStatistics segmentStats = segment.getStatistics();
|
||||
TripStatistics trackStats = track.getStatistics();
|
||||
segment.setId(track.getId());
|
||||
segment.setName(track.getName());
|
||||
segment.setDescription(/* track.getDescription() */ "");
|
||||
segment.setCategory(track.getCategory());
|
||||
segmentStats.setStartTime(trackStats.getStartTime());
|
||||
segmentStats.setStopTime(trackStats.getStopTime());
|
||||
boolean startNewTrackSegment = false;
|
||||
for (Location loc : locations) {
|
||||
if (totalLocationsPrepared % 100 == 0) {
|
||||
updateProgress();
|
||||
}
|
||||
if (loc.getLatitude() > 90) {
|
||||
startNewTrackSegment = true;
|
||||
}
|
||||
|
||||
if (startNewTrackSegment) {
|
||||
// Close up the last segment.
|
||||
prepareTrackSegment(segment, splitTracks);
|
||||
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"MyTracksSendToMyMaps: Starting new track segment...");
|
||||
startNewTrackSegment = false;
|
||||
segment = new Track();
|
||||
segment.setId(track.getId());
|
||||
segment.setName(track.getName());
|
||||
segment.setDescription(/* track.getDescription() */ "");
|
||||
segment.setCategory(track.getCategory());
|
||||
}
|
||||
|
||||
if (loc.getLatitude() <= 90) {
|
||||
segment.addLocation(loc);
|
||||
if (segmentStats.getStartTime() < 0) {
|
||||
segmentStats.setStartTime(loc.getTime());
|
||||
}
|
||||
}
|
||||
totalLocationsPrepared++;
|
||||
}
|
||||
|
||||
prepareTrackSegment(segment, splitTracks);
|
||||
|
||||
return splitTracks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a track segment for sending to google maps.
|
||||
* The main steps are:
|
||||
* - correcting end time
|
||||
* - decimating locations
|
||||
* - splitting into smaller tracks.
|
||||
*
|
||||
* The final track pieces will be put in the array list splitTracks.
|
||||
*
|
||||
* @param segment the original segment of the track
|
||||
* @param splitTracks an array of smaller track segments
|
||||
*/
|
||||
private void prepareTrackSegment(
|
||||
Track segment, ArrayList<Track> splitTracks) {
|
||||
TripStatistics segmentStats = segment.getStatistics();
|
||||
if (segmentStats.getStopTime() < 0
|
||||
&& segment.getLocations().size() > 0) {
|
||||
segmentStats.setStopTime(segment.getLocations().size() - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decimate to 2 meter precision. Mapshop doesn't like too many
|
||||
* points:
|
||||
*/
|
||||
MyTracksUtils.decimate(segment, 2.0);
|
||||
|
||||
/* It the track still has > 500 points, split it in pieces: */
|
||||
if (segment.getLocations().size() > 500) {
|
||||
splitTracks.addAll(MyTracksUtils.split(segment, 500));
|
||||
} else if (segment.getLocations().size() >= 2) {
|
||||
splitTracks.add(segment);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads a given list of tracks to Google MyMaps using the maps GData feed.
|
||||
*/
|
||||
private boolean uploadTrackPoints(final Track track) {
|
||||
return wrapper.runQuery(new QueryFunction() {
|
||||
@Override
|
||||
public void query(MapsClient client)
|
||||
throws AuthenticationException, IOException, Exception {
|
||||
String featureFeed = MapsClient.getFeaturesFeed(mapId);
|
||||
Log.d(MyTracksConstants.TAG, "Feature feed url: " + featureFeed);
|
||||
uploadTrackPoints(track, client, featureFeed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean uploadTrackPoints(Track splitTrack,
|
||||
MapsClient client,
|
||||
String featureFeed)
|
||||
throws IOException, Exception {
|
||||
Entry entry = null;
|
||||
int numLocations = splitTrack.getLocations().size();
|
||||
if (numLocations < 2) {
|
||||
// Need at least two points for a polyline:
|
||||
Log.w(MyTracksConstants.TAG, "Not uploading too few points");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Put the line:
|
||||
entry = gdataConverter.getEntryForFeature(
|
||||
buildMyMapsLineFeature(splitTrack));
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: Creating line " + entry.getTitle());
|
||||
try {
|
||||
client.createEntry(featureFeed, auth.getAuthToken(), entry);
|
||||
Log.d(MyTracksConstants.TAG, "SendToMyMaps: createEntry success!");
|
||||
} catch (IOException e) {
|
||||
Log.w(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: createEntry 1st try failed. Trying again.");
|
||||
// Retry once (often IOException is thrown on a timeout):
|
||||
client.createEntry(featureFeed, auth.getAuthToken(), entry);
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: createEntry success on 2nd try!");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a MyMapsFeature from a track.
|
||||
*
|
||||
* @param track the track
|
||||
* @return a MyMapsFeature
|
||||
*/
|
||||
private static MyMapsFeature buildMyMapsLineFeature(Track track) {
|
||||
MyMapsFeature myMapsFeature = new MyMapsFeature();
|
||||
myMapsFeature.generateAndroidId();
|
||||
myMapsFeature.setType(MyMapsFeature.LINE);
|
||||
if (track.getName().length() < 1) {
|
||||
// Features must have a name (otherwise GData upload may fail):
|
||||
myMapsFeature.setTitle("-");
|
||||
} else {
|
||||
myMapsFeature.setTitle(track.getName());
|
||||
}
|
||||
myMapsFeature.setColor(0x80FF0000);
|
||||
for (Location loc : track.getLocations()) {
|
||||
myMapsFeature.addPoint(MyTracksUtils.getGeoPoint(loc));
|
||||
}
|
||||
return myMapsFeature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads all of the waypoints associated with this track to map.
|
||||
*
|
||||
* @param track The track to upload waypoints for.
|
||||
*
|
||||
* @return True on success.
|
||||
*/
|
||||
private boolean uploadWaypoints(final Track track) {
|
||||
return wrapper.runQuery(new QueryFunction() {
|
||||
public void query(MapsClient client) {
|
||||
// TODO: Stream through he waypoints in chunks.
|
||||
// I am leaving the number of waypoints very high which should not be a
|
||||
// problem because we don't try to load them into objects all at the
|
||||
// same time.
|
||||
Cursor c = null;
|
||||
c = providerUtils.getWaypointsCursor(
|
||||
track.getId(), 0,
|
||||
MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS);
|
||||
String featureFeed = MapsClient.getFeaturesFeed(mapId);
|
||||
if (c != null) {
|
||||
try {
|
||||
if (c.moveToFirst()) {
|
||||
// This will skip the 1st waypoint (it carries the stats for the
|
||||
// last segment).
|
||||
while (c.moveToNext()) {
|
||||
Waypoint wpt = providerUtils.createWaypoint(c);
|
||||
Entry entry = gdataConverter.getEntryForFeature(
|
||||
buildMyMapsPlacemarkFeature(wpt));
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: Creating waypoint.");
|
||||
try {
|
||||
client.createEntry(featureFeed, auth.getAuthToken(), entry);
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: createEntry success!");
|
||||
} catch (IOException e) {
|
||||
Log.w(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: createEntry 1st try failed. Retrying.");
|
||||
|
||||
// Retry once (often IOException is thrown on a timeout):
|
||||
client.createEntry(featureFeed, auth.getAuthToken(), entry);
|
||||
Log.d(MyTracksConstants.TAG,
|
||||
"SendToMyMaps: createEntry success on 2nd try!");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
Log.w(MyTracksConstants.TAG, "ParseException caught.", e);
|
||||
} catch (HttpException e) {
|
||||
Log.w(MyTracksConstants.TAG, "HttpException caught.", e);
|
||||
} catch (IOException e) {
|
||||
Log.w(MyTracksConstants.TAG, "IOException caught.", e);
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a MyMapsFeature from a track.
|
||||
*
|
||||
* @param wpt the waypoint
|
||||
* @return a MyMapsFeature
|
||||
*/
|
||||
private static MyMapsFeature buildMyMapsPlacemarkFeature(Waypoint wpt) {
|
||||
MyMapsFeature myMapsFeature = new MyMapsFeature();
|
||||
myMapsFeature.generateAndroidId();
|
||||
myMapsFeature.setType(MyMapsFeature.MARKER);
|
||||
myMapsFeature.setIconUrl(wpt.getIcon());
|
||||
myMapsFeature.setDescription(wpt.getDescription());
|
||||
myMapsFeature.addPoint(MyTracksUtils.getGeoPoint(wpt.getLocation()));
|
||||
if (wpt.getName().length() < 1) {
|
||||
// Features must have a name (otherwise GData upload may fail):
|
||||
myMapsFeature.setTitle("-");
|
||||
} else {
|
||||
myMapsFeature.setTitle(wpt.getName());
|
||||
}
|
||||
myMapsFeature.setDescription(wpt.getDescription().replaceAll("\n", "<br>"));
|
||||
return myMapsFeature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current upload progress.
|
||||
*/
|
||||
private void updateProgress() {
|
||||
// The percent of the total that represents the completed part of this
|
||||
// segment.
|
||||
int totalPercentage =
|
||||
(totalLocationsRead + totalLocationsPrepared + totalLocationsUploaded)
|
||||
/ (totalLocations * 3);
|
||||
totalPercentage = Math.min(99, totalPercentage);
|
||||
progressIndicator.setProgressValue(totalPercentage);
|
||||
}
|
||||
}
|
||||
@@ -37,13 +37,15 @@ public class BackupColumns {
|
||||
TracksColumns.MOVINGTIME, TracksColumns.AVGSPEED, TracksColumns.AVGMOVINGSPEED,
|
||||
TracksColumns.MAXSPEED, TracksColumns.MINELEVATION, TracksColumns.MAXELEVATION,
|
||||
TracksColumns.ELEVATIONGAIN, TracksColumns.MINGRADE, TracksColumns.MAXGRADE,
|
||||
TracksColumns.MINLAT, TracksColumns.MAXLAT, TracksColumns.MINLON, TracksColumns.MAXLON };
|
||||
TracksColumns.MINLAT, TracksColumns.MAXLAT, TracksColumns.MINLON, TracksColumns.MAXLON,
|
||||
TracksColumns.MAPID, TracksColumns.TABLEID};
|
||||
public static final byte[] TRACKS_BACKUP_COLUMN_TYPES = {
|
||||
LONG_TYPE_ID, STRING_TYPE_ID, STRING_TYPE_ID, STRING_TYPE_ID,
|
||||
LONG_TYPE_ID, LONG_TYPE_ID, LONG_TYPE_ID, LONG_TYPE_ID, INT_TYPE_ID,
|
||||
FLOAT_TYPE_ID, LONG_TYPE_ID, LONG_TYPE_ID, FLOAT_TYPE_ID, FLOAT_TYPE_ID,
|
||||
FLOAT_TYPE_ID, FLOAT_TYPE_ID, FLOAT_TYPE_ID, FLOAT_TYPE_ID, FLOAT_TYPE_ID,
|
||||
FLOAT_TYPE_ID, INT_TYPE_ID, INT_TYPE_ID, INT_TYPE_ID, INT_TYPE_ID };
|
||||
FLOAT_TYPE_ID, INT_TYPE_ID, INT_TYPE_ID, INT_TYPE_ID, INT_TYPE_ID, STRING_TYPE_ID,
|
||||
STRING_TYPE_ID};
|
||||
|
||||
public static final String[] WAYPOINTS_BACKUP_COLUMNS = {
|
||||
WaypointsColumns._ID, WaypointsColumns.TRACKID, WaypointsColumns.NAME,
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.docs;
|
||||
|
||||
import com.google.android.apps.mymaps.MyMapsConstants;
|
||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.io.AuthManager;
|
||||
@@ -82,12 +81,13 @@ public class DocsHelper {
|
||||
* returned.
|
||||
*/
|
||||
public String createSpreadsheet(final Context context,
|
||||
final GDataWrapper docListWrapper, final String name) throws IOException {
|
||||
final GDataWrapper<GDataServiceClient> docListWrapper, final String name) throws IOException {
|
||||
final AtomicReference<String> idSaver = new AtomicReference<String>();
|
||||
|
||||
boolean result = docListWrapper.runQuery(new QueryFunction() {
|
||||
boolean result = docListWrapper.runQuery(new QueryFunction<GDataServiceClient>() {
|
||||
@Override
|
||||
public void query(GDataServiceClient client) throws IOException {
|
||||
public void query(GDataServiceClient client) throws IOException,
|
||||
GDataWrapper.AuthenticationException {
|
||||
// Construct and send request
|
||||
URL url = new URL(DOCS_FEED_URL);
|
||||
URLConnection conn = url.openConnection();
|
||||
@@ -165,34 +165,41 @@ public class DocsHelper {
|
||||
* be returned if no spreadsheet exists by the given name.
|
||||
* @throws IOException If an error occurs during the GData request.
|
||||
*/
|
||||
public String requestSpreadsheetId(final GDataWrapper docListWrapper,
|
||||
public String requestSpreadsheetId(final GDataWrapper<GDataServiceClient> docListWrapper,
|
||||
final String title) throws IOException {
|
||||
final AtomicReference<String> idSaver = new AtomicReference<String>();
|
||||
|
||||
boolean result = docListWrapper.runQuery(new QueryFunction() {
|
||||
boolean result = docListWrapper.runQuery(new QueryFunction<GDataServiceClient>() {
|
||||
@Override
|
||||
public void query(GDataServiceClient client)
|
||||
throws IOException, ParseException, HttpException {
|
||||
throws IOException, GDataWrapper.ParseException, GDataWrapper.HttpException,
|
||||
GDataWrapper.AuthenticationException {
|
||||
GDataParser listParser;
|
||||
listParser = client.getParserForFeed(Entry.class,
|
||||
DOCS_MY_SPREADSHEETS_FEED_URL,
|
||||
docListWrapper.getAuthManager().getAuthToken());
|
||||
listParser.init();
|
||||
try {
|
||||
listParser = client.getParserForFeed(Entry.class,
|
||||
DOCS_MY_SPREADSHEETS_FEED_URL,
|
||||
docListWrapper.getAuthManager().getAuthToken());
|
||||
listParser.init();
|
||||
|
||||
while (listParser.hasMoreData()) {
|
||||
Entry entry = listParser.readNextEntry(null);
|
||||
String entryTitle = entry.getTitle();
|
||||
Log.i(MyTracksConstants.TAG, "Found docs entry: " + entryTitle);
|
||||
if (entryTitle.equals(title)) {
|
||||
String entryId = entry.getId();
|
||||
int lastSlash = entryId.lastIndexOf('/');
|
||||
idSaver.set(entryId.substring(lastSlash + 15));
|
||||
break;
|
||||
while (listParser.hasMoreData()) {
|
||||
Entry entry = listParser.readNextEntry(null);
|
||||
String entryTitle = entry.getTitle();
|
||||
Log.i(MyTracksConstants.TAG, "Found docs entry: " + entryTitle);
|
||||
if (entryTitle.equals(title)) {
|
||||
String entryId = entry.getId();
|
||||
int lastSlash = entryId.lastIndexOf('/');
|
||||
idSaver.set(entryId.substring(lastSlash + 15));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
throw new GDataWrapper.ParseException(e);
|
||||
} catch (HttpException e) {
|
||||
throw new GDataWrapper.HttpException(e.getStatusCode(), e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (!result) {
|
||||
throw newIOException(docListWrapper,
|
||||
"Failed to retrieve spreadsheet list.");
|
||||
@@ -211,30 +218,36 @@ public class DocsHelper {
|
||||
* ID.
|
||||
* @throws IOException If an error occurs during the GData request.
|
||||
*/
|
||||
public String getWorksheetId(final GDataWrapper trixWrapper,
|
||||
public String getWorksheetId(final GDataWrapper<GDataServiceClient> trixWrapper,
|
||||
final String spreadsheetId) throws IOException {
|
||||
final AtomicReference<String> idSaver = new AtomicReference<String>();
|
||||
|
||||
boolean result = trixWrapper.runQuery(new QueryFunction() {
|
||||
boolean result = trixWrapper.runQuery(new QueryFunction<GDataServiceClient>() {
|
||||
@Override
|
||||
public void query(GDataServiceClient client)
|
||||
throws AuthenticationException, IOException, ParseException {
|
||||
throws GDataWrapper.AuthenticationException, IOException, GDataWrapper.ParseException, GDataWrapper.HttpException {
|
||||
String uri = String.format(DOCS_WORKSHEETS_URL_FORMAT, spreadsheetId);
|
||||
GDataParser sheetParser =
|
||||
((SpreadsheetsClient) client).getParserForWorksheetsFeed(uri,
|
||||
trixWrapper.getAuthManager().getAuthToken());
|
||||
sheetParser.init();
|
||||
if (!sheetParser.hasMoreData()) {
|
||||
Log.i(MyTracksConstants.TAG, "Found no worksheets");
|
||||
return;
|
||||
GDataParser sheetParser;
|
||||
try {
|
||||
sheetParser = ((SpreadsheetsClient) client).getParserForWorksheetsFeed(uri,
|
||||
trixWrapper.getAuthManager().getAuthToken());
|
||||
sheetParser.init();
|
||||
if (!sheetParser.hasMoreData()) {
|
||||
Log.i(MyTracksConstants.TAG, "Found no worksheets");
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab the first worksheet.
|
||||
WorksheetEntry worksheetEntry =
|
||||
(WorksheetEntry) sheetParser.readNextEntry(new WorksheetEntry());
|
||||
|
||||
int lastSlash = worksheetEntry.getId().lastIndexOf('/');
|
||||
idSaver.set(worksheetEntry.getId().substring(lastSlash + 1));
|
||||
} catch (ParseException e) {
|
||||
throw new GDataWrapper.ParseException(e);
|
||||
} catch (AuthenticationException e) {
|
||||
throw new GDataWrapper.AuthenticationException(e);
|
||||
}
|
||||
|
||||
// Grab the first worksheet.
|
||||
WorksheetEntry worksheetEntry =
|
||||
(WorksheetEntry) sheetParser.readNextEntry(new WorksheetEntry());
|
||||
|
||||
int lastSlash = worksheetEntry.getId().lastIndexOf('/');
|
||||
idSaver.set(worksheetEntry.getId().substring(lastSlash + 1));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -295,7 +308,7 @@ public class DocsHelper {
|
||||
|
||||
if (track.getMapId().length() > 0) {
|
||||
tagBuilder.append("map", String.format("%s?msa=0&msid=%s",
|
||||
MyMapsConstants.MAPSHOP_BASE_URL, track.getMapId()));
|
||||
MyTracksConstants.MAPSHOP_BASE_URL, track.getMapId()));
|
||||
}
|
||||
|
||||
String postText = new StringBuilder()
|
||||
|
||||
@@ -17,11 +17,6 @@ package com.google.android.apps.mytracks.io.gdata;
|
||||
|
||||
import com.google.android.apps.mytracks.MyTracksConstants;
|
||||
import com.google.android.apps.mytracks.io.AuthManager;
|
||||
import com.google.wireless.gdata.client.GDataServiceClient;
|
||||
import com.google.wireless.gdata.client.HttpException;
|
||||
import com.google.wireless.gdata.parser.ParseException;
|
||||
import com.google.wireless.gdata2.ConflictDetectedException;
|
||||
import com.google.wireless.gdata2.client.AuthenticationException;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
@@ -39,9 +34,60 @@ import java.util.concurrent.TimeoutException;
|
||||
* handling. After a query is run, the wrapper can be queried about the error
|
||||
* that occurred.
|
||||
*
|
||||
* @param C the GData service client
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class GDataWrapper {
|
||||
public class GDataWrapper<C> {
|
||||
|
||||
public static class AuthenticationException extends Exception {
|
||||
private Exception exception;
|
||||
private static final long serialVersionUID = 1L;
|
||||
public AuthenticationException(Exception caught) {
|
||||
this.exception = caught;
|
||||
}
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
};
|
||||
|
||||
public static class ParseException extends Exception {
|
||||
private Exception exception;
|
||||
private static final long serialVersionUID = 1L;
|
||||
public ParseException(Exception caught) {
|
||||
this.exception = caught;
|
||||
}
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
};
|
||||
|
||||
public static class ConflictDetectedException extends Exception {
|
||||
private Exception exception;
|
||||
private static final long serialVersionUID = 1L;
|
||||
public ConflictDetectedException(Exception caught) {
|
||||
this.exception = caught;
|
||||
}
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
};
|
||||
|
||||
public static class HttpException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private int statusCode;
|
||||
private String statusMessage;
|
||||
public HttpException(int statusCode, String statusMessage) {
|
||||
super();
|
||||
this.statusCode = statusCode;
|
||||
this.statusMessage = statusMessage;
|
||||
}
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
public String getStatusMessage() {
|
||||
return statusMessage;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A QueryFunction is passed in when executing a query. The query function of
|
||||
@@ -49,8 +95,8 @@ public class GDataWrapper {
|
||||
* should execute whatever operations it desires on the client without concern
|
||||
* for whether the client will throw an error.
|
||||
*/
|
||||
public interface QueryFunction {
|
||||
public abstract void query(GDataServiceClient client)
|
||||
public interface QueryFunction<C> {
|
||||
public abstract void query(C client)
|
||||
throws AuthenticationException, IOException, ParseException,
|
||||
ConflictDetectedException, HttpException;
|
||||
}
|
||||
@@ -92,7 +138,7 @@ public class GDataWrapper {
|
||||
|
||||
private String errorMessage;
|
||||
private int errorType;
|
||||
private GDataServiceClient gdataServiceClient;
|
||||
private C gdataServiceClient;
|
||||
private AuthManager auth;
|
||||
private boolean retryOnAuthFailure;
|
||||
|
||||
@@ -103,7 +149,7 @@ public class GDataWrapper {
|
||||
retryOnAuthFailure = false;
|
||||
}
|
||||
|
||||
public void setClient(GDataServiceClient gdataServiceClient) {
|
||||
public void setClient(C gdataServiceClient) {
|
||||
this.gdataServiceClient = gdataServiceClient;
|
||||
}
|
||||
|
||||
@@ -112,7 +158,7 @@ public class GDataWrapper {
|
||||
return runCommon(function, null);
|
||||
}
|
||||
|
||||
public boolean runQuery(final QueryFunction query) {
|
||||
public boolean runQuery(final QueryFunction<C> query) {
|
||||
return runCommon(null, query);
|
||||
}
|
||||
|
||||
@@ -120,7 +166,7 @@ public class GDataWrapper {
|
||||
* Runs an arbitrary piece of code.
|
||||
*/
|
||||
private boolean runCommon(final AuthenticatedFunction function,
|
||||
final QueryFunction query) {
|
||||
final QueryFunction<C> query) {
|
||||
for (int i = 0; i <= AUTH_TOKEN_INVALIDATE_REFRESH_NUM_RETRIES; i++) {
|
||||
runOne(function, query);
|
||||
if (errorType == ERROR_NO_ERROR) {
|
||||
@@ -144,7 +190,7 @@ public class GDataWrapper {
|
||||
* errorMessage will contain the result/status of the function/query.
|
||||
*/
|
||||
private void runOne(final AuthenticatedFunction function,
|
||||
final QueryFunction query) {
|
||||
final QueryFunction<C> query) {
|
||||
try {
|
||||
if (function != null) {
|
||||
function.run(this.auth.getAuthToken());
|
||||
@@ -160,7 +206,7 @@ public class GDataWrapper {
|
||||
errorMessage = null;
|
||||
|
||||
} catch (AuthenticationException e) {
|
||||
Log.e(MyTracksConstants.TAG, "Exception", e);
|
||||
Log.e(MyTracksConstants.TAG, "AuthenticationException", e);
|
||||
errorType = ERROR_AUTH;
|
||||
errorMessage = e.getMessage();
|
||||
} catch (HttpException e) {
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mymaps;
|
||||
package com.google.android.apps.mytracks.util;
|
||||
|
||||
import com.google.android.maps.GeoPoint;
|
||||
|
||||
@@ -61,4 +61,4 @@ public class GeoRect {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,11 +22,11 @@ import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.maps.GeoPoint;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.Signature;
|
||||
import android.location.Location;
|
||||
import android.os.StrictMode;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -267,12 +267,28 @@ public class MyTracksUtils {
|
||||
} catch (NameNotFoundException e) {
|
||||
Log.e(MyTracksConstants.TAG, "Unable to get signatures", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is a utility class w/ only static memebers.
|
||||
* Get the My Tracks version from the manifest.
|
||||
*
|
||||
* @return the version, or an empty string in case of failure.
|
||||
*/
|
||||
public static String getMyTracksVersion(Context context) {
|
||||
try {
|
||||
PackageInfo pi = context.getPackageManager().getPackageInfo(
|
||||
"com.google.android.maps.mytracks",
|
||||
PackageManager.GET_META_DATA);
|
||||
return pi.versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
Log.w(MyTracksConstants.TAG, "Failed to get version info.", e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a utility class w/ only static members.
|
||||
*/
|
||||
protected MyTracksUtils() {
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ public class StringUtils implements DescriptionGenerator {
|
||||
+ "<img border=\"0\" src=\"%s\"/>",
|
||||
|
||||
// Line 1
|
||||
context.getString(R.string.my_map_link),
|
||||
context.getString(R.string.fusiontable_link),
|
||||
|
||||
// Line 2
|
||||
context.getString(R.string.total_distance_label),
|
||||
|
||||
+5
@@ -101,6 +101,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
values.put(TracksColumns.NAME, track.getName());
|
||||
values.put(TracksColumns.DESCRIPTION, track.getDescription());
|
||||
values.put(TracksColumns.MAPID, track.getMapId());
|
||||
values.put(TracksColumns.TABLEID, track.getTableId());
|
||||
values.put(TracksColumns.CATEGORY, track.getCategory());
|
||||
values.put(TracksColumns.NUMPOINTS, track.getNumberOfPoints());
|
||||
values.put(TracksColumns.STARTID, track.getStartId());
|
||||
@@ -269,6 +270,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
int idxDescription =
|
||||
cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION);
|
||||
int idxMapId = cursor.getColumnIndexOrThrow(TracksColumns.MAPID);
|
||||
int idxTableId = cursor.getColumnIndexOrThrow(TracksColumns.TABLEID);
|
||||
int idxCategory = cursor.getColumnIndexOrThrow(TracksColumns.CATEGORY);
|
||||
int idxStartId = cursor.getColumnIndexOrThrow(TracksColumns.STARTID);
|
||||
int idxStartTime = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME);
|
||||
@@ -308,6 +310,9 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
if (!cursor.isNull(idxMapId)) {
|
||||
track.setMapId(cursor.getString(idxMapId));
|
||||
}
|
||||
if (!cursor.isNull(idxTableId)) {
|
||||
track.setTableId(cursor.getString(idxTableId));
|
||||
}
|
||||
if (!cursor.isNull(idxCategory)) {
|
||||
track.setCategory(cursor.getString(idxCategory));
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ public class Track implements Parcelable {
|
||||
track.locations.add(loc);
|
||||
}
|
||||
|
||||
track.tableId = source.readString();
|
||||
return track;
|
||||
}
|
||||
|
||||
@@ -81,6 +82,7 @@ public class Track implements Parcelable {
|
||||
private String name = "";
|
||||
private String description = "";
|
||||
private String mapId = "";
|
||||
private String tableId = "";
|
||||
private long startId = -1;
|
||||
private long stopId = -1;
|
||||
private String category = "";
|
||||
@@ -104,6 +106,8 @@ public class Track implements Parcelable {
|
||||
for (int i = 0; i < numberOfPoints; ++i) {
|
||||
dest.writeParcelable(locations.get(i), 0);
|
||||
}
|
||||
|
||||
dest.writeString(tableId);
|
||||
}
|
||||
|
||||
// Getters and setters:
|
||||
@@ -161,6 +165,14 @@ public class Track implements Parcelable {
|
||||
this.mapId = mapId;
|
||||
}
|
||||
|
||||
public String getTableId() {
|
||||
return tableId;
|
||||
}
|
||||
|
||||
public void setTableId(String tableId) {
|
||||
this.tableId = tableId;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
@@ -59,4 +59,5 @@ public interface TracksColumns extends BaseColumns {
|
||||
public static final String MINLON = "minlon";
|
||||
public static final String MAXLON = "maxlon";
|
||||
public static final String MAPID = "mapid";
|
||||
public static final String TABLEID = "tableid";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user