diff options
Diffstat (limited to 'main')
142 files changed, 4778 insertions, 3989 deletions
diff --git a/main/.classpath b/main/.classpath index 6435e16..f3ebe20 100644 --- a/main/.classpath +++ b/main/.classpath @@ -8,5 +8,6 @@ <classpathentry kind="lib" path="libs/mapsforge-map-0.2.4.jar"/> <classpathentry kind="lib" path="libs/commons-collections-3.2.1.jar"/> <classpathentry kind="lib" path="libs/android-support-v4.jar"/> + <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> <classpathentry kind="output" path="bin/classes"/> </classpath> diff --git a/main/libs/android-support-v4.jar b/main/libs/android-support-v4.jar Binary files differindex d006198..99e063b 100644 --- a/main/libs/android-support-v4.jar +++ b/main/libs/android-support-v4.jar diff --git a/main/proguard.cfg b/main/proguard.cfg index 74e71cf..5c21420 100644 --- a/main/proguard.cfg +++ b/main/proguard.cfg @@ -14,6 +14,7 @@ -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep public class cgeo.geocaching.* +-keep class android.support.v4.os.** { *; } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); diff --git a/main/project/eclipse installation/cgeo eclipse components.p2f b/main/project/eclipse installation/cgeo eclipse components.p2f index a0ac12c..2ecc593 100644 --- a/main/project/eclipse installation/cgeo eclipse components.p2f +++ b/main/project/eclipse installation/cgeo eclipse components.p2f @@ -1,25 +1,25 @@ <?xml version='1.0' encoding='UTF-8'?>
<?p2f version='1.0.0'?>
<p2f version='1.0.0'>
- <ius size='16'>
- <iu id='com.android.ide.eclipse.ddms.feature.group' name='Android DDMS' version='12.0.0.v201106281929-138431'>
+ <ius size='20'>
+ <iu id='com.android.ide.eclipse.ddms.feature.group' name='Android DDMS' version='17.0.0.v201203161636-291853'>
<repositories size='1'>
- <repository location='https://dl-ssl.google.com/android/eclipse/'/>
+ <repository location='https://dl-ssl.google.com/android/eclipse'/>
</repositories>
</iu>
- <iu id='com.android.ide.eclipse.adt.feature.group' name='Android Development Tools' version='12.0.0.v201106281929-138431'>
+ <iu id='com.android.ide.eclipse.adt.feature.group' name='Android Development Tools' version='17.0.0.v201203161636-291853'>
<repositories size='1'>
- <repository location='https://dl-ssl.google.com/android/eclipse/'/>
+ <repository location='https://dl-ssl.google.com/android/eclipse'/>
</repositories>
</iu>
- <iu id='com.android.ide.eclipse.hierarchyviewer.feature.group' name='Android Hierarchy Viewer' version='12.0.0.v201106281929-138431'>
+ <iu id='com.android.ide.eclipse.hierarchyviewer.feature.group' name='Android Hierarchy Viewer' version='17.0.0.v201203161636-291853'>
<repositories size='1'>
- <repository location='https://dl-ssl.google.com/android/eclipse/'/>
+ <repository location='https://dl-ssl.google.com/android/eclipse'/>
</repositories>
</iu>
- <iu id='com.android.ide.eclipse.traceview.feature.group' name='Android Traceview' version='12.0.0.v201106281929-138431'>
+ <iu id='com.android.ide.eclipse.traceview.feature.group' name='Android Traceview' version='17.0.0.v201203161636-291853'>
<repositories size='1'>
- <repository location='https://dl-ssl.google.com/android/eclipse/'/>
+ <repository location='https://dl-ssl.google.com/android/eclipse'/>
</repositories>
</iu>
<iu id='com.instantiations.assist.eclipse.audit.feature.group' name='CodePro - Audit' version='7.1.0.r37x201109091206'>
@@ -32,56 +32,91 @@ <repository location='http://dl.google.com/eclipse/inst/codepro/latest/3.7'/>
</repositories>
</iu>
- <iu id='org.eclipse.egit.feature.group' name='Eclipse EGit' version='1.1.0.201109151100-r'>
- <repositories size='1'>
+ <iu id='org.eclipse.egit.feature.group' name='Eclipse EGit' version='1.3.0.201202151440-r'>
+ <repositories size='3'>
<repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
+ <repository location='http://download.eclipse.org/egit/updates'/>
</repositories>
</iu>
- <iu id='org.eclipse.mylyn.github.feature.feature.group' name='Eclipse EGit Mylyn GitHub Feature' version='1.1.0.201109151100-r'>
- <repositories size='1'>
+ <iu id='org.eclipse.mylyn.github.feature.feature.group' name='Eclipse EGit Mylyn GitHub Feature' version='1.3.0.201202151440-r'>
+ <repositories size='3'>
+ <repository location='http://download.eclipse.org/egit/github/updates'/>
<repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
</repositories>
</iu>
- <iu id='org.eclipse.jdt.feature.group' name='Eclipse Java Development Tools' version='3.7.1.r371_v20110810-0800-7z8gFcoFMLfTabvKsR5Qm9rBGEBK'>
- <repositories size='2'>
- <repository location='http://download.eclipse.org/eclipse/updates/3.7'/>
+ <iu id='org.eclipse.jdt.feature.group' name='Eclipse Java Development Tools' version='3.7.2.v20120120-1414-7z8gFcuFMP7BW5XTz0jLTnz0l9B1'>
+ <repositories size='3'>
<repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://download.eclipse.org/eclipse/updates/3.7'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
</repositories>
</iu>
- <iu id='org.eclipse.platform.ide' name='Eclipse Platform' version='3.7.1.M20110909-1335'>
- <repositories size='2'>
- <repository location='http://download.eclipse.org/eclipse/updates/3.7'/>
+ <iu id='org.eclipse.platform.ide' name='Eclipse Platform' version='3.7.2.M20120208-0800'>
+ <repositories size='3'>
<repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://download.eclipse.org/eclipse/updates/3.7'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
</repositories>
</iu>
- <iu id='org.eclipse.egit.mylyn.feature.group' name='EGit Mylyn' version='1.1.0.201109151100-r'>
+ <iu id='EclipseRegExFeature.feature.group' name='Eclipse_RegEx_Feature' version='1.3.1'>
<repositories size='1'>
+ <repository location='http://brosinski.com/regex/update'/>
+ </repositories>
+ </iu>
+ <iu id='org.eclipse.egit.mylyn.feature.group' name='EGit Mylyn' version='1.3.0.201202151440-r'>
+ <repositories size='3'>
<repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
+ <repository location='http://download.eclipse.org/egit/updates'/>
</repositories>
</iu>
- <iu id='org.eclipse.mylyn.ide_feature.feature.group' name='Mylyn Context Connector: Eclipse IDE' version='3.6.2.v20110908-0706'>
+ <iu id='edu.umd.cs.findbugs.plugin.eclipse.feature.group' name='FindBugs Feature' version='2.0.0.20111221'>
<repositories size='1'>
+ <repository location='http://findbugs.cs.umd.edu/eclipse'/>
+ </repositories>
+ </iu>
+ <iu id='org.eclipse.wst.jsdt.feature.feature.group' name='JavaScript Development Tools' version='1.3.2.v201201112313-7G78FZvFC7sRekSz-g-nAlz'>
+ <repositories size='2'>
<repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
</repositories>
</iu>
- <iu id='org.eclipse.mylyn.java_feature.feature.group' name='Mylyn Context Connector: Java Development' version='3.6.2.v20110908-0706'>
- <repositories size='1'>
+ <iu id='org.eclipse.epp.mpc.feature.group' name='Marketplace Client' version='1.1.1.I20110907-0947'>
+ <repositories size='2'>
<repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
</repositories>
</iu>
- <iu id='org.eclipse.mylyn.team_feature.feature.group' name='Mylyn Context Connector: Team Support' version='3.6.2.v20110908-0706'>
- <repositories size='1'>
+ <iu id='org.eclipse.mylyn.ide_feature.feature.group' name='Mylyn Context Connector: Eclipse IDE' version='3.6.5.v20120215-0100'>
+ <repositories size='2'>
<repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
</repositories>
</iu>
- <iu id='org.eclipse.mylyn_feature.feature.group' name='Mylyn Task List' version='3.6.2.v20110908-0706'>
- <repositories size='1'>
+ <iu id='org.eclipse.mylyn.java_feature.feature.group' name='Mylyn Context Connector: Java Development' version='3.6.5.v20120215-0100'>
+ <repositories size='2'>
<repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
</repositories>
</iu>
- <iu id='org.eclipse.mylyn.context_feature.feature.group' name='Mylyn Task-Focused Interface' version='3.6.2.v20110908-0706'>
- <repositories size='1'>
+ <iu id='org.eclipse.mylyn.team_feature.feature.group' name='Mylyn Context Connector: Team Support' version='3.6.5.v20120215-0100'>
+ <repositories size='2'>
+ <repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
+ </repositories>
+ </iu>
+ <iu id='org.eclipse.mylyn_feature.feature.group' name='Mylyn Task List' version='3.6.5.v20120215-0100'>
+ <repositories size='2'>
+ <repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
+ </repositories>
+ </iu>
+ <iu id='org.eclipse.mylyn.context_feature.feature.group' name='Mylyn Task-Focused Interface' version='3.6.5.v20120215-0100'>
+ <repositories size='2'>
<repository location='http://download.eclipse.org/releases/indigo'/>
+ <repository location='http://marketplace.eclipse.org/repo/'/>
</repositories>
</iu>
</ius>
diff --git a/main/project/localization/findextratranslations.sh b/main/project/localization/findextratranslations.sh index 8e2898d..8e2898d 100644..100755 --- a/main/project/localization/findextratranslations.sh +++ b/main/project/localization/findextratranslations.sh diff --git a/main/project/localization/findmissingtranslations.sh b/main/project/localization/findmissingtranslations.sh index 4c47cbd..4c47cbd 100644..100755 --- a/main/project/localization/findmissingtranslations.sh +++ b/main/project/localization/findmissingtranslations.sh diff --git a/main/res/layout/fieldnote_export_dialog.xml b/main/res/layout/fieldnote_export_dialog.xml new file mode 100644 index 0000000..f897985 --- /dev/null +++ b/main/res/layout/fieldnote_export_dialog.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="3dip" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/export_fieldnotes_info" />
+
+ <CheckBox
+ android:id="@+id/upload"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:text="@string/export_fieldnotes_upload" />
+
+ <CheckBox
+ android:id="@+id/onlynew"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:text="@string/export_fieldnotes_onlynew" />
+
+ <Button
+ android:id="@+id/export"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="3dip"
+ android:text="@string/export" />
+
+</LinearLayout>
\ No newline at end of file diff --git a/main/res/values-de/strings.xml b/main/res/values-de/strings.xml index fcd962c..3a1b26f 100644 --- a/main/res/values-de/strings.xml +++ b/main/res/values-de/strings.xml @@ -10,7 +10,7 @@ <string name="settings">Einstellungen</string> <string name="helpers">Nรผtzliche Apps</string> <string name="about">รber c:geo</string> - <string name="helper">Du willst mehr รผber <b>c:geo</b> erfahren?\nSchaue in die Bedienungsanleitung.</string> + <string name="helper">Um mehr รผber <b>c:geo</b> zu erfahren\neinfach die Bedienungsanleitung รถffnen.</string> <string name="latitude">Breitengrad</string> <string name="longitude">Lรคngengrad</string> @@ -127,12 +127,12 @@ <string name="err_server">Verbindung zu Geocaching.com konnte nicht hergestellt werden (Server oder Verbindung inaktiv?)</string> <string name="err_login">Keine Anmeldedaten gespeichert.</string> <string name="err_login_failed">Login fehlgeschlagen.</string> - <string name="err_login_failed_toast">c:geo konnte sich nicht einloggen und arbeitet im Offline-Modus. รberprรผfe deine Login-Daten in den Einstellungen oder stelle eine Internetverbindung her.</string> + <string name="err_login_failed_toast">c:geo konnte sich nicht einloggen und arbeitet im Offline-Modus. Bitte die Login-Daten in den Einstellungen รผberprรผfen oder eine Internetverbindung herstellen.</string> <string name="err_unknown">Unbekannter Fehler</string> <string name="err_comm">Unbekannter Kommunikationsfehler</string> <string name="err_missing_auth">Benutzername oder Passwort nicht gesetzt.</string> <string name="err_wrong">Falsche Anmeldedaten</string> - <string name="err_maintenance">Geocaching.com wird zur Zeit gewartet, bitte versuche es spรคter erneut. c:geo arbeitet im Offline-Modus.</string> + <string name="err_maintenance">Geocaching.com wird zur Zeit gewartet, bitte spรคter erneut versuchen. c:geo arbeitet im Offline-Modus.</string> <string name="err_license">Die Geocaching.com Nutzungsbedingungen wurden nicht akzeptiert. c:geo kann deshalb keine Koordinaten laden.</string> <string name="err_unpublished">Der aufgerufene Cache ist noch nicht verรถffentlicht</string> <string name="err_premium_only">Der Cache ist nur fรผr Premium Mitglieder von Geocaching.com verfรผgbar</string> @@ -145,13 +145,13 @@ <string name="err_detail_cache_find_any">c:geo konnte keine Caches finden.</string> <string name="err_detail_cache_find_next">c:geo konnte die nรคchsten Caches nicht finden.</string> <string name="err_detail_cache_forgot">c:geo hat vergessen, welcher Cache aufgerufen werden sollte.</string> - <string name="err_detail_cache_forgot_visit">c:geo hat vergessen, welchen Cache du besucht hast.</string> + <string name="err_detail_cache_forgot_visit">c:geo hat vergessen, welcher Cache besucht werden sollte.</string> <string name="err_detail_no_spoiler">c:geo hat kein Hinweisbild fรผr diesen Cache gefunden.</string> <string name="err_detail_no_map_static">c:geo hat keine statische Karte fรผr diesen Cache gefunden.</string> <string name="err_detail_not_load_map_static">c:geo konnte die statische Karte nicht laden.</string> <string name="err_detail_ask_store_map_static">c:geo konnte die statische Karte nicht laden. Jetzt speichern?</string> <string name="err_detail_still_working">Arbeite noch an anderer Aufgabe.</string> - <string name="err_watchlist_still_managing">c:geo versucht noch immer deine Watchlist zu aktualisieren.</string> + <string name="err_watchlist_still_managing">c:geo versucht noch immer die Watchlist zu aktualisieren.</string> <string name="err_watchlist_failed">รndern der Watchlist nicht erfolgreich.</string> <string name="err_navigation_no">c:geo konnte keine unterstรผtzte Art der Navigation finden.</string> <string name="err_application_no">c:geo konnte keine passende Anwendung finden.</string> @@ -166,23 +166,23 @@ <string name="err_dwld_details_failed">Download der Cache-Details fehlgeschlagen.</string> <string name="err_load_descr_failed">Laden der Cachebeschreibung fehlgeschlagen.</string> <string name="err_location_unknown">c:geo erkennt die Position des Caches nicht.</string> - <string name="err_missing_device_name">Bitte lege einen Namen fรผr dein Handy fest, bevor du dich registrierst.</string> + <string name="err_missing_device_name">Vor der Registrierung muss ein Name fรผr das Endgerรคt festlegt werden.</string> <string name="err_tb_display">"c:geo kann den gewรผnschten Trackable nicht anzeigen. Ist es wirklich einer?</string> <string name="err_tb_details_open">c:geo konnte die Details des Trackables nicht รถffnen.</string> <string name="err_tb_details_download">c:geo konnte die Details des Trackables nicht laden, weil</string> - <string name="err_tb_forgot">c:geo hat den gewรผnschten Trackable vergessen.</string> - <string name="err_tb_forgot_saw">c:geo hat vergessen, welchen Trackable du gesehen hast.</string> + <string name="err_tb_forgot">c:geo hat vergessen, welcher Trackable geรถffnet werden sollte.</string> + <string name="err_tb_forgot_saw">c:geo hat vergessen, welcher Trackable gesehen wurde.</string> <string name="err_tb_find">c:geo findet den Trackable nicht</string> <string name="err_tb_find_that">c:geo konnte diesen Trackable nicht finden.</string> <string name="err_waypoint_cache_unknown">c:geo weiร nicht, zu welchem Cache der Wegpunkt hinzugefรผgt werden soll.</string> - <string name="err_waypoint_unknown">c:geo hat vergessen, welchen Wegpunkt du ansehen wolltest.</string> + <string name="err_waypoint_unknown">c:geo hat vergessen, welcher Wegpunkt angesehen werden sollte.</string> <string name="err_waypoint_add_failed">c:geo konnte den Wegpunkt nicht hinzufรผgen.</string> <string name="err_waypoint_load_failed">c:geo konnte den Wegpunkt nicht laden.</string> <string name="err_waypoint_delete_failed">c:geo konnte den Wegpunkt nicht lรถschen.</string> <string name="err_waypoint_open_cache_failed">c:geo konnte die Cachedetails nicht laden.</string> - <string name="err_point_unknown_position">c:geo konnte deinen Standort nicht bestimmen.</string> + <string name="err_point_unknown_position">c:geo konnte den aktuellen Standort nicht bestimmen.</string> <string name="err_point_no_position_given_title">Info benรถtigt</string> <string name="err_point_no_position_given">Mindestens Lรคngen- und Breitengrad oder Entfernung und Richtung angeben. Auch alle Angaben sind mรถglich.</string> <string name="err_point_curr_position_unavailable">c:geo hat noch keine aktuelle Koordinaten. Bitte einen Moment wartenโฆ</string> @@ -197,7 +197,7 @@ <string name="err_log_post_failed">c:geo konnte Log nicht absenden.</string> <string name="err_search_address_no_match">Keinen passenden Ort gefunden.</string> - <string name="err_search_address_forgot">c:geo hat die Adresse vergessen, die du suchst.</string> + <string name="err_search_address_forgot">c:geo hat die Adresse vergessen, die gesucht wurde.</string> <string name="err_parse_lat">c:geo konnte den Breitengrad nicht verarbeiten.</string> <string name="err_parse_lon">c:geo konnte den Lรคngengrad nicht verarbeiten.</string> <string name="err_parse_dist">c:geo konnte die Entfernung nicht verarbeiten.</string> @@ -218,7 +218,7 @@ <string name="warn_search_help_tb">Code des Trackables eingeben, z.B. \"TB29QMZ\".</string> <string name="warn_log_text_fill">Bitte Text einfรผgen.</string> <string name="warn_load_images">c:geo konnte die Bilder nicht laden.</string> - + <string name="warn_invalid_mapfile">Die gewรคhlte Datei ist keine gรผltige Mapsforge-Karte in der Version 0.2.4.\nOffline Karte ist nicht verfรผgbar.</string> <string name="info_log_posted">Log erfolgreich gesendet.</string> <string name="info_log_saved">Log erfolgreich gespeichert.</string> @@ -288,9 +288,9 @@ <string name="caches_nearby">In der Nรคhe</string> <string name="caches_manage">Verwalten</string> <string name="caches_drop_selected">Ausgewรคhlte lรถschen</string> - <string name="caches_drop_selected_ask">Bist du sicher, dass die ausgewรคhlten Caches vom Gerรคt gelรถscht werden sollen?</string> + <string name="caches_drop_selected_ask">Sollen die ausgewรคhlten Caches wirklich vom Gerรคt gelรถscht werden?</string> <string name="caches_drop_all">Alle lรถschen</string> - <string name="caches_drop_all_ask">Bist du sicher, dass alle Caches von dieser Liste gelรถscht werden sollen?</string> + <string name="caches_drop_all_ask">Sollen wirklich alle Caches von dieser Liste gelรถscht werden?</string> <string name="caches_drop_stored">Gespeicherte lรถschen</string> <string name="caches_drop_progress">Entferne Cachesโฆ</string> <string name="caches_drop_all_and_list">Alle und Liste lรถschen</string> @@ -300,7 +300,7 @@ <string name="caches_move_all">Alle verschieben</string> <string name="caches_map_locus">Locus</string> <string name="caches_recaptcha_title">reCAPTCHA</string> - <string name="caches_recaptcha_explanation">Bitte Text vom Bild abschreiben. Wichtig, um Koordinaten des Caches laden zu kรถnnen. Optional, kann in den Einstellungen deaktiviert werden.</string> + <string name="caches_recaptcha_explanation">Bitte Text vom Bild abschreiben. Wichtig, um Koordinaten des Caches laden zu kรถnnen. Dies ist optional und kann in den Einstellungen deaktiviert werden.</string> <string name="caches_recaptcha_hint">Text vom Bild</string> <string name="caches_recaptcha_continue">Fortfahren</string> <string name="caches_filter">Filter</string> @@ -310,7 +310,7 @@ <string name="caches_filter_track">Mit Trackables</string> <string name="caches_filter_clear">Filter zurรผcksetzen</string> <string name="caches_filter_size_title">Grรถรe wรคhlen</string> - <string name="caches_filter_type_title">Wรคhle den Typ</string> + <string name="caches_filter_type_title">Typ wรคhlen</string> <string name="caches_filter_modified">Mit geรคnderten Koordinaten</string> <string name="caches_exporting_fieldnote">Exportiere als Field-Notesโฆ</string> <string name="caches_removing_from_history">Lรถsche aus Verlaufโฆ</string> @@ -329,7 +329,7 @@ <string name="list_dialog_create_ok">Neue Liste wurde erstellt</string> <string name="list_dialog_create_err">c:geo konnte die neue Liste nicht erstellen</string> <string name="list_dialog_remove_title">Liste entfernen</string> - <string name="list_dialog_remove_description">Aktuelle Liste lรถschen? Alle Caches dieser Liste werden in die Standardliste verschoben.</string> + <string name="list_dialog_remove_description">Soll die aktuelle Liste gelรถscht werden? Alle Caches dieser Liste werden in die Standardliste verschoben.</string> <string name="list_dialog_remove">Entfernen</string> <string name="list_dialog_remove_ok">Liste wurde gelรถscht</string> <string name="list_dialog_remove_err">c:geo konnte die Liste nicht lรถschen</string> @@ -363,7 +363,7 @@ <string name="init_signature">Signatur</string> <string name="init_signature_help_button">Hilfe</string> <string name="init_signature_help_title">Tipps und Tricks fรผr die Signatur</string> - <string name="init_signature_help_text">Verfasse eine Signatur fรผr deinen Logtext.\nErlaubte Platzhalter sind: [DATE], [TIME], [DATETIME], [USER] & [NUMBER]. Diese werden beim Einfรผgen der Signatur durch ihre Werte ersetzt.</string> + <string name="init_signature_help_text">Verwendete Signatur fรผr Logtexte.\nErlaubte Platzhalter sind: [DATE], [TIME], [DATETIME], [USER] & [NUMBER]. Diese werden beim Einfรผgen der Signatur durch die entsprechenden Werte ersetzt.</string> <string name="init_signature_template_button">Platzhalter einfรผgen</string> <string name="init_signature_template_date">Datum</string> <string name="init_signature_template_time">Zeit</string> @@ -393,7 +393,7 @@ <string name="init_log_offline">Offline loggen (Dialog fรผr Online-Log nicht anzeigen)</string> <string name="init_livelist">Richtung zum Cache in der Cache-Liste anzeigen</string> <string name="init_altitude">Hรถhenkorrektur</string> - <string name="init_altitude_description">Falls das GPS eine falsche Hรถhe ermittelt, kannst du sie durch Angabe eines positiven oder negativen Wertes in Metern korrigieren.</string> + <string name="init_altitude_description">Falls das GPS eine falsche Hรถhe ermittelt, kann dies durch Angabe eines positiven oder negativen Wertes in Metern korrigiert werden.</string> <string name="init_clear">Login zurรผcksetzen</string> <string name="init_cleared">c:geo hat die Anmeldedaten gelรถscht.</string> <string name="init_backup">Sicherung</string> @@ -407,23 +407,23 @@ <string name="init_restore_success">Wiederherstellung beendet.</string> <string name="init_restore_failed">Wiederherstellung fehlgeschlagen.</string> <string name="init_restore_running">Wiederherstellung der Cache-Datenbankโฆ</string> - <string name="init_restore_confirm">Die Cache-Datenbank ist leer. Mรถchtest du die vorhandene Sicherung wiederherstellen?</string> + <string name="init_restore_confirm">Die Cache-Datenbank ist leer. Soll die vorhandene Sicherung wiederhergestellt werden?</string> <string name="init_backup_last">Backup verfรผgbar von</string> <string name="init_backup_last_no">Keine Datei mit Datenbanksicherung gefunden.</string> <string name="init_mapsources">Kartenherkunft</string> - <string name="init_mapsources_description">Hier kannst du die Quelle fรผr deine Karte wรคhlen. Alternativ zu Google Maps stehen verschiedene OpenStreetMap-Stile zur Verfรผgung und daneben auch Karten-Dateien fรผr die Offline-Nutzung (siehe http://code.google.com/p/mapsforge/ fรผr die Details).</string> - <string name="init_mapsource_select">Wรคhle eine Kartenquelle</string> + <string name="init_mapsources_description">Hier kann die Quelle der benutzen Karte gewรคhlt werden. Alternativ zu Google Maps stehen verschiedene OpenStreetMap-Stile zur Verfรผgung und daneben auch Karten-Dateien fรผr die Offline-Nutzung (siehe http://code.google.com/p/mapsforge/ fรผr die Details).</string> + <string name="init_mapsource_select">Kartenquelle wรคhlen</string> <string name="init_select_mapfile">โฆ</string> <string name="init_maptrail">Zeige Spur auf Karte</string> <string name="init_trackautovisit">Trackables automatisch auf \"besuchen\" setzen</string> <string name="init_sigautoinsert">Signatur automatisch einfรผgen</string> <string name="init_loaddirectionimg">Richtungs-Grafik laden wenn nรถtig (nur Basic Member)</string> <string name="init_default_navigation_tool">Standardnavigation</string> - <string name="init_default_navigation_tool_description">Hier kannst du dein bevorzugtes Navigationswerkzeug festlegen.</string> + <string name="init_default_navigation_tool_description">Hier kann das bevorzugte Navigationswerkzeug festgelegt werden.</string> <string name="init_default_navigation_tool_select">Wรคhle Werkzeug</string> - <string name="init_default_navigation_tool_2_description">Hier kannst du dein zweites bevorzugtes Navigationswerkzeug festlegen. Es ist durch langen Klick auf das Navigationssymbol in der Titelzeile eines Caches erreichbar.</string> + <string name="init_default_navigation_tool_2_description">Hier kannst das zweite bevorzugte Navigationswerkzeug festgelegt werden. Es ist durch langen Klick auf das Navigationssymbol in der Titelzeile eines Caches erreichbar.</string> <string name="init_debug_title">Fehlersuche</string> - <string name="init_debug_note">c:geo kann bei Bedarf viele Debuginformationen speichern. Im Normalfall ist dies nicht notwendig, jedoch kann es den Entwicklern bei der Fehlersuche helfen. In diesem Fall werden sie dich bitten, diese Einstellung zu aktivieren und spรคter das Log-File zuzusenden.</string> + <string name="init_debug_note">c:geo kann bei Bedarf viele Debuginformationen speichern. Im Normalfall ist dies nicht notwendig, jedoch kann es den Entwicklern bei der Fehlersuche helfen. In diesem Fall wird der Benutzer gebeten diese Einstellung zu aktivieren und spรคter das Log-File zuzusenden.</string> <string name="init_debug">Debug-Log aktivieren</string> <!-- map sources --> @@ -432,11 +432,11 @@ <string name="map_source_osm_cyclemap">OSM: Radfahrerkarte</string> <string name="init_sendToCgeo">Send to c:geo</string> - <string name="init_sendToCgeo_name">Der Name deines Handys:</string> - <string name="init_sendToCgeo_description">Send to c:geo erlaubt es, mit einem speziellen Plugin fรผr Firefox oder Chrome, Caches direkt von der Geocachingseite zu empfangen. Bitte lies dir die Details vor einer Registrierung auf <a href="http://send2.cgeo.org/">http://send2.cgeo.org/</a> durch.</string> + <string name="init_sendToCgeo_name">Name des Endgerรคtes:</string> + <string name="init_sendToCgeo_description">Send to c:geo erlaubt es, mit einem speziellen Plugin fรผr Firefox oder Chrome, Caches direkt von der Geocachingseite zu empfangen. Bitte dazu die Details vor einer Registrierung auf <a href="http://send2.cgeo.org/">http://send2.cgeo.org/</a> durchlesen.</string> <string name="init_sendToCgeo_register">Registrierung anfordern</string> - <string name="init_sendToCgeo_registering">Registriere dein Handy fรผr "Send to c:geo"โฆ</string> - <string name="init_sendToCgeo_register_ok">Registrierung erfolgreich. Dein PIN code ist ####. Benutze diesen auf der c:geo website, um dein Handy im Browser hinzuzufรผgen.</string> + <string name="init_sendToCgeo_registering">Das Gerรคt wird fรผr "Send to c:geo" registriertโฆ</string> + <string name="init_sendToCgeo_register_ok">Registrierung erfolgreich. Der PIN Code ist ####. Bitte diesen auf der der c:geo Website angeben, um das Endgerรคt im Browser hinzuzufรผgen.</string> <string name="init_sendToCgeo_register_fail">Registrierung fehlgeschlagen.</string> <string name="sendToCgeo_download_fail">c:geo konnte Caches nicht laden. Entweder besteht keine Internetverbindung oder send2c:geo funktioniert nicht.</string> <string name="sendToCgeo_no_registration">c:geo konnte Caches nicht laden. Registrierung fรผr send2c:geo ungรผltig. Bitte in Einstellungen neu registrieren.</string> @@ -594,12 +594,12 @@ <string name="gpx_import_canceled">Der GPX-Import wurde abgebrochen</string> <!-- map file select --> - <string name="map_file_select_title">Wรคhle eine Kartendatei</string> + <string name="map_file_select_title">Kartendatei wรคhlen</string> <!-- import --> <string name="import_title">Importiereโฆ</string> <string name="web_import_title">Aus dem Internet importieren</string> - <string name="web_import_waiting">Erwarte neue Caches aus dem Internetโฆ</string> + <string name="web_import_waiting">Warte auf neue Caches aus dem Internetโฆ</string> <string name="web_downloading">Lade herunter</string> <string name="web_downloaded">Heruntergeladen</string> @@ -658,7 +658,7 @@ <string name="map_strategy_fast">Schnell</string> <string name="map_strategy_auto">Geschwindigkeitsabhรคngig</string> <string name="map_strategy_detailed">Detailliert</string> - <string name="live_map_notification">Auf der neuen Live-Karte sind die Koordinaten nicht immer genau. Eventuell ungenaue Koordinaten sind mit einem orangen Kreis markiert.\nDas รffnen der Cache-Details oder das Speichern des Cache liefert immer genaue Koordinaten.\n\nMehr Informationen รผber alle รnderungen findet ihr auf der \"รber c:geo\"-Seite in der App.</string> + <string name="live_map_notification">Auf der neuen Live-Karte sind die Koordinaten nicht immer genau. Eventuell ungenaue Koordinaten sind mit einem orangen Kreis markiert.\nDas รffnen der Cache-Details oder das Speichern des Cache liefert immer genaue Koordinaten.\n\nMehr Informationen รผber alle รnderungen befinden sich auf der \"รber c:geo\"-Seite in der App.</string> <string name="live_map_note_close">Schlieรen</string> <string name="live_map_note_dontshow">Nicht mehr anzeigen</string> @@ -752,6 +752,18 @@ <string name="addon_missing_title">Add-On fehlt</string> <string name="addon_download_prompt">Jetzt im Google Play Store herunterladen</string> + <!-- export --> + <string name="export">Exportieren</string> + <string name="export_as">Exportieren alsโฆ</string> + <string name="export_exportedto">exportiert nach</string> + <string name="export_failed">Exportieren fehlgeschlagen</string> + <string name="export_fieldnotes">Field Notes</string> + <string name="export_fieldnotes_info">Field Notes werden nach /sdcard/field-notes mit dem aktuellen Datum und Zeit als Dateiname exportiert.</string> + <string name="export_fieldnotes_upload">Hochladen auf geocaching.com</string> + <string name="export_fieldnotes_uploading">Hochladenโฆ</string> + <string name="export_fieldnotes_onlynew">Nur seit letztem Export</string> + <string name="export_gpx">GPX</string> + <!-- attributes (permissions -> allowed, not allowed) --> <string name="attribute_dogs_yes">Hunde erlaubt</string> <string name="attribute_dogs_no">Hunde nicht erlaubt</string> @@ -901,7 +913,7 @@ <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo page</a></string> <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string> <string name="nutshellmanual">Benutzung: <a href="http://manual.cgeo.org/">c:geo Kurzanleitung</a></string> - <string name="about_go4cache">Der Service <b>Go 4 cache</b> ermรถglicht es, andere Geocacher in Echtzeit auf der Karte zu sehen (in <b>c:geo</b> oder im Browser). Es kann auch angezeigt werden, welchen Cache du suchst. Wenn <b>c:geo</b> mit <b>Go 4 cache</b> verbunden wird, kann <b>c:geo</b> die aktuelle Position verรถffentlichen (nur wรคhrend <b>c:geo</b> ausgefรผhrt wird).</string> + <string name="about_go4cache">Der Service <b>Go 4 cache</b> ermรถglicht es, andere Geocacher in Echtzeit auf der Karte zu sehen (in <b>c:geo</b> oder im Browser). Es kann auch angezeigt werden, welcher Cache gerade gesucht wird. Wenn <b>c:geo</b> mit <b>Go 4 cache</b> verbunden wird, kann <b>c:geo</b> die aktuelle Position verรถffentlichen (nur wรคhrend <b>c:geo</b> ausgefรผhrt wird).</string> <string name="about_twitter">Soll jeder neue Fund auf Twitter verรถffentlicht werden, wenn er รผber <b>c:geo</b> geloggt wird?</string> <string name="about_auth_1">Der folgende Prozess erlaubt es <b>c:geo</b> auf den persรถnlichen Twitter-Account zuzugreifen, wenn zugestimmt wird.</string> <string name="about_auth_2">Ein Klick auf \"Starte Autorisierung\" รถffnet eine Twitter-Seite in einem Browserfenster. Durch die Anmeldung und die Bestรคtigung wird <b>c:geo</b> ermรถglicht, auf den persรถnlichen Twitter-Account zuzugreifen. Wird dies bestรคtigt, nennt Twitter eine numerische PIN, diese muss kopiert und in <b>c:geo</b> eingefรผgt werden. Das ist alles.</string> diff --git a/main/res/values-fr/strings.xml b/main/res/values-fr/strings.xml index e9bc5fd..5da8177 100644 --- a/main/res/values-fr/strings.xml +++ b/main/res/values-fr/strings.xml @@ -218,7 +218,7 @@ <string name="warn_search_help_tb">Veuillez remplir le code de l\'objet voyageur. Par exemple \"TB29QMZ\".</string> <string name="warn_log_text_fill">Merci de saisir un texte pour votre visite.</string> <string name="warn_load_images">c:geo n\'a pas pu charger les images.</string> - + <string name="warn_invalid_mapfile">Le fichier sรฉlectionnรฉ n\'est pas un fichier de carte mapsforge version 0.2.4.\nLes cartes hors-lignes ne sont pas disponibles.</string> <string name="info_log_posted">Envoi de la visite rรฉussi.</string> <string name="info_log_saved">Sauvegarde de la visite rรฉussie.</string> @@ -299,6 +299,7 @@ <string name="caches_move_selected">Dรฉplacer les caches sรฉlectionnรฉes</string> <string name="caches_move_all">Tout dรฉplacer</string> <string name="caches_map_locus">Locus</string> + <string name="caches_map_locus_export">Exporter vers Locus</string> <string name="caches_recaptcha_title">reCAPTCHA</string> <string name="caches_recaptcha_explanation">Recopier le texte se trouvant dans l\'image pour charger les coordonnรฉes des caches. Cette รฉtape peut รชtre dรฉsactivรฉe dans les Paramรจtres.</string> <string name="caches_recaptcha_hint">Texte de l\'image</string> @@ -759,6 +760,18 @@ <string name="addon_missing_title">Module complรฉmentaire manquant</string> <string name="addon_download_prompt">Le tรฉlรฉcharger sur Google Play.</string> + <!-- export --> + <string name="export">Exporter</string> + <string name="export_as">Exporter en tant queโฆ</string> + <string name="export_exportedto">exportรฉ vers</string> + <string name="export_failed">รchec de l\'exportation</string> + <string name="export_fieldnotes">Notes de terrain</string> + <string name="export_fieldnotes_info">Les notes de terrain seront sauvรฉes dans le dossier /sdcard/field-notes avec, comme nom de fichier, la date et l\'heure courantes.</string> + <string name="export_fieldnotes_upload">Envoyer vers geocaching.com</string> + <string name="export_fieldnotes_uploading">Envoi en coursโฆ</string> + <string name="export_fieldnotes_onlynew">Uniquement les nouveautรฉs depuis le dernier envoi</string> + <string name="export_gpx">GPX</string> + <!-- attributes (permissions -> allowed, not allowed) --> <string name="attribute_dogs_yes">Chiens autorisรฉs</string> <string name="attribute_dogs_no">Chiens interdits</string> diff --git a/main/res/values-sk/strings.xml b/main/res/values-sk/strings.xml index c4865f9..33a5610 100644 --- a/main/res/values-sk/strings.xml +++ b/main/res/values-sk/strings.xml @@ -235,6 +235,7 @@ <string name="loc_sat">sat</string> <string name="loc_trying">zisลฅovanie pozรญcie</string> <string name="loc_no_addr">neznรกma adresa</string> + <string name="loc_gps_disabled">GPS zakรกzanรก</string> <!-- standard menu --> <string name="menu_about">O aplikรกcii</string> @@ -298,6 +299,7 @@ <string name="caches_move_selected">Presunรบลฅ vybranรฉ</string> <string name="caches_move_all">Presunรบลฅ vลกetky</string> <string name="caches_map_locus">Locus</string> + <string name="caches_map_locus_export">Exportovaลฅย do Locus</string> <string name="caches_recaptcha_title">reCAPTCHA</string> <string name="caches_recaptcha_explanation">Opรญลกte text z obrรกzku. Je to dรดleลพitรฉ pre stiahnutie sรบradnรญc skrรฝลก. Tรบto vlastnosลฅ je moลพnรฉ vypnรบลฅ v Nastaveniach.</string> <string name="caches_recaptcha_hint">Text z obrรกzku</string> @@ -421,6 +423,9 @@ <string name="init_default_navigation_tool_description">Mรดลพete si vybraลฅ preferovanรฝ nรกstroj pre navigรกciu.</string> <string name="init_default_navigation_tool_select">Vyberte nรกstroj</string> <string name="init_default_navigation_tool_2_description">Mรดลพete vybraลฅย druhรฝย preferovanรฝย nรกstroj pre navigรกciu. Spustรญte ho dlhรฝm drลพanรญm ikony navigรกcia vedฤพa nรกzvu skrรฝลกe.</string> + <string name="init_debug_title">Ladiace informรกcie</string> + <string name="init_debug_note">c:geo mรดลพe vytvรกraลฅ generovaลฅย mnoลพstvo ladiacich informรกciรญ. Aj keฤ tieto informรกcie nie sรบ pre pouลพรญvateฤพov zvyฤajne pouลพiteฤพnรฉ, vรฝvojรกri ich mรดลพu potrebovaลฅ pre analรฝzu chyby. V tomto prรญpade vรกs poลพiadajรบ zaฤiarknuลฅย polรญฤko niลพลกie a poslaลฅย vytvorenรฝ log sรบbor.</string> + <string name="init_debug">Generovanie ladiacich informรกciรญ</string> <!-- map sources --> <string name="map_source_google_map">Google: Mapa</string> @@ -584,8 +589,10 @@ <string name="gpx_import_store_static_maps">Ukladanie statickรฝch mรกp</string> <string name="gpx_import_storing">Zapisovanie skrรฝลก do databรกzy\nZapรญsanรฉ:</string> <string name="gpx_import_caches_imported">skrรฝลกe importovanรฉ</string> - <string name="gpx_import_title">Import GPX</string> + <string name="gpx_import_static_maps_skipped">Preberanie statickรฝch mรกp zruลกenรฉ</string> + <string name="gpx_import_title_static_maps">Uloลพenie statickรฝch mรกp</string> <string name="gpx_import_title_reading_file">ฤรญtanie sรบboru</string> + <string name="gpx_import_title">Import GPX</string> <string name="gpx_import_title_caches_imported">Vรฝsledok</string> <string name="gpx_import_title_caches_import_failed">Import zlyhal</string> <string name="gpx_import_error_io">Nedรกย sa preฤรญtaลฅย sรบbor</string> @@ -636,6 +643,13 @@ <string name="waypoint_coordinate_formats_plain">Iba text</string> + <!-- distance units --> + <string name="unit_m">m</string> + <string name="unit_km">km</string> + <string name="unit_ft">ft</string> + <string name="unit_yd">yd</string> + <string name="unit_mi">mi</string> + <!-- visit --> <string name="visit_tweet">informovaลฅ o nรกjdenรญ na Twitteri</string> @@ -659,6 +673,10 @@ <string name="map_strategy_fast">Rรฝchla</string> <string name="map_strategy_auto">Podฤพa rรฝchlosti</string> <string name="map_strategy_detailed">Podrobnรก</string> + <string name="live_map_notification">Na novej aktรญvnej mape nemusia byลฅ sรบradnice vลพdy presnรฉ. Sรบradnice, ktorรฉ mรดลพu byลฅย nepresnรฉ, sรบ oznaฤenรฉย oranลพovรฝm krรบลพkom.\nPo otvorenรญ detailu skrรฝลกe, alebo po jej uloลพenรญ pre pouลพitie offline, sรบ zรญskanรฉ vลพdy presnรฉย sรบradnice.\n\nViac informรกciรญ ku vลกetkรฝm zmenรกm sa nachรกdzajรบ na strรกnke โO c:geoโ v aplikรกcii.</string> + <string name="live_map_note_close">Zatvoriลฅ</string> + <string name="live_map_note_dontshow">Nabudรบce nezobrazovaลฅ</string> + <!-- search --> <string name="search_bar_hint">Hฤพadanie skrรฝลก</string> diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index b497979..292206e 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -218,7 +218,7 @@ <string name="warn_search_help_tb">Enter the code for a trackable. For example \"TB29QMZ\".</string> <string name="warn_log_text_fill">Please fill in text for your log.</string> <string name="warn_load_images">c:geo failed to load images.</string> - + <string name="warn_invalid_mapfile">The selected map file is not a valid mapsforge version 0.2.4 map file.\nOffline maps are not available.</string> <string name="info_log_posted">c:geo successfully submitted the log.</string> <string name="info_log_saved">c:geo successfully saved the log.</string> @@ -779,14 +779,26 @@ <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">You can use radar from this application with c:geo. It also offers a lot of other GPS-related information.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> - <string name="helper_bluetoothgps_description">Allows you to use external GPS device to get better reception, more precise location and can spare battery of your phone.</string> + <string name="helper_bluetoothgps_description">Allows you to use an external GPS receiver to get more precise location and can spare battery of your device.</string> <string name="helper_barcode_title">Barcode Scanner</string> <string name="helper_barcode_description">There are Greasemonkey scripts and websites which allow to display a geocode as barcode. With this app c:geo can read that geocode directly from the screen of your computer.</string> <!-- add-ons --> <string name="addon_missing_title">Missing Add-On</string> <string name="addon_download_prompt">Get it now from Google Play.</string> - + + <!-- export --> + <string name="export">Export</string> + <string name="export_as">Export asโฆ</string> + <string name="export_exportedto">exported to</string> + <string name="export_failed">Exported failed</string> + <string name="export_fieldnotes">Field Notes</string> + <string name="export_fieldnotes_info">Field Notes will be exported into /sdcard/field-notes with current date and time as file name.</string> + <string name="export_fieldnotes_upload">Upload to geocaching.com</string> + <string name="export_fieldnotes_uploading">Uploadingโฆ</string> + <string name="export_fieldnotes_onlynew">Only since last export</string> + <string name="export_gpx">GPX</string> + <!-- attributes (permissions -> allowed, not allowed) --> <string name="attribute_dogs_yes">Dogs allowed</string> <string name="attribute_dogs_no">Dogs not allowed</string> @@ -984,6 +996,7 @@ ยท Pascal (localization NL)\n ยท Pavol Babinฤรกk (code, loc. SK)\n ยท Peter (localization HU)\n + ยท <a href="https://github.com/Portree-Kid">Portree Kid</a> (code)\n ยท Rainer S. (code)\n ยท Ray (code, loc. JA)\n ยท <a href="http://seromenho.com/">Ricardo Seromenho</a> (localization PT)\n @@ -991,7 +1004,7 @@ ยท <a href="http://www.blueskysoftware.it/">RomNexus6</a> (localization IT)\n ยท <a href="http://www.sammyshp.de/">SammysHP</a> (code, localization DE)\n ยท <a href="http://www.rfc1149.net/sam.html">Samuel Tardieu</a> (code, localization FR)\n - ยท serenity (localization FR)\n + ยท serenity (localization DE)\n ยท Shan, a.k.a. ShakurNO (localization NO)\n ยท Shizo87 (tester)\n ยท stephanme/Geoteufel (code)\n @@ -1010,10 +1023,13 @@ <string name="changelog">\n <b>Next release</b>\n\n <b>New Features/Functions:</b>\n - ยท - <b>Bugfixing:</b>\n - ยท + ยท Export caches as GPX file\n + ยท Field notes can now be uploaded to the website\n \n + <b>Bugfixing:</b>\n + ยท Static maps download for waypoints now off by default\n + ยท Waypoints on map do no longer disappear when moving map\n + \n <a href="https://github.com/cgeo/c-geo-opensource/issues?milestone=6&state=closed">Detailed list of all changes</a>\n \n <b>Known Limitations/Bugs:</b>\n @@ -1022,8 +1038,6 @@ Be aware: If navigation is started directly from live map it may also use the approximated coords!\n In fast mode the cache type might be wrong in rare cases\n Fast mode only detectes Tradi, Multi, Mystery, Event caches\n - Waypoints on map might disappear when moving the map\n - (Workaround: Increase waypoint limit in settings)\n ยท Other:\n Log images with huge size will cause a long loading time\n OSM:Offline does only support map-files with version 0.2.4\n\n\n diff --git a/main/src/cgeo/geocaching/AdressListActivity.java b/main/src/cgeo/geocaching/AdressListActivity.java index 39b9f22..57d3cdd 100644 --- a/main/src/cgeo/geocaching/AdressListActivity.java +++ b/main/src/cgeo/geocaching/AdressListActivity.java @@ -49,7 +49,7 @@ public class AdressListActivity extends AbstractListActivity { try { return geocoder.getFromLocationName(keyword, 20); } catch (Exception e) { - Log.e(Settings.tag, "AdressListActivity.doInBackground", e); + Log.e("AdressListActivity.doInBackground", e); return null; } } @@ -68,7 +68,7 @@ public class AdressListActivity extends AbstractListActivity { } } } catch (Exception e) { - Log.e(Settings.tag, "AdressListActivity.onPostExecute", e); + Log.e("AdressListActivity.onPostExecute", e); } } diff --git a/main/src/cgeo/geocaching/CacheCache.java b/main/src/cgeo/geocaching/CacheCache.java index a2b5324..7f6f67e 100644 --- a/main/src/cgeo/geocaching/CacheCache.java +++ b/main/src/cgeo/geocaching/CacheCache.java @@ -1,10 +1,18 @@ package cgeo.geocaching; import cgeo.geocaching.cgData.StorageLocation; -import cgeo.geocaching.utils.LeastRecentlyUsedCache; +import cgeo.geocaching.connector.gc.GCBase; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.utils.LeastRecentlyUsedMap; +import cgeo.geocaching.utils.LeastRecentlyUsedMap.RemoveHandler; +import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; +import java.util.HashSet; +import java.util.Set; + /** * Cache for Caches. Every cache is stored in memory while c:geo is active to * speed up the app and to minimize network request - which are slow. @@ -14,12 +22,15 @@ import org.apache.commons.lang3.StringUtils; public class CacheCache { private static final int MAX_CACHED_CACHES = 1000; - final private LeastRecentlyUsedCache<String, cgCache> cachesCache; + final private LeastRecentlyUsedMap<String, cgCache> cachesCache; + final private RemoveHandler<cgCache> removeHandler; private static CacheCache instance = null; private CacheCache() { - cachesCache = new LeastRecentlyUsedCache<String, cgCache>(MAX_CACHED_CACHES); + cachesCache = new LeastRecentlyUsedMap.LruCache<String, cgCache>(MAX_CACHED_CACHES); + removeHandler = new CacheRemoveHandler(); + cachesCache.setRemoveHandler(removeHandler); } public static CacheCache getInstance() { @@ -74,9 +85,33 @@ public class CacheCache { return cachesCache.get(geocode); } + public Set<String> getInViewport(final Viewport viewport, final CacheType cacheType) { + final Set<String> geocodes = new HashSet<String>(); + for (final cgCache cache : cachesCache.values()) { + if (cache.getCoords() == null) { + // FIXME: this kludge must be removed, it is only present to help us debug the cases where + // caches contain null coordinates. + Log.e("CacheCache.getInViewport: got cache with null coordinates: " + cache.getGeocode()); + continue; + } + if ((CacheType.ALL == cacheType || cache.getType() == cacheType) && viewport.contains(cache)) { + geocodes.add(cache.getGeocode()); + } + } + return geocodes; + } + @Override public String toString() { return StringUtils.join(cachesCache.keySet(), ' '); } + private class CacheRemoveHandler implements RemoveHandler<cgCache> { + + @Override + public void onRemove(cgCache removed) { + GCBase.removeFromTileCache(removed.getCoords()); + } + } + } diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index de754b9..847d04c 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -7,6 +7,7 @@ import cgeo.geocaching.apps.cache.GeneralAppsFactory; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; @@ -15,7 +16,6 @@ import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.geopoint.HumanDistance; import cgeo.geocaching.geopoint.IConversion; import cgeo.geocaching.network.HtmlImage; -import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.ui.DecryptTextClickListener; import cgeo.geocaching.ui.Formatter; @@ -39,6 +39,8 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; @@ -219,9 +221,9 @@ public class CacheDetailActivity extends AbstractActivity { String uriQuery = uri.getQuery(); if (uriQuery != null) { - Log.i(Settings.tag, "Opening URI: " + uriHost + uriPath + "?" + uriQuery); + Log.i("Opening URI: " + uriHost + uriPath + "?" + uriQuery); } else { - Log.i(Settings.tag, "Opening URI: " + uriHost + uriPath); + Log.i("Opening URI: " + uriHost + uriPath); } if (uriHost.contains("geocaching.com")) { @@ -580,7 +582,7 @@ public class CacheDetailActivity extends AbstractActivity { cache.openInBrowser(this); return true; } else if (menuItem == MENU_CACHES_AROUND) { - cachesAround(); + cgeocaches.startActivityCachesAround(this, cache.getCoords()); return true; } else if (menuItem == MENU_CALENDAR) { addToCalendarWithIntent(); @@ -607,7 +609,7 @@ public class CacheDetailActivity extends AbstractActivity { private class LoadCacheHandler extends CancellableHandler { @Override public void handleRegularMessage(final Message msg) { - if (cgBase.UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { + if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { updateStatusMsg((String) msg.obj); } else { if (search == null) { @@ -743,7 +745,7 @@ public class CacheDetailActivity extends AbstractActivity { cacheDistanceView.setText(dist.toString()); cacheDistanceView.bringToFront(); } catch (Exception e) { - Log.w(Settings.tag, "Failed to update location."); + Log.w("Failed to update location."); } } } @@ -773,25 +775,43 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - search = cgBase.searchByGeocode(geocode, StringUtils.isBlank(geocode) ? guid : null, 0, false, handler); + search = cgCache.searchByGeocode(geocode, StringUtils.isBlank(geocode) ? guid : null, 0, false, handler); handler.sendMessage(Message.obtain()); } } /** - * Starts activity to search for caches near this cache. + * Indicates whether the specified action can be used as an intent. This + * method queries the package manager for installed packages that can + * respond to an intent with the specified action. If no suitable package is + * found, this method returns false. * - * Also finishes this activity. + * @param context + * The application's environment. + * @param action + * The Intent action to check for availability. + * @param uri + * The Intent URI to check for availability. + * + * @return True if an Intent with the specified action can be sent and + * responded to, false otherwise. */ - private void cachesAround() { - cgeocaches.startActivityCachesAround(this, cache.getCoords()); - - finish(); + private static boolean isIntentAvailable(Context context, String action, Uri uri) { + final PackageManager packageManager = context.getPackageManager(); + final Intent intent; + if (uri == null) { + intent = new Intent(action); + } else { + intent = new Intent(action, uri); + } + List<ResolveInfo> list = packageManager.queryIntentActivities(intent, + PackageManager.MATCH_DEFAULT_ONLY); + return list.size() > 0; } private void addToCalendarWithIntent() { - final boolean calendarAddOnAvailable = cgBase.isIntentAvailable(this, ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST)); + final boolean calendarAddOnAvailable = isIntentAvailable(this, ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST)); if (calendarAddOnAvailable) { final Parameters params = new Parameters( @@ -832,25 +852,6 @@ public class CacheDetailActivity extends AbstractActivity { } /** - * Creates a {@link List} of all coordinates (cache and waypoints) for the current cache. - * - * @return A {@link List} of all coordinates - */ - public List<IWaypoint> getCoordinates() { - List<IWaypoint> coordinates = new ArrayList<IWaypoint>(); - - // cache - coordinates.add(cache); - - // waypoints - if (cache.hasWaypoints()) { - coordinates.addAll(cache.getWaypoints()); - } - - return coordinates; - } - - /** * Tries to navigate to the {@link cgCache} of this activity. */ private void startDefaultNavigation() { @@ -1038,7 +1039,7 @@ public class CacheDetailActivity extends AbstractActivity { ((ViewPager) container).addView(view, 0); } } catch (Exception e) { - Log.e(Settings.tag, "ViewPagerAdapter.instantiateItem ", e); + Log.e("ViewPagerAdapter.instantiateItem ", e); } return view; @@ -1157,7 +1158,7 @@ public class CacheDetailActivity extends AbstractActivity { } /** - * lazy-creates the layout holding the icons of the chaches attributes + * lazy-creates the layout holding the icons of the caches attributes * and makes it visible */ private void showAttributeIcons(LinearLayout attribBox, int parentWidth) { @@ -1175,7 +1176,7 @@ public class CacheDetailActivity extends AbstractActivity { } /** - * lazy-creates the layout holding the discriptions of the chaches attributes + * lazy-creates the layout holding the descriptions of the caches attributes * and makes it visible */ private void showAttributeDescriptions(LinearLayout attribBox) { @@ -1457,7 +1458,7 @@ public class CacheDetailActivity extends AbstractActivity { if (cache.getHiddenDate() != null) { long time = cache.getHiddenDate().getTime(); if (time > 0) { - String dateString = cgBase.formatFullDate(time); + String dateString = Formatter.formatFullDate(time); if (cache.isEventCache()) { dateString = DateUtils.formatDateTime(cgeoapplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY) + ", " + dateString; } @@ -1556,7 +1557,7 @@ public class CacheDetailActivity extends AbstractActivity { private class StoreCacheHandler extends CancellableHandler { @Override public void handleRegularMessage(Message msg) { - if (cgBase.UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { + if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { updateStatusMsg((String) msg.obj); } else { storeThread = null; @@ -1574,7 +1575,7 @@ public class CacheDetailActivity extends AbstractActivity { private class RefreshCacheHandler extends CancellableHandler { @Override public void handleRegularMessage(Message msg) { - if (cgBase.UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { + if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { updateStatusMsg((String) msg.obj); } else { refreshThread = null; @@ -1658,7 +1659,7 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - cgBase.refreshCache(CacheDetailActivity.this, cache.getGeocode(), cache.getListId(), handler); + cache.refresh(CacheDetailActivity.this, cache.getListId(), handler); handler.sendEmptyMessage(0); } @@ -1688,7 +1689,7 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - cgBase.dropCache(cache, handler); + cache.drop(handler); } } @@ -1744,7 +1745,7 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - handler.sendEmptyMessage(cgBase.addToWatchlist(cache)); + handler.sendEmptyMessage(GCParser.addToWatchlist(cache)); } } @@ -1758,7 +1759,7 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - handler.sendEmptyMessage(cgBase.removeFromWatchlist(cache)); + handler.sendEmptyMessage(GCParser.removeFromWatchlist(cache)); } } @@ -1845,9 +1846,7 @@ public class CacheDetailActivity extends AbstractActivity { private class PreviewMapTask extends AsyncTask<Void, Void, BitmapDrawable> { @Override - protected BitmapDrawable doInBackground(Void... params) { - BitmapDrawable image = null; - + protected BitmapDrawable doInBackground(Void... parameters) { try { final String latlonMap = cache.getCoords().format(GeopointFormatter.Format.LAT_LON_DECDEGREE_COMMA); @@ -1858,15 +1857,15 @@ public class CacheDetailActivity extends AbstractActivity { final int height = (int) (110 * metrics.density); // TODO move this code to StaticMapProvider and use its constant values - final String markerUrl = Network.urlencode_rfc3986("http://cgeo.carnero.cc/_markers/my_location_mdpi.png"); + final String markerUrl = "http://cgeo.carnero.cc/_markers/my_location_mdpi.png"; final HtmlImage mapGetter = new HtmlImage(CacheDetailActivity.this, cache.getGeocode(), false, 0, false); - image = mapGetter.getDrawable("http://maps.google.com/maps/api/staticmap?zoom=15&size=" + width + "x" + height + "&maptype=roadmap&markers=icon%3A" + markerUrl + "%7Cshadow:false%7C" + latlonMap + "&sensor=false"); + final Parameters params = new Parameters("zoom", "15", "size", width + "x" + height, "maptype", "roadmap", "markers", "icon:" + markerUrl + "|shadow:false|" + latlonMap, "sensor", "false"); + return mapGetter.getDrawable("http://maps.google.com/maps/api/staticmap?" + params); } catch (Exception e) { - Log.w(Settings.tag, "CacheDetailActivity.PreviewMapTask", e); + Log.w("CacheDetailActivity.PreviewMapTask", e); + return null; } - - return image; } @Override @@ -2190,7 +2189,7 @@ public class CacheDetailActivity extends AbstractActivity { } } - view.setAdapter(new ArrayAdapter<cgLog>(CacheDetailActivity.this, R.layout.cacheview_logs_item, cache.getLogs(allLogs)) { + view.setAdapter(new ArrayAdapter<LogEntry>(CacheDetailActivity.this, R.layout.cacheview_logs_item, cache.getLogs(allLogs)) { final UserActionsClickListener userActionsClickListener = new UserActionsClickListener(); final DecryptTextClickListener decryptTextClickListener = new DecryptTextClickListener(); @@ -2206,10 +2205,10 @@ public class CacheDetailActivity extends AbstractActivity { rowView.setTag(holder); } - final cgLog log = getItem(position); + final LogEntry log = getItem(position); if (log.date > 0) { - holder.date.setText(cgBase.formatShortDate(log.date)); + holder.date.setText(Formatter.formatShortDate(log.date)); holder.date.setVisibility(View.VISIBLE); } else { holder.date.setVisibility(View.GONE); @@ -2239,10 +2238,10 @@ public class CacheDetailActivity extends AbstractActivity { } // images - if (CollectionUtils.isNotEmpty(log.logImages)) { + if (log.hasLogImages()) { List<String> titles = new ArrayList<String>(5); - for (cgImage image : log.logImages) { + for (cgImage image : log.getLogImages()) { if (StringUtils.isNotBlank(image.getTitle())) { titles.add(image.getTitle()); } @@ -2256,7 +2255,7 @@ public class CacheDetailActivity extends AbstractActivity { holder.images.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - cgeoimages.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<cgImage>(log.logImages)); + cgeoimages.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<cgImage>(log.getLogImages())); } }); } else { @@ -2368,7 +2367,7 @@ public class CacheDetailActivity extends AbstractActivity { // info final List<String> infoTextList = new ArrayList<String>(3); - if (WaypointType.ALL_TYPES_EXCEPT_OWN.containsKey(wpt.getWaypointType())) { + if (WaypointType.ALL_TYPES_EXCEPT_OWN.contains(wpt.getWaypointType())) { infoTextList.add(wpt.getWaypointType().getL10n()); } if (cgWaypoint.PREFIX_OWN.equalsIgnoreCase(wpt.getPrefix())) { @@ -2506,4 +2505,18 @@ public class CacheDetailActivity extends AbstractActivity { return view; } } + + public static void startActivity(final Context context, final String geocode, final String cacheName) { + final Intent cachesIntent = new Intent(context, CacheDetailActivity.class); + cachesIntent.putExtra("geocode", geocode); + cachesIntent.putExtra("name", cacheName); + context.startActivity(cachesIntent); + } + + public static void startActivityGuid(final Context context, final String guid, final String cacheName) { + final Intent cacheIntent = new Intent(context, CacheDetailActivity.class); + cacheIntent.putExtra("guid", guid); + cacheIntent.putExtra("name", cacheName); + context.startActivity(cacheIntent); + } } diff --git a/main/src/cgeo/geocaching/Destination.java b/main/src/cgeo/geocaching/Destination.java new file mode 100644 index 0000000..441e959 --- /dev/null +++ b/main/src/cgeo/geocaching/Destination.java @@ -0,0 +1,44 @@ +package cgeo.geocaching; + +import cgeo.geocaching.geopoint.Geopoint; + +public final class Destination implements ICoordinates { + + final private long id; + final private long date; + final private Geopoint coords; + + public Destination(long id, long date, final Geopoint coords) { + this.id = id; + this.date = date; + this.coords = coords; + } + + public Destination(final Geopoint coords) { + this(0, System.currentTimeMillis(), coords); + } + + public long getDate() { + return date; + } + + @Override + public Geopoint getCoords() { + return coords; + } + + @Override + public int hashCode() { + return coords.hashCode(); + } + + @Override + public boolean equals(final Object obj) { + return obj != null && obj instanceof Destination && ((Destination) obj).coords.equals(coords); + } + + public long getId() { + return id; + } + +} diff --git a/main/src/cgeo/geocaching/IBasicCache.java b/main/src/cgeo/geocaching/IBasicCache.java index 5e67b2d..195572b 100644 --- a/main/src/cgeo/geocaching/IBasicCache.java +++ b/main/src/cgeo/geocaching/IBasicCache.java @@ -11,7 +11,7 @@ import cgeo.geocaching.enumerations.CacheType; * @author blafoo * */ -public interface IBasicCache extends ILogable { +public interface IBasicCache extends ILogable, ICoordinates { public abstract String getGuid(); diff --git a/main/src/cgeo/geocaching/ICache.java b/main/src/cgeo/geocaching/ICache.java index b6a809f..dccdb85 100644 --- a/main/src/cgeo/geocaching/ICache.java +++ b/main/src/cgeo/geocaching/ICache.java @@ -28,16 +28,6 @@ public interface ICache extends IBasicCache { public String getOwnerReal(); /** - * @return Latitude, e.g. N 52ยฐ 12.345 - */ - public String getLatitude(); - - /** - * @return Longitude, e.g. E 9ยฐ 34.567 - */ - public String getLongitude(); - - /** * @return true if the user is the owner of the cache, false else */ public boolean isOwn(); diff --git a/main/src/cgeo/geocaching/ICoordinates.java b/main/src/cgeo/geocaching/ICoordinates.java new file mode 100644 index 0000000..b70e4ac --- /dev/null +++ b/main/src/cgeo/geocaching/ICoordinates.java @@ -0,0 +1,9 @@ +package cgeo.geocaching; + +import cgeo.geocaching.geopoint.Geopoint; + +public interface ICoordinates { + + public abstract Geopoint getCoords(); + +} diff --git a/main/src/cgeo/geocaching/IWaypoint.java b/main/src/cgeo/geocaching/IWaypoint.java index 3e26052..ad12d48 100644 --- a/main/src/cgeo/geocaching/IWaypoint.java +++ b/main/src/cgeo/geocaching/IWaypoint.java @@ -4,18 +4,15 @@ package cgeo.geocaching; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.Geopoint; /** * @author blafoo * */ -public interface IWaypoint extends ILogable { +public interface IWaypoint extends ILogable, ICoordinates { public abstract int getId(); - public abstract Geopoint getCoords(); - public abstract WaypointType getWaypointType(); public abstract String getCoordType(); diff --git a/main/src/cgeo/geocaching/LogEntry.java b/main/src/cgeo/geocaching/LogEntry.java new file mode 100644 index 0000000..3f6ed74 --- /dev/null +++ b/main/src/cgeo/geocaching/LogEntry.java @@ -0,0 +1,69 @@ +package cgeo.geocaching; + +import cgeo.geocaching.enumerations.LogType; + +import org.apache.commons.collections.CollectionUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class LogEntry { + /** + * avoid creating new empty lists all the time using this constant. We could also return Collections.EMPTY_LIST + * using a cast, but that might trigger static code analysis tools. + */ + private static final List<cgImage> EMPTY_LIST = Collections.emptyList(); + public int id = 0; + public LogType type = LogType.LOG_NOTE; // note + public String author = ""; + public String log = ""; + public long date = 0; + public int found = -1; + /** Friend's log entry */ + public boolean friend = false; + private List<cgImage> logImages = null; + public String cacheName = ""; // used for trackables + public String cacheGuid = ""; // used for trackables + + @Override + public int hashCode() { + return (int) date * type.hashCode() * author.hashCode() * log.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof LogEntry)) { + return false; + } + final LogEntry otherLog = (LogEntry) obj; + return date == otherLog.date && + type == otherLog.type && + author.compareTo(otherLog.author) == 0 && + log.compareTo(otherLog.log) == 0; + } + + public void addLogImage(final cgImage image) { + if (logImages == null) { + logImages = new ArrayList<cgImage>(); + } + logImages.add(image); + } + + /** + * @return the log images or an empty list, never <code>null</code> + */ + public List<cgImage> getLogImages() { + if (logImages == null) { + return EMPTY_LIST; + } + return logImages; + } + + public boolean hasLogImages() { + return CollectionUtils.isNotEmpty(logImages); + } +} diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java index e7c9a88..2e56c7c 100644 --- a/main/src/cgeo/geocaching/SearchResult.java +++ b/main/src/cgeo/geocaching/SearchResult.java @@ -1,5 +1,6 @@ package cgeo.geocaching; +import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.LoadFlag; @@ -7,7 +8,6 @@ import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.gcvote.GCVote; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import android.os.Parcel; @@ -129,7 +129,7 @@ public class SearchResult implements Parcelable { } public void setViewstates(String[] viewstates) { - if (cgBase.isEmpty(viewstates)) { + if (Login.isEmpty(viewstates)) { return; } @@ -201,14 +201,8 @@ public class SearchResult implements Parcelable { return cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE)); } - /** Add the cache geocodes to the search and store them in the CacheCache */ - public void addCaches(final Set<cgCache> caches) { - if (CollectionUtils.isEmpty(caches)) { - return; - } - - for (final cgCache cache : caches) { - addCache(cache); - } + public boolean isEmpty() { + return geocodes.isEmpty(); } + } diff --git a/main/src/cgeo/geocaching/Settings.java b/main/src/cgeo/geocaching/Settings.java index 76d185e..03427c5 100644 --- a/main/src/cgeo/geocaching/Settings.java +++ b/main/src/cgeo/geocaching/Settings.java @@ -5,17 +5,19 @@ import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.maps.MapProviderFactory; import cgeo.geocaching.maps.interfaces.MapProvider; +import cgeo.geocaching.maps.mapsforge.MapsforgeMapProvider; import cgeo.geocaching.utils.CryptUtils; +import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; -import org.mapsforge.android.maps.MapDatabase; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.res.Configuration; import android.content.res.Resources; +import android.preference.PreferenceManager; import java.util.Locale; @@ -82,9 +84,9 @@ public final class Settings { private static final String KEY_DEBUG = "debug"; private static final String KEY_HIDE_LIVE_MAP_HINT = "hidelivemaphint"; private static final String KEY_LIVE_MAP_HINT_SHOW_COUNT = "livemaphintshowcount"; + private static final String KEY_SETTINGS_VERSION = "settingsversion"; private final static int unitsMetric = 1; - private final static int unitsImperial = 2; // twitter api keys private final static String keyConsumerPublic = CryptUtils.rot13("ESnsCvAv3kEupF1GCR3jGj"); @@ -110,18 +112,14 @@ public final class Settings { } } - // usable values - public static final String tag = "cgeo"; - - /** Name of the preferences file */ - public static final String preferences = "cgeo.pref"; - - private static final SharedPreferences sharedPrefs = cgeoapplication.getInstance().getSharedPreferences(Settings.preferences, Context.MODE_PRIVATE); private static String username = null; private static String password = null; - // Debug settings are accessed often enough to be cached - private static Boolean cachedDebug = sharedPrefs.getBoolean(KEY_DEBUG, false); + private static final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(cgeoapplication.getInstance().getBaseContext()); + static { + migrateSettings(); + Log.setDebugUnsaved(sharedPrefs.getBoolean(KEY_DEBUG, false)); + } // maps private static MapProvider mapProvider = null; @@ -130,6 +128,77 @@ public final class Settings { // this class is not to be instantiated; } + private static void migrateSettings() { + // migrate from non standard file location and integer based boolean types + if (sharedPrefs.getInt(KEY_SETTINGS_VERSION, 0) < 1) { + final String oldPreferencesName = "cgeo.pref"; + final SharedPreferences old = cgeoapplication.getInstance().getSharedPreferences(oldPreferencesName, Context.MODE_PRIVATE); + final Editor e = sharedPrefs.edit(); + + e.putString(KEY_TEMP_TOKEN_SECRET, old.getString(KEY_TEMP_TOKEN_SECRET, null)); + e.putString(KEY_TEMP_TOKEN_PUBLIC, old.getString(KEY_TEMP_TOKEN_PUBLIC, null)); + e.putBoolean(KEY_HELP_SHOWN, old.getInt(KEY_HELP_SHOWN, 0) != 0); + e.putFloat(KEY_ANYLONGITUDE, old.getFloat(KEY_ANYLONGITUDE, 0)); + e.putFloat(KEY_ANYLATITUDE, old.getFloat(KEY_ANYLATITUDE, 0)); + e.putBoolean(KEY_PUBLICLOC, 0 != old.getInt(KEY_PUBLICLOC, 0)); + e.putBoolean(KEY_USE_OFFLINEMAPS, 0 != old.getInt(KEY_USE_OFFLINEMAPS, 1)); + e.putBoolean(KEY_USE_OFFLINEWPMAPS, 0 != old.getInt(KEY_USE_OFFLINEWPMAPS, 0)); + e.putString(KEY_WEB_DEVICE_CODE, old.getString(KEY_WEB_DEVICE_CODE, null)); + e.putString(KEY_WEBDEVICE_NAME, old.getString(KEY_WEBDEVICE_NAME, null)); + e.putBoolean(KEY_MAP_LIVE, old.getInt(KEY_MAP_LIVE, 1) != 0); + e.putInt(KEY_MAP_SOURCE, old.getInt(KEY_MAP_SOURCE, 0)); + e.putBoolean(KEY_USE_TWITTER, 0 != old.getInt(KEY_USE_TWITTER, 0)); + e.putBoolean(KEY_SHOW_ADDRESS, 0 != old.getInt(KEY_SHOW_ADDRESS, 1)); + e.putBoolean(KEY_SHOW_CAPTCHA, old.getBoolean(KEY_SHOW_CAPTCHA, false)); + e.putBoolean(KEY_MAP_TRAIL, old.getInt(KEY_MAP_TRAIL, 1) != 0); + e.putInt(KEY_LAST_MAP_ZOOM, old.getInt(KEY_LAST_MAP_ZOOM, 14)); + e.putBoolean(KEY_LIVE_LIST, 0 != old.getInt(KEY_LIVE_LIST, 1)); + e.putBoolean(KEY_METRIC_UNITS, old.getInt(KEY_METRIC_UNITS, unitsMetric) == unitsMetric); + e.putBoolean(KEY_SKIN, old.getInt(KEY_SKIN, 0) != 0); + e.putInt(KEY_LAST_USED_LIST, old.getInt(KEY_LAST_USED_LIST, StoredList.STANDARD_LIST_ID)); + e.putString(KEY_CACHE_TYPE, old.getString(KEY_CACHE_TYPE, CacheType.ALL.id)); + e.putString(KEY_TWITTER_TOKEN_SECRET, old.getString(KEY_TWITTER_TOKEN_SECRET, null)); + e.putString(KEY_TWITTER_TOKEN_PUBLIC, old.getString(KEY_TWITTER_TOKEN_PUBLIC, null)); + e.putInt(KEY_VERSION, old.getInt(KEY_VERSION, 0)); + e.putBoolean(KEY_LOAD_DESCRIPTION, 0 != old.getInt(KEY_LOAD_DESCRIPTION, 0)); + e.putBoolean(KEY_RATING_WANTED, old.getBoolean(KEY_RATING_WANTED, true)); + e.putBoolean(KEY_ELEVATION_WANTED, old.getBoolean(KEY_ELEVATION_WANTED, true)); + e.putBoolean(KEY_FRIENDLOGS_WANTED, old.getBoolean(KEY_FRIENDLOGS_WANTED, true)); + e.putBoolean(KEY_USE_ENGLISH, old.getBoolean(KEY_USE_ENGLISH, false)); + e.putBoolean(KEY_USE_COMPASS, 0 != old.getInt(KEY_USE_COMPASS, 1)); + e.putBoolean(KEY_AUTO_VISIT_TRACKABLES, old.getBoolean(KEY_AUTO_VISIT_TRACKABLES, false)); + e.putBoolean(KEY_AUTO_INSERT_SIGNATURE, old.getBoolean(KEY_AUTO_INSERT_SIGNATURE, false)); + e.putInt(KEY_ALTITUDE_CORRECTION, old.getInt(KEY_ALTITUDE_CORRECTION, 0)); + e.putBoolean(KEY_USE_GOOGLE_NAVIGATION, 0 != old.getInt(KEY_USE_GOOGLE_NAVIGATION, 1)); + e.putBoolean(KEY_STORE_LOG_IMAGES, old.getBoolean(KEY_STORE_LOG_IMAGES, false)); + e.putBoolean(KEY_EXCLUDE_DISABLED, 0 != old.getInt(KEY_EXCLUDE_DISABLED, 0)); + e.putBoolean(KEY_EXCLUDE_OWN, 0 != old.getInt(KEY_EXCLUDE_OWN, 0)); + e.putString(KEY_MAPFILE, old.getString(KEY_MAPFILE, null)); + e.putString(KEY_SIGNATURE, old.getString(KEY_SIGNATURE, null)); + e.putString(KEY_GCVOTE_PASSWORD, old.getString(KEY_GCVOTE_PASSWORD, null)); + e.putString(KEY_PASSWORD, old.getString(KEY_PASSWORD, null)); + e.putString(KEY_USERNAME, old.getString(KEY_USERNAME, null)); + e.putString(KEY_MEMBER_STATUS, old.getString(KEY_MEMBER_STATUS, "")); + e.putInt(KEY_COORD_INPUT_FORMAT, old.getInt(KEY_COORD_INPUT_FORMAT, 0)); + e.putBoolean(KEY_LOG_OFFLINE, old.getBoolean(KEY_LOG_OFFLINE, false)); + e.putBoolean(KEY_LOAD_DIRECTION_IMG, old.getBoolean(KEY_LOAD_DIRECTION_IMG, true)); + e.putString(KEY_GC_CUSTOM_DATE, old.getString(KEY_GC_CUSTOM_DATE, null)); + e.putInt(KEY_SHOW_WAYPOINTS_THRESHOLD, old.getInt(KEY_SHOW_WAYPOINTS_THRESHOLD, 0)); + e.putString(KEY_COOKIE_STORE, old.getString(KEY_COOKIE_STORE, null)); + e.putBoolean(KEY_OPEN_LAST_DETAILS_PAGE, old.getBoolean(KEY_OPEN_LAST_DETAILS_PAGE, false)); + e.putInt(KEY_LAST_DETAILS_PAGE, old.getInt(KEY_LAST_DETAILS_PAGE, 1)); + e.putInt(KEY_DEFAULT_NAVIGATION_TOOL, old.getInt(KEY_DEFAULT_NAVIGATION_TOOL, 0)); + e.putInt(KEY_DEFAULT_NAVIGATION_TOOL_2, old.getInt(KEY_DEFAULT_NAVIGATION_TOOL_2, 0)); + e.putInt(KEY_LIVE_MAP_STRATEGY, old.getInt(KEY_LIVE_MAP_STRATEGY, Strategy.AUTO.id)); + e.putBoolean(KEY_DEBUG, old.getBoolean(KEY_DEBUG, false)); + e.putBoolean(KEY_HIDE_LIVE_MAP_HINT, old.getInt(KEY_HIDE_LIVE_MAP_HINT, 0) != 0); + e.putInt(KEY_LIVE_MAP_HINT_SHOW_COUNT, old.getInt(KEY_LIVE_MAP_HINT_SHOW_COUNT, 0)); + + e.putInt(KEY_SETTINGS_VERSION, 1) ; // mark migrated + e.commit(); + } + } + public static void setLanguage(boolean useEnglish) { final Configuration config = new Configuration(); config.locale = useEnglish ? new Locale("en") : Locale.getDefault(); @@ -315,7 +384,7 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_MAP_LIVE, live ? 1 : 0); + edit.putBoolean(KEY_MAP_LIVE, live); } }); } @@ -371,15 +440,8 @@ public final class Settings { return commitResult; } - public static boolean isValidMapFile() { - return checkMapfile(getMapFile()); - } - - private static boolean checkMapfile(final String mapFileIn) { - if (null == mapFileIn) { - return false; - } - return MapDatabase.isValidMapFile(mapFileIn); + public static boolean isValidMapFile(final String mapFileIn) { + return MapsforgeMapProvider.isValidMapFile(mapFileIn); } public static coordInputFormatEnum getCoordInputFormat() { @@ -443,7 +505,7 @@ public final class Settings { } public static boolean isExcludeMyCaches() { - return 0 != sharedPrefs.getInt(KEY_EXCLUDE_OWN, 0); + return sharedPrefs.getBoolean(KEY_EXCLUDE_OWN, false); } /** @@ -463,7 +525,7 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_EXCLUDE_OWN, exclude ? 1 : 0); + edit.putBoolean(KEY_EXCLUDE_OWN, exclude); } }); } @@ -483,7 +545,7 @@ public final class Settings { } public static boolean isShowAddress() { - return 0 != sharedPrefs.getInt(KEY_SHOW_ADDRESS, 1); + return sharedPrefs.getBoolean(KEY_SHOW_ADDRESS, true); } public static void setShowAddress(final boolean showAddress) { @@ -491,7 +553,7 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_SHOW_ADDRESS, showAddress ? 1 : 0); + edit.putBoolean(KEY_SHOW_ADDRESS, showAddress); } }); } @@ -511,7 +573,7 @@ public final class Settings { } public static boolean isExcludeDisabledCaches() { - return 0 != sharedPrefs.getInt(KEY_EXCLUDE_DISABLED, 0); + return sharedPrefs.getBoolean(KEY_EXCLUDE_DISABLED, false); } public static void setExcludeDisabledCaches(final boolean exclude) { @@ -519,13 +581,13 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_EXCLUDE_DISABLED, exclude ? 1 : 0); + edit.putBoolean(KEY_EXCLUDE_DISABLED, exclude); } }); } public static boolean isStoreOfflineMaps() { - return 0 != sharedPrefs.getInt(KEY_USE_OFFLINEMAPS, 1); + return sharedPrefs.getBoolean(KEY_USE_OFFLINEMAPS, true); } public static void setStoreOfflineMaps(final boolean offlineMaps) { @@ -533,13 +595,13 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_USE_OFFLINEMAPS, offlineMaps ? 1 : 0); + edit.putBoolean(KEY_USE_OFFLINEMAPS, offlineMaps); } }); } public static boolean isStoreOfflineWpMaps() { - return 0 != sharedPrefs.getInt(KEY_USE_OFFLINEWPMAPS, 1); + return sharedPrefs.getBoolean(KEY_USE_OFFLINEWPMAPS, false); } public static void setStoreOfflineWpMaps(final boolean offlineMaps) { @@ -547,7 +609,7 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_USE_OFFLINEWPMAPS, offlineMaps ? 1 : 0); + edit.putBoolean(KEY_USE_OFFLINEWPMAPS, offlineMaps); } }); } @@ -567,7 +629,7 @@ public final class Settings { } public static boolean isUseGoogleNavigation() { - return 0 != sharedPrefs.getInt(KEY_USE_GOOGLE_NAVIGATION, 1); + return sharedPrefs.getBoolean(KEY_USE_GOOGLE_NAVIGATION, true); } public static void setUseGoogleNavigation(final boolean useGoogleNavigation) { @@ -575,13 +637,13 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_USE_GOOGLE_NAVIGATION, useGoogleNavigation ? 1 : 0); + edit.putBoolean(KEY_USE_GOOGLE_NAVIGATION, useGoogleNavigation); } }); } public static boolean isAutoLoadDescription() { - return 0 != sharedPrefs.getInt(KEY_LOAD_DESCRIPTION, 0); + return sharedPrefs.getBoolean(KEY_LOAD_DESCRIPTION, false); } public static void setAutoLoadDesc(final boolean autoLoad) { @@ -589,7 +651,7 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_LOAD_DESCRIPTION, autoLoad ? 1 : 0); + edit.putBoolean(KEY_LOAD_DESCRIPTION, autoLoad); } }); } @@ -641,7 +703,7 @@ public final class Settings { } public static boolean isLiveList() { - return 0 != sharedPrefs.getInt(KEY_LIVE_LIST, 1); + return sharedPrefs.getBoolean(KEY_LIVE_LIST, true); } public static void setLiveList(final boolean liveList) { @@ -649,13 +711,13 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_LIVE_LIST, liveList ? 1 : 0); + edit.putBoolean(KEY_LIVE_LIST, liveList); } }); } public static boolean isPublicLoc() { - return 0 != sharedPrefs.getInt(KEY_PUBLICLOC, 0); + return sharedPrefs.getBoolean(KEY_PUBLICLOC, false); } public static void setPublicLoc(final boolean publicLocation) { @@ -663,7 +725,7 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_PUBLICLOC, publicLocation ? 1 : 0); + edit.putBoolean(KEY_PUBLICLOC, publicLocation); } }); } @@ -697,7 +759,7 @@ public final class Settings { } public static boolean isUseMetricUnits() { - return sharedPrefs.getInt(KEY_METRIC_UNITS, unitsMetric) == unitsMetric; + return sharedPrefs.getBoolean(KEY_METRIC_UNITS, true); } public static void setUseMetricUnits(final boolean metric) { @@ -705,17 +767,17 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_METRIC_UNITS, metric ? unitsMetric : unitsImperial); + edit.putBoolean(KEY_METRIC_UNITS, metric); } }); } public static boolean isLiveMap() { - return sharedPrefs.getInt(KEY_MAP_LIVE, 1) != 0; + return sharedPrefs.getBoolean(KEY_MAP_LIVE, true); } public static boolean isMapTrail() { - return sharedPrefs.getInt(KEY_MAP_TRAIL, 1) != 0; + return sharedPrefs.getBoolean(KEY_MAP_TRAIL, true); } public static void setMapTrail(final boolean showTrail) { @@ -723,7 +785,7 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_MAP_TRAIL, showTrail ? 1 : 0); + edit.putBoolean(KEY_MAP_TRAIL, showTrail); } }); } @@ -786,7 +848,7 @@ public final class Settings { } public static boolean isUseCompass() { - return 0 != sharedPrefs.getInt(KEY_USE_COMPASS, 1); + return sharedPrefs.getBoolean(KEY_USE_COMPASS, true); } public static void setUseCompass(final boolean useCompass) { @@ -794,13 +856,13 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_USE_COMPASS, useCompass ? 1 : 0); + edit.putBoolean(KEY_USE_COMPASS, useCompass); } }); } public static boolean isHelpShown() { - return sharedPrefs.getInt(KEY_HELP_SHOWN, 0) != 0; + return sharedPrefs.getBoolean(KEY_HELP_SHOWN, false); } public static void setHelpShown() { @@ -808,13 +870,13 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_HELP_SHOWN, 1); + edit.putBoolean(KEY_HELP_SHOWN, true); } }); } public static boolean isLightSkin() { - return sharedPrefs.getInt(KEY_SKIN, 0) != 0; + return sharedPrefs.getBoolean(KEY_SKIN, false); } public static void setLightSkin(final boolean lightSkin) { @@ -822,7 +884,7 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_SKIN, lightSkin ? 1 : 0); + edit.putBoolean(KEY_SKIN, lightSkin); } }); } @@ -864,6 +926,12 @@ public final class Settings { return CacheType.getById(sharedPrefs.getString(KEY_CACHE_TYPE, CacheType.ALL.id)); } + /** + * The Threshold for the showing of child waypoints + * + * @return + */ + public static int getWayPointsThreshold() { return sharedPrefs.getInt(KEY_SHOW_WAYPOINTS_THRESHOLD, 0); } @@ -879,7 +947,7 @@ public final class Settings { } public static boolean isUseTwitter() { - return 0 != sharedPrefs.getInt(KEY_USE_TWITTER, 0); + return sharedPrefs.getBoolean(KEY_USE_TWITTER, false); } public static void setUseTwitter(final boolean useTwitter) { @@ -887,7 +955,7 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_USE_TWITTER, useTwitter ? 1 : 0); + edit.putBoolean(KEY_USE_TWITTER, useTwitter); } }); } @@ -1023,7 +1091,7 @@ public final class Settings { public static boolean isDebug() { - return cachedDebug; + return Log.isDebug(); } public static void setDebug(final boolean debug) { @@ -1033,11 +1101,11 @@ public final class Settings { edit.putBoolean(KEY_DEBUG, debug); } }); - cachedDebug = debug; + Log.setDebugUnsaved(debug); } public static boolean getHideLiveMapHint() { - return sharedPrefs.getInt(KEY_HIDE_LIVE_MAP_HINT, 0) == 0 ? false : true; + return sharedPrefs.getBoolean(KEY_HIDE_LIVE_MAP_HINT, false); } public static void setHideLiveHint(final boolean hide) { @@ -1045,7 +1113,7 @@ public final class Settings { @Override public void edit(Editor edit) { - edit.putInt(KEY_HIDE_LIVE_MAP_HINT, hide ? 1 : 0); + edit.putBoolean(KEY_HIDE_LIVE_MAP_HINT, hide); } }); } @@ -1063,4 +1131,9 @@ public final class Settings { } }); } + + public static String getPreferencesName() { + // there is currently no Android API to get the file name of the shared preferences + return cgeoapplication.getInstance().getPackageName() + "_preferences"; + } } diff --git a/main/src/cgeo/geocaching/StaticMapsActivity.java b/main/src/cgeo/geocaching/StaticMapsActivity.java index f9d023f..fdb6d67 100644 --- a/main/src/cgeo/geocaching/StaticMapsActivity.java +++ b/main/src/cgeo/geocaching/StaticMapsActivity.java @@ -78,7 +78,7 @@ public class StaticMapsActivity extends AbstractActivity { if (waitDialog != null) { waitDialog.dismiss(); } - Log.e(Settings.tag, "StaticMapsActivity.loadMapsHandler: " + e.toString()); + Log.e("StaticMapsActivity.loadMapsHandler: " + e.toString()); } } }; @@ -160,7 +160,7 @@ public class StaticMapsActivity extends AbstractActivity { } } } catch (Exception e) { - Log.e(Settings.tag, "StaticMapsActivity.LoadMapsThread.run.1: " + e.toString()); + Log.e("StaticMapsActivity.LoadMapsThread.run.1: " + e.toString()); } } @@ -179,14 +179,14 @@ public class StaticMapsActivity extends AbstractActivity { } } } catch (Exception e) { - Log.e(Settings.tag, "StaticMapsActivity.LoadMapsThread.run.2: " + e.toString()); + Log.e("StaticMapsActivity.LoadMapsThread.run.2: " + e.toString()); } } } loadMapsHandler.sendMessage(Message.obtain()); } catch (Exception e) { - Log.e(Settings.tag, "StaticMapsActivity.LoadMapsThread.run: " + e.toString()); + Log.e("StaticMapsActivity.LoadMapsThread.run: " + e.toString()); } } } diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 9c17a34..fc55949 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -1,10 +1,10 @@ package cgeo.geocaching; import cgeo.geocaching.concurrent.BlockingThreadPool; -import cgeo.geocaching.concurrent.Task; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.geopoint.GeopointFormatter.Format; import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.Log; import org.apache.commons.collections.CollectionUtils; @@ -30,7 +30,7 @@ public class StaticMapsProvider { return LocalStorage.getStorageFile(geocode, "map_" + prefix + level, false, createDirs); } - private static void downloadDifferentZooms(final cgCache cache, String markerUrl, String prefix, String latlonMap, int edge, String waypoints) { + private static void downloadDifferentZooms(final cgCache cache, String markerUrl, String prefix, String latlonMap, int edge, final Parameters waypoints) { downloadMap(cache, 20, "satellite", markerUrl, prefix, 1, latlonMap, edge, waypoints); downloadMap(cache, 18, "satellite", markerUrl, prefix, 2, latlonMap, edge, waypoints); downloadMap(cache, 16, "roadmap", markerUrl, prefix, 3, latlonMap, edge, waypoints); @@ -38,13 +38,22 @@ public class StaticMapsProvider { downloadMap(cache, 11, "roadmap", markerUrl, prefix, 5, latlonMap, edge, waypoints); } - private static void downloadMap(cgCache cache, int zoom, String mapType, String markerUrl, String prefix, int level, String latlonMap, int edge, String waypoints) { - final String mapUrl = "http://maps.google.com/maps/api/staticmap?center=" + latlonMap; - final String url = mapUrl + "&zoom=" + zoom + "&size=" + edge + "x" + edge + "&maptype=" + mapType + "&markers=icon%3A" + markerUrl + "%7C" + latlonMap + waypoints + "&sensor=false"; - final File file = getMapFile(cache.getGeocode(), prefix, level, true); - final HttpResponse httpResponse = Network.request(url, null, false); + private static void downloadMap(cgCache cache, int zoom, String mapType, String markerUrl, String prefix, int level, String latlonMap, int edge, final Parameters waypoints) { + final String mapUrl = "http://maps.google.com/maps/api/staticmap"; + final Parameters params = new Parameters( + "center", latlonMap, + "zoom", String.valueOf(zoom), + "size", edge + "x" + edge, + "maptype", mapType, + "markers", "icon:" + markerUrl + '|' + latlonMap, + "sensor", "false"); + if (waypoints != null) { + params.addAll(waypoints); + } + final HttpResponse httpResponse = Network.getRequest(mapUrl, params); if (httpResponse != null) { + final File file = getMapFile(cache.getGeocode(), prefix, level, true); if (LocalStorage.saveEntityToFile(httpResponse, file)) { // Delete image if it has no contents final long fileSize = file.length(); @@ -96,7 +105,7 @@ public class StaticMapsProvider { String wpLatlonMap = waypoint.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA); String wpMarkerUrl = getWpMarkerUrl(waypoint); // download map images in separate background thread for higher performance - downloadMaps(cache, wpMarkerUrl, "wp" + waypoint.getId() + "_", wpLatlonMap, edge, "", waitForResult); + downloadMaps(cache, wpMarkerUrl, "wp" + waypoint.getId() + "_", wpLatlonMap, edge, null, waitForResult); } public static void storeCacheStaticMap(cgCache cache, Activity activity, final boolean waitForResult) { @@ -106,22 +115,19 @@ public class StaticMapsProvider { private static void storeCacheStaticMap(cgCache cache, int edge, final boolean waitForResult) { final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA); - final StringBuilder waypoints = new StringBuilder(); + final Parameters waypoints = new Parameters(); if (cache.hasWaypoints()) { for (cgWaypoint waypoint : cache.getWaypoints()) { if (waypoint.getCoords() == null) { continue; } - String wpMarkerUrl = getWpMarkerUrl(waypoint); - waypoints.append("&markers=icon%3A"); - waypoints.append(wpMarkerUrl); - waypoints.append("%7C"); - waypoints.append(waypoint.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA)); + final String wpMarkerUrl = getWpMarkerUrl(waypoint); + waypoints.put("markers", "icon:" + wpMarkerUrl + "|" + waypoint.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA)); } } // download map images in separate background thread for higher performance final String cacheMarkerUrl = getCacheMarkerUrl(cache); - downloadMaps(cache, cacheMarkerUrl, "", latlonMap, edge, waypoints.toString(), waitForResult); + downloadMaps(cache, cacheMarkerUrl, "", latlonMap, edge, waypoints, waitForResult); } private static int guessMinDisplaySide(Display display) { @@ -141,12 +147,12 @@ public class StaticMapsProvider { } private static void downloadMaps(final cgCache cache, final String markerUrl, final String prefix, final String latlonMap, final int edge, - final String waypoints, boolean waitForResult) { + final Parameters waypoints, boolean waitForResult) { if (waitForResult) { downloadDifferentZooms(cache, markerUrl, prefix, latlonMap, edge, waypoints); } else { - Task currentTask = new Task("getting static map") { + final Runnable currentTask = new Runnable() { @Override public void run() { downloadDifferentZooms(cache, markerUrl, prefix, latlonMap, edge, waypoints); @@ -155,7 +161,7 @@ public class StaticMapsProvider { try { pool.add(currentTask, 20, TimeUnit.SECONDS); } catch (InterruptedException e) { - Log.e(Settings.tag, "StaticMapsProvider.downloadMaps error adding task: " + e.toString()); + Log.e("StaticMapsProvider.downloadMaps error adding task: " + e.toString()); } } } @@ -168,12 +174,12 @@ public class StaticMapsProvider { type += "_disabled"; } - return Network.urlencode_rfc3986(MARKERS_URL + "marker_cache_" + type + ".png"); + return MARKERS_URL + "marker_cache_" + type + ".png"; } private static String getWpMarkerUrl(final cgWaypoint waypoint) { String type = waypoint.getWaypointType() != null ? waypoint.getWaypointType().id : null; - return Network.urlencode_rfc3986(MARKERS_URL + "marker_waypoint_" + type + ".png"); + return MARKERS_URL + "marker_waypoint_" + type + ".png"; } public static void removeWpStaticMaps(int wp_id, String geocode) { @@ -183,7 +189,7 @@ public class StaticMapsProvider { StaticMapsProvider.getMapFile(geocode, "wp" + wp_id + "_", level, false).delete(); } } catch (Exception e) { - Log.e(Settings.tag, "StaticMapsProvider.removeWpStaticMaps: " + e.toString()); + Log.e("StaticMapsProvider.removeWpStaticMaps: " + e.toString()); } } } diff --git a/main/src/cgeo/geocaching/StoredList.java b/main/src/cgeo/geocaching/StoredList.java index 3b5a47a..fc03b26 100644 --- a/main/src/cgeo/geocaching/StoredList.java +++ b/main/src/cgeo/geocaching/StoredList.java @@ -1,5 +1,19 @@ package cgeo.geocaching; +import cgeo.geocaching.activity.IAbstractActivity; +import cgeo.geocaching.utils.RunnableWithArgument; + +import org.apache.commons.lang3.StringUtils; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.res.Resources; +import android.view.View; +import android.widget.EditText; + +import java.util.ArrayList; +import java.util.List; public class StoredList { public static final int TEMPORARY_LIST_ID = 0; @@ -18,4 +32,108 @@ public class StoredList { public String getTitleAndCount() { return title + " [" + count + "]"; } + + public static class UserInterface { + private final IAbstractActivity activity; + private final cgeoapplication app; + private final Resources res; + + public UserInterface(final IAbstractActivity activity) { + this.activity = activity; + app = cgeoapplication.getInstance(); + res = app.getResources(); + } + + public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards) { + final List<StoredList> lists = app.getLists(); + + if (lists == null) { + return; + } + + final List<CharSequence> listsTitle = new ArrayList<CharSequence>(); + for (StoredList list : lists) { + listsTitle.add(list.getTitleAndCount()); + } + listsTitle.add("<" + res.getString(R.string.list_menu_create) + ">"); + + final CharSequence[] items = new CharSequence[listsTitle.size()]; + + AlertDialog.Builder builder = new AlertDialog.Builder((Activity) activity); + builder.setTitle(res.getString(titleId)); + builder.setItems(listsTitle.toArray(items), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialogInterface, int itemId) { + if (itemId >= lists.size()) { + // create new list on the fly + promptForListCreation(runAfterwards); + } + else { + if (runAfterwards != null) { + runAfterwards.run(lists.get(itemId).id); + } + } + } + }); + builder.create().show(); + } + + public void promptForListCreation(final RunnableWithArgument<Integer> runAfterwards) { + handleListNameInput("", R.string.list_dialog_create_title, R.string.list_dialog_create, new RunnableWithArgument<String>() { + + @Override + public void run(final String listName) { + final int newId = app.createList(listName); + + if (newId >= 10) { + activity.showToast(res.getString(R.string.list_dialog_create_ok)); + if (runAfterwards != null) { + runAfterwards.run(newId); + } + } else { + activity.showToast(res.getString(R.string.list_dialog_create_err)); + } + } + }); + } + + private void handleListNameInput(final String defaultValue, int dialogTitle, int buttonTitle, final RunnableWithArgument<String> runnable) { + final AlertDialog.Builder alert = new AlertDialog.Builder((Activity) activity); + final View view = ((Activity) activity).getLayoutInflater().inflate(R.layout.list_create_dialog, null); + final EditText input = (EditText) view.findViewById(R.id.text); + input.setText(defaultValue); + + alert.setTitle(dialogTitle); + alert.setView(view); + alert.setPositiveButton(buttonTitle, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + // remove whitespaces added by autocompletion of Android keyboard + String listName = StringUtils.trim(input.getText().toString()); + if (StringUtils.isNotBlank(listName)) { + runnable.run(listName); + } + } + }); + alert.setNegativeButton(res.getString(R.string.list_dialog_cancel), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + dialog.dismiss(); + } + }); + + alert.show(); + } + + public void promptForListRename(final int listId, final Runnable runAfterRename) { + final StoredList list = app.getList(listId); + handleListNameInput(list.title, R.string.list_dialog_rename_title, R.string.list_dialog_rename, new RunnableWithArgument<String>() { + + @Override + public void run(final String listName) { + app.renameList(listId, listName); + if (runAfterRename != null) { + runAfterRename.run(); + } + } + }); + } + } } diff --git a/main/src/cgeo/geocaching/TrackableLog.java b/main/src/cgeo/geocaching/TrackableLog.java new file mode 100644 index 0000000..8e2ad90 --- /dev/null +++ b/main/src/cgeo/geocaching/TrackableLog.java @@ -0,0 +1,18 @@ +package cgeo.geocaching; + +import cgeo.geocaching.enumerations.LogTypeTrackable; + +public final class TrackableLog { + public TrackableLog(String trackCode, String name, int id, int ctl) { + this.trackCode = trackCode; + this.name = name; + this.id = id; + this.ctl = ctl; + } + + public final int ctl; + public final int id; + public final String trackCode; + public final String name; + public LogTypeTrackable action = LogTypeTrackable.DO_NOTHING; // base.logTrackablesAction - no action +} diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java index a471483..a2fde26 100644 --- a/main/src/cgeo/geocaching/VisitCacheActivity.java +++ b/main/src/cgeo/geocaching/VisitCacheActivity.java @@ -1,6 +1,8 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.connector.gc.GCParser; +import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; @@ -8,11 +10,11 @@ import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.LogTypeTrackable; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.gcvote.GCVote; -import cgeo.geocaching.network.Login; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.twitter.Twitter; import cgeo.geocaching.ui.DateDialog; +import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate; @@ -64,7 +66,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D private List<LogType> possibleLogTypes = new ArrayList<LogType>(); private String[] viewstates = null; private boolean gettingViewstate = true; - private List<cgTrackableLog> trackables = null; + private List<TrackableLog> trackables = null; private Calendar date = Calendar.getInstance(); private LogType typeSelected = LogType.LOG_UNKNOWN; private int attempts = 0; @@ -88,13 +90,13 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D showToast(res.getString(R.string.info_log_type_changed)); } - if (cgBase.isEmpty(viewstates) && attempts < 2) { + if (Login.isEmpty(viewstates) && attempts < 2) { final LoadDataThread thread; thread = new LoadDataThread(); thread.start(); return; - } else if (cgBase.isEmpty(viewstates) && attempts >= 2) { + } else if (Login.isEmpty(viewstates) && attempts >= 2) { showToast(res.getString(R.string.err_log_load_data)); showProgress(false); @@ -114,7 +116,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D final LinearLayout inventoryView = (LinearLayout) findViewById(R.id.inventory); inventoryView.removeAllViews(); - for (cgTrackableLog tb : trackables) { + for (TrackableLog tb : trackables) { LinearLayout inventoryItem = (LinearLayout) inflater.inflate(R.layout.visit_trackable, null); ((TextView) inventoryItem.findViewById(R.id.trackcode)).setText(tb.trackCode); @@ -370,7 +372,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D if (viewId == R.id.type) { for (final LogType typeOne : possibleLogTypes) { menu.add(viewId, typeOne.id, 0, typeOne.getL10n()); - Log.w(Settings.tag, "Adding " + typeOne + " " + typeOne.getL10n()); + Log.w("Adding " + typeOne + " " + typeOne.getL10n()); } } else if (viewId == R.id.changebutton) { final int textId = ((TextView) findViewById(viewId)).getId(); @@ -382,7 +384,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D } else { final int realViewId = ((LinearLayout) findViewById(viewId)).getId(); - for (final cgTrackableLog tb : trackables) { + for (final TrackableLog tb : trackables) { if (tb.id == realViewId) { menu.setHeaderTitle(tb.name); } @@ -419,14 +421,14 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D } tbText.setText(res.getString(logType.resourceId) + " โผ"); } - for (cgTrackableLog tb : trackables) { + for (TrackableLog tb : trackables) { tb.action = logType; } tbChanged = true; return true; } } catch (Exception e) { - Log.e(Settings.tag, "cgeovisit.onContextItemSelected: " + e.toString()); + Log.e("cgeovisit.onContextItemSelected: " + e.toString()); } } else { try { @@ -442,21 +444,21 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D return false; } - for (cgTrackableLog tb : trackables) { + for (TrackableLog tb : trackables) { if (tb.id == group) { tbChanged = true; tb.action = logType; tbText.setText(res.getString(logType.resourceId) + " โผ"); - Log.i(Settings.tag, "Trackable " + tb.trackCode + " (" + tb.name + ") has new action: #" + id); + Log.i("Trackable " + tb.trackCode + " (" + tb.name + ") has new action: #" + id); } } return true; } } catch (Exception e) { - Log.e(Settings.tag, "cgeovisit.onContextItemSelected: " + e.toString()); + Log.e("cgeovisit.onContextItemSelected: " + e.toString()); } } @@ -475,7 +477,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D possibleLogTypes = cache.getPossibleLogTypes(); - final cgLog log = app.loadLogOffline(geocode); + final LogEntry log = app.loadLogOffline(geocode); if (log != null) { typeSelected = log.type; date.setTime(new Date(log.date)); @@ -507,7 +509,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D }); final Button dateButton = (Button) findViewById(R.id.date); - dateButton.setText(cgBase.formatShortDate(date.getTime().getTime())); + dateButton.setText(Formatter.formatShortDate(date.getTime().getTime())); dateButton.setOnClickListener(new DateListener()); final EditText logView = (EditText) findViewById(R.id.log); @@ -522,7 +524,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D lastState.restore(this); } - if (cgBase.isEmpty(viewstates)) { + if (Login.isEmpty(viewstates)) { enablePostButton(false); new LoadDataThread().start(); } else { @@ -545,7 +547,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D date = dateIn; final Button dateButton = (Button) findViewById(R.id.date); - dateButton.setText(cgBase.formatShortDate(date.getTime().getTime())); + dateButton.setText(Formatter.formatShortDate(date.getTime().getTime())); } public void setType(LogType type) { @@ -609,7 +611,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D setType(typeSelected); final Button dateButton = (Button) findViewById(R.id.date); - dateButton.setText(cgBase.formatShortDate(date.getTime().getTime())); + dateButton.setText(Formatter.formatShortDate(date.getTime().getTime())); dateButton.setOnClickListener(new DateListener()); final EditText logView = (EditText) findViewById(R.id.log); @@ -656,19 +658,19 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D return; } - final String page = Network.getResponseData(Network.request("http://www.geocaching.com/seek/log.aspx", params, false, false, false)); + final String page = Network.getResponseData(Network.getRequest("http://www.geocaching.com/seek/log.aspx", params)); viewstates = Login.getViewstates(page); - trackables = cgBase.parseTrackableLog(page); + trackables = GCParser.parseTrackableLog(page); - final List<LogType> typesPre = cgBase.parseTypes(page); + final List<LogType> typesPre = GCParser.parseTypes(page); if (CollectionUtils.isNotEmpty(typesPre)) { possibleLogTypes.clear(); possibleLogTypes.addAll(typesPre); possibleLogTypes.remove(LogType.LOG_UPDATE_COORDINATES); } } catch (Exception e) { - Log.e(Settings.tag, "cgeovisit.loadData.run: " + e.toString()); + Log.e("cgeovisit.loadData.run: " + e.toString()); } loadDataHandler.sendEmptyMessage(0); @@ -695,12 +697,12 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D public StatusCode postLogFn(String log) { try { - final StatusCode status = cgBase.postLog(geocode, cacheid, viewstates, typeSelected, + final StatusCode status = GCParser.postLog(geocode, cacheid, viewstates, typeSelected, date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), log, trackables); if (status == StatusCode.NO_ERROR) { - final cgLog logNow = new cgLog(); + final LogEntry logNow = new LogEntry(); logNow.author = Settings.getUsername(); logNow.date = date.getTimeInMillis(); logNow.type = typeSelected; @@ -741,7 +743,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D return status; } catch (Exception e) { - Log.e(Settings.tag, "cgeovisit.postLogFn: " + e.toString()); + Log.e("cgeovisit.postLogFn: " + e.toString()); } return StatusCode.LOG_POST_ERROR; @@ -765,7 +767,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D private class ActivityState { private final String[] viewstates; - private final List<cgTrackableLog> trackables; + private final List<TrackableLog> trackables; private final int attempts; private final List<LogType> possibleLogTypes; private final LogType typeSelected; diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index 8e8ad9d..8ddd21a 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -2,11 +2,10 @@ package cgeo.geocaching.activity; import cgeo.geocaching.R; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.compatibility.Compatibility; -import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.Cookies; import android.app.Activity; import android.content.Context; @@ -85,10 +84,8 @@ public abstract class AbstractActivity extends Activity implements IAbstractActi res = this.getResources(); app = (cgeoapplication) this.getApplication(); - cgBase.initialize(app); - // Restore cookie store if needed - Network.restoreCookieStore(Settings.getCookieStore()); + Cookies.restoreCookieStore(Settings.getCookieStore()); ActivityMixin.keepScreenOn(this, keepScreenOn); } @@ -131,7 +128,7 @@ public abstract class AbstractActivity extends Activity implements IAbstractActi /** * insert text into the EditText at the current cursor position - * + * * @param editText * @param insertText * @param moveCursor diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java index b3bbb3f..7af75b8 100644 --- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java @@ -1,6 +1,5 @@ package cgeo.geocaching.activity; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.compatibility.Compatibility; @@ -73,7 +72,6 @@ public abstract class AbstractListActivity extends ListActivity implements // init res = this.getResources(); app = (cgeoapplication) this.getApplication(); - cgBase.initialize(app); ActivityMixin.keepScreenOn(this, keepScreenOn); } diff --git a/main/src/cgeo/geocaching/activity/IAbstractActivity.java b/main/src/cgeo/geocaching/activity/IAbstractActivity.java index dd22cff..2503b99 100644 --- a/main/src/cgeo/geocaching/activity/IAbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/IAbstractActivity.java @@ -1,8 +1,5 @@ package cgeo.geocaching.activity; -import cgeo.geocaching.cgCache; - -import android.view.Menu; import android.view.View; public interface IAbstractActivity { @@ -13,19 +10,11 @@ public interface IAbstractActivity { public void goManual(View view); - public void showProgress(final boolean show); - - public void setTheme(); - public void showToast(String text); public void showShortToast(String text); public void helpDialog(String title, String message); - public void setTitle(final String title); - - void addVisitMenu(Menu menu, cgCache cache); - public void invalidateOptionsMenuCompatible(); } diff --git a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java index 1ccf8dc..80e2dac 100644 --- a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java +++ b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java @@ -1,7 +1,6 @@ package cgeo.geocaching.apps; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgWaypoint; import cgeo.geocaching.enumerations.CacheSize; @@ -112,7 +111,7 @@ public abstract class AbstractLocusApp extends AbstractApp { } // create one simple point with location - final Location loc = new Location(Settings.tag); + final Location loc = new Location("cgeo"); loc.setLatitude(cache.getCoords().getLatitude()); loc.setLongitude(cache.getCoords().getLongitude()); @@ -191,7 +190,7 @@ public abstract class AbstractLocusApp extends AbstractApp { } // create one simple point with location - final Location loc = new Location(Settings.tag); + final Location loc = new Location("cgeo"); loc.setLatitude(waypoint.getCoords().getLatitude()); loc.setLongitude(waypoint.getCoords().getLongitude()); diff --git a/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java b/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java index df5e991..49db025 100644 --- a/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java +++ b/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java @@ -1,6 +1,5 @@ package cgeo.geocaching.apps.cache; -import cgeo.geocaching.Settings; import cgeo.geocaching.cgCache; import cgeo.geocaching.apps.AbstractAppFactory; import cgeo.geocaching.utils.Log; @@ -37,7 +36,7 @@ public final class GeneralAppsFactory extends AbstractAppFactory { try { return app.invoke(activity, cache); } catch (Exception e) { - Log.e(Settings.tag, "GeneralAppsFactory.onMenuItemSelected: " + e.toString()); + Log.e("GeneralAppsFactory.onMenuItemSelected: " + e.toString()); } } return false; diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java index 878bbb8..24aa693 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java @@ -1,7 +1,6 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.utils.Log; @@ -32,7 +31,7 @@ class GoogleMapsApp extends AbstractPointNavigationApp { } catch (Exception e) { // nothing } - Log.i(Settings.tag, "cgBase.runExternalMap: No maps application available."); + Log.i("cgBase.runExternalMap: No maps application available."); ActivityMixin.showToast(activity, getString(R.string.err_application_no)); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java index a3d335c..74141c3 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java @@ -84,8 +84,7 @@ class GoogleNavigationApp extends AbstractNavigationApp { // nothing } - Log.i(Settings.tag, - "cgBase.runNavigation: No navigation application available."); + Log.i("cgBase.runNavigation: No navigation application available."); return false; } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java index 8bb54b7..052189a 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java @@ -19,10 +19,7 @@ import android.app.AlertDialog; import android.content.DialogInterface; import android.view.Menu; import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; import android.widget.ArrayAdapter; -import android.widget.TextView; import java.util.ArrayList; import java.util.List; @@ -66,6 +63,16 @@ public final class NavigationAppFactory extends AbstractAppFactory { * The id - used in c:geo settings */ public final int id; + + /* + * display app name in array adapter + * + * @see java.lang.Enum#toString() + */ + @Override + public String toString() { + return app.getName(); + } } /** @@ -127,24 +134,9 @@ public final class NavigationAppFactory extends AbstractAppFactory { } /* * Using an ArrayAdapter with list of NavigationAppsEnum items avoids - * handling between mapping list positions allows us to do dynamic filtering of the list based on usecase. + * handling between mapping list positions allows us to do dynamic filtering of the list based on use case. */ - final ArrayAdapter<NavigationAppsEnum> adapter = new ArrayAdapter<NavigationAppsEnum>(activity, android.R.layout.select_dialog_item, items) { - @Override - public View getView(int position, View convertView, ViewGroup parent) { - TextView textView = (TextView) super.getView(position, convertView, parent); - textView.setText(getItem(position).app.getName()); - return textView; - } - - @Override - public View getDropDownView(int position, View convertView, ViewGroup parent) { - TextView textView = (TextView) super.getDropDownView(position, convertView, parent); - textView.setText(getItem(position).app.getName()); - return textView; - } - }; - adapter.setDropDownViewResource(android.R.layout.select_dialog_item); + final ArrayAdapter<NavigationAppsEnum> adapter = new ArrayAdapter<NavigationAppsEnum>(activity, android.R.layout.select_dialog_item, items); builder.setAdapter(adapter, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { @@ -257,7 +249,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { try { return app.invoke(geo, activity, cache, waypoint, destination); } catch (Exception e) { - Log.e(Settings.tag, "NavigationAppFactory.onMenuItemSelected: " + e.toString()); + Log.e("NavigationAppFactory.onMenuItemSelected: " + e.toString()); } } return false; @@ -291,14 +283,14 @@ public final class NavigationAppFactory extends AbstractAppFactory { try { app.invoke(geo, activity, cache, waypoint, destination); } catch (Exception e) { - Log.e(Settings.tag, "NavigationAppFactory.startDefaultNavigationApplication: " + e.toString()); + Log.e("NavigationAppFactory.startDefaultNavigationApplication: " + e.toString()); } } } /** * Starts the second default navigation tool if correctly set and installed or the compass app as default fallback. - * + * * @param geo * @param activity * @param cache @@ -314,14 +306,14 @@ public final class NavigationAppFactory extends AbstractAppFactory { try { app.invoke(geo, activity, cache, waypoint, destination); } catch (Exception e) { - Log.e(Settings.tag, "NavigationAppFactory.startDefaultNavigationApplication2: " + e.toString()); + Log.e("NavigationAppFactory.startDefaultNavigationApplication2: " + e.toString()); } } } /** * Returns the default navigation tool if correctly set and installed or the compass app as default fallback - * + * * @param activity * @return never <code>null</code> */ @@ -341,7 +333,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Returns the second default navigation tool if correctly set and installed or the compass app as default fallback - * + * * @param activity * @return never <code>null</code> */ diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java index a73ac4d..c8f201d 100644 --- a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java +++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java @@ -2,7 +2,6 @@ package cgeo.geocaching.apps.cachelist; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; -import cgeo.geocaching.Settings; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgGeo; import cgeo.geocaching.activity.IAbstractActivity; @@ -73,7 +72,7 @@ public final class CacheListAppFactory extends AbstractAppFactory { activity.invalidateOptionsMenuCompatible(); return result; } catch (Exception e) { - Log.e(Settings.tag, "CacheListAppFactory.onMenuItemSelected: " + e.toString()); + Log.e("CacheListAppFactory.onMenuItemSelected: " + e.toString()); } } return false; diff --git a/main/src/cgeo/geocaching/backup/CentralBackupAgent.java b/main/src/cgeo/geocaching/backup/CentralBackupAgent.java index 28b9e4b..aef2b7b 100644 --- a/main/src/cgeo/geocaching/backup/CentralBackupAgent.java +++ b/main/src/cgeo/geocaching/backup/CentralBackupAgent.java @@ -7,11 +7,11 @@ import android.app.backup.SharedPreferencesBackupHelper; public class CentralBackupAgent extends BackupAgentHelper { - static final String PREFS_BACKUP_KEY = "prefs"; + private static final String PREFS_BACKUP_KEY = "prefs"; @Override public void onCreate() { - SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, Settings.preferences); + final SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, Settings.getPreferencesName()); addHelper(PREFS_BACKUP_KEY, helper); } diff --git a/main/src/cgeo/geocaching/cgCache.java b/main/src/cgeo/geocaching/cgCache.java index beffa85..f95fb2c 100644 --- a/main/src/cgeo/geocaching/cgCache.java +++ b/main/src/cgeo/geocaching/cgCache.java @@ -9,12 +9,14 @@ import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; +import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.geopoint.GeopointParser; +import cgeo.geocaching.network.HtmlImage; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; @@ -27,6 +29,8 @@ import android.content.Intent; import android.content.res.Resources; import android.net.Uri; import android.os.Handler; +import android.os.Message; +import android.text.Html; import android.text.Spannable; import java.util.ArrayList; @@ -88,7 +92,7 @@ public class cgCache implements ICache, IWaypoint { private List<String> attributes = null; private List<cgWaypoint> waypoints = null; private ArrayList<cgImage> spoilers = null; - private List<cgLog> logs = null; + private List<LogEntry> logs = null; private List<cgTrackable> inventory = null; private Map<LogType, Integer> logCounts = new HashMap<LogType, Integer>(); private boolean logOffline = false; @@ -100,7 +104,7 @@ public class cgCache implements ICache, IWaypoint { private String nameForSorting; private final EnumSet<StorageLocation> storageLocation = EnumSet.of(StorageLocation.HEAP); private boolean finalDefined = false; - private int zoomlevel = Tile.ZOOMLEVEL_MAX; + private int zoomlevel = Tile.ZOOMLEVEL_MAX + 1; private static final Pattern NUMBER_PATTERN = Pattern.compile("\\d+"); @@ -298,18 +302,10 @@ public class cgCache implements ICache, IWaypoint { * @param other * @return true if both caches have the same content */ - public boolean isEqualTo(cgCache other) { - if (other == null) { - return false; - } - - if ( - // updated - // detailedUpdate - // visitedDate - detailed == other.detailed && - geocode.equalsIgnoreCase(other.geocode) && - name.equalsIgnoreCase(other.name) && + private boolean isEqualTo(final cgCache other) { + return detailed == other.detailed && + StringUtils.equalsIgnoreCase(geocode, other.geocode) && + StringUtils.equalsIgnoreCase(name, other.name) && cacheType == other.cacheType && size == other.size && found == other.found && @@ -317,25 +313,25 @@ public class cgCache implements ICache, IWaypoint { premiumMembersOnly == other.premiumMembersOnly && difficulty == other.difficulty && terrain == other.terrain && - (coords != null ? coords.isEqualTo(other.coords) : coords == other.coords) && + (coords != null ? coords.equals(other.coords) : null == other.coords) && reliableLatLon == other.reliableLatLon && disabled == other.disabled && archived == other.archived && listId == other.listId && - owner.equalsIgnoreCase(other.owner) && - ownerReal.equalsIgnoreCase(other.ownerReal) && - (description != null ? description.equalsIgnoreCase(other.description) : null == other.description) && - (personalNote != null ? personalNote.equalsIgnoreCase(other.personalNote) : null == other.personalNote) && - shortdesc.equalsIgnoreCase(other.shortdesc) && - latlon.equalsIgnoreCase(other.latlon) && - location.equalsIgnoreCase(other.location) && + StringUtils.equalsIgnoreCase(owner, other.owner) && + StringUtils.equalsIgnoreCase(ownerReal, other.ownerReal) && + StringUtils.equalsIgnoreCase(description, other.description) && + StringUtils.equalsIgnoreCase(personalNote, other.personalNote) && + StringUtils.equalsIgnoreCase(shortdesc, other.shortdesc) && + StringUtils.equalsIgnoreCase(latlon, other.latlon) && + StringUtils.equalsIgnoreCase(location, other.location) && favorite == other.favorite && favoritePoints == other.favoritePoints && onWatchlist == other.onWatchlist && - (hidden != null ? hidden.compareTo(other.hidden) == 0 : hidden == other.hidden) && - guid.equalsIgnoreCase(other.guid) && - hint.equalsIgnoreCase(other.hint) && - cacheId.equalsIgnoreCase(other.cacheId) && + (hidden != null ? hidden.equals(other.hidden) : null == other.hidden) && + StringUtils.equalsIgnoreCase(guid, other.guid) && + StringUtils.equalsIgnoreCase(hint, other.hint) && + StringUtils.equalsIgnoreCase(cacheId, other.cacheId) && (direction != null ? direction.equals(other.direction) : null == other.direction) && (distance != null ? distance.equals(other.distance) : null == other.distance) && (elevation != null ? elevation.equals(other.elevation) : null == other.elevation) && @@ -351,10 +347,7 @@ public class cgCache implements ICache, IWaypoint { inventory == other.inventory && logCounts == other.logCounts && logOffline == other.logOffline && - finalDefined == other.finalDefined) { - return true; - } - return false; + finalDefined == other.finalDefined; } public boolean hasTrackables() { @@ -393,7 +386,7 @@ public class cgCache implements ICache, IWaypoint { * * @return true: page contains guid of cache, false: otherwise */ - boolean isGuidContainedInPage(final String page) { + public boolean isGuidContainedInPage(final String page) { if (StringUtils.isBlank(page)) { return false; } @@ -404,17 +397,16 @@ public class cgCache implements ICache, IWaypoint { Pattern patternOk = Pattern.compile(guid, Pattern.CASE_INSENSITIVE); Matcher matcherOk = patternOk.matcher(page); if (matcherOk.find()) { - Log.i(Settings.tag, "cgCache.isGuidContainedInPage: guid '" + guid + "' found"); + Log.i("cgCache.isGuidContainedInPage: guid '" + guid + "' found"); return true; } else { - Log.i(Settings.tag, "cgCache.isGuidContainedInPage: guid '" + guid + "' not found"); + Log.i("cgCache.isGuidContainedInPage: guid '" + guid + "' not found"); return false; } } public boolean isEventCache() { - return CacheType.EVENT == cacheType || CacheType.MEGA_EVENT == cacheType - || CacheType.CITO == cacheType || CacheType.LOSTANDFOUND == cacheType; + return cacheType.isEvent(); } public boolean logVisit(IAbstractActivity fromActivity) { @@ -534,16 +526,6 @@ public class cgCache implements ICache, IWaypoint { } @Override - public String getLatitude() { - return coords != null ? coords.format(GeopointFormatter.Format.LAT_DECMINUTE) : null; - } - - @Override - public String getLongitude() { - return coords != null ? coords.format(GeopointFormatter.Format.LON_DECMINUTE) : null; - } - - @Override public String getOwner() { return owner; } @@ -956,7 +938,7 @@ public class cgCache implements ICache, IWaypoint { return false; } - public List<cgLog> getLogs() { + public List<LogEntry> getLogs() { return getLogs(true); } @@ -965,15 +947,15 @@ public class cgCache implements ICache, IWaypoint { * true for all logs, false for friend logs only * @return the logs with all entries or just the entries of the friends, never <code>null</code> */ - public List<cgLog> getLogs(boolean allLogs) { + public List<LogEntry> getLogs(boolean allLogs) { if (logs == null) { return Collections.emptyList(); } if (allLogs) { return logs; } - ArrayList<cgLog> friendLogs = new ArrayList<cgLog>(); - for (cgLog log : logs) { + ArrayList<LogEntry> friendLogs = new ArrayList<LogEntry>(); + for (LogEntry log : logs) { if (log.friend) { friendLogs.add(log); } @@ -985,7 +967,7 @@ public class cgCache implements ICache, IWaypoint { * @param logs * the log entries */ - public void setLogs(List<cgLog> logs) { + public void setLogs(List<LogEntry> logs) { this.logs = logs; } @@ -1361,7 +1343,7 @@ public class cgCache implements ICache, IWaypoint { matcher = coordPattern.matcher(note); } } catch (Exception e) { - Log.e(Settings.tag, "cgCache.parseWaypointsFromNote: " + e.toString()); + Log.e("cgCache.parseWaypointsFromNote: " + e.toString()); } } @@ -1376,16 +1358,16 @@ public class cgCache implements ICache, IWaypoint { return attributes != null && attributes.size() > 0; } - public void prependLog(final cgLog log) { + public void prependLog(final LogEntry log) { if (logs == null) { - logs = new ArrayList<cgLog>(); + logs = new ArrayList<LogEntry>(); } logs.add(0, log); } - public void appendLog(final cgLog log) { + public void appendLog(final LogEntry log) { if (logs == null) { - logs = new ArrayList<cgLog>(); + logs = new ArrayList<LogEntry>(); } logs.add(log); } @@ -1414,17 +1396,13 @@ public class cgCache implements ICache, IWaypoint { if (!(obj instanceof cgCache)) { return false; } - // just compare the geocode even if that is not what "equals" normaly does - return geocode != null ? geocode.compareTo(((cgCache) obj).geocode) == 0 : false; + // just compare the geocode even if that is not what "equals" normally does + return StringUtils.isNotBlank(geocode) ? geocode.equals(((cgCache) obj).geocode) : false; } public void store(Activity activity, CancellableHandler handler) { final int listId = Math.max(getListId(), StoredList.STANDARD_LIST_ID); - cgBase.storeCache(activity, this, null, listId, false, handler); - } - - public int getZoomlevel() { - return this.zoomlevel; + storeCache(activity, this, null, listId, false, handler); } public void setZoomlevel(int zoomlevel) { @@ -1445,4 +1423,171 @@ public class cgCache implements ICache, IWaypoint { public String getCoordType() { return "cache"; } + + public void drop(Handler handler) { + try { + cgeoapplication.getInstance().markDropped(getGeocode()); + cgeoapplication.getInstance().removeCache(getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE)); + + handler.sendMessage(Message.obtain()); + } catch (Exception e) { + Log.e("cache.drop: ", e); + } + } + + public void checkFields() { + if (StringUtils.isBlank(getGeocode())) { + Log.e("cgBase.loadLogsFromDetails: geo code not parsed correctly"); + } + if (StringUtils.isBlank(getName())) { + Log.e("name not parsed correctly"); + } + if (StringUtils.isBlank(getGuid())) { + Log.e("guid not parsed correctly"); + } + if (getTerrain() == 0.0) { + Log.e("terrain not parsed correctly"); + } + if (getDifficulty() == 0.0) { + Log.e("difficulty not parsed correctly"); + } + if (StringUtils.isBlank(getOwner())) { + Log.e("owner not parsed correctly"); + } + if (StringUtils.isBlank(getOwnerReal())) { + Log.e("owner real not parsed correctly"); + } + if (getHiddenDate() == null) { + Log.e("hidden not parsed correctly"); + } + if (getFavoritePoints() < 0) { + Log.e("favoriteCount not parsed correctly"); + } + if (getSize() == null) { + Log.e("size not parsed correctly"); + } + if (getType() == null || getType() == CacheType.UNKNOWN) { + Log.e("type not parsed correctly"); + } + if (getCoords() == null) { + Log.e("coordinates not parsed correctly"); + } + if (StringUtils.isBlank(getLocation())) { + Log.e("location not parsed correctly"); + } + } + + public void refresh(Activity activity, int newListId, CancellableHandler handler) { + cgeoapplication.getInstance().removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); + storeCache(activity, null, geocode, newListId, true, handler); + } + + public static void storeCache(Activity activity, cgCache origCache, String geocode, int listId, boolean forceRedownload, CancellableHandler handler) { + try { + cgCache cache; + // get cache details, they may not yet be complete + if (origCache != null) { + // only reload the cache if it was already stored or doesn't have full details (by checking the description) + if (origCache.getListId() >= StoredList.STANDARD_LIST_ID || StringUtils.isBlank(origCache.getDescription())) { + final SearchResult search = searchByGeocode(origCache.getGeocode(), null, listId, false, handler); + cache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); + } else { + cache = origCache; + } + } else if (StringUtils.isNotBlank(geocode)) { + final SearchResult search = searchByGeocode(geocode, null, listId, forceRedownload, handler); + cache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); + } else { + cache = null; + } + + if (cache == null) { + if (handler != null) { + handler.sendMessage(Message.obtain()); + } + + return; + } + + if (CancellableHandler.isCancelled(handler)) { + return; + } + + final HtmlImage imgGetter = new HtmlImage(activity, cache.getGeocode(), false, listId, true); + + // store images from description + if (StringUtils.isNotBlank(cache.getDescription())) { + Html.fromHtml(cache.getDescription(), imgGetter, null); + } + + if (CancellableHandler.isCancelled(handler)) { + return; + } + + // store spoilers + if (CollectionUtils.isNotEmpty(cache.getSpoilers())) { + for (cgImage oneSpoiler : cache.getSpoilers()) { + imgGetter.getDrawable(oneSpoiler.getUrl()); + } + } + + if (CancellableHandler.isCancelled(handler)) { + return; + } + + // store images from logs + if (Settings.isStoreLogImages()) { + for (LogEntry log : cache.getLogs(true)) { + if (log.hasLogImages()) { + for (cgImage oneLogImg : log.getLogImages()) { + imgGetter.getDrawable(oneLogImg.getUrl()); + } + } + } + } + + if (CancellableHandler.isCancelled(handler)) { + return; + } + + // store map previews + StaticMapsProvider.downloadMaps(cache, activity); + + if (CancellableHandler.isCancelled(handler)) { + return; + } + + cache.setListId(listId); + cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + + if (handler != null) { + handler.sendMessage(Message.obtain()); + } + } catch (Exception e) { + Log.e("cgBase.storeCache"); + } + } + + public static SearchResult searchByGeocode(final String geocode, final String guid, final int listId, final boolean forceReload, final CancellableHandler handler) { + if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) { + Log.e("cgeoBase.searchByGeocode: No geocode nor guid given"); + return null; + } + + cgeoapplication app = cgeoapplication.getInstance(); + if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (app.isOffline(geocode, guid) || app.isThere(geocode, guid, true, true))) { + final SearchResult search = new SearchResult(); + final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : app.getGeocode(guid); + search.addGeocode(realGeocode); + return search; + } + + // if we have no geocode, we can't dynamically select the handler, but must explicitly use GC + if (geocode == null && guid != null) { + return GCConnector.getInstance().searchByGeocode(null, guid, app, handler); + } + + return ConnectorFactory.getConnector(geocode).searchByGeocode(geocode, guid, app, handler); + } + } diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java index 24f1e22..604137a 100644 --- a/main/src/cgeo/geocaching/cgData.java +++ b/main/src/cgeo/geocaching/cgData.java @@ -10,6 +10,7 @@ import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.utils.Log; import org.apache.commons.collections.CollectionUtils; @@ -28,6 +29,7 @@ import android.database.sqlite.SQLiteStatement; import java.io.File; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.EnumSet; @@ -57,6 +59,8 @@ public class cgData { "inventoryunknown", "onWatchlist", "personal_note", "reliable_latlon", "coordsChanged", "finalDefined" // reason is replaced by listId in cgCache }; + /** The list of fields needed for mapping. */ + private static final String[] WAYPOINT_COLUMNS = new String[] { "_id", "geocode", "updated", "type", "prefix", "lookup", "name", "latlon", "latitude", "longitude", "note", "own" }; /** Number of days (as ms) after temporarily saved caches are deleted */ private static long DAYS_AFTER_CACHE_IS_DELETED = 3 * 24 * 60 * 60 * 1000; @@ -265,16 +269,16 @@ public class cgData { databaseRW = dbHelper.getWritableDatabase(); if (databaseRW != null && databaseRW.isOpen()) { - Log.i(Settings.tag, "Connection to RW database established."); + Log.i("Connection to RW database established."); } else { - Log.e(Settings.tag, "Failed to open connection to RW database."); + Log.e("Failed to open connection to RW database."); } if (databaseRW != null && databaseRW.inTransaction()) { databaseRW.endTransaction(); } } catch (Exception e) { - Log.e(Settings.tag, "cgData.openDb.RW: " + e.toString()); + Log.e("cgData.openDb.RW: " + e.toString()); } } @@ -290,16 +294,16 @@ public class cgData { } if (databaseRO != null && databaseRO.isOpen()) { - Log.i(Settings.tag, "Connection to RO database established."); + Log.i("Connection to RO database established."); } else { - Log.e(Settings.tag, "Failed to open connection to RO database."); + Log.e("Failed to open connection to RO database."); } if (databaseRO != null && databaseRO.inTransaction()) { databaseRO.endTransaction(); } } catch (Exception e) { - Log.e(Settings.tag, "cgData.openDb.RO: " + e.toString()); + Log.e("cgData.openDb.RO: " + e.toString()); } } @@ -324,7 +328,7 @@ public class cgData { databaseRO = null; SQLiteDatabase.releaseMemory(); - Log.d(Settings.tag, "Closing RO database"); + Log.d("Closing RO database"); } if (databaseRW != null) { @@ -338,7 +342,7 @@ public class cgData { databaseRW = null; SQLiteDatabase.releaseMemory(); - Log.d(Settings.tag, "Closing RW database"); + Log.d("Closing RW database"); } if (dbHelper != null) { @@ -359,7 +363,7 @@ public class cgData { public String backupDatabase() { if (!LocalStorage.isExternalStorageAvailable()) { - Log.w(Settings.tag, "Database wasn't backed up: no external memory"); + Log.w("Database wasn't backed up: no external memory"); return null; } @@ -369,10 +373,10 @@ public class cgData { init(); if (backupDone) { - Log.i(Settings.tag, "Database was copied to " + target); + Log.i("Database was copied to " + target); return target.getPath(); } else { - Log.e(Settings.tag, "Database could not be copied to " + target); + Log.e("Database could not be copied to " + target); return null; } } @@ -388,7 +392,7 @@ public class cgData { public boolean restoreDatabase() { if (!LocalStorage.isExternalStorageAvailable()) { - Log.w(Settings.tag, "Database wasn't restored: no external memory"); + Log.w("Database wasn't restored: no external memory"); return false; } @@ -398,9 +402,9 @@ public class cgData { init(); if (restoreDone) { - Log.i(Settings.tag, "Database succesfully restored from " + sourceFile.getPath()); + Log.i("Database succesfully restored from " + sourceFile.getPath()); } else { - Log.e(Settings.tag, "Could not restore database from " + sourceFile.getPath()); + Log.e("Could not restore database from " + sourceFile.getPath()); } return restoreDone; @@ -451,7 +455,7 @@ public class cgData { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.i(Settings.tag, "Upgrade database from ver. " + oldVersion + " to ver. " + newVersion + ": start"); + Log.i("Upgrade database from ver. " + oldVersion + " to ver. " + newVersion + ": start"); try { if (db.isReadOnly()) { @@ -464,284 +468,19 @@ public class cgData { dropDatabase(db); onCreate(db); - Log.i(Settings.tag, "Database structure created."); + Log.i("Database structure created."); } if (oldVersion > 0) { db.execSQL("delete from " + dbTableCaches + " where reason = 0"); - if (oldVersion < 34) { // upgrade to 34 - try { - db.execSQL("create index if not exists in_a on " + dbTableCaches + " (geocode)"); - db.execSQL("create index if not exists in_b on " + dbTableCaches + " (guid)"); - db.execSQL("create index if not exists in_c on " + dbTableCaches + " (reason)"); - db.execSQL("create index if not exists in_d on " + dbTableCaches + " (detailed)"); - db.execSQL("create index if not exists in_e on " + dbTableCaches + " (type)"); - db.execSQL("create index if not exists in_a on " + dbTableAttributes + " (geocode)"); - db.execSQL("create index if not exists in_a on " + dbTableWaypoints + " (geocode)"); - db.execSQL("create index if not exists in_b on " + dbTableWaypoints + " (geocode, type)"); - db.execSQL("create index if not exists in_a on " + dbTableSpoilers + " (geocode)"); - db.execSQL("create index if not exists in_a on " + dbTableLogs + " (geocode)"); - db.execSQL("create index if not exists in_a on " + dbTableTrackables + " (geocode)"); - - Log.i(Settings.tag, "Indexes added."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 34: " + e.toString()); - } - } - - if (oldVersion < 37) { // upgrade to 37 - try { - db.execSQL("alter table " + dbTableCaches + " add column direction text"); - db.execSQL("alter table " + dbTableCaches + " add column distance double"); - - Log.i(Settings.tag, "Columns direction and distance added to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 37: " + e.toString()); - } - } - - if (oldVersion < 38) { // upgrade to 38 - try { - db.execSQL("drop table " + dbTableLogs); - db.execSQL(dbCreateLogs); - - Log.i(Settings.tag, "Changed type column in " + dbTableLogs + " to integer."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 38: " + e.toString()); - } - } - - if (oldVersion < 39) { // upgrade to 39 - try { - db.execSQL(dbCreateLists); - - Log.i(Settings.tag, "Created lists table."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 39: " + e.toString()); - } - } - - if (oldVersion < 40) { // upgrade to 40 - try { - db.execSQL("drop table " + dbTableTrackables); - db.execSQL(dbCreateTrackables); - - Log.i(Settings.tag, "Changed type of geocode column in trackables table."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 40: " + e.toString()); - } - } - - if (oldVersion < 41) { // upgrade to 41 - try { - db.execSQL("alter table " + dbTableCaches + " add column rating float"); - db.execSQL("alter table " + dbTableCaches + " add column votes integer"); - db.execSQL("alter table " + dbTableCaches + " add column vote integer"); - - Log.i(Settings.tag, "Added columns for GCvote."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 41: " + e.toString()); - } - } - - if (oldVersion < 42) { // upgrade to 42 - try { - db.execSQL(dbCreateLogsOffline); - - Log.i(Settings.tag, "Added table for offline logs"); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 42: " + e.toString()); - } - } - - if (oldVersion < 43) { // upgrade to 43 - try { - final String dbTableCachesTemp = dbTableCaches + "_temp"; - final String dbCreateCachesTemp = "" - + "create temporary table " + dbTableCachesTemp + " (" - + "_id integer primary key autoincrement, " - + "updated long not null, " - + "detailed integer not null default 0, " - + "detailedupdate long, " - + "geocode text unique not null, " - + "reason integer not null default 0, " // cached, favourite... - + "cacheid text, " - + "guid text, " - + "type text, " - + "name text, " - + "owner text, " - + "hidden long, " - + "hint text, " - + "size text, " - + "difficulty float, " - + "terrain float, " - + "latlon text, " - + "latitude_string text, " - + "longitude_string text, " - + "location text, " - + "distance double, " - + "latitude double, " - + "longitude double, " - + "shortdesc text, " - + "description text, " - + "rating float, " - + "votes integer, " - + "vote integer, " - + "disabled integer not null default 0, " - + "archived integer not null default 0, " - + "members integer not null default 0, " - + "found integer not null default 0, " - + "favourite integer not null default 0, " - + "inventorycoins integer default 0, " - + "inventorytags integer default 0, " - + "inventoryunknown integer default 0 " - + "); "; - final String dbCreateCachesNew = "" - + "create table " + dbTableCaches + " (" - + "_id integer primary key autoincrement, " - + "updated long not null, " - + "detailed integer not null default 0, " - + "detailedupdate long, " - + "geocode text unique not null, " - + "reason integer not null default 0, " // cached, favourite... - + "cacheid text, " - + "guid text, " - + "type text, " - + "name text, " - + "owner text, " - + "hidden long, " - + "hint text, " - + "size text, " - + "difficulty float, " - + "terrain float, " - + "latlon text, " - + "latitude_string text, " - + "longitude_string text, " - + "location text, " - + "direction double, " - + "distance double, " - + "latitude double, " - + "longitude double, " - + "shortdesc text, " - + "description text, " - + "rating float, " - + "votes integer, " - + "vote integer, " - + "disabled integer not null default 0, " - + "archived integer not null default 0, " - + "members integer not null default 0, " - + "found integer not null default 0, " - + "favourite integer not null default 0, " - + "inventorycoins integer default 0, " - + "inventorytags integer default 0, " - + "inventoryunknown integer default 0 " - + "); "; - - db.beginTransaction(); - db.execSQL(dbCreateCachesTemp); - db.execSQL("insert into " + dbTableCachesTemp + " select _id, updated, detailed, detailedupdate, geocode, reason, cacheid, guid, type, name, owner, hidden, hint, size, difficulty, terrain, latlon, latitude_string, longitude_string, location, distance, latitude, longitude, shortdesc, description, rating, votes, vote, disabled, archived, members, found, favourite, inventorycoins, inventorytags, inventoryunknown from " + dbTableCaches); - db.execSQL("drop table " + dbTableCaches); - db.execSQL(dbCreateCachesNew); - db.execSQL("insert into " + dbTableCaches + " select _id, updated, detailed, detailedupdate, geocode, reason, cacheid, guid, type, name, owner, hidden, hint, size, difficulty, terrain, latlon, latitude_string, longitude_string, location, null, distance, latitude, longitude, shortdesc, description, rating, votes, vote, disabled, archived, members, found, favourite, inventorycoins, inventorytags, inventoryunknown from " + dbTableCachesTemp); - db.execSQL("drop table " + dbTableCachesTemp); - db.setTransactionSuccessful(); - - Log.i(Settings.tag, "Changed direction column"); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 43: " + e.toString()); - } finally { - db.endTransaction(); - } - } - - if (oldVersion < 44) { // upgrade to 44 - try { - db.execSQL("alter table " + dbTableCaches + " add column favourite_cnt integer"); - - Log.i(Settings.tag, "Column favourite_cnt added to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 44: " + e.toString()); - } - } - - if (oldVersion < 45) { // upgrade to 45 - try { - db.execSQL("alter table " + dbTableCaches + " add column owner_real text"); - - Log.i(Settings.tag, "Column owner_real added to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 45: " + e.toString()); - } - } - - if (oldVersion < 46) { // upgrade to 46 - try { - db.execSQL("alter table " + dbTableCaches + " add column visiteddate long"); - db.execSQL("create index if not exists in_f on " + dbTableCaches + " (visiteddate, detailedupdate)"); - - Log.i(Settings.tag, "Added column for date of visit."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 46: " + e.toString()); - } - } - if (oldVersion < 47) { // upgrade to 47 - try { - db.execSQL("alter table " + dbTableCaches + " add column own integer not null default 0"); - - Log.i(Settings.tag, "Added column own."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 47: " + e.toString()); - } - } - - if (oldVersion < 48) { // upgrade to 48 - try { - db.execSQL("alter table " + dbTableCaches + " add column elevation double"); - - Log.i(Settings.tag, "Column elevation added to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 48: " + e.toString()); - } - } - - if (oldVersion < 49) { // upgrade to 49 - try { - db.execSQL(dbCreateLogCount); - - Log.i(Settings.tag, "Created table " + dbTableLogCount + "."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 49: " + e.toString()); - } - } - - if (oldVersion < 50) { // upgrade to 50 - try { - db.execSQL("alter table " + dbTableCaches + " add column myvote float"); - - Log.i(Settings.tag, "Added float column for votes to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 50: " + e.toString()); - } - } - - if (oldVersion < 51) { // upgrade to 51 - try { - db.execSQL("alter table " + dbTableCaches + " add column reliable_latlon integer"); - - Log.i(Settings.tag, "Column reliable_latlon added to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 51: " + e.toString()); - } - } - if (oldVersion < 52) { // upgrade to 52 try { db.execSQL(dbCreateSearchDestinationHistory); - Log.i(Settings.tag, "Added table " + dbTableSearchDestionationHistory + "."); + Log.i("Added table " + dbTableSearchDestionationHistory + "."); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 52", e); + Log.e("Failed to upgrade to ver. 52", e); } } @@ -749,9 +488,9 @@ public class cgData { try { db.execSQL("alter table " + dbTableCaches + " add column onWatchlist integer"); - Log.i(Settings.tag, "Column onWatchlist added to " + dbTableCaches + "."); + Log.i("Column onWatchlist added to " + dbTableCaches + "."); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 53", e); + Log.e("Failed to upgrade to ver. 53", e); } } @@ -759,7 +498,7 @@ public class cgData { try { db.execSQL(dbCreateLogImages); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 54: " + e.toString()); + Log.e("Failed to upgrade to ver. 54: " + e.toString()); } } @@ -768,7 +507,7 @@ public class cgData { try { db.execSQL("alter table " + dbTableCaches + " add column personal_note text"); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 55: " + e.toString()); + Log.e("Failed to upgrade to ver. 55: " + e.toString()); } } @@ -780,7 +519,7 @@ public class cgData { "lower(attribute) where attribute like \"%_yes\" " + "or attribute like \"%_no\""); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 56: " + e.toString()); + Log.e("Failed to upgrade to ver. 56: " + e.toString()); } } @@ -795,7 +534,7 @@ public class cgData { db.execSQL("drop index in_f"); createIndices(db); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 57: " + e.toString()); + Log.e("Failed to upgrade to ver. 57: " + e.toString()); } } @@ -883,9 +622,9 @@ public class cgData { db.setTransactionSuccessful(); - Log.i(Settings.tag, "Removed latitude_string and longitude_string columns"); + Log.i("Removed latitude_string and longitude_string columns"); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 58", e); + Log.e("Failed to upgrade to ver. 58", e); } finally { db.endTransaction(); } @@ -897,7 +636,7 @@ public class cgData { createIndices(db); removeObsoleteCacheDirectories(db); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 59", e); + Log.e("Failed to upgrade to ver. 59", e); } } @@ -905,7 +644,7 @@ public class cgData { try { removeSecEmptyDirs(); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 60", e); + Log.e("Failed to upgrade to ver. 60", e); } } if (oldVersion < 61) { @@ -913,7 +652,7 @@ public class cgData { db.execSQL("alter table " + dbTableLogs + " add column friend integer"); db.execSQL("alter table " + dbTableCaches + " add column coordsChanged integer default 0"); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 61: " + e.toString()); + Log.e("Failed to upgrade to ver. 61: " + e.toString()); } } @@ -924,7 +663,7 @@ public class cgData { db.execSQL("alter table " + dbTableWaypoints + " add column own integer default 0"); db.execSQL("update " + dbTableWaypoints + " set own = 1 where type = 'own'"); } catch (Exception e) { - Log.e(Settings.tag, "Failed to upgrade to ver. 62: " + e.toString()); + Log.e("Failed to upgrade to ver. 62: " + e.toString()); } } @@ -935,7 +674,7 @@ public class cgData { db.endTransaction(); } - Log.i(Settings.tag, "Upgrade database from ver. " + oldVersion + " to ver. " + newVersion + ": completed"); + Log.i("Upgrade database from ver. " + oldVersion + " to ver. " + newVersion + ": completed"); } } @@ -968,7 +707,7 @@ public class cgData { @Override public void run() { for (final File dir : toRemove) { - Log.i(Settings.tag, "Removing obsolete cache directory for " + dir.getName()); + Log.i("Removing obsolete cache directory for " + dir.getName()); LocalStorage.deleteDirectory(dir); } } @@ -1032,7 +771,7 @@ public class cgData { } } } catch (Exception e) { - Log.e(Settings.tag, "cgData.allDetailedThere: " + e.toString()); + Log.e("cgData.allDetailedThere: " + e.toString()); } if (cursor != null) { @@ -1093,7 +832,7 @@ public class cgData { } } } catch (Exception e) { - Log.e(Settings.tag, "cgData.isThere: " + e.toString()); + Log.e("cgData.isThere: " + e.toString()); } if (cursor != null) { @@ -1171,7 +910,7 @@ public class cgData { cursor.close(); } } catch (Exception e) { - Log.e(Settings.tag, "cgData.isOffline: " + e.toString()); + Log.e("cgData.isOffline: " + e.toString()); } return listId >= StoredList.STANDARD_LIST_ID; @@ -1192,7 +931,7 @@ public class cgData { } catch (SQLiteDoneException e) { // Do nothing, it only means we have no information on the cache } catch (Exception e) { - Log.e(Settings.tag, "cgData.getGeocodeForGuid", e); + Log.e("cgData.getGeocodeForGuid", e); } return null; @@ -1213,7 +952,7 @@ public class cgData { } catch (SQLiteDoneException e) { // Do nothing, it only means we have no information on the cache } catch (Exception e) { - Log.e(Settings.tag, "cgData.getCacheidForGeocode", e); + Log.e("cgData.getCacheidForGeocode", e); } return null; @@ -1254,7 +993,7 @@ public class cgData { cache.addStorageLocation(StorageLocation.DATABASE); cacheCache.putCacheInCache(cache); - Log.d(Settings.tag, "Saving " + cache.toString() + " (" + cache.getListId() + ") to DB"); + Log.d("Saving " + cache.toString() + " (" + cache.getListId() + ") to DB"); ContentValues values = new ContentValues(); @@ -1412,37 +1151,25 @@ public class cgData { /** * Persists the given <code>destination</code> into the database. * - * @param destinations - * @return <code>true</code> if the given destination was successfully - * persisted <code>false</code> otherwise. + * @param destination + * a destination to save */ - public boolean saveSearchedDestination(cgDestination destination) { - boolean success = true; - - if (destination == null) { - success = false; - } else { - init(); - - databaseRW.beginTransaction(); + public void saveSearchedDestination(final Destination destination) { + init(); - try { - ContentValues values = new ContentValues(); - values.put("date", destination.getDate()); - putCoords(values, destination.getCoords()); + databaseRW.beginTransaction(); - long id = databaseRW.insert(dbTableSearchDestionationHistory, null, values); - destination.setId(id); - databaseRW.setTransactionSuccessful(); - } catch (Exception e) { - success = false; - Log.e(Settings.tag, "Updating searchedDestinations db failed", e); - } finally { - databaseRW.endTransaction(); - } + try { + ContentValues values = new ContentValues(); + values.put("date", destination.getDate()); + putCoords(values, destination.getCoords()); + databaseRW.insert(dbTableSearchDestionationHistory, null, values); + databaseRW.setTransactionSuccessful(); + } catch (Exception e) { + Log.e("Updating searchedDestinations db failed", e); + } finally { + databaseRW.endTransaction(); } - - return success; } public boolean saveWaypoints(String geocode, List<cgWaypoint> waypoints, boolean drop) { @@ -1452,7 +1179,7 @@ public class cgData { init(); - Log.d(Settings.tag, "cgData.saveWaypoints(drop=" + drop + ")"); + Log.d("cgData.saveWaypoints(drop=" + drop + ")"); boolean ok = false; databaseRW.beginTransaction(); @@ -1618,11 +1345,11 @@ public class cgData { return true; } - public boolean saveLogs(String geocode, List<cgLog> logs) { + public boolean saveLogs(String geocode, List<LogEntry> logs) { return saveLogs(geocode, logs, true); } - public boolean saveLogs(String geocode, List<cgLog> logs, boolean drop) { + public boolean saveLogs(String geocode, List<LogEntry> logs, boolean drop) { if (StringUtils.isBlank(geocode) || logs == null) { return false; } @@ -1639,7 +1366,7 @@ public class cgData { if (!logs.isEmpty()) { InsertHelper helper = new InsertHelper(databaseRW, dbTableLogs); long timeStamp = System.currentTimeMillis(); - for (cgLog log : logs) { + for (LogEntry log : logs) { helper.prepareForInsert(); helper.bind(LOGS_GEOCODE, geocode); @@ -1653,9 +1380,9 @@ public class cgData { long log_id = helper.execute(); - if (CollectionUtils.isNotEmpty(log.logImages)) { + if (log.hasLogImages()) { ContentValues values = new ContentValues(); - for (cgImage img : log.logImages) { + for (cgImage img : log.getLogImages()) { values.clear(); values.put("log_id", log_id); values.put("title", img.getTitle()); @@ -1759,34 +1486,13 @@ public class cgData { return true; } - public List<Number> getBounds(Set<String> geocodes) { + public Viewport getBounds(final Set<String> geocodes) { if (CollectionUtils.isEmpty(geocodes)) { return null; } final Set<cgCache> caches = loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB); - - double latMin = 360.0; - double latMax = -360.0; - double lonMin = 360.0; - double lonMax = -360.0; - for (cgCache cache : caches) { - final Geopoint coords = cache.getCoords(); - double latitude = coords.getLatitude(); - latMin = Math.min(latitude, latMin); - latMax = Math.max(latitude, latMax); - double longitude = coords.getLongitude(); - lonMin = Math.min(longitude, lonMin); - lonMax = Math.max(longitude, lonMax); - } - - final List<Number> viewport = new ArrayList<Number>(); - viewport.add(caches.size()); - viewport.add(latMin); - viewport.add(latMax); - viewport.add(lonMin); - viewport.add(lonMax); - return viewport; + return Viewport.containing(caches); } /** @@ -1801,14 +1507,8 @@ public class cgData { throw new IllegalArgumentException("geocode must not be empty"); } - Set<String> geocodes = new HashSet<String>(); - geocodes.add(geocode); - - Set<cgCache> caches = loadCaches(geocodes, loadFlags); - if (caches != null && caches.size() >= 1) { - return (cgCache) caches.toArray()[0]; - } - return null; + final Set<cgCache> caches = loadCaches(Collections.singleton(geocode), loadFlags); + return caches.isEmpty() ? null : caches.iterator().next(); } /** @@ -1843,12 +1543,10 @@ public class cgData { loadFlags.contains(LoadFlag.LOAD_INVENTORY) || loadFlags.contains(LoadFlag.LOAD_OFFLINE_LOG)) { - Set<cgCache> cachesFromDB = loadCaches(remaining, null, null, null, null, loadFlags); - if (cachesFromDB != null) { - result.addAll(cachesFromDB); - for (cgCache cache : cachesFromDB) { - remaining.remove(cache.getGeocode()); - } + final Set<cgCache> cachesFromDB = loadCachesFromGeocodes(remaining, loadFlags); + result.addAll(cachesFromDB); + for (final cgCache cache : cachesFromDB) { + remaining.remove(cache.getGeocode()); } } @@ -1863,7 +1561,7 @@ public class cgData { } if (remaining.size() >= 1) { - Log.e(Settings.tag, "cgData.loadCaches(" + remaining.toString() + ") failed"); + Log.e("cgData.loadCaches(" + remaining.toString() + ") failed"); } return result; } @@ -1872,150 +1570,107 @@ public class cgData { * Load caches. * * @param geocodes - * OR - * @param centerLat - * @param centerLon - * @param spanLat - * @param spanLon * @param loadFlags * @return Set of loaded caches. Never null. */ - public Set<cgCache> loadCaches(final Set<String> geocodes, final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final EnumSet<LoadFlag> loadFlags) { - final Set<cgCache> caches = new HashSet<cgCache>(); + private Set<cgCache> loadCachesFromGeocodes(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) { if (CollectionUtils.isEmpty(geocodes)) { - return caches; - } - // Using more than one of the parametersets results in overly comlex wheres - if (CollectionUtils.isNotEmpty(geocodes) - && centerLat != null - && centerLon != null - && spanLat != null - && spanLon != null) { - throw new IllegalArgumentException("Please use only one parameter"); + return Collections.emptySet(); } - Log.d(Settings.tag, "cgData.loadCaches(" + geocodes.toString() + ") from DB"); + + Log.d("cgData.loadCachesFromGeocodes(" + geocodes.toString() + ") from DB"); init(); - Cursor cursor = null; + final Cursor cursor = databaseRO.query( + dbTableCaches, + CACHE_COLUMNS, + cgData.whereGeocodeIn(geocodes), + null, + null, + null, + null, + null); try { - StringBuilder where = cgData.whereGeocodeIn(geocodes); - - // viewport limitation - if (centerLat != null && centerLon != null && spanLat != null && spanLon != null) { - double latMin = (centerLat / 1e6) - ((spanLat / 1e6) / 2) - ((spanLat / 1e6) / 4); - double latMax = (centerLat / 1e6) + ((spanLat / 1e6) / 2) + ((spanLat / 1e6) / 4); - double lonMin = (centerLon / 1e6) - ((spanLon / 1e6) / 2) - ((spanLon / 1e6) / 4); - double lonMax = (centerLon / 1e6) + ((spanLon / 1e6) / 2) + ((spanLon / 1e6) / 4); - double llCache; - - if (latMin > latMax) { - llCache = latMax; - latMax = latMin; - latMin = llCache; - } - if (lonMin > lonMax) { - llCache = lonMax; - lonMax = lonMin; - lonMin = llCache; - } - - if (where.length() > 0) { - where.append(" and "); - } - where.append("(latitude >= "); - where.append(String.format((Locale) null, "%.6f", latMin)); - where.append(" and latitude <= "); - where.append(String.format((Locale) null, "%.6f", latMax)); - where.append(" and longitude >= "); - where.append(String.format((Locale) null, "%.6f", lonMin)); - where.append(" and longitude <= "); - where.append(String.format((Locale) null, "%.6f", lonMax)); - where.append(')'); - } - cursor = databaseRO.query( - dbTableCaches, - CACHE_COLUMNS, - where.toString(), - null, - null, - null, - null, - null); - - if (cursor != null) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - - do { - //Extracted Method = LOADDBMINIMAL - cgCache cache = cgData.createCacheFromDatabaseContent(cursor); + if (cursor.moveToFirst()) { + final Set<cgCache> caches = new HashSet<cgCache>(); + do { + //Extracted Method = LOADDBMINIMAL + cgCache cache = cgData.createCacheFromDatabaseContent(cursor); - if (loadFlags.contains(LoadFlag.LOAD_ATTRIBUTES)) { - cache.setAttributes(loadAttributes(cache.getGeocode())); - } + if (loadFlags.contains(LoadFlag.LOAD_ATTRIBUTES)) { + cache.setAttributes(loadAttributes(cache.getGeocode())); + } - if (loadFlags.contains(LoadFlag.LOAD_WAYPOINTS)) { - final List<cgWaypoint> waypoints = loadWaypoints(cache.getGeocode()); - if (CollectionUtils.isNotEmpty(waypoints)) { - cache.setWaypoints(waypoints, false); - } + if (loadFlags.contains(LoadFlag.LOAD_WAYPOINTS)) { + final List<cgWaypoint> waypoints = loadWaypoints(cache.getGeocode()); + if (CollectionUtils.isNotEmpty(waypoints)) { + cache.setWaypoints(waypoints, false); } + } - if (loadFlags.contains(LoadFlag.LOAD_SPOILERS)) { - final List<cgImage> spoilers = loadSpoilers(cache.getGeocode()); - if (CollectionUtils.isNotEmpty(spoilers)) { - if (cache.getSpoilers() == null) { - cache.setSpoilers(new ArrayList<cgImage>()); - } else { - cache.getSpoilers().clear(); - } - cache.getSpoilers().addAll(spoilers); + if (loadFlags.contains(LoadFlag.LOAD_SPOILERS)) { + final List<cgImage> spoilers = loadSpoilers(cache.getGeocode()); + if (CollectionUtils.isNotEmpty(spoilers)) { + if (cache.getSpoilers() == null) { + cache.setSpoilers(new ArrayList<cgImage>()); + } else { + cache.getSpoilers().clear(); } + cache.getSpoilers().addAll(spoilers); } + } - if (loadFlags.contains(LoadFlag.LOAD_LOGS)) { - cache.setLogs(loadLogs(cache.getGeocode())); - final Map<LogType, Integer> logCounts = loadLogCounts(cache.getGeocode()); - if (MapUtils.isNotEmpty(logCounts)) { - cache.getLogCounts().clear(); - cache.getLogCounts().putAll(logCounts); - } + if (loadFlags.contains(LoadFlag.LOAD_LOGS)) { + cache.setLogs(loadLogs(cache.getGeocode())); + final Map<LogType, Integer> logCounts = loadLogCounts(cache.getGeocode()); + if (MapUtils.isNotEmpty(logCounts)) { + cache.getLogCounts().clear(); + cache.getLogCounts().putAll(logCounts); } + } - if (loadFlags.contains(LoadFlag.LOAD_INVENTORY)) { - final List<cgTrackable> inventory = loadInventory(cache.getGeocode()); - if (CollectionUtils.isNotEmpty(inventory)) { - if (cache.getInventory() == null) { - cache.setInventory(new ArrayList<cgTrackable>()); - } else { - cache.getInventory().clear(); - } - cache.getInventory().addAll(inventory); + if (loadFlags.contains(LoadFlag.LOAD_INVENTORY)) { + final List<cgTrackable> inventory = loadInventory(cache.getGeocode()); + if (CollectionUtils.isNotEmpty(inventory)) { + if (cache.getInventory() == null) { + cache.setInventory(new ArrayList<cgTrackable>()); + } else { + cache.getInventory().clear(); } + cache.getInventory().addAll(inventory); } + } - if (loadFlags.contains(LoadFlag.LOAD_OFFLINE_LOG)) { - cache.setLogOffline(hasLogOffline(cache.getGeocode())); - } - cache.addStorageLocation(StorageLocation.DATABASE); - cacheCache.putCacheInCache(cache); + if (loadFlags.contains(LoadFlag.LOAD_OFFLINE_LOG)) { + cache.setLogOffline(hasLogOffline(cache.getGeocode())); + } + cache.addStorageLocation(StorageLocation.DATABASE); + cacheCache.putCacheInCache(cache); - caches.add(cache); - } while (cursor.moveToNext()); - } + caches.add(cache); + } while (cursor.moveToNext()); + return caches; + } else { + return Collections.emptySet(); } - } catch (Exception e) { - Log.e(Settings.tag, "cgData.getCaches: " + e.toString()); - } - - if (cursor != null) { + } finally { cursor.close(); } + } + + /** + * Builds a where for a viewport with the size enhanced by 50%. + * + * @param dbTable + * @param viewport + * @return + */ - return caches; + private static String buildCoordinateWhere(final String dbTable, final Viewport viewport) { + return viewport.resize(1.5).sqlWhere(dbTable); } /** @@ -2134,7 +1789,7 @@ public class cgData { cache.setUserModifiedCoords(cursor.getInt(cacheColumnIndex[37]) > 0); cache.setFinalDefined(cursor.getInt(cacheColumnIndex[40]) > 0); - Log.d(Settings.tag, "Loading " + cache.toString() + " (" + cache.getListId() + ") from DB"); + Log.d("Loading " + cache.toString() + " (" + cache.getListId() + ") from DB"); return cache; } @@ -2185,7 +1840,7 @@ public class cgData { Cursor cursor = databaseRO.query( dbTableWaypoints, - new String[] { "_id", "geocode", "updated", "type", "prefix", "lookup", "name", "latlon", "latitude", "longitude", "note", "own" }, + WAYPOINT_COLUMNS, "_id = ?", new String[] { Integer.toString(id) }, null, @@ -2193,7 +1848,7 @@ public class cgData { null, "1"); - Log.d(Settings.tag, "cgData.loadWaypoint(" + id + ")"); + Log.d("cgData.loadWaypoint(" + id + ")"); if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); @@ -2219,7 +1874,7 @@ public class cgData { Cursor cursor = databaseRO.query( dbTableWaypoints, - new String[] { "_id", "geocode", "updated", "type", "prefix", "lookup", "name", "latlon", "latitude", "longitude", "note", "own" }, + WAYPOINT_COLUMNS, "geocode = ?", new String[] { geocode }, null, @@ -2262,7 +1917,7 @@ public class cgData { return waypoint; } - public List<cgImage> loadSpoilers(String geocode) { + private List<cgImage> loadSpoilers(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } @@ -2307,7 +1962,7 @@ public class cgData { * * @return A list of previously entered destinations or an empty list. */ - public List<cgDestination> loadHistoryOfSearchedLocations() { + public List<Destination> loadHistoryOfSearchedLocations() { init(); Cursor cursor = databaseRO.query(dbTableSearchDestionationHistory, @@ -2319,7 +1974,7 @@ public class cgData { "date desc", "100"); - final List<cgDestination> destinations = new LinkedList<cgDestination>(); + final List<Destination> destinations = new LinkedList<Destination>(); if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); @@ -2329,10 +1984,7 @@ public class cgData { int indexLongitude = cursor.getColumnIndex("longitude"); do { - final cgDestination dest = new cgDestination(); - dest.setId(cursor.getLong(indexId)); - dest.setDate(cursor.getLong(indexDate)); - dest.setCoords(getCoords(cursor, indexLatitude, indexLongitude)); + final Destination dest = new Destination(cursor.getLong(indexId), cursor.getLong(indexDate), getCoords(cursor, indexLatitude, indexLongitude)); // If coordinates are non-existent or invalid, do not consider // this point. @@ -2359,7 +2011,7 @@ public class cgData { databaseRW.setTransactionSuccessful(); } catch (Exception e) { success = false; - Log.e(Settings.tag, "Unable to clear searched destinations", e); + Log.e("Unable to clear searched destinations", e); } finally { databaseRW.endTransaction(); } @@ -2367,14 +2019,14 @@ public class cgData { return success; } - public List<cgLog> loadLogs(String geocode) { + public List<LogEntry> loadLogs(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - List<cgLog> logs = new ArrayList<cgLog>(); + List<LogEntry> logs = new ArrayList<LogEntry>(); Cursor cursor = databaseRO.rawQuery( "SELECT cg_logs._id as cg_logs_id, type, author, log, date, found, friend, " + dbTableLogImages + "._id as cg_logImages_id, log_id, title, url FROM " @@ -2382,7 +2034,7 @@ public class cgData { + " ON ( cg_logs._id = log_id ) WHERE geocode = ? ORDER BY date desc, cg_logs._id asc", new String[] { geocode }); if (cursor != null && cursor.getCount() > 0) { - cgLog log = null; + LogEntry log = null; int indexLogsId = cursor.getColumnIndex("cg_logs_id"); int indexType = cursor.getColumnIndex("type"); int indexAuthor = cursor.getColumnIndex("author"); @@ -2395,7 +2047,7 @@ public class cgData { int indexUrl = cursor.getColumnIndex("url"); while (cursor.moveToNext() && logs.size() < 100) { if (log == null || log.id != cursor.getInt(indexLogsId)) { - log = new cgLog(); + log = new LogEntry(); log.id = cursor.getInt(indexLogsId); log.type = LogType.getById(cursor.getInt(indexType)); log.author = cursor.getString(indexAuthor); @@ -2408,11 +2060,7 @@ public class cgData { if (!cursor.isNull(indexLogImagesId)) { String title = cursor.getString(indexTitle); String url = cursor.getString(indexUrl); - if (log.logImages == null) { - log.logImages = new ArrayList<cgImage>(); - } - final cgImage log_img = new cgImage(url, title); - log.logImages.add(log_img); + log.addLogImage(new cgImage(url, title)); } } } @@ -2463,7 +2111,7 @@ public class cgData { return logCounts; } - public List<cgTrackable> loadInventory(String geocode) { + private List<cgTrackable> loadInventory(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } @@ -2594,7 +2242,7 @@ public class cgData { count = (int) compiledStmnt.simpleQueryForLong(); compiledStmnt.close(); } catch (Exception e) { - Log.e(Settings.tag, "cgData.loadAllStoredCachesCount: " + e.toString()); + Log.e("cgData.loadAllStoredCachesCount: " + e.toString()); } return count; @@ -2610,16 +2258,23 @@ public class cgData { count = (int) sqlCount.simpleQueryForLong(); sqlCount.close(); } catch (Exception e) { - Log.e(Settings.tag, "cgData.getAllHistoricCachesCount: " + e.toString()); + Log.e("cgData.getAllHistoricCachesCount: " + e.toString()); } return count; } + /** + * Return a batch of stored geocodes. + * + * @param detailedOnly + * @param coords + * the current coordinates to sort by distance, or null to sort by geocode + * @param cacheType + * @param listId + * @return + */ public Set<String> loadBatchOfStoredGeocodes(final boolean detailedOnly, final Geopoint coords, final CacheType cacheType, final int listId) { - if (coords == null) { - throw new IllegalArgumentException("coords must not be null"); - } if (cacheType == null) { throw new IllegalArgumentException("cacheType must not be null"); } @@ -2643,7 +2298,9 @@ public class cgData { } try { - Cursor cursor = databaseRO.query( + Cursor cursor; + if (coords != null) { + cursor = databaseRO.query( dbTableCaches, new String[] { "geocode", "(abs(latitude-" + String.format((Locale) null, "%.6f", coords.getLatitude()) + ") + abs(longitude-" + String.format((Locale) null, "%.6f", coords.getLongitude()) + ")) as dif" }, @@ -2653,22 +2310,29 @@ public class cgData { null, "dif", null); + } else { + cursor = databaseRO.query( + dbTableCaches, + new String[] { "geocode" }, + specifySql.toString(), + null, + null, + null, + "geocode"); + } - if (cursor != null) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - int index = cursor.getColumnIndex("geocode"); - - do { - geocodes.add(cursor.getString(index)); - } while (cursor.moveToNext()); - } + if (cursor.moveToFirst()) { + final int index = cursor.getColumnIndex("geocode"); - cursor.close(); + do { + geocodes.add(cursor.getString(index)); + } while (cursor.moveToNext()); } + cursor.close(); + } catch (Exception e) { - Log.e(Settings.tag, "cgData.loadBatchOfStoredGeocodes: " + e.toString()); + Log.e("cgData.loadBatchOfStoredGeocodes: " + e.toString()); } return geocodes; @@ -2718,58 +2382,46 @@ public class cgData { cursor.close(); } } catch (Exception e) { - Log.e(Settings.tag, "cgData.loadBatchOfHistoricGeocodes: " + e.toString()); + Log.e("cgData.loadBatchOfHistoricGeocodes: " + e.toString()); } return geocodes; } /** Retrieve all stored caches from DB */ - public Set<String> loadCachedInViewport(final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { - return loadInViewport(false, centerLat, centerLon, spanLat, spanLon, cacheType); + public Set<String> loadCachedInViewport(final Viewport viewport, final CacheType cacheType) { + return loadInViewport(false, viewport, cacheType); } /** Retrieve stored caches from DB with listId >= 1 */ - public Set<String> loadStoredInViewport(final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { - return loadInViewport(true, centerLat, centerLon, spanLat, spanLon, cacheType); + public Set<String> loadStoredInViewport(final Viewport viewport, final CacheType cacheType) { + return loadInViewport(true, viewport, cacheType); } - public Set<String> loadInViewport(final boolean stored, final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { - if (centerLat == null || centerLon == null || spanLat == null || spanLon == null) { - return null; - } - + /** + * Loads the geocodes of caches in a viewport from CacheCache and/or Database + * + * @param stored + * True - query only stored caches, False - query cached ones as well + * @param centerLat + * @param centerLon + * @param spanLat + * @param spanLon + * @param cacheType + * @return Set with geocodes + */ + private Set<String> loadInViewport(final boolean stored, final Viewport viewport, final CacheType cacheType) { init(); - Set<String> geocodes = new HashSet<String>(); + final Set<String> geocodes = new HashSet<String>(); + + // if not stored only, get codes from CacheCache as well + if (!stored) { + geocodes.addAll(CacheCache.getInstance().getInViewport(viewport, cacheType)); + } // viewport limitation - double latMin = (centerLat / 1e6) - ((spanLat / 1e6) / 2) - ((spanLat / 1e6) / 4); - double latMax = (centerLat / 1e6) + ((spanLat / 1e6) / 2) + ((spanLat / 1e6) / 4); - double lonMin = (centerLon / 1e6) - ((spanLon / 1e6) / 2) - ((spanLon / 1e6) / 4); - double lonMax = (centerLon / 1e6) + ((spanLon / 1e6) / 2) + ((spanLon / 1e6) / 4); - double llCache; - - if (latMin > latMax) { - llCache = latMax; - latMax = latMin; - latMin = llCache; - } - if (lonMin > lonMax) { - llCache = lonMax; - lonMax = lonMin; - lonMin = llCache; - } - - StringBuilder where = new StringBuilder(); - where.append("latitude >= "); - where.append(String.format((Locale) null, "%.6f", latMin)); - where.append(" and latitude <= "); - where.append(String.format((Locale) null, "%.6f", latMax)); - where.append(" and longitude >= "); - where.append(String.format((Locale) null, "%.6f", lonMin)); - where.append(" and longitude <= "); - where.append(String.format((Locale) null, "%.6f", lonMax)); + final StringBuilder where = new StringBuilder(buildCoordinateWhere(dbTableCaches, viewport)); // cacheType limitation if (cacheType != CacheType.ALL) { @@ -2784,7 +2436,7 @@ public class cgData { } try { - Cursor cursor = databaseRO.query( + final Cursor cursor = databaseRO.query( dbTableCaches, new String[] { "geocode" }, where.toString(), @@ -2794,75 +2446,16 @@ public class cgData { null, "500"); - if (cursor != null) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - int index = cursor.getColumnIndex("geocode"); - - do { - geocodes.add(cursor.getString(index)); - } while (cursor.moveToNext()); - } else { - cursor.close(); - return null; - } - - cursor.close(); - } - } catch (Exception e) { - Log.e(Settings.tag, "cgData.loadInViewport: " + e.toString()); - } - - return geocodes; - } - - public List<String> getOfflineAll(CacheType cacheType) { - init(); - - List<String> geocodes = new ArrayList<String>(); - - StringBuilder where = new StringBuilder(); - - // cacheType limitation - if (cacheType != CacheType.ALL) { - where.append(cacheType); - where.append('"'); - } - - // offline caches only - if (where.length() > 0) { - where.append(" and "); - } - where.append("reason >= 1"); - - try { - Cursor cursor = databaseRO.query( - dbTableCaches, - new String[] { "geocode" }, - where.toString(), - null, - null, - null, - null, - "5000"); - - if (cursor != null) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - int index = cursor.getColumnIndex("geocode"); - - do { - geocodes.add(cursor.getString(index)); - } while (cursor.moveToNext()); - } else { - cursor.close(); - return null; - } + if (cursor.moveToFirst()) { + final int index = cursor.getColumnIndex("geocode"); - cursor.close(); + do { + geocodes.add(cursor.getString(index)); + } while (cursor.moveToNext()); } + cursor.close(); } catch (Exception e) { - Log.e(Settings.tag, "cgData.getOfflineAll: " + e.toString()); + Log.e("cgData.loadInViewport: " + e.toString()); } return geocodes; @@ -2912,7 +2505,7 @@ public class cgData { public void clean(boolean more) { init(); - Log.d(Settings.tag, "Database clean: started"); + Log.d("Database clean: started"); Cursor cursor = null; Set<String> geocodes = new HashSet<String>(); @@ -2957,7 +2550,7 @@ public class cgData { final int size = geocodes.size(); if (size > 0) { - Log.d(Settings.tag, "Database clean: removing " + size + " geocaches from listId=0"); + Log.d("Database clean: removing " + size + " geocaches from listId=0"); removeCaches(geocodes, LoadFlags.REMOVE_ALL); } @@ -2965,13 +2558,13 @@ public class cgData { final SQLiteStatement countSql = databaseRO.compileStatement("select count(_id) from " + dbTableCaches + " where reason = 0"); final int count = (int) countSql.simpleQueryForLong(); countSql.close(); - Log.d(Settings.tag, "Database clean: " + count + " geocaches remaining for listId=0"); + Log.d("Database clean: " + count + " geocaches remaining for listId=0"); } catch (Exception e) { - Log.w(Settings.tag, "cgData.clean: " + e.toString()); + Log.w("cgData.clean: " + e.toString()); } - Log.d(Settings.tag, "Database clean: finished"); + Log.d("Database clean: finished"); } /** @@ -2987,7 +2580,7 @@ public class cgData { values.put("reason", StoredList.TEMPORARY_LIST_ID); databaseRW.update(dbTableCaches, values, "reason = ?", new String[] { Integer.toString(listId) }); } catch (Exception e) { - Log.e(Settings.tag, "cgData.dropList: error when updating reason", e); + Log.e("cgData.dropList: error when updating reason", e); } } @@ -3084,20 +2677,20 @@ public class cgData { } } } catch (Exception e) { - Log.e(Settings.tag, "cgData.saveLogOffline: " + e.toString()); + Log.e("cgData.saveLogOffline: " + e.toString()); } return status; } - public cgLog loadLogOffline(String geocode) { + public LogEntry loadLogOffline(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - cgLog log = null; + LogEntry log = null; Cursor cursor = databaseRO.query( dbTableLogsOffline, @@ -3112,7 +2705,7 @@ public class cgData { if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); - log = new cgLog(); + log = new LogEntry(); log.id = cursor.getInt(cursor.getColumnIndex("_id")); log.type = LogType.getById(cursor.getInt(cursor.getColumnIndex("type"))); log.log = cursor.getString(cursor.getColumnIndex("log")); @@ -3166,7 +2759,7 @@ public class cgData { return logCount.simpleQueryForLong() > 0; } } catch (Exception e) { - Log.e(Settings.tag, "cgData.hasLogOffline", e); + Log.e("cgData.hasLogOffline", e); } return false; @@ -3209,7 +2802,7 @@ public class cgData { lists.addAll(storedLists); } catch (Exception e) { - Log.e(Settings.tag, "cgData.readLists: " + e.toString()); + Log.e("cgData.readLists: " + e.toString()); } return lists; } @@ -3386,7 +2979,7 @@ public class cgData { return true; } - public boolean removeSearchedDestination(cgDestination destination) { + public boolean removeSearchedDestination(Destination destination) { boolean success = true; if (destination == null) { success = false; @@ -3398,7 +2991,7 @@ public class cgData { databaseRW.delete(dbTableSearchDestionationHistory, "_id = " + destination.getId(), null); databaseRW.setTransactionSuccessful(); } catch (Exception e) { - Log.e(Settings.tag, "Unable to remove searched destination", e); + Log.e("Unable to remove searched destination", e); success = false; } finally { databaseRW.endTransaction(); @@ -3435,7 +3028,7 @@ public class cgData { } catch (SQLiteDoneException e) { // Do nothing, it only means we have no information on the cache } catch (Exception e) { - Log.e(Settings.tag, "cgData.getCacheDescription", e); + Log.e("cgData.getCacheDescription", e); } return null; @@ -3457,7 +3050,7 @@ public class cgData { newlyCreatedDatabase = false; } - private static StringBuilder whereGeocodeIn(Set<String> geocodes) { + private static String whereGeocodeIn(Set<String> geocodes) { final StringBuilder where = new StringBuilder(); if (geocodes != null && geocodes.size() > 0) { @@ -3476,7 +3069,59 @@ public class cgData { where.append(')'); } - return where; + return where.toString(); + } + + /** + * Loads all Waypoints in the coordinate rectangle. + * + * @param centerLat + * @param centerLon + * @param spanLat + * @param spanLon + * @param excludeDisabled + * @param excludeMine + * @return + */ + + public Collection<? extends cgWaypoint> loadWaypoints(final Viewport viewport, boolean excludeMine, boolean excludeDisabled) { + final StringBuilder where = new StringBuilder(buildCoordinateWhere(dbTableWaypoints, viewport)); + if (excludeMine) + { + where.append("and " + dbTableCaches + ".own == 0 and " + dbTableCaches + ".found == 0 "); + } + if (excludeDisabled) + { + where.append("and " + dbTableCaches + ".disabled == 0 "); + } + init(); + + List<cgWaypoint> waypoints = new ArrayList<cgWaypoint>(); + + String query = "SELECT "; + for (int i = 0; i < WAYPOINT_COLUMNS.length; i++) { + query += (i > 0 ? ", " : "") + dbTableWaypoints + "." + WAYPOINT_COLUMNS[i] + " "; + } + query += " FROM " + dbTableWaypoints + ", " + dbTableCaches + " WHERE " + dbTableWaypoints + "._id == " + dbTableCaches + "._id and " + where; + Cursor cursor = databaseRO.rawQuery( + query, null); + + if (cursor != null && cursor.getCount() > 0) { + cursor.moveToFirst(); + + do { + + cgWaypoint waypoint = createWaypointFromDatabaseContent(cursor); + + waypoints.add(waypoint); + } while (cursor.moveToNext()); + } + + if (cursor != null) { + cursor.close(); + } + + return waypoints; } } diff --git a/main/src/cgeo/geocaching/cgDestination.java b/main/src/cgeo/geocaching/cgDestination.java deleted file mode 100644 index cf9a8ef..0000000 --- a/main/src/cgeo/geocaching/cgDestination.java +++ /dev/null @@ -1,74 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.geopoint.Geopoint; - -public class cgDestination { - - private long id; - - private long date; - - private Geopoint coords; - - public cgDestination() { - } - - public cgDestination(long id, long date, final Geopoint coords) { - super(); - this.id = id; - this.date = date; - this.coords = coords; - } - - public long getDate() { - return date; - } - - public void setDate(long date) { - this.date = date; - } - - public Geopoint getCoords() { - return coords; - } - - public void setCoords(final Geopoint coords) { - this.coords = coords; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(coords.getLatitude()); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(coords.getLongitude()); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof cgDestination)) { - return false; - } - cgDestination other = (cgDestination) obj; - return coords.isEqualTo(other.coords); - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - -} diff --git a/main/src/cgeo/geocaching/cgGeo.java b/main/src/cgeo/geocaching/cgGeo.java index a8748c0..c5ab556 100644 --- a/main/src/cgeo/geocaching/cgGeo.java +++ b/main/src/cgeo/geocaching/cgGeo.java @@ -45,7 +45,7 @@ public class cgGeo { try { geoManager.requestLocationUpdates(listener.locationProvider, 0, 0, listener); } catch (Exception e) { - Log.w(Settings.tag, "There is no location provider " + listener.locationProvider); + Log.w("There is no location provider " + listener.locationProvider); } } } @@ -244,7 +244,7 @@ public class cgGeo { lastLocation.setProvider(LAST_LOCATION_PSEUDO_PROVIDER); assign(lastLocation); - Log.i(Settings.tag, "Using last location from " + provider); + Log.i("Using last location from " + provider); break; } } diff --git a/main/src/cgeo/geocaching/cgLog.java b/main/src/cgeo/geocaching/cgLog.java deleted file mode 100644 index 2b3568d..0000000 --- a/main/src/cgeo/geocaching/cgLog.java +++ /dev/null @@ -1,39 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.enumerations.LogType; - -import java.util.List; - -public class cgLog { - public int id = 0; - public LogType type = LogType.LOG_NOTE; // note - public String author = ""; - public String log = ""; - public long date = 0; - public int found = -1; - /** Friend's logentry */ - public boolean friend = false; - public List<cgImage> logImages = null; - public String cacheName = ""; // used for trackables - public String cacheGuid = ""; // used for trackables - - @Override - public int hashCode() { - return (int) date * type.hashCode() * author.hashCode() * log.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof cgLog)) { - return false; - } - final cgLog otherLog = (cgLog) obj; - return date == otherLog.date && - type == otherLog.type && - author.compareTo(otherLog.author) == 0 && - log.compareTo(otherLog.log) == 0 ? true : false; - } -} diff --git a/main/src/cgeo/geocaching/cgSearchHandler.java b/main/src/cgeo/geocaching/cgSearchHandler.java index 5f94d32..6d38ea1 100644 --- a/main/src/cgeo/geocaching/cgSearchHandler.java +++ b/main/src/cgeo/geocaching/cgSearchHandler.java @@ -99,7 +99,7 @@ public class cgSearchHandler extends Handler { imgHandler.sendEmptyMessage(0); } catch (IOException e) { - Log.e(Settings.tag, "Failed to download reCAPTCHA image"); + Log.e("Failed to download reCAPTCHA image"); } } } diff --git a/main/src/cgeo/geocaching/cgSearchThread.java b/main/src/cgeo/geocaching/cgSearchThread.java index 99ab685..ff73a66 100644 --- a/main/src/cgeo/geocaching/cgSearchThread.java +++ b/main/src/cgeo/geocaching/cgSearchThread.java @@ -23,7 +23,7 @@ abstract public class cgSearchThread extends Thread { try { wait(); } catch (InterruptedException e) { - Log.w(Settings.tag, "searchThread is not waiting for user..."); + Log.w("searchThread is not waiting for user..."); } } diff --git a/main/src/cgeo/geocaching/cgTrackable.java b/main/src/cgeo/geocaching/cgTrackable.java index 1e11b43..f46e39b 100644 --- a/main/src/cgeo/geocaching/cgTrackable.java +++ b/main/src/cgeo/geocaching/cgTrackable.java @@ -34,7 +34,7 @@ public class cgTrackable implements ILogable { private String goal = null; private String details = null; private String image = null; - private List<cgLog> logs = new ArrayList<cgLog>(); + private List<LogEntry> logs = new ArrayList<LogEntry>(); private String trackingcode = null; public String getUrl() { @@ -44,7 +44,7 @@ public class cgTrackable implements ILogable { int id = Integer.parseInt(hex, 16); return "http://geokrety.org/konkret.php?id=" + id; } catch (NumberFormatException e) { - Log.e(Settings.tag, "cgTrackable.getUrl", e); + Log.e("cgTrackable.getUrl", e); return null; } } @@ -188,11 +188,11 @@ public class cgTrackable implements ILogable { this.image = image; } - public List<cgLog> getLogs() { + public List<LogEntry> getLogs() { return logs; } - public void setLogs(List<cgLog> logs) { + public void setLogs(List<LogEntry> logs) { this.logs = logs; } diff --git a/main/src/cgeo/geocaching/cgTrackableLog.java b/main/src/cgeo/geocaching/cgTrackableLog.java deleted file mode 100644 index ee134da..0000000 --- a/main/src/cgeo/geocaching/cgTrackableLog.java +++ /dev/null @@ -1,11 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.enumerations.LogTypeTrackable; - -public class cgTrackableLog { - public int ctl = -1; - public int id = -1; - public String trackCode = null; - public String name = null; - public LogTypeTrackable action = LogTypeTrackable.DO_NOTHING; // base.logTrackablesAction - no action -} diff --git a/main/src/cgeo/geocaching/cgWaypoint.java b/main/src/cgeo/geocaching/cgWaypoint.java index d70e5ae..ee865ee 100644 --- a/main/src/cgeo/geocaching/cgWaypoint.java +++ b/main/src/cgeo/geocaching/cgWaypoint.java @@ -179,10 +179,6 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { return waypointType; } - public void setWaypointType(WaypointType type) { - this.waypointType = type; - } - public String getLookup() { return lookup; } @@ -223,14 +219,6 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { this.note = note; } - public int getCachedOrder() { - return cachedOrder; - } - - public void setCachedOrder(int cachedOrder) { - this.cachedOrder = cachedOrder; - } - @Override public String toString() { return name + " " + waypointType.getL10n(); diff --git a/main/src/cgeo/geocaching/cgeo.java b/main/src/cgeo/geocaching/cgeo.java index ba7d725..86f8824 100644 --- a/main/src/cgeo/geocaching/cgeo.java +++ b/main/src/cgeo/geocaching/cgeo.java @@ -2,17 +2,13 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.enumerations.CacheSize; +import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; -import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; -import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.HumanDistance; import cgeo.geocaching.geopoint.IConversion; import cgeo.geocaching.maps.CGeoMap; -import cgeo.geocaching.network.Login; import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; @@ -151,9 +147,9 @@ public class cgeo extends AbstractActivity { final int satellitesFixed = msg.arg1; final int satellitesVisible = msg.arg2; if (satellitesFixed > 0) { - satellites = res.getString(R.string.loc_sat) + ": " + satellitesFixed + "/" + satellitesVisible; + satellites = res.getString(R.string.loc_sat) + ": " + satellitesFixed + '/' + satellitesVisible; } else if (satellitesVisible >= 0) { - satellites = res.getString(R.string.loc_sat) + ": 0/" + geo.satellitesVisible; + satellites = res.getString(R.string.loc_sat) + ": 0/" + satellitesVisible; } break; } @@ -184,7 +180,7 @@ public class cgeo extends AbstractActivity { showToast(res.getString(reason == StatusCode.MAINTENANCE ? reason.getErrorString() : R.string.err_login_failed_toast)); } } catch (Exception e) { - Log.w(Settings.tag, "cgeo.fisrtLoginHander: " + e.toString()); + Log.w("cgeo.firstLoginHander: " + e.toString()); } } }; @@ -226,12 +222,12 @@ public class cgeo extends AbstractActivity { version = info.versionCode; - Log.i(Settings.tag, "Starting " + info.packageName + " " + info.versionCode + " a.k.a " + info.versionName + "..."); + Log.i("Starting " + info.packageName + " " + info.versionCode + " a.k.a " + info.versionName + "..."); info = null; manager = null; } catch (Exception e) { - Log.i(Settings.tag, "No info."); + Log.i("No info."); } try { @@ -517,29 +513,6 @@ public class cgeo extends AbstractActivity { initialized = true; Settings.setLanguage(Settings.isUseEnglish()); - - /* - * "update" the cache size/type. For a better performance - * the resource strings are stored in the enum's. In case of a - * locale change the resource strings don't get updated automatically. - * That's why we have to do it on our own. - */ - for (CacheSize cacheSize : CacheSize.values()) { - cacheSize.setL10n(); - } - for (CacheType cacheType : CacheType.values()) { - cacheType.setL10n(); - } - for (LogType logType : LogType.values()) { - logType.setL10n(); - } - for (WaypointType waypointType : WaypointType.values()) { - waypointType.setL10n(); - } - for (Strategy strategy : Strategy.values()) { - strategy.setL10n(); - } - Settings.getLogin(); if (app.firstRun) { @@ -702,7 +675,7 @@ public class cgeo extends AbstractActivity { navLocation.setText(res.getString(R.string.loc_trying)); } } catch (Exception e) { - Log.w(Settings.tag, "Failed to update location."); + Log.w("Failed to update location."); } } } @@ -792,7 +765,7 @@ public class cgeo extends AbstractActivity { countBubble.setVisibility(View.VISIBLE); } } catch (Exception e) { - Log.w(Settings.tag, "cgeo.countBubbleHander: " + e.toString()); + Log.w("cgeo.countBubbleHander: " + e.toString()); } } }; @@ -836,7 +809,7 @@ public class cgeo extends AbstractActivity { boolean more = false; if (version != Settings.getVersion()) { - Log.i(Settings.tag, "Initializing hard cleanup - version changed from " + Settings.getVersion() + " to " + version + "."); + Log.i("Initializing hard cleanup - version changed from " + Settings.getVersion() + " to " + version + "."); more = true; } @@ -874,9 +847,7 @@ public class cgeo extends AbstractActivity { // invoke settings activity to insert login details if (status == StatusCode.NO_LOGIN_INFO_STORED) { - final Context context = cgeo.this; - final Intent initIntent = new Intent(context, cgeoinit.class); - context.startActivity(initIntent); + cgeoinit.startActivity(cgeo.this); } } } @@ -903,7 +874,7 @@ public class cgeo extends AbstractActivity { addresses = geocoder.getFromLocation(geo.coordsNow.getLatitude(), geo.coordsNow.getLongitude(), 1); } catch (Exception e) { - Log.i(Settings.tag, "Failed to obtain address"); + Log.i("Failed to obtain address"); } obtainAddressHandler.sendEmptyMessage(0); diff --git a/main/src/cgeo/geocaching/cgeoabout.java b/main/src/cgeo/geocaching/cgeoabout.java index c1f7e83..0c812f0 100644 --- a/main/src/cgeo/geocaching/cgeoabout.java +++ b/main/src/cgeo/geocaching/cgeoabout.java @@ -37,7 +37,7 @@ public class cgeoabout extends AbstractActivity { ((TextView) findViewById(R.id.contributors)).setMovementMethod(LinkMovementMethod.getInstance()); ((TextView) findViewById(R.id.changelog)).setMovementMethod(LinkMovementMethod.getInstance()); } catch (Exception e) { - Log.e(Settings.tag, "cgeoabout.init: Failed to obtain package version."); + Log.e("cgeoabout.init: Failed to obtain package version."); } } diff --git a/main/src/cgeo/geocaching/cgeoadvsearch.java b/main/src/cgeo/geocaching/cgeoadvsearch.java index 2086c7d..194fdbb 100644 --- a/main/src/cgeo/geocaching/cgeoadvsearch.java +++ b/main/src/cgeo/geocaching/cgeoadvsearch.java @@ -146,7 +146,7 @@ public class cgeoadvsearch extends AbstractActivity { } } catch (Exception e) { - Log.w(Settings.tag, "cgeoadvsearch.instantSearch: " + e.toString()); + Log.w("cgeoadvsearch.instantSearch: " + e.toString()); } return false; @@ -271,7 +271,7 @@ public class cgeoadvsearch extends AbstractActivity { } } } catch (Exception e) { - Log.w(Settings.tag, "Failed to update location."); + Log.w("Failed to update location."); } } } @@ -313,7 +313,7 @@ public class cgeoadvsearch extends AbstractActivity { } } else { try { - cgeocaches.startActivityCoordinates(this, GeopointParser.parseLatitude(latText), GeopointParser.parseLongitude(lonText)); + cgeocaches.startActivityCoordinates(this, GeopointParser.parse(latText, lonText)); } catch (GeopointParser.ParseException e) { showToast(res.getString(e.resource)); } diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/cgeoapplication.java index 6418d86..8b5eb57 100644 --- a/main/src/cgeo/geocaching/cgeoapplication.java +++ b/main/src/cgeo/geocaching/cgeoapplication.java @@ -7,6 +7,7 @@ import cgeo.geocaching.enumerations.LoadFlags.LoadFlag; import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; @@ -21,9 +22,10 @@ import android.os.Message; import java.io.File; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.EnumSet; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -54,14 +56,14 @@ public class cgeoapplication extends Application { @Override public void onLowMemory() { - Log.i(Settings.tag, "Cleaning applications cache."); + Log.i("Cleaning applications cache."); storage.removeAllFromCache(); } @Override public void onTerminate() { - Log.d(Settings.tag, "Terminating c:geo..."); + Log.d("Terminating c:geo..."); cleanGeo(); cleanDir(); @@ -135,7 +137,7 @@ public class cgeoapplication extends Application { public cgGeo startGeo(UpdateLocationCallback geoUpdate) { if (geo == null) { geo = new cgGeo(); - Log.i(Settings.tag, "Location service started"); + Log.i("Location service started"); } geo.replaceUpdate(geoUpdate); @@ -171,7 +173,7 @@ public class cgeoapplication extends Application { if (!geoInUse && geo != null) { cleanGeo(); - Log.i(Settings.tag, "Location service stopped"); + Log.i("Location service stopped"); } } } @@ -180,7 +182,7 @@ public class cgeoapplication extends Application { if (dir == null) { dir = new cgDirection(context, dirUpdate); - Log.i(Settings.tag, "Direction service started"); + Log.i("Direction service started"); } dir.replaceUpdate(dirUpdate); @@ -212,7 +214,7 @@ public class cgeoapplication extends Application { if (!dirInUse && dir != null) { cleanDir(); - Log.i(Settings.tag, "Direction service stopped"); + Log.i("Direction service stopped"); } } } @@ -275,19 +277,16 @@ public class cgeoapplication extends Application { return storage.allDetailedThere(); } - public List<Number> getBounds(String geocode) { + public Viewport getBounds(String geocode) { if (geocode == null) { return null; } - Set<String> geocodeList = new HashSet<String>(); - geocodeList.add(geocode); - - return getBounds(geocodeList); + return getBounds(Collections.singleton(geocode)); } /** {@link cgData#getBounds(Set)} */ - public List<Number> getBounds(final Set<String> geocodes) { + public Viewport getBounds(final Set<String> geocodes) { return storage.getBounds(geocodes); } @@ -298,7 +297,7 @@ public class cgeoapplication extends Application { } /** {@link cgData#loadHistoryOfSearchedLocations()} */ - public List<cgDestination> getHistoryOfSearchedLocations() { + public List<Destination> getHistoryOfSearchedLocations() { return storage.loadHistoryOfSearchedLocations(); } @@ -307,15 +306,15 @@ public class cgeoapplication extends Application { return new SearchResult(geocodes, getAllHistoricCachesCount()); } - /** {@link cgData#loadCachedInViewport(Long, Long, Long, Long, CacheType)} */ - public SearchResult getCachedInViewport(final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { - final Set<String> geocodes = storage.loadCachedInViewport(centerLat, centerLon, spanLat, spanLon, cacheType); + /** {@link cgData#loadCachedInViewport(long, long, long, long, CacheType)} */ + public SearchResult getCachedInViewport(final Viewport viewport, final CacheType cacheType) { + final Set<String> geocodes = storage.loadCachedInViewport(viewport, cacheType); return new SearchResult(geocodes); } - /** {@link cgData#loadStoredInViewport(Long, Long, Long, Long, CacheType)} */ - public SearchResult getStoredInViewport(final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { - final Set<String> geocodes = storage.loadStoredInViewport(centerLat, centerLon, spanLat, spanLon, cacheType); + /** {@link cgData#loadStoredInViewport(long, long, long, long, CacheType)} */ + public SearchResult getStoredInViewport(final Viewport viewport, final CacheType cacheType) { + final Set<String> geocodes = storage.loadStoredInViewport(viewport, cacheType); return new SearchResult(geocodes); } @@ -349,9 +348,9 @@ public class cgeoapplication extends Application { return storage.clearSearchedDestinations(); } - /** {@link cgData#saveSearchedDestination(cgDestination)} */ - public boolean saveSearchedDestination(cgDestination destination) { - return storage.saveSearchedDestination(destination); + /** {@link cgData#saveSearchedDestination(Destination)} */ + public void saveSearchedDestination(Destination destination) { + storage.saveSearchedDestination(destination); } /** {@link cgData#saveWaypoints(String, List, boolean)} */ @@ -384,21 +383,11 @@ public class cgeoapplication extends Application { storage.dropList(listId); } - /** {@link cgData#loadInventory(String)} */ - public List<cgTrackable> loadInventory(String geocode) { - return storage.loadInventory(geocode); - } - /** {@link cgData#loadLogCounts(String)} */ public Map<LogType, Integer> loadLogCounts(String geocode) { return storage.loadLogCounts(geocode); } - /** {@link cgData#loadSpoilers(String)} */ - public List<cgImage> loadSpoilers(String geocode) { - return storage.loadSpoilers(geocode); - } - /** {@link cgData#loadWaypoint(int)} */ public cgWaypoint loadWaypoint(int id) { return storage.loadWaypoint(id); @@ -423,7 +412,7 @@ public class cgeoapplication extends Application { return StringUtils.defaultString(action); } - public boolean addLog(String geocode, cgLog log) { + public boolean addLog(String geocode, LogEntry log) { if (StringUtils.isBlank(geocode)) { return false; } @@ -431,7 +420,7 @@ public class cgeoapplication extends Application { return false; } - List<cgLog> list = new ArrayList<cgLog>(); + List<LogEntry> list = new ArrayList<LogEntry>(); list.add(log); return storage.saveLogs(geocode, list, false); @@ -451,7 +440,7 @@ public class cgeoapplication extends Application { } /** {@link cgData#loadLogOffline(String)} */ - public cgLog loadLogOffline(String geocode) { + public LogEntry loadLogOffline(String geocode) { return storage.loadLogOffline(geocode); } @@ -495,8 +484,8 @@ public class cgeoapplication extends Application { return storage.removeList(id); } - /** {@link cgData#removeSearchedDestination(cgDestination)} */ - public boolean removeSearchedDestinations(cgDestination destination) { + /** {@link cgData#removeSearchedDestination(Destination)} */ + public boolean removeSearchedDestinations(Destination destination) { return storage.removeSearchedDestination(destination); } @@ -520,11 +509,6 @@ public class cgeoapplication extends Application { return storage.loadCaches(geocodes, loadFlags); } - /** {@link cgData#loadCaches} */ - public Set<cgCache> loadCaches(Long centerLat, Long centerLon, Long spanLat, Long spanLon, final EnumSet<LoadFlag> loadFlags) { - return storage.loadCaches(null, centerLat, centerLon, spanLat, spanLon, loadFlags); - } - /** {@link cgData#saveCache} */ public boolean saveCache(cgCache cache, EnumSet<LoadFlags.SaveFlag> saveFlags) { return storage.saveCache(cache, saveFlags); @@ -540,4 +524,8 @@ public class cgeoapplication extends Application { storage.removeCaches(geocodes, removeFlags); } + public Collection<? extends cgWaypoint> getWaypointsInViewport(final Viewport viewport, boolean excludeMine, boolean excludeDisabled) { + return storage.loadWaypoints(viewport, excludeMine, excludeDisabled); + } + } diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 63b9a2e..70bf892 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -6,21 +6,19 @@ import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cachelist.CacheListAppFactory; +import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.enumerations.CacheListType; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; +import cgeo.geocaching.export.ExportFactory; import cgeo.geocaching.files.GPXImporter; -import cgeo.geocaching.filter.AttributeFilter; +import cgeo.geocaching.filter.FilterUserInterface; import cgeo.geocaching.filter.IFilter; -import cgeo.geocaching.filter.ModifiedFilter; -import cgeo.geocaching.filter.SizeFilter; -import cgeo.geocaching.filter.StateFilter; -import cgeo.geocaching.filter.TrackablesFilter; -import cgeo.geocaching.filter.TypeFilter; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.maps.CGeoMap; +import cgeo.geocaching.network.Cookies; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.sorting.CacheComparator; @@ -54,7 +52,6 @@ import android.content.Intent; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; -import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.ContextMenu; @@ -66,23 +63,15 @@ import android.view.MenuItem; import android.view.SubMenu; import android.view.View; import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.EditText; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; -import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -91,6 +80,7 @@ public class cgeocaches extends AbstractListActivity { private static final int MAX_LIST_ITEMS = 1000; private static final String EXTRAS_LIST_TYPE = "type"; + private static final String EXTRAS_COORDS = "coords"; private static final int MENU_REFRESH_STORED = 2; private static final int MENU_CACHE_DETAILS = 4; private static final int MENU_DROP_CACHES = 5; @@ -110,20 +100,15 @@ public class cgeocaches extends AbstractListActivity { private static final int MENU_SORT_VOTE = 19; private static final int MENU_SORT_INVENTORY = 20; private static final int MENU_IMPORT_WEB = 21; - private static final int MENU_EXPORT_NOTES = 22; + private static final int MENU_EXPORT = 22; private static final int MENU_REMOVE_FROM_HISTORY = 23; private static final int MENU_DROP_CACHE = 24; private static final int MENU_MOVE_TO_LIST = 25; - private static final int MENU_FILTER_CLEAR = 26; - private static final int MENU_FILTER_TRACKABLES = 27; - private static final int SUBMENU_FILTER_SIZE = 28; - private static final int SUBMENU_FILTER_TYPE = 29; private static final int MENU_SWITCH_SELECT_MODE = 52; private static final int SUBMENU_SHOW_MAP = 54; private static final int SUBMENU_MANAGE_LISTS = 55; private static final int SUBMENU_MANAGE_OFFLINE = 56; private static final int SUBMENU_SORT = 57; - private static final int SUBMENU_FILTER = 58; private static final int SUBMENU_IMPORT = 59; private static final int SUBMENU_MANAGE_HISTORY = 60; private static final int MENU_SORT_DATE = 61; @@ -132,10 +117,9 @@ public class cgeocaches extends AbstractListActivity { private static final int MENU_RENAME_LIST = 64; private static final int MENU_DROP_CACHES_AND_LIST = 65; private static final int MENU_DEFAULT_NAVIGATION = 66; - private static final int SUBMENU_FILTER_ATTRIBUTES = 67; - private static final int SUBMENU_FILTER_STATE = 68; private static final int MENU_NAVIGATION = 69; - private static final int MENU_FILTER_MODIFIED = 70; + private static final int MENU_STORE_CACHE = 73; + private static final int MENU_FILTER = 74; private static final int MSG_DONE = -1; private static final int MSG_CANCEL = -99; @@ -166,10 +150,8 @@ public class cgeocaches extends AbstractListActivity { private LoadDetailsThread threadDetails = null; private LoadFromWebThread threadWeb = null; private DropDetailsThread threadR = null; - private ExportFieldNotesThread threadF = null; private RemoveFromHistoryThread threadH = null; private int listId = StoredList.TEMPORARY_LIST_ID; - private List<StoredList> lists = null; private GeocodeComparator gcComparator = new GeocodeComparator(); private Handler loadCachesHandler = new Handler() { @@ -206,14 +188,14 @@ public class cgeocaches extends AbstractListActivity { dialog.setNegativeButton(res.getString(R.string.license_dismiss), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - Network.clearCookies(); + Cookies.clearCookies(); dialog.cancel(); } }); dialog.setPositiveButton(res.getString(R.string.license_show), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - Network.clearCookies(); + Cookies.clearCookies(); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/software/agreement.aspx?ID=0"))); } }); @@ -236,7 +218,7 @@ public class cgeocaches extends AbstractListActivity { } } catch (Exception e) { showToast(res.getString(R.string.err_detail_cache_find_any)); - Log.e(Settings.tag, "cgeocaches.loadCachesHandler: " + e.toString()); + Log.e("cgeocaches.loadCachesHandler: " + e.toString()); hideLoading(); showProgress(false); @@ -249,7 +231,7 @@ public class cgeocaches extends AbstractListActivity { hideLoading(); showProgress(false); } catch (Exception e2) { - Log.e(Settings.tag, "cgeocaches.loadCachesHandler.2: " + e2.toString()); + Log.e("cgeocaches.loadCachesHandler.2: " + e2.toString()); } if (adapter != null) { @@ -303,7 +285,7 @@ public class cgeocaches extends AbstractListActivity { } } catch (Exception e) { showToast(res.getString(R.string.err_detail_cache_find_next)); - Log.e(Settings.tag, "cgeocaches.loadNextPageHandler: " + e.toString()); + Log.e("cgeocaches.loadNextPageHandler: " + e.toString()); } hideLoading(); @@ -469,39 +451,6 @@ public class cgeocaches extends AbstractListActivity { } } }; - private Handler exportFieldNotesHandler = new Handler() { - - @Override - public void handleMessage(Message msg) - { - setAdapter(); - - if (msg.what > -1) - { - cacheList.get(msg.what).setStatusChecked(false); - progress.setProgress(detailProgress); - } - else if (-2 == msg.what) - { - showToast(res.getString(R.string.info_fieldnotes_exported_to) + ": " + msg.obj.toString()); - } - else if (-3 == msg.what) - { - showToast(res.getString(R.string.err_fieldnotes_export_failed)); - } else if (msg.what == MSG_CANCEL) { - if (threadF != null) { - threadF.kill(); - } - } else { - if (adapter != null) - { - adapter.setSelectMode(false, true); - } - - progress.dismiss(); - } - } - }; private Handler importGpxAttachementFinishedHandler = new Handler() { @Override @@ -537,7 +486,7 @@ public class cgeocaches extends AbstractListActivity { if (extras != null) { Object typeObject = extras.get(EXTRAS_LIST_TYPE); type = (typeObject instanceof CacheListType) ? (CacheListType) typeObject : CacheListType.OFFLINE; - coords = new Geopoint(extras.getDouble("latitude"), extras.getDouble("longitude")); + coords = (Geopoint) extras.getParcelable(EXTRAS_COORDS); cacheType = Settings.getCacheType(); keyword = extras.getString("keyword"); address = extras.getString("address"); @@ -546,7 +495,7 @@ public class cgeocaches extends AbstractListActivity { if (Intent.ACTION_VIEW.equals(getIntent().getAction())) { type = CacheListType.OFFLINE; if (coords == null) { - coords = new Geopoint(0, 0); + coords = new Geopoint(0.0, 0.0); } } @@ -666,7 +615,7 @@ public class cgeocaches extends AbstractListActivity { default: title = "caches"; setTitle(title); - Log.e(Settings.tag, "cgeocaches.onCreate: No action or unknown action specified"); + Log.e("cgeocaches.onCreate: No action or unknown action specified"); break; } prepareFilterBar(); @@ -726,7 +675,7 @@ public class cgeocaches extends AbstractListActivity { // refresh standard list if it has changed (new caches downloaded) if (type == CacheListType.OFFLINE && listId >= StoredList.STANDARD_LIST_ID && search != null) { - SearchResult newSearch = cgBase.searchByStored(coords, cacheType, listId); + SearchResult newSearch = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, cacheType, listId); if (newSearch != null && newSearch.getTotal() != search.getTotal()) { refreshCurrentList(); } @@ -760,17 +709,7 @@ public class cgeocaches extends AbstractListActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { - SubMenu subMenuFilter = menu.addSubMenu(0, SUBMENU_FILTER, 0, res.getString(R.string.caches_filter)).setIcon(R.drawable.ic_menu_filter); - subMenuFilter.setHeaderTitle(res.getString(R.string.caches_filter_title)); - if (Settings.getCacheType() == CacheType.ALL) { - subMenuFilter.add(0, SUBMENU_FILTER_TYPE, 0, res.getString(R.string.caches_filter_type)); - } - subMenuFilter.add(0, SUBMENU_FILTER_SIZE, 0, res.getString(R.string.caches_filter_size)); - subMenuFilter.add(0, SUBMENU_FILTER_ATTRIBUTES, 0, res.getString(R.string.cache_attributes)); - subMenuFilter.add(0, SUBMENU_FILTER_STATE, 0, res.getString(R.string.cache_status)); - subMenuFilter.add(0, MENU_FILTER_TRACKABLES, 0, res.getString(R.string.caches_filter_track)); - subMenuFilter.add(0, MENU_FILTER_MODIFIED, 0, res.getString(R.string.caches_filter_modified)); - subMenuFilter.add(0, MENU_FILTER_CLEAR, 0, res.getString(R.string.caches_filter_clear)); + menu.add(0, MENU_FILTER, 0, res.getString(R.string.caches_filter)).setIcon(R.drawable.ic_menu_filter); SubMenu subMenuSort = menu.addSubMenu(0, SUBMENU_SORT, 0, res.getString(R.string.caches_sort)).setIcon(android.R.drawable.ic_menu_sort_alphabetically); subMenuSort.setHeaderTitle(res.getString(R.string.caches_sort_title)); @@ -808,9 +747,8 @@ public class cgeocaches extends AbstractListActivity { subMenu.add(0, MENU_DROP_CACHES_AND_LIST, 0, res.getString(R.string.caches_drop_all_and_list)); subMenu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.cache_offline_refresh)); // download details for all caches subMenu.add(0, MENU_MOVE_TO_LIST, 0, res.getString(R.string.cache_menu_move_list)); - subMenu.add(0, MENU_EXPORT_NOTES, 0, res.getString(R.string.cache_export_fieldnote)); // export field notes - if (Settings.getWebDeviceCode() == null) - { + subMenu.add(0, MENU_EXPORT, 0, res.getString(R.string.export)); // export caches + if (Settings.getWebDeviceCode() == null) { menu.add(0, MENU_IMPORT_GPX, 0, res.getString(R.string.gpx_import_title)).setIcon(android.R.drawable.ic_menu_upload); // import gpx file } else { SubMenu subMenuImport = menu.addSubMenu(0, SUBMENU_IMPORT, 0, res.getString(R.string.import_title)).setIcon(android.R.drawable.ic_menu_upload); // import @@ -818,11 +756,10 @@ public class cgeocaches extends AbstractListActivity { subMenuImport.add(1, MENU_IMPORT_WEB, 0, res.getString(R.string.web_import_title)).setCheckable(false).setChecked(false); } } else { - if (type == CacheListType.HISTORY) - { + if (type == CacheListType.HISTORY) { SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_HISTORY, 0, res.getString(R.string.caches_manage)).setIcon(android.R.drawable.ic_menu_save); subMenu.add(0, MENU_REMOVE_FROM_HISTORY, 0, res.getString(R.string.cache_clear_history)); // remove from history - subMenu.add(0, MENU_EXPORT_NOTES, 0, res.getString(R.string.cache_export_fieldnote)); // export field notes + subMenu.add(0, MENU_EXPORT, 0, res.getString(R.string.export)); // export caches } menu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.caches_store_offline)).setIcon(android.R.drawable.ic_menu_set_as); // download details for all caches } @@ -859,30 +796,12 @@ public class cgeocaches extends AbstractListActivity { boolean isNonDefaultList = listId != StoredList.STANDARD_LIST_ID; if (type == CacheListType.OFFLINE) { // only offline list - if (hasSelection) { - menu.findItem(MENU_DROP_CACHES).setTitle(res.getString(R.string.caches_drop_selected) + " (" + adapter.getChecked() + ")"); - } else { - menu.findItem(MENU_DROP_CACHES).setTitle(res.getString(R.string.caches_drop_all)); - } + setMenuItemLabel(menu, MENU_DROP_CACHES, R.string.caches_drop_selected, R.string.caches_drop_all); menu.findItem(MENU_DROP_CACHES_AND_LIST).setVisible(!hasSelection && isNonDefaultList); - - if (hasSelection) { - menu.findItem(MENU_REFRESH_STORED).setTitle(res.getString(R.string.caches_refresh_selected) + " (" + adapter.getChecked() + ")"); - } else { - menu.findItem(MENU_REFRESH_STORED).setTitle(res.getString(R.string.caches_refresh_all)); - } - - if (hasSelection) { - menu.findItem(MENU_MOVE_TO_LIST).setTitle(res.getString(R.string.caches_move_selected) + " (" + adapter.getChecked() + ")"); - } else { - menu.findItem(MENU_MOVE_TO_LIST).setTitle(res.getString(R.string.caches_move_all)); - } + setMenuItemLabel(menu, MENU_REFRESH_STORED, R.string.caches_refresh_selected, R.string.caches_refresh_all); + setMenuItemLabel(menu, MENU_MOVE_TO_LIST, R.string.caches_move_selected, R.string.caches_move_all); } else { // search and history list (all other than offline) - if (hasSelection) { - menu.findItem(MENU_REFRESH_STORED).setTitle(res.getString(R.string.caches_store_selected) + " (" + adapter.getChecked() + ")"); - } else { - menu.findItem(MENU_REFRESH_STORED).setTitle(res.getString(R.string.caches_store_offline)); - } + setMenuItemLabel(menu, MENU_REFRESH_STORED, R.string.caches_store_selected, R.string.caches_store_offline); } // Hide menus if cache-list is empty @@ -925,39 +844,28 @@ public class cgeocaches extends AbstractListActivity { item.setVisible(multipleLists); } - item = menu.findItem(MENU_REMOVE_FROM_HISTORY); - if (null != item) { - if (hasSelection) { - item.setTitle(res.getString(R.string.cache_remove_from_history) + " (" + adapter.getChecked() + ")"); - } else { - item.setTitle(res.getString(R.string.cache_clear_history)); - } - } - - item = menu.findItem(MENU_EXPORT_NOTES); - if (null != item) { - // Hide Field Notes export if there are no caches with logs - item.setVisible(false); - for (cgCache cache : cacheList) { - if (cache.isLogOffline()) { - item.setVisible(true); - if (hasSelection) { - item.setTitle(res.getString(R.string.cache_export_fieldnote) + " (" + adapter.getChecked() + ")"); - } else { - item.setTitle(res.getString(R.string.cache_export_fieldnote)); - } - break; - } - } - } - + setMenuItemLabel(menu, MENU_REMOVE_FROM_HISTORY, R.string.cache_remove_from_history, R.string.cache_clear_history); + setMenuItemLabel(menu, MENU_EXPORT, R.string.export, R.string.export); } catch (Exception e) { - Log.e(Settings.tag, "cgeocaches.onPrepareOptionsMenu: " + e.toString()); + Log.e("cgeocaches.onPrepareOptionsMenu", e); } return true; } + private void setMenuItemLabel(final Menu menu, final int menuId, final int resIdSelection, final int resId) { + final MenuItem menuItem = menu.findItem(menuId); + if (menuItem == null) { + return; + } + boolean hasSelection = adapter != null && adapter.getChecked() > 0; + if (hasSelection) { + menuItem.setTitle(res.getString(resIdSelection) + " (" + adapter.getChecked() + ")"); + } else { + menuItem.setTitle(res.getString(resId)); + } + } + @Override public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); @@ -985,7 +893,7 @@ public class cgeocaches extends AbstractListActivity { invalidateOptionsMenuCompatible(); return false; case MENU_CREATE_LIST: - createList(null); + new StoredList.UserInterface(this).promptForListCreation(null); invalidateOptionsMenuCompatible(); return false; case MENU_DROP_LIST: @@ -1044,34 +952,27 @@ public class cgeocaches extends AbstractListActivity { case MENU_SORT_STATE: setComparator(item, new StateComparator()); return true; - case SUBMENU_FILTER_TYPE: - showFilterMenu(TypeFilter.getAllFilters(), res.getString(R.string.caches_filter_type_title)); - return true; - case SUBMENU_FILTER_SIZE: - showFilterMenu(SizeFilter.getAllFilters(), res.getString(R.string.caches_filter_size_title)); - return true; - case SUBMENU_FILTER_ATTRIBUTES: - showFilterMenu(AttributeFilter.getAllFilters(), res.getString(R.string.cache_attributes)); - return true; - case SUBMENU_FILTER_STATE: - showFilterMenu(StateFilter.getAllFilters(), res.getString(R.string.cache_status)); - return true; - case MENU_FILTER_TRACKABLES: - setFilter(new TrackablesFilter(res.getString(R.string.caches_filter_track))); - return true; - case MENU_FILTER_MODIFIED: - setFilter(new ModifiedFilter(res.getString(R.string.caches_filter_modified))); + case MENU_FILTER: + new FilterUserInterface(this).selectFilter(new RunnableWithArgument<IFilter>() { + @Override + public void run(IFilter selectedFilter) { + if (selectedFilter != null) { + setFilter(selectedFilter); + } + else { + // clear filter + if (adapter != null) { + setFilter(null); + } + } + } + }); return true; - case MENU_FILTER_CLEAR: - if (adapter != null) { - setFilter(null); - } - return false; case MENU_IMPORT_WEB: importWeb(); return false; - case MENU_EXPORT_NOTES: - exportFieldNotes(); + case MENU_EXPORT: + exportCaches(); return false; case MENU_REMOVE_FROM_HISTORY: removeFromHistoryCheck(); @@ -1086,23 +987,6 @@ public class cgeocaches extends AbstractListActivity { return CacheListAppFactory.onMenuItemSelected(item, geo, cacheList, this, search); } - private void showFilterMenu(final IFilter[] filters, final String menuTitle) { - final AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(menuTitle); - - final String[] names = new String[filters.length]; - for (int i = 0; i < filters.length; i++) { - names[i] = filters[i].getName(); - } - builder.setItems(names, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - setFilter(filters[item]); - } - }); - - builder.create().show(); - } - private void setComparator(MenuItem item, CacheComparator comparator) { if (adapter != null) { @@ -1123,7 +1007,7 @@ public class cgeocaches extends AbstractListActivity { try { adapterInfo = (AdapterContextMenuInfo) info; } catch (Exception e) { - Log.w(Settings.tag, "cgeocaches.onCreateContextMenu: " + e.toString()); + Log.w("cgeocaches.onCreateContextMenu: " + e.toString()); } if (adapterInfo == null || adapterInfo.position >= adapter.getCount()) { @@ -1153,36 +1037,27 @@ public class cgeocaches extends AbstractListActivity { menu.add(0, MENU_MOVE_TO_LIST, 0, res.getString(R.string.cache_menu_move_list)); } } + else { + menu.add(0, MENU_STORE_CACHE, 0, res.getString(R.string.cache_offline_store)); + } } private void moveCachesToOtherList() { - final List<StoredList> cacheLists = app.getLists(); - ArrayList<String> listNames = new ArrayList<String>(); - for (StoredList list : cacheLists) { - listNames.add(list.getTitleAndCount()); - } + new StoredList.UserInterface(this).promptForListSelection(R.string.cache_menu_move_list, new RunnableWithArgument<Integer>() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(res.getString(R.string.cache_menu_move_list)); - builder.setItems(listNames.toArray(new String[listNames.size()]), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - moveCachesToList(cacheLists.get(item)); - } - }); - builder.create().show(); - } + @Override + public void run(Integer newListId) { + final boolean moveAll = adapter.getChecked() == 0; + for (final cgCache c : Collections.unmodifiableList(cacheList)) { + if (moveAll || c.isStatusChecked()) { + app.moveToList(c.getGeocode(), newListId); + } + } + adapter.resetChecks(); - private void moveCachesToList(final StoredList list) { - int newListId = list.id; - final boolean moveAll = adapter.getChecked() == 0; - for (final cgCache c : Collections.unmodifiableList(cacheList)) { - if (moveAll || c.isStatusChecked()) { - app.moveToList(c.getGeocode(), newListId); + refreshCurrentList(); } - } - adapter.resetChecks(); - - refreshCurrentList(); + }); } @Override @@ -1201,7 +1076,7 @@ public class cgeocaches extends AbstractListActivity { try { adapterInfo = (AdapterContextMenuInfo) info; } catch (Exception e) { - Log.w(Settings.tag, "cgeocaches.onContextItemSelected: " + e.toString()); + Log.w("cgeocaches.onContextItemSelected: " + e.toString()); } if (id == MENU_DEFAULT_NAVIGATION) { @@ -1223,7 +1098,7 @@ public class cgeocaches extends AbstractListActivity { return true; } else if (id == MENU_DROP_CACHE) { - cgBase.dropCache(getCacheFromAdapter(adapterInfo), new Handler() { + getCacheFromAdapter(adapterInfo).drop(new Handler() { @Override public void handleMessage(Message msg) { refreshCurrentList(); @@ -1232,23 +1107,20 @@ public class cgeocaches extends AbstractListActivity { return true; } else if (id == MENU_MOVE_TO_LIST) { final String geocode = getCacheFromAdapter(adapterInfo).getGeocode(); - final List<StoredList> cacheLists = app.getLists(); - ArrayList<String> listNames = new ArrayList<String>(); - for (StoredList list : cacheLists) { - listNames.add(list.getTitleAndCount()); - } + new StoredList.UserInterface(this).promptForListSelection(R.string.cache_menu_move_list, new RunnableWithArgument<Integer>() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(res.getString(R.string.cache_menu_move_list)); - builder.setItems(listNames.toArray(new String[listNames.size()]), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - final int newListId = cacheLists.get(item).id; + @Override + public void run(Integer newListId) { app.moveToList(geocode, newListId); adapter.resetChecks(); refreshCurrentList(); } }); - builder.create().show(); + return true; + } else if (id == MENU_STORE_CACHE) { + final cgCache cache = getCacheFromAdapter(adapterInfo); + //FIXME: this must use the same handler like in the CacheDetailActivity. Will be done by moving the handler into the store method. + cache.store(this, null); return true; } @@ -1463,8 +1335,7 @@ public class cgeocaches extends AbstractListActivity { threadDetails.start(); } - public void removeFromHistoryCheck() - { + public void removeFromHistoryCheck() { AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setCancelable(true); dialog.setTitle(res.getString(R.string.caches_removing_from_history)); @@ -1486,8 +1357,7 @@ public class cgeocaches extends AbstractListActivity { alert.show(); } - public void removeFromHistory() - { + public void removeFromHistory() { if (adapter != null && adapter.getChecked() > 0) { // there are some checked caches @@ -1508,27 +1378,22 @@ public class cgeocaches extends AbstractListActivity { threadH.start(); } - public void exportFieldNotes() - { - if (adapter != null && adapter.getChecked() > 0) - { - // there are some checked caches - detailTotal = adapter.getChecked(); - } - else - { - // no checked caches, export all - detailTotal = cacheList.size(); + public void exportCaches() { + List<cgCache> caches; + if (adapter != null && adapter.getChecked() > 0) { + // there are some caches checked + caches = new LinkedList<cgCache>(); + for (cgCache cache : cacheList) { + if (cache.isStatusChecked()) { + caches.add(cache); + } + } + } else { + // no caches checked, export all + caches = cacheList; } - detailProgress = 0; - showProgress(false); - - progress.show(this, null, res.getString(R.string.caches_exporting_fieldnote), ProgressDialog.STYLE_HORIZONTAL, exportFieldNotesHandler.obtainMessage(MSG_CANCEL)); - progress.setMaxProgressAndReset(detailTotal); - - threadF = new ExportFieldNotesThread(exportFieldNotesHandler); - threadF.start(); + ExportFactory.showExportMenu(caches, this); } public void importWeb() { @@ -1604,7 +1469,7 @@ public class cgeocaches extends AbstractListActivity { } } } catch (Exception e) { - Log.w(Settings.tag, "Failed to UpdateLocation location."); + Log.w("Failed to UpdateLocation location."); } } } @@ -1641,7 +1506,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgBase.searchByStored(coords, Settings.getCacheType(), listId); + search = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, Settings.getCacheType(), listId); handler.sendMessage(Message.obtain()); } } @@ -1671,7 +1536,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgBase.searchByNextPage(this, search, Settings.isShowCaptcha()); + search = GCParser.searchByNextPage(this, search, Settings.isShowCaptcha()); handler.sendMessage(Message.obtain()); } @@ -1698,7 +1563,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgBase.searchByCoords(this, coords, cacheType, Settings.isShowCaptcha()); + search = GCParser.searchByCoords(this, coords, cacheType, Settings.isShowCaptcha()); handler.sendMessage(Message.obtain()); } @@ -1725,7 +1590,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgBase.searchByKeyword(this, keyword, cacheType, Settings.isShowCaptcha()); + search = GCParser.searchByKeyword(this, keyword, cacheType, Settings.isShowCaptcha()); handler.sendMessage(Message.obtain()); } } @@ -1751,7 +1616,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgBase.searchByUsername(this, username, cacheType, Settings.isShowCaptcha()); + search = GCParser.searchByUsername(this, username, cacheType, Settings.isShowCaptcha()); handler.sendMessage(Message.obtain()); } } @@ -1783,7 +1648,7 @@ public class cgeocaches extends AbstractListActivity { params.put("cacheType", cacheType.id); } - search = cgBase.searchByOwner(this, username, cacheType, Settings.isShowCaptcha()); + search = GCParser.searchByOwner(this, username, cacheType, Settings.isShowCaptcha()); handler.sendMessage(Message.obtain()); } @@ -1829,7 +1694,7 @@ public class cgeocaches extends AbstractListActivity { try { if (needToStop) { - Log.i(Settings.tag, "Stopped storing process."); + Log.i("Stopped storing process."); break; } @@ -1840,26 +1705,26 @@ public class cgeocaches extends AbstractListActivity { delay = 500; } - Log.i(Settings.tag, "Waiting for next cache " + delay + " ms"); + Log.i("Waiting for next cache " + delay + " ms"); sleep(delay); } catch (Exception e) { - Log.e(Settings.tag, "cgeocaches.LoadDetailsThread.sleep: " + e.toString()); + Log.e("cgeocaches.LoadDetailsThread.sleep: " + e.toString()); } } if (needToStop) { - Log.i(Settings.tag, "Stopped storing process."); + Log.i("Stopped storing process."); break; } detailProgress++; - cgBase.refreshCache(cgeocaches.this, cache.getGeocode(), listIdLD, null); + cache.refresh(cgeocaches.this, listIdLD, null); handler.sendEmptyMessage(cacheList.indexOf(cache)); yield(); } catch (Exception e) { - Log.e(Settings.tag, "cgeocaches.LoadDetailsThread: " + e.toString()); + Log.e("cgeocaches.LoadDetailsThread: " + e.toString()); } last = System.currentTimeMillis(); @@ -1904,7 +1769,7 @@ public class cgeocaches extends AbstractListActivity { deviceCode = ""; } final Parameters params = new Parameters("code", deviceCode); - HttpResponse responseFromWeb = Network.request("http://send2.cgeo.org/read.html", params, true); + HttpResponse responseFromWeb = Network.getRequest("http://send2.cgeo.org/read.html", params); if (responseFromWeb != null && responseFromWeb.getStatusLine().getStatusCode() == 200) { final String response = Network.getResponseData(responseFromWeb); @@ -1916,7 +1781,7 @@ public class cgeocaches extends AbstractListActivity { handler.sendMessage(handler.obtainMessage(1, GCcode)); yield(); - cgBase.storeCache(cgeocaches.this, null, GCcode, listIdLFW, false, null); + cgCache.storeCache(cgeocaches.this, null, GCcode, listIdLFW, false, null); handler.sendMessage(handler.obtainMessage(2, GCcode)); yield(); @@ -1949,7 +1814,7 @@ public class cgeocaches extends AbstractListActivity { times = 0; } } catch (InterruptedException e) { - Log.e(Settings.tag, "cgeocaches.LoadFromWebThread.sleep: " + e.toString()); + Log.e("cgeocaches.LoadFromWebThread.sleep: " + e.toString()); } } @@ -1989,13 +1854,13 @@ public class cgeocaches extends AbstractListActivity { try { if (needToStop) { - Log.i(Settings.tag, "Stopped dropping process."); + Log.i("Stopped dropping process."); break; } app.markDropped(cache.getGeocode()); } catch (Exception e) { - Log.e(Settings.tag, "cgeocaches.DropDetailsThread: " + e.toString()); + Log.e("cgeocaches.DropDetailsThread: " + e.toString()); } } cacheListTemp.clear(); @@ -2036,7 +1901,7 @@ public class cgeocaches extends AbstractListActivity { try { if (needToStop) { - Log.i(Settings.tag, "Stopped removing process."); + Log.i("Stopped removing process."); break; } @@ -2047,128 +1912,7 @@ public class cgeocaches extends AbstractListActivity { yield(); } catch (Exception e) { - Log.e(Settings.tag, "cgeocaches.RemoveFromHistoryThread: " + e.toString()); - } - } - - handler.sendEmptyMessage(MSG_DONE); - } - } - - private class ExportFieldNotesThread extends Thread - { - private final Handler handler; - private volatile boolean needToStop = false; - private int checked = 0; - - public ExportFieldNotesThread(Handler handlerIn) - { - setPriority(Thread.MIN_PRIORITY); - - handler = handlerIn; - - if (adapter != null) - { - checked = adapter.getChecked(); - } - } - - public void kill() - { - needToStop = true; - } - - @Override - public void run() - { - SimpleDateFormat fieldNoteDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - StringBuilder fieldNoteBuffer = new StringBuilder(500); - - // We need our own HashMap because LogType will give us localized and maybe - // different strings than gc.com expects in the field note - // We only need such logtypes that are possible to log via c:geo - Map<LogType, String> logTypes = new HashMap<LogType, String>(); - logTypes.put(LogType.LOG_FOUND_IT, "Found it"); - logTypes.put(LogType.LOG_DIDNT_FIND_IT, "Didn't find it"); - logTypes.put(LogType.LOG_NOTE, "Write Note"); - logTypes.put(LogType.LOG_NEEDS_ARCHIVE, "Needs archived"); - logTypes.put(LogType.LOG_NEEDS_MAINTENANCE, "Needs Maintenance"); - logTypes.put(LogType.LOG_WILL_ATTEND, "Will Attend"); - logTypes.put(LogType.LOG_ATTENDED, "Attended"); - logTypes.put(LogType.LOG_WEBCAM_PHOTO_TAKEN, "Webcam Photo Taken"); - - for (cgCache cache : cacheList) { - if (checked > 0 && !cache.isStatusChecked()) { - handler.sendEmptyMessage(0); - - yield(); - continue; - } - - try { - if (needToStop) - { - Log.i(Settings.tag, "Stopped exporting process."); - break; - } - - if (cache.isLogOffline()) - { - cgLog log = app.loadLogOffline(cache.getGeocode()); - - if (null != logTypes.get(log.type)) - { - fieldNoteBuffer.append(cache.getGeocode()) - .append(',') - .append(fieldNoteDateFormat.format(new Date(log.date))) - .append(',') - .append(logTypes.get(log.type)) - .append(",\"") - .append(StringUtils.replaceChars(log.log, '"', '\'')) - .append("\"\n"); - } - } - - detailProgress++; - - handler.sendEmptyMessage(cacheList.indexOf(cache)); - - yield(); - } catch (Exception e) { - Log.e(Settings.tag, "cgeocaches.ExportFieldNotesThread: " + e.toString()); - } - } - - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) - { - File exportLocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/field-notes"); - exportLocation.mkdirs(); - - SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); - File exportFile = new File(exportLocation + "/" + fileNameDateFormat.format(new Date()) + ".txt"); - - OutputStream os = null; - Writer fw = null; - try - { - os = new FileOutputStream(exportFile); - fw = new OutputStreamWriter(os, "ISO-8859-1"); // TODO: gc.com doesn't support UTF-8 - fw.write(fieldNoteBuffer.toString()); - - Message.obtain(handler, -2, exportFile).sendToTarget(); - } catch (IOException e) { - Log.e(Settings.tag, "cgeocaches.ExportFieldNotesThread: " + e.toString()); - handler.sendEmptyMessage(-3); - } finally - { - if (fw != null) - { - try { - fw.close(); - } catch (IOException e) { - Log.e(Settings.tag, "cgeocaches.ExportFieldNotesThread: " + e.toString()); - } - } + Log.e("cgeocaches.RemoveFromHistoryThread: " + e.toString()); } } @@ -2209,41 +1953,13 @@ public class cgeocaches extends AbstractListActivity { if (type != CacheListType.OFFLINE) { return; } + new StoredList.UserInterface(this).promptForListSelection(R.string.list_title, new RunnableWithArgument<Integer>() { - lists = app.getLists(); - - if (lists == null) { - return; - } - - final List<CharSequence> listsTitle = new ArrayList<CharSequence>(); - for (StoredList list : lists) { - listsTitle.add(list.getTitleAndCount()); - } - listsTitle.add("<" + res.getString(R.string.list_menu_create) + ">"); - - final CharSequence[] items = new CharSequence[listsTitle.size()]; - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(res.getString(R.string.list_title)); - builder.setItems(listsTitle.toArray(items), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialogInterface, int itemId) { - if (itemId >= lists.size()) { - // create new list on the fly - createList(new RunnableWithArgument<Integer>() { - - @Override - public void run(final Integer arg) { - switchListById(arg.intValue()); - } - }); - } - else { - switchListById(lists.get(itemId).id); - } + @Override + public void run(final Integer selectedListId) { + switchListById(selectedListId.intValue()); } }); - builder.create().show(); } public void switchListById(int id) { @@ -2301,58 +2017,11 @@ public class cgeocaches extends AbstractListActivity { } } - private void handleListNameInput(final String defaultValue, int dialogTitle, int buttonTitle, final RunnableWithArgument<String> runnable) { - final AlertDialog.Builder alert = new AlertDialog.Builder(this); - final View view = inflater.inflate(R.layout.list_create_dialog, null); - final EditText input = (EditText) view.findViewById(R.id.text); - input.setText(defaultValue); - - alert.setTitle(dialogTitle); - alert.setView(view); - alert.setPositiveButton(buttonTitle, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - // remove whitespaces added by autocompletion of Android keyboard - String listName = StringUtils.trim(input.getText().toString()); - if (StringUtils.isNotBlank(listName)) { - runnable.run(listName); - } - } - }); - alert.setNegativeButton(res.getString(R.string.list_dialog_cancel), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - dialog.dismiss(); - } - }); - - alert.show(); - } - - private void createList(final RunnableWithArgument<Integer> runAfterwards) { - handleListNameInput("", R.string.list_dialog_create_title, R.string.list_dialog_create, new RunnableWithArgument<String>() { - - @Override - public void run(final String listName) { - final int newId = app.createList(listName); - - if (newId >= 10) { - showToast(res.getString(R.string.list_dialog_create_ok)); - if (runAfterwards != null) { - runAfterwards.run(newId); - } - } else { - showToast(res.getString(R.string.list_dialog_create_err)); - } - } - }); - } - private void renameList() { - final StoredList list = app.getList(listId); - handleListNameInput(list.title, R.string.list_dialog_rename_title, R.string.list_dialog_rename, new RunnableWithArgument<String>() { + new StoredList.UserInterface(this).promptForListRename(listId, new Runnable() { @Override - public void run(final String listName) { - app.renameList(listId, listName); + public void run() { refreshCurrentList(); } }); @@ -2461,8 +2130,7 @@ public class cgeocaches extends AbstractListActivity { Intent cachesIntent = new Intent(context, cachesActivity.getClass()); cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.COORDINATE); - cachesIntent.putExtra("latitude", coords.getLatitude()); - cachesIntent.putExtra("longitude", coords.getLongitude()); + cachesIntent.putExtra(EXTRAS_COORDS, coords); context.startActivity(cachesIntent); } @@ -2529,8 +2197,7 @@ public class cgeocaches extends AbstractListActivity { public static void startActivityNearest(final Context context, final Geopoint coordsNow) { final Intent cachesIntent = new Intent(context, cgeocaches.class); cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.NEAREST); - cachesIntent.putExtra("latitude", coordsNow.getLatitude()); - cachesIntent.putExtra("longitude", coordsNow.getLongitude()); + cachesIntent.putExtra(EXTRAS_COORDS, coordsNow); context.startActivity(cachesIntent); } @@ -2540,20 +2207,18 @@ public class cgeocaches extends AbstractListActivity { context.startActivity(cachesIntent); } - public static void startActivityAddress(Context context, double latitude, double longitude, String address) { + public static void startActivityAddress(final Context context, final Geopoint coords, final String address) { Intent addressIntent = new Intent(context, cgeocaches.class); addressIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.ADDRESS); - addressIntent.putExtra("latitude", latitude); - addressIntent.putExtra("longitude", longitude); + addressIntent.putExtra(EXTRAS_COORDS, coords); addressIntent.putExtra("address", address); context.startActivity(addressIntent); } - public static void startActivityCoordinates(final Context context, double latitude, double longitude) { + public static void startActivityCoordinates(final Context context, final Geopoint coords) { final Intent cachesIntent = new Intent(context, cgeocaches.class); cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.COORDINATE); - cachesIntent.putExtra("latitude", latitude); - cachesIntent.putExtra("longitude", longitude); + cachesIntent.putExtra(EXTRAS_COORDS, coords); context.startActivity(cachesIntent); } diff --git a/main/src/cgeo/geocaching/cgeocoords.java b/main/src/cgeo/geocaching/cgeocoords.java index b4868ce..fdedfda 100644 --- a/main/src/cgeo/geocaching/cgeocoords.java +++ b/main/src/cgeo/geocaching/cgeocoords.java @@ -419,7 +419,7 @@ public class cgeocoords extends Dialog { if (geo != null && geo.coordsNow != null) { gp = geo.coordsNow; } else { - gp = new Geopoint(0, 0); + gp = new Geopoint(0.0, 0.0); } } } diff --git a/main/src/cgeo/geocaching/cgeoimages.java b/main/src/cgeo/geocaching/cgeoimages.java index 6f12bed..bac0cad 100644 --- a/main/src/cgeo/geocaching/cgeoimages.java +++ b/main/src/cgeo/geocaching/cgeoimages.java @@ -207,7 +207,7 @@ public class cgeoimages extends AbstractActivity { image.getBitmap().compress(CompressFormat.JPEG, 100, fos); fos.close(); } catch (Exception e) { - Log.e(Settings.tag, "cgeoimages.handleMessage.onClick: " + e.toString()); + Log.e("cgeoimages.handleMessage.onClick: " + e.toString()); return; } diff --git a/main/src/cgeo/geocaching/cgeoinit.java b/main/src/cgeo/geocaching/cgeoinit.java index cb5808f..2269ad7 100644 --- a/main/src/cgeo/geocaching/cgeoinit.java +++ b/main/src/cgeo/geocaching/cgeoinit.java @@ -4,13 +4,15 @@ import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum; import cgeo.geocaching.compatibility.Compatibility; +import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.maps.MapProviderFactory; -import cgeo.geocaching.network.Login; +import cgeo.geocaching.network.Cookies; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.twitter.TwitterAuthorizationActivity; +import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate; @@ -20,6 +22,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.http.HttpResponse; import android.app.ProgressDialog; +import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.graphics.drawable.Drawable; @@ -73,7 +76,7 @@ public class cgeoinit extends AbstractActivity { } catch (Exception e) { showToast(res.getString(R.string.err_login_failed)); - Log.e(Settings.tag, "cgeoinit.logInHandler: " + e.toString()); + Log.e("cgeoinit.logInHandler: " + e.toString()); } if (loginDialog != null && loginDialog.isShowing()) { @@ -101,7 +104,7 @@ public class cgeoinit extends AbstractActivity { } catch (Exception e) { showToast(res.getString(R.string.init_sendToCgeo_register_fail)); - Log.e(Settings.tag, "cgeoinit.webHandler: " + e.toString()); + Log.e("cgeoinit.webHandler: " + e.toString()); } if (webDialog != null && webDialog.isShowing()) { @@ -731,7 +734,7 @@ public class cgeoinit extends AbstractActivity { TextView lastBackup = (TextView) findViewById(R.id.backup_last); File lastBackupFile = cgeoapplication.isRestoreFile(); if (lastBackupFile != null) { - lastBackup.setText(res.getString(R.string.init_backup_last) + " " + cgBase.formatTime(lastBackupFile.lastModified()) + ", " + cgBase.formatDate(lastBackupFile.lastModified())); + lastBackup.setText(res.getString(R.string.init_backup_last) + " " + Formatter.formatTime(lastBackupFile.lastModified()) + ", " + Formatter.formatDate(lastBackupFile.lastModified())); } else { lastBackup.setText(res.getString(R.string.init_backup_last_no)); } @@ -821,7 +824,7 @@ public class cgeoinit extends AbstractActivity { loginDialog.setCancelable(false); Settings.setLogin(username, password); - Network.clearCookies(); + Cookies.clearCookies(); (new Thread() { @@ -863,7 +866,7 @@ public class cgeoinit extends AbstractActivity { final String cod = StringUtils.defaultString(deviceCode); final Parameters params = new Parameters("name", nam, "code", cod); - HttpResponse response = Network.request("http://send2.cgeo.org/auth.html", params, true); + HttpResponse response = Network.getRequest("http://send2.cgeo.org/auth.html", params); if (response != null && response.getStatusLine().getStatusCode() == 200) { @@ -872,7 +875,7 @@ public class cgeoinit extends AbstractActivity { try { pin = Integer.parseInt(strings[1].trim()); } catch (Exception e) { - Log.e(Settings.tag, "webDialog: " + e.toString()); + Log.e("webDialog: " + e.toString()); } String code = strings[0]; Settings.setWebNameCode(nam, code); @@ -892,9 +895,18 @@ public class cgeoinit extends AbstractActivity { if (resultCode == RESULT_OK) { if (data.hasExtra("mapfile")) { Settings.setMapFile(data.getStringExtra("mapfile")); + if (!Settings.isValidMapFile(Settings.getMapFile())) { + showToast(res.getString(R.string.warn_invalid_mapfile)); + } } } initMapfileEdittext(true); } } + + public static void startActivity(Context fromActivity) { + final Intent initIntent = new Intent(fromActivity, cgeoinit.class); + fromActivity.startActivity(initIntent); + } + } diff --git a/main/src/cgeo/geocaching/cgeonavigate.java b/main/src/cgeo/geocaching/cgeonavigate.java index f5da2a1..869b9dd 100644 --- a/main/src/cgeo/geocaching/cgeonavigate.java +++ b/main/src/cgeo/geocaching/cgeonavigate.java @@ -26,8 +26,7 @@ import java.util.List; public class cgeonavigate extends AbstractActivity { - private static final String EXTRAS_LONGITUDE = "longitude"; - private static final String EXTRAS_LATITUDE = "latitude"; + private static final String EXTRAS_COORDS = "coords"; private static final String EXTRAS_NAME = "name"; private static final String EXTRAS_GEOCODE = "geocode"; private static final List<IWaypoint> coordinates = new ArrayList<IWaypoint>(); @@ -88,7 +87,7 @@ public class cgeonavigate extends AbstractActivity { geocode = extras.getString(EXTRAS_GEOCODE); title = geocode; name = extras.getString(EXTRAS_NAME); - dstCoords = new Geopoint(extras.getDouble(EXTRAS_LATITUDE), extras.getDouble(EXTRAS_LONGITUDE)); + dstCoords = (Geopoint) extras.getParcelable(EXTRAS_COORDS); if (StringUtils.isNotBlank(name)) { if (StringUtils.isNotBlank(title)) { @@ -271,7 +270,7 @@ public class cgeonavigate extends AbstractActivity { setDestCoords(); updateDistanceInfo(); - Log.d(Settings.tag, "destination set: " + title + " (" + dstCoords + ")"); + Log.d("destination set: " + title + " (" + dstCoords + ")"); return true; } @@ -294,23 +293,6 @@ public class cgeonavigate extends AbstractActivity { ((TextView) findViewById(R.id.destination)).setText(dstCoords.toString()); } - public void setDest(final Geopoint coords) { - if (coords == null) { - return; - } - - title = "some place"; - setTitle(); - setDestCoords(); - - dstCoords = coords; - updateDistanceInfo(); - } - - public Geopoint getCoordinatesNow() { - return geo.coordsNow; - } - private void updateDistanceInfo() { if (geo == null || geo.coordsNow == null || dstCoords == null) { return; @@ -384,7 +366,7 @@ public class cgeonavigate extends AbstractActivity { northHeading = geo.bearingNow; } } catch (Exception e) { - Log.w(Settings.tag, "Failed to update location."); + Log.w("Failed to update location."); } } } @@ -410,8 +392,7 @@ public class cgeonavigate extends AbstractActivity { } final Intent navigateIntent = new Intent(context, cgeonavigate.class); - navigateIntent.putExtra(EXTRAS_LATITUDE, coords.getLatitude()); - navigateIntent.putExtra(EXTRAS_LONGITUDE, coords.getLongitude()); + navigateIntent.putExtra(EXTRAS_COORDS, coords); navigateIntent.putExtra(EXTRAS_GEOCODE, geocode.toUpperCase()); if (null != displayedName) { navigateIntent.putExtra(EXTRAS_NAME, displayedName); diff --git a/main/src/cgeo/geocaching/cgeopoint.java b/main/src/cgeo/geocaching/cgeopoint.java index d3e5fba..0335453 100644 --- a/main/src/cgeo/geocaching/cgeopoint.java +++ b/main/src/cgeo/geocaching/cgeopoint.java @@ -6,6 +6,7 @@ import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.geopoint.GeopointParser; +import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; @@ -40,18 +41,18 @@ public class cgeopoint extends AbstractActivity { private static final int MENU_CACHES_AROUND = 5; private static final int MENU_CLEAR_HISTORY = 6; - private static class DestinationHistoryAdapter extends ArrayAdapter<cgDestination> { + private static class DestinationHistoryAdapter extends ArrayAdapter<Destination> { private LayoutInflater inflater = null; public DestinationHistoryAdapter(Context context, - List<cgDestination> objects) { + List<Destination> objects) { super(context, 0, objects); } @Override public View getView(final int position, final View convertView, final ViewGroup parent) { - cgDestination loc = getItem(position); + Destination loc = getItem(position); View v = convertView; @@ -70,7 +71,7 @@ public class cgeopoint extends AbstractActivity { longitude.setText(lonString); latitude.setText(latString); - date.setText(cgBase.formatShortDateTime(getContext(), loc.getDate())); + date.setText(Formatter.formatShortDateTime(getContext(), loc.getDate())); return v; } @@ -89,7 +90,7 @@ public class cgeopoint extends AbstractActivity { private Button latButton = null; private Button lonButton = null; private boolean changed = false; - private List<cgDestination> historyOfSearchedLocations; + private List<Destination> historyOfSearchedLocations; private DestinationHistoryAdapter destionationHistoryAdapter; private ListView historyListView; private TextView historyFooter; @@ -137,8 +138,8 @@ public class cgeopoint extends AbstractActivity { public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { final Object selection = arg0.getItemAtPosition(arg2); - if (selection instanceof cgDestination) { - navigateTo(((cgDestination) selection).getCoords()); + if (selection instanceof Destination) { + navigateTo(((Destination) selection).getCoords()); } } }); @@ -163,21 +164,21 @@ public class cgeopoint extends AbstractActivity { switch (item.getItemId()) { case CONTEXT_MENU_NAVIGATE: contextMenuItemPosition = position; - if (destination instanceof cgDestination) { - NavigationAppFactory.showNavigationMenu(geo, this, null, null, ((cgDestination) destination).getCoords()); + if (destination instanceof Destination) { + NavigationAppFactory.showNavigationMenu(geo, this, null, null, ((Destination) destination).getCoords()); return true; } break; case CONTEXT_MENU_DELETE_WAYPOINT: - if (destination instanceof cgDestination) { - removeFromHistory((cgDestination) destination); + if (destination instanceof Destination) { + removeFromHistory((Destination) destination); } return true; case CONTEXT_MENU_EDIT_WAYPOINT: - if (destination instanceof cgDestination) { - final Geopoint gp = ((cgDestination) destination).getCoords(); + if (destination instanceof Destination) { + final Geopoint gp = ((Destination) destination).getCoords(); latButton.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); lonButton.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); } @@ -205,7 +206,7 @@ public class cgeopoint extends AbstractActivity { return destionationHistoryAdapter; } - private List<cgDestination> getHistoryOfSearchedLocations() { + private List<Destination> getHistoryOfSearchedLocations() { if (historyOfSearchedLocations == null) { // Load from database historyOfSearchedLocations = app.getHistoryOfSearchedLocations(); @@ -382,8 +383,7 @@ public class cgeopoint extends AbstractActivity { final Geopoint coords = getDestination(); - if (coords != null) - { + if (coords != null) { addToHistory(coords); } @@ -410,12 +410,9 @@ public class cgeopoint extends AbstractActivity { private void addToHistory(final Geopoint coords) { // Add locations to history - cgDestination loc = new cgDestination(); - loc.setCoords(coords); + final Destination loc = new Destination(coords); - if (!getHistoryOfSearchedLocations().contains(loc)) - { - loc.setDate(System.currentTimeMillis()); + if (!getHistoryOfSearchedLocations().contains(loc)) { getHistoryOfSearchedLocations().add(0, loc); // Save location @@ -426,7 +423,7 @@ public class cgeopoint extends AbstractActivity { } } - private void removeFromHistory(cgDestination destination) { + private void removeFromHistory(Destination destination) { if (getHistoryOfSearchedLocations().contains(destination)) { getHistoryOfSearchedLocations().remove(destination); @@ -483,7 +480,7 @@ public class cgeopoint extends AbstractActivity { return; } - cgeocaches.startActivityCoordinates(this, coords.getLatitude(), coords.getLongitude()); + cgeocaches.startActivityCoordinates(this, coords); finish(); } @@ -500,7 +497,7 @@ public class cgeopoint extends AbstractActivity { latButton.setHint(geo.coordsNow.format(GeopointFormatter.Format.LAT_DECMINUTE_RAW)); lonButton.setHint(geo.coordsNow.format(GeopointFormatter.Format.LON_DECMINUTE_RAW)); } catch (Exception e) { - Log.w(Settings.tag, "Failed to update location."); + Log.w("Failed to update location."); } } } diff --git a/main/src/cgeo/geocaching/cgeopopup.java b/main/src/cgeo/geocaching/cgeopopup.java index 8ad07bb..99e75d8 100644 --- a/main/src/cgeo/geocaching/cgeopopup.java +++ b/main/src/cgeo/geocaching/cgeopopup.java @@ -16,6 +16,7 @@ import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; import android.app.ProgressDialog; +import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.net.Uri; @@ -74,7 +75,7 @@ public class cgeopopup extends AbstractActivity { } catch (Exception e) { showToast(res.getString(R.string.err_store)); - Log.e(Settings.tag, "cgeopopup.storeCacheHandler: " + e.toString()); + Log.e("cgeopopup.storeCacheHandler: " + e.toString()); } if (storeDialog != null) { @@ -97,7 +98,7 @@ public class cgeopopup extends AbstractActivity { } catch (Exception e) { showToast(res.getString(R.string.err_drop)); - Log.e(Settings.tag, "cgeopopup.dropCacheHandler: " + e.toString()); + Log.e("cgeopopup.dropCacheHandler: " + e.toString()); } if (dropDialog != null) { @@ -452,7 +453,7 @@ public class cgeopopup extends AbstractActivity { offlineStore.setOnClickListener(new storeCache()); } } catch (Exception e) { - Log.e(Settings.tag, "cgeopopup.init: " + e.toString()); + Log.e("cgeopopup.init: " + e.toString()); } if (geo != null) { @@ -515,7 +516,7 @@ public class cgeopopup extends AbstractActivity { cacheDistance.bringToFront(); } } catch (Exception e) { - Log.w(Settings.tag, "Failed to update location."); + Log.w("Failed to update location."); } } } @@ -595,7 +596,7 @@ public class cgeopopup extends AbstractActivity { @Override public void run() { - cgBase.dropCache(cache, handler); + cache.drop(handler); } } @@ -657,4 +658,10 @@ public class cgeopopup extends AbstractActivity { super.goManual(view); finish(); } + + public static void startActivity(final Context context, final String geocode) { + final Intent popupIntent = new Intent(context, cgeopopup.class); + popupIntent.putExtra("geocode", geocode); + context.startActivity(popupIntent); + } } diff --git a/main/src/cgeo/geocaching/cgeotouch.java b/main/src/cgeo/geocaching/cgeotouch.java index 09857a2..56b5ba1 100644 --- a/main/src/cgeo/geocaching/cgeotouch.java +++ b/main/src/cgeo/geocaching/cgeotouch.java @@ -1,13 +1,15 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.connector.gc.GCParser; +import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; -import cgeo.geocaching.network.Login; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.twitter.Twitter; import cgeo.geocaching.ui.DateDialog; +import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; @@ -63,7 +65,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog setType((LogType) msg.obj); showToast(res.getString(R.string.info_log_type_changed)); } else { - if (cgBase.isEmpty(viewstates) && attempts < 2) { + if (Login.isEmpty(viewstates) && attempts < 2) { showToast(res.getString(R.string.err_log_load_data_again)); loadData thread; @@ -71,7 +73,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog thread.start(); return; - } else if (cgBase.isEmpty(viewstates) && attempts >= 2) { + } else if (Login.isEmpty(viewstates) && attempts >= 2) { showToast(res.getString(R.string.err_log_load_data)); showProgress(false); @@ -203,8 +205,8 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog textContent = text.getText().toString(); final long now = System.currentTimeMillis(); - dateString = cgBase.formatDate(now); - timeString = cgBase.formatTime(now); + dateString = Formatter.formatDate(now); + timeString = Formatter.formatTime(now); if ((id & 0x4) == 0x4) { addText += dateString; @@ -287,7 +289,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog }); Button dateButton = (Button) findViewById(R.id.date); - dateButton.setText(cgBase.formatShortDate(date.getTime().getTime())); + dateButton.setText(Formatter.formatShortDate(date.getTime().getTime())); dateButton.setOnClickListener(new cgeotouchDateListener()); if (tweetBox == null) { @@ -299,7 +301,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog tweetCheck.setChecked(true); Button buttonPost = (Button) findViewById(R.id.post); - if (cgBase.isEmpty(viewstates)) { + if (Login.isEmpty(viewstates)) { buttonPost.setEnabled(false); buttonPost.setOnTouchListener(null); buttonPost.setOnClickListener(null); @@ -319,7 +321,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog date = dateIn; final Button dateButton = (Button) findViewById(R.id.date); - dateButton.setText(cgBase.formatShortDate(date.getTime().getTime())); + dateButton.setText(Formatter.formatShortDate(date.getTime().getTime())); } public void setType(LogType type) { @@ -392,11 +394,11 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog return; } - final String page = Network.getResponseData(Network.request("http://www.geocaching.com/track/log.aspx", params, false, false, false)); + final String page = Network.getResponseData(Network.getRequest("http://www.geocaching.com/track/log.aspx", params)); viewstates = Login.getViewstates(page); - final List<LogType> typesPre = cgBase.parseTypes(page); + final List<LogType> typesPre = GCParser.parseTypes(page); if (typesPre.size() > 0) { logTypes.clear(); logTypes.addAll(typesPre); @@ -408,7 +410,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog loadDataHandler.obtainMessage(MSG_UPDATE_TYPE, typeSelected).sendToTarget(); } } catch (Exception e) { - Log.e(Settings.tag, "cgeotouch.loadData.run: " + e.toString()); + Log.e("cgeotouch.loadData.run: " + e.toString()); } loadDataHandler.sendEmptyMessage(0); @@ -442,7 +444,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog tweetCheck = (CheckBox) findViewById(R.id.tweet); } - final StatusCode status = cgBase.postLogTrackable(guid, tracking, viewstates, typeSelected, date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), log); + final StatusCode status = GCParser.postLogTrackable(guid, tracking, viewstates, typeSelected, date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), log); if (status == StatusCode.NO_ERROR && Settings.isUseTwitter() && Settings.isTwitterLoginValid() && @@ -452,7 +454,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog return status; } catch (Exception e) { - Log.e(Settings.tag, "cgeotouch.postLogFn: " + e.toString()); + Log.e("cgeotouch.postLogFn: " + e.toString()); } return StatusCode.LOG_POST_ERROR; diff --git a/main/src/cgeo/geocaching/cgeotrackable.java b/main/src/cgeo/geocaching/cgeotrackable.java index 7b310ed..923e420 100644 --- a/main/src/cgeo/geocaching/cgeotrackable.java +++ b/main/src/cgeo/geocaching/cgeotrackable.java @@ -1,11 +1,12 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.geopoint.HumanDistance; import cgeo.geocaching.network.HtmlImage; +import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import android.app.ProgressDialog; @@ -155,7 +156,7 @@ public class cgeotrackable extends AbstractActivity { // trackable released if (trackable.getReleased() != null) { - addDetail(R.string.trackable_released, cgBase.formatDate(trackable.getReleased().getTime())); + addDetail(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime())); } // trackable distance @@ -221,7 +222,7 @@ public class cgeotrackable extends AbstractActivity { Message message = handler.obtainMessage(0, image); handler.sendMessage(message); } catch (Exception e) { - Log.e(Settings.tag, "cgeospoilers.onCreate.onClick.run: " + e.toString()); + Log.e("cgeospoilers.onCreate.onClick.run: " + e.toString()); } } }.start(); @@ -229,7 +230,7 @@ public class cgeotrackable extends AbstractActivity { imgView.addView(trackableImage); } } catch (Exception e) { - Log.e(Settings.tag, "cgeotrackable.loadTrackableHandler: " + e.toString() + Arrays.toString(e.getStackTrace())); + Log.e("cgeotrackable.loadTrackableHandler: " + e.toString() + Arrays.toString(e.getStackTrace())); } displayLogs(); @@ -428,7 +429,7 @@ public class cgeotrackable extends AbstractActivity { trackable = cgeoapplication.getInstance().getTrackableByGeocode(geocode); if ((trackable == null || trackable.isLoggable()) && !StringUtils.startsWithIgnoreCase(geocode, "GK")) { - trackable = cgBase.searchTrackable(geocode, guid, id); + trackable = GCParser.searchTrackable(geocode, guid, id); } handler.sendMessage(Message.obtain()); } @@ -442,11 +443,11 @@ public class cgeotrackable extends AbstractActivity { RelativeLayout rowView; if (trackable != null && trackable.getLogs() != null) { - for (cgLog log : trackable.getLogs()) { + for (LogEntry log : trackable.getLogs()) { rowView = (RelativeLayout) inflater.inflate(R.layout.trackable_logs_item, null); if (log.date > 0) { - ((TextView) rowView.findViewById(R.id.added)).setText(cgBase.formatShortDate(log.date)); + ((TextView) rowView.findViewById(R.id.added)).setText(Formatter.formatShortDate(log.date)); } ((TextView) rowView.findViewById(R.id.type)).setText(log.type.getL10n()); @@ -460,10 +461,7 @@ public class cgeotrackable extends AbstractActivity { final String cacheName = log.cacheName; ((TextView) rowView.findViewById(R.id.location)).setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { - Intent cacheIntent = new Intent(cgeotrackable.this, CacheDetailActivity.class); - cacheIntent.putExtra("guid", cacheGuid); - cacheIntent.putExtra("name", Html.fromHtml(cacheName).toString()); - startActivity(cacheIntent); + CacheDetailActivity.startActivityGuid(cgeotrackable.this, cacheGuid, Html.fromHtml(cacheName).toString()); } }); } @@ -475,9 +473,9 @@ public class cgeotrackable extends AbstractActivity { // add LogImages LinearLayout logLayout = (LinearLayout) rowView.findViewById(R.id.log_layout); - if (CollectionUtils.isNotEmpty(log.logImages)) { + if (log.hasLogImages()) { - final ArrayList<cgImage> logImages = new ArrayList<cgImage>(log.logImages); + final ArrayList<cgImage> logImages = new ArrayList<cgImage>(log.getLogImages()); final View.OnClickListener listener = new View.OnClickListener() { @Override @@ -487,8 +485,8 @@ public class cgeotrackable extends AbstractActivity { }; ArrayList<String> titles = new ArrayList<String>(); - for (int i_img_cnt = 0; i_img_cnt < log.logImages.size(); i_img_cnt++) { - String img_title = log.logImages.get(i_img_cnt).getTitle(); + for (cgImage image : log.getLogImages()) { + String img_title = image.getTitle(); if (!StringUtils.isBlank(img_title)) { titles.add(img_title); } @@ -525,7 +523,7 @@ public class cgeotrackable extends AbstractActivity { registerForContextMenu(view); openContextMenu(view); } catch (Exception e) { - Log.e(Settings.tag, "cgeotrackable.userActions.onClick ", e); + Log.e("cgeotrackable.userActions.onClick ", e); } } } @@ -573,7 +571,7 @@ public class cgeotrackable extends AbstractActivity { Message message = handler.obtainMessage(0, image); handler.sendMessage(message); } catch (Exception e) { - Log.e(Settings.tag, "cgeotrackable.tbIconThread.run: " + e.toString()); + Log.e("cgeotrackable.tbIconThread.run: " + e.toString()); } } } diff --git a/main/src/cgeo/geocaching/cgeowaypoint.java b/main/src/cgeo/geocaching/cgeowaypoint.java index 89450ec..2c14601 100644 --- a/main/src/cgeo/geocaching/cgeowaypoint.java +++ b/main/src/cgeo/geocaching/cgeowaypoint.java @@ -9,6 +9,7 @@ import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; import android.app.ProgressDialog; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; @@ -111,7 +112,7 @@ public class cgeowaypoint extends AbstractActivity { waitDialog.dismiss(); waitDialog = null; } - Log.e(Settings.tag, "cgeowaypoint.loadWaypointHandler: " + e.toString()); + Log.e("cgeowaypoint.loadWaypointHandler: " + e.toString()); } } @@ -295,7 +296,7 @@ public class cgeowaypoint extends AbstractActivity { loadWaypointHandler.sendMessage(Message.obtain()); } catch (Exception e) { - Log.e(Settings.tag, "cgeowaypoint.loadWaypoint.run: " + e.toString()); + Log.e("cgeowaypoint.loadWaypoint.run: " + e.toString()); } } } @@ -383,4 +384,10 @@ public class cgeowaypoint extends AbstractActivity { } return NavigationAppFactory.onMenuItemSelected(item, geo, this, null, waypoint, null); } + + public static void startActivity(final Context context, final int waypointId) { + Intent popupIntent = new Intent(context, cgeowaypoint.class); + popupIntent.putExtra("waypoint", waypointId); + context.startActivity(popupIntent); + } } diff --git a/main/src/cgeo/geocaching/cgeowaypointadd.java b/main/src/cgeo/geocaching/cgeowaypointadd.java index 4bc5be0..196a8b3 100644 --- a/main/src/cgeo/geocaching/cgeowaypointadd.java +++ b/main/src/cgeo/geocaching/cgeowaypointadd.java @@ -9,6 +9,7 @@ import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.geopoint.GeopointParser; +import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; @@ -72,7 +73,12 @@ public class cgeowaypointadd extends AbstractActivity { ((Button) findViewById(R.id.buttonLongitude)).setText(waypoint.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE)); } ((EditText) findViewById(R.id.name)).setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getName())).toString()); - ((EditText) findViewById(R.id.note)).setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getNote())).toString()); + if (BaseUtils.containsHtml(waypoint.getNote())) { + ((EditText) findViewById(R.id.note)).setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getNote())).toString()); + } + else { + ((EditText) findViewById(R.id.note)).setText(StringUtils.trimToEmpty(waypoint.getNote())); + } } if (own) { @@ -81,7 +87,7 @@ public class cgeowaypointadd extends AbstractActivity { initializeDistanceUnitSelector(); } catch (Exception e) { - Log.e(Settings.tag, "cgeowaypointadd.loadWaypointHandler: " + e.toString()); + Log.e("cgeowaypointadd.loadWaypointHandler: " + e.toString()); } finally { if (waitDialog != null) { waitDialog.dismiss(); @@ -136,7 +142,10 @@ public class cgeowaypointadd extends AbstractActivity { Button addWaypoint = (Button) findViewById(R.id.add_waypoint); addWaypoint.setOnClickListener(new coordsListener()); - List<String> wayPointNames = new ArrayList<String>(WaypointType.ALL_TYPES_EXCEPT_OWN.values()); + List<String> wayPointNames = new ArrayList<String>(); + for (WaypointType wpt : WaypointType.ALL_TYPES_EXCEPT_OWN) { + wayPointNames.add(wpt.getL10n()); + } AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.name); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, wayPointNames); textView.setAdapter(adapter); @@ -208,7 +217,7 @@ public class cgeowaypointadd extends AbstractActivity { Spinner waypointTypeSelector = (Spinner) findViewById(R.id.type); - wpTypes = new ArrayList<WaypointType>(WaypointType.ALL_TYPES_EXCEPT_OWN.keySet()); + wpTypes = new ArrayList<WaypointType>(WaypointType.ALL_TYPES_EXCEPT_OWN); ArrayAdapter<WaypointType> wpAdapter = new ArrayAdapter<WaypointType>(this, android.R.layout.simple_spinner_item, wpTypes.toArray(new WaypointType[wpTypes.size()])); wpAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); waypointTypeSelector.setAdapter(wpAdapter); @@ -245,7 +254,7 @@ public class cgeowaypointadd extends AbstractActivity { @Override public void updateLocation(cgGeo geo) { - Log.d(Settings.tag, "cgeowaypointadd.updateLocation called"); + Log.d("cgeowaypointadd.updateLocation called"); if (geo == null || geo.coordsNow == null) { return; } @@ -256,7 +265,7 @@ public class cgeowaypointadd extends AbstractActivity { bLat.setHint(geo.coordsNow.format(GeopointFormatter.Format.LAT_DECMINUTE_RAW)); bLon.setHint(geo.coordsNow.format(GeopointFormatter.Format.LON_DECMINUTE_RAW)); } catch (Exception e) { - Log.w(Settings.tag, "Failed to update location."); + Log.w("Failed to update location."); } } } @@ -270,7 +279,7 @@ public class cgeowaypointadd extends AbstractActivity { loadWaypointHandler.sendMessage(Message.obtain()); } catch (Exception e) { - Log.e(Settings.tag, "cgeowaypoint.loadWaypoint.run: " + e.toString()); + Log.e("cgeowaypoint.loadWaypoint.run: " + e.toString()); } } } diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java index 72058cd..0fc9624 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java @@ -1,6 +1,5 @@ package cgeo.geocaching.compatibility; -import cgeo.geocaching.Settings; import cgeo.geocaching.utils.Log; import android.app.Activity; @@ -15,7 +14,7 @@ public class AndroidLevel8 implements AndroidLevel8Interface { } public void dataChanged(final String name) { - Log.i(Settings.tag, "Requesting settings backup with settings manager"); + Log.i("Requesting settings backup with settings manager"); BackupManager.dataChanged(name); } } diff --git a/main/src/cgeo/geocaching/compatibility/Compatibility.java b/main/src/cgeo/geocaching/compatibility/Compatibility.java index bfc491e..6086604 100644 --- a/main/src/cgeo/geocaching/compatibility/Compatibility.java +++ b/main/src/cgeo/geocaching/compatibility/Compatibility.java @@ -1,6 +1,5 @@ package cgeo.geocaching.compatibility; -import cgeo.geocaching.Settings; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.utils.Log; @@ -54,7 +53,7 @@ public final class Compatibility { } } catch (final Exception e) { // This should never happen: IllegalArgumentException, IllegalAccessException or InvocationTargetException - Log.e(Settings.tag, "Cannot call getRotation()", e); + Log.e("Cannot call getRotation()", e); } } else { final Display display = activity.getWindowManager() @@ -95,7 +94,7 @@ public final class Compatibility { try { MethodUtils.invokeMethod(activity, "overridePendingTransition", enterAnim, exitAnim); } catch (Exception e) { - Log.e(Settings.tag, "cannot call overridePendingTransition", e); + Log.e("cannot call overridePendingTransition", e); } } diff --git a/main/src/cgeo/geocaching/concurrent/Task.java b/main/src/cgeo/geocaching/concurrent/Task.java deleted file mode 100644 index 2472538..0000000 --- a/main/src/cgeo/geocaching/concurrent/Task.java +++ /dev/null @@ -1,16 +0,0 @@ -package cgeo.geocaching.concurrent; - -/** - * Basic class for Runnables added to ThreadPool. - */ -public abstract class Task implements Runnable { - private String name = null; - - public Task(String name) { - this.name = name; - } - - public String getName() { - return this.name; - } -} diff --git a/main/src/cgeo/geocaching/connector/gc/GCBase.java b/main/src/cgeo/geocaching/connector/gc/GCBase.java index 871e75a..2f22c52 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCBase.java +++ b/main/src/cgeo/geocaching/connector/gc/GCBase.java @@ -2,7 +2,6 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheSize; @@ -13,11 +12,11 @@ import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.IConversion; import cgeo.geocaching.geopoint.Viewport; -import cgeo.geocaching.network.Login; import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.Parameters; import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.BaseUtils; -import cgeo.geocaching.utils.LeastRecentlyUsedCache; +import cgeo.geocaching.utils.LeastRecentlyUsedMap; import cgeo.geocaching.utils.Log; import org.apache.commons.collections.CollectionUtils; @@ -31,6 +30,7 @@ import android.graphics.Bitmap; import java.text.ParseException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -52,6 +52,9 @@ public class GCBase { protected final static long GC_BASE31 = 31; protected final static long GC_BASE16 = 16; + private final static LeastRecentlyUsedMap<Integer, Tile> tileCache = new LeastRecentlyUsedMap.LruCache<Integer, Tile>(64); + private static Viewport lastSearchViewport = null; + /** * Searches the view port on the live map with Strategy.AUTO * @@ -84,6 +87,17 @@ public class GCBase { } } + public static void removeFromTileCache(Geopoint coords) { + if (coords != null) { + Collection<Tile> tiles = new ArrayList<Tile>(tileCache.values()); + for (Tile tile : tiles) { + if (tile.containsPoint(coords)) { + tileCache.remove(tile.hashCode()); + } + } + } + } + /** * Searches the view port on the live map for caches. * The strategy dictates if only live map information is used or if an additional @@ -98,7 +112,7 @@ public class GCBase { * @return */ private static SearchResult searchByViewport(final Viewport viewport, final String[] tokens, Strategy strategy) { - Log.d(Settings.tag, "GCBase.searchByViewport" + viewport.toString()); + Log.d("GCBase.searchByViewport" + viewport.toString()); String referer = GCConstants.URL_LIVE_MAP; @@ -110,58 +124,76 @@ public class GCBase { for (Tile tile : tiles) { - StringBuilder url = new StringBuilder(); - url.append("?x=").append(tile.getX()) // x tile - .append("&y=").append(tile.getY()) // y tile - .append("&z=").append(tile.getZoomlevel()); // zoom level - if (tokens != null) { - url.append("&k=").append(tokens[0]); // user session - url.append("&st=").append(tokens[1]); // session token - } - url.append("&ep=1"); - if (Settings.isExcludeMyCaches()) { - url.append("&hf=1").append("&hh=1"); // hide found, hide hidden - } - if (Settings.getCacheType() == CacheType.TRADITIONAL) { - url.append("&ect=9,5,3,6,453,13,1304,137,11,4,8,1858"); // 2 = tradi 3 = multi 8 = mystery - } - if (Settings.getCacheType() == CacheType.MULTI) { - url.append("&ect=9,5,2,6,453,13,1304,137,11,4,8,1858"); - } - if (Settings.getCacheType() == CacheType.MYSTERY) { - url.append("&ect=9,5,3,6,453,13,1304,137,11,4,2,1858"); - } - if (tile.getZoomlevel() != 14) { - url.append("&_=").append(String.valueOf(System.currentTimeMillis())); - } - // other types t.b.d - final String urlString = url.toString(); + if (!tileCache.containsKey(tile.hashCode())) { + final Parameters params = new Parameters( + "x", String.valueOf(tile.getX()), + "y", String.valueOf(tile.getY()), + "z", String.valueOf(tile.getZoomlevel()), + "ep", "1"); + if (tokens != null) { + params.put("k", tokens[0], "st", tokens[1]); + } + if (Settings.isExcludeMyCaches()) { + params.put("hf", "1", "hh", "1"); // hide found, hide hidden + } + if (Settings.getCacheType() == CacheType.TRADITIONAL) { + params.put("ect", "9,5,3,6,453,13,1304,137,11,4,8,1858"); // 2 = tradi 3 = multi 8 = mystery + } else if (Settings.getCacheType() == CacheType.MULTI) { + params.put("ect", "9,5,2,6,453,13,1304,137,11,4,8,1858"); + } else if (Settings.getCacheType() == CacheType.MYSTERY) { + params.put("ect", "9,5,3,6,453,13,1304,137,11,4,2,1858"); + } + if (tile.getZoomlevel() != 14) { + params.put("_", String.valueOf(System.currentTimeMillis())); + } + // TODO: other types t.b.d - // The PNG must be request before ! Else the following request would return with 204 - No Content - Bitmap bitmap = Tile.requestMapTile(GCConstants.URL_MAP_TILE + urlString, referer); + // The PNG must be requested first, otherwise the following request would always return with 204 - No Content + Bitmap bitmap = Tile.requestMapTile(GCConstants.URL_MAP_TILE, params, referer); - assert bitmap.getWidth() == Tile.TILE_SIZE : "Bitmap has wrong width"; - assert bitmap.getHeight() == Tile.TILE_SIZE : "Bitmap has wrong height"; + // Check bitmap size + if (bitmap != null && (bitmap.getWidth() != Tile.TILE_SIZE || + bitmap.getHeight() != Tile.TILE_SIZE)) { + bitmap.recycle(); + bitmap = null; + } - String data = Tile.requestMapInfo(GCConstants.URL_MAP_INFO + urlString, referer); - if (StringUtils.isEmpty(data)) { - Log.e(Settings.tag, "GCBase.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")"); - } else { - final SearchResult search = parseMapJSON(data, tile, bitmap, strategy); - if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) { - Log.e(Settings.tag, "GCBase.searchByViewport: No cache parsed for viewport " + viewport); + String data = Tile.requestMapInfo(GCConstants.URL_MAP_INFO, params, referer); + if (StringUtils.isEmpty(data)) { + Log.e("GCBase.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")"); + } else { + final SearchResult search = parseMapJSON(data, tile, bitmap, strategy); + if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) { + Log.e("GCBase.searchByViewport: No cache parsed for viewport " + viewport); + } + else { + searchResult.addGeocodes(search.getGeocodes()); + } + tileCache.put(tile.hashCode(), tile); } - else { - searchResult.addGeocodes(search.getGeocodes()); + + // release native bitmap memory + if (bitmap != null) { + bitmap.recycle(); } + } } } if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY)) { - SearchResult search = cgBase.searchByCoords(null, viewport.getCenter(), Settings.getCacheType(), false); - if (search != null) { - searchResult.addGeocodes(search.getGeocodes()); + Geopoint center = viewport.getCenter(); + if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) { + SearchResult search = GCParser.searchByCoords(null, center, Settings.getCacheType(), false); + if (search != null && !search.isEmpty()) { + final Set<String> geocodes = search.getGeocodes(); + if (Settings.isPremiumMember()) { + lastSearchViewport = cgeoapplication.getInstance().getBounds(geocodes); + } else { + lastSearchViewport = new Viewport(center, 0.01, 0.01); + } + searchResult.addGeocodes(geocodes); + } } } @@ -180,7 +212,7 @@ public class GCBase { try { - final LeastRecentlyUsedCache<String, String> nameCache = new LeastRecentlyUsedCache<String, String>(2000); // JSON id, cache name + final LeastRecentlyUsedMap<String, String> nameCache = new LeastRecentlyUsedMap.LruCache<String, String>(2000); // JSON id, cache name if (StringUtils.isEmpty(data)) { throw new JSONException("No page given"); @@ -265,7 +297,7 @@ public class GCBase { cache.setName(nameCache.get(id)); cache.setZoomlevel(tile.getZoomlevel()); cache.setCoords(tile.getCoord(xy)); - if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && positions.size() < 64) { + if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && positions.size() < 64 && bitmap != null) { // don't parse if there are too many caches. The decoding would return too much wrong results IconDecoder.parseMapPNG(cache, bitmap, xy, tile.getZoomlevel()); } else { @@ -273,10 +305,10 @@ public class GCBase { } searchResult.addCache(cache); } - Log.d(Settings.tag, "Retrieved " + searchResult.getCount() + " caches for tile " + tile.toString()); + Log.d("Retrieved " + searchResult.getCount() + " caches for tile " + tile.toString()); } catch (Exception e) { - Log.e(Settings.tag, "GCBase.parseMapJSON", e); + Log.e("GCBase.parseMapJSON", e); } return searchResult; @@ -325,65 +357,9 @@ public class GCBase { return gcid; } - private static String modulo(final long value, final long base, final String sequence) { - String result = ""; - long rest = 0; - long divResult = value; - do - { - rest = divResult % base; - divResult = (int) Math.floor(divResult / base); - result = sequence.charAt((int) rest) + result; - } while (divResult != 0); - return result; - } - - /** - * Convert (old) GCIds to GCCode (geocode) - * - * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40 - */ - public static String gcidToGCCode(final long gcid) { - String gccode = modulo(gcid + 411120, GC_BASE31, SEQUENCE_GCID); - if ((gccode.length() < 4) || (gccode.length() == 4 && SEQUENCE_GCID.indexOf(gccode.charAt(0)) < 16)) { - gccode = modulo(gcid, GC_BASE16, SEQUENCE_GCID); - } - return "GC" + gccode; - } - - /** - * Convert ids from the live map to (old) GCIds - * - * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40 - */ - public static long newidToGCId(final String newid) { - long gcid = 0; - for (int p = 0; p < newid.length(); p++) { - gcid = GC_BASE57 * gcid + SEQUENCE_NEWID.indexOf(newid.charAt(p)); - } - return gcid; - } - - /** - * Convert (old) GCIds to ids used in the live map - * - * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40 - */ - public static String gcidToNewId(final long gcid) { - return modulo(gcid, GC_BASE57, SEQUENCE_NEWID); - } - - /** - * Convert ids from the live map into GCCode (geocode) - */ - public static String newidToGeocode(final String newid) { - long gcid = GCBase.newidToGCId(newid); - return GCBase.gcidToGCCode(gcid); - } - /** Get user session & session token from the Live Map. Needed for following requests */ public static String[] getTokens() { - final HttpResponse response = Network.request(GCConstants.URL_LIVE_MAP, null, false); + final HttpResponse response = Network.getRequest(GCConstants.URL_LIVE_MAP); final String data = Network.getResponseData(response); String userSession = BaseUtils.getMatch(data, GCConstants.PATTERN_USERSESSION, ""); String sessionToken = BaseUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, ""); @@ -392,18 +368,14 @@ public class GCBase { public static SearchResult searchByGeocodes(final Set<String> geocodes) { - SearchResult result = new SearchResult(); + final SearchResult result = new SearchResult(); final String geocodeList = StringUtils.join(geocodes.toArray(), "|"); - - String referer = GCConstants.URL_LIVE_MAP_DETAILS; - - StringBuilder url = new StringBuilder(); - url.append("?i=").append(geocodeList).append("&_=").append(String.valueOf(System.currentTimeMillis())); - final String urlString = url.toString(); + final String referer = GCConstants.URL_LIVE_MAP_DETAILS; try { - String data = Tile.requestMapInfo(referer + urlString, referer); + final Parameters params = new Parameters("i", geocodeList, "_", String.valueOf(System.currentTimeMillis())); + final String data = Tile.requestMapInfo(referer, params, referer); // Example JSON information // {"status":"success", diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java index d955418..a431359 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java @@ -3,13 +3,11 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.connector.AbstractConnector; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.geopoint.Viewport; -import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; @@ -17,7 +15,6 @@ import cgeo.geocaching.utils.Log; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; - import java.util.Set; import java.util.regex.Pattern; @@ -90,7 +87,7 @@ public class GCConnector extends AbstractConnector { public SearchResult searchByGeocode(final String geocode, final String guid, final cgeoapplication app, final CancellableHandler handler) { if (app == null) { - Log.e(Settings.tag, "cgeoBase.searchByGeocode: No application found"); + Log.e("cgeoBase.searchByGeocode: No application found"); return null; } @@ -103,15 +100,15 @@ public class GCConnector extends AbstractConnector { params.put("log", "y"); params.put("numlogs", String.valueOf(GCConstants.NUMBER_OF_LOGS)); - cgBase.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_loadpage); + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_loadpage); - final String page = Network.requestLogged("http://www.geocaching.com/seek/cache_details.aspx", params, false, false, false); + final String page = Login.getRequestLogged("http://www.geocaching.com/seek/cache_details.aspx", params); if (StringUtils.isEmpty(page)) { final SearchResult search = new SearchResult(); if (app.isThere(geocode, guid, true, false)) { if (StringUtils.isBlank(geocode) && StringUtils.isNotBlank(guid)) { - Log.i(Settings.tag, "Loading old cache from cache."); + Log.i("Loading old cache from cache."); search.addGeocode(app.getGeocode(guid)); } else { @@ -121,15 +118,15 @@ public class GCConnector extends AbstractConnector { return search; } - Log.e(Settings.tag, "cgeoBase.searchByGeocode: No data from server"); + Log.e("cgeoBase.searchByGeocode: No data from server"); search.setError(StatusCode.COMMUNICATION_ERROR); return search; } - final SearchResult searchResult = cgBase.parseCache(page, handler); + final SearchResult searchResult = GCParser.parseCache(page, handler); if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) { - Log.e(Settings.tag, "cgeoBase.searchByGeocode: No cache parsed"); + Log.e("cgeoBase.searchByGeocode: No cache parsed"); return searchResult; } diff --git a/main/src/cgeo/geocaching/cgBase.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index 090bffc..cf7c762 100644 --- a/main/src/cgeo/geocaching/cgBase.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -1,14 +1,19 @@ -// $codepro.audit.disable logExceptions -package cgeo.geocaching; - -import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.connector.ConnectorFactory; -import cgeo.geocaching.connector.gc.GCConnector; -import cgeo.geocaching.connector.gc.GCConstants; +package cgeo.geocaching.connector.gc; + +import cgeo.geocaching.LogEntry; +import cgeo.geocaching.R; +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.TrackableLog; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgImage; +import cgeo.geocaching.cgSearchThread; +import cgeo.geocaching.cgTrackable; +import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.LogTypeTrackable; @@ -19,8 +24,6 @@ import cgeo.geocaching.gcvote.GCVote; import cgeo.geocaching.gcvote.GCVoteRating; import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.network.HtmlImage; -import cgeo.geocaching.network.Login; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.ui.DirectionImage; @@ -36,20 +39,10 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; import android.net.Uri; -import android.os.Handler; -import android.os.Message; import android.text.Html; import android.text.Spannable; import android.text.Spanned; -import android.text.format.DateUtils; import android.text.style.StrikethroughSpan; import java.net.URLDecoder; @@ -57,74 +50,20 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.regex.Matcher; -public class cgBase { - +public abstract class GCParser { private final static SimpleDateFormat dateTbIn1 = new SimpleDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009 private final static SimpleDateFormat dateTbIn2 = new SimpleDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009 - public static String version = null; - - private static Context context; - public static Resources res; - - public static final int UPDATE_LOAD_PROGRESS_DETAIL = 42186; - - private cgBase() { - //initialize(app); - throw new UnsupportedOperationException(); // static class, not to be instantiated - } - - /** - * Called from AbstractActivity.onCreate() and AbstractListActivity.onCreate() - * - * @param app - */ - public static void initialize(final cgeoapplication app) { - context = app.getBaseContext(); - res = app.getBaseContext().getResources(); - - try { - final PackageManager manager = app.getPackageManager(); - final PackageInfo info = manager.getPackageInfo(app.getPackageName(), 0); - version = info.versionName; - } catch (PackageManager.NameNotFoundException e) { - Log.e(Settings.tag, "unable to get version information", e); - version = null; - } - } - - public static void sendLoadProgressDetail(final Handler handler, final int str) { - if (null != handler) { - handler.obtainMessage(UPDATE_LOAD_PROGRESS_DETAIL, cgeoapplication.getInstance().getString(str)).sendToTarget(); - } - } - - /** - * checks if an Array of Strings is empty or not. Empty means: - * - Array is null - * - or all elements are null or empty strings - */ - public static boolean isEmpty(String[] a) { - if (a == null) { - return true; - } - - for (String s : a) { - if (StringUtils.isNotEmpty(s)) { - return false; - } - } - return true; - } private static SearchResult parseSearch(final cgSearchThread thread, final String url, final String pageContent, final boolean showCaptcha) { if (StringUtils.isBlank(pageContent)) { - Log.e(Settings.tag, "cgeoBase.parseSearch: No page given"); + Log.e("cgeoBase.parseSearch: No page given"); return null; } @@ -144,7 +83,7 @@ public class cgBase { if (recaptchaJsParam != null) { final Parameters params = new Parameters("k", recaptchaJsParam.trim()); - final String recaptchaJs = Network.getResponseData(Network.request("http://www.google.com/recaptcha/api/challenge", params, true)); + final String recaptchaJs = Network.getResponseData(Network.getRequest("http://www.google.com/recaptcha/api/challenge", params)); if (StringUtils.isNotBlank(recaptchaJs)) { recaptchaChallenge = BaseUtils.getMatch(recaptchaJs, GCConstants.PATTERN_SEARCH_RECAPTCHACHALLENGE, true, 1, null, true); @@ -163,7 +102,7 @@ public class cgBase { int startPos = page.indexOf("<div id=\"ctl00_ContentBody_ResultsPanel\""); if (startPos == -1) { - Log.e(Settings.tag, "cgeoBase.parseSearch: ID \"ctl00_ContentBody_dlResults\" not found on page"); + Log.e("cgeoBase.parseSearch: ID \"ctl00_ContentBody_dlResults\" not found on page"); return null; } @@ -172,7 +111,7 @@ public class cgBase { startPos = page.indexOf('>'); int endPos = page.indexOf("ctl00_ContentBody_UnitTxt"); if (startPos == -1 || endPos == -1) { - Log.e(Settings.tag, "cgeoBase.parseSearch: ID \"ctl00_ContentBody_UnitTxt\" not found on page"); + Log.e("cgeoBase.parseSearch: ID \"ctl00_ContentBody_UnitTxt\" not found on page"); return null; } @@ -215,7 +154,7 @@ public class cgBase { } } catch (Exception e) { // failed to parse GUID and/or Disabled - Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse GUID and/or Disabled data"); + Log.w("cgeoBase.parseSearch: Failed to parse GUID and/or Disabled data"); } if (Settings.isExcludeDisabledCaches() && (cache.isDisabled() || cache.isArchived())) { @@ -276,14 +215,14 @@ public class cgBase { cids.add(cache.getCacheId()); } - // favourite count + // favorite count try { result = BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_FAVORITE, false, 1, null, true); if (null != result) { cache.setFavoritePoints(Integer.parseInt(result)); } } catch (NumberFormatException e) { - Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse favourite count"); + Log.w("cgeoBase.parseSearch: Failed to parse favourite count"); } if (cache.getNameSp() == null) { @@ -303,7 +242,7 @@ public class cgBase { searchResult.setTotal(Integer.parseInt(result)); } } catch (NumberFormatException e) { - Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse cache count"); + Log.w("cgeoBase.parseSearch: Failed to parse cache count"); } if (thread != null && recaptchaChallenge != null) { @@ -315,7 +254,7 @@ public class cgBase { } if (cids.size() > 0 && (Settings.isPremiumMember() || showCaptcha) && (recaptchaChallenge == null || StringUtils.isNotBlank(recaptchaText))) { - Log.i(Settings.tag, "Trying to get .loc for " + cids.size() + " caches"); + Log.i("Trying to get .loc for " + cids.size() + " caches"); try { // get coordinates for parsed caches @@ -345,7 +284,7 @@ public class cgBase { if (StringUtils.isNotBlank(coordinates)) { if (coordinates.contains("You have not agreed to the license agreement. The license agreement is required before you can start downloading GPX or LOC files from Geocaching.com")) { - Log.i(Settings.tag, "User has not agreed to the license agreement. Can\'t download .loc file."); + Log.i("User has not agreed to the license agreement. Can\'t download .loc file."); searchResult.setError(StatusCode.UNAPPROVED_LICENSE); @@ -356,7 +295,7 @@ public class cgBase { LocParser.parseLoc(searchResult, coordinates); } catch (Exception e) { - Log.e(Settings.tag, "cgBase.parseSearch.CIDs: " + e.toString()); + Log.e("cgBase.parseSearch.CIDs: " + e.toString()); } } @@ -386,7 +325,7 @@ public class cgBase { } // update progress message so user knows we're still working. Otherwise it will remain on whatever was set // in getExtraOnlineInfo (which could be logs, gcvote, or elevation) - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_render); + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_render); // save full detailed caches cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); } @@ -394,10 +333,10 @@ public class cgBase { } static SearchResult parseCacheFromText(final String page, final CancellableHandler handler) { - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_details); + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_details); if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgeoBase.parseCache: No page given"); + Log.e("cgeoBase.parseCache: No page given"); return null; } @@ -457,7 +396,7 @@ public class cgBase { int pos = tableInside.indexOf("id=\"cacheDetails\""); if (pos == -1) { - Log.e(Settings.tag, "cgeoBase.parseCache: ID \"cacheDetails\" not found on page"); + Log.e("cgeoBase.parseCache: ID \"cacheDetails\" not found on page"); return null; } @@ -465,7 +404,7 @@ public class cgBase { pos = tableInside.indexOf("<div class=\"CacheInformationTable\""); if (pos == -1) { - Log.e(Settings.tag, "cgeoBase.parseCache: class \"CacheInformationTable\" not found on page"); + Log.e("cgeoBase.parseCache: class \"CacheInformationTable\" not found on page"); return null; } @@ -502,7 +441,7 @@ public class cgBase { } } catch (ParseException e) { // failed to parse cache hidden date - Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache hidden (event) date"); + Log.w("cgeoBase.parseCache: Failed to parse cache hidden (event) date"); } // favourite @@ -528,7 +467,7 @@ public class cgBase { cache.setCoords(new Geopoint(cache.getLatlon())); cache.setReliableLatLon(true); } catch (Geopoint.GeopointException e) { - Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache coordinates: " + e.toString()); + Log.w("cgeoBase.parseCache: Failed to parse cache coordinates: " + e.toString()); } } @@ -545,7 +484,7 @@ public class cgBase { } } - checkFields(cache); + cache.checkFields(); // cache personal note cache.setPersonalNote(BaseUtils.getMatch(page, GCConstants.PATTERN_PERSONALNOTE, true, cache.getPersonalNote())); @@ -582,7 +521,7 @@ public class cgBase { } } catch (Exception e) { // failed to parse cache attributes - Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache attributes"); + Log.w("cgeoBase.parseCache: Failed to parse cache attributes"); } // cache spoilers @@ -592,7 +531,7 @@ public class cgBase { if (CancellableHandler.isCancelled(handler)) { return null; } - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers); + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers); final Matcher matcherSpoilersInside = GCConstants.PATTERN_SPOILERSINSIDE.matcher(spoilers); @@ -619,7 +558,7 @@ public class cgBase { } } catch (Exception e) { // failed to parse cache spoilers - Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache spoilers"); + Log.w("cgeoBase.parseCache: Failed to parse cache spoilers"); } // cache inventory @@ -653,7 +592,7 @@ public class cgBase { } } catch (Exception e) { // failed to parse cache inventory - Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache inventory (2)"); + Log.w("cgeoBase.parseCache: Failed to parse cache inventory (2)"); } // cache logs counts @@ -678,7 +617,7 @@ public class cgBase { } catch (Exception e) { // failed to parse logs - Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache log count"); + Log.w("cgeoBase.parseCache: Failed to parse cache log count"); } // add waypoint for original coordinates in case of user-modified listing-coordinates @@ -686,8 +625,7 @@ public class cgBase { final String originalCoords = BaseUtils.getMatch(page, GCConstants.PATTERN_LATLON_ORIG, false, null); if (null != originalCoords) { - // res is null during the unit tests - final cgWaypoint waypoint = new cgWaypoint(res != null ? res.getString(R.string.cache_coordinates_original) : "res = null", WaypointType.WAYPOINT, false); + final cgWaypoint waypoint = new cgWaypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.WAYPOINT, false); waypoint.setCoords(new Geopoint(originalCoords)); cache.addWaypoint(waypoint, false); cache.setUserModifiedCoords(true); @@ -704,8 +642,7 @@ public class cgBase { if (CancellableHandler.isCancelled(handler)) { return null; } - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_waypoints); - + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_waypoints); String wpList = page.substring(wpBegin); @@ -732,7 +669,7 @@ public class cgBase { // waypoint name // res is null during the unit tests - final String name = BaseUtils.getMatch(wp[6], GCConstants.PATTERN_WPNAME, true, 1, res != null ? res.getString(R.string.waypoint) : "res = null", true); + final String name = BaseUtils.getMatch(wp[6], GCConstants.PATTERN_WPNAME, true, 1, cgeoapplication.getInstance().getString(R.string.waypoint), true); // waypoint type final String resulttype = BaseUtils.getMatch(wp[3], GCConstants.PATTERN_WPTYPE, null); @@ -780,485 +717,6 @@ public class cgBase { return searchResult; } - private static void getExtraOnlineInfo(final cgCache cache, final String page, final CancellableHandler handler) { - if (CancellableHandler.isCancelled(handler)) { - return; - } - - //cache.setLogs(loadLogsFromDetails(page, cache, false)); - if (Settings.isFriendLogsWanted()) { - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs); - List<cgLog> allLogs = cache.getLogs(); - List<cgLog> friendLogs = loadLogsFromDetails(page, cache, true, false); - if (friendLogs != null) { - for (cgLog log : friendLogs) { - if (allLogs.contains(log)) { - allLogs.get(allLogs.indexOf(log)).friend = true; - } else { - allLogs.add(log); - } - } - } - } - - if (Settings.isElevationWanted()) { - if (CancellableHandler.isCancelled(handler)) { - return; - } - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_elevation); - if (cache.getCoords() != null) { - cache.setElevation(cache.getCoords().getElevation()); - } - } - - if (Settings.isRatingWanted()) { - if (CancellableHandler.isCancelled(handler)) { - return; - } - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_gcvote); - final GCVoteRating rating = GCVote.getRating(cache.getGuid(), cache.getGeocode()); - if (rating != null) { - cache.setRating(rating.getRating()); - cache.setVotes(rating.getVotes()); - cache.setMyVote(rating.getMyVote()); - } - } - } - - /** - * Load logs from a cache details page. - * - * @param page - * the text of the details page - * @param cache - * the cache object to put the logs in - * @param friends - * retrieve friend logs - */ - private static List<cgLog> loadLogsFromDetails(final String page, final cgCache cache, final boolean friends, final boolean getDataFromPage) { - String rawResponse = null; - - if (!getDataFromPage) { - final Matcher userTokenMatcher = GCConstants.PATTERN_USERTOKEN2.matcher(page); - if (!userTokenMatcher.find()) { - Log.e(Settings.tag, "cgBase.loadLogsFromDetails: unable to extract userToken"); - return null; - } - - final String userToken = userTokenMatcher.group(1); - final Parameters params = new Parameters( - "tkn", userToken, - "idx", "1", - "num", String.valueOf(GCConstants.NUMBER_OF_LOGS), - "decrypt", "true", - // "sp", Boolean.toString(personal), // personal logs - "sf", Boolean.toString(friends)); - - final HttpResponse response = Network.request("http://www.geocaching.com/seek/geocache.logbook", params, false, false, false); - if (response == null) { - Log.e(Settings.tag, "cgBase.loadLogsFromDetails: cannot log logs, response is null"); - return null; - } - final int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != 200) { - Log.e(Settings.tag, "cgBase.loadLogsFromDetails: error " + statusCode + " when requesting log information"); - return null; - } - rawResponse = Network.getResponseData(response); - if (rawResponse == null) { - Log.e(Settings.tag, "cgBase.loadLogsFromDetails: unable to read whole response"); - return null; - } - } else { - // extract embedded JSON data from page - rawResponse = BaseUtils.getMatch(page, GCConstants.PATTERN_LOGBOOK, ""); - } - - List<cgLog> logs = new ArrayList<cgLog>(); - - try { - final JSONObject resp = new JSONObject(rawResponse); - if (!resp.getString("status").equals("success")) { - Log.e(Settings.tag, "cgBase.loadLogsFromDetails: status is " + resp.getString("status")); - return null; - } - - final JSONArray data = resp.getJSONArray("data"); - - for (int index = 0; index < data.length(); index++) { - final JSONObject entry = data.getJSONObject(index); - final cgLog logDone = new cgLog(); - logDone.friend = friends; - - // FIXME: use the "LogType" field instead of the "LogTypeImage" one. - final String logIconNameExt = entry.optString("LogTypeImage", ".gif"); - final String logIconName = logIconNameExt.substring(0, logIconNameExt.length() - 4); - logDone.type = LogType.getByIconName(logIconName); - - try { - logDone.date = Login.parseGcCustomDate(entry.getString("Visited")).getTime(); - } catch (ParseException e) { - Log.e(Settings.tag, "cgBase.loadLogsFromDetails: failed to parse log date."); - } - - logDone.author = entry.getString("UserName"); - logDone.found = entry.getInt("GeocacheFindCount"); - logDone.log = entry.getString("LogText"); - - final JSONArray images = entry.getJSONArray("Images"); - for (int i = 0; i < images.length(); i++) { - final JSONObject image = images.getJSONObject(i); - String url = "http://img.geocaching.com/cache/log/" + image.getString("FileName"); - String title = image.getString("Name"); - final cgImage logImage = new cgImage(url, title); - if (logDone.logImages == null) { - logDone.logImages = new ArrayList<cgImage>(); - } - logDone.logImages.add(logImage); - } - - logs.add(logDone); - } - } catch (JSONException e) { - // failed to parse logs - Log.w(Settings.tag, "cgBase.loadLogsFromDetails: Failed to parse cache logs", e); - } - - return logs; - } - - private static void checkFields(cgCache cache) { - if (StringUtils.isBlank(cache.getGeocode())) { - Log.e(Settings.tag, "cgBase.loadLogsFromDetails: geo code not parsed correctly"); - } - if (StringUtils.isBlank(cache.getName())) { - Log.e(Settings.tag, "name not parsed correctly"); - } - if (StringUtils.isBlank(cache.getGuid())) { - Log.e(Settings.tag, "guid not parsed correctly"); - } - if (cache.getTerrain() == 0.0) { - Log.e(Settings.tag, "terrain not parsed correctly"); - } - if (cache.getDifficulty() == 0.0) { - Log.e(Settings.tag, "difficulty not parsed correctly"); - } - if (StringUtils.isBlank(cache.getOwner())) { - Log.e(Settings.tag, "owner not parsed correctly"); - } - if (StringUtils.isBlank(cache.getOwnerReal())) { - Log.e(Settings.tag, "owner real not parsed correctly"); - } - if (cache.getHiddenDate() == null) { - Log.e(Settings.tag, "hidden not parsed correctly"); - } - if (cache.getFavoritePoints() < 0) { - Log.e(Settings.tag, "favoriteCount not parsed correctly"); - } - if (cache.getSize() == null) { - Log.e(Settings.tag, "size not parsed correctly"); - } - if (cache.getType() == null || cache.getType() == CacheType.UNKNOWN) { - Log.e(Settings.tag, "type not parsed correctly"); - } - if (cache.getCoords() == null) { - Log.e(Settings.tag, "coordinates not parsed correctly"); - } - if (StringUtils.isBlank(cache.getLocation())) { - Log.e(Settings.tag, "location not parsed correctly"); - } - } - - /** - * Parse a trackable HTML description into a cgTrackable object - * - * @param page - * the HTML page to parse, already processed through {@link BaseUtils#replaceWhitespace} - * @param app - * if not null, the application to use to save the trackable - * @return the parsed trackable, or null if none could be parsed - */ - public static cgTrackable parseTrackable(final String page, final cgeoapplication app, final String possibleTrackingcode) { - if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgeoBase.parseTrackable: No page given"); - return null; - } - - final cgTrackable trackable = new cgTrackable(); - - // trackable geocode - trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode()).toUpperCase()); - - // trackable id - trackable.setGuid(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GUID, true, trackable.getGuid())); - - // trackable icon - trackable.setIconUrl(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ICON, true, trackable.getIconUrl())); - - // trackable name - trackable.setName(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_NAME, true, trackable.getName())); - - // trackable type - if (StringUtils.isNotBlank(trackable.getName())) { - trackable.setType(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_TYPE, true, trackable.getType())); - } - - // trackable owner name - try { - final Matcher matcherOwner = GCConstants.PATTERN_TRACKABLE_OWNER.matcher(page); - if (matcherOwner.find() && matcherOwner.groupCount() > 0) { - trackable.setOwnerGuid(matcherOwner.group(1)); - trackable.setOwner(matcherOwner.group(2).trim()); - } - } catch (Exception e) { - // failed to parse trackable owner name - Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable owner name"); - } - - // trackable origin - trackable.setOrigin(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ORIGIN, true, trackable.getOrigin())); - - // trackable spotted - try { - final Matcher matcherSpottedCache = GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE.matcher(page); - if (matcherSpottedCache.find() && matcherSpottedCache.groupCount() > 0) { - trackable.setSpottedGuid(matcherSpottedCache.group(1)); - trackable.setSpottedName(matcherSpottedCache.group(2).trim()); - trackable.setSpottedType(cgTrackable.SPOTTED_CACHE); - } - - final Matcher matcherSpottedUser = GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER.matcher(page); - if (matcherSpottedUser.find() && matcherSpottedUser.groupCount() > 0) { - trackable.setSpottedGuid(matcherSpottedUser.group(1)); - trackable.setSpottedName(matcherSpottedUser.group(2).trim()); - trackable.setSpottedType(cgTrackable.SPOTTED_USER); - } - - if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDUNKNOWN)) { - trackable.setSpottedType(cgTrackable.SPOTTED_UNKNOWN); - } - - if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) { - trackable.setSpottedType(cgTrackable.SPOTTED_OWNER); - } - } catch (Exception e) { - // failed to parse trackable last known place - Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable last known place"); - } - - // released date - can be missing on the page - try { - String releaseString = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_RELEASES, false, null); - if (releaseString != null) { - trackable.setReleased(dateTbIn1.parse(releaseString)); - if (trackable.getReleased() == null) { - trackable.setReleased(dateTbIn2.parse(releaseString)); - } - } - } catch (ParseException e1) { - trackable.setReleased(null); - } - - - // trackable distance - try { - final String distance = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_DISTANCE, false, null); - if (null != distance) { - trackable.setDistance(DistanceParser.parseDistance(distance, Settings.isUseMetricUnits())); - } - } catch (NumberFormatException e) { - throw e; - } - - // trackable goal - trackable.setGoal(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal())); - - // trackable details & image - try { - final Matcher matcherDetailsImage = GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE.matcher(page); - if (matcherDetailsImage.find() && matcherDetailsImage.groupCount() > 0) { - final String image = StringUtils.trim(matcherDetailsImage.group(3)); - final String details = StringUtils.trim(matcherDetailsImage.group(4)); - - if (StringUtils.isNotEmpty(image)) { - trackable.setImage(image); - } - if (StringUtils.isNotEmpty(details) && !StringUtils.equals(details, "No additional details available.")) { - trackable.setDetails(details); - } - } - } catch (Exception e) { - // failed to parse trackable details & image - Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable details & image"); - } - - // trackable logs - try - { - final Matcher matcherLogs = GCConstants.PATTERN_TRACKABLE_LOG.matcher(page); - /* - * 1. Type (img) - * 2. Date - * 3. Author - * 4. Cache-GUID - * 5. <ignored> (strike-through property for ancien caches) - * 6. Cache-name - * 7. Logtext - */ - while (matcherLogs.find()) - { - final cgLog logDone = new cgLog(); - - logDone.type = LogType.getByIconName(matcherLogs.group(1)); - logDone.author = Html.fromHtml(matcherLogs.group(3)).toString().trim(); - - try - { - logDone.date = Login.parseGcCustomDate(matcherLogs.group(2)).getTime(); - } catch (ParseException e) { - } - - logDone.log = matcherLogs.group(7).trim(); - - if (matcherLogs.group(4) != null && matcherLogs.group(6) != null) - { - logDone.cacheGuid = matcherLogs.group(4); - logDone.cacheName = matcherLogs.group(6); - } - - // Apply the pattern for images in a trackable log entry against each full log (group(0)) - final Matcher matcherLogImages = GCConstants.PATTERN_TRACKABLE_LOG_IMAGES.matcher(matcherLogs.group(0)); - /* - * 1. Image URL - * 2. Image title - */ - while (matcherLogImages.find()) - { - final cgImage logImage = new cgImage(matcherLogImages.group(1), matcherLogImages.group(2)); - if (logDone.logImages == null) { - logDone.logImages = new ArrayList<cgImage>(); - } - logDone.logImages.add(logImage); - } - - trackable.getLogs().add(logDone); - } - } catch (Exception e) { - // failed to parse logs - Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache logs" + e.toString()); - } - - // trackingcode - if (!StringUtils.equalsIgnoreCase(trackable.getGeocode(), possibleTrackingcode)) { - trackable.setTrackingcode(possibleTrackingcode); - } - - if (app != null) { - app.saveTrackable(trackable); - } - - return trackable; - } - - public static List<LogType> parseTypes(String page) { - if (StringUtils.isEmpty(page)) { - return null; - } - - final List<LogType> types = new ArrayList<LogType>(); - - final Matcher typeBoxMatcher = GCConstants.PATTERN_TYPEBOX.matcher(page); - String typesText = null; - if (typeBoxMatcher.find()) { - if (typeBoxMatcher.groupCount() > 0) { - typesText = typeBoxMatcher.group(1); - } - } - - if (typesText != null) { - - final Matcher typeMatcher = GCConstants.PATTERN_TYPE2.matcher(typesText); - while (typeMatcher.find()) { - if (typeMatcher.groupCount() > 1) { - final int type = Integer.parseInt(typeMatcher.group(2)); - - if (type > 0) { - types.add(LogType.getById(type)); - } - } - } - } - - return types; - } - - public static List<cgTrackableLog> parseTrackableLog(final String page) { - if (StringUtils.isEmpty(page)) { - return null; - } - - final List<cgTrackableLog> trackables = new ArrayList<cgTrackableLog>(); - - String table = StringUtils.substringBetween(page, "<table id=\"tblTravelBugs\"", "</table>"); - - // if no trackables are currently in the account, the table is not available, so return an empty list instead of null - if (StringUtils.isBlank(table)) { - return trackables; - } - - table = StringUtils.substringBetween(table, "<tbody>", "</tbody>"); - if (StringUtils.isBlank(table)) { - Log.e(Settings.tag, "cgeoBase.parseTrackableLog: tbody not found on page"); - return null; - } - - final Matcher trackableMatcher = GCConstants.PATTERN_TRACKABLE.matcher(page); - while (trackableMatcher.find()) { - if (trackableMatcher.groupCount() > 0) { - final cgTrackableLog trackableLog = new cgTrackableLog(); - - if (trackableMatcher.group(1) != null) { - trackableLog.trackCode = trackableMatcher.group(1); - } else { - continue; - } - if (trackableMatcher.group(2) != null) { - trackableLog.name = Html.fromHtml(trackableMatcher.group(2)).toString(); - } else { - continue; - } - if (trackableMatcher.group(3) != null) { - trackableLog.ctl = Integer.valueOf(trackableMatcher.group(3)); - } else { - continue; - } - if (trackableMatcher.group(5) != null) { - trackableLog.id = Integer.valueOf(trackableMatcher.group(5)); - } else { - continue; - } - - Log.i(Settings.tag, "Trackable in inventory (#" + trackableLog.ctl + "/" + trackableLog.id + "): " + trackableLog.trackCode + " - " + trackableLog.name); - - trackables.add(trackableLog); - } - } - - return trackables; - } - - /** - * Insert the right cache type restriction in parameters - * - * @param params - * the parameters to insert the restriction into - * @param cacheType - * the type of cache, or null to include everything - */ - static private void insertCacheType(final Parameters params, final CacheType cacheType) { - params.put("tx", cacheType.guid); - } - public static SearchResult searchByNextPage(cgSearchThread thread, final SearchResult search, boolean showCaptcha) { if (search == null) { return search; @@ -1268,12 +726,12 @@ public class cgBase { final String url = search.getUrl(); if (StringUtils.isBlank(url)) { - Log.e(Settings.tag, "cgeoBase.searchByNextPage: No url found"); + Log.e("cgeoBase.searchByNextPage: No url found"); return search; } - if (isEmpty(viewstates)) { - Log.e(Settings.tag, "cgeoBase.searchByNextPage: No viewstate given"); + if (Login.isEmpty(viewstates)) { + Log.e("cgeoBase.searchByNextPage: No viewstate given"); return search; } @@ -1291,22 +749,22 @@ public class cgBase { if (loginState == StatusCode.NO_ERROR) { page = Network.getResponseData(Network.postRequest(uri, params)); } else if (loginState == StatusCode.NO_LOGIN_INFO_STORED) { - Log.i(Settings.tag, "Working as guest."); + Log.i("Working as guest."); } else { search.setError(loginState); - Log.e(Settings.tag, "cgeoBase.searchByNextPage: Can not log in geocaching"); + Log.e("cgeoBase.searchByNextPage: Can not log in geocaching"); return search; } } if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgeoBase.searchByNextPage: No data from server"); + Log.e("cgeoBase.searchByNextPage: No data from server"); return search; } final SearchResult searchResult = parseSearch(thread, url, page, showCaptcha); if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) { - Log.e(Settings.tag, "cgeoBase.searchByNextPage: No cache parsed"); + Log.e("cgeoBase.searchByNextPage: No cache parsed"); return search; } @@ -1319,30 +777,25 @@ public class cgBase { return search; } - public static SearchResult searchByGeocode(final String geocode, final String guid, final int listId, final boolean forceReload, final CancellableHandler handler) { - if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) { - Log.e(Settings.tag, "cgeoBase.searchByGeocode: No geocode nor guid given"); - return null; - } - - cgeoapplication app = cgeoapplication.getInstance(); - if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (app.isOffline(geocode, guid) || app.isThere(geocode, guid, true, true))) { - final SearchResult search = new SearchResult(); - final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : app.getGeocode(guid); - search.addGeocode(realGeocode); - return search; - } - - // if we have no geocode, we can't dynamically select the handler, but must explicitly use GC - if (geocode == null && guid != null) { - return GCConnector.getInstance().searchByGeocode(null, guid, app, handler); + /** + * Possibly hide caches found or hidden by user. This mutates its params argument when possible. + * + * @param params + * the parameters to mutate, or null to create a new Parameters if needed + * @param my + * @param addF + * @return the original params if not null, maybe augmented with f=1, or a new Parameters with f=1 or null otherwise + */ + public static Parameters addFToParams(final Parameters params, final boolean my, final boolean addF) { + if (!my && Settings.isExcludeMyCaches() && addF) { + if (params == null) { + return new Parameters("f", "1"); + } + params.put("f", "1"); + Log.i("Skipping caches found or hidden by user."); } - return ConnectorFactory.getConnector(geocode).searchByGeocode(geocode, guid, app, handler); - } - - public static SearchResult searchByStored(final Geopoint coords, final CacheType cacheType, final int list) { - return cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, cacheType, list); + return params; } /** @@ -1360,16 +813,16 @@ public class cgBase { final String uri = "http://www.geocaching.com/seek/nearest.aspx"; final String fullUri = uri + "?" + addFToParams(params, false, true); - String page = Network.requestLogged(uri, params, false, my, true); + final String page = Login.getRequestLogged(uri, addFToParams(params, my, true)); if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgeoBase.searchByAny: No data from server"); + Log.e("cgeoBase.searchByAny: No data from server"); return null; } final SearchResult searchResult = parseSearch(thread, fullUri, page, showCaptcha); if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) { - Log.e(Settings.tag, "cgeoBase.searchByAny: No cache parsed"); + Log.e("cgeoBase.searchByAny: No cache parsed"); return searchResult; } @@ -1387,7 +840,7 @@ public class cgBase { public static SearchResult searchByKeyword(final cgSearchThread thread, final String keyword, final CacheType cacheType, final boolean showCaptcha) { if (StringUtils.isBlank(keyword)) { - Log.e(Settings.tag, "cgeoBase.searchByKeyword: No keyword given"); + Log.e("cgeoBase.searchByKeyword: No keyword given"); return null; } @@ -1397,7 +850,7 @@ public class cgBase { public static SearchResult searchByUsername(final cgSearchThread thread, final String userName, final CacheType cacheType, final boolean showCaptcha) { if (StringUtils.isBlank(userName)) { - Log.e(Settings.tag, "cgeoBase.searchByUsername: No user name given"); + Log.e("cgeoBase.searchByUsername: No user name given"); return null; } @@ -1406,7 +859,7 @@ public class cgBase { boolean my = false; if (userName.equalsIgnoreCase(Settings.getLogin().left)) { my = true; - Log.i(Settings.tag, "cgBase.searchByUsername: Overriding users choice, downloading all caches."); + Log.i("cgBase.searchByUsername: Overriding users choice, downloading all caches."); } return searchByAny(thread, cacheType, my, showCaptcha, params); @@ -1414,7 +867,7 @@ public class cgBase { public static SearchResult searchByOwner(final cgSearchThread thread, final String userName, final CacheType cacheType, final boolean showCaptcha) { if (StringUtils.isBlank(userName)) { - Log.e(Settings.tag, "cgeoBase.searchByOwner: No user name given"); + Log.e("cgeoBase.searchByOwner: No user name given"); return null; } @@ -1424,7 +877,7 @@ public class cgBase { public static cgTrackable searchTrackable(final String geocode, final String guid, final String id) { if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid) && StringUtils.isBlank(id)) { - Log.w(Settings.tag, "cgeoBase.searchTrackable: No geocode nor guid nor id given"); + Log.w("cgeoBase.searchTrackable: No geocode nor guid nor id given"); return null; } @@ -1440,16 +893,16 @@ public class cgBase { params.put("id", id); } - String page = Network.requestLogged("http://www.geocaching.com/track/details.aspx", params, false, false, false); + final String page = Login.getRequestLogged("http://www.geocaching.com/track/details.aspx", params); if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgeoBase.searchTrackable: No data from server"); + Log.e("cgeoBase.searchTrackable: No data from server"); return trackable; } trackable = parseTrackable(page, cgeoapplication.getInstance(), geocode); if (trackable == null) { - Log.e(Settings.tag, "cgeoBase.searchTrackable: No trackable parsed"); + Log.e("cgeoBase.searchTrackable: No trackable parsed"); return null; } @@ -1458,14 +911,14 @@ public class cgBase { public static StatusCode postLog(final String geocode, final String cacheid, final String[] viewstates, final LogType logType, final int year, final int month, final int day, - final String log, final List<cgTrackableLog> trackables) { - if (isEmpty(viewstates)) { - Log.e(Settings.tag, "cgeoBase.postLog: No viewstate given"); + final String log, final List<TrackableLog> trackables) { + if (Login.isEmpty(viewstates)) { + Log.e("cgeoBase.postLog: No viewstate given"); return StatusCode.LOG_POST_ERROR; } if (StringUtils.isBlank(log)) { - Log.e(Settings.tag, "cgeoBase.postLog: No log text given"); + Log.e("cgeoBase.postLog: No log text given"); return StatusCode.NO_LOG_TEXT; } @@ -1488,9 +941,9 @@ public class cgBase { final String logInfo = logUpdated.toString().replace("\n", "\r\n").trim(); // windows' eol and remove leading and trailing whitespaces if (trackables != null) { - Log.i(Settings.tag, "Trying to post log for cache #" + cacheid + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + logInfo + "; trackables: " + trackables.size()); + Log.i("Trying to post log for cache #" + cacheid + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + logInfo + "; trackables: " + trackables.size()); } else { - Log.i(Settings.tag, "Trying to post log for cache #" + cacheid + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + logInfo + "; trackables: 0"); + Log.i("Trying to post log for cache #" + cacheid + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + logInfo + "; trackables: 0"); } final Parameters params = new Parameters( @@ -1509,7 +962,7 @@ public class cgBase { if (trackables != null && !trackables.isEmpty()) { // we have some trackables to proceed final StringBuilder hdnSelected = new StringBuilder(); - for (final cgTrackableLog tb : trackables) { + for (final TrackableLog tb : trackables) { if (tb.action != LogTypeTrackable.DO_NOTHING) { hdnSelected.append(Integer.toString(tb.id)); hdnSelected.append(tb.action.action); @@ -1528,13 +981,13 @@ public class cgBase { if (loginState == StatusCode.NO_ERROR) { page = Network.getResponseData(Network.postRequest(uri, params)); } else { - Log.e(Settings.tag, "cgeoBase.postLog: Can not log in geocaching (error: " + loginState + ")"); + Log.e("cgeoBase.postLog: Can not log in geocaching (error: " + loginState + ")"); return loginState; } } if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgeoBase.postLog: No data from server"); + Log.e("cgeoBase.postLog: No data from server"); return StatusCode.NO_DATA_FROM_SERVER; } @@ -1546,8 +999,8 @@ public class cgBase { if (matcher.find() && matcher.groupCount() > 0) { final String[] viewstatesConfirm = Login.getViewstates(page); - if (isEmpty(viewstatesConfirm)) { - Log.e(Settings.tag, "cgeoBase.postLog: No viewstate for confirm log"); + if (Login.isEmpty(viewstatesConfirm)) { + Log.e("cgeoBase.postLog: No viewstate for confirm log"); return StatusCode.LOG_POST_ERROR; } @@ -1562,7 +1015,7 @@ public class cgBase { if (trackables != null && !trackables.isEmpty()) { // we have some trackables to proceed final StringBuilder hdnSelected = new StringBuilder(); - for (cgTrackableLog tb : trackables) { + for (TrackableLog tb : trackables) { String ctl = null; final String action = Integer.toString(tb.id) + tb.action.action; @@ -1586,14 +1039,14 @@ public class cgBase { page = Network.getResponseData(Network.postRequest(uri, params)); } } catch (Exception e) { - Log.e(Settings.tag, "cgeoBase.postLog.confim: " + e.toString()); + Log.e("cgeoBase.postLog.confim: " + e.toString()); } try { final Matcher matcherOk = GCConstants.PATTERN_OK1.matcher(page); if (matcherOk.find()) { - Log.i(Settings.tag, "Log successfully posted to cache #" + cacheid); + Log.i("Log successfully posted to cache #" + cacheid); if (geocode != null) { cgeoapplication.getInstance().saveVisitDate(geocode); @@ -1607,26 +1060,26 @@ public class cgBase { return StatusCode.NO_ERROR; } } catch (Exception e) { - Log.e(Settings.tag, "cgeoBase.postLog.check: " + e.toString()); + Log.e("cgeoBase.postLog.check: " + e.toString()); } - Log.e(Settings.tag, "cgeoBase.postLog: Failed to post log because of unknown error"); + Log.e("cgeoBase.postLog: Failed to post log because of unknown error"); return StatusCode.LOG_POST_ERROR; } public static StatusCode postLogTrackable(final String tbid, final String trackingCode, final String[] viewstates, final LogType logType, final int year, final int month, final int day, final String log) { - if (isEmpty(viewstates)) { - Log.e(Settings.tag, "cgeoBase.postLogTrackable: No viewstate given"); + if (Login.isEmpty(viewstates)) { + Log.e("cgeoBase.postLogTrackable: No viewstate given"); return StatusCode.LOG_POST_ERROR; } if (StringUtils.isBlank(log)) { - Log.e(Settings.tag, "cgeoBase.postLogTrackable: No log text given"); + Log.e("cgeoBase.postLogTrackable: No log text given"); return StatusCode.NO_LOG_TEXT; } - Log.i(Settings.tag, "Trying to post log for trackable #" + trackingCode + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + log); + Log.i("Trying to post log for trackable #" + trackingCode + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + log); final String logInfo = log.replace("\n", "\r\n"); // windows' eol @@ -1658,13 +1111,13 @@ public class cgBase { if (loginState == StatusCode.NO_ERROR) { page = Network.getResponseData(Network.postRequest(uri, params)); } else { - Log.e(Settings.tag, "cgeoBase.postLogTrackable: Can not log in geocaching (error: " + loginState + ")"); + Log.e("cgeoBase.postLogTrackable: Can not log in geocaching (error: " + loginState + ")"); return loginState; } } if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgeoBase.postLogTrackable: No data from server"); + Log.e("cgeoBase.postLogTrackable: No data from server"); return StatusCode.NO_DATA_FROM_SERVER; } @@ -1672,14 +1125,14 @@ public class cgBase { final Matcher matcherOk = GCConstants.PATTERN_OK2.matcher(page); if (matcherOk.find()) { - Log.i(Settings.tag, "Log successfully posted to trackable #" + trackingCode); + Log.i("Log successfully posted to trackable #" + trackingCode); return StatusCode.NO_ERROR; } } catch (Exception e) { - Log.e(Settings.tag, "cgeoBase.postLogTrackable.check: " + e.toString()); + Log.e("cgeoBase.postLogTrackable.check: " + e.toString()); } - Log.e(Settings.tag, "cgeoBase.postLogTrackable: Failed to post log because of unknown error"); + Log.e("cgeoBase.postLogTrackable: Failed to post log because of unknown error"); return StatusCode.LOG_POST_ERROR; } @@ -1692,19 +1145,19 @@ public class cgBase { */ public static int addToWatchlist(final cgCache cache) { final String uri = "http://www.geocaching.com/my/watchlist.aspx?w=" + cache.getCacheId(); - String page = Network.postRequestLogged(uri); + String page = Login.postRequestLogged(uri); if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgBase.addToWatchlist: No data from server"); + Log.e("cgBase.addToWatchlist: No data from server"); return -1; // error } boolean guidOnPage = cache.isGuidContainedInPage(page); if (guidOnPage) { - Log.i(Settings.tag, "cgBase.addToWatchlist: cache is on watchlist"); + Log.i("cgBase.addToWatchlist: cache is on watchlist"); cache.setOnWatchlist(true); } else { - Log.e(Settings.tag, "cgBase.addToWatchlist: cache is not on watchlist"); + Log.e("cgBase.addToWatchlist: cache is not on watchlist"); } return guidOnPage ? 1 : -1; // on watchlist (=added) / else: error } @@ -1718,10 +1171,10 @@ public class cgBase { */ public static int removeFromWatchlist(final cgCache cache) { final String uri = "http://www.geocaching.com/my/watchlist.aspx?ds=1&action=rem&id=" + cache.getCacheId(); - String page = Network.postRequestLogged(uri); + String page = Login.postRequestLogged(uri); if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgBase.removeFromWatchlist: No data from server"); + Log.e("cgBase.removeFromWatchlist: No data from server"); return -1; // error } @@ -1735,278 +1188,431 @@ public class cgBase { page = Network.getResponseData(Network.postRequest(uri, params)); boolean guidOnPage = cache.isGuidContainedInPage(page); if (!guidOnPage) { - Log.i(Settings.tag, "cgBase.removeFromWatchlist: cache removed from watchlist"); + Log.i("cgBase.removeFromWatchlist: cache removed from watchlist"); cache.setOnWatchlist(false); } else { - Log.e(Settings.tag, "cgBase.removeFromWatchlist: cache not removed from watchlist"); + Log.e("cgBase.removeFromWatchlist: cache not removed from watchlist"); } return guidOnPage ? -1 : 0; // on watchlist (=error) / not on watchlist } /** - * Possibly hide caches found or hidden by user. This mutates its params argument when possible. + * Parse a trackable HTML description into a cgTrackable object * - * @param params - * the parameters to mutate, or null to create a new Parameters if needed - * @param my - * @param addF - * @return the original params if not null, maybe augmented with f=1, or a new Parameters with f=1 or null otherwise + * @param page + * the HTML page to parse, already processed through {@link BaseUtils#replaceWhitespace} + * @param app + * if not null, the application to use to save the trackable + * @return the parsed trackable, or null if none could be parsed */ - public static Parameters addFToParams(final Parameters params, final boolean my, final boolean addF) { - if (!my && Settings.isExcludeMyCaches() && addF) { - if (params == null) { - return new Parameters("f", "1"); - } - params.put("f", "1"); - Log.i(Settings.tag, "Skipping caches found or hidden by user."); + public static cgTrackable parseTrackable(final String page, final cgeoapplication app, final String possibleTrackingcode) { + if (StringUtils.isBlank(page)) { + Log.e("cgeoBase.parseTrackable: No page given"); + return null; } - return params; - } + final cgTrackable trackable = new cgTrackable(); + + // trackable geocode + trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode()).toUpperCase()); + + // trackable id + trackable.setGuid(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GUID, true, trackable.getGuid())); + + // trackable icon + trackable.setIconUrl(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ICON, true, trackable.getIconUrl())); + + // trackable name + trackable.setName(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_NAME, true, trackable.getName())); + + // trackable type + if (StringUtils.isNotBlank(trackable.getName())) { + trackable.setType(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_TYPE, true, trackable.getType())); + } - public static void storeCache(Activity activity, cgCache origCache, String geocode, int listId, boolean forceRedownload, CancellableHandler handler) { + // trackable owner name try { - cgCache cache; - // get cache details, they may not yet be complete - if (origCache != null) { - // only reload the cache if it was already stored or doesn't have full details (by checking the description) - if (origCache.getListId() >= StoredList.STANDARD_LIST_ID || StringUtils.isBlank(origCache.getDescription())) { - final SearchResult search = searchByGeocode(origCache.getGeocode(), null, listId, false, handler); - cache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); - } else { - cache = origCache; - } - } else if (StringUtils.isNotBlank(geocode)) { - final SearchResult search = searchByGeocode(geocode, null, listId, forceRedownload, handler); - cache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); - } else { - cache = null; + final Matcher matcherOwner = GCConstants.PATTERN_TRACKABLE_OWNER.matcher(page); + if (matcherOwner.find() && matcherOwner.groupCount() > 0) { + trackable.setOwnerGuid(matcherOwner.group(1)); + trackable.setOwner(matcherOwner.group(2).trim()); } + } catch (Exception e) { + // failed to parse trackable owner name + Log.w("cgeoBase.parseTrackable: Failed to parse trackable owner name"); + } - if (cache == null) { - if (handler != null) { - handler.sendMessage(Message.obtain()); - } + // trackable origin + trackable.setOrigin(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ORIGIN, true, trackable.getOrigin())); - return; + // trackable spotted + try { + final Matcher matcherSpottedCache = GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE.matcher(page); + if (matcherSpottedCache.find() && matcherSpottedCache.groupCount() > 0) { + trackable.setSpottedGuid(matcherSpottedCache.group(1)); + trackable.setSpottedName(matcherSpottedCache.group(2).trim()); + trackable.setSpottedType(cgTrackable.SPOTTED_CACHE); } - if (CancellableHandler.isCancelled(handler)) { - return; + final Matcher matcherSpottedUser = GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER.matcher(page); + if (matcherSpottedUser.find() && matcherSpottedUser.groupCount() > 0) { + trackable.setSpottedGuid(matcherSpottedUser.group(1)); + trackable.setSpottedName(matcherSpottedUser.group(2).trim()); + trackable.setSpottedType(cgTrackable.SPOTTED_USER); } - final HtmlImage imgGetter = new HtmlImage(activity, cache.getGeocode(), false, listId, true); - - // store images from description - if (StringUtils.isNotBlank(cache.getDescription())) { - Html.fromHtml(cache.getDescription(), imgGetter, null); + if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDUNKNOWN)) { + trackable.setSpottedType(cgTrackable.SPOTTED_UNKNOWN); } - if (CancellableHandler.isCancelled(handler)) { - return; + if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) { + trackable.setSpottedType(cgTrackable.SPOTTED_OWNER); } + } catch (Exception e) { + // failed to parse trackable last known place + Log.w("cgeoBase.parseTrackable: Failed to parse trackable last known place"); + } - // store spoilers - if (CollectionUtils.isNotEmpty(cache.getSpoilers())) { - for (cgImage oneSpoiler : cache.getSpoilers()) { - imgGetter.getDrawable(oneSpoiler.getUrl()); + // released date - can be missing on the page + try { + String releaseString = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_RELEASES, false, null); + if (releaseString != null) { + trackable.setReleased(dateTbIn1.parse(releaseString)); + if (trackable.getReleased() == null) { + trackable.setReleased(dateTbIn2.parse(releaseString)); } } + } catch (ParseException e1) { + trackable.setReleased(null); + } - if (CancellableHandler.isCancelled(handler)) { - return; + // trackable distance + try { + final String distance = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_DISTANCE, false, null); + if (null != distance) { + trackable.setDistance(DistanceParser.parseDistance(distance, Settings.isUseMetricUnits())); } + } catch (NumberFormatException e) { + throw e; + } - // store images from logs - if (Settings.isStoreLogImages()) { - for (cgLog log : cache.getLogs(true)) { - if (CollectionUtils.isNotEmpty(log.logImages)) { - for (cgImage oneLogImg : log.logImages) { - imgGetter.getDrawable(oneLogImg.getUrl()); - } - } + // trackable goal + trackable.setGoal(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal())); + + // trackable details & image + try { + final Matcher matcherDetailsImage = GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE.matcher(page); + if (matcherDetailsImage.find() && matcherDetailsImage.groupCount() > 0) { + final String image = StringUtils.trim(matcherDetailsImage.group(3)); + final String details = StringUtils.trim(matcherDetailsImage.group(4)); + + if (StringUtils.isNotEmpty(image)) { + trackable.setImage(image); + } + if (StringUtils.isNotEmpty(details) && !StringUtils.equals(details, "No additional details available.")) { + trackable.setDetails(details); } } + } catch (Exception e) { + // failed to parse trackable details & image + Log.w("cgeoBase.parseTrackable: Failed to parse trackable details & image"); + } - if (CancellableHandler.isCancelled(handler)) { - return; - } + // trackable logs + try + { + final Matcher matcherLogs = GCConstants.PATTERN_TRACKABLE_LOG.matcher(page); + /* + * 1. Type (img) + * 2. Date + * 3. Author + * 4. Cache-GUID + * 5. <ignored> (strike-through property for ancien caches) + * 6. Cache-name + * 7. Logtext + */ + while (matcherLogs.find()) + { + final LogEntry logDone = new LogEntry(); - // store map previews - StaticMapsProvider.downloadMaps(cache, activity); + logDone.type = LogType.getByIconName(matcherLogs.group(1)); + logDone.author = Html.fromHtml(matcherLogs.group(3)).toString().trim(); - if (CancellableHandler.isCancelled(handler)) { - return; - } + try + { + logDone.date = Login.parseGcCustomDate(matcherLogs.group(2)).getTime(); + } catch (ParseException e) { + } - cache.setListId(listId); - cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + logDone.log = matcherLogs.group(7).trim(); - if (handler != null) { - handler.sendMessage(Message.obtain()); + if (matcherLogs.group(4) != null && matcherLogs.group(6) != null) + { + logDone.cacheGuid = matcherLogs.group(4); + logDone.cacheName = matcherLogs.group(6); + } + + // Apply the pattern for images in a trackable log entry against each full log (group(0)) + final Matcher matcherLogImages = GCConstants.PATTERN_TRACKABLE_LOG_IMAGES.matcher(matcherLogs.group(0)); + /* + * 1. Image URL + * 2. Image title + */ + while (matcherLogImages.find()) + { + final cgImage logImage = new cgImage(matcherLogImages.group(1), matcherLogImages.group(2)); + logDone.addLogImage(logImage); + } + + trackable.getLogs().add(logDone); } } catch (Exception e) { - Log.e(Settings.tag, "cgBase.storeCache"); + // failed to parse logs + Log.w("cgeoBase.parseCache: Failed to parse cache logs" + e.toString()); } - } - public static void refreshCache(Activity activity, String geocode, int listId, CancellableHandler handler) { - cgeoapplication.getInstance().removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); - storeCache(activity, null, geocode, listId, true, handler); + // trackingcode + if (!StringUtils.equalsIgnoreCase(trackable.getGeocode(), possibleTrackingcode)) { + trackable.setTrackingcode(possibleTrackingcode); + } + + if (app != null) { + app.saveTrackable(trackable); + } + + return trackable; } - public static void dropCache(final cgCache cache, final Handler handler) { + /** + * Load logs from a cache details page. + * + * @param page + * the text of the details page + * @param cache + * the cache object to put the logs in + * @param friends + * retrieve friend logs + */ + private static List<LogEntry> loadLogsFromDetails(final String page, final cgCache cache, final boolean friends, final boolean getDataFromPage) { + String rawResponse = null; + + if (!getDataFromPage) { + final Matcher userTokenMatcher = GCConstants.PATTERN_USERTOKEN2.matcher(page); + if (!userTokenMatcher.find()) { + Log.e("cgBase.loadLogsFromDetails: unable to extract userToken"); + return null; + } + + final String userToken = userTokenMatcher.group(1); + final Parameters params = new Parameters( + "tkn", userToken, + "idx", "1", + "num", String.valueOf(GCConstants.NUMBER_OF_LOGS), + "decrypt", "true", + // "sp", Boolean.toString(personal), // personal logs + "sf", Boolean.toString(friends)); + + final HttpResponse response = Network.getRequest("http://www.geocaching.com/seek/geocache.logbook", params); + if (response == null) { + Log.e("cgBase.loadLogsFromDetails: cannot log logs, response is null"); + return null; + } + final int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != 200) { + Log.e("cgBase.loadLogsFromDetails: error " + statusCode + " when requesting log information"); + return null; + } + rawResponse = Network.getResponseData(response); + if (rawResponse == null) { + Log.e("cgBase.loadLogsFromDetails: unable to read whole response"); + return null; + } + } else { + // extract embedded JSON data from page + rawResponse = BaseUtils.getMatch(page, GCConstants.PATTERN_LOGBOOK, ""); + } + + List<LogEntry> logs = new ArrayList<LogEntry>(); + try { - cgeoapplication.getInstance().markDropped(cache.getGeocode()); - cgeoapplication.getInstance().removeCache(cache.getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE)); + final JSONObject resp = new JSONObject(rawResponse); + if (!resp.getString("status").equals("success")) { + Log.e("cgBase.loadLogsFromDetails: status is " + resp.getString("status")); + return null; + } - handler.sendMessage(Message.obtain()); - } catch (Exception e) { - Log.e(Settings.tag, "cgBase.dropCache: " + e.toString()); + final JSONArray data = resp.getJSONArray("data"); + + for (int index = 0; index < data.length(); index++) { + final JSONObject entry = data.getJSONObject(index); + final LogEntry logDone = new LogEntry(); + logDone.friend = friends; + + // FIXME: use the "LogType" field instead of the "LogTypeImage" one. + final String logIconNameExt = entry.optString("LogTypeImage", ".gif"); + final String logIconName = logIconNameExt.substring(0, logIconNameExt.length() - 4); + logDone.type = LogType.getByIconName(logIconName); + + try { + logDone.date = Login.parseGcCustomDate(entry.getString("Visited")).getTime(); + } catch (ParseException e) { + Log.e("cgBase.loadLogsFromDetails: failed to parse log date."); + } + + logDone.author = entry.getString("UserName"); + logDone.found = entry.getInt("GeocacheFindCount"); + logDone.log = entry.getString("LogText"); + + final JSONArray images = entry.getJSONArray("Images"); + for (int i = 0; i < images.length(); i++) { + final JSONObject image = images.getJSONObject(i); + String url = "http://img.geocaching.com/cache/log/" + image.getString("FileName"); + String title = image.getString("Name"); + final cgImage logImage = new cgImage(url, title); + logDone.addLogImage(logImage); + } + + logs.add(logDone); + } + } catch (JSONException e) { + // failed to parse logs + Log.w("cgBase.loadLogsFromDetails: Failed to parse cache logs", e); } - } - public static boolean runNavigation(Activity activity, Resources res, Settings settings, final Geopoint coords) { - return runNavigation(activity, res, settings, coords, null); + return logs; } - public static boolean runNavigation(Activity activity, Resources res, Settings settings, final Geopoint coords, final Geopoint coordsNow) { - if (activity == null) { - return false; - } - if (settings == null) { - return false; + public static List<LogType> parseTypes(String page) { + if (StringUtils.isEmpty(page)) { + return null; } - // Google Navigation - if (Settings.isUseGoogleNavigation()) { - try { - activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:ll=" + coords.getLatitude() + "," + coords.getLongitude()))); + final List<LogType> types = new ArrayList<LogType>(); - return true; - } catch (Exception e) { - // nothing + final Matcher typeBoxMatcher = GCConstants.PATTERN_TYPEBOX.matcher(page); + String typesText = null; + if (typeBoxMatcher.find()) { + if (typeBoxMatcher.groupCount() > 0) { + typesText = typeBoxMatcher.group(1); } } - // Google Maps Directions - try { - if (coordsNow != null) { - activity.startActivity(new Intent(Intent.ACTION_VIEW, - Uri.parse("http://maps.google.com/maps?f=d&saddr=" + coordsNow.getLatitude() + "," + coordsNow.getLongitude() + - "&daddr=" + coords.getLatitude() + "," + coords.getLongitude()))); - } else { - activity.startActivity(new Intent(Intent.ACTION_VIEW, - Uri.parse("http://maps.google.com/maps?f=d&daddr=" + coords.getLatitude() + "," + coords.getLongitude()))); + if (typesText != null) { + + final Matcher typeMatcher = GCConstants.PATTERN_TYPE2.matcher(typesText); + while (typeMatcher.find()) { + if (typeMatcher.groupCount() > 1) { + final int type = Integer.parseInt(typeMatcher.group(2)); + + if (type > 0) { + types.add(LogType.getById(type)); + } + } } + } - return true; - } catch (Exception e) { - // nothing + return types; + } + + public static List<TrackableLog> parseTrackableLog(final String page) { + if (StringUtils.isEmpty(page)) { + return null; } - Log.i(Settings.tag, "cgBase.runNavigation: No navigation application available."); + String table = StringUtils.substringBetween(page, "<table id=\"tblTravelBugs\"", "</table>"); - if (res != null) { - ActivityMixin.showToast(activity, res.getString(R.string.err_navigation_no)); + // if no trackables are currently in the account, the table is not available, so return an empty list instead of null + if (StringUtils.isBlank(table)) { + return Collections.emptyList(); } - return false; - } + table = StringUtils.substringBetween(table, "<tbody>", "</tbody>"); + if (StringUtils.isBlank(table)) { + Log.e("cgeoBase.parseTrackableLog: tbody not found on page"); + return null; + } - /** - * Generate a time string according to system-wide settings (locale, 12/24 hour) - * such as "13:24". - * - * @param date - * milliseconds since the epoch - * @return the formatted string - */ - public static String formatTime(long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_TIME); - } + final List<TrackableLog> trackableLogs = new ArrayList<TrackableLog>(); - /** - * Generate a date string according to system-wide settings (locale, date format) - * such as "20 December" or "20 December 2010". The year will only be included when necessary. - * - * @param date - * milliseconds since the epoch - * @return the formatted string - */ - public static String formatDate(long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE); - } + final Matcher trackableMatcher = GCConstants.PATTERN_TRACKABLE.matcher(page); + while (trackableMatcher.find()) { + if (trackableMatcher.groupCount() > 0) { - /** - * Generate a date string according to system-wide settings (locale, date format) - * such as "20 December 2010". The year will always be included, making it suitable - * to generate long-lived log entries. - * - * @param date - * milliseconds since the epoch - * @return the formatted string - */ - public static String formatFullDate(long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_SHOW_YEAR); - } + final String trackCode = trackableMatcher.group(1); + final String name = Html.fromHtml(trackableMatcher.group(2)).toString(); + try { + final Integer ctl = Integer.valueOf(trackableMatcher.group(3)); + final Integer id = Integer.valueOf(trackableMatcher.group(5)); + if (trackCode != null && name != null && ctl != null && id != null) { + final TrackableLog entry = new TrackableLog(trackCode, name, id.intValue(), ctl.intValue()); - /** - * Generate a numeric date string according to system-wide settings (locale, date format) - * such as "10/20/2010". - * - * @param date - * milliseconds since the epoch - * @return the formatted string - */ - public static String formatShortDate(long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_NUMERIC_DATE); + Log.i("Trackable in inventory (#" + entry.ctl + "/" + entry.id + "): " + entry.trackCode + " - " + entry.name); + trackableLogs.add(entry); + } + } catch (NumberFormatException e) { + Log.e("GCParser.parseTrackableLog", e); + } + } + } + + return trackableLogs; } /** - * Generate a numeric date and time string according to system-wide settings (locale, - * date format) such as "7 sept. at 12:35". + * Insert the right cache type restriction in parameters * - * @param context - * a Context - * @param date - * milliseconds since the epoch - * @return the formatted string + * @param params + * the parameters to insert the restriction into + * @param cacheType + * the type of cache, or null to include everything */ - public static String formatShortDateTime(Context context, long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL); + static private void insertCacheType(final Parameters params, final CacheType cacheType) { + params.put("tx", cacheType.guid); } - /** - * Indicates whether the specified action can be used as an intent. This - * method queries the package manager for installed packages that can - * respond to an intent with the specified action. If no suitable package is - * found, this method returns false. - * - * @param context - * The application's environment. - * @param action - * The Intent action to check for availability. - * @param uri - * The Intent URI to check for availability. - * - * @return True if an Intent with the specified action can be sent and - * responded to, false otherwise. - */ - public static boolean isIntentAvailable(Context context, String action, Uri uri) { - final PackageManager packageManager = context.getPackageManager(); - final Intent intent; - if (uri == null) { - intent = new Intent(action); - } else { - intent = new Intent(action, uri); + private static void getExtraOnlineInfo(final cgCache cache, final String page, final CancellableHandler handler) { + if (CancellableHandler.isCancelled(handler)) { + return; + } + + //cache.setLogs(loadLogsFromDetails(page, cache, false)); + if (Settings.isFriendLogsWanted()) { + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs); + List<LogEntry> allLogs = cache.getLogs(); + List<LogEntry> friendLogs = loadLogsFromDetails(page, cache, true, false); + if (friendLogs != null) { + for (LogEntry log : friendLogs) { + if (allLogs.contains(log)) { + allLogs.get(allLogs.indexOf(log)).friend = true; + } else { + allLogs.add(log); + } + } + } + } + + if (Settings.isElevationWanted()) { + if (CancellableHandler.isCancelled(handler)) { + return; + } + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_elevation); + if (cache.getCoords() != null) { + cache.setElevation(cache.getCoords().getElevation()); + } + } + + if (Settings.isRatingWanted()) { + if (CancellableHandler.isCancelled(handler)) { + return; + } + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_gcvote); + final GCVoteRating rating = GCVote.getRating(cache.getGuid(), cache.getGeocode()); + if (rating != null) { + cache.setRating(rating.getRating()); + cache.setVotes(rating.getVotes()); + cache.setMyVote(rating.getMyVote()); + } } - List<ResolveInfo> list = packageManager.queryIntentActivities(intent, - PackageManager.MATCH_DEFAULT_ONLY); - return list.size() > 0; } } - diff --git a/main/src/cgeo/geocaching/network/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java index d5f511d..1e614df 100644 --- a/main/src/cgeo/geocaching/network/Login.java +++ b/main/src/cgeo/geocaching/connector/gc/Login.java @@ -1,10 +1,13 @@ -package cgeo.geocaching.network; +package cgeo.geocaching.connector.gc; import cgeo.geocaching.R; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; -import cgeo.geocaching.connector.gc.GCConstants; +import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.StatusCode; +import cgeo.geocaching.network.Cookies; +import cgeo.geocaching.network.HtmlImage; +import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.Log; @@ -32,7 +35,6 @@ public abstract class Login { // false = not logged in private static boolean actualLoginStatus = false; private static String actualUserName = ""; - private static String actualMemberStatus = ""; private static int actualCachesFound = -1; private static String actualStatus = ""; @@ -61,33 +63,30 @@ public abstract class Login { final ImmutablePair<String, String> login = Settings.getLogin(); if (login == null || StringUtils.isEmpty(login.left) || StringUtils.isEmpty(login.right)) { - Login.setActualStatus(cgBase.res.getString(R.string.err_login)); - Log.e(Settings.tag, "cgeoBase.login: No login information stored"); + Login.setActualStatus(cgeoapplication.getInstance().getString(R.string.err_login)); + Log.e("cgeoBase.login: No login information stored"); return StatusCode.NO_LOGIN_INFO_STORED; } - // res is null during the unit tests - if (cgBase.res != null) { - Login.setActualStatus(cgBase.res.getString(R.string.init_login_popup_working)); - } - HttpResponse loginResponse = Network.request("https://www.geocaching.com/login/default.aspx", null, false, false, false); + Login.setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_working)); + HttpResponse loginResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx"); String loginData = Network.getResponseData(loginResponse); if (loginResponse != null && loginResponse.getStatusLine().getStatusCode() == 503 && BaseUtils.matches(loginData, GCConstants.PATTERN_MAINTENANCE)) { return StatusCode.MAINTENANCE; } if (StringUtils.isBlank(loginData)) { - Log.e(Settings.tag, "cgeoBase.login: Failed to retrieve login page (1st)"); + Log.e("cgeoBase.login: Failed to retrieve login page (1st)"); return StatusCode.CONNECTION_FAILED; // no loginpage } if (Login.getLoginStatus(loginData)) { - Log.i(Settings.tag, "Already logged in Geocaching.com as " + login.left); + Log.i("Already logged in Geocaching.com as " + login.left); Login.switchToEnglish(loginData); return StatusCode.NO_ERROR; // logged in } - Network.clearCookies(); + Cookies.clearCookies(); Settings.setCookieStore(null); final Parameters params = new Parameters( @@ -98,8 +97,8 @@ public abstract class Login { "ctl00$ContentBody$cbRememberMe", "on", "ctl00$ContentBody$btnSignIn", "Login"); final String[] viewstates = Login.getViewstates(loginData); - if (cgBase.isEmpty(viewstates)) { - Log.e(Settings.tag, "cgeoBase.login: Failed to find viewstates"); + if (isEmpty(viewstates)) { + Log.e("cgeoBase.login: Failed to find viewstates"); return StatusCode.LOGIN_PARSE_ERROR; // no viewstates } Login.putViewstates(params, viewstates); @@ -109,36 +108,36 @@ public abstract class Login { if (StringUtils.isNotBlank(loginData)) { if (Login.getLoginStatus(loginData)) { - Log.i(Settings.tag, "Successfully logged in Geocaching.com as " + login.left); + Log.i("Successfully logged in Geocaching.com as " + login.left); Login.switchToEnglish(loginData); - Settings.setCookieStore(Network.dumpCookieStore()); + Settings.setCookieStore(Cookies.dumpCookieStore()); return StatusCode.NO_ERROR; // logged in } else { if (loginData.contains("Your username/password combination does not match.")) { - Log.i(Settings.tag, "Failed to log in Geocaching.com as " + login.left + " because of wrong username/password"); + Log.i("Failed to log in Geocaching.com as " + login.left + " because of wrong username/password"); return StatusCode.WRONG_LOGIN_DATA; // wrong login } else { - Log.i(Settings.tag, "Failed to log in Geocaching.com as " + login.left + " for some unknown reason"); + Log.i("Failed to log in Geocaching.com as " + login.left + " for some unknown reason"); return StatusCode.UNKNOWN_ERROR; // can't login } } } else { - Log.e(Settings.tag, "cgeoBase.login: Failed to retrieve login page (2nd)"); + Log.e("cgeoBase.login: Failed to retrieve login page (2nd)"); // FIXME: should it be CONNECTION_FAILED to match the first attempt? return StatusCode.COMMUNICATION_ERROR; // no login page } } public static StatusCode logout() { - HttpResponse logoutResponse = Network.request("https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fdefault.aspx%3f", null, false, false, false); + HttpResponse logoutResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fdefault.aspx%3f"); String logoutData = Network.getResponseData(logoutResponse); if (logoutResponse != null && logoutResponse.getStatusLine().getStatusCode() == 503 && BaseUtils.matches(logoutData, GCConstants.PATTERN_MAINTENANCE)) { return StatusCode.MAINTENANCE; } - Network.clearCookies(); + Cookies.clearCookies(); Settings.setCookieStore(null); return StatusCode.NO_ERROR; } @@ -171,14 +170,6 @@ public abstract class Login { actualUserName = userName; } - public static String getActualMemberStatus() { - return actualMemberStatus; - } - - public static void setActualMemberStatus(final String memberStatus) { - actualMemberStatus = memberStatus; - } - public static int getActualCachesFound() { return actualCachesFound; } @@ -191,20 +182,16 @@ public abstract class Login { */ public static boolean getLoginStatus(final String page) { if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgeoBase.checkLogin: No page given"); + Log.e("cgeoBase.checkLogin: No page given"); return false; } - // res is null during the unit tests - if (cgBase.res != null) { - setActualStatus(cgBase.res.getString(R.string.init_login_popup_ok)); - } + setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_ok)); // on every page except login page setActualLoginStatus(BaseUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME)); if (isActualLoginStatus()) { setActualUserName(BaseUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???")); - setActualMemberStatus(BaseUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, "???")); setActualCachesFound(Integer.parseInt(BaseUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", ""))); return true; } @@ -213,28 +200,24 @@ public abstract class Login { setActualLoginStatus(BaseUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME_LOGIN_PAGE)); if (isActualLoginStatus()) { setActualUserName(Settings.getUsername()); - setActualMemberStatus(Settings.getMemberStatus()); // number of caches found is not part of this page return true; } - // res is null during the unit tests - if (cgBase.res != null) { - setActualStatus(cgBase.res.getString(R.string.init_login_popup_failed)); - } + setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_failed)); return false; } private static void switchToEnglish(String previousPage) { if (previousPage != null && previousPage.indexOf(ENGLISH) >= 0) { - Log.i(Settings.tag, "Geocaching.com language already set to English"); + Log.i("Geocaching.com language already set to English"); // get find count - getLoginStatus(Network.getResponseData(Network.request("http://www.geocaching.com/email/", null, false))); + getLoginStatus(Network.getResponseData(Network.getRequest("http://www.geocaching.com/email/"))); } else { - final String page = Network.getResponseData(Network.request("http://www.geocaching.com/default.aspx", null, false)); + final String page = Network.getResponseData(Network.getRequest("http://www.geocaching.com/default.aspx")); getLoginStatus(page); if (page == null) { - Log.e(Settings.tag, "Failed to read viewstates to set geocaching.com language"); + Log.e("Failed to read viewstates to set geocaching.com language"); } final Parameters params = new Parameters( "__EVENTTARGET", "ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem", // switch to english @@ -242,14 +225,14 @@ public abstract class Login { Login.transferViewstates(page, params); final HttpResponse response = Network.postRequest("http://www.geocaching.com/default.aspx", params); if (!Network.isSuccess(response)) { - Log.e(Settings.tag, "Failed to set geocaching.com language to English"); + Log.e("Failed to set geocaching.com language to English"); } } } public static BitmapDrawable downloadAvatarAndGetMemberStatus(final Context context) { try { - final String profile = BaseUtils.replaceWhitespace(Network.getResponseData(Network.request("http://www.geocaching.com/my/", null, false))); + final String profile = BaseUtils.replaceWhitespace(Network.getResponseData(Network.getRequest("http://www.geocaching.com/my/"))); Settings.setMemberStatus(BaseUtils.getMatch(profile, GCConstants.PATTERN_MEMBER_STATUS, true, null)); @@ -261,9 +244,9 @@ public abstract class Login { return imgGetter.getDrawable(avatarURL); } // No match? There may be no avatar set by user. - Log.d(Settings.tag, "No avatar set for user"); + Log.d("No avatar set for user"); } catch (Exception e) { - Log.w(Settings.tag, "Error when retrieving user avatar", e); + Log.w("Error when retrieving user avatar", e); } return null; } @@ -273,10 +256,10 @@ public abstract class Login { */ public static void detectGcCustomDate() { - final String result = Network.getResponseData(Network.request("http://www.geocaching.com/account/ManagePreferences.aspx", null, false, false, false)); + final String result = Network.getResponseData(Network.getRequest("http://www.geocaching.com/account/ManagePreferences.aspx")); if (null == result) { - Log.w(Settings.tag, "cgeoBase.detectGcCustomDate: result is null"); + Log.w("cgeoBase.detectGcCustomDate: result is null"); return; } @@ -315,6 +298,24 @@ public abstract class Login { } /** + * checks if an Array of Strings is empty or not. Empty means: + * - Array is null + * - or all elements are null or empty strings + */ + public static boolean isEmpty(String[] a) { + if (a == null) { + return true; + } + + for (String s : a) { + if (StringUtils.isNotEmpty(s)) { + return false; + } + } + return true; + } + + /** * read all viewstates from page * * @return String[] with all view states @@ -333,7 +334,7 @@ public abstract class Login { try { count = Integer.parseInt(matcherViewstateCount.group(1)); } catch (NumberFormatException e) { - Log.e(Settings.tag, "getViewStates", e); + Log.e("getViewStates", e); } } @@ -351,7 +352,7 @@ public abstract class Login { try { no = Integer.parseInt(sno); } catch (NumberFormatException e) { - Log.e(Settings.tag, "getViewStates", e); + Log.e("getViewStates", e); no = 0; } } @@ -389,10 +390,45 @@ public abstract class Login { putViewstates(params, getViewstates(page)); } - static public String[] requestViewstates(final String uri, final Parameters params, boolean xContentType, boolean my) { - final HttpResponse response = Network.request(uri, params, xContentType, my, false); + /** + * POST HTTP request. Do the request a second time if the user is not logged in + * + * @param uri + * @return + */ + public static String postRequestLogged(final String uri) { + HttpResponse response = Network.postRequest(uri, null); + String data = Network.getResponseData(response); + + if (!getLoginStatus(data)) { + if (login() == StatusCode.NO_ERROR) { + response = Network.postRequest(uri, null); + data = Network.getResponseData(response); + } else { + Log.i("Working as guest."); + } + } + return data; + } - return getViewstates(Network.getResponseData(response)); + /** + * GET HTTP request. Do the request a second time if the user is not logged in + * + * @param uri + * @param params + * @return + */ + public static String getRequestLogged(final String uri, final Parameters params) { + final String data = Network.getResponseData(Network.getRequest(uri, params)); + + if (!getLoginStatus(data)) { + if (login() == StatusCode.NO_ERROR) { + return Network.getResponseData(Network.getRequest(uri, params)); + } else { + Log.i("Working as guest."); + } + } + return data; } } diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java index 2a146cc..289c9db 100644 --- a/main/src/cgeo/geocaching/connector/gc/Tile.java +++ b/main/src/cgeo/geocaching/connector/gc/Tile.java @@ -1,12 +1,12 @@ package cgeo.geocaching.connector.gc; -import cgeo.geocaching.Settings; import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.Log; import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -45,22 +45,16 @@ public class Tile { private final int tileX; private final int tileY; private final int zoomlevel; + private final Viewport viewPort; public Tile(Geopoint origin, int zoomlevel) { - assert zoomlevel >= ZOOMLEVEL_MIN && zoomlevel <= ZOOMLEVEL_MAX : "zoomlevel out of range"; this.zoomlevel = Math.max(Math.min(zoomlevel, ZOOMLEVEL_MAX), ZOOMLEVEL_MIN); tileX = calcX(origin); tileY = calcY(origin); - } - - public Tile(int tileX, int tileY, int zoomlevel) { - assert zoomlevel >= ZOOMLEVEL_MIN && zoomlevel <= ZOOMLEVEL_MAX : "zoomlevel out of range"; - this.zoomlevel = zoomlevel; - this.tileX = tileX; - this.tileY = tileY; + viewPort = new Viewport(getCoord(new UTFGridPosition(0, 0)), getCoord(new UTFGridPosition(63, 63))); } public int getZoomlevel() { @@ -161,7 +155,7 @@ public class Tile { public static int calcZoomLat(final Geopoint bottom, final Geopoint top) { int zoom = (int) Math.ceil( - Math.log(2 * Math.PI / + Math.log(2.0 * Math.PI / Math.abs( asinh(tanGrad(bottom.getLatitude())) - asinh(tanGrad(top.getLatitude())) @@ -213,26 +207,23 @@ public class Tile { } /** Request JSON informations for a tile */ - public static String requestMapInfo(final String url, final String referer) { - final HttpGet request = new HttpGet(url); - request.addHeader("Accept", "application/json, text/javascript, */*; q=0.01"); - request.addHeader("Referer", referer); - request.addHeader("X-Requested-With", "XMLHttpRequest"); - return Network.getResponseData(Network.request(request), false); + public static String requestMapInfo(final String url, final Parameters params, final String referer) { + return Network.getResponseData(Network.getRequest(url, params, new Parameters("Referer", referer))); } /** Request .png image for a tile. */ - public static Bitmap requestMapTile(final String url, final String referer) { - final HttpGet request = new HttpGet(url); - request.addHeader("Accept", "image/png,image/*;q=0.8,*/*;q=0.5"); - request.addHeader("Referer", referer); - request.addHeader("X-Requested-With", "XMLHttpRequest"); - final HttpResponse response = Network.request(request); + public static Bitmap requestMapTile(final String url, final Parameters params, final String referer) { + final HttpResponse response = Network.getRequest(url, params, new Parameters("Referer", referer)); try { return response != null ? BitmapFactory.decodeStream(response.getEntity().getContent()) : null; } catch (IOException e) { - Log.e(Settings.tag, "cgBase.requestMapTile() " + e.getMessage()); + Log.e("cgBase.requestMapTile() " + e.getMessage()); } return null; } + + public boolean containsPoint(Geopoint coords) { + + return viewPort.contains(coords); + } } diff --git a/main/src/cgeo/geocaching/connector/opencaching/OkapiClient.java b/main/src/cgeo/geocaching/connector/opencaching/OkapiClient.java index 7c1138a..4e4d9f7 100644 --- a/main/src/cgeo/geocaching/connector/opencaching/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/opencaching/OkapiClient.java @@ -1,9 +1,8 @@ package cgeo.geocaching.connector.opencaching; -import cgeo.geocaching.Settings; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgImage; -import cgeo.geocaching.cgLog; +import cgeo.geocaching.LogEntry; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; @@ -114,7 +113,7 @@ final public class OkapiClient { return caches; } } catch (JSONException e) { - Log.e(Settings.tag, "OkapiClient.parseCaches", e); + Log.e("OkapiClient.parseCaches", e); } return null; } @@ -181,7 +180,7 @@ final public class OkapiClient { // save full detailed caches cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); } catch (JSONException e) { - Log.e(Settings.tag, "OkapiClient.parseCache", e); + Log.e("OkapiClient.parseCache", e); } return cache; } @@ -203,22 +202,22 @@ final public class OkapiClient { return user.getString(USER_USERNAME); } - private static List<cgLog> parseLogs(JSONArray logsJSON) { - List<cgLog> result = null; + private static List<LogEntry> parseLogs(JSONArray logsJSON) { + List<LogEntry> result = null; for (int i = 0; i < logsJSON.length(); i++) { try { JSONObject logResponse = logsJSON.getJSONObject(i); - cgLog log = new cgLog(); + LogEntry log = new LogEntry(); log.date = parseDate(logResponse.getString(LOG_DATE)).getTime(); log.log = logResponse.getString(LOG_COMMENT).trim(); log.type = parseLogType(logResponse.getString(LOG_TYPE)); log.author = parseUser(logResponse.getJSONObject(LOG_USER)); if (result == null) { - result = new ArrayList<cgLog>(); + result = new ArrayList<LogEntry>(); } result.add(log); } catch (JSONException e) { - Log.e(Settings.tag, "OkapiClient.parseLogs", e); + Log.e("OkapiClient.parseLogs", e); } } return result; @@ -240,7 +239,7 @@ final public class OkapiClient { try { return ISO8601DATEFORMAT.parse(strippedDate); } catch (ParseException e) { - Log.e(Settings.tag, "OkapiClient.parseDate", e); + Log.e("OkapiClient.parseDate", e); } return null; } @@ -260,7 +259,7 @@ final public class OkapiClient { try { size = response.getDouble(CACHE_SIZE); } catch (JSONException e) { - Log.e(Settings.tag, "OkapiClient.getCacheSize", e); + Log.e("OkapiClient.getCacheSize", e); } switch ((int) Math.round(size)) { case 1: diff --git a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java new file mode 100644 index 0000000..46e198f --- /dev/null +++ b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java @@ -0,0 +1,139 @@ +package cgeo.geocaching.enumerations; + +import cgeo.geocaching.cgeoapplication; + +import android.content.res.Resources; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + + +public enum CacheAttribute { + UNKNOWN(0, ""), + DOGS(1, "dogs"), + FEE(2, "fee"), + RAPPELLING(3, "rappelling"), + BOAT(4, "boat"), + SCUBA(5, "scuba"), + KIDS(6, "kids"), + ONEHOUR(7, "onehour"), + SCENIC(8, "scenic"), + HIKING(9, "hiking"), + CLIMBING(10, "climbing"), + WADING(11, "wading"), + SWIMMING(12, "swimming"), + AVAILABLE(13, "available"), + NIGHT(14, "night"), + WINTER(15, "winter"), + POISONOAK(17, "poisonoak"), + DANGEROUSANIMALS(18, "dangerousanimals"), + TICKS(19, "ticks"), + MINE(29, "mine"), + CLIFF(21, "cliff"), + HUNTING(22, "hunting"), + DANGER(23, "danger"), + WHEELCHAIR(24, "wheelchair"), + PARKING(25, "parking"), + PUBLIC(26, "public"), + WATER(27, "water"), + RESTROOMS(28, "restrooms"), + PHONE(29, "phone"), + PICNIC(30, "picnic"), + CAMPING(31, "camping"), + BICYCLES(32, "bicycles"), + MOTORCYCLES(33, "motorcycles"), + QUADS(34, "quads"), + JEEPS(35, "jeeps"), + SNOWMOBILES(36, "snowmobiles"), + HORSES(37, "horses"), + CAMPFIRES(38, "campfires"), + THORN(39, "thorn"), + STEALTH(40, "stealth"), + STROLLER(41, "stroller"), + FIRSTAID(42, "firstaid"), + COW(43, "cow"), + FLASHLIGHT(44, "flashlight"), + LANDF(45, "landf"), + RV(46, "rv"), + FIELD_PUZZLE(47, "field_puzzle"), + UV(48, "uv"), + SNOWSHOES(49, "snowshoes"), + SKIIS(50, "skiis"), + SPECIAL_TOOLS(51, "s_tool"), + NIGHTCACHE(52, "nightcache"), + PARKNGRAB(53, "parkngrab"), + ABANDONED_BUILDING(54, "abandonedbuilding"), + HIKE_SHORT(55, "hike_short"), + HIKE_MED(56, "hike_med"), + HIKE_LONG(57, "hike_long"), + FUEL(58, "fuel"), + FOOD(59, "food"), + WIRELESS_BEACON(60, "wirelessbeacon"), + PARTNERSHIP(61, "partnership"), + SEASONAL(62, "seasonal"), + TOURIST_OK(63, "touristok"), + TREECLIMBING(64, "treeclimbing"), + FRONTYARD(65, "frontyard"), + TEAMWORK(66, "teamwork"); + + public static final String INTERNAL_PRE = "attribute_"; + public static final String INTERNAL_YES = "_yes"; + public static final String INTERNAL_NO = "_no"; + + public final int id; + public final String gcRawName; + + private CacheAttribute(final int id, final String gcRawName) { + this.id = id; + this.gcRawName = gcRawName; + } + + public String getL10n(final boolean enabled) { + final String attributeDescriptor = INTERNAL_PRE + gcRawName + (enabled ? INTERNAL_YES : INTERNAL_NO); + + cgeoapplication instance = cgeoapplication.getInstance(); + if (instance != null) { + Resources res = instance.getResources(); + int id = res.getIdentifier(attributeDescriptor, "string", instance.getBaseContext().getPackageName()); + + return (id > 0) ? res.getString(id) : attributeDescriptor; + } else { + return attributeDescriptor; + } + } + + private final static Map<String, CacheAttribute> FIND_BY_GCRAWNAME; + + static { + final HashMap<String, CacheAttribute> mapGcRawNames = new HashMap<String, CacheAttribute>(); + for (CacheAttribute attr : values()) { + mapGcRawNames.put(attr.gcRawName, attr); + } + FIND_BY_GCRAWNAME = Collections.unmodifiableMap(mapGcRawNames); + } + + public static CacheAttribute getById(final int id) { + for (CacheAttribute attr : values()) { + if (attr.id == id) { + return attr; + } + } + return UNKNOWN; + } + + public static CacheAttribute getByGcRawName(final String gcRawName) { + final CacheAttribute result = gcRawName != null ? FIND_BY_GCRAWNAME.get(gcRawName) : null; + if (result == null) { + return UNKNOWN; + } + return result; + } + + public static String trimAttributeName(String attributeName) { + if (null == attributeName) { + return ""; + } + return attributeName.replace(INTERNAL_PRE, "").replace(INTERNAL_YES, "").replace(INTERNAL_NO, "").trim(); + } +} diff --git a/main/src/cgeo/geocaching/enumerations/CacheSize.java b/main/src/cgeo/geocaching/enumerations/CacheSize.java index 9b0a559..b20a227 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheSize.java +++ b/main/src/cgeo/geocaching/enumerations/CacheSize.java @@ -25,13 +25,11 @@ public enum CacheSize { public final String id; public final int comparable; private final int stringId; - private String l10n; // not final because the locale can be changed private CacheSize(String id, int comparable, int stringId) { this.id = id; this.comparable = comparable; this.stringId = stringId; - setL10n(); } final private static Map<String, CacheSize> FIND_BY_ID; @@ -61,12 +59,7 @@ public enum CacheSize { } public final String getL10n() { - return l10n; + return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId); } - - public void setL10n() { - this.l10n = cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId); - } - } diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java index 96e7eb5..482418e 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheType.java +++ b/main/src/cgeo/geocaching/enumerations/CacheType.java @@ -37,7 +37,6 @@ public enum CacheType { public final String pattern; public final String guid; private final int stringId; - private String l10n; // not final because the locale can be changed public final int markerId; private CacheType(String id, String pattern, String guid, int stringId, int markerId) { @@ -45,7 +44,6 @@ public enum CacheType { this.pattern = pattern; this.guid = guid; this.stringId = stringId; - setL10n(); this.markerId = markerId; } @@ -63,7 +61,7 @@ public enum CacheType { } public final static CacheType getById(final String id) { - final CacheType result = id != null ? CacheType.FIND_BY_ID.get(id.toLowerCase().trim()) : null; + final CacheType result = (id != null) ? CacheType.FIND_BY_ID.get(id.toLowerCase().trim()) : null; if (result == null) { return UNKNOWN; } @@ -71,7 +69,7 @@ public enum CacheType { } public final static CacheType getByPattern(final String pattern) { - final CacheType result = pattern != null ? CacheType.FIND_BY_PATTERN.get(pattern.toLowerCase().trim()) : null; + final CacheType result = (pattern != null) ? CacheType.FIND_BY_PATTERN.get(pattern.toLowerCase().trim()) : null; if (result == null) { return UNKNOWN; } @@ -79,11 +77,10 @@ public enum CacheType { } public final String getL10n() { - return l10n; + return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId); } - public void setL10n() { - this.l10n = cgeoapplication.getInstance().getBaseContext().getResources().getString(this.stringId); + public boolean isEvent() { + return CacheType.EVENT == this || CacheType.MEGA_EVENT == this || CacheType.CITO == this || CacheType.LOSTANDFOUND == this; } - } diff --git a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java b/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java index 0f0b721..c4782d8 100644 --- a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java +++ b/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java @@ -28,13 +28,11 @@ public interface LiveMapStrategy { public final int id; public final EnumSet<StrategyFlag> flags; private final int stringId; - private String l10n; // not final because the locale can be changed private Strategy(int id, EnumSet<StrategyFlag> flags, int stringId) { this.id = id; this.flags = flags; this.stringId = stringId; - setL10n(); } public final static Strategy getById(final int id) { @@ -47,12 +45,7 @@ public interface LiveMapStrategy { } public final String getL10n() { - return l10n; - } - - public void setL10n() { - this.l10n = cgeoapplication.getInstance().getBaseContext().getResources().getString(this.stringId); + return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId); } } - } diff --git a/main/src/cgeo/geocaching/enumerations/LogType.java b/main/src/cgeo/geocaching/enumerations/LogType.java index aab4196..14be6a1 100644 --- a/main/src/cgeo/geocaching/enumerations/LogType.java +++ b/main/src/cgeo/geocaching/enumerations/LogType.java @@ -42,17 +42,15 @@ public enum LogType { LOG_UNKNOWN(0, "unknown", "", R.string.err_unknown); // LogType not init. yet public final int id; - private final String iconName; - private final String type; + public final String iconName; + public final String type; private final int stringId; - private String l10n; // not final because the locale can be changed private LogType(int id, String iconName, String type, int stringId) { this.id = id; this.iconName = iconName; this.type = type; this.stringId = stringId; - setL10n(); } private final static Map<String, LogType> FIND_BY_ICONNAME; @@ -94,12 +92,6 @@ public enum LogType { } public final String getL10n() { - return l10n; + return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId); } - - public void setL10n() { - this.l10n = cgeoapplication.getInstance().getBaseContext().getResources().getString(this.stringId); - } - } - diff --git a/main/src/cgeo/geocaching/enumerations/StatusCode.java b/main/src/cgeo/geocaching/enumerations/StatusCode.java index d49acb2..1a1f05d 100644 --- a/main/src/cgeo/geocaching/enumerations/StatusCode.java +++ b/main/src/cgeo/geocaching/enumerations/StatusCode.java @@ -2,41 +2,34 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.R; -import android.content.Context; import android.content.res.Resources; public enum StatusCode { - COMMUNICATION_NOT_STARTED(0, R.string.err_start), - NO_ERROR(1, R.string.err_none), - LOG_SAVED(2, R.string.info_log_saved), - LOGIN_PARSE_ERROR(-1, R.string.err_parse), - CONNECTION_FAILED(-2, R.string.err_server), - NO_LOGIN_INFO_STORED(-3, R.string.err_login), - UNKNOWN_ERROR(-4, R.string.err_unknown), - COMMUNICATION_ERROR(-5, R.string.err_comm), - WRONG_LOGIN_DATA(-6, R.string.err_wrong), - UNAPPROVED_LICENSE(-7, R.string.err_license), - UNPUBLISHED_CACHE(-8, R.string.err_unpublished), - PREMIUM_ONLY(-9, R.string.err_premium_only), - MAINTENANCE(-10, R.string.err_maintenance), - LOG_POST_ERROR(1000, R.string.err_log_post_failed), - NO_LOG_TEXT(1001, R.string.warn_log_text_fill), - NO_DATA_FROM_SERVER(1002, R.string.err_log_failed_server), - NOT_LOGGED_IN(-11, R.string.init_login_popup_failed); - - final private int error_code; + COMMUNICATION_NOT_STARTED(R.string.err_start), + NO_ERROR(R.string.err_none), + LOG_SAVED(R.string.info_log_saved), + LOGIN_PARSE_ERROR(R.string.err_parse), + CONNECTION_FAILED(R.string.err_server), + NO_LOGIN_INFO_STORED(R.string.err_login), + UNKNOWN_ERROR(R.string.err_unknown), + COMMUNICATION_ERROR(R.string.err_comm), + WRONG_LOGIN_DATA(R.string.err_wrong), + UNAPPROVED_LICENSE(R.string.err_license), + UNPUBLISHED_CACHE(R.string.err_unpublished), + PREMIUM_ONLY(R.string.err_premium_only), + MAINTENANCE(R.string.err_maintenance), + LOG_POST_ERROR(R.string.err_log_post_failed), + NO_LOG_TEXT(R.string.warn_log_text_fill), + NO_DATA_FROM_SERVER(R.string.err_log_failed_server), + NOT_LOGGED_IN(R.string.init_login_popup_failed); + final private int error_string; - StatusCode(int error_code, int error_string) { - this.error_code = error_code; + StatusCode(int error_string) { this.error_string = error_string; } - public int getCode() { - return error_code; - } - public int getErrorString() { return error_string; } @@ -45,8 +38,4 @@ public enum StatusCode { return res.getString(error_string); } - public String getErrorString(final Context context) { - return getErrorString(context.getResources()); - } - } diff --git a/main/src/cgeo/geocaching/enumerations/WaypointType.java b/main/src/cgeo/geocaching/enumerations/WaypointType.java index 78e5ceb..44004c0 100644 --- a/main/src/cgeo/geocaching/enumerations/WaypointType.java +++ b/main/src/cgeo/geocaching/enumerations/WaypointType.java @@ -5,7 +5,9 @@ import cgeo.geocaching.cgeoapplication; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; /** * Enum listing waypoint types @@ -23,13 +25,11 @@ public enum WaypointType { public final String id; public final int stringId; - private String l10n; // not final because the locale can be changed public final int markerId; private WaypointType(String id, int stringId, int markerId) { this.id = id; this.stringId = stringId; - setL10n(); this.markerId = markerId; } @@ -38,13 +38,13 @@ public enum WaypointType { * non public so that <code>null</code> handling can be handled centrally in the enum type itself */ private static final Map<String, WaypointType> FIND_BY_ID; - public static final Map<WaypointType, String> ALL_TYPES_EXCEPT_OWN = new HashMap<WaypointType, String>(); + public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN = new HashSet<WaypointType>(); static { final HashMap<String, WaypointType> mapping = new HashMap<String, WaypointType>(); for (WaypointType wt : values()) { mapping.put(wt.id, wt); if (wt != WaypointType.OWN) { - ALL_TYPES_EXCEPT_OWN.put(wt, wt.getL10n()); + ALL_TYPES_EXCEPT_OWN.add(wt); } } FIND_BY_ID = Collections.unmodifiableMap(mapping); @@ -66,15 +66,9 @@ public enum WaypointType { } public final String getL10n() { - return l10n; + return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId); } - public void setL10n() { - this.l10n = cgeoapplication.getInstance().getBaseContext().getResources().getString(this.stringId); - if (WaypointType.ALL_TYPES_EXCEPT_OWN != null && WaypointType.ALL_TYPES_EXCEPT_OWN.containsKey(this)) { - WaypointType.ALL_TYPES_EXCEPT_OWN.put(this, this.getL10n()); - } - } @Override public final String toString() { diff --git a/main/src/cgeo/geocaching/export/AbstractExport.java b/main/src/cgeo/geocaching/export/AbstractExport.java new file mode 100644 index 0000000..85b060b --- /dev/null +++ b/main/src/cgeo/geocaching/export/AbstractExport.java @@ -0,0 +1,32 @@ +package cgeo.geocaching.export; + +import cgeo.geocaching.cgeoapplication; + +abstract class AbstractExport implements Export { + private final String name; + + protected AbstractExport(final String name) { + this.name = name; + } + + public String getName() { + return name; + } + + /** + * Generates a localized string from a resource id. + * + * @param resourceId + * the resource id of the string + * @return localized string + */ + protected static String getString(int resourceId) { + return cgeoapplication.getInstance().getString(resourceId); + } + + @Override + public String toString() { + // used in the array adapter of the dialog showing the exports + return getName(); + } +} diff --git a/main/src/cgeo/geocaching/export/Export.java b/main/src/cgeo/geocaching/export/Export.java new file mode 100644 index 0000000..7a2b075 --- /dev/null +++ b/main/src/cgeo/geocaching/export/Export.java @@ -0,0 +1,29 @@ +package cgeo.geocaching.export; + +import cgeo.geocaching.cgCache; + +import android.app.Activity; + +import java.util.List; + +/** + * Represents an exporter to export a {@link List} of {@link cgCache} to various formats. + */ +interface Export { + /** + * Export a {@link List} of {@link cgCache} to various formats. + * + * @param caches + * The {@link List} of {@link cgCache} to be exported + * @param activity + * optional: Some exporters might have an UI which requires an {@link Activity} + */ + public void export(List<cgCache> caches, Activity activity); + + /** + * Get the localized name of this exporter. + * + * @return localized name + */ + public String getName(); +} diff --git a/main/src/cgeo/geocaching/export/ExportFactory.java b/main/src/cgeo/geocaching/export/ExportFactory.java new file mode 100644 index 0000000..8b3df58 --- /dev/null +++ b/main/src/cgeo/geocaching/export/ExportFactory.java @@ -0,0 +1,65 @@ +package cgeo.geocaching.export; + +import cgeo.geocaching.R; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.utils.Log; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.widget.ArrayAdapter; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Factory to create a dialog with all available exporters. + */ +public abstract class ExportFactory { + + /** + * Contains instances of all available exporter classes. + */ + private static final List<Class<? extends Export>> exporterClasses; + + static { + final ArrayList<Class<? extends Export>> temp = new ArrayList<Class<? extends Export>>(); + temp.add(FieldnoteExport.class); + temp.add(GpxExport.class); + exporterClasses = Collections.unmodifiableList(temp); + } + + /** + * Creates a dialog so that the user can select an exporter. + * + * @param caches + * The {@link List} of {@link cgCache} to be exported + * @param activity + * The {@link Activity} in whose context the dialog should be shown + */ + public static void showExportMenu(final List<cgCache> caches, final Activity activity) { + final AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle(R.string.export).setIcon(android.R.drawable.ic_menu_share); + + final ArrayList<Export> export = new ArrayList<Export>(); + for (Class<? extends Export> exporterClass : exporterClasses) { + try { + export.add(exporterClass.newInstance()); + } catch (Exception ex) { + Log.e("showExportMenu", ex); + } + } + + final ArrayAdapter<Export> adapter = new ArrayAdapter<Export>(activity, android.R.layout.select_dialog_item, export); + + builder.setAdapter(adapter, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + final Export selectedExport = adapter.getItem(item); + selectedExport.export(caches, activity); + } + }); + + builder.create().show(); + } +}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java new file mode 100644 index 0000000..05fb828 --- /dev/null +++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java @@ -0,0 +1,257 @@ +package cgeo.geocaching.export; + +import cgeo.geocaching.LogEntry; +import cgeo.geocaching.R; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.activity.ActivityMixin; +import cgeo.geocaching.activity.Progress; +import cgeo.geocaching.enumerations.LogType; +import cgeo.geocaching.utils.Log; + +import org.apache.commons.lang3.StringUtils; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.os.AsyncTask; +import android.os.Environment; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Exports offline-logs in the Groundspeak Field Note format.<br> + * <br> + * + * Field Notes are simple plain text files, but poorly documented. Syntax:<br> + * <code>GCxxxxx,yyyy-mm-ddThh:mm:ssZ,Found it,"logtext"</code> + */ +class FieldnoteExport extends AbstractExport { + private static final File exportLocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/field-notes"); + private static final SimpleDateFormat fieldNoteDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + + protected FieldnoteExport() { + super(getString(R.string.export_fieldnotes)); + } + + /** + * A dialog to allow the user to set options for the export. + * + * Currently available options are: upload field notes, only new logs since last export/upload + */ + private class ExportOptionsDialog extends AlertDialog { + public ExportOptionsDialog(final List<cgCache> caches, final Activity activity) { + super(activity); + + View layout = activity.getLayoutInflater().inflate(R.layout.fieldnote_export_dialog, null); + setView(layout); + + ((Button) layout.findViewById(R.id.export)).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + new ExportTask( + caches, + activity, + ((CheckBox) findViewById(R.id.upload)).isChecked(), + ((CheckBox) findViewById(R.id.onlynew)).isChecked()) + .execute((Void) null); + } + }); + } + } + + @Override + public void export(final List<cgCache> caches, final Activity activity) { + if (null == activity) { + // No activity given, so no user interaction possible. + // Start export with default parameters. + new ExportTask(caches, null, false, false).execute((Void) null); + } else { + // Show configuration dialog + new ExportOptionsDialog(caches, activity).show(); + } + } + + private class ExportTask extends AsyncTask<Void, Integer, Boolean> { + private final List<cgCache> caches; + private final Activity activity; + private final boolean onlyNew; + private final Progress progress = new Progress(); + private File exportFile; + + private static final int STATUS_UPLOAD = -1; + + /** + * Instantiates and configurates the task for exporting field notes. + * + * @param caches + * The {@link List} of {@link cgCache} to be exported + * @param activity + * optional: Show a progress bar and toasts + * @param upload + * Upload the Field Note to geocaching.com + * @param onlyNew + * Upload/export only new logs since last export + */ + public ExportTask(final List<cgCache> caches, final Activity activity, final boolean upload, final boolean onlyNew) { + this.caches = caches; + this.activity = activity; + this.onlyNew = onlyNew; + } + + @Override + protected void onPreExecute() { + if (null != activity) { + progress.show(activity, null, getString(R.string.export) + ": " + getName(), ProgressDialog.STYLE_HORIZONTAL, null); + progress.setMaxProgressAndReset(caches.size()); + } + } + + @Override + protected Boolean doInBackground(Void... params) { + final StringBuilder fieldNoteBuffer = new StringBuilder(); + + // We need our own HashMap because LogType will give us localized and maybe + // different strings than gc.com expects in the field note + // We only need such logtypes that are possible to log via c:geo + Map<LogType, String> logTypes = new HashMap<LogType, String>(); + logTypes.put(LogType.LOG_FOUND_IT, "Found it"); + logTypes.put(LogType.LOG_DIDNT_FIND_IT, "Didn't find it"); + logTypes.put(LogType.LOG_NOTE, "Write Note"); + logTypes.put(LogType.LOG_NEEDS_ARCHIVE, "Needs archived"); + logTypes.put(LogType.LOG_NEEDS_MAINTENANCE, "Needs Maintenance"); + logTypes.put(LogType.LOG_WILL_ATTEND, "Will Attend"); + logTypes.put(LogType.LOG_ATTENDED, "Attended"); + logTypes.put(LogType.LOG_WEBCAM_PHOTO_TAKEN, "Webcam Photo Taken"); + + for (int i = 0; i < caches.size(); i++) { + try { + final cgCache cache = caches.get(i); + if (cache.isLogOffline()) { + LogEntry log = cgeoapplication.getInstance().loadLogOffline(cache.getGeocode()); + if (null != logTypes.get(log.type)) { + fieldNoteBuffer.append(cache.getGeocode()) + .append(',') + .append(fieldNoteDateFormat.format(new Date(log.date))) + .append(',') + .append(logTypes.get(log.type)) + .append(",\"") + .append(StringUtils.replaceChars(log.log, '"', '\'')) + .append("\"\n"); + } + } + publishProgress(i + 1); + } catch (Exception e) { + Log.e("FieldnoteExport.ExportTask generation", e); + return false; + } + } + + fieldNoteBuffer.append("\n"); + + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + exportLocation.mkdirs(); + + SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".txt"); + + OutputStream os = null; + Writer fw = null; + try { + os = new FileOutputStream(exportFile); + fw = new OutputStreamWriter(os, "ISO-8859-1"); // TODO: gc.com doesn't support UTF-8 + fw.write(fieldNoteBuffer.toString()); + } catch (IOException e) { + Log.e("FieldnoteExport.ExportTask export", e); + return false; + } finally { + if (fw != null) { + try { + fw.close(); + } catch (IOException e) { + Log.e("FieldnoteExport.ExportTask export", e); + return false; + } + } + } + } else { + return false; + } + + /* + * if (upload) { + * TODO Use multipart POST request for uploading + * publishProgress(STATUS_UPLOAD); + * + * final Parameters uploadParams = new Parameters( + * "__EVENTTARGET", "", + * "__EVENTARGUMENT", "", + * "__VIEWSTATE", "", + * //TODO "ctl00$ContentBody$chkSuppressDate", "on", + * "ctl00$ContentBody$FieldNoteLoader", fieldNoteBuffer.toString(), + * "ctl00$ContentBody$btnUpload", "Upload Field Note"); + * final String uri = "http://www.geocaching.com/my/uploadfieldnotes.aspx"; + * + * String page = Network.getResponseData(Network.postRequest(uri, uploadParams)); + * if (!Login.getLoginStatus(page)) { + * final StatusCode loginState = Login.login(); + * if (loginState == StatusCode.NO_ERROR) { + * page = Network.getResponseData(Network.postRequest(uri, uploadParams)); + * } else { + * Log.e(Settings.tag, "FieldnoteExport.ExportTask upload: No login (error: " + loginState + ")"); + * return false; + * } + * } + * + * if (StringUtils.isBlank(page)) { + * Log.e(Settings.tag, "FieldnoteExport.ExportTask upload: No data from server"); + * return false; + * } + * } + */ + + return true; + } + + @Override + protected void onPostExecute(Boolean result) { + if (null != activity) { + progress.dismiss(); + + if (result) { + if (onlyNew) { + // update last export time in settings + } + ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString()); + } else { + ActivityMixin.showToast(activity, getString(R.string.export_failed)); + } + } + } + + @Override + protected void onProgressUpdate(Integer... status) { + if (null != activity) { + if (STATUS_UPLOAD == status[0]) { + progress.setMessage(getString(R.string.export_fieldnotes_uploading)); + } else { + progress.setProgress(status[0]); + } + } + } + } +} diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java new file mode 100644 index 0000000..2c833a2 --- /dev/null +++ b/main/src/cgeo/geocaching/export/GpxExport.java @@ -0,0 +1,301 @@ +package cgeo.geocaching.export; + +import cgeo.geocaching.R; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.LogEntry; +import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.activity.ActivityMixin; +import cgeo.geocaching.activity.Progress; +import cgeo.geocaching.enumerations.CacheAttribute; +import cgeo.geocaching.enumerations.LoadFlags; +import cgeo.geocaching.utils.BaseUtils; +import cgeo.geocaching.utils.Log; + +import org.apache.commons.lang3.StringEscapeUtils; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.os.AsyncTask; +import android.os.Environment; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +class GpxExport extends AbstractExport { + private static final File exportLocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/gpx-export"); + private static final SimpleDateFormat dateFormatZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + + protected GpxExport() { + super(getString(R.string.export_gpx)); + } + + @Override + public void export(final List<cgCache> caches, final Activity activity) { + new ExportTask(caches, activity).execute((Void) null); + } + + private class ExportTask extends AsyncTask<Void, Integer, Boolean> { + private final List<cgCache> caches; + private final Activity activity; + private final Progress progress = new Progress(); + private File exportFile; + + /** + * Instantiates and configures the task for exporting field notes. + * + * @param caches + * The {@link List} of {@link cgCache} to be exported + * @param activity + * optional: Show a progress bar and toasts + */ + public ExportTask(final List<cgCache> caches, final Activity activity) { + this.caches = caches; + this.activity = activity; + } + + @Override + protected void onPreExecute() { + if (null != activity) { + progress.show(activity, null, getString(R.string.export) + ": " + getName(), ProgressDialog.STYLE_HORIZONTAL, null); + progress.setMaxProgressAndReset(caches.size()); + } + } + + @Override + protected Boolean doInBackground(Void... params) { + // quick check for being able to write the GPX file + if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + return false; + } + + // FIXME: complete export is created in memory. That should be some file stream instead. + final StringBuilder gpx = new StringBuilder(); + + gpx.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); + gpx.append("<gpx version=\"1.0\" creator=\"c:geo - http://www.cgeo.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/0\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0/1 http://www.groundspeak.com/cache/1/0/1/cache.xsd\">"); + + try { + for (int i = 0; i < caches.size(); i++) { + cgCache cache = caches.get(i); + + if (!cache.isDetailed()) { + cache = cgeoapplication.getInstance().loadCache(caches.get(i).getGeocode(), LoadFlags.LOAD_ALL_DB_ONLY); + } + + gpx.append("<wpt "); + gpx.append("lat=\"" + cache.getCoords().getLatitude() + "\" "); + gpx.append("lon=\"" + cache.getCoords().getLongitude() + "\">"); + + gpx.append("<time>"); + gpx.append(StringEscapeUtils.escapeXml(dateFormatZ.format(cache.getHiddenDate()))); + gpx.append("</time>"); + + gpx.append("<name>"); + gpx.append(StringEscapeUtils.escapeXml(cache.getGeocode())); + gpx.append("</name>"); + + gpx.append("<desc>"); + gpx.append(StringEscapeUtils.escapeXml(cache.getName())); + gpx.append("</desc>"); + + gpx.append("<sym>"); + gpx.append(cache.isFound() ? "Geocache Found" : "Geocache"); + gpx.append("</sym>"); + + gpx.append("<type>"); + gpx.append(StringEscapeUtils.escapeXml("Geocache|" + cache.getType().toString())); //TODO: Correct (english) string + gpx.append("</type>"); + + gpx.append("<groundspeak:cache "); + gpx.append("available=\"" + (!cache.isDisabled() ? "True" : "False")); + gpx.append("\" archived=\"" + (cache.isArchived() ? "True" : "False") + "\" "); + gpx.append("xmlns:groundspeak=\"http://www.groundspeak.com/cache/1/0/1\">"); + + gpx.append("<groundspeak:name>"); + gpx.append(StringEscapeUtils.escapeXml(cache.getName())); + gpx.append("</groundspeak:name>"); + + gpx.append("<groundspeak:placed_by>"); + gpx.append(StringEscapeUtils.escapeXml(cache.getOwner())); + gpx.append("</groundspeak:placed_by>"); + + gpx.append("<groundspeak:owner>"); + gpx.append(StringEscapeUtils.escapeXml(cache.getOwnerReal())); + gpx.append("</groundspeak:owner>"); + + gpx.append("<groundspeak:type>"); + gpx.append(StringEscapeUtils.escapeXml(cache.getType().toString())); //TODO: Correct (english) string + gpx.append("</groundspeak:type>"); + + gpx.append("<groundspeak:container>"); + gpx.append(StringEscapeUtils.escapeXml(cache.getSize().toString())); //TODO: Correct (english) string + gpx.append("</groundspeak:container>"); + + if (cache.hasAttributes()) { + //TODO: Attribute conversion required: English verbose name, gpx-id + gpx.append("<groundspeak:attributes>"); + + for (String attribute : cache.getAttributes()) { + final CacheAttribute attr = CacheAttribute.getByGcRawName(CacheAttribute.trimAttributeName(attribute)); + final boolean enabled = attribute.endsWith(CacheAttribute.INTERNAL_YES); + + gpx.append("<groundspeak:attribute id=\""); + gpx.append(attr.id); + gpx.append("\" inc=\""); + if (enabled) { + gpx.append('1'); + } else { + gpx.append('0'); + } + gpx.append("\">"); + gpx.append(StringEscapeUtils.escapeXml(attr.getL10n(enabled))); + gpx.append("</groundspeak:attribute>"); + } + + gpx.append("</groundspeak:attributes>"); + } + + gpx.append("<groundspeak:difficulty>"); + gpx.append(Float.toString(cache.getDifficulty())); + gpx.append("</groundspeak:difficulty>"); + + gpx.append("<groundspeak:terrain>"); + gpx.append(Float.toString(cache.getTerrain())); + gpx.append("</groundspeak:terrain>"); + + gpx.append("<groundspeak:country>"); + gpx.append(StringEscapeUtils.escapeXml(cache.getLocation())); + gpx.append("</groundspeak:country>"); + + gpx.append("<groundspeak:state>"); + gpx.append(StringEscapeUtils.escapeXml(cache.getLocation())); + gpx.append("</groundspeak:state>"); + + gpx.append("<groundspeak:short_description html=\""); + if (BaseUtils.containsHtml(cache.getShortDescription())) { + gpx.append("True"); + } else { + gpx.append("False"); + } + gpx.append("\">"); + gpx.append(StringEscapeUtils.escapeXml(cache.getShortDescription())); + gpx.append("</groundspeak:short_description>"); + + gpx.append("<groundspeak:long_description html=\""); + if (BaseUtils.containsHtml(cache.getDescription())) { + gpx.append("True"); + } else { + gpx.append("False"); + } + gpx.append("\">"); + gpx.append(StringEscapeUtils.escapeXml(cache.getDescription())); + gpx.append("</groundspeak:long_description>"); + + gpx.append("<groundspeak:encoded_hints>"); + gpx.append(StringEscapeUtils.escapeXml(cache.getHint())); + gpx.append("</groundspeak:encoded_hints>"); + + gpx.append("</groundspeak:cache>"); + + //TODO: Waypoints + + if (cache.getLogs().size() > 0) { + gpx.append("<groundspeak:logs>"); + + for (LogEntry log : cache.getLogs()) { + gpx.append("<groundspeak:log id=\""); + gpx.append(log.id); + gpx.append("\">"); + + gpx.append("<groundspeak:date>"); + gpx.append(StringEscapeUtils.escapeXml(dateFormatZ.format(new Date(log.date)))); + gpx.append("</groundspeak:date>"); + + gpx.append("<groundspeak:type>"); + gpx.append(StringEscapeUtils.escapeXml(log.type.type)); + gpx.append("</groundspeak:type>"); + + gpx.append("<groundspeak:finder id=\"\">"); + gpx.append(StringEscapeUtils.escapeXml(log.author)); + gpx.append("</groundspeak:finder>"); + + gpx.append("<groundspeak:text encoded=\"False\">"); + gpx.append(StringEscapeUtils.escapeXml(log.log)); + gpx.append("</groundspeak:text>"); + + gpx.append("</groundspeak:log>"); + } + + gpx.append("</groundspeak:logs>"); + } + + gpx.append("</wpt>"); + + publishProgress(i + 1); + } + } catch (Exception e) { + Log.e("GpxExport.ExportTask generation", e); + return false; + } + + gpx.append("</gpx>"); + + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + exportLocation.mkdirs(); + + SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".gpx"); + + OutputStream os = null; + Writer fw = null; + try { + os = new FileOutputStream(exportFile); + fw = new OutputStreamWriter(os, "UTF-8"); + fw.write(gpx.toString()); + } catch (IOException e) { + Log.e("GpxExport.ExportTask export", e); + return false; + } finally { + if (fw != null) { + try { + fw.close(); + } catch (IOException e) { + Log.e("GpxExport.ExportTask export", e); + return false; + } + } + } + } else { + return false; + } + + return true; + } + + @Override + protected void onPostExecute(Boolean result) { + if (null != activity) { + progress.dismiss(); + if (result) { + ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString()); + } else { + ActivityMixin.showToast(activity, getString(R.string.export_failed)); + } + } + } + + @Override + protected void onProgressUpdate(Integer... status) { + if (null != activity) { + progress.setProgress(status[0]); + } + } + } +} diff --git a/main/src/cgeo/geocaching/files/FileList.java b/main/src/cgeo/geocaching/files/FileList.java index dbdea60..576aa2c 100644 --- a/main/src/cgeo/geocaching/files/FileList.java +++ b/main/src/cgeo/geocaching/files/FileList.java @@ -1,7 +1,6 @@ package cgeo.geocaching.files; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; import cgeo.geocaching.StoredList; import cgeo.geocaching.activity.AbstractListActivity; import cgeo.geocaching.utils.Log; @@ -87,7 +86,7 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis if (waitDialog != null) { waitDialog.dismiss(); } - Log.e(Settings.tag, "cgFileList.loadFilesHandler: " + e.toString()); + Log.e("cgFileList.loadFilesHandler: " + e.toString()); } } }; @@ -188,10 +187,10 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis listDir(list, Environment.getExternalStorageDirectory()); } } else { - Log.w(Settings.tag, "No external media mounted."); + Log.w("No external media mounted."); } } catch (Exception e) { - Log.e(Settings.tag, "cgFileList.loadFiles.run: " + e.toString()); + Log.e("cgFileList.loadFiles.run: " + e.toString()); } changeWaitDialogHandler.sendMessage(Message.obtain(changeWaitDialogHandler, 0, "loaded directories")); diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java index 8fd099d..ccb71cd 100644 --- a/main/src/cgeo/geocaching/files/GPXImporter.java +++ b/main/src/cgeo/geocaching/files/GPXImporter.java @@ -112,7 +112,7 @@ public class GPXImporter { }
}
- Log.i(Settings.tag, "importGPX: " + uri + ", mimetype=" + mimeType);
+ Log.i("importGPX: " + uri + ", mimetype=" + mimeType);
if (GPX_MIME_TYPES.contains(mimeType)) {
new ImportGpxAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start();
} else if (ZIP_MIME_TYPES.contains(mimeType)) {
@@ -142,7 +142,7 @@ public class GPXImporter { importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_STORE_CACHES, R.string.gpx_import_storing, caches.size()));
SearchResult search = storeParsedCaches(caches);
- Log.i(Settings.tag, "Imported successfully " + caches.size() + " caches.");
+ Log.i("Imported successfully " + caches.size() + " caches.");
if (Settings.isStoreOfflineMaps() || Settings.isStoreOfflineWpMaps()) {
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_STORE_STATIC_MAPS, R.string.gpx_import_store_static_maps, search.getCount()));
@@ -155,16 +155,16 @@ public class GPXImporter { importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED, search.getCount(), 0, search));
} catch (IOException e) {
- Log.i(Settings.tag, "Importing caches failed - error reading data: " + e.getMessage());
+ Log.i("Importing caches failed - error reading data: " + e.getMessage());
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_io, 0, e.getLocalizedMessage()));
} catch (ParserException e) {
- Log.i(Settings.tag, "Importing caches failed - data format error" + e.getMessage());
+ Log.i("Importing caches failed - data format error" + e.getMessage());
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_parser, 0, e.getLocalizedMessage()));
} catch (CancellationException e) {
- Log.i(Settings.tag, "Importing caches canceled");
+ Log.i("Importing caches canceled");
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_CANCELED));
} catch (Exception e) {
- Log.e(Settings.tag, "Importing caches failed - unknown error: ", e);
+ Log.e("Importing caches failed - unknown error: ", e);
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_unexpected, 0, e.getLocalizedMessage()));
}
}
@@ -194,7 +194,7 @@ public class GPXImporter { int storedCacheMaps = 0;
for (String geocode : importedCaches.getGeocodes()) {
cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
- Log.d(Settings.tag, "GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode);
+ Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode);
StaticMapsProvider.downloadMaps(cache, app);
storedCacheMaps++;
if (progressHandler.isCancelled()) {
@@ -216,7 +216,7 @@ public class GPXImporter { @Override
protected Collection<cgCache> doImport() throws IOException, ParserException {
- Log.i(Settings.tag, "Import LOC file: " + file.getAbsolutePath());
+ Log.i("Import LOC file: " + file.getAbsolutePath());
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) file.length()));
LocParser parser = new LocParser(listId);
return parser.parse(file, progressHandler);
@@ -253,7 +253,7 @@ public class GPXImporter { @Override
protected Collection<cgCache> doImport(GPXParser parser) throws IOException, ParserException {
- Log.i(Settings.tag, "Import GPX file: " + cacheFile.getAbsolutePath());
+ Log.i("Import GPX file: " + cacheFile.getAbsolutePath());
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) cacheFile.length()));
Collection<cgCache> caches = parser.parse(cacheFile, progressHandler);
@@ -261,7 +261,7 @@ public class GPXImporter { if (wptsFilename != null) {
final File wptsFile = new File(cacheFile.getParentFile(), wptsFilename);
if (wptsFile.canRead()) {
- Log.i(Settings.tag, "Import GPX waypoint file: " + wptsFile.getAbsolutePath());
+ Log.i("Import GPX waypoint file: " + wptsFile.getAbsolutePath());
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) wptsFile.length()));
caches = parser.parse(wptsFile, progressHandler);
}
@@ -282,7 +282,7 @@ public class GPXImporter { @Override
protected Collection<cgCache> doImport(GPXParser parser) throws IOException, ParserException {
- Log.i(Settings.tag, "Import GPX from uri: " + uri);
+ Log.i("Import GPX from uri: " + uri);
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, -1));
InputStream is = contentResolver.openInputStream(uri);
try {
@@ -347,7 +347,7 @@ public class GPXImporter { public ImportGpxZipFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
super(listId, importStepHandler, progressHandler);
this.cacheFile = file;
- Log.i(Settings.tag, "Import zipped GPX: " + file);
+ Log.i("Import zipped GPX: " + file);
}
@Override
@@ -364,7 +364,7 @@ public class GPXImporter { super(listId, importStepHandler, progressHandler);
this.uri = uri;
this.contentResolver = contentResolver;
- Log.i(Settings.tag, "Import zipped GPX from uri: " + uri);
+ Log.i("Import zipped GPX from uri: " + uri);
}
@Override
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java index 0a8137e..051a49b 100644 --- a/main/src/cgeo/geocaching/files/GPXParser.java +++ b/main/src/cgeo/geocaching/files/GPXParser.java @@ -1,10 +1,9 @@ package cgeo.geocaching.files; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; import cgeo.geocaching.StoredList; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgLog; +import cgeo.geocaching.LogEntry; import cgeo.geocaching.cgTrackable; import cgeo.geocaching.cgWaypoint; import cgeo.geocaching.cgeoapplication; @@ -77,7 +76,7 @@ public abstract class GPXParser extends FileParser { private cgCache cache; private cgTrackable trackable = new cgTrackable(); - private cgLog log = new cgLog(); + private LogEntry log = new LogEntry(); private String type = null; private String sym = null; @@ -259,7 +258,7 @@ public abstract class GPXParser extends FileParser { Double.valueOf(attrs.getValue("lon")))); } } catch (Exception e) { - Log.w(Settings.tag, "Failed to parse waypoint's latitude and/or longitude."); + Log.w("Failed to parse waypoint's latitude and/or longitude."); } } }); @@ -295,7 +294,7 @@ public abstract class GPXParser extends FileParser { final String key = cache.getGeocode(); if (result.containsKey(key)) { - Log.w(Settings.tag, "Duplicate geocode during GPX import: " + key); + Log.w("Duplicate geocode during GPX import: " + key); } result.put(key, cache); showProgressMessage(progressHandler, progressStream.getProgress()); @@ -346,7 +345,7 @@ public abstract class GPXParser extends FileParser { try { cache.setHidden(parseDate(body)); } catch (Exception e) { - Log.w(Settings.tag, "Failed to parse cache date: " + e.toString()); + Log.w("Failed to parse cache date: " + e.toString()); } } }); @@ -468,7 +467,7 @@ public abstract class GPXParser extends FileParser { cache.setDisabled(!attrs.getValue("available").equalsIgnoreCase("true")); } } catch (Exception e) { - Log.w(Settings.tag, "Failed to parse cache attributes."); + Log.w("Failed to parse cache attributes."); } } }); @@ -548,7 +547,7 @@ public abstract class GPXParser extends FileParser { try { cache.setDifficulty(Float.parseFloat(body)); } catch (NumberFormatException e) { - Log.w(Settings.tag, "Failed to parse difficulty: " + e.toString()); + Log.w("Failed to parse difficulty: " + e.toString()); } } }); @@ -561,7 +560,7 @@ public abstract class GPXParser extends FileParser { try { cache.setTerrain(Float.parseFloat(body)); } catch (NumberFormatException e) { - Log.w(Settings.tag, "Failed to parse terrain: " + e.toString()); + Log.w("Failed to parse terrain: " + e.toString()); } } }); @@ -675,7 +674,7 @@ public abstract class GPXParser extends FileParser { @Override public void start(Attributes attrs) { - log = new cgLog(); + log = new LogEntry(); try { if (attrs.getIndex("id") > -1) { @@ -705,7 +704,7 @@ public abstract class GPXParser extends FileParser { try { log.date = parseDate(body).getTime(); } catch (Exception e) { - Log.w(Settings.tag, "Failed to parse log date: " + e.toString()); + Log.w("Failed to parse log date: " + e.toString()); } } }); @@ -744,7 +743,7 @@ public abstract class GPXParser extends FileParser { Xml.parse(progressStream, Xml.Encoding.UTF_8, root.getContentHandler()); return result.values(); } catch (SAXException e) { - Log.e(Settings.tag, "Cannot parse .gpx file as GPX " + version + ": could not parse XML - " + e.toString()); + Log.e("Cannot parse .gpx file as GPX " + version + ": could not parse XML - " + e.toString()); throw new ParserException("Cannot parse .gpx file as GPX " + version + ": could not parse XML", e); } } diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java index 3be8da4..ad44dc4 100644 --- a/main/src/cgeo/geocaching/files/LocParser.java +++ b/main/src/cgeo/geocaching/files/LocParser.java @@ -1,7 +1,6 @@ package cgeo.geocaching.files; import cgeo.geocaching.SearchResult; -import cgeo.geocaching.Settings; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheSize; @@ -103,8 +102,7 @@ public final class LocParser extends FileParser { } } - Log.i(Settings.tag, - "Coordinates found in .loc file: " + coords.size()); + Log.i("Coordinates found in .loc file: " + coords.size()); return coords; } @@ -113,7 +111,7 @@ public final class LocParser extends FileParser { try { return new Geopoint(Double.valueOf(latitude), Double.valueOf(longitude)); } catch (NumberFormatException e) { - Log.e(Settings.tag, "LOC format has changed"); + Log.e("LOC format has changed"); } // fall back to parser, just in case the format changes return GeopointParser.parse(latitude, longitude); @@ -144,7 +142,7 @@ public final class LocParser extends FileParser { cache.setListId(listId); cache.setDetailed(true); } - Log.i(Settings.tag, "Caches found in .loc file: " + caches.size()); + Log.i("Caches found in .loc file: " + caches.size()); return caches; } diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java index a97c176..f37d22f 100644 --- a/main/src/cgeo/geocaching/files/LocalStorage.java +++ b/main/src/cgeo/geocaching/files/LocalStorage.java @@ -1,6 +1,5 @@ package cgeo.geocaching.files; -import cgeo.geocaching.Settings; import cgeo.geocaching.utils.CryptUtils; import cgeo.geocaching.utils.Log; @@ -159,7 +158,7 @@ public class LocalStorage { saveHeader("last-modified", response, targetFile); return saved; } catch (IOException e) { - Log.e(Settings.tag, "LocalStorage.saveEntityToFile", e); + Log.e("LocalStorage.saveEntityToFile", e); } return false; @@ -203,7 +202,7 @@ public class LocalStorage { } catch (final FileNotFoundException e) { // Do nothing, the file does not exist } catch (final Exception e) { - Log.w(Settings.tag, "could not read saved header " + name + " for " + baseFile, e); + Log.w("could not read saved header " + name + " for " + baseFile, e); } return null; } @@ -234,7 +233,7 @@ public class LocalStorage { inputStream.close(); } } catch (IOException e) { - Log.e(Settings.tag, "LocalStorage.saveToFile", e); + Log.e("LocalStorage.saveToFile", e); } return false; } @@ -257,7 +256,7 @@ public class LocalStorage { input = new FileInputStream(source); output = new FileOutputStream(destination); } catch (FileNotFoundException e) { - Log.e(Settings.tag, "LocalStorage.copy: could not open file", e); + Log.e("LocalStorage.copy: could not open file", e); if (input != null) { try { input.close(); @@ -274,7 +273,7 @@ public class LocalStorage { input.close(); output.close(); } catch (IOException e) { - Log.e(Settings.tag, "LocalStorage.copy: could not close file", e); + Log.e("LocalStorage.copy: could not close file", e); return false; } @@ -291,7 +290,7 @@ public class LocalStorage { // Flushing is only necessary if the stream is not immediately closed afterwards. // We rely on all callers to do that correctly outside of this method } catch (IOException e) { - Log.e(Settings.tag, "LocalStorage.copy: error when copying data", e); + Log.e("LocalStorage.copy: error when copying data", e); return false; } diff --git a/main/src/cgeo/geocaching/filter/AbstractFilter.java b/main/src/cgeo/geocaching/filter/AbstractFilter.java index 49cf84a..e9f9003 100644 --- a/main/src/cgeo/geocaching/filter/AbstractFilter.java +++ b/main/src/cgeo/geocaching/filter/AbstractFilter.java @@ -26,4 +26,14 @@ abstract class AbstractFilter implements IFilter { public String getName() { return name; } + + /* + * show name in array adapter + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getName(); + } } diff --git a/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java b/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java new file mode 100644 index 0000000..ff3fce5 --- /dev/null +++ b/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java @@ -0,0 +1,16 @@ +package cgeo.geocaching.filter; + +import cgeo.geocaching.cgeoapplication; + + +abstract class AbstractRangeFilter extends AbstractFilter { + + protected final float rangeMin; + protected final float rangeMax; + + public AbstractRangeFilter(int ressourceId, int range) { + super(cgeoapplication.getInstance().getResources().getString(ressourceId) + ' ' + (range == 5 ? '5' : String.valueOf(range) + " + " + String.format("%.1f", range + 0.5))); + this.rangeMin = range; + rangeMax = rangeMin + 1f; + } +}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java index 0ef0787..2565178 100644 --- a/main/src/cgeo/geocaching/filter/AttributeFilter.java +++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java @@ -11,7 +11,7 @@ import android.content.res.Resources; import java.util.EnumSet; -public class AttributeFilter extends AbstractFilter { +class AttributeFilter extends AbstractFilter { private final String attribute; @@ -34,20 +34,27 @@ public class AttributeFilter extends AbstractFilter { @Override public boolean accepts(final cgCache cache) { - final cgCache fullCache = cgeoapplication.getInstance().loadCache(cache.getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES)); + cgCache fullCache = cgeoapplication.getInstance().loadCache(cache.getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES)); + if (fullCache == null) { + fullCache = cache; + } return fullCache.getAttributes().contains(attribute); } - public static IFilter[] getAllFilters() { - final String packageName = cgeoapplication.getInstance().getBaseContext().getPackageName(); - final Resources res = cgeoapplication.getInstance().getResources(); + public static class Factory implements IFilterFactory { + + @Override + public IFilter[] getFilters() { + final String packageName = cgeoapplication.getInstance().getBaseContext().getPackageName(); + final Resources res = cgeoapplication.getInstance().getResources(); - final String[] ids = res.getStringArray(R.array.attribute_ids); - final IFilter[] filters = new IFilter[ids.length]; - for (int i = 0; i < ids.length; i++) { - filters[i] = new AttributeFilter(getName("attribute_" + ids[i], res, packageName), ids[i]); + final String[] ids = res.getStringArray(R.array.attribute_ids); + final IFilter[] filters = new IFilter[ids.length]; + for (int i = 0; i < ids.length; i++) { + filters[i] = new AttributeFilter(getName("attribute_" + ids[i], res, packageName), ids[i]); + } + return filters; } - return filters; - } + } } diff --git a/main/src/cgeo/geocaching/filter/DifficultyFilter.java b/main/src/cgeo/geocaching/filter/DifficultyFilter.java new file mode 100644 index 0000000..368c20f --- /dev/null +++ b/main/src/cgeo/geocaching/filter/DifficultyFilter.java @@ -0,0 +1,31 @@ +package cgeo.geocaching.filter; + +import cgeo.geocaching.R; +import cgeo.geocaching.cgCache; + +import java.util.ArrayList; + +class DifficultyFilter extends AbstractRangeFilter { + + public DifficultyFilter(int difficulty) { + super(R.string.cache_difficulty, difficulty); + } + + @Override + public boolean accepts(cgCache cache) { + return rangeMin <= cache.getDifficulty() && cache.getDifficulty() < rangeMax; + } + + public static class Factory implements IFilterFactory { + + @Override + public IFilter[] getFilters() { + final ArrayList<IFilter> filters = new ArrayList<IFilter>(5); + for (int difficulty = 1; difficulty <= 5; difficulty++) { + filters.add(new DifficultyFilter(difficulty)); + } + return filters.toArray(new IFilter[filters.size()]); + } + + } +} diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java new file mode 100644 index 0000000..1d22e52 --- /dev/null +++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java @@ -0,0 +1,122 @@ +package cgeo.geocaching.filter; + +import cgeo.geocaching.R; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.activity.IAbstractActivity; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RunnableWithArgument; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.res.Resources; +import android.widget.ArrayAdapter; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +public final class FilterUserInterface { + + private static class FactoryEntry { + private final String name; + private final Class<? extends IFilterFactory> filterFactory; + + public FactoryEntry(final String name, final Class<? extends IFilterFactory> filterFactory) { + this.name = name; + this.filterFactory = filterFactory; + } + + @Override + public String toString() { + return name; + } + } + + private final IAbstractActivity activity; + private final ArrayList<FactoryEntry> registry; + private final Resources res; + + public FilterUserInterface(final IAbstractActivity activity) { + this.activity = activity; + this.res = cgeoapplication.getInstance().getResources(); + + registry = new ArrayList<FactoryEntry>(); + if (Settings.getCacheType() == CacheType.ALL) { + register(R.string.caches_filter_type, TypeFilter.Factory.class); + } + register(R.string.caches_filter_size, SizeFilter.Factory.class); + register(R.string.cache_terrain, TerrainFilter.Factory.class); + register(R.string.cache_difficulty, DifficultyFilter.Factory.class); + register(R.string.cache_attributes, AttributeFilter.Factory.class); + register(R.string.cache_status, StateFilter.Factory.class); + register(R.string.caches_filter_track, TrackablesFilter.class); + register(R.string.caches_filter_modified, ModifiedFilter.class); + + // sort by localized names + Collections.sort(registry, new Comparator<FactoryEntry>() { + + @Override + public int compare(FactoryEntry lhs, FactoryEntry rhs) { + return lhs.name.compareToIgnoreCase(rhs.name); + } + }); + + // reset shall be last + register(R.string.caches_filter_clear, null); + } + + private void register(int resourceId, Class<? extends IFilterFactory> factoryClass) { + registry.add(new FactoryEntry(res.getString(resourceId), factoryClass)); + } + + public void selectFilter(final RunnableWithArgument<IFilter> runAfterwards) { + final AlertDialog.Builder builder = new AlertDialog.Builder((Activity) activity); + builder.setTitle(R.string.caches_filter); + + final ArrayAdapter<FactoryEntry> adapter = new ArrayAdapter<FactoryEntry>((Activity) activity, android.R.layout.select_dialog_item, registry); + + builder.setAdapter(adapter, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int itemIndex) { + FactoryEntry entry = adapter.getItem(itemIndex); + // reset? + if (entry.filterFactory == null) { + runAfterwards.run(null); + } + else { + try { + IFilterFactory factoryInstance = entry.filterFactory.newInstance(); + selectFromFactory(factoryInstance, entry.name, runAfterwards); + } catch (Exception e) { + Log.e("selectFilter", e); + } + } + } + }); + + builder.create().show(); + } + + private void selectFromFactory(final IFilterFactory factory, final String menuTitle, final RunnableWithArgument<IFilter> runAfterwards) { + final IFilter[] filters = factory.getFilters(); + if (filters.length == 1) { + runAfterwards.run(filters[0]); + return; + } + + final AlertDialog.Builder builder = new AlertDialog.Builder((Activity) activity); + builder.setTitle(menuTitle); + + final ArrayAdapter<IFilter> adapter = new ArrayAdapter<IFilter>((Activity) activity, android.R.layout.select_dialog_item, filters); + builder.setAdapter(adapter, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + runAfterwards.run(filters[item]); + } + }); + + builder.create().show(); + } + +} diff --git a/main/src/cgeo/geocaching/filter/IFilterFactory.java b/main/src/cgeo/geocaching/filter/IFilterFactory.java new file mode 100644 index 0000000..3491fd7 --- /dev/null +++ b/main/src/cgeo/geocaching/filter/IFilterFactory.java @@ -0,0 +1,5 @@ +package cgeo.geocaching.filter; + +interface IFilterFactory { + public IFilter[] getFilters(); +} diff --git a/main/src/cgeo/geocaching/filter/ModifiedFilter.java b/main/src/cgeo/geocaching/filter/ModifiedFilter.java index 6063f58..f74bb4d 100644 --- a/main/src/cgeo/geocaching/filter/ModifiedFilter.java +++ b/main/src/cgeo/geocaching/filter/ModifiedFilter.java @@ -1,11 +1,13 @@ package cgeo.geocaching.filter; +import cgeo.geocaching.R; import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgeoapplication; -public class ModifiedFilter extends AbstractFilter { +class ModifiedFilter extends AbstractFilter implements IFilterFactory { - public ModifiedFilter(String name) { - super(name); + public ModifiedFilter() { + super(cgeoapplication.getInstance().getString(R.string.caches_filter_modified)); } @Override @@ -13,4 +15,9 @@ public class ModifiedFilter extends AbstractFilter { // modified on GC return cache.hasUserModifiedCoords() || cache.hasFinalDefined(); } + + @Override + public IFilter[] getFilters() { + return new IFilter[] { this }; + } } diff --git a/main/src/cgeo/geocaching/filter/SizeFilter.java b/main/src/cgeo/geocaching/filter/SizeFilter.java index 4f0d830..b08c2ae 100644 --- a/main/src/cgeo/geocaching/filter/SizeFilter.java +++ b/main/src/cgeo/geocaching/filter/SizeFilter.java @@ -5,7 +5,7 @@ import cgeo.geocaching.enumerations.CacheSize; import java.util.ArrayList; -public class SizeFilter extends AbstractFilter { +class SizeFilter extends AbstractFilter { private final CacheSize cacheSize; public SizeFilter(CacheSize cacheSize) { @@ -23,14 +23,19 @@ public class SizeFilter extends AbstractFilter { return cacheSize.getL10n(); } - public static AbstractFilter[] getAllFilters() { - final CacheSize[] cacheSizes = CacheSize.values(); - ArrayList<SizeFilter> filters = new ArrayList<SizeFilter>(); - for (CacheSize cacheSize : cacheSizes) { - if (cacheSize != CacheSize.UNKNOWN) { - filters.add(new SizeFilter(cacheSize)); + public static class Factory implements IFilterFactory { + + @Override + public IFilter[] getFilters() { + final CacheSize[] cacheSizes = CacheSize.values(); + final ArrayList<SizeFilter> filters = new ArrayList<SizeFilter>(); + for (CacheSize cacheSize : cacheSizes) { + if (cacheSize != CacheSize.UNKNOWN) { + filters.add(new SizeFilter(cacheSize)); + } } + return filters.toArray(new SizeFilter[filters.size()]); } - return filters.toArray(new SizeFilter[filters.size()]); + } } diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java index 454cc92..b086477 100644 --- a/main/src/cgeo/geocaching/filter/StateFilter.java +++ b/main/src/cgeo/geocaching/filter/StateFilter.java @@ -10,16 +10,18 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -public abstract class StateFilter extends AbstractFilter { +abstract class StateFilter extends AbstractFilter { - public StateFilter(String name) { + final static Resources res = cgeoapplication.getInstance().getResources(); + + protected StateFilter(String name) { super(name); } - private static class StateFoundFilter extends StateFilter { + static class StateFoundFilter extends StateFilter { - public StateFoundFilter(String name) { - super(name); + public StateFoundFilter() { + super(res.getString(R.string.cache_status_found)); } @Override @@ -29,9 +31,9 @@ public abstract class StateFilter extends AbstractFilter { } - private static class StateArchivedFilter extends StateFilter { - public StateArchivedFilter(String name) { - super(name); + static class StateArchivedFilter extends StateFilter { + public StateArchivedFilter() { + super(res.getString(R.string.cache_status_archived)); } @Override @@ -40,9 +42,9 @@ public abstract class StateFilter extends AbstractFilter { } } - private static class StateDisabledFilter extends StateFilter { - public StateDisabledFilter(String name) { - super(name); + static class StateDisabledFilter extends StateFilter { + public StateDisabledFilter() { + super(res.getString(R.string.cache_status_disabled)); } @Override @@ -51,9 +53,9 @@ public abstract class StateFilter extends AbstractFilter { } } - private static class StatePremiumFilter extends StateFilter { - public StatePremiumFilter(String name) { - super(name); + static class StatePremiumFilter extends StateFilter { + public StatePremiumFilter() { + super(res.getString(R.string.cache_status_premium)); } @Override @@ -63,8 +65,8 @@ public abstract class StateFilter extends AbstractFilter { } private static class StateOfflineLogFilter extends StateFilter { - public StateOfflineLogFilter(String name) { - super(name); + public StateOfflineLogFilter() { + super(res.getString(R.string.cache_status_offline_log)); } @Override @@ -73,24 +75,28 @@ public abstract class StateFilter extends AbstractFilter { } } - public static AbstractFilter[] getAllFilters() { - final Resources res = cgeoapplication.getInstance().getResources(); - final ArrayList<StateFilter> filters = new ArrayList<StateFilter>(); - filters.add(new StateFoundFilter(res.getString(R.string.cache_status_found))); - filters.add(new StateArchivedFilter(res.getString(R.string.cache_status_archived))); - filters.add(new StateDisabledFilter(res.getString(R.string.cache_status_disabled))); - filters.add(new StatePremiumFilter(res.getString(R.string.cache_status_premium))); - filters.add(new StateOfflineLogFilter(res.getString(R.string.cache_status_offline_log))); - - Collections.sort(filters, new Comparator<StateFilter>() { + public static class Factory implements IFilterFactory { - @Override - public int compare(StateFilter filter1, StateFilter filter2) { - return filter1.getName().compareToIgnoreCase(filter2.getName()); - } - }); + @Override + public IFilter[] getFilters() { + final ArrayList<StateFilter> filters = new ArrayList<StateFilter>(); + filters.add(new StateFoundFilter()); + filters.add(new StateArchivedFilter()); + filters.add(new StateDisabledFilter()); + filters.add(new StatePremiumFilter()); + filters.add(new StateOfflineLogFilter()); + + Collections.sort(filters, new Comparator<StateFilter>() { + + @Override + public int compare(StateFilter filter1, StateFilter filter2) { + return filter1.getName().compareToIgnoreCase(filter2.getName()); + } + }); + + return filters.toArray(new StateFilter[filters.size()]); + } - return filters.toArray(new StateFilter[filters.size()]); } } diff --git a/main/src/cgeo/geocaching/filter/TerrainFilter.java b/main/src/cgeo/geocaching/filter/TerrainFilter.java new file mode 100644 index 0000000..5cee87e --- /dev/null +++ b/main/src/cgeo/geocaching/filter/TerrainFilter.java @@ -0,0 +1,31 @@ +package cgeo.geocaching.filter; + + +import cgeo.geocaching.R; +import cgeo.geocaching.cgCache; + +import java.util.ArrayList; + +class TerrainFilter extends AbstractRangeFilter { + + public TerrainFilter(int terrain) { + super(R.string.cache_terrain, terrain); + } + + @Override + public boolean accepts(cgCache cache) { + return rangeMin <= cache.getTerrain() && cache.getTerrain() < rangeMax; + } + + public static class Factory implements IFilterFactory { + @Override + public IFilter[] getFilters() { + final ArrayList<IFilter> filters = new ArrayList<IFilter>(5); + for (int terrain = 1; terrain <= 5; terrain++) { + filters.add(new TerrainFilter(terrain)); + } + return filters.toArray(new IFilter[filters.size()]); + } + } + +} diff --git a/main/src/cgeo/geocaching/filter/TrackablesFilter.java b/main/src/cgeo/geocaching/filter/TrackablesFilter.java index 99d888b..90def5b 100644 --- a/main/src/cgeo/geocaching/filter/TrackablesFilter.java +++ b/main/src/cgeo/geocaching/filter/TrackablesFilter.java @@ -1,14 +1,22 @@ package cgeo.geocaching.filter; +import cgeo.geocaching.R; import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgeoapplication; -public class TrackablesFilter extends AbstractFilter { - public TrackablesFilter(String name) { - super(name); +class TrackablesFilter extends AbstractFilter implements IFilterFactory { + public TrackablesFilter() { + super(cgeoapplication.getInstance().getString(R.string.caches_filter_track)); } @Override public boolean accepts(cgCache cache) { return cache.hasTrackables(); } + + @Override + public IFilter[] getFilters() { + return new IFilter[] { this }; + } + } diff --git a/main/src/cgeo/geocaching/filter/TypeFilter.java b/main/src/cgeo/geocaching/filter/TypeFilter.java index bb32fdd..11321c7 100644 --- a/main/src/cgeo/geocaching/filter/TypeFilter.java +++ b/main/src/cgeo/geocaching/filter/TypeFilter.java @@ -5,7 +5,7 @@ import cgeo.geocaching.enumerations.CacheType; import java.util.ArrayList; -public class TypeFilter extends AbstractFilter { +class TypeFilter extends AbstractFilter { private final CacheType cacheType; public TypeFilter(final CacheType cacheType) { @@ -23,14 +23,19 @@ public class TypeFilter extends AbstractFilter { return cacheType.getL10n(); } - public static IFilter[] getAllFilters() { - final CacheType[] types = CacheType.values(); - ArrayList<IFilter> filters = new ArrayList<IFilter>(types.length); - for (CacheType cacheType : types) { - if (cacheType != CacheType.ALL) { - filters.add(new TypeFilter(cacheType)); + public static class Factory implements IFilterFactory { + + @Override + public IFilter[] getFilters() { + final CacheType[] types = CacheType.values(); + final ArrayList<IFilter> filters = new ArrayList<IFilter>(types.length); + for (CacheType cacheType : types) { + if (cacheType != CacheType.ALL) { + filters.add(new TypeFilter(cacheType)); + } } + return filters.toArray(new TypeFilter[filters.size()]); } - return filters.toArray(new TypeFilter[filters.size()]); + } } diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java index 2f2f370..070be09 100644 --- a/main/src/cgeo/geocaching/gcvote/GCVote.java +++ b/main/src/cgeo/geocaching/gcvote/GCVote.java @@ -4,14 +4,13 @@ import cgeo.geocaching.Settings; import cgeo.geocaching.cgCache; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; -import cgeo.geocaching.utils.LeastRecentlyUsedCache; +import cgeo.geocaching.utils.LeastRecentlyUsedMap; import cgeo.geocaching.utils.Log; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -29,7 +28,7 @@ public final class GCVote { private static final Pattern patternVoteElement = Pattern.compile("<vote ([^>]+)>", Pattern.CASE_INSENSITIVE); private static final int MAX_CACHED_RATINGS = 1000; - private static LeastRecentlyUsedCache<String, GCVoteRating> ratingsCache = new LeastRecentlyUsedCache<String, GCVoteRating>(MAX_CACHED_RATINGS); + private static LeastRecentlyUsedMap<String, GCVoteRating> ratingsCache = new LeastRecentlyUsedMap.LruCache<String, GCVoteRating>(MAX_CACHED_RATINGS); /** * Get user rating for a given guid or geocode. For a guid first the ratings cache is checked @@ -96,7 +95,7 @@ public final class GCVote { params.put("waypoints", StringUtils.join(geocodes.toArray(), ',')); } params.put("version", "cgeo"); - final String page = Network.getResponseData(Network.request("http://gcvote.com/getVotes.php", params, false, false, false)); + final String page = Network.getResponseData(Network.getRequest("http://gcvote.com/getVotes.php", params)); if (page == null) { return null; } @@ -118,7 +117,7 @@ public final class GCVote { } } } catch (Exception e) { - Log.w(Settings.tag, "GCVote.getRating: Failed to parse guid"); + Log.w("GCVote.getRating: Failed to parse guid"); } if (guid == null) { continue; @@ -135,7 +134,7 @@ public final class GCVote { } } } catch (Exception e) { - Log.w(Settings.tag, "GCVote.getRating: Failed to parse loggedIn"); + Log.w("GCVote.getRating: Failed to parse loggedIn"); } float rating = 0; @@ -145,7 +144,7 @@ public final class GCVote { rating = Float.parseFloat(matcherRating.group(1)); } } catch (Exception e) { - Log.w(Settings.tag, "GCVote.getRating: Failed to parse rating"); + Log.w("GCVote.getRating: Failed to parse rating"); } if (rating <= 0) { continue; @@ -158,7 +157,7 @@ public final class GCVote { votes = Integer.parseInt(matcherVotes.group(1)); } } catch (Exception e) { - Log.w(Settings.tag, "GCVote.getRating: Failed to parse vote count"); + Log.w("GCVote.getRating: Failed to parse vote count"); } if (votes < 0) { continue; @@ -172,7 +171,7 @@ public final class GCVote { myVote = Float.parseFloat(matcherVote.group(1)); } } catch (Exception e) { - Log.w(Settings.tag, "GCVote.getRating: Failed to parse user's vote"); + Log.w("GCVote.getRating: Failed to parse user's vote"); } } @@ -183,7 +182,7 @@ public final class GCVote { } } } catch (Exception e) { - Log.e(Settings.tag, "GCVote.getRating: " + e.toString()); + Log.e("GCVote.getRating: " + e.toString()); } return ratings; @@ -220,7 +219,7 @@ public final class GCVote { "voteUser", String.format("%.1f", vote).replace(',', '.'), "version", "cgeo"); - final String result = Network.getResponseData(Network.request("http://gcvote.com/setVote.php", params, false, false, false)); + final String result = Network.getResponseData(Network.getRequest("http://gcvote.com/setVote.php", params)); return result.trim().equalsIgnoreCase("ok"); } @@ -258,7 +257,7 @@ public final class GCVote { } } } catch (Exception e) { - Log.e(Settings.tag, "GCvote.loadRatings: " + e.toString()); + Log.e("GCvote.loadRatings: " + e.toString()); } } } diff --git a/main/src/cgeo/geocaching/geopoint/Geopoint.java b/main/src/cgeo/geocaching/geopoint/Geopoint.java index ef08401..ff97a4c 100644 --- a/main/src/cgeo/geocaching/geopoint/Geopoint.java +++ b/main/src/cgeo/geocaching/geopoint/Geopoint.java @@ -1,6 +1,6 @@ package cgeo.geocaching.geopoint; -import cgeo.geocaching.Settings; +import cgeo.geocaching.ICoordinates; import cgeo.geocaching.geopoint.GeopointFormatter.Format; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; @@ -11,6 +11,8 @@ import org.json.JSONArray; import org.json.JSONObject; import android.location.Location; +import android.os.Parcel; +import android.os.Parcelable; import java.math.BigDecimal; import java.math.RoundingMode; @@ -18,8 +20,7 @@ import java.math.RoundingMode; /** * Abstraction of geographic point. */ -public final class Geopoint -{ +public final class Geopoint implements ICoordinates, Parcelable { public static final double deg2rad = Math.PI / 180; public static final double rad2deg = 180 / Math.PI; public static final float erad = 6371.0f; @@ -47,19 +48,6 @@ public final class Geopoint } /** - * Creates new Geopoint with given latitude and longitude (both microdegree). - * - * @param lat - * latitude - * @param lon - * longitude - */ - public Geopoint(final int lat, final int lon) - { - this(lat / 1e6, lon / 1e6); - } - - /** * Creates new Geopoint with latitude and longitude parsed from string. * * @param text @@ -98,6 +86,17 @@ public final class Geopoint } /** + * Create new Geopoint from Parcel. + * + * @param in + * a Parcel to read the saved data from + */ + public Geopoint(final Parcel in) { + latitude = in.readDouble(); + longitude = in.readDouble(); + } + + /** * Get latitude in degree. * * @return latitude @@ -114,7 +113,7 @@ public final class Geopoint */ public int getLatitudeE6() { - return (int) (latitude * 1E6); + return (int) Math.round(latitude * 1E6); } /** @@ -134,7 +133,7 @@ public final class Geopoint */ public int getLongitudeE6() { - return (int) (longitude * 1E6); + return (int) Math.round(longitude * 1E6); } /** @@ -200,16 +199,21 @@ public final class Geopoint return new Geopoint(rlat * rad2deg, rlon * rad2deg); } - /** - * Checks if given Geopoint is identical with this Geopoint. - * - * @param gp - * Geopoint to check - * @return true if identical, false otherwise - */ - public boolean isEqualTo(Geopoint gp) - { - return null != gp && gp.latitude == latitude && gp.longitude == longitude; + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null || !(obj instanceof Geopoint)) { + return false; + } + final Geopoint gp = (Geopoint) obj; + return getLatitudeE6() == gp.getLatitudeE6() && getLongitudeE6() == gp.getLongitudeE6(); + } + + @Override + public int hashCode() { + return getLatitudeE6() ^ getLongitudeE6(); } /** @@ -242,7 +246,7 @@ public final class Geopoint /** * Returns formatted coordinates with default format. * Default format is decimalminutes, e.g. N 52ยฐ 36.123 E 010ยฐ 03.456 - * + * * @return formatted coordinates */ @Override @@ -506,10 +510,38 @@ public final class Geopoint return result.getDouble("elevation"); } } catch (Exception e) { - Log.w(Settings.tag, "cgBase.getElevation: " + e.toString()); + Log.w("cgBase.getElevation: " + e.toString()); } return null; } + //FIXME: this interface implementation is totally confusing as it returns the class itself. + // it can therefore be removed completely (and any invocation of it) without any disadvantages + @Override + public Geopoint getCoords() { + return this; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(final Parcel dest, final int flags) { + dest.writeDouble(latitude); + dest.writeDouble(longitude); + } + + public static final Parcelable.Creator<Geopoint> CREATOR = new Parcelable.Creator<Geopoint>() { + public Geopoint createFromParcel(final Parcel in) { + return new Geopoint(in); + } + + public Geopoint[] newArray(final int size) { + return new Geopoint[size]; + } + }; + } diff --git a/main/src/cgeo/geocaching/geopoint/Viewport.java b/main/src/cgeo/geocaching/geopoint/Viewport.java index 390bdb4..67aed2c 100644 --- a/main/src/cgeo/geocaching/geopoint/Viewport.java +++ b/main/src/cgeo/geocaching/geopoint/Viewport.java @@ -1,7 +1,10 @@ package cgeo.geocaching.geopoint; -import cgeo.geocaching.Settings; -import cgeo.geocaching.utils.Log; +import cgeo.geocaching.ICoordinates; + +import java.util.Locale; +import java.util.Set; + public class Viewport { @@ -10,19 +13,29 @@ public class Viewport { public final Geopoint bottomLeft; public final Geopoint topRight; - public Viewport(final Geopoint bottomLeft, final Geopoint topRight) { - this.bottomLeft = bottomLeft; - this.topRight = topRight; - this.center = new Geopoint((bottomLeft.getLatitude() + topRight.getLatitude()) / 2, - (bottomLeft.getLongitude() + topRight.getLongitude()) / 2); + public Viewport(final ICoordinates point1, final ICoordinates point2) { + final Geopoint gp1 = point1.getCoords(); + final Geopoint gp2 = point2.getCoords(); + this.bottomLeft = new Geopoint(Math.min(gp1.getLatitude(), gp2.getLatitude()), + Math.min(gp1.getLongitude(), gp2.getLongitude())); + this.topRight = new Geopoint(Math.max(gp1.getLatitude(), gp2.getLatitude()), + Math.max(gp1.getLongitude(), gp2.getLongitude())); + this.center = new Geopoint((gp1.getLatitude() + gp2.getLatitude()) / 2, + (gp1.getLongitude() + gp2.getLongitude()) / 2); } - public Viewport(final Geopoint center, final double latSpan, final double lonSpan) { - this.center = center; - final double centerLat = center.getLatitude(); - final double centerLon = center.getLongitude(); - bottomLeft = new Geopoint(centerLat - latSpan / 2, centerLon - lonSpan / 2); - topRight = new Geopoint(centerLat + latSpan / 2, centerLon + lonSpan / 2); + public Viewport(final ICoordinates center, final double latSpan, final double lonSpan) { + this.center = center.getCoords(); + final double centerLat = this.center.getLatitude(); + final double centerLon = this.center.getLongitude(); + final double latHalfSpan = Math.abs(latSpan) / 2; + final double lonHalfSpan = Math.abs(lonSpan) / 2; + bottomLeft = new Geopoint(centerLat - latHalfSpan, centerLon - lonHalfSpan); + topRight = new Geopoint(centerLat + latHalfSpan, centerLon + lonHalfSpan); + } + + public Viewport(final double lat1, final double lat2, final double lon1, final double lon2) { + this(new Geopoint(lat1, lon1), new Geopoint(lat2, lon2)); } public double getLatitudeMin() { @@ -45,78 +58,125 @@ public class Viewport { return center; } + public double getLatitudeSpan() { + return getLatitudeMax() - getLatitudeMin(); + } + + public double getLongitudeSpan() { + return getLongitudeMax() - getLongitudeMin(); + } + + /** + * Check whether a point is contained in this viewport. + * + * @param point + * the coordinates to check + * @return true if the point is contained in this viewport, false otherwise + */ + public boolean contains(final ICoordinates point) { + final Geopoint coords = point.getCoords(); + return coords.getLongitudeE6() >= bottomLeft.getLongitudeE6() + && coords.getLongitudeE6() <= topRight.getLongitudeE6() + && coords.getLatitudeE6() >= bottomLeft.getLatitudeE6() + && coords.getLatitudeE6() <= topRight.getLatitudeE6(); + } + @Override public String toString() { return "(" + bottomLeft.toString() + "," + topRight.toString() + ")"; } /** - * Check if coordinates are located in a viewport (defined by its center and span - * in each direction). + * Check whether another viewport is fully included into the current one. * - * @param centerLat - * the viewport center latitude - * @param centerLon - * the viewport center longitude - * @param spanLat - * the latitude span - * @param spanLon - * the longitude span - * @param coords - * the coordinates to check - * @return true if the coordinates are in the viewport + * @param vp + * the other viewport + * @return true if the vp is fully included into this one, false otherwise */ - public static boolean isCacheInViewPort(int centerLat, int centerLon, int spanLat, int spanLon, final Geopoint coords) { - return 2 * Math.abs(coords.getLatitudeE6() - centerLat) <= Math.abs(spanLat) && - 2 * Math.abs(coords.getLongitudeE6() - centerLon) <= Math.abs(spanLon); + public boolean includes(final Viewport vp) { + return contains(vp.bottomLeft) && contains(vp.topRight); } /** - * Check if an area is located in a viewport (defined by its center and span - * in each direction). - * - * expects coordinates in E6 format + * Return the "where" part of the string appropriate for a SQL query. * - * @param centerLat1 - * @param centerLon1 - * @param centerLat2 - * @param centerLon2 - * @param spanLat1 - * @param spanLon1 - * @param spanLat2 - * @param spanLon2 - * @return + * @param dbTable + * the database table to use as prefix, or null if no prefix is required + * @return the string without the "where" keyword */ - public static boolean isInViewPort(int centerLat1, int centerLon1, int centerLat2, int centerLon2, int spanLat1, int spanLon1, int spanLat2, int spanLon2) { - try { - final int left1 = centerLat1 - (spanLat1 / 2); - final int left2 = centerLat2 - (spanLat2 / 2); - if (left2 <= left1) { - return false; - } + public String sqlWhere(final String dbTable) { + final String prefix = dbTable == null ? "" : (dbTable + "."); + return String.format((Locale) null, + "%slatitude >= %s and %slatitude <= %s and %slongitude >= %s and %slongitude <= %s", + prefix, getLatitudeMin(), prefix, getLatitudeMax(), prefix, getLongitudeMin(), prefix, getLongitudeMax()); + } - final int right1 = centerLat1 + (spanLat1 / 2); - final int right2 = centerLat2 + (spanLat2 / 2); - if (right2 >= right1) { - return false; - } + /** + * Return a widened or shrunk viewport. + * + * @param factor + * multiplicative factor for the latitude and longitude span (> 1 to widen, < 1 to shrink) + * @return a widened or shrunk viewport + */ + public Viewport resize(final double factor) { + return new Viewport(getCenter(), getLatitudeSpan() * factor, getLongitudeSpan() * factor); + } - final int top1 = centerLon1 + (spanLon1 / 2); - final int top2 = centerLon2 + (spanLon2 / 2); - if (top2 >= top1) { - return false; - } + /** + * Return a viewport that contains the current viewport as well as another point. + * + * @param coords + * the point we want in the viewport + * @return either the same or an expanded viewport + */ + public Viewport expand(final ICoordinates point) { + if (contains(point)) { + return this; + } else { + final Geopoint coords = point.getCoords(); + final double latitude = coords.getLatitude(); + final double longitude = coords.getLongitude(); + final double latMin = Math.min(getLatitudeMin(), latitude); + final double latMax = Math.max(getLatitudeMax(), latitude); + final double lonMin = Math.min(getLongitudeMin(), longitude); + final double lonMax = Math.max(getLongitudeMax(), longitude); + return new Viewport(new Geopoint(latMin, lonMin), new Geopoint(latMax, lonMax)); + } + } - final int bottom1 = centerLon1 - (spanLon1 / 2); - final int bottom2 = centerLon2 - (spanLon2 / 2); - if (bottom2 <= bottom1) { - return false; + /** + * Return the smallest viewport containing all the given points. + * + * @param points + * a set of points. Point with null coordinates (or null themselves) will be ignored + * @return the smallest viewport containing the non-null coordinates, or null if no coordinates are non-null + */ + static public Viewport containing(final Set<? extends ICoordinates> points) { + Viewport viewport = null; + for (final ICoordinates point : points) { + final Geopoint coords = point == null ? null : point.getCoords(); + if (coords != null) { + if (viewport == null) { + viewport = new Viewport(coords, coords); + } else { + viewport = viewport.expand(coords); + } } + } + return viewport; + } - return true; - } catch (Exception e) { - Log.e(Settings.tag, "Viewport.isInViewPort: " + e.toString()); + @Override + public boolean equals(final Object other) { + if (other == null || !(other instanceof Viewport)) { return false; } + final Viewport vp = (Viewport) other; + return bottomLeft.equals(vp.bottomLeft) && topRight.equals(vp.topRight); + } + + @Override + public int hashCode() { + return bottomLeft.hashCode() ^ topRight.hashCode(); } } diff --git a/main/src/cgeo/geocaching/go4cache/Go4Cache.java b/main/src/cgeo/geocaching/go4cache/Go4Cache.java index 6271245..b0a7b35 100644 --- a/main/src/cgeo/geocaching/go4cache/Go4Cache.java +++ b/main/src/cgeo/geocaching/go4cache/Go4Cache.java @@ -1,7 +1,6 @@ package cgeo.geocaching.go4cache; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter.Format; @@ -16,6 +15,8 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -41,6 +42,7 @@ public final class Go4Cache extends Thread { private final static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 2010-07-25 14:44:01 final private ArrayBlockingQueue<Geopoint> queue = new ArrayBlockingQueue<Geopoint>(1); + private String packageVersion; public static Go4Cache getInstance() { // no need to be synchronized return InstanceHolder.INSTANCE; @@ -48,10 +50,22 @@ public final class Go4Cache extends Thread { private Go4Cache() { // private singleton constructor super("Go4Cache"); + initializeVersion(); setPriority(Thread.MIN_PRIORITY); start(); } + private void initializeVersion() { + try { + final PackageManager manager = cgeoapplication.getInstance().getPackageManager(); + final PackageInfo info = manager.getPackageInfo(cgeoapplication.getInstance().getPackageName(), 0); + packageVersion = info.versionName; + } catch (PackageManager.NameNotFoundException e) { + Log.e("unable to get version information", e); + packageVersion = null; + } + } + /** * Send the coordinates to go4cache.com if the user opted in to do so. * @@ -68,7 +82,7 @@ public final class Go4Cache extends Thread { @Override public void run() { - Log.d(Settings.tag, "Go4Cache task started"); + Log.d("Go4Cache task started"); Geopoint latestCoords = null; String latestAction = null; @@ -96,8 +110,8 @@ public final class Go4Cache extends Thread { "ln", lonStr, "a", currentAction, "s", (CryptUtils.sha1(username + "|" + latStr + "|" + lonStr + "|" + currentAction + "|" + CryptUtils.md5("carnero: developing your dreams"))).toLowerCase()); - if (null != cgBase.version) { - params.put("v", cgBase.version); + if (null != packageVersion) { + params.put("v", packageVersion); } Network.postRequest("http://api.go4cache.com/", params); @@ -108,7 +122,7 @@ public final class Go4Cache extends Thread { latestAction = currentAction; } } catch (InterruptedException e) { - Log.e(Settings.tag, "Go4Cache.run: interrupted", e); + Log.e("Go4Cache.run: interrupted", e); } } @@ -138,7 +152,7 @@ public final class Go4Cache extends Thread { final String data = Network.getResponseData(Network.postRequest("http://api.go4cache.com/get.php", params)); if (StringUtils.isBlank(data)) { - Log.e(Settings.tag, "cgeoBase.getGeocachersInViewport: No data from server"); + Log.e("cgeoBase.getGeocachersInViewport: No data from server"); return null; } @@ -150,7 +164,7 @@ public final class Go4Cache extends Thread { users.add(parseUser(oneUser)); } } catch (Exception e) { - Log.e(Settings.tag, "cgBase.getGeocachersInViewport: " + e.toString()); + Log.e("cgBase.getGeocachersInViewport: " + e.toString()); } return Collections.unmodifiableList(users); diff --git a/main/src/cgeo/geocaching/maps/AbstractMap.java b/main/src/cgeo/geocaching/maps/AbstractMap.java index 4fc99a5..ae5b57b 100644 --- a/main/src/cgeo/geocaching/maps/AbstractMap.java +++ b/main/src/cgeo/geocaching/maps/AbstractMap.java @@ -68,4 +68,6 @@ public abstract class AbstractMap { public abstract void goManual(View view); + public abstract void onSaveInstanceState(final Bundle outState); + } diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index e424bcc..7c70266 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -8,7 +8,6 @@ import cgeo.geocaching.Settings; import cgeo.geocaching.StoredList; import cgeo.geocaching.UpdateDirectionCallback; import cgeo.geocaching.UpdateLocationCallback; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgDirection; import cgeo.geocaching.cgGeo; @@ -18,6 +17,7 @@ import cgeo.geocaching.cgeocaches; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.gc.GCBase; +import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; import cgeo.geocaching.enumerations.LoadFlags; @@ -35,9 +35,8 @@ import cgeo.geocaching.maps.interfaces.MapProvider; import cgeo.geocaching.maps.interfaces.MapViewImpl; import cgeo.geocaching.maps.interfaces.OnMapDragListener; import cgeo.geocaching.maps.interfaces.OtherCachersOverlayItemImpl; -import cgeo.geocaching.network.Login; -import cgeo.geocaching.utils.BoundedList; import cgeo.geocaching.utils.CancellableHandler; +import cgeo.geocaching.utils.LeastRecentlyUsedSet; import cgeo.geocaching.utils.Log; import org.apache.commons.collections.CollectionUtils; @@ -95,8 +94,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto //Menu private static final String EXTRAS_GEOCODE = "geocode"; - private static final String EXTRAS_LONGITUDE = "longitude"; - private static final String EXTRAS_LATITUDE = "latitude"; + private static final String EXTRAS_COORDS = "coords"; private static final String EXTRAS_WPTTYPE = "wpttype"; private static final String EXTRAS_MAPSTATE = "mapstate"; private static final String EXTRAS_SEARCH = "search"; @@ -115,6 +113,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private static final String EXTRAS_MAP_TITLE = "mapTitle"; + private static final String BUNDLE_MAP_SOURCE = "mapSource"; + private static final String BUNDLE_MAP_STATE = "mapState"; + private Resources res = null; private MapProvider mapProvider = null; private Activity activity = null; @@ -136,14 +137,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private boolean noMapTokenShowed = false; // map status data private boolean followMyLocation = false; - private Integer centerLatitude = null; - private Integer centerLongitude = null; - private Integer spanLatitude = null; - private Integer spanLongitude = null; - private Integer centerLatitudeUsers = null; - private Integer centerLongitudeUsers = null; - private Integer spanLatitudeUsers = null; - private Integer spanLongitudeUsers = null; + private Viewport viewport = null; + private Viewport viewportUsers = null; private int zoom = -100; // threads private LoadTimer loadTimer = null; @@ -171,7 +166,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private static Map<Integer, LayerDrawable> overlaysCache = new HashMap<Integer, LayerDrawable>(); private int cachesCnt = 0; /** List of caches in the viewport */ - private final BoundedList<cgCache> caches = new BoundedList<cgCache>(MAX_CACHES); + private final LeastRecentlyUsedSet<cgCache> caches = new LeastRecentlyUsedSet<cgCache>(MAX_CACHES); + /** List of waypoints in the viewport */ + private final LeastRecentlyUsedSet<cgWaypoint> waypoints = new LeastRecentlyUsedSet<cgWaypoint>(MAX_CACHES); // storing for offline private ProgressDialog waitDialog = null; private int detailTotal = 0; @@ -327,24 +324,23 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto */ private String mapTitle; + /* Current source id */ + private int currentSourceId; + public CGeoMap(MapActivityImpl activity) { super(activity); } protected void countVisibleCaches() { - final ArrayList<cgCache> protectedCaches = new ArrayList<cgCache>(caches); + final List<cgCache> protectedCaches = caches.getAsList(); int count = 0; if (protectedCaches.size() > 0) { - final GeoPointImpl mapCenter = mapView.getMapViewCenter(); - final int mapCenterLat = mapCenter.getLatitudeE6(); - final int mapCenterLon = mapCenter.getLongitudeE6(); - final int mapSpanLat = mapView.getLatitudeSpan(); - final int mapSpanLon = mapView.getLongitudeSpan(); + final Viewport viewport = mapView.getViewport(); - for (cgCache cache : protectedCaches) { + for (final cgCache cache : protectedCaches) { if (cache != null && cache.getCoords() != null) { - if (Viewport.isCacheInViewPort(mapCenterLat, mapCenterLon, mapSpanLat, mapSpanLon, cache.getCoords())) { + if (viewport.contains(cache)) { count++; } } @@ -354,6 +350,12 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } @Override + public void onSaveInstanceState(final Bundle outState) { + outState.putInt(BUNDLE_MAP_SOURCE, currentSourceId); + outState.putIntArray(BUNDLE_MAP_STATE, currentMapState()); + } + + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -363,6 +365,34 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto app = (cgeoapplication) activity.getApplication(); mapProvider = Settings.getMapProvider(); + + // Get parameters from the intent + final Bundle extras = activity.getIntent().getExtras(); + if (extras != null) { + searchIntent = (SearchResult) extras.getParcelable(EXTRAS_SEARCH); + geocodeIntent = extras.getString(EXTRAS_GEOCODE); + coordsIntent = (Geopoint) extras.getParcelable(EXTRAS_COORDS); + waypointTypeIntent = WaypointType.findById(extras.getString(EXTRAS_WPTTYPE)); + mapStateIntent = extras.getIntArray(EXTRAS_MAPSTATE); + mapTitle = extras.getString(EXTRAS_MAP_TITLE); + } + if (StringUtils.isBlank(mapTitle)) { + mapTitle = res.getString(R.string.map_map); + } + + // Get fresh map information from the bundle if any + if (savedInstanceState != null) { + currentSourceId = savedInstanceState.getInt(BUNDLE_MAP_SOURCE, Settings.getMapSource()); + mapStateIntent = savedInstanceState.getIntArray(BUNDLE_MAP_STATE); + } else { + currentSourceId = Settings.getMapSource(); + } + + // If recreating from an obsolete map source, we may need a restart + if (changeMapSource(Settings.getMapSource())) { + return; + } + // reset status noMapTokenShowed = false; @@ -420,26 +450,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto dirUpdate.updateDirection(dir); } - // get parameters - Bundle extras = activity.getIntent().getExtras(); - if (extras != null) { - searchIntent = (SearchResult) extras.getParcelable(EXTRAS_SEARCH); - geocodeIntent = extras.getString(EXTRAS_GEOCODE); - final double latitudeIntent = extras.getDouble(EXTRAS_LATITUDE); - final double longitudeIntent = extras.getDouble(EXTRAS_LONGITUDE); - coordsIntent = new Geopoint(latitudeIntent, longitudeIntent); - waypointTypeIntent = WaypointType.findById(extras.getString(EXTRAS_WPTTYPE)); - mapStateIntent = extras.getIntArray(EXTRAS_MAPSTATE); - mapTitle = extras.getString(EXTRAS_MAP_TITLE); - - if (coordsIntent.getLatitude() == 0.0 || coordsIntent.getLongitude() == 0.0) { - coordsIntent = null; - } - } - - if (StringUtils.isBlank(mapTitle)) { - mapTitle = res.getString(R.string.map_map); - } // live map, if no arguments are given live = (searchIntent == null && geocodeIntent == null && coordsIntent == null); @@ -447,7 +457,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (null == mapStateIntent) { followMyLocation = live; } else { - followMyLocation = 1 == mapStateIntent[3] ? true : false; + followMyLocation = 1 == mapStateIntent[3]; } if (geocodeIntent != null || searchIntent != null || coordsIntent != null || mapStateIntent != null) { centerMap(geocodeIntent, searchIntent, coordsIntent, mapStateIntent); @@ -484,6 +494,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto public void onResume() { super.onResume(); + if (changeMapSource(Settings.getMapSource())) { + return; + } + app.setAction(StringUtils.defaultIfBlank(geocodeIntent, null)); if (geo == null) { geo = app.startGeo(geoUpdate); @@ -507,12 +521,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } dirtyCaches.clear(); // Update display - GeoPointImpl mapCenterNow = mapView.getMapViewCenter(); - int centerLatitudeNow = mapCenterNow.getLatitudeE6(); - int centerLongitudeNow = mapCenterNow.getLongitudeE6(); - int spanLatitudeNow = mapView.getLatitudeSpan(); - int spanLongitudeNow = mapView.getLongitudeSpan(); - displayExecutor.execute(new DisplayRunnable(centerLatitudeNow, centerLongitudeNow, spanLatitudeNow, spanLongitudeNow)); + displayExecutor.execute(new DisplayRunnable(mapView.getViewport())); } startTimer(); @@ -671,7 +680,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto menu.findItem(SUBMENU_STRATEGY).setEnabled(live); } catch (Exception e) { - Log.e(Settings.tag, "cgeomap.onPrepareOptionsMenu: " + e.toString()); + Log.e("cgeomap.onPrepareOptionsMenu: " + e.toString()); } return true; @@ -696,25 +705,22 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (live && !isLoading() && CollectionUtils.isNotEmpty(caches)) { final List<String> geocodes = new ArrayList<String>(); - List<cgCache> cachesProtected = new ArrayList<cgCache>(caches); + final List<cgCache> cachesProtected = caches.getAsList(); + try { if (cachesProtected.size() > 0) { - final GeoPointImpl mapCenter = mapView.getMapViewCenter(); - final int mapCenterLat = mapCenter.getLatitudeE6(); - final int mapCenterLon = mapCenter.getLongitudeE6(); - final int mapSpanLat = mapView.getLatitudeSpan(); - final int mapSpanLon = mapView.getLongitudeSpan(); + final Viewport viewport = mapView.getViewport(); - for (cgCache cache : cachesProtected) { + for (final cgCache cache : cachesProtected) { if (cache != null && cache.getCoords() != null) { - if (Viewport.isCacheInViewPort(mapCenterLat, mapCenterLon, mapSpanLat, mapSpanLon, cache.getCoords()) && !app.isOffline(cache.getGeocode(), null)) { + if (viewport.contains(cache) && !app.isOffline(cache.getGeocode(), null)) { geocodes.add(cache.getGeocode()); } } } } } catch (Exception e) { - Log.e(Settings.tag, "cgeomap.onOptionsItemSelected.#4: " + e.toString()); + Log.e("cgeomap.onOptionsItemSelected.#4: " + e.toString()); } detailTotal = geocodes.size(); @@ -748,7 +754,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto dir = app.startDir(activity, dirUpdate); } } catch (Exception e) { - Log.e(Settings.tag, "cgeocaches.onPrepareOptionsMenu.onCancel: " + e.toString()); + Log.e("cgeocaches.onPrepareOptionsMenu.onCancel: " + e.toString()); } } }); @@ -807,35 +813,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto item.setChecked(true); int mapSource = MapProviderFactory.getMapSourceFromMenuId(id); - boolean mapRestartRequired = switchMapSource(mapSource); - - if (mapRestartRequired) { - // close old mapview - activity.finish(); - - // prepare information to restart a similar view - Intent mapIntent = new Intent(activity, Settings.getMapProvider().getMapClass()); - - mapIntent.putExtra(EXTRAS_SEARCH, searchIntent); - mapIntent.putExtra(EXTRAS_GEOCODE, geocodeIntent); - if (coordsIntent != null) { - mapIntent.putExtra(EXTRAS_LATITUDE, coordsIntent.getLatitude()); - mapIntent.putExtra(EXTRAS_LONGITUDE, coordsIntent.getLongitude()); - } - mapIntent.putExtra(EXTRAS_WPTTYPE, waypointTypeIntent != null ? waypointTypeIntent.id : null); - int[] mapState = new int[4]; - GeoPointImpl mapCenter = mapView.getMapViewCenter(); - mapState[0] = mapCenter.getLatitudeE6(); - mapState[1] = mapCenter.getLongitudeE6(); - mapState[2] = mapView.getMapZoomLevel(); - mapState[3] = followMyLocation ? 1 : 0; - mapIntent.putExtra(EXTRAS_MAPSTATE, mapState); - mapIntent.putExtra(EXTRAS_MAP_TITLE, mapTitle); - - // start the new map - activity.startActivity(mapIntent); - - } + changeMapSource(mapSource); return true; } @@ -843,16 +821,72 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto return false; } - private boolean switchMapSource(int sourceId) { - boolean mapRestartRequired = !MapProviderFactory.isSameProvider(Settings.getMapSource(), sourceId); + /** + * Restart the current activity if the map provider has changed, or change the map source if needed. + * + * @param mapSource + * the new map source, which can be the same as the current one + * @return true if a restart is needed, false otherwise + */ + private boolean changeMapSource(final int mapSource) { + final boolean restartRequired = !MapProviderFactory.isSameProvider(currentSourceId, mapSource); - Settings.setMapSource(sourceId); + Settings.setMapSource(mapSource); + currentSourceId = mapSource; - if (!mapRestartRequired) { + if (restartRequired) { + mapRestart(); + } else if (mapView != null) { mapView.setMapSource(); } - return mapRestartRequired; + return restartRequired; + } + + /** + * Restart the current activity with the default map source. + */ + private void mapRestart() { + // close old mapview + activity.finish(); + + // prepare information to restart a similar view + Intent mapIntent = new Intent(activity, Settings.getMapProvider().getMapClass()); + + mapIntent.putExtra(EXTRAS_SEARCH, searchIntent); + mapIntent.putExtra(EXTRAS_GEOCODE, geocodeIntent); + if (coordsIntent != null) { + mapIntent.putExtra(EXTRAS_COORDS, coordsIntent); + } + mapIntent.putExtra(EXTRAS_WPTTYPE, waypointTypeIntent != null ? waypointTypeIntent.id : null); + mapIntent.putExtra(EXTRAS_MAP_TITLE, mapTitle); + + final int[] mapState = currentMapState(); + if (mapState != null) { + mapIntent.putExtra(EXTRAS_MAPSTATE, mapState); + } + + // start the new map + activity.startActivity(mapIntent); + } + + /** + * Get the current map state from the map view if it exists or from the mapStateIntent field otherwise. + * + * @return the current map state as an array of int, or null if no map state is available + */ + private int[] currentMapState() { + if (mapView != null) { + int[] mapState = new int[4]; + GeoPointImpl mapCenter = mapView.getMapViewCenter(); + mapState[0] = mapCenter.getLatitudeE6(); + mapState[1] = mapCenter.getLongitudeE6(); + mapState[2] = mapView.getMapZoomLevel(); + mapState[3] = followMyLocation ? 1 : 0; + return mapState; + } else { + return mapStateIntent; + } } private void savePrefs() { @@ -908,7 +942,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } catch (Exception e) { - Log.w(Settings.tag, "Failed to update location."); + Log.w("Failed to update location."); } } } @@ -981,11 +1015,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (mapView != null) { // get current viewport - GeoPointImpl mapCenterNow = mapView.getMapViewCenter(); - int centerLatitudeNow = mapCenterNow.getLatitudeE6(); - int centerLongitudeNow = mapCenterNow.getLongitudeE6(); - int spanLatitudeNow = mapView.getLatitudeSpan(); - int spanLongitudeNow = mapView.getLongitudeSpan(); + final Viewport viewportNow = mapView.getViewport(); + int zoomNow = mapView.getMapZoomLevel(); // check if map moved or zoomed //TODO Portree Use Rectangle inside with bigger search window. That will stop reloading on every move @@ -995,20 +1026,16 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto moved = true; } else if (live && Settings.isLiveMap() && !downloaded) { moved = true; - } else if (centerLatitude == null || centerLongitude == null) { + } else if (viewport == null) { moved = true; - } else if (spanLatitude == null || spanLongitude == null) { + } else if (zoomNow != zoom) { moved = true; - } else if (((Math.abs(spanLatitudeNow - spanLatitude) > 50) || (Math.abs(spanLongitudeNow - spanLongitude) > 50) || // changed zoom - (Math.abs(centerLatitudeNow - centerLatitude) > (spanLatitudeNow / 4)) || (Math.abs(centerLongitudeNow - centerLongitude) > (spanLongitudeNow / 4)) // map moved - ) && (cachesCnt <= 0 || CollectionUtils.isEmpty(caches) - || !Viewport.isInViewPort(centerLatitude, centerLongitude, centerLatitudeNow, centerLongitudeNow, spanLatitude, spanLongitude, spanLatitudeNow, spanLongitudeNow))) { + } else if (mapMoved(viewport, viewportNow) && (cachesCnt <= 0 || CollectionUtils.isEmpty(caches) || !viewport.includes(viewportNow))) { moved = true; } // update title on any change - int zoomNow = mapView.getMapZoomLevel(); - if (moved || zoomNow != zoom || spanLatitudeNow != spanLatitude || spanLongitudeNow != spanLongitude || centerLatitudeNow != centerLatitude || centerLongitudeNow != centerLongitude) { + if (moved || zoomNow != zoom || !viewportNow.equals(viewport)) { displayHandler.sendEmptyMessage(UPDATE_TITLE); } zoom = zoomNow; @@ -1020,19 +1047,15 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto long currentTime = System.currentTimeMillis(); if (1000 < (currentTime - loadThreadRun)) { - centerLatitude = centerLatitudeNow; - centerLongitude = centerLongitudeNow; - spanLatitude = spanLatitudeNow; - spanLongitude = spanLongitudeNow; - - loadExecutor.execute(new LoadRunnable(centerLatitude, centerLongitude, spanLatitude, spanLongitude)); + viewport = viewportNow; + loadExecutor.execute(new LoadRunnable(viewport)); } } } yield(); } catch (Exception e) { - Log.w(Settings.tag, "cgeomap.LoadTimer.run: " + e.toString()); + Log.w("cgeomap.LoadTimer.run: " + e.toString()); } } } @@ -1069,11 +1092,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (mapView != null) { // get current viewport - GeoPointImpl mapCenterNow = mapView.getMapViewCenter(); - int centerLatitudeNow = mapCenterNow.getLatitudeE6(); - int centerLongitudeNow = mapCenterNow.getLongitudeE6(); - int spanLatitudeNow = mapView.getLatitudeSpan(); - int spanLongitudeNow = mapView.getLongitudeSpan(); + final Viewport viewportNow = mapView.getViewport(); // check if map moved or zoomed boolean moved = false; @@ -1082,30 +1101,22 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (60000 < (currentTime - go4CacheThreadRun)) { moved = true; - } else if (centerLatitudeUsers == null || centerLongitudeUsers == null) { - moved = true; - } else if (spanLatitudeUsers == null || spanLongitudeUsers == null) { + } else if (viewportUsers == null) { moved = true; - } else if (((Math.abs(spanLatitudeNow - spanLatitudeUsers) > 50) || (Math.abs(spanLongitudeNow - spanLongitudeUsers) > 50) || // changed zoom - (Math.abs(centerLatitudeNow - centerLatitudeUsers) > (spanLatitudeNow / 4)) || (Math.abs(centerLongitudeNow - centerLongitudeUsers) > (spanLongitudeNow / 4)) // map moved - ) && !Viewport.isInViewPort(centerLatitudeUsers, centerLongitudeUsers, centerLatitudeNow, centerLongitudeNow, spanLatitudeUsers, spanLongitudeUsers, spanLatitudeNow, spanLongitudeNow)) { + } else if (mapMoved(viewportUsers, viewportNow) && !viewportUsers.includes(viewportNow)) { moved = true; } // save new values if (moved && (1000 < (currentTime - go4CacheThreadRun))) { - centerLatitudeUsers = centerLatitudeNow; - centerLongitudeUsers = centerLongitudeNow; - spanLatitudeUsers = spanLatitudeNow; - spanLongitudeUsers = spanLongitudeNow; - - Go4CacheExecutor.execute(new Go4CacheRunnable(centerLatitudeNow, centerLongitudeNow, spanLatitudeNow, spanLongitudeNow)); + viewportUsers = viewportNow; + Go4CacheExecutor.execute(new Go4CacheRunnable(viewportUsers)); } } yield(); } catch (Exception e) { - Log.w(Settings.tag, "cgeomap.LoadUsersTimer.run: " + e.toString()); + Log.w("cgeomap.LoadUsersTimer.run: " + e.toString()); } } } @@ -1118,8 +1129,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private class LoadRunnable extends DoRunnable { - public LoadRunnable(long centerLatIn, long centerLonIn, long spanLatIn, long spanLonIn) { - super(centerLatIn, centerLonIn, spanLatIn, spanLonIn); + public LoadRunnable(final Viewport viewport) { + super(viewport); } @Override @@ -1138,34 +1149,50 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } else { // live map if (!live || !Settings.isLiveMap()) { - search = new SearchResult(app.getStoredInViewport(centerLat, centerLon, spanLat, spanLon, Settings.getCacheType())); + search = new SearchResult(app.getStoredInViewport(viewport, Settings.getCacheType())); } else { - search = new SearchResult(app.getCachedInViewport(centerLat, centerLon, spanLat, spanLon, Settings.getCacheType())); + search = new SearchResult(app.getCachedInViewport(viewport, Settings.getCacheType())); } } if (search != null) { downloaded = true; - caches.addAll(search.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS)); + Set<cgCache> cachesFromSearchResult = search.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS); + caches.addAll(cachesFromSearchResult); } if (live) { final boolean excludeMine = Settings.isExcludeMyCaches(); final boolean excludeDisabled = Settings.isExcludeDisabledCaches(); - final ArrayList<cgCache> tempList = new ArrayList<cgCache>(caches); + final List<cgCache> tempList = caches.getAsList(); + for (cgCache cache : tempList) { if ((cache.isFound() && excludeMine) || (cache.isOwn() && excludeMine) || (cache.isDisabled() && excludeDisabled)) { caches.remove(cache); } } } + countVisibleCaches(); + if (cachesCnt < Settings.getWayPointsThreshold()) + { + waypoints.clear(); + if (searchIntent == null && geocodeIntent == null) { + //All visible waypoints + waypoints.addAll(app.getWaypointsInViewport(viewport, Settings.isExcludeMyCaches(), Settings.isExcludeDisabledCaches())); + } else { + //All waypoints from the viewed caches + for (cgCache c : caches.getAsList()) { + waypoints.addAll(c.getWaypoints()); + } + } + } //render - displayExecutor.execute(new DisplayRunnable(centerLat, centerLon, spanLat, spanLon)); + displayExecutor.execute(new DisplayRunnable(viewport)); if (live && Settings.isLiveMap()) { - downloadExecutor.execute(new DownloadRunnable(centerLat, centerLon, spanLat, spanLon)); + downloadExecutor.execute(new DownloadRunnable(viewport)); } } finally { showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress @@ -1180,8 +1207,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private class DownloadRunnable extends DoRunnable { - public DownloadRunnable(long centerLatIn, long centerLonIn, long spanLatIn, long spanLonIn) { - super(centerLatIn, centerLonIn, spanLatIn, spanLonIn); + public DownloadRunnable(final Viewport viewport) { + super(viewport); } @Override @@ -1199,8 +1226,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } - final Viewport viewport = new Viewport(new Geopoint(centerLat / 1e6, centerLon / 1e6), 0.8 * spanLat / 1e6, 0.8 * spanLon / 1e6); - search = ConnectorFactory.searchByViewport(viewport, tokens); + search = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens); if (search != null) { downloaded = true; if (search.getError() == StatusCode.NOT_LOGGED_IN) { @@ -1222,10 +1248,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } //render - displayExecutor.execute(new DisplayRunnable(centerLat, centerLon, spanLat, spanLon)); + displayExecutor.execute(new DisplayRunnable(viewport)); } catch (ThreadDeath e) { - Log.d(Settings.tag, "DownloadThread stopped"); + Log.d("DownloadThread stopped"); displayHandler.sendEmptyMessage(UPDATE_TITLE); } finally { showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress @@ -1238,8 +1264,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto */ private class DisplayRunnable extends DoRunnable { - public DisplayRunnable(long centerLatIn, long centerLonIn, long spanLatIn, long spanLonIn) { - super(centerLatIn, centerLonIn, spanLatIn, spanLonIn); + public DisplayRunnable(final Viewport viewport) { + super(viewport); } @Override @@ -1251,29 +1277,28 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } // display caches - final List<cgCache> cachesToDisplay = new ArrayList<cgCache>(caches); + final List<cgCache> cachesToDisplay = caches.getAsList(); + final List<cgWaypoint> waypointsToDisplay = new ArrayList<cgWaypoint>(waypoints); final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<CachesOverlayItemImpl>(); if (!cachesToDisplay.isEmpty()) { + // Only show waypoints for single view or setting + // when less than showWaypointsthreshold Caches shown + if (cachesToDisplay.size() == 1 || (cachesCnt < Settings.getWayPointsThreshold())) { + for (cgWaypoint waypoint : waypointsToDisplay) { + + if (waypoint.getCoords() == null) { + continue; + } + + itemsToDisplay.add(getItem(waypoint, null, waypoint)); + } + } for (cgCache cache : cachesToDisplay) { if (cache.getCoords() == null) { continue; } - - // display cache waypoints - if (cache.hasWaypoints() - // Only show waypoints for single view or setting - // when less than showWaypointsthreshold Caches shown - && (cachesToDisplay.size() == 1 || (cachesToDisplay.size() < Settings.getWayPointsThreshold()))) { - for (cgWaypoint waypoint : cache.getWaypoints()) { - if (waypoint.getCoords() == null) { - continue; - } - - itemsToDisplay.add(getItem(waypoint, null, waypoint)); - } - } itemsToDisplay.add(getItem(cache, cache, null)); } @@ -1289,7 +1314,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto displayHandler.sendEmptyMessage(UPDATE_TITLE); } catch (ThreadDeath e) { - Log.d(Settings.tag, "DisplayThread stopped"); + Log.d("DisplayThread stopped"); displayHandler.sendEmptyMessage(UPDATE_TITLE); } finally { showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); @@ -1303,21 +1328,15 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private class Go4CacheRunnable extends DoRunnable { - public Go4CacheRunnable(long centerLatIn, long centerLonIn, long spanLatIn, long spanLonIn) { - super(centerLatIn, centerLonIn, spanLatIn, spanLonIn); + public Go4CacheRunnable(final Viewport viewport) { + super(viewport); } @Override public void run() { - final Geopoint center = new Geopoint((int) centerLat, (int) centerLon); - final Viewport viewport = new Viewport(center, spanLat / 1e6 * 1.5, spanLon / 1e6 * 1.5); - - try { - go4CacheThreadRun = System.currentTimeMillis(); - List<Go4CacheUser> go4CacheUsers = Go4Cache.getGeocachersInViewport(Settings.getUsername(), viewport); - go4CacheDisplayExecutor.execute(new Go4CacheDisplayRunnable(go4CacheUsers, centerLat, centerLon, spanLat, spanLon)); - } finally { - } + go4CacheThreadRun = System.currentTimeMillis(); + List<Go4CacheUser> go4CacheUsers = Go4Cache.getGeocachersInViewport(Settings.getUsername(), viewport.resize(1.5)); + go4CacheDisplayExecutor.execute(new Go4CacheDisplayRunnable(go4CacheUsers, viewport)); } } @@ -1328,8 +1347,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private List<Go4CacheUser> users = null; - public Go4CacheDisplayRunnable(List<Go4CacheUser> usersIn, long centerLatIn, long centerLonIn, long spanLatIn, long spanLonIn) { - super(centerLatIn, centerLonIn, spanLatIn, spanLonIn); + public Go4CacheDisplayRunnable(List<Go4CacheUser> usersIn, final Viewport viewport) { + super(viewport); users = usersIn; } @@ -1397,16 +1416,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private abstract class DoRunnable implements Runnable { - protected long centerLat = 0L; - protected long centerLon = 0L; - protected long spanLat = 0L; - protected long spanLon = 0L; + final protected Viewport viewport; - public DoRunnable(long centerLatIn, long centerLonIn, long spanLatIn, long spanLonIn) { - centerLat = centerLatIn; - centerLon = centerLonIn; - spanLat = spanLatIn; - spanLon = spanLonIn; + public DoRunnable(final Viewport viewport) { + this.viewport = viewport; } public abstract void run(); @@ -1478,15 +1491,15 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } if (handler.isCancelled()) { - Log.i(Settings.tag, "Stopped storing process."); + Log.i("Stopped storing process."); break; } - cgBase.storeCache(activity, null, geocode, StoredList.STANDARD_LIST_ID, false, handler); + cgCache.storeCache(activity, null, geocode, StoredList.STANDARD_LIST_ID, false, handler); } } catch (Exception e) { - Log.e(Settings.tag, "cgeocaches.LoadDetails.run: " + e.toString()); + Log.e("cgeocaches.LoadDetails.run: " + e.toString()); } finally { // one more cache over detailProgress++; @@ -1504,6 +1517,13 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } + private static boolean mapMoved(final Viewport referenceViewport, final Viewport newViewport) { + return Math.abs(newViewport.getLatitudeSpan() - referenceViewport.getLatitudeSpan()) > 50e-6 || + Math.abs(newViewport.getLongitudeSpan() - referenceViewport.getLongitudeSpan()) > 50e-6 || + Math.abs(newViewport.center.getLatitude() - referenceViewport.center.getLatitude()) > referenceViewport.getLatitudeSpan() / 4 || + Math.abs(newViewport.center.getLongitude() - referenceViewport.center.getLongitude()) > referenceViewport.getLongitudeSpan() / 4; + } + // center map to desired location private void centerMap(final Geopoint coords) { if (coords == null) { @@ -1537,46 +1557,21 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto alreadyCentered = true; } else if (!centered && (geocodeCenter != null || searchIntent != null)) { try { - List<Number> viewport = null; + Viewport viewport = null; if (geocodeCenter != null) { viewport = app.getBounds(geocodeCenter); - } else { - if (searchCenter != null) { - viewport = app.getBounds(searchCenter.getGeocodes()); - } - } - - if (viewport == null || viewport.size() < 5) { - return; + } else if (searchCenter != null) { + viewport = app.getBounds(searchCenter.getGeocodes()); } - int cnt = (Integer) viewport.get(0); - if (cnt <= 0) { + if (viewport == null) { return; } - int minLat = (int) ((Double) viewport.get(1) * 1e6); - int maxLat = (int) ((Double) viewport.get(2) * 1e6); - int maxLon = (int) ((Double) viewport.get(3) * 1e6); - int minLon = (int) ((Double) viewport.get(4) * 1e6); - - int centerLat = 0; - int centerLon = 0; - - if ((Math.abs(maxLat) - Math.abs(minLat)) != 0) { - centerLat = minLat + ((maxLat - minLat) / 2); - } else { - centerLat = maxLat; - } - if ((Math.abs(maxLon) - Math.abs(minLon)) != 0) { - centerLon = minLon + ((maxLon - minLon) / 2); - } else { - centerLon = maxLon; - } - mapController.setCenter(mapProvider.getGeoPointBase(new Geopoint(centerLat, centerLon))); - if (Math.abs(maxLat - minLat) != 0 && Math.abs(maxLon - minLon) != 0) { - mapController.zoomToSpan(Math.abs(maxLat - minLat), Math.abs(maxLon - minLon)); + mapController.setCenter(mapProvider.getGeoPointBase(viewport.center)); + if (viewport.getLatitudeSpan() != 0 && viewport.getLongitudeSpan() != 0) { + mapController.zoomToSpan((int) (viewport.getLatitudeSpan() * 1e6), (int) (viewport.getLongitudeSpan() * 1e6)); } } catch (Exception e) { // nothing at all @@ -1666,8 +1661,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto public static void startActivityCoords(final Activity fromActivity, final Geopoint coords, final WaypointType type, final String title) { final Intent mapIntent = newIntent(fromActivity); - mapIntent.putExtra(EXTRAS_LATITUDE, coords.getLatitude()); - mapIntent.putExtra(EXTRAS_LONGITUDE, coords.getLongitude()); + mapIntent.putExtra(EXTRAS_COORDS, coords); if (type != null) { mapIntent.putExtra(EXTRAS_WPTTYPE, type.id); } diff --git a/main/src/cgeo/geocaching/maps/CachesOverlay.java b/main/src/cgeo/geocaching/maps/CachesOverlay.java index ddd6ec6..17c7c0f 100644 --- a/main/src/cgeo/geocaching/maps/CachesOverlay.java +++ b/main/src/cgeo/geocaching/maps/CachesOverlay.java @@ -18,7 +18,6 @@ import org.apache.commons.lang3.StringUtils; import android.app.ProgressDialog; import android.content.Context; -import android.content.Intent; import android.graphics.Canvas; import android.graphics.DashPathEffect; import android.graphics.Paint; @@ -36,11 +35,9 @@ public class CachesOverlay extends AbstractItemizedOverlay { private Context context = null; private boolean displayCircles = false; private ProgressDialog waitDialog = null; - private Point center = new Point(); - private Point left = new Point(); private Paint blockedCircle = null; - private PaintFlagsDrawFilter setfil = null; - private PaintFlagsDrawFilter remfil = null; + private PaintFlagsDrawFilter setFilter = null; + private PaintFlagsDrawFilter removeFilter = null; private MapProvider mapProvider = null; public CachesOverlay(ItemizedOverlayImpl ovlImpl, Context contextIn) { @@ -107,65 +104,91 @@ public class CachesOverlay extends AbstractItemizedOverlay { } private void drawInternal(Canvas canvas, MapProjectionImpl projection) { + if (!displayCircles || items.isEmpty()) { + return; + } // prevent content changes getOverlayImpl().lock(); try { - if (displayCircles) { - if (blockedCircle == null) { - blockedCircle = new Paint(); - blockedCircle.setAntiAlias(true); - blockedCircle.setStrokeWidth(2.0f); - blockedCircle.setARGB(127, 0, 0, 0); - blockedCircle.setPathEffect(new DashPathEffect(new float[] { 3, 2 }, 0)); + lazyInitializeDrawingObjects(); + canvas.setDrawFilter(setFilter); + + final int radius = calculateDrawingRadius(projection); + final Point center = new Point(); + + for (CachesOverlayItemImpl item : items) { + final Geopoint itemCoord = item.getCoord().getCoords(); + final GeoPointImpl itemGeo = mapProvider.getGeoPointBase(itemCoord); + projection.toPixels(itemGeo, center); + + final CacheType type = item.getType(); + if (type == null || type == CacheType.MULTI || type == CacheType.MYSTERY || type == CacheType.VIRTUAL || type.isEvent()) { + blockedCircle.setColor(0x66000000); + blockedCircle.setStyle(Style.STROKE); + canvas.drawCircle(center.x, center.y, radius, blockedCircle); + } else { + blockedCircle.setColor(0x66BB0000); + blockedCircle.setStyle(Style.STROKE); + canvas.drawCircle(center.x, center.y, radius, blockedCircle); + + blockedCircle.setColor(0x44BB0000); + blockedCircle.setStyle(Style.FILL); + canvas.drawCircle(center.x, center.y, radius, blockedCircle); } + } + canvas.setDrawFilter(removeFilter); + } finally { + getOverlayImpl().unlock(); + } + } - if (setfil == null) { - setfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); - } - if (remfil == null) { - remfil = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); - } + /** + * calculate the radius of the circle to be drawn for the first item only. Those circles are only 161 meters in + * reality and therefore the minor changes due to the projection will not make any visible difference at the zoom + * levels which are used to see the circles. + * + * @param projection + * @return + */ + private int calculateDrawingRadius(MapProjectionImpl projection) { + float[] distanceArray = new float[1]; + final Geopoint itemCoord = items.get(0).getCoord().getCoords(); - canvas.setDrawFilter(setfil); + Location.distanceBetween(itemCoord.getLatitude(), itemCoord.getLongitude(), + itemCoord.getLatitude(), itemCoord.getLongitude() + 1, distanceArray); + final float longitudeLineDistance = distanceArray[0]; - for (CachesOverlayItemImpl item : items) { - final IWaypoint itemCoord = item.getCoord(); - float[] result = new float[1]; + final GeoPointImpl itemGeo = mapProvider.getGeoPointBase(itemCoord); - Location.distanceBetween(itemCoord.getCoords().getLatitude(), itemCoord.getCoords().getLongitude(), - itemCoord.getCoords().getLatitude(), itemCoord.getCoords().getLongitude() + 1, result); - final float longitudeLineDistance = result[0]; + final Geopoint leftCoords = new Geopoint(itemCoord.getLatitude(), + itemCoord.getLongitude() - 161 / longitudeLineDistance); + final GeoPointImpl leftGeo = mapProvider.getGeoPointBase(leftCoords); - GeoPointImpl itemGeo = mapProvider.getGeoPointBase(itemCoord.getCoords()); + final Point center = new Point(); + projection.toPixels(itemGeo, center); - final Geopoint leftCoords = new Geopoint(itemCoord.getCoords().getLatitude(), - itemCoord.getCoords().getLongitude() - 161 / longitudeLineDistance); - GeoPointImpl leftGeo = mapProvider.getGeoPointBase(leftCoords); + final Point left = new Point(); + projection.toPixels(leftGeo, left); - projection.toPixels(itemGeo, center); - projection.toPixels(leftGeo, left); - int radius = center.x - left.x; + final int radius = center.x - left.x; + return radius; + } - final CacheType type = item.getType(); - if (type == null || type == CacheType.MULTI || type == CacheType.MYSTERY || type == CacheType.VIRTUAL) { - blockedCircle.setColor(0x66000000); - blockedCircle.setStyle(Style.STROKE); - canvas.drawCircle(center.x, center.y, radius, blockedCircle); - } else { - blockedCircle.setColor(0x66BB0000); - blockedCircle.setStyle(Style.STROKE); - canvas.drawCircle(center.x, center.y, radius, blockedCircle); + private void lazyInitializeDrawingObjects() { + if (blockedCircle == null) { + blockedCircle = new Paint(); + blockedCircle.setAntiAlias(true); + blockedCircle.setStrokeWidth(2.0f); + blockedCircle.setARGB(127, 0, 0, 0); + blockedCircle.setPathEffect(new DashPathEffect(new float[] { 3, 2 }, 0)); + } - blockedCircle.setColor(0x44BB0000); - blockedCircle.setStyle(Style.FILL); - canvas.drawCircle(center.x, center.y, radius, blockedCircle); - } - } - canvas.setDrawFilter(remfil); - } - } finally { - getOverlayImpl().unlock(); + if (setFilter == null) { + setFilter = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); + } + if (removeFilter == null) { + removeFilter = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); } } @@ -203,19 +226,11 @@ public class CachesOverlay extends AbstractItemizedOverlay { final IWaypoint coordinate = item.getCoord(); if (StringUtils.isNotBlank(coordinate.getCoordType()) && coordinate.getCoordType().equalsIgnoreCase("cache") && StringUtils.isNotBlank(coordinate.getGeocode())) { - Intent popupIntent = new Intent(context, cgeopopup.class); - - popupIntent.putExtra("geocode", coordinate.getGeocode()); - CGeoMap.markCacheAsDirty(coordinate.getGeocode()); - context.startActivity(popupIntent); + cgeopopup.startActivity(context, coordinate.getGeocode()); } else if (coordinate.getCoordType() != null && coordinate.getCoordType().equalsIgnoreCase("waypoint") && coordinate.getId() > 0) { - Intent popupIntent = new Intent(context, cgeowaypoint.class); - - popupIntent.putExtra("waypoint", coordinate.getId()); - CGeoMap.markCacheAsDirty(coordinate.getGeocode()); - context.startActivity(popupIntent); + cgeowaypoint.startActivity(context, coordinate.getId()); } else { waitDialog.dismiss(); return false; @@ -223,7 +238,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { waitDialog.dismiss(); } catch (Exception e) { - Log.e(Settings.tag, "cgMapOverlay.onTap: " + e.toString()); + Log.e("cgMapOverlay.onTap: " + e.toString()); } return false; @@ -234,7 +249,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { try { return items.get(index); } catch (Exception e) { - Log.e(Settings.tag, "cgMapOverlay.createItem: " + e.toString()); + Log.e("cgMapOverlay.createItem: " + e.toString()); } return null; @@ -245,7 +260,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { try { return items.size(); } catch (Exception e) { - Log.e(Settings.tag, "cgMapOverlay.size: " + e.toString()); + Log.e("cgMapOverlay.size: " + e.toString()); } return 0; diff --git a/main/src/cgeo/geocaching/maps/OtherCachersOverlay.java b/main/src/cgeo/geocaching/maps/OtherCachersOverlay.java index 9cc20f1..6ca050e 100644 --- a/main/src/cgeo/geocaching/maps/OtherCachersOverlay.java +++ b/main/src/cgeo/geocaching/maps/OtherCachersOverlay.java @@ -1,7 +1,6 @@ package cgeo.geocaching.maps; import cgeo.geocaching.CacheDetailActivity; -import cgeo.geocaching.Settings; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.go4cache.Go4CacheUser; import cgeo.geocaching.maps.interfaces.ItemizedOverlayImpl; @@ -14,7 +13,6 @@ import org.apache.commons.lang3.StringUtils; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.graphics.Canvas; import java.util.ArrayList; @@ -92,7 +90,7 @@ public class OtherCachersOverlay extends AbstractItemizedOverlay { return true; } catch (Exception e) { - Log.e(Settings.tag, "cgUsersOverlay.onTap: " + e.toString()); + Log.e("cgUsersOverlay.onTap: " + e.toString()); } return false; @@ -108,7 +106,7 @@ public class OtherCachersOverlay extends AbstractItemizedOverlay { try { return items.get(index); } catch (Exception e) { - Log.e(Settings.tag, "cgUsersOverlay.createItem: " + e.toString()); + Log.e("cgUsersOverlay.createItem: " + e.toString()); } return null; @@ -119,7 +117,7 @@ public class OtherCachersOverlay extends AbstractItemizedOverlay { try { return items.size(); } catch (Exception e) { - Log.e(Settings.tag, "cgUsersOverlay.size: " + e.toString()); + Log.e("cgUsersOverlay.size: " + e.toString()); } return 0; @@ -135,9 +133,7 @@ public class OtherCachersOverlay extends AbstractItemizedOverlay { public void onClick(DialogInterface dialog, int id) { if (geocode != null) { - final Intent detailIntent = new Intent(context, CacheDetailActivity.class); - detailIntent.putExtra("geocode", geocode); - context.startActivity(detailIntent); + CacheDetailActivity.startActivity(context, geocode); } dialog.cancel(); diff --git a/main/src/cgeo/geocaching/maps/ScaleOverlay.java b/main/src/cgeo/geocaching/maps/ScaleOverlay.java index f43ba25..e1d193e 100644 --- a/main/src/cgeo/geocaching/maps/ScaleOverlay.java +++ b/main/src/cgeo/geocaching/maps/ScaleOverlay.java @@ -25,11 +25,6 @@ public class ScaleOverlay implements GeneralOverlay { private Paint scaleShadow = null; private BlurMaskFilter blur = null; private float pixelDensity = 0; - private double pixels = 0d; - private int bottom = 0; - private double distance = 0d; - private double distanceRound = 0d; - private String units = null; private OverlayImpl ovlImpl = null; public ScaleOverlay(Activity activity, OverlayImpl overlayImpl) { @@ -51,64 +46,42 @@ public class ScaleOverlay implements GeneralOverlay { drawInternal(canvas, mapView); } + static private double keepSignificantDigit(final double distance) { + final double scale = Math.pow(10, Math.floor(Math.log10(distance))); + return scale * Math.floor(distance / scale); + } + private void drawInternal(Canvas canvas, MapViewImpl mapView) { final double span = mapView.getLongitudeSpan() / 1e6; final GeoPointImpl center = mapView.getMapViewCenter(); - pixels = mapView.getWidth() * SCALE_WIDTH_FACTOR; // pixels related to following latitude span - bottom = mapView.getHeight() - 14; // pixels from bottom side of screen + final int bottom = mapView.getHeight() - 14; // pixels from bottom side of screen final Geopoint leftCoords = new Geopoint(center.getLatitudeE6() / 1e6, center.getLongitudeE6() / 1e6 - span / 2); final Geopoint rightCoords = new Geopoint(center.getLatitudeE6() / 1e6, center.getLongitudeE6() / 1e6 + span / 2); - distance = leftCoords.distanceTo(rightCoords) * SCALE_WIDTH_FACTOR; - distanceRound = 0d; - - //FIXME: merge with getHumanDistance() + String units; + double distance = leftCoords.distanceTo(rightCoords) * SCALE_WIDTH_FACTOR; if (Settings.isUseMetricUnits()) { - if (distance > 100) { // 100+ km > 1xx km - distanceRound = Math.floor(distance / 100) * 100; + if (distance >= 1) { units = "km"; - } else if (distance > 10) { // 10 - 100 km > 1x km - distanceRound = Math.floor(distance / 10) * 10; - units = "km"; - } else if (distance > 1) { // 1 - 10 km > 1.x km - distanceRound = Math.floor(distance); - units = "km"; - } else if (distance > 0.1) { // 100 m - 1 km > 1xx m - distance *= 1000; - distanceRound = Math.floor(distance / 100) * 100; - units = "m"; - } else { // 1 - 100 m > 1x m + } else { distance *= 1000; - distanceRound = Math.round(distance / 10) * 10; units = "m"; } } else { distance /= IConversion.MILES_TO_KILOMETER; - - if (distance > 100) { // 100+ mi > 1xx mi - distanceRound = Math.floor(distance / 100) * 100; - units = "mi"; - } else if (distance > 10) { // 10 - 100 mi > 1x mi - distanceRound = Math.floor(distance / 10) * 10; + if (distance >= 1) { units = "mi"; - } else if (distance > 1) { // 1 - 10 mi > 1.x mi - distanceRound = Math.floor(distance); - units = "mi"; - } else if (distance > 0.1) { // 0.1 mi - 1.0 mi > 1xx ft - distance *= 5280; - distanceRound = Math.floor(distance / 100) * 100; - units = "ft"; - } else { // 1 - 100 ft > 1x ft + } else { distance *= 5280; - distanceRound = Math.round(distance / 10) * 10; units = "ft"; } } - pixels = Math.round((pixels / distance) * distanceRound); + final double distanceRound = keepSignificantDigit(distance); + final double pixels = Math.round((mapView.getWidth() * SCALE_WIDTH_FACTOR / distance) * distanceRound); if (blur == null) { blur = new BlurMaskFilter(3, BlurMaskFilter.Blur.NORMAL); diff --git a/main/src/cgeo/geocaching/maps/google/GoogleGeoPoint.java b/main/src/cgeo/geocaching/maps/google/GoogleGeoPoint.java index 56bc40c..d5f6385 100644 --- a/main/src/cgeo/geocaching/maps/google/GoogleGeoPoint.java +++ b/main/src/cgeo/geocaching/maps/google/GoogleGeoPoint.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.google; +import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import com.google.android.maps.GeoPoint; @@ -10,4 +11,9 @@ public class GoogleGeoPoint extends GeoPoint implements GeoPointImpl { super(latitudeE6, longitudeE6); } + @Override + public Geopoint getCoords() { + return new Geopoint(getLatitudeE6() / 1e6, getLongitudeE6() / 1e6); + } + } diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java index ba53003..6cbe9ec 100644 --- a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java +++ b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java @@ -36,6 +36,11 @@ public class GoogleMapActivity extends MapActivity implements MapActivityImpl { } @Override + protected void onSaveInstanceState(final Bundle outState) { + mapBase.onSaveInstanceState(outState); + } + + @Override protected void onDestroy() { mapBase.onDestroy(); } diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java index 9c23035..8bf7deb 100644 --- a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java +++ b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java @@ -3,6 +3,7 @@ package cgeo.geocaching.maps.google; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import cgeo.geocaching.Settings; +import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.maps.CachesOverlay; import cgeo.geocaching.maps.OtherCachersOverlay; import cgeo.geocaching.maps.PositionOverlay; @@ -60,7 +61,7 @@ public class GoogleMapView extends MapView implements MapViewImpl { super.draw(canvas); } catch (Exception e) { - Log.e(Settings.tag, "GoogleMapView.draw: " + e.toString()); + Log.e("GoogleMapView.draw: " + e.toString()); } } @@ -74,7 +75,7 @@ public class GoogleMapView extends MapView implements MapViewImpl { super.displayZoomControls(takeFocus); } catch (Exception e) { - Log.e(Settings.tag, "GoogleMapView.displayZoomControls: " + e.toString()); + Log.e("GoogleMapView.displayZoomControls: " + e.toString()); } } @@ -90,6 +91,11 @@ public class GoogleMapView extends MapView implements MapViewImpl { } @Override + public Viewport getViewport() { + return new Viewport(getMapViewCenter(), getLatitudeSpan() / 1e6, getLongitudeSpan() / 1e6); + } + + @Override public void addOverlay(OverlayImpl ovl) { getOverlays().add((Overlay) ovl); } diff --git a/main/src/cgeo/geocaching/maps/interfaces/GeoPointImpl.java b/main/src/cgeo/geocaching/maps/interfaces/GeoPointImpl.java index 55f014b..5636da2 100644 --- a/main/src/cgeo/geocaching/maps/interfaces/GeoPointImpl.java +++ b/main/src/cgeo/geocaching/maps/interfaces/GeoPointImpl.java @@ -1,5 +1,7 @@ package cgeo.geocaching.maps.interfaces; +import cgeo.geocaching.ICoordinates; + /** * Defines the common functions of the provider-specific * GeoPoint implementations @@ -7,7 +9,7 @@ package cgeo.geocaching.maps.interfaces; * @author rsudev * */ -public interface GeoPointImpl { +public interface GeoPointImpl extends ICoordinates { int getLatitudeE6(); diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java b/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java index 08e04f1..c567cf2 100644 --- a/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java +++ b/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.interfaces; +import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.maps.CachesOverlay; import cgeo.geocaching.maps.OtherCachersOverlay; import cgeo.geocaching.maps.PositionOverlay; @@ -78,4 +79,6 @@ public interface MapViewImpl { */ boolean needsInvertedColors(); + Viewport getViewport(); + } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeGeoPoint.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeGeoPoint.java index 19dc7c5..490822b 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeGeoPoint.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeGeoPoint.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.mapsforge; +import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import org.mapsforge.android.maps.GeoPoint; @@ -9,4 +10,9 @@ public class MapsforgeGeoPoint extends GeoPoint implements GeoPointImpl { public MapsforgeGeoPoint(int latitudeE6, int longitudeE6) { super(latitudeE6, longitudeE6); } + + @Override + public Geopoint getCoords() { + return new Geopoint(getLatitudeE6() / 1e6, getLongitudeE6() / 1e6); + } } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java index 6ca34d6..06d018c 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java @@ -31,6 +31,11 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl } @Override + protected void onSaveInstanceState(final Bundle outState) { + mapBase.onSaveInstanceState(outState); + } + + @Override protected void onDestroy() { mapBase.onDestroy(); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java index 1929b7b..2e0cc45 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java @@ -12,6 +12,8 @@ import cgeo.geocaching.maps.interfaces.GeoPointImpl; import cgeo.geocaching.maps.interfaces.MapProvider; import cgeo.geocaching.maps.interfaces.OtherCachersOverlayItemImpl; +import org.mapsforge.android.maps.MapDatabase; + import android.app.Activity; import android.content.Context; import android.content.res.Resources; @@ -91,4 +93,8 @@ public class MapsforgeMapProvider implements MapProvider { return baseItem; } + public static boolean isValidMapFile(String mapFileIn) { + return MapDatabase.isValidMapFile(mapFileIn); + } + } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java index 78bcd54..aaede4d 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java @@ -1,6 +1,8 @@ package cgeo.geocaching.maps.mapsforge; +import cgeo.geocaching.R; import cgeo.geocaching.Settings; +import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.maps.CachesOverlay; import cgeo.geocaching.maps.OtherCachersOverlay; import cgeo.geocaching.maps.PositionOverlay; @@ -16,7 +18,6 @@ import cgeo.geocaching.maps.interfaces.OverlayImpl.overlayType; import cgeo.geocaching.utils.Log; import org.mapsforge.android.maps.GeoPoint; -import org.mapsforge.android.maps.MapDatabase; import org.mapsforge.android.maps.MapView; import org.mapsforge.android.maps.MapViewMode; import org.mapsforge.android.maps.Overlay; @@ -30,6 +31,7 @@ import android.util.AttributeSet; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; +import android.widget.Toast; public class MapsforgeMapView extends MapView implements MapViewImpl { private GestureDetector gestureDetector; @@ -49,7 +51,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { super.draw(canvas); } catch (Exception e) { - Log.e(Settings.tag, "MapsforgeMapView.draw: " + e.toString()); + Log.e("MapsforgeMapView.draw: " + e.toString()); } } @@ -70,6 +72,11 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } @Override + public Viewport getViewport() { + return new Viewport(getMapViewCenter(), getLatitudeSpan() / 1e6, getLongitudeSpan() / 1e6); + } + + @Override public void addOverlay(OverlayImpl ovl) { getOverlays().add((Overlay) ovl); } @@ -170,11 +177,14 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { setMapViewMode(MapViewMode.OPENCYCLEMAP_TILE_DOWNLOAD); break; case MapsforgeMapProvider.OFFLINE: - if (MapDatabase.isValidMapFile(Settings.getMapFile())) { - setMapViewMode(MapViewMode.CANVAS_RENDERER); - super.setMapFile(Settings.getMapFile()); - } else { - setMapViewMode(MapViewMode.MAPNIK_TILE_DOWNLOAD); + setMapViewMode(MapViewMode.CANVAS_RENDERER); + super.setMapFile(Settings.getMapFile()); + if (!Settings.isValidMapFile(Settings.getMapFile())) { + Toast.makeText( + getContext(), + getContext().getResources().getString(R.string.warn_invalid_mapfile), + Toast.LENGTH_LONG) + .show(); } break; default: @@ -196,7 +206,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } } catch (Exception e) { - Log.e(Settings.tag, "MapsforgeMapView.repaintRequired: " + e.toString()); + Log.e("MapsforgeMapView.repaintRequired: " + e.toString()); } } } diff --git a/main/src/cgeo/geocaching/network/Cookies.java b/main/src/cgeo/geocaching/network/Cookies.java new file mode 100644 index 0000000..68310e6 --- /dev/null +++ b/main/src/cgeo/geocaching/network/Cookies.java @@ -0,0 +1,47 @@ +package cgeo.geocaching.network; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.CookieStore; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.cookie.BasicClientCookie; + +public abstract class Cookies { + + private static boolean cookieStoreRestored = false; + final static CookieStore cookieStore = new BasicCookieStore(); + + public static void restoreCookieStore(final String oldCookies) { + if (!cookieStoreRestored) { + clearCookies(); + if (oldCookies != null) { + for (final String cookie : StringUtils.split(oldCookies, ';')) { + final String[] split = StringUtils.split(cookie, "=", 3); + if (split.length == 3) { + final BasicClientCookie newCookie = new BasicClientCookie(split[0], split[1]); + newCookie.setDomain(split[2]); + cookieStore.addCookie(newCookie); + } + } + } + cookieStoreRestored = true; + } + } + + public static String dumpCookieStore() { + StringBuilder cookies = new StringBuilder(); + for (final Cookie cookie : cookieStore.getCookies()) { + cookies.append(cookie.getName()); + cookies.append('='); + cookies.append(cookie.getValue()); + cookies.append('='); + cookies.append(cookie.getDomain()); + cookies.append(';'); + } + return cookies.toString(); + } + + public static void clearCookies() { + cookieStore.clear(); + } +} diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index 6cb4b86..b6be931 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -1,7 +1,6 @@ package cgeo.geocaching.network; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; import cgeo.geocaching.StoredList; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.files.LocalStorage; @@ -72,16 +71,16 @@ public class HtmlImage implements Html.ImageGetter { return new BitmapDrawable(getTransparent1x1Image()); } - Bitmap imagePre = onlySave ? null : loadImageFromStorage(url); + Bitmap imagePre = loadImageFromStorage(url); // Download image and save it to the cache - if (imagePre == null || onlySave) { + if (imagePre == null) { final String absoluteURL = makeAbsoluteURL(url); if (absoluteURL != null) { try { final File file = LocalStorage.getStorageFile(geocode, url, true, true); - final HttpResponse httpResponse = Network.request(absoluteURL, null, false, file); + final HttpResponse httpResponse = Network.getRequest(absoluteURL, null, file); if (httpResponse != null) { final int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode == 200) { @@ -91,7 +90,7 @@ public class HtmlImage implements Html.ImageGetter { } } } catch (Exception e) { - Log.e(Settings.tag, "HtmlImage.getDrawable (downloading from web)", e); + Log.e("HtmlImage.getDrawable (downloading from web)", e); } } } @@ -107,7 +106,7 @@ public class HtmlImage implements Html.ImageGetter { // get image and return if (imagePre == null) { - Log.d(Settings.tag, "HtmlImage.getDrawable: Failed to obtain image"); + Log.d("HtmlImage.getDrawable: Failed to obtain image"); if (returnErrorImage) { imagePre = BitmapFactory.decodeResource(context.getResources(), R.drawable.image_not_loaded); @@ -130,7 +129,7 @@ public class HtmlImage implements Html.ImageGetter { try { imagePre = Bitmap.createScaledBitmap(imagePre, width, height, true); } catch (Exception e) { - Log.d(Settings.tag, "HtmlImage.getDrawable: Failed to scale image"); + Log.d("HtmlImage.getDrawable: Failed to scale image"); return null; } } else { @@ -158,7 +157,7 @@ public class HtmlImage implements Html.ImageGetter { final File fileSec = LocalStorage.getStorageSecFile(geocode, url, true); return loadCachedImage(fileSec); } catch (Exception e) { - Log.w(Settings.tag, "HtmlImage.getDrawable (reading cache): " + e.toString()); + Log.w("HtmlImage.getDrawable (reading cache): " + e.toString()); } return null; } @@ -182,7 +181,7 @@ public class HtmlImage implements Html.ImageGetter { } } } catch (Exception e) { - Log.e(Settings.tag, "HtmlImage.makeAbsoluteURL (parse URL)", e); + Log.e("HtmlImage.makeAbsoluteURL (parse URL)", e); } return null; } @@ -207,7 +206,7 @@ public class HtmlImage implements Html.ImageGetter { fis = new FileInputStream(file); BitmapFactory.decodeStream(fis, null, options); } catch (FileNotFoundException e) { - Log.e(Settings.tag, "HtmlImage.setSampleSize", e); + Log.e("HtmlImage.setSampleSize", e); } finally { if (fis != null) { try { diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java index 502db33..bb5a949 100644 --- a/main/src/cgeo/geocaching/network/Network.java +++ b/main/src/cgeo/geocaching/network/Network.java @@ -1,13 +1,9 @@ package cgeo.geocaching.network; -import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; -import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.Log; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; import org.apache.http.HeaderElement; @@ -18,17 +14,13 @@ import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; import org.apache.http.NameValuePair; -import org.apache.http.client.CookieStore; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.cookie.Cookie; import org.apache.http.entity.HttpEntityWrapper; -import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.CoreConnectionPNames; import org.apache.http.params.CoreProtocolPNames; @@ -44,11 +36,10 @@ import android.net.Uri; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import java.util.List; import java.util.zip.GZIPInputStream; - public abstract class Network { static class GzipDecompressingEntity extends HttpEntityWrapper { @@ -76,8 +67,6 @@ public abstract class Network { private static final String PATTERN_PASSWORD = "(?<=[\\?&])[Pp]ass(w(or)?d)?=[^&#$]+"; private final static HttpParams clientParams = new BasicHttpParams(); - private static boolean cookieStoreRestored = false; - private final static CookieStore cookieStore = new BasicCookieStore(); static { Network.clientParams.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, HTTP.UTF_8); @@ -91,7 +80,7 @@ public abstract class Network { private static HttpClient getHttpClient() { final DefaultHttpClient client = new DefaultHttpClient(); - client.setCookieStore(cookieStore); + client.setCookieStore(Cookies.cookieStore); client.setParams(clientParams); client.addRequestInterceptor(new HttpRequestInterceptor() { @@ -117,7 +106,7 @@ public abstract class Network { HeaderElement[] codecs = ceheader.getElements(); for (int i = 0; i < codecs.length; i++) { if (codecs[i].getName().equalsIgnoreCase("gzip")) { - Log.d(Settings.tag, "Decompressing response"); + Log.d("Decompressing response"); response.setEntity( new Network.GzipDecompressingEntity(response.getEntity())); return; @@ -132,40 +121,6 @@ public abstract class Network { return client; } - public static void restoreCookieStore(final String oldCookies) { - if (!cookieStoreRestored) { - Network.clearCookies(); - if (oldCookies != null) { - for (final String cookie : StringUtils.split(oldCookies, ';')) { - final String[] split = StringUtils.split(cookie, "=", 3); - if (split.length == 3) { - final BasicClientCookie newCookie = new BasicClientCookie(split[0], split[1]); - newCookie.setDomain(split[2]); - cookieStore.addCookie(newCookie); - } - } - } - cookieStoreRestored = true; - } - } - - public static String dumpCookieStore() { - StringBuilder cookies = new StringBuilder(); - for (final Cookie cookie : cookieStore.getCookies()) { - cookies.append(cookie.getName()); - cookies.append('='); - cookies.append(cookie.getValue()); - cookies.append('='); - cookies.append(cookie.getDomain()); - cookies.append(';'); - } - return cookies.toString(); - } - - public static void clearCookies() { - cookieStore.clear(); - } - /** * POST HTTP request * @@ -173,117 +128,148 @@ public abstract class Network { * @param params * @return */ - public static HttpResponse postRequest(final String uri, final List<? extends NameValuePair> params) { - try { - HttpPost request = new HttpPost(uri); - if (params != null) { - request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); - } - request.setHeader("X-Requested-With", "XMLHttpRequest"); - return Network.request(request); - } catch (Exception e) { - // Can be UnsupportedEncodingException, ClientProtocolException or IOException - Log.e(Settings.tag, "postRequest", e); - return null; - } - } - - /** - * GET HTTP request - * - * @param uri - * @param params - * @param xContentType - * @param my - * @param addF - * @return - */ - public static HttpResponse request(final String uri, final Parameters params, boolean xContentType, boolean my, boolean addF) { - return Network.request(uri, cgBase.addFToParams(params, my, addF), xContentType); + public static HttpResponse postRequest(final String uri, final Parameters params) { + return request("POST", uri, params, null, null); } /** - * GET HTTP request + * Make an HTTP request * + * @param method + * the HTTP method to use ("GET" or "POST") * @param uri + * the URI to request * @param params - * @param xContentType + * the parameters to add the the GET request + * @param headers + * the headers to add to the GET request * @param cacheFile - * the name of the file storing the cached resource, or null not to use one - * @return + * the cache file used to cache this query + * @return the HTTP response, or null in case of an encoding error in a POST request arguments */ - public static HttpResponse request(final String uri, final Parameters params, final boolean xContentType, final File cacheFile) { - final String fullUri = params == null ? uri : Uri.parse(uri).buildUpon().encodedQuery(params.toString()).build().toString(); - final HttpRequestBase request = new HttpGet(fullUri); + private static HttpResponse request(final String method, final String uri, final Parameters params, final Parameters headers, final File cacheFile) { + HttpRequestBase request; + if (method.equals("GET")) { + final String fullUri = params == null ? uri : Uri.parse(uri).buildUpon().encodedQuery(params.toString()).build().toString(); + request = new HttpGet(fullUri); + } else { + request = new HttpPost(uri); + if (params != null) { + try { + ((HttpPost) request).setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); + } catch (final UnsupportedEncodingException e) { + Log.e("request", e); + return null; + } + } + } - request.setHeader("X-Requested-With", "XMLHttpRequest"); + for (final NameValuePair header : Parameters.extend(Parameters.merge(headers, cacheHeaders(cacheFile)), + "Accept-Charset", "utf-8,iso-8859-1;q=0.8,utf-16;q=0.8,*;q=0.7", + "Accept-Language", "en-US,*;q=0.9", + "X-Requested-With", "XMLHttpRequest")) { + request.setHeader(header.getName(), header.getValue()); + } + + request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, Network.USER_AGENT); - if (xContentType) { - request.setHeader("Content-Type", "application/x-www-form-urlencoded"); + final String reqLogStr = request.getMethod() + " " + Network.hidePassword(request.getURI().toString()); + Log.d(reqLogStr); + + final HttpClient client = Network.getHttpClient(); + for (int i = 0; i <= Network.NB_DOWNLOAD_RETRIES; i++) { + final long before = System.currentTimeMillis(); + try { + final HttpResponse response = client.execute(request); + int status = response.getStatusLine().getStatusCode(); + if (status == 200) { + Log.d(status + Network.formatTimeSpan(before) + reqLogStr); + } else { + Log.w(status + " [" + response.getStatusLine().getReasonPhrase() + "]" + Network.formatTimeSpan(before) + reqLogStr); + } + return response; + } catch (IOException e) { + final String timeSpan = Network.formatTimeSpan(before); + final String tries = (i + 1) + "/" + (Network.NB_DOWNLOAD_RETRIES + 1); + if (i == Network.NB_DOWNLOAD_RETRIES) { + Log.e("Failure " + tries + timeSpan + reqLogStr, e); + } else { + Log.e("Failure " + tries + " (" + e.toString() + ")" + timeSpan + "- retrying " + reqLogStr); + } + } } + return null; + } + + private static Parameters cacheHeaders(final File cacheFile) { if (cacheFile != null && cacheFile.exists()) { final String etag = LocalStorage.getSavedHeader(cacheFile, "etag"); if (etag != null) { - request.setHeader("If-None-Match", etag); + return new Parameters("If-None-Match", etag); } else { final String lastModified = LocalStorage.getSavedHeader(cacheFile, "last-modified"); if (lastModified != null) { - request.setHeader("If-Modified-Since", lastModified); + return new Parameters("If-Modified-Since", lastModified); } } } - - return Network.request(request); + return null; } /** * GET HTTP request * * @param uri + * the URI to request * @param params - * @param xContentType - * @return + * the parameters to add the the GET request + * @param cacheFile + * the name of the file storing the cached resource, or null not to use one + * @return the HTTP response */ - public static HttpResponse request(final String uri, final Parameters params, final boolean xContentType) { - return request(uri, params, xContentType, null); + public static HttpResponse getRequest(final String uri, final Parameters params, final File cacheFile) { + return request("GET", uri, params, null, cacheFile); } - public static HttpResponse request(final HttpRequestBase request) { - request.setHeader("Accept-Charset", "utf-8,iso-8859-1;q=0.8,utf-16;q=0.8,*;q=0.7"); - request.setHeader("Accept-Language", "en-US,*;q=0.9"); - request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, USER_AGENT); - return Network.doRequest(request); - } - private static HttpResponse doRequest(final HttpRequestBase request) { - final String reqLogStr = request.getMethod() + " " + hidePassword(request.getURI().toString()); - Log.d(Settings.tag, reqLogStr); + /** + * GET HTTP request + * + * @param uri + * the URI to request + * @param params + * the parameters to add the the GET request + * @return the HTTP response + */ + public static HttpResponse getRequest(final String uri, final Parameters params) { + return request("GET", uri, params, null, null); + } - final HttpClient client = getHttpClient(); - for (int i = 0; i <= NB_DOWNLOAD_RETRIES; i++) { - final long before = System.currentTimeMillis(); - try { - final HttpResponse response = client.execute(request); - int status = response.getStatusLine().getStatusCode(); - if (status == 200) { - Log.d(Settings.tag, status + Network.formatTimeSpan(before) + reqLogStr); - } else { - Log.w(Settings.tag, status + " [" + response.getStatusLine().getReasonPhrase() + "]" + Network.formatTimeSpan(before) + reqLogStr); - } - return response; - } catch (IOException e) { - final String timeSpan = Network.formatTimeSpan(before); - final String tries = (i + 1) + "/" + (NB_DOWNLOAD_RETRIES + 1); - if (i == NB_DOWNLOAD_RETRIES) { - Log.e(Settings.tag, "Failure " + tries + timeSpan + reqLogStr, e); - } else { - Log.e(Settings.tag, "Failure " + tries + " (" + e.toString() + ")" + timeSpan + "- retrying " + reqLogStr); - } - } - } + /** + * GET HTTP request + * + * @param uri + * the URI to request + * @param params + * the parameters to add the the GET request + * @param headers + * the headers to add to the GET request + * @return the HTTP response + */ + public static HttpResponse getRequest(final String uri, final Parameters params, final Parameters headers) { + return request("GET", uri, params, headers, null); + } - return null; + /** + * GET HTTP request + * + * @param uri + * the URI to request + * @return the HTTP response + */ + public static HttpResponse getRequest(final String uri) { + return request("GET", uri, null, null, null); } private static String formatTimeSpan(final long before) { @@ -296,33 +282,24 @@ public abstract class Network { } public static JSONObject requestJSON(final String uri, final Parameters params) { - final HttpGet request = new HttpGet(Network.prepareParameters(uri, params)); - request.setHeader("Accept", "application/json, text/javascript, */*; q=0.01"); - request.setHeader("Content-Type", "application/json; charset=UTF-8"); - request.setHeader("X-Requested-With", "XMLHttpRequest"); - - final HttpResponse response = doRequest(request); - if (response != null && response.getStatusLine().getStatusCode() == 200) { + final HttpResponse response = request("GET", uri, params, new Parameters("Accept", "application/json, text/javascript, */*; q=0.01"), null); + if (isSuccess(response)) { try { return new JSONObject(Network.getResponseData(response)); - } catch (JSONException e) { - Log.e(Settings.tag, "Network.requestJSON", e); + } catch (final JSONException e) { + Log.e("Network.requestJSON", e); } } return null; } - private static String prepareParameters(final String baseUri, final Parameters params) { - return CollectionUtils.isNotEmpty(params) ? baseUri + "?" + params.toString() : baseUri; - } - private static String getResponseDataNoError(final HttpResponse response, boolean replaceWhitespace) { try { String data = EntityUtils.toString(response.getEntity(), HTTP.UTF_8); return replaceWhitespace ? BaseUtils.replaceWhitespace(data) : data; } catch (Exception e) { - Log.e(Settings.tag, "getResponseData", e); + Log.e("getResponseData", e); return null; } } @@ -331,59 +308,13 @@ public abstract class Network { return Network.getResponseData(response, true); } - static public String getResponseData(final HttpResponse response, boolean replaceWhitespace) { + public static String getResponseData(final HttpResponse response, boolean replaceWhitespace) { if (!isSuccess(response)) { return null; } return getResponseDataNoError(response, replaceWhitespace); } - /** - * POST HTTP request. Do the request a second time if the user is not logged in - * - * @param uri - * @return - */ - public static String postRequestLogged(final String uri) { - HttpResponse response = postRequest(uri, null); - String data = getResponseData(response); - - if (!Login.getLoginStatus(data)) { - if (Login.login() == StatusCode.NO_ERROR) { - response = postRequest(uri, null); - data = getResponseData(response); - } else { - Log.i(Settings.tag, "Working as guest."); - } - } - return data; - } - - /** - * GET HTTP request. Do the request a second time if the user is not logged in - * - * @param uri - * @param params - * @param xContentType - * @param my - * @param addF - * @return - */ - public static String requestLogged(final String uri, final Parameters params, boolean xContentType, boolean my, boolean addF) { - HttpResponse response = request(uri, params, xContentType, my, addF); - String data = getResponseData(response); - - if (!Login.getLoginStatus(data)) { - if (Login.login() == StatusCode.NO_ERROR) { - response = request(uri, params, xContentType, my, addF); - data = getResponseData(response); - } else { - Log.i(Settings.tag, "Working as guest."); - } - } - return data; - } - public static String urlencode_rfc3986(String text) { return StringUtils.replace(URLEncoder.encode(text).replace("+", "%20"), "%7E", "~"); } diff --git a/main/src/cgeo/geocaching/network/Parameters.java b/main/src/cgeo/geocaching/network/Parameters.java index e65bec2..5c0328a 100644 --- a/main/src/cgeo/geocaching/network/Parameters.java +++ b/main/src/cgeo/geocaching/network/Parameters.java @@ -12,7 +12,7 @@ import java.util.Comparator; /** * List of key/values pairs to be used in a GET or POST request. - * + * */ public class Parameters extends ArrayList<NameValuePair> { @@ -44,14 +44,16 @@ public class Parameters extends ArrayList<NameValuePair> { * list of key/value pairs * @throws InvalidParameterException * if the number of key/values is unbalanced + * @return the object itself to facilitate chaining */ - public void put(final String... keyValues) { + public Parameters put(final String... keyValues) { if (keyValues.length % 2 == 1) { throw new InvalidParameterException("odd number of parameters"); } for (int i = 0; i < keyValues.length; i += 2) { add(new BasicNameValuePair(keyValues[i], keyValues[i + 1])); } + return this; } /** @@ -63,12 +65,46 @@ public class Parameters extends ArrayList<NameValuePair> { Collections.sort(this, comparator); } - /** - * @return the URL encoded string corresponding to those parameters - */ @Override public String toString() { return URLEncodedUtils.format(this, HTTP.UTF_8); } + /** + * Extend or create a Parameters object with new key/value pairs. + * + * @param params + * an existing object or null to create a new one + * @param keyValues + * list of key/value pair + * @throws InvalidParameterException + * if the number of key/values is unbalanced + * @return the object itself if it is non-null, a new one otherwise + */ + public static Parameters extend(final Parameters params, final String... keyValues) { + if (params == null) { + return new Parameters(keyValues); + } else { + return params.put(keyValues); + } + } + + /** + * Merge two (possibly null) Parameters object. + * + * @param params + * the object to merge into if non-null + * @param extra + * the object to merge from if non-null + * @return params with extra data if params was non-null, extra otherwise + */ + public static Parameters merge(final Parameters params, final Parameters extra) { + if (params == null) { + return extra; + } else if (extra != null) { + params.addAll(extra); + } + return params; + } + } diff --git a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java index f008528..9c3f15b 100644 --- a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java +++ b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java @@ -1,7 +1,6 @@ package cgeo.geocaching.sorting; import cgeo.geocaching.cgCache; -import cgeo.geocaching.Settings; import cgeo.geocaching.utils.Log; @@ -20,7 +19,7 @@ public abstract class AbstractCacheComparator implements CacheComparator { } return compareCaches(cache1, cache2); } catch (Exception e) { - Log.e(Settings.tag, "AbstractCacheComparator.compare: " + e.toString()); + Log.e("AbstractCacheComparator.compare: " + e.toString()); } return 0; } diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java index 0696cf1..4a10046 100644 --- a/main/src/cgeo/geocaching/twitter/Twitter.java +++ b/main/src/cgeo/geocaching/twitter/Twitter.java @@ -38,12 +38,12 @@ public final class Twitter { OAuth.signOAuth("api.twitter.com", "/1/statuses/update.json", "POST", false, parameters, Settings.getTokenPublic(), Settings.getTokenSecret()); final HttpResponse httpResponse = Network.postRequest("http://api.twitter.com/1/statuses/update.json", parameters); if (httpResponse != null && httpResponse.getStatusLine().getStatusCode() == 200) { - Log.i(Settings.tag, "Tweet posted"); + Log.i("Tweet posted"); } else { - Log.e(Settings.tag, "Tweet could not be posted"); + Log.e("Tweet could not be posted"); } } catch (Exception e) { - Log.e(Settings.tag, "cgBase.postTweet: " + e.toString()); + Log.e("cgBase.postTweet: " + e.toString()); } } diff --git a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java index c9710e9..86db2d2 100644 --- a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java @@ -141,7 +141,7 @@ public class TwitterAuthorizationActivity extends AbstractActivity { try { final Parameters params = new Parameters(); OAuth.signOAuth(host, pathRequest, method, true, params, null, null); - final String line = Network.getResponseData(Network.request("https://" + host + pathRequest, params, false)); + final String line = Network.getResponseData(Network.getRequest("https://" + host + pathRequest, params)); if (StringUtils.isNotBlank(line)) { @@ -164,12 +164,12 @@ public class TwitterAuthorizationActivity extends AbstractActivity { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://" + host + pathAuthorize + "?" + encodedParams))); status = 1; } catch (Exception e) { - Log.e(Settings.tag, "TwitterAuthorizationActivity.requestToken(2): " + e.toString()); + Log.e("TwitterAuthorizationActivity.requestToken(2): " + e.toString()); } } } } catch (Exception e) { - Log.e(Settings.tag, "TwitterAuthorizationActivity.requestToken(1): " + e.toString()); + Log.e("TwitterAuthorizationActivity.requestToken(1): " + e.toString()); } requestTokenHandler.sendEmptyMessage(status); @@ -209,7 +209,7 @@ public class TwitterAuthorizationActivity extends AbstractActivity { status = 1; } } catch (Exception e) { - Log.e(Settings.tag, "TwitterAuthorizationActivity.changeToken: " + e.toString()); + Log.e("TwitterAuthorizationActivity.changeToken: " + e.toString()); } changeTokensHandler.sendEmptyMessage(status); diff --git a/main/src/cgeo/geocaching/ui/AddressListAdapter.java b/main/src/cgeo/geocaching/ui/AddressListAdapter.java index e557882..34e751f 100644 --- a/main/src/cgeo/geocaching/ui/AddressListAdapter.java +++ b/main/src/cgeo/geocaching/ui/AddressListAdapter.java @@ -56,7 +56,7 @@ public class AddressListAdapter extends ArrayAdapter<Address> { @Override public void onClick(View v) { Activity activity = (Activity) v.getContext(); - cgeocaches.startActivityAddress(activity, address.getLatitude(), address.getLongitude(), StringUtils.defaultString(address.getAddressLine(0))); + cgeocaches.startActivityAddress(activity, new Geopoint(address.getLatitude(), address.getLongitude()), StringUtils.defaultString(address.getAddressLine(0))); activity.finish(); } }); diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java index 6c03889..54f4505 100644 --- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java +++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java @@ -3,7 +3,6 @@ package cgeo.geocaching.ui; import cgeo.geocaching.CacheDetailActivity; import cgeo.geocaching.R; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.enumerations.CacheListType; import cgeo.geocaching.enumerations.CacheSize; @@ -20,7 +19,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.HashCodeBuilder; import android.app.Activity; -import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -195,17 +193,6 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { notifyDataSetChanged(); } - public void clearFilter() { - if (originalList != null) { - list.clear(); - list.addAll(originalList); - - currentFilter = null; - } - - notifyDataSetChanged(); - } - public boolean isFilter() { return currentFilter != null; } @@ -375,7 +362,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { } if (position > getCount()) { - Log.w(Settings.tag, "CacheListAdapter.getView: Attempt to access missing item #" + position); + Log.w("CacheListAdapter.getView: Attempt to access missing item #" + position); return null; } @@ -590,8 +577,8 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { if (cacheListType == CacheListType.HISTORY && cache.getVisitedDate() > 0) { ArrayList<String> infos = new ArrayList<String>(); infos.add(StringUtils.upperCase(cache.getGeocode())); - infos.add(cgBase.formatDate(cache.getVisitedDate())); - infos.add(cgBase.formatTime(cache.getVisitedDate())); + infos.add(Formatter.formatDate(cache.getVisitedDate())); + infos.add(Formatter.formatTime(cache.getVisitedDate())); holder.info.setText(StringUtils.join(infos, Formatter.SEPARATOR)); } else { ArrayList<String> infos = new ArrayList<String>(); @@ -609,7 +596,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { if (cache.getSize() != CacheSize.UNKNOWN && cache.showSize()) { infos.add(cache.getSize().getL10n()); } else if (cache.isEventCache() && cache.getHiddenDate() != null) { - infos.add(cgBase.formatShortDate(cache.getHiddenDate().getTime())); + infos.add(Formatter.formatShortDate(cache.getHiddenDate().getTime())); } if (cache.isPremiumMembersOnly()) { @@ -699,10 +686,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { } // load cache details - Intent cachesIntent = new Intent(getContext(), CacheDetailActivity.class); - cachesIntent.putExtra("geocode", geocode); - cachesIntent.putExtra("name", name); - getContext().startActivity(cachesIntent); + CacheDetailActivity.startActivity(getContext(), geocode, name); } // long tap on item @@ -781,7 +765,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { return true; } } catch (Exception e) { - Log.w(Settings.tag, "CacheListAdapter.detectGesture.onFling: " + e.toString()); + Log.w("CacheListAdapter.detectGesture.onFling: " + e.toString()); } return false; diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java index 7f6f792..d9e0bfe 100644 --- a/main/src/cgeo/geocaching/ui/CompassView.java +++ b/main/src/cgeo/geocaching/ui/CompassView.java @@ -1,7 +1,6 @@ package cgeo.geocaching.ui; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; import cgeo.geocaching.utils.Log; import android.content.Context; @@ -58,7 +57,7 @@ public class CompassView extends View { try { invalidate(); } catch (Exception e) { - Log.e(Settings.tag, "CompassView.changeHandler: " + e.toString()); + Log.e("CompassView.changeHandler: " + e.toString()); } } }; diff --git a/main/src/cgeo/geocaching/ui/DirectionImage.java b/main/src/cgeo/geocaching/ui/DirectionImage.java index aa01b97..b246718 100644 --- a/main/src/cgeo/geocaching/ui/DirectionImage.java +++ b/main/src/cgeo/geocaching/ui/DirectionImage.java @@ -17,7 +17,7 @@ public class DirectionImage { } final HttpResponse httpResponse = - Network.request("http://www.geocaching.com/ImgGen/seek/CacheDir.ashx", new Parameters("k", code), false); + Network.getRequest("http://www.geocaching.com/ImgGen/seek/CacheDir.ashx", new Parameters("k", code)); if (httpResponse != null) { LocalStorage.saveEntityToFile(httpResponse, getDirectionFile(geocode, true)); } diff --git a/main/src/cgeo/geocaching/ui/Formatter.java b/main/src/cgeo/geocaching/ui/Formatter.java index 661a9a0..6ee1a65 100644 --- a/main/src/cgeo/geocaching/ui/Formatter.java +++ b/main/src/cgeo/geocaching/ui/Formatter.java @@ -1,8 +1,80 @@ package cgeo.geocaching.ui; -public interface Formatter { +import cgeo.geocaching.cgeoapplication; + +import android.content.Context; +import android.text.format.DateUtils; + +public abstract class Formatter { /** Text separator used for formatting texts */ public static final String SEPARATOR = " ยท "; + private static final Context context = cgeoapplication.getInstance().getBaseContext(); + + /** + * Generate a time string according to system-wide settings (locale, 12/24 hour) + * such as "13:24". + * + * @param date + * milliseconds since the epoch + * @return the formatted string + */ + public static String formatTime(long date) { + return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_TIME); + } + + /** + * Generate a date string according to system-wide settings (locale, date format) + * such as "20 December" or "20 December 2010". The year will only be included when necessary. + * + * @param date + * milliseconds since the epoch + * @return the formatted string + */ + public static String formatDate(long date) { + return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE); + } + + /** + * Generate a date string according to system-wide settings (locale, date format) + * such as "20 December 2010". The year will always be included, making it suitable + * to generate long-lived log entries. + * + * @param date + * milliseconds since the epoch + * @return the formatted string + */ + public static String formatFullDate(long date) { + return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE + | DateUtils.FORMAT_SHOW_YEAR); + } + + /** + * Generate a numeric date string according to system-wide settings (locale, date format) + * such as "10/20/2010". + * + * @param date + * milliseconds since the epoch + * @return the formatted string + */ + public static String formatShortDate(long date) { + return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE + | DateUtils.FORMAT_NUMERIC_DATE); + } + + /** + * Generate a numeric date and time string according to system-wide settings (locale, + * date format) such as "7 sept. at 12:35". + * + * @param context + * a Context + * @param date + * milliseconds since the epoch + * @return the formatted string + */ + public static String formatShortDateTime(Context context, long date) { + return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL); + } + } diff --git a/main/src/cgeo/geocaching/ui/GPXListAdapter.java b/main/src/cgeo/geocaching/ui/GPXListAdapter.java index 5a58840..aa2234a 100644 --- a/main/src/cgeo/geocaching/ui/GPXListAdapter.java +++ b/main/src/cgeo/geocaching/ui/GPXListAdapter.java @@ -1,7 +1,6 @@ package cgeo.geocaching.ui; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; import cgeo.geocaching.cgeogpxes; import cgeo.geocaching.files.GPXImporter; import cgeo.geocaching.utils.Log; @@ -34,7 +33,7 @@ public class GPXListAdapter extends ArrayAdapter<File> { } if (position > getCount()) { - Log.w(Settings.tag, "cgGPXListAdapter.getView: Attempt to access missing item #" + position); + Log.w("cgGPXListAdapter.getView: Attempt to access missing item #" + position); return null; } diff --git a/main/src/cgeo/geocaching/ui/MapfileListAdapter.java b/main/src/cgeo/geocaching/ui/MapfileListAdapter.java index c4720d5..e7380f0 100644 --- a/main/src/cgeo/geocaching/ui/MapfileListAdapter.java +++ b/main/src/cgeo/geocaching/ui/MapfileListAdapter.java @@ -1,7 +1,6 @@ package cgeo.geocaching.ui; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; import cgeo.geocaching.cgSelectMapfile; import cgeo.geocaching.utils.Log; @@ -35,7 +34,7 @@ public class MapfileListAdapter extends ArrayAdapter<File> { } if (position > getCount()) { - Log.w(Settings.tag, "cgGPXListAdapter.getView: Attempt to access missing item #" + position); + Log.w("cgGPXListAdapter.getView: Attempt to access missing item #" + position); return null; } diff --git a/main/src/cgeo/geocaching/utils/BaseUtils.java b/main/src/cgeo/geocaching/utils/BaseUtils.java index 44c35a1..d468fc9 100644 --- a/main/src/cgeo/geocaching/utils/BaseUtils.java +++ b/main/src/cgeo/geocaching/utils/BaseUtils.java @@ -3,8 +3,6 @@ */ package cgeo.geocaching.utils; -import java.util.ArrayList; -import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -84,17 +82,6 @@ public final class BaseUtils { return BaseUtils.getMatch(data, p, true, 1, defaultValue, false); } - public static List<String> getMatches(final String data, final Pattern p, int count) { - ArrayList<String> result = new ArrayList<String>(); - final Matcher matcher = p.matcher(data); - while (matcher.find()) { - for (int i = 0; i < count; i++) { - result.add(matcher.group(i)); - } - } - return result; - } - /** * Searches for the pattern p in the data. * diff --git a/main/src/cgeo/geocaching/utils/BoundedList.java b/main/src/cgeo/geocaching/utils/BoundedList.java deleted file mode 100644 index 3fa1112..0000000 --- a/main/src/cgeo/geocaching/utils/BoundedList.java +++ /dev/null @@ -1,46 +0,0 @@ -package cgeo.geocaching.utils; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * Base class for a limited list. - * - * @author blafoo - */ -public class BoundedList<T> extends ArrayList<T> { - - private static final long serialVersionUID = -5077882607489806620L; - private final int maxEntries; - - public BoundedList(int maxEntries) { - this.maxEntries = maxEntries; - } - - private void removeElements(int count) { - for (int i = 0; i < count; i++) { - this.remove(0); - } - } - - @Override - public boolean add(T item) { - removeElements(this.size() + 1 - maxEntries); - return super.add(item); - } - - @Override - public boolean addAll(Collection<? extends T> collection) { - if (collection.size() > this.size()) { - this.clear(); - for (T item : collection) { - this.add(item); - } - return false; - } else { - removeElements(this.size() + collection.size() - maxEntries); - return super.addAll(collection); - } - } - -} diff --git a/main/src/cgeo/geocaching/utils/CancellableHandler.java b/main/src/cgeo/geocaching/utils/CancellableHandler.java index d4915eb..8cf8f28 100644 --- a/main/src/cgeo/geocaching/utils/CancellableHandler.java +++ b/main/src/cgeo/geocaching/utils/CancellableHandler.java @@ -1,5 +1,7 @@ package cgeo.geocaching.utils; +import cgeo.geocaching.cgeoapplication; + import android.os.Handler; import android.os.Message; @@ -9,6 +11,7 @@ import android.os.Message; */ public abstract class CancellableHandler extends Handler { + protected static final int UPDATE_LOAD_PROGRESS_DETAIL = 42186; private volatile boolean cancelled = false; private static class CancelHolder { @@ -109,4 +112,9 @@ public abstract class CancellableHandler extends Handler { return handler != null && handler.isCancelled(); } + public static void sendLoadProgressDetail(final Handler handler, final int resourceId) { + if (null != handler) { + handler.obtainMessage(UPDATE_LOAD_PROGRESS_DETAIL, cgeoapplication.getInstance().getString(resourceId)).sendToTarget(); + } + } } diff --git a/main/src/cgeo/geocaching/utils/CryptUtils.java b/main/src/cgeo/geocaching/utils/CryptUtils.java index 87b37c4..f04327e 100644 --- a/main/src/cgeo/geocaching/utils/CryptUtils.java +++ b/main/src/cgeo/geocaching/utils/CryptUtils.java @@ -1,6 +1,5 @@ package cgeo.geocaching.utils; -import cgeo.geocaching.Settings; import android.text.Spannable; import android.text.SpannableStringBuilder; @@ -74,7 +73,7 @@ public final class CryptUtils { digest.update(text.getBytes(), 0, text.length()); hashed = new BigInteger(1, digest.digest()).toString(16); } catch (Exception e) { - Log.e(Settings.tag, "cgBase.md5: " + e.toString()); + Log.e("cgBase.md5: " + e.toString()); } return hashed; @@ -88,7 +87,7 @@ public final class CryptUtils { digest.update(text.getBytes(), 0, text.length()); hashed = new BigInteger(1, digest.digest()).toString(16); } catch (Exception e) { - Log.e(Settings.tag, "cgBase.sha1: " + e.toString()); + Log.e("cgBase.sha1: " + e.toString()); } return hashed; @@ -103,7 +102,7 @@ public final class CryptUtils { mac.init(secretKeySpec); macBytes = mac.doFinal(text.getBytes()); } catch (Exception e) { - Log.e(Settings.tag, "cgBase.hashHmac: " + e.toString()); + Log.e("cgBase.hashHmac: " + e.toString()); } return macBytes; @@ -136,49 +135,6 @@ public final class CryptUtils { return buffer; } - public static byte[] base64Decode(String text) { - char[] in = text.toCharArray(); - - int iLen = in.length; - if (iLen % 4 != 0) { - throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4."); - } - while (iLen > 0 && in[iLen - 1] == '=') { - iLen--; - } - int oLen = (iLen * 3) / 4; - byte[] out = new byte[oLen]; - int ip = 0; - int op = 0; - while (ip < iLen) { - int i0 = in[ip++]; - int i1 = in[ip++]; - int i2 = ip < iLen ? in[ip++] : 'A'; - int i3 = ip < iLen ? in[ip++] : 'A'; - if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) { - throw new IllegalArgumentException("Illegal character in Base64 encoded data."); - } - int b0 = base64map2[i0]; - int b1 = base64map2[i1]; - int b2 = base64map2[i2]; - int b3 = base64map2[i3]; - if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) { - throw new IllegalArgumentException("Illegal character in Base64 encoded data."); - } - int o0 = (b0 << 2) | (b1 >>> 4); - int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); - int o2 = ((b2 & 3) << 6) | b3; - out[op++] = (byte) o0; - if (op < oLen) { - out[op++] = (byte) o1; - } - if (op < oLen) { - out[op++] = (byte) o2; - } - } - return out; - } - public static String base64Encode(byte[] in) { int iLen = in.length; int oDataLen = (iLen * 4 + 2) / 3; // output length without padding diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedCache.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedCache.java deleted file mode 100644 index 6d18cf5..0000000 --- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedCache.java +++ /dev/null @@ -1,24 +0,0 @@ -package cgeo.geocaching.utils; - -import java.util.LinkedHashMap; - -/** - * Base class for a caching cache. Don't mix up with a geocache ! - * - * @author blafoo - */ -public class LeastRecentlyUsedCache<K, V> extends LinkedHashMap<K, V> { - - private static final long serialVersionUID = -5077882607489806620L; - private final int maxEntries; - - public LeastRecentlyUsedCache(int maxEntries) { - this.maxEntries = maxEntries; - } - - @Override - protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) { - return size() > maxEntries; - } - -} diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java new file mode 100644 index 0000000..5628a4b --- /dev/null +++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java @@ -0,0 +1,139 @@ +package cgeo.geocaching.utils; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Base class for caching objects. Don't mix up with a geocache ! + * + * The LeastRecentlyUsedMap is basically a LinkedHashMap which can be configured to have certain modes of operation: + * <ul> + * <li> LRU_CACHE means that the elements are updated in the LinkedList on every get() access, + * so the objects that are dropped are the ones that haven't been used the longest</li> + * <li> BOUNDED means that objects are updated only when they are put, + * so the objects that are dropped are the ones that haven't been written the longest</li> + * </ul> + * + * @author blafoo + * @author Teschi + */ +public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { + + private static enum OperationModes { + LRU_CACHE, BOUNDED + } + + private static final long serialVersionUID = -5077882607489806620L; + + private final int maxEntries; + private final OperationModes opMode; + private RemoveHandler<V> removeHandler; + + // store the HashMap parameters for serialization, as we can't access the originals in the LinkedHashMap + final int initialCapacity; + final float loadFactor; + + protected LeastRecentlyUsedMap(int maxEntries, int initialCapacity, float loadFactor, OperationModes opMode) { + super(initialCapacity, loadFactor, (opMode==OperationModes.LRU_CACHE)); + this.initialCapacity = initialCapacity; + this.loadFactor = loadFactor; + this.maxEntries = maxEntries; + this.opMode = opMode; + } + + protected LeastRecentlyUsedMap(int maxEntries, OperationModes opMode) { + this(maxEntries, 16, 0.75f, opMode); + } + + @Override + public V put(K key, V value) { + // in case the underlying Map is not running with accessOrder==true, the map won't notice any changes + // of existing keys, so for the normal BOUNDED mode we remove and put the value to get its order updated. + if (opMode == OperationModes.BOUNDED && containsKey(key)) { + // avoid trigger the remove notification + final V oldVal = super.remove(key); + put(key, value); + return oldVal; + } else { + return super.put(key, value); + } + } + + @Override + protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { + return size() > maxEntries; + } + + public int getMaxEntries() { + return maxEntries; + } + + @Override + public V remove(Object key) { + + V removed = super.remove(key); + + if (removed != null && removeHandler != null) { + removeHandler.onRemove(removed); + } + + return removed; + } + + /** + * Sets a handler for remove notifications. Currently only one handler + * instance is supported + * + * @param removeHandler + * The new handler to receive notifications or null to remove a handler + */ + public void setRemoveHandler(RemoveHandler<V> removeHandler) { + this.removeHandler = removeHandler; + } + + public static class LruCache<K, V> extends LeastRecentlyUsedMap<K, V> { + private static final long serialVersionUID = 9028478916221334454L; + + public LruCache(int maxEntries, int initialCapacity, float loadFactor) { + super(maxEntries, initialCapacity, loadFactor, OperationModes.LRU_CACHE); + } + + public LruCache(int maxEntries) { + super(maxEntries, OperationModes.LRU_CACHE); + } + } + + public static class Bounded<K, V> extends LeastRecentlyUsedMap<K, V> { + + private static final long serialVersionUID = -1476389304214398315L; + + public Bounded(int maxEntries, int initialCapacity, float loadFactor) { + super(maxEntries, initialCapacity, loadFactor, OperationModes.BOUNDED); + } + + public Bounded(int maxEntries) { + super(maxEntries, OperationModes.BOUNDED); + } + } + + /** + * Interface for handlers that wish to get notified when items are + * removed from the LRUMap + * + * @author rsudev + * + * @param <V> + */ + public interface RemoveHandler<V> { + + /** + * Method will be called on remove + * + * @param removed + * Item that has been removed + */ + void onRemove(V removed); + + } + +} diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java new file mode 100644 index 0000000..eea7a11 --- /dev/null +++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java @@ -0,0 +1,198 @@ +package cgeo.geocaching.utils; + +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; + +/** + * Synchronized set wrapper for the LeastRecentlyUsedMap. + * + * This code is heavily based on the HashSet code that represent Map as a Set. + * Unfortunately HashSet does not allow to use a custom Map as its Storage. + * Therefore overriding removeEldestEntry() is impossible for a normal LinkedHashSet. + * + * Synchronization is added to guard against concurrent modification. Iterator + * access has to be guarded externally or the synchronized getAsList method can be used + * to get a clone for iteration + * + * @author Teschi + */ +public class LeastRecentlyUsedSet<E> extends AbstractSet<E> + implements Cloneable, java.io.Serializable { + + private static final long serialVersionUID = -1942301031191419547L; + + private transient LeastRecentlyUsedMap<E, Object> map; + private static final Object PRESENT = new Object(); + + public LeastRecentlyUsedSet(int maxEntries, int initialCapacity, float loadFactor) { + // because we don't use any Map.get() methods from the Set, BOUNDED and LRU_CACHE have the exact same Behaviour + // So we useLRU_CACHE mode because it should perform a bit better (as it doesn't re-add explicitly) + map = new LeastRecentlyUsedMap.LruCache<E, Object>(maxEntries, initialCapacity, loadFactor); + } + + public LeastRecentlyUsedSet(int maxEntries) { + map = new LeastRecentlyUsedMap.LruCache<E, Object>(maxEntries); + } + + /** + * Copy of the HashSet code if iterator() + * Iterator access has to be synchronized externally! + * + * @see HashSet + */ + @Override + public Iterator<E> iterator() { + return map.keySet().iterator(); + } + + /** + * Synchronized access to set size + * Copy of the HashSet code if size() + * + * @see HashSet + */ + @Override + public synchronized int size() { + return map.size(); + } + + /** + * Synchronized check of set emptiness + * Copy of the HashSet code if isEmpty() + * + * @see HashSet + */ + @Override + public synchronized boolean isEmpty() { + return map.isEmpty(); + } + + /** + * Synchronized check for containment + * Copy of the HashSet code if contains() + * + * @see HashSet + */ + @Override + public synchronized boolean contains(Object o) { + return map.containsKey(o); + } + + /** + * Synchronized addition of an item + * Copy of the HashSet code if add() + * + * @see HashSet + */ + @Override + public synchronized boolean add(E e) { + return map.put(e, PRESENT) == null; + } + + /** + * Synchronized removal of a contained item + * Copy of the HashSet code if remove() + * + * @see HashSet + */ + @Override + public synchronized boolean remove(Object o) { + return map.remove(o) == PRESENT; + } + + /** + * Synchronized clearing of the set + * Copy of the HashSet code if clear() + * + * @see HashSet + */ + @Override + public synchronized void clear() { + map.clear(); + } + + /** + * (synchronized) Clone of the set + * Copy of the HashSet code if clone() + * + * @see HashSet + */ + @Override + @SuppressWarnings("unchecked") + public Object clone() { + try { + synchronized (this) { + final LeastRecentlyUsedSet<E> newSet = (LeastRecentlyUsedSet<E>) super.clone(); + newSet.map = (LeastRecentlyUsedMap<E, Object>) map.clone(); + return newSet; + } + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } + + /** + * Creates a clone as a list in a synchronized fashion. + * + * @return List based clone of the set + */ + public synchronized List<E> getAsList() { + return new ArrayList<E>(this); + } + + /** + * Serialization version of HashSet with the additional parameters for the custom Map + * + * @see HashSet + */ + private void writeObject(java.io.ObjectOutputStream s) + throws java.io.IOException { + // Write out any hidden serialization magic + s.defaultWriteObject(); + + // Write out HashMap capacity and load factor + s.writeInt(map.initialCapacity); + s.writeFloat(map.loadFactor); + s.writeInt(map.getMaxEntries()); + + // Write out size + s.writeInt(map.size()); + + // Write out all elements in the proper order. + for (final Iterator<E> i = map.keySet().iterator(); i.hasNext();) { + s.writeObject(i.next()); + } + } + + /** + * Serialization version of HashSet with the additional parameters for the custom Map + * + * @see HashSet + */ + @SuppressWarnings("unchecked") + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + // Read in any hidden serialization magic + s.defaultReadObject(); + + // Read in HashMap capacity and load factor and create backing HashMap + final int capacity = s.readInt(); + final float loadFactor = s.readFloat(); + final int maxEntries = s.readInt(); + + map = new LeastRecentlyUsedMap.LruCache<E, Object>(maxEntries, capacity, loadFactor); + + // Read in size + final int size = s.readInt(); + + // Read in all elements in the proper order. + for (int i = 0; i < size; i++) { + E e = (E) s.readObject(); + map.put(e, PRESENT); + } + } + +} diff --git a/main/src/cgeo/geocaching/utils/Log.java b/main/src/cgeo/geocaching/utils/Log.java index 42c1705..9f5bd3d 100644 --- a/main/src/cgeo/geocaching/utils/Log.java +++ b/main/src/cgeo/geocaching/utils/Log.java @@ -1,67 +1,69 @@ package cgeo.geocaching.utils; -import cgeo.geocaching.Settings; final public class Log { - public static void v(final String tag, final String msg) { - if (Settings.isDebug()) { - android.util.Log.v(tag, msg); - } + private static final String TAG = "cgeo"; + + private static boolean isDebug = true; + + public static boolean isDebug() { + return isDebug; } - public static void v(final String tag, final String msg, final Throwable t) { - if (Settings.isDebug()) { - android.util.Log.v(tag, msg, t); - } + public static void setDebugUnsaved(boolean isDebug) { + Log.isDebug = isDebug; } - public static void d(final String tag, final String msg) { - if (Settings.isDebug()) { - android.util.Log.d(tag, msg); + public static void v(final String msg) { + if (isDebug) { + android.util.Log.v(TAG, msg); } } - public static void d(final String tag, final String msg, final Throwable t) { - if (Settings.isDebug()) { - android.util.Log.d(tag, msg, t); + public static void v(final String msg, final Throwable t) { + if (isDebug) { + android.util.Log.v(TAG, msg, t); } } - public static void i(final String tag, final String msg) { - if (Settings.isDebug()) { - android.util.Log.i(tag, msg); + public static void d(final String msg) { + if (isDebug) { + android.util.Log.d(TAG, msg); } } - public static void i(final String tag, final String msg, final Throwable t) { - if (Settings.isDebug()) { - android.util.Log.i(tag, msg, t); + public static void d(final String msg, final Throwable t) { + if (isDebug) { + android.util.Log.d(TAG, msg, t); } } - public static void w(final String tag, final String msg) { - android.util.Log.w(tag, msg); + public static void i(final String msg) { + if (isDebug) { + android.util.Log.i(TAG, msg); + } } - public static void w(final String tag, final String msg, final Throwable t) { - android.util.Log.w(tag, msg, t); + public static void i(final String msg, final Throwable t) { + if (isDebug) { + android.util.Log.i(TAG, msg, t); + } } - public static void e(final String tag, final String msg) { - android.util.Log.e(tag, msg); + public static void w(final String msg) { + android.util.Log.w(TAG, msg); } - public static void e(final String tag, final String msg, final Throwable t) { - android.util.Log.e(tag, msg, t); + public static void w(final String msg, final Throwable t) { + android.util.Log.w(TAG, msg, t); } - public static void wtf(final String tag, final String msg) { - android.util.Log.wtf(tag, msg); + public static void e(final String msg) { + android.util.Log.e(TAG, msg); } - public static void wtf(final String tag, final String msg, final Throwable t) { - android.util.Log.wtf(tag, msg, t); + public static void e(final String msg, final Throwable t) { + android.util.Log.e(TAG, msg, t); } - } diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java index 9a5e422..60866e0 100644 --- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java +++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java @@ -2,10 +2,10 @@ package cgeo.geocaching.utils; import cgeo.geocaching.R; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.connector.gc.GCConstants; -import cgeo.geocaching.network.Login; +import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.network.Network; +import cgeo.geocaching.ui.Formatter; import org.apache.commons.lang3.StringUtils; @@ -55,14 +55,14 @@ public class LogTemplateProvider { @Override public String getValue(final boolean offline) { - return cgBase.formatFullDate(System.currentTimeMillis()); + return Formatter.formatFullDate(System.currentTimeMillis()); } }, new LogTemplate("TIME", R.string.init_signature_template_time) { @Override public String getValue(final boolean offline) { - return cgBase.formatTime(System.currentTimeMillis()); + return Formatter.formatTime(System.currentTimeMillis()); } }, new LogTemplate("DATETIME", R.string.init_signature_template_datetime) { @@ -70,7 +70,7 @@ public class LogTemplateProvider { @Override public String getValue(final boolean offline) { final long currentTime = System.currentTimeMillis(); - return cgBase.formatFullDate(currentTime) + " " + cgBase.formatTime(currentTime); + return Formatter.formatFullDate(currentTime) + " " + Formatter.formatTime(currentTime); } }, new LogTemplate("USER", R.string.init_signature_template_user) { @@ -89,7 +89,7 @@ public class LogTemplateProvider { if (offline) { return ""; } - final String page = Network.getResponseData(Network.request("http://www.geocaching.com/email/", null, false, false, false)); + final String page = Network.getResponseData(Network.getRequest("http://www.geocaching.com/email/")); current = parseFindCount(page); } @@ -133,7 +133,7 @@ public class LogTemplateProvider { try { return Integer.parseInt(BaseUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", "")); } catch (NumberFormatException e) { - Log.e(Settings.tag, "parseFindCount", e); + Log.e("parseFindCount", e); return -1; } } diff --git a/main/support/proguard.jar b/main/support/proguard.jar Binary files differindex f688284..56d68ba 100644 --- a/main/support/proguard.jar +++ b/main/support/proguard.jar |
