aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main/.settings/org.eclipse.jdt.core.prefs6
-rw-r--r--main/.settings/org.eclipse.jdt.ui.prefs5
-rw-r--r--main/AndroidManifest.xml106
-rw-r--r--main/libs/android-support-v4.jarbin621451 -> 627582 bytes
-rw-r--r--main/libs/rxjava-android-0.15.1.jarbin0 -> 16776 bytes
-rw-r--r--main/libs/rxjava-core-0.15.1.jarbin0 -> 496439 bytes
-rw-r--r--main/proguard-project.txt5
-rw-r--r--main/res/layout/main_activity.xml17
-rw-r--r--main/res/layout/search_activity.xml8
-rw-r--r--main/res/menu/details_context.xml5
-rw-r--r--main/res/values-cs/strings.xml3
-rw-r--r--main/res/values-da/strings.xml1
-rw-r--r--main/res/values-de/strings.xml8
-rw-r--r--main/res/values-es/strings.xml2
-rw-r--r--main/res/values-fr/strings.xml4
-rw-r--r--main/res/values-hu/strings.xml3
-rw-r--r--main/res/values-it/strings.xml3
-rw-r--r--main/res/values-ja/strings.xml3
-rw-r--r--main/res/values-nb/strings.xml2
-rw-r--r--main/res/values-nl/strings.xml3
-rw-r--r--main/res/values-pl/strings.xml3
-rw-r--r--main/res/values-pt/strings.xml3
-rw-r--r--main/res/values-sk/strings.xml3
-rw-r--r--main/res/values-sl/strings.xml3
-rw-r--r--main/res/values-sv/strings.xml3
-rw-r--r--main/res/values/changelog_master.xml7
-rw-r--r--main/res/values/preference_keys.xml14
-rw-r--r--main/res/values/strings.xml16
-rw-r--r--main/res/xml/preferences.xml59
-rw-r--r--main/res/xml/searchable.xml1
-rw-r--r--main/src/cgeo/calendar/CalendarAddon.java58
-rw-r--r--main/src/cgeo/calendar/ICalendar.java2
-rw-r--r--main/src/cgeo/contacts/IContacts.java2
-rw-r--r--main/src/cgeo/geocaching/AbstractPopupActivity.java2
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java325
-rw-r--r--main/src/cgeo/geocaching/CacheListActivity.java169
-rw-r--r--main/src/cgeo/geocaching/CacheMenuHandler.java55
-rw-r--r--main/src/cgeo/geocaching/CachePopup.java6
-rw-r--r--main/src/cgeo/geocaching/CgeoApplication.java66
-rw-r--r--main/src/cgeo/geocaching/CompassActivity.java5
-rw-r--r--main/src/cgeo/geocaching/CreateShortcutActivity.java10
-rw-r--r--main/src/cgeo/geocaching/DataStore.java192
-rw-r--r--main/src/cgeo/geocaching/DirectionProvider.java90
-rw-r--r--main/src/cgeo/geocaching/EditWaypointActivity.java1
-rw-r--r--main/src/cgeo/geocaching/GeoDataProvider.java146
-rw-r--r--main/src/cgeo/geocaching/Geocache.java21
-rw-r--r--main/src/cgeo/geocaching/Intents.java4
-rw-r--r--main/src/cgeo/geocaching/LogCacheActivity.java6
-rw-r--r--main/src/cgeo/geocaching/LogTrackableActivity.java2
-rw-r--r--main/src/cgeo/geocaching/MainActivity.java195
-rw-r--r--main/src/cgeo/geocaching/PocketQueryList.java137
-rw-r--r--main/src/cgeo/geocaching/SearchActivity.java78
-rw-r--r--main/src/cgeo/geocaching/SearchResult.java2
-rw-r--r--main/src/cgeo/geocaching/StaticMapsActivity.java1
-rw-r--r--main/src/cgeo/geocaching/StatusFragment.java129
-rw-r--r--main/src/cgeo/geocaching/TrackableActivity.java2
-rw-r--r--main/src/cgeo/geocaching/UsefulAppsActivity.java1
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractListActivity.java23
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java1
-rw-r--r--main/src/cgeo/geocaching/apps/AbstractLocusApp.java1
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java2
-rw-r--r--main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java3
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractConnector.java14
-rw-r--r--main/src/cgeo/geocaching/connector/ConnectorFactory.java40
-rw-r--r--main/src/cgeo/geocaching/connector/UserAction.java10
-rw-r--r--main/src/cgeo/geocaching/connector/ec/ECApi.java1
-rw-r--r--main/src/cgeo/geocaching/connector/ec/ECConnector.java2
-rw-r--r--main/src/cgeo/geocaching/connector/ec/ECLogin.java1
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java31
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCLogin.java13
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java39
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java41
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OXGPXParser.java4
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java1
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java4
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java27
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java8
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java4
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java17
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheAttribute.java8
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheListType.java2
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheSize.java37
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheType.java2
-rw-r--r--main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java2
-rw-r--r--main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java23
-rw-r--r--main/src/cgeo/geocaching/enumerations/StatusCode.java2
-rw-r--r--main/src/cgeo/geocaching/export/GpxExport.java2
-rw-r--r--main/src/cgeo/geocaching/files/LocalStorage.java9
-rw-r--r--main/src/cgeo/geocaching/files/SimpleDirChooser.java4
-rw-r--r--main/src/cgeo/geocaching/filter/DistanceFilter.java2
-rw-r--r--main/src/cgeo/geocaching/filter/FilterUserInterface.java13
-rw-r--r--main/src/cgeo/geocaching/filter/ModifiedFilter.java2
-rw-r--r--main/src/cgeo/geocaching/geopoint/Geopoint.java26
-rw-r--r--main/src/cgeo/geocaching/geopoint/GeopointParser.java36
-rw-r--r--main/src/cgeo/geocaching/geopoint/Viewport.java68
-rw-r--r--main/src/cgeo/geocaching/list/PseudoList.java6
-rw-r--r--main/src/cgeo/geocaching/list/StoredList.java40
-rw-r--r--main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java2
-rw-r--r--main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java2
-rw-r--r--main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java2
-rw-r--r--main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java4
-rw-r--r--main/src/cgeo/geocaching/maps/CGeoMap.java10
-rw-r--r--main/src/cgeo/geocaching/maps/MapProviderFactory.java2
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleCacheOverlay.java5
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java2
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapView.java9
-rw-r--r--main/src/cgeo/geocaching/maps/interfaces/ItemizedOverlayImpl.java2
-rw-r--r--main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java2
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java5
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java8
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java5
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java6
-rw-r--r--main/src/cgeo/geocaching/network/HtmlImage.java165
-rw-r--r--main/src/cgeo/geocaching/network/Network.java1
-rw-r--r--main/src/cgeo/geocaching/network/OAuth.java1
-rw-r--r--main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java1
-rw-r--r--main/src/cgeo/geocaching/network/StatusUpdater.java57
-rw-r--r--main/src/cgeo/geocaching/search/AutoCompleteAdapter.java71
-rw-r--r--main/src/cgeo/geocaching/search/SuggestionProvider.java57
-rw-r--r--main/src/cgeo/geocaching/settings/OAuthPreference.java4
-rw-r--r--main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java1
-rw-r--r--main/src/cgeo/geocaching/settings/Settings.java12
-rw-r--r--main/src/cgeo/geocaching/settings/SettingsActivity.java110
-rw-r--r--main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java35
-rw-r--r--main/src/cgeo/geocaching/sorting/CacheComparator.java4
-rw-r--r--main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java9
-rw-r--r--main/src/cgeo/geocaching/sorting/DateComparator.java7
-rw-r--r--main/src/cgeo/geocaching/sorting/DifficultyComparator.java4
-rw-r--r--main/src/cgeo/geocaching/sorting/DistanceComparator.java5
-rw-r--r--main/src/cgeo/geocaching/sorting/FindsComparator.java4
-rw-r--r--main/src/cgeo/geocaching/sorting/GeocodeComparator.java13
-rw-r--r--main/src/cgeo/geocaching/sorting/InventoryComparator.java5
-rw-r--r--main/src/cgeo/geocaching/sorting/NameComparator.java4
-rw-r--r--main/src/cgeo/geocaching/sorting/PopularityComparator.java5
-rw-r--r--main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java5
-rw-r--r--main/src/cgeo/geocaching/sorting/RatingComparator.java5
-rw-r--r--main/src/cgeo/geocaching/sorting/SizeComparator.java4
-rw-r--r--main/src/cgeo/geocaching/sorting/StateComparator.java5
-rw-r--r--main/src/cgeo/geocaching/sorting/StorageTimeComparator.java5
-rw-r--r--main/src/cgeo/geocaching/sorting/TerrainComparator.java4
-rw-r--r--main/src/cgeo/geocaching/sorting/VisitComparator.java5
-rw-r--r--main/src/cgeo/geocaching/sorting/VoteComparator.java5
-rw-r--r--main/src/cgeo/geocaching/speech/SpeechService.java4
-rw-r--r--main/src/cgeo/geocaching/speech/TextFactory.java2
-rw-r--r--main/src/cgeo/geocaching/twitter/Twitter.java1
-rw-r--r--main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java1
-rw-r--r--main/src/cgeo/geocaching/ui/AnchorAwareLinkMovementMethod.java2
-rw-r--r--main/src/cgeo/geocaching/ui/CacheDetailsCreator.java21
-rw-r--r--main/src/cgeo/geocaching/ui/ImagesList.java92
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java4
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/Dialogs.java6
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java2
-rw-r--r--main/src/cgeo/geocaching/utils/CancellableHandler.java16
-rw-r--r--main/src/cgeo/geocaching/utils/GeoDirHandler.java107
-rw-r--r--main/src/cgeo/geocaching/utils/IObserver.java22
-rw-r--r--main/src/cgeo/geocaching/utils/ISubject.java57
-rw-r--r--main/src/cgeo/geocaching/utils/ImageUtils.java2
-rw-r--r--main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java3
-rw-r--r--main/src/cgeo/geocaching/utils/LogTemplateProvider.java4
-rw-r--r--main/src/cgeo/geocaching/utils/MemorySubject.java45
-rw-r--r--main/src/cgeo/geocaching/utils/RunnableWithArgument.java7
-rw-r--r--main/src/cgeo/geocaching/utils/Subject.java76
-rw-r--r--main/src/cgeo/geocaching/utils/TextUtils.java1
-rw-r--r--main/thirdparty/android/support/v4/app/FragmentListActivity.java4
-rw-r--r--main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java6
-rw-r--r--tests/.settings/org.eclipse.jdt.core.prefs28
-rw-r--r--tests/libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jarbin0 -> 14613 bytes
-rw-r--r--tests/src/cgeo/geocaching/CgeoApplicationTest.java32
-rw-r--r--tests/src/cgeo/geocaching/SettingsTest.java2
-rw-r--r--tests/src/cgeo/geocaching/connector/ConnectorFactoryTest.java24
-rw-r--r--tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java10
-rw-r--r--tests/src/cgeo/geocaching/connector/gc/GCParserTest.java11
-rw-r--r--tests/src/cgeo/geocaching/connector/trackable/GeokretyConnectorTest.java13
-rw-r--r--tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java11
-rw-r--r--tests/src/cgeo/geocaching/enumerations/CacheAttributeTest.java3
-rw-r--r--tests/src/cgeo/geocaching/enumerations/CacheSizeTest.java2
-rw-r--r--tests/src/cgeo/geocaching/enumerations/LogTypeTrackableTest.java6
-rw-r--r--tests/src/cgeo/geocaching/geopoint/GeoPointParserTest.java16
-rw-r--r--tests/src/cgeo/geocaching/geopoint/ViewportTest.java17
-rw-r--r--tests/src/cgeo/geocaching/network/OAuthTest.java8
-rw-r--r--tests/src/cgeo/geocaching/sorting/DistanceComparatorTest.java2
-rw-r--r--tests/src/cgeo/geocaching/utils/LogTemplateProviderTest.java4
-rw-r--r--tests/src/cgeo/geocaching/utils/MemorySubjectTest.java79
-rw-r--r--tests/src/cgeo/test/Compare.java6
185 files changed, 2025 insertions, 1989 deletions
diff --git a/main/.settings/org.eclipse.jdt.core.prefs b/main/.settings/org.eclipse.jdt.core.prefs
index 3e9e8a8..2fc1133 100644
--- a/main/.settings/org.eclipse.jdt.core.prefs
+++ b/main/.settings/org.eclipse.jdt.core.prefs
@@ -1,5 +1,5 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
@@ -83,7 +83,7 @@ org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
@@ -192,7 +192,7 @@ org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
diff --git a/main/.settings/org.eclipse.jdt.ui.prefs b/main/.settings/org.eclipse.jdt.ui.prefs
index 92e2c88..a80d8c1 100644
--- a/main/.settings/org.eclipse.jdt.ui.prefs
+++ b/main/.settings/org.eclipse.jdt.ui.prefs
@@ -1,11 +1,14 @@
-#Tue Feb 21 06:54:46 CET 2012
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_cgeo
formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
org.eclipse.jdt.ui.ignorelowercasenames=true
org.eclipse.jdt.ui.importorder=cgeo;com;org;android;java;javax;
+org.eclipse.jdt.ui.keywordthis=false
org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
org.eclipse.jdt.ui.staticondemandthreshold=99
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml
index 1884a9b..d83f2b3 100644
--- a/main/AndroidManifest.xml
+++ b/main/AndroidManifest.xml
@@ -111,8 +111,8 @@
android:name=".twitter.TwitterAuthorizationActivity"
android:configChanges="keyboardHidden|orientation"
android:label="@string/auth_twitter"
- android:windowSoftInputMode="stateHidden"
- android:launchMode="singleTask" >
+ android:launchMode="singleTask"
+ android:windowSoftInputMode="stateHidden" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -142,11 +142,11 @@
android:label="@string/search_address_result"
android:windowSoftInputMode="stateHidden" >
</activity>
- <activity
+ <activity
android:name=".settings.SettingsActivity"
+ android:configChanges="keyboardHidden|orientation"
android:label="@string/settings_titlebar"
- android:theme="@style/settings"
- android:configChanges="keyboardHidden|orientation" >
+ android:theme="@style/settings" >
</activity>
<activity
android:name=".CacheListActivity"
@@ -308,6 +308,8 @@
android:name="cgeo.geocaching.TrackableActivity"
android:configChanges="keyboardHidden|orientation"
android:label="@string/app_name" >
+
+ <!-- TravelBug URL via coord.info redirection -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -326,6 +328,19 @@
<category android:name="android.intent.category.BROWSABLE" />
<data
+ android:host="www.coord.info"
+ android:pathPrefix="/TB"
+ android:scheme="http" />
+ </intent-filter>
+
+ <!-- TravelBug URL tracking page -->
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data
android:host="geocaching.com"
android:pathPrefix="/track/details.aspx"
android:scheme="http" />
@@ -341,6 +356,56 @@
android:pathPrefix="/track/details.aspx"
android:scheme="http" />
</intent-filter>
+
+ <!-- GeoKrety URLs -->
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data
+ android:host="geokrety.org"
+ android:pathPrefix="/konkret.php"
+ android:scheme="http" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data
+ android:host="www.geokrety.org"
+ android:pathPrefix="/konkret.php"
+ android:scheme="http" />
+ </intent-filter>
+
+ <!--
+ Geokrety QR code URLs, not yet implemented
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data
+ android:host="geokrety.org"
+ android:pathPrefix="/m/qr.php"
+ android:scheme="http" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data
+ android:host="www.geokrety.org"
+ android:pathPrefix="/m/qr.php"
+ android:scheme="http" />
+ </intent-filter>
+ -->
</activity>
<activity
android:name=".CompassActivity"
@@ -358,10 +423,6 @@
android:label="@string/map_file_select_title" >
</activity>
- <provider
- android:name=".apps.LocusDataStorageProvider"
- android:authorities="cgeo.geocaching.apps.locusdatastorageprovider" />
-
<activity
android:name="WaypointPopup"
android:configChanges="keyboardHidden|orientation"
@@ -387,8 +448,8 @@
android:name=".connector.oc.OCDEAuthorizationActivity"
android:configChanges="keyboardHidden|orientation"
android:label="@string/app_name"
- android:windowSoftInputMode="stateHidden"
- android:launchMode="singleTask">
+ android:launchMode="singleTask"
+ android:windowSoftInputMode="stateHidden" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -405,8 +466,8 @@
android:name=".connector.oc.OCPLAuthorizationActivity"
android:configChanges="keyboardHidden|orientation"
android:label="@string/app_name"
- android:windowSoftInputMode="stateHidden"
- android:launchMode="singleTask">
+ android:launchMode="singleTask"
+ android:windowSoftInputMode="stateHidden" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -421,12 +482,23 @@
</activity>
<activity
android:name=".CreateShortcutActivity"
- android:label="@string/create_shortcut" >
+ android:label="@string/cgeo_shortcut" >
<intent-filter>
- <action android:name="android.intent.action.CREATE_SHORTCUT"/>
- <category android:name="android.intent.category.DEFAULT"/>
+ <action android:name="android.intent.action.CREATE_SHORTCUT" />
+
+ <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
+ <!-- provide enhanced meta data for caches (and waypoints) when invoking Locus from c:geo -->
+ <provider
+ android:name=".apps.LocusDataStorageProvider"
+ android:authorities="cgeo.geocaching.apps.locusdatastorageprovider" />
+
+ <!-- search suggestions for the search bar at the top -->
+ <provider
+ android:name=".search.SuggestionProvider"
+ android:authorities="cgeo.geocaching.search.SuggestionProvider" />
</application>
-</manifest>
+
+</manifest> \ No newline at end of file
diff --git a/main/libs/android-support-v4.jar b/main/libs/android-support-v4.jar
index 9056828..96644ed 100644
--- a/main/libs/android-support-v4.jar
+++ b/main/libs/android-support-v4.jar
Binary files differ
diff --git a/main/libs/rxjava-android-0.15.1.jar b/main/libs/rxjava-android-0.15.1.jar
new file mode 100644
index 0000000..4e50a44
--- /dev/null
+++ b/main/libs/rxjava-android-0.15.1.jar
Binary files differ
diff --git a/main/libs/rxjava-core-0.15.1.jar b/main/libs/rxjava-core-0.15.1.jar
new file mode 100644
index 0000000..5759337
--- /dev/null
+++ b/main/libs/rxjava-core-0.15.1.jar
Binary files differ
diff --git a/main/proguard-project.txt b/main/proguard-project.txt
index 03ef6b3..eae0a42 100644
--- a/main/proguard-project.txt
+++ b/main/proguard-project.txt
@@ -13,6 +13,11 @@
# apache.commons.collections has some bean related collections, which are undefined in Android
-dontwarn java.beans.*
+# rxjava includes references to the test frameworks within their class files
+-dontwarn org.mockito.**
+-dontwarn org.junit.**
+-dontwarn org.robolectric.**
+
#-dontnote org.apache.commons.logging.**
-keep public class cgeo.geocaching.*
diff --git a/main/res/layout/main_activity.xml b/main/res/layout/main_activity.xml
index ef86954..9e124a1 100644
--- a/main/res/layout/main_activity.xml
+++ b/main/res/layout/main_activity.xml
@@ -35,8 +35,7 @@
android:gravity="center"
android:orientation="vertical" >
- <LinearLayout
- style="@style/icon_mainscreen_row" >
+ <LinearLayout style="@style/icon_mainscreen_row" >
<LinearLayout
style="@style/icon_mainscreen_cell"
@@ -52,8 +51,7 @@
android:text="@string/live_map_button" />
</LinearLayout>
- <LinearLayout
- style="@style/icon_mainscreen_cell" >
+ <LinearLayout style="@style/icon_mainscreen_cell" >
<ImageView
android:id="@+id/nearest"
@@ -76,8 +74,7 @@
style="@style/icon_mainscreen_count"
android:textIsSelectable="false" />
- <LinearLayout
- style="@style/icon_mainscreen_cell_counter" >
+ <LinearLayout style="@style/icon_mainscreen_cell_counter" >
<ImageView
android:id="@+id/search_offline"
@@ -91,8 +88,7 @@
</RelativeLayout>
</LinearLayout>
- <LinearLayout
- style="@style/icon_mainscreen_row" >
+ <LinearLayout style="@style/icon_mainscreen_row" >
<LinearLayout
style="@style/icon_mainscreen_cell"
@@ -146,7 +142,6 @@
android:layout_alignParentBottom="true"
android:layout_marginLeft="6dip"
android:layout_marginRight="6dip"
- android:onClick="cgeoNavSettings"
android:orientation="vertical" >
<LinearLayout
@@ -158,11 +153,13 @@
<TextView
android:id="@+id/nav_location"
style="@style/location_current"
+ android:onClick="cgeoNavSettings"
android:text="@string/loc_trying" />
<RelativeLayout
android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
+ android:layout_height="wrap_content"
+ android:onClick="cgeoNavSettings" >
<TextView
android:id="@+id/nav_type"
diff --git a/main/res/layout/search_activity.xml b/main/res/layout/search_activity.xml
index 25f914b..28256f1 100644
--- a/main/res/layout/search_activity.xml
+++ b/main/res/layout/search_activity.xml
@@ -53,7 +53,7 @@
android:text="@string/search_address" />
</RelativeLayout>
- <EditText
+ <AutoCompleteTextView
android:id="@+id/address"
style="@style/edittext_full"
android:hint="@string/search_address"
@@ -98,7 +98,7 @@
android:text="@string/search_kw" />
</RelativeLayout>
- <EditText
+ <AutoCompleteTextView
android:id="@+id/keyword"
style="@style/edittext_full"
android:hint="@string/search_kw_prefill"
@@ -119,7 +119,7 @@
android:text="@string/search_fbu" />
</RelativeLayout>
- <EditText
+ <AutoCompleteTextView
android:id="@+id/finder"
style="@style/edittext_full"
android:hint="@string/search_fbu_prefill"
@@ -140,7 +140,7 @@
android:text="@string/search_hbu" />
</RelativeLayout>
- <EditText
+ <AutoCompleteTextView
android:id="@+id/owner"
style="@style/edittext_full"
android:hint="@string/search_hbu_prefill"
diff --git a/main/res/menu/details_context.xml b/main/res/menu/details_context.xml
index 0ae2f6d..3125459 100644
--- a/main/res/menu/details_context.xml
+++ b/main/res/menu/details_context.xml
@@ -17,5 +17,10 @@
android:id="@+id/menu_cache_share_field"
android:title="@string/cache_share_field">
</item>
+ <item
+ android:id="@+id/menu_calendar"
+ android:title="@string/cache_menu_event"
+ android:visible="false">
+ </item>
</menu> \ No newline at end of file
diff --git a/main/res/values-cs/strings.xml b/main/res/values-cs/strings.xml
index 66286f0..b220580 100644
--- a/main/res/values-cs/strings.xml
+++ b/main/res/values-cs/strings.xml
@@ -121,7 +121,6 @@
<string name="translate_to_english">Přeložit do angličtiny</string>
<string name="translate_length_warning">Při velkém množství textu může překládání selhat.</string>
<string name="err_none">OK</string>
- <string name="err_start">Komunikace nezačala</string>
<string name="err_parse">Čtení přihlašovací obrazovky selhalo</string>
<string name="err_server">Nelze se připojit na Geocaching.com. Stránka může být nedostupná nebo je chyba v tvém připojení k Internetu</string>
<string name="err_login">Nejsou uloženy žádné přihlašovací údaje</string>
@@ -177,7 +176,6 @@
<string name="err_log_load_data">c:geo nemůže načíst data požadovaná k zalogování návštěvy.</string>
<string name="err_log_load_data_again">c:geo nemůže načíst data požadovaná k zalogování návštěvy. Zkouší to znovu.</string>
<string name="err_log_load_data_still">c:geo stále načítá data požadovaná k odeslání Logu. Prosím, počkej ještě chvíli.</string>
- <string name="err_log_failed_server">c:geo nemůže odeslat Log, protože server neodpovídá.</string>
<string name="err_log_post_failed">Zdá se, že tvůj Log nebyl odeslán. Prosím, zkontroluj to na Geocaching.com.</string>
<string name="err_logimage_post_failed">Zdá se, že tvůj obrázek nebyl nahrán. Zkontroluj to, prosím, na Geocaching.com.</string>
<string name="err_search_address_forgot">c:geo zapomnělo hledanou adresu.</string>
@@ -599,7 +597,6 @@
<string name="cache_coordinates">Souřadnice</string>
<string name="cache_coordinates_original">Původní souřadnice</string>
<string name="cache_spoiler_images_title">Obrázky s nápovědou</string>
- <string name="cache_images_title">Obrázky</string>
<string name="cache_log_types">Typy zápisů</string>
<string name="cache_coordinates_no">Tato keš nemá souřadnice.</string>
<string name="cache_clear_history">Vymazat historii</string>
diff --git a/main/res/values-da/strings.xml b/main/res/values-da/strings.xml
index d784056..6b23d3d 100644
--- a/main/res/values-da/strings.xml
+++ b/main/res/values-da/strings.xml
@@ -53,7 +53,6 @@
<string name="log_clear">Fjern</string>
<string name="log_webcam">Webcamfoto taget</string>
<string name="err_none">Ok</string>
- <string name="err_start">Forbindelse ikke oprettet</string>
<string name="err_parse">Login-side kan ikke indlæses</string>
<string name="err_server">Kan ikke forbinde til Geocaching.com (server eller forbindelsesfejl?)</string>
<string name="err_login">Ingen login gemt</string>
diff --git a/main/res/values-de/strings.xml b/main/res/values-de/strings.xml
index 927cce0..3803faa 100644
--- a/main/res/values-de/strings.xml
+++ b/main/res/values-de/strings.xml
@@ -121,7 +121,6 @@
<string name="translate_to_english">Übersetze in Englisch</string>
<string name="translate_length_warning">Die Übersetzung kann bei sehr langen Texten evtl. fehlschlagen.</string>
<string name="err_none">OK</string>
- <string name="err_start">Kommunikation nicht gestartet</string>
<string name="err_parse">Parsing der Anmeldung gescheitert</string>
<string name="err_server">Verbindung zu Geocaching.com konnte nicht hergestellt werden (Server oder Verbindung inaktiv?)</string>
<string name="err_server_ec">Verbindung zu Extremcaching.com konnte nicht hergestellt werden (Server oder Verbindung inaktiv?)</string>
@@ -178,7 +177,6 @@
<string name="err_log_load_data">c:geo konnte die benötigten Daten nicht laden, um den Besuch zu loggen.</string>
<string name="err_log_load_data_again">c:geo konnte die benötigten Daten nicht laden, um den Besuch zu loggen. Bitte erneut versuchen.</string>
<string name="err_log_load_data_still">c:geo lädt gerade die benötigten Daten. Bitte kurz warten.</string>
- <string name="err_log_failed_server">c:geo konnte Log nicht senden, weil der Server nicht antwortete.</string>
<string name="err_log_post_failed">c:geo konnte Log nicht absenden.</string>
<string name="err_log_post_failed_ec">Es scheint dass Ihr Log nicht hochgeladen werden konnte. Bitte prüfen Sie es auf Extremcaching.com nach.</string>
<string name="err_logimage_post_failed">Es scheint dass Ihr Logfoto nicht hochgeladen werden konnte. Bitte prüfen Sie es auf Geocaching.com nach.</string>
@@ -638,7 +636,6 @@
<string name="cache_coordinates">Koordinaten</string>
<string name="cache_coordinates_original">Ursprüngliche Koordinaten</string>
<string name="cache_spoiler_images_title">Hinweisbilder</string>
- <string name="cache_images_title">Bilder</string>
<string name="cache_log_types">Logs</string>
<string name="cache_coordinates_no">Dieser Cache hat keine Koordinaten.</string>
<string name="cache_clear_history">Verlauf leeren</string>
@@ -806,7 +803,7 @@
<string name="user_menu_view_found">Gefundene Caches</string>
<string name="user_menu_open_browser">Profil im Browser öffnen</string>
<string name="user_menu_send_message">Nachricht senden</string>
- <string name="user_menu_open_contact">Öffne Adressbuch</string>
+ <string name="user_menu_open_contact">Öffne Kontakt</string>
<string name="navigation">Navigation</string>
<string name="compass_title">Kompass</string>
<string name="use_gps">Nur GPS nutzen</string>
@@ -821,6 +818,8 @@
<string name="helper_calendar_title">c:geo Kalender Add-on</string>
<string name="helper_calendar_missing">c:geo Kalender Add-on nicht installiert</string>
<string name="helper_calendar_description">Ermöglicht die Übernahme von Event-Caches in den Kalender.</string>
+ <string name="helper_contacts_title">c:geo Kontakte Add-on</string>
+ <string name="helper_contacts_description">Ermöglicht das direkte Öffnen von Kontakten (aus dem eigenen Adressbuch) von Logeinträgen aus, so dass man Freunde einfacher um Hilfe fragen kann.</string>
<string name="helper_locus_title">Locus</string>
<string name="helper_locus_description">Sehr gute App für Online- und Offline-Karten (nur Rasterkarten) mit vielen weiteren Funktionen wie z.B. Trackaufzeichnung, POIs und vieles mehr.</string>
<string name="helper_gpsstatus_title">GPS-Status</string>
@@ -1111,5 +1110,6 @@
<item quantity="other">%s Favoriten</item>
</plurals>
<string name="percent_favorite_points">% Favoriten</string>
+ <string name="cgeo_shortcut">c:geo Shortcut</string>
<string name="create_shortcut">Shortcut erstellen</string>
</resources>
diff --git a/main/res/values-es/strings.xml b/main/res/values-es/strings.xml
index b502385..9287073 100644
--- a/main/res/values-es/strings.xml
+++ b/main/res/values-es/strings.xml
@@ -114,7 +114,6 @@
<string name="log_image_description">Descripción</string>
<string name="log_image_scale">Redimensionamiento</string>
<string name="err_none">Aceptar</string>
- <string name="err_start">Comunicación no iniciada</string>
<string name="err_parse">Error procesando la página de acceso</string>
<string name="err_server">Error conectando a Geocaching.com (¿servidor o conexión caidos?)</string>
<string name="err_login">No hay información de acceso guardada</string>
@@ -160,7 +159,6 @@
<string name="err_log_load_data">Lo siento, c:geo no puede cargar los datos necesarios para registrar la visita.</string>
<string name="err_log_load_data_again">Lo siento, c:geo no puede cargar los datos necesarios para registrar la visita. Intentándolo de nuevo.</string>
<string name="err_log_load_data_still">c:geo sigue cargando datos para registrar el escondite. Debes esperar un poquito mas.</string>
- <string name="err_log_failed_server">Lo siento, c:geo no ha podido enviar el registro porque el servidor no responde.</string>
<string name="err_log_post_failed">Lo siento, c:geo no ha podido enviar el registro.</string>
<string name="err_search_address_forgot">Lo siento, c:geo ha olvidado la dirección que buscabas.</string>
<string name="err_parse_lat">Lo siento, c:geo no puede procesar la latitud.</string>
diff --git a/main/res/values-fr/strings.xml b/main/res/values-fr/strings.xml
index 7b8a8d7..3918c30 100644
--- a/main/res/values-fr/strings.xml
+++ b/main/res/values-fr/strings.xml
@@ -121,7 +121,6 @@
<string name="translate_to_english">Traduire en anglais</string>
<string name="translate_length_warning">La traduction d\'un texte trop long peut échouer.</string>
<string name="err_none">ok</string>
- <string name="err_start">Communication non démarrée</string>
<string name="err_parse">Échec login lecture page</string>
<string name="err_server">Échec de la connexion à Geocaching.com (probléme de serveur ou de connexion?)</string>
<string name="err_server_ec">Impossible de contacter Extremcaching.com. Le site web peut ne pas fonctionner ou votre connexion Internet peut être défectueuse.</string>
@@ -178,7 +177,6 @@
<string name="err_log_load_data">c:geo ne peut pas charger les données pour enregistrer votre visite.</string>
<string name="err_log_load_data_again">c:geo ne peut pas charger les données pour enregistrer votre visite. Essayer plus tard.</string>
<string name="err_log_load_data_still">c:geo est en train de charger les données pour enregistrer votre visite. Veuillez patienter encore un peu.</string>
- <string name="err_log_failed_server">c:geo n\'a pas réussi à charger les données pour enregistrer votre visite car le serveur ne répond pas.</string>
<string name="err_log_post_failed">Il semble que votre visite n\'a pas été enregistrée. Veuillez vérifier sur le site Geocaching.com.</string>
<string name="err_log_post_failed_ec">Il semble que votre visite n\'a pas été enregistrée. Veuillez vérifier sur le site Extremcaching.com.</string>
<string name="err_logimage_post_failed">Il semble que l\'envoi de l\'image ait échoué. Veuillez vérifier sur le site Geocaching.com.</string>
@@ -651,7 +649,6 @@
<string name="cache_coordinates">Coordonnées</string>
<string name="cache_coordinates_original">Coordonnées d\'origine</string>
<string name="cache_spoiler_images_title">Images indices</string>
- <string name="cache_images_title">Images</string>
<string name="cache_log_types">Types de visites</string>
<string name="cache_coordinates_no">Cette cache n\'a pas de coordonnées.</string>
<string name="cache_clear_history">Effacer l\'historique</string>
@@ -1117,6 +1114,7 @@
<string name="tts_oclock">%s heures</string>
<string name="clipboard_copy_ok">Copié dans le presse-papiers</string>
<string name="percent_favorite_points">%\ favoris</string>
+ <string name="cgeo_shortcut">c:geo raccourci</string>
<string name="create_shortcut">Créer un raccourci</string>
<string-array name="log_image_scales">
<item>Taille originale</item>
diff --git a/main/res/values-hu/strings.xml b/main/res/values-hu/strings.xml
index f46885f..cfc4312 100644
--- a/main/res/values-hu/strings.xml
+++ b/main/res/values-hu/strings.xml
@@ -105,7 +105,6 @@
<string name="translate_to_english">Fordítás angolra</string>
<string name="translate_length_warning">A fordítás sikertelen lehet hosszú szövegeknél.</string>
<string name="err_none">Ok</string>
- <string name="err_start">A kommunikáció nem indult el</string>
<string name="err_parse">Hiba a belépőoldalon</string>
<string name="err_server">Hiba a kapcsolatban a geocaching.com-mal (a szerver vagy a kapcsolat nem működik?)</string>
<string name="err_login">Nincs mentett belépési adat</string>
@@ -157,7 +156,6 @@
<string name="err_log_load_data">Sajnáljuk, a c:geo nem tudja betölteni az adatokat amik a megtalálás bejelentéséhez szükségesek.</string>
<string name="err_log_load_data_again">Sajnáljuk, a c:geo nem tudja betölteni az adatokat amik a megtalálás bejelentéséhez szükségesek. Újrapróbálkozás.</string>
<string name="err_log_load_data_still">A c:geo még tölti az adatokat amik a megtalálás bejelentéséhez szükségesek. Kérlek várj egy kicsit tovább.</string>
- <string name="err_log_failed_server">Sajnáljuk, a c:geo-nak nem sikerült hozzáadni a logot mert a szerver nem válaszol.</string>
<string name="err_log_post_failed">Úgy tűnik a logot nem került hozzáadásra. Kérlek ellenőrizd a geocaching.com-on.</string>
<string name="err_search_address_forgot">Sajnáljuk, a c:geo elfelejtette a címet amit kerestél.</string>
<string name="err_parse_lat">Sajnáljuk, a c:geo nem tudja értelmezni a szélességet.</string>
@@ -503,7 +501,6 @@
<string name="cache_coordinates">Koordináták</string>
<string name="cache_coordinates_original">Eredeti koordináták</string>
<string name="cache_spoiler_images_title">Spoiler képek</string>
- <string name="cache_images_title">Képek</string>
<string name="cache_log_types">Bejegyzés típusok</string>
<string name="cache_coordinates_no">Ennek a ládának nincsenek koordinátái.</string>
<string name="cache_clear_history">Előzmények törlése</string>
diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml
index ae86197..8f26c2c 100644
--- a/main/res/values-it/strings.xml
+++ b/main/res/values-it/strings.xml
@@ -121,7 +121,6 @@
<string name="translate_to_english">Traduci in inglese</string>
<string name="translate_length_warning">La traduzione può fallire quando c\'è molto testo.</string>
<string name="err_none">OK</string>
- <string name="err_start">Comunicazione non avviata</string>
<string name="err_parse">Errore analizzando la pagina di login</string>
<string name="err_server">Connessione fallita con Geocaching.com (server o connessione non disponibile?)</string>
<string name="err_login">Informazioni di login non memorizzate</string>
@@ -177,7 +176,6 @@
<string name="err_log_load_data">c:geo non riesce a caricare i dati necessari per salvare il log della tua visita.</string>
<string name="err_log_load_data_again">c:geo non riesce a caricare i dati necessari per salvare il log della tua visita. Nuovo tentativo in corso.</string>
<string name="err_log_load_data_still">c:geo sta ancora caricando i dati necessari per salvare il log. Per cortesia attendere ancora un pochino.</string>
- <string name="err_log_failed_server">c:geo non è riuscito ad inviare il log perché il server non risponde.</string>
<string name="err_log_post_failed">Sembra che il log non sia stato inviato. Prego verificare su Geocaching.com.</string>
<string name="err_logimage_post_failed">Sembra che l\'immagine del tuo log non sia stata caricata. Si prega di controllare su Geocaching.com.</string>
<string name="err_search_address_forgot">c:geo ha dimenticato l\'indirizzo che vuoi trovare.</string>
@@ -608,7 +606,6 @@
<string name="cache_coordinates">Coordinate</string>
<string name="cache_coordinates_original">Coordinate originali</string>
<string name="cache_spoiler_images_title">Immagini spoiler</string>
- <string name="cache_images_title">Immagini</string>
<string name="cache_log_types">Tipi di Log</string>
<string name="cache_coordinates_no">Questo cache non ha coordinate.</string>
<string name="cache_clear_history">Cancella cronologia</string>
diff --git a/main/res/values-ja/strings.xml b/main/res/values-ja/strings.xml
index d7e5287..987391f 100644
--- a/main/res/values-ja/strings.xml
+++ b/main/res/values-ja/strings.xml
@@ -121,7 +121,6 @@
<string name="translate_to_english">英語に翻訳</string>
<string name="translate_length_warning">文章が長すぎるので翻訳できないかもしれません。</string>
<string name="err_none">OK</string>
- <string name="err_start">通信を始めることができませんでした</string>
<string name="err_parse">ログインページの解析に失敗しました</string>
<string name="err_server">Geocaching.comに接続できません。サーバが停止中かインターネットに未接続かもしれません。</string>
<string name="err_login">ログイン情報が保存されていません</string>
@@ -177,7 +176,6 @@
<string name="err_log_load_data">ログを書くのに必要なデータをロードすることができません。</string>
<string name="err_log_load_data_again">ログを書くのに必要なデータをロードすることができません。もう一度やってみてください。</string>
<string name="err_log_load_data_still">ログを投稿するのに必要なデータをまだロード中です。もう少しお待ちください。</string>
- <string name="err_log_failed_server">サーバの反応がないのでログを投稿することができませんでした。</string>
<string name="err_log_post_failed">ログを投稿することができなかったようです。Geocaching.comで確認してください。</string>
<string name="err_logimage_post_failed">ログの添付画像がアップロードされなかったようです。Geocaching.comで確認してください。</string>
<string name="err_search_address_forgot">c:geo forgot the address you tried to find.</string>
@@ -582,7 +580,6 @@
<string name="cache_coordinates">座標</string>
<string name="cache_coordinates_original">オリジナル座標</string>
<string name="cache_spoiler_images_title">スポイラー画像</string>
- <string name="cache_images_title">画像</string>
<string name="cache_log_types">ログタイプ</string>
<string name="cache_coordinates_no">このキャッシュに座標値はありません。</string>
<string name="cache_clear_history">全履歴を削除</string>
diff --git a/main/res/values-nb/strings.xml b/main/res/values-nb/strings.xml
index 6eb61a2..d5af0cf 100644
--- a/main/res/values-nb/strings.xml
+++ b/main/res/values-nb/strings.xml
@@ -69,7 +69,6 @@
<string name="log_new_log">Logg</string>
<string name="log_new_log_text">Logg tekst</string>
<string name="err_none">Ok</string>
- <string name="err_start">Klarte ikke å koble til</string>
<string name="err_parse">Klarte ikke å lese innloggings-siden</string>
<string name="err_server">Klarte ikke å koble til Geocaching.com (server eller tilkobling nede?)</string>
<string name="err_login">Ingen innloggings-opplysninger lagret</string>
@@ -103,7 +102,6 @@
<string name="err_log_load_data">Beklager, c:geo klarte ikke å laste den nødvendige informasjonen for å logge funnet.</string>
<string name="err_log_load_data_again">Beklager, c:geo klarte ikke å laste den nødvendige informasjonen for å logge funnet. c:geo prøver på nytt.</string>
<string name="err_log_load_data_still">c:geo laster fortsatt informasjonen som er nødvendig for å logge funnet. Vennligst vent.</string>
- <string name="err_log_failed_server">Beklager, c:geo klarte ikke å logge funnet fordi serveren er nede.</string>
<string name="err_log_post_failed">Beklager, c:geo klarte ikke å logge funnet.</string>
<string name="err_search_address_forgot">Beklager, c:geo glemte adressen du prøvde å finne.</string>
<string name="err_parse_lat">Beklager, c:geo klarte ikke å lese breddegraden.</string>
diff --git a/main/res/values-nl/strings.xml b/main/res/values-nl/strings.xml
index 27081f7..e1a4852 100644
--- a/main/res/values-nl/strings.xml
+++ b/main/res/values-nl/strings.xml
@@ -121,7 +121,6 @@
<string name="translate_to_english">Vertaal naar engels</string>
<string name="translate_length_warning">Vertaling kan mislukken bij grote stukken tekst.</string>
<string name="err_none">Ok</string>
- <string name="err_start">Communicatie niet gestart</string>
<string name="err_parse">Login pagina verwerken mislukt</string>
<string name="err_server">Verbinding met Geocaching.com mislukt (geen verbinding of server niet bereikbaar)</string>
<string name="err_login">Geen login informatie opgeslagen</string>
@@ -177,7 +176,6 @@
<string name="err_log_load_data">Sorry, c:geo kan data om bezoek te loggen niet laden.</string>
<string name="err_log_load_data_again">Sorry, c:geo kan data om bezoek te loggen niet laden. Bezig nogmaals te proberen.</string>
<string name="err_log_load_data_still">c:geo is nog steeds bezig om data te laden om bezoek te loggen. Graag nog even geduld.</string>
- <string name="err_log_failed_server">Sorry, c:geo kon bezoek niet loggen omdat de server niet reageert.</string>
<string name="err_log_post_failed">Sorry, het is c:geo niet gelukt het log te posten.</string>
<string name="err_logimage_post_failed">Het lijkt erop dat uw log-foto is niet geüpload. Controleer het op Geocaching.com.</string>
<string name="err_search_address_forgot">Sorry, c:geo is het adres dat je zoekt vergeten.</string>
@@ -599,7 +597,6 @@
<string name="cache_coordinates">Coördinaten</string>
<string name="cache_coordinates_original">Originele coordinaten</string>
<string name="cache_spoiler_images_title">Spoiler afbeeldingen</string>
- <string name="cache_images_title">Afbeeldingen</string>
<string name="cache_log_types">Log types</string>
<string name="cache_coordinates_no">Deze cache heeft geen coördinaten.</string>
<string name="cache_clear_history">Maak geschiedenis leeg</string>
diff --git a/main/res/values-pl/strings.xml b/main/res/values-pl/strings.xml
index 3fbbda6..90c17f7 100644
--- a/main/res/values-pl/strings.xml
+++ b/main/res/values-pl/strings.xml
@@ -121,7 +121,6 @@
<string name="translate_to_english">Przetłumacz na angielski</string>
<string name="translate_length_warning">Tłumaczenie może nie udać się przy dużej ilości tekstu.</string>
<string name="err_none">OK</string>
- <string name="err_start">Komunikacja nie rozpoczeła się</string>
<string name="err_parse">Nieudany odczyt strony logowania.</string>
<string name="err_server">Nieudane połączenie z Geocaching.com. Strona albo Twoje połączenie internetowe nie działa.</string>
<string name="err_login">Brak danych do logowania.</string>
@@ -177,7 +176,6 @@
<string name="err_log_load_data">c:geo nie może załadować danych wymaganych do wpisania wizyty.</string>
<string name="err_log_load_data_again">c:geo nie może załadować danych wymaganych do wpisania wizyty. Próbuję ponownie.</string>
<string name="err_log_load_data_still">Nadal trwa ładowanie danych wymaganych do wpisu w dzienniku. Proszę czekać…</string>
- <string name="err_log_failed_server">c:geo nie może dokonać wpisu ponieważ serwer nie odpowiada.</string>
<string name="err_log_post_failed">Wygląda na to, że Twój wpis nie został zapisany. Proszę sprawdź na Geocaching.com.</string>
<string name="err_logimage_post_failed">Wygląda na to, że Twój obraz nie został dodany. Proszę sprawdź to na Geocaching.com.</string>
<string name="err_search_address_forgot">c:geo zapomniał adresu, którego szukałeś.</string>
@@ -599,7 +597,6 @@
<string name="cache_coordinates">Współrzędne</string>
<string name="cache_coordinates_original">Oryginalne współrzędne</string>
<string name="cache_spoiler_images_title">Zdjęcia spoiler</string>
- <string name="cache_images_title">Zdjęcia</string>
<string name="cache_log_types">Rodzaj wpisu</string>
<string name="cache_coordinates_no">Ta skrzynka nie ma współrzędnych GPS.</string>
<string name="cache_clear_history">Usuń historię</string>
diff --git a/main/res/values-pt/strings.xml b/main/res/values-pt/strings.xml
index 5cb824c..0ecec98 100644
--- a/main/res/values-pt/strings.xml
+++ b/main/res/values-pt/strings.xml
@@ -121,7 +121,6 @@
<string name="translate_to_english">Traduzir para inglês</string>
<string name="translate_length_warning">A tradução pode falhar se o texto fôr muito grande.</string>
<string name="err_none">Ok</string>
- <string name="err_start">Comunicação não iniciada</string>
<string name="err_parse">Falha na análise da página de login</string>
<string name="err_server">Falha na ligação a Geocaching.com (servidor ou ligação em baixo?)</string>
<string name="err_login">Informação de login não gravada</string>
@@ -177,7 +176,6 @@
<string name="err_log_load_data">O c:geo não consegue carregar os dados necessários para registar a sua visita.</string>
<string name="err_log_load_data_again">O c:geo não consegue carregar os dados necessários para registar a sua visita. A tentar de novo.</string>
<string name="err_log_load_data_still">O c:geo ainda está a carregar dados necessários para publicar o registo. Por favor espere mais um pouco.</string>
- <string name="err_log_failed_server">O c:geo falhou a publicação do registo porque o servidor não responde.</string>
<string name="err_log_post_failed">O c:geo falhou a publicação do registo.</string>
<string name="err_logimage_post_failed">Parece que a sua imagem de registo não foi enviada. Por favor verifique em Geocaching.com.</string>
<string name="err_search_address_forgot">O c:geo esqueceu o endereço que procura.</string>
@@ -606,7 +604,6 @@
<string name="cache_coordinates">Coordenadas</string>
<string name="cache_coordinates_original">Coordenadas originais</string>
<string name="cache_spoiler_images_title">Imagens spoiler</string>
- <string name="cache_images_title">Imagens</string>
<string name="cache_log_types">Tipos de log</string>
<string name="cache_coordinates_no">Esta cache não tem coordenadas.</string>
<string name="cache_clear_history">Apagar histórico</string>
diff --git a/main/res/values-sk/strings.xml b/main/res/values-sk/strings.xml
index 615a630..278f5aa 100644
--- a/main/res/values-sk/strings.xml
+++ b/main/res/values-sk/strings.xml
@@ -105,7 +105,6 @@
<string name="translate_to_english">Preložiť do angličtiny</string>
<string name="translate_length_warning">Pre veľké texty môže preklad zlyhať.</string>
<string name="err_none">Ok</string>
- <string name="err_start">Komunikácia nezačala.</string>
<string name="err_parse">Zlyhalo čítanie prihlasovacej stránky.</string>
<string name="err_server">Zlyhalo pripojenie k serveru Geocaching.com (pripojenie, alebo server nefunkčný?)</string>
<string name="err_login">Nie sú uložené žiadne prihlasovacie údaje.</string>
@@ -157,7 +156,6 @@
<string name="err_log_load_data">c:geo nemôže načítať dáta potrebné pre zalogovanie návštevy.</string>
<string name="err_log_load_data_again">c:geo nemôže načítať dáta potrebné pre zalogovanie návštevy. Skúša to znovu.</string>
<string name="err_log_load_data_still">c:geo stále načítava dáta potrebné pre zalogovanie návštevy. Prosím, počkajte chvíľu.</string>
- <string name="err_log_failed_server">c:geo nemohlo odoslať log, pretože server neodpovedá.</string>
<string name="err_log_post_failed">c:geo nemohlo odoslať log.</string>
<string name="err_search_address_forgot">c:geo zabudlo adresu, ktorú sa pokúšate nájsť.</string>
<string name="err_parse_lat">c:geo nemôže dopočítať šírku.</string>
@@ -504,7 +502,6 @@
<string name="cache_coordinates">Súradnice</string>
<string name="cache_coordinates_original">Pôvodné súradnice</string>
<string name="cache_spoiler_images_title">Spoilerové obrázky</string>
- <string name="cache_images_title">Obrázky</string>
<string name="cache_log_types">Typy záznamov</string>
<string name="cache_coordinates_no">Táto skrýša nemá žiadne súradnice.</string>
<string name="cache_clear_history">Vymazať históriu</string>
diff --git a/main/res/values-sl/strings.xml b/main/res/values-sl/strings.xml
index 86e7ce7..dce642c 100644
--- a/main/res/values-sl/strings.xml
+++ b/main/res/values-sl/strings.xml
@@ -121,7 +121,6 @@
<string name="translate_to_english">Prevedi v: angleščino</string>
<string name="translate_length_warning">Prevod lahko spodleti zaradi velike količine besedila.</string>
<string name="err_none">OK</string>
- <string name="err_start">Komunikacija se ni začela</string>
<string name="err_parse">Razčlenjevanje prijavne strani ni uspelo</string>
<string name="err_server">Ni bilo mogoče vzpostaviti povezave z Geocaching.com. Spletna stran ali vaša povezava z internetom je lahko nedosegljiva.</string>
<string name="err_login">Prijavni podatki niso shranjeni</string>
@@ -177,7 +176,6 @@
<string name="err_log_load_data">c:geo ni mogel naložiti podatkov za zapis obiska.</string>
<string name="err_log_load_data_again">c:geo ne more naložiti podatkov za zapis obiska. Ponovni poskus…</string>
<string name="err_log_load_data_still">c:geo še vedno nalaga podatke za zapis obiska. Prosimo počakajte še trenutek.</string>
- <string name="err_log_failed_server">c:geo ni mogel objaviti zapisa, ker se strežnik ne odziva.</string>
<string name="err_log_post_failed">Izgleda, kot da zapis ni bil objavljen. Preverite na Geocaching.com.</string>
<string name="err_logimage_post_failed">Izgleda, kot da slika ni bila naložena. Preverite na Geocaching.com.</string>
<string name="err_search_address_forgot">c:geo je pozabil naslov, ki ste ga hoteli najti.</string>
@@ -598,7 +596,6 @@
<string name="cache_coordinates">Koordinate</string>
<string name="cache_coordinates_original">Originalne koordiante</string>
<string name="cache_spoiler_images_title">Spoiler slike</string>
- <string name="cache_images_title">Slike</string>
<string name="cache_log_types">Tipi zapisov</string>
<string name="cache_coordinates_no">Zaklad nima koordinat.</string>
<string name="cache_clear_history">Počisti zgodovino</string>
diff --git a/main/res/values-sv/strings.xml b/main/res/values-sv/strings.xml
index 463730e..6a8a200 100644
--- a/main/res/values-sv/strings.xml
+++ b/main/res/values-sv/strings.xml
@@ -121,7 +121,6 @@
<string name="translate_to_english">Översätt till engelska</string>
<string name="translate_length_warning">Översättningen kan misslyckas med långa texter.</string>
<string name="err_none">Ok</string>
- <string name="err_start">Kommunikationen har inte påbörjats</string>
<string name="err_parse">Misslyckades att analysera inloggningssidan</string>
<string name="err_server">Misslyckades att ansluta till Geocaching.com. Hemsidan kan vara ur funktion eller så är det problem med din anslutning till Internet.</string>
<string name="err_login">Inloggningsinformationen ej sparad</string>
@@ -177,7 +176,6 @@
<string name="err_log_load_data">Tyvärr kan c:geo inte ladda information som krävs för att logga ditt besök.</string>
<string name="err_log_load_data_again">Tyvärr kan c:geo inte ladda information som krävs för att logga ditt besök. Försöker igen.</string>
<string name="err_log_load_data_still">c:geo laddar fortfarande data för att kunna posta loggen. Vänligen vänta en stund till.</string>
- <string name="err_log_failed_server">Tyvärr misslyckades c:geo att posta loggen eftersom servern inte svarade.</string>
<string name="err_log_post_failed">Tyvärr misslyckades c:geo att posta loggen.</string>
<string name="err_logimage_post_failed">Det verkar som om din bild till loggen inte kunde laddas upp. Vänligen kontrollera den på Geocaching.com.</string>
<string name="err_search_address_forgot">Tyvärr glömde c:geo adressen du sökte efter.</string>
@@ -596,7 +594,6 @@
<string name="cache_coordinates">Koordinater</string>
<string name="cache_coordinates_original">Ursprungliga koordinater</string>
<string name="cache_spoiler_images_title">Spoiler bilder</string>
- <string name="cache_images_title">Bilder</string>
<string name="cache_log_types">Loggtyper</string>
<string name="cache_coordinates_no">Cachen saknar koordinater.</string>
<string name="cache_clear_history">Rensa historik</string>
diff --git a/main/res/values/changelog_master.xml b/main/res/values/changelog_master.xml
index 1e3c3d4..8ebc0f7 100644
--- a/main/res/values/changelog_master.xml
+++ b/main/res/values/changelog_master.xml
@@ -2,5 +2,12 @@
<resources>
<!-- changelog for the master branch -->
<string name="changelog_master" translatable="false">
+ <b>Next feature release</b>\n
+ <b>New Features:</b>\n
+ · Parallel loading from different platforms to speed up live map\n
+ <b>Bugfixing:</b>\n
+ · \n
+ \n
+ \n
</string>
</resources>
diff --git a/main/res/values/preference_keys.xml b/main/res/values/preference_keys.xml
index 0e4675d..d231795 100644
--- a/main/res/values/preference_keys.xml
+++ b/main/res/values/preference_keys.xml
@@ -6,13 +6,18 @@
and in the Java code as constants and avoid code duplication.
-->
- <string name="pref_fakekey_main_screen">fakekey_main_screen</string>
- <string name="pref_fakekey_services_screen">fakekey_services_screen</string>
- <string name="pref_fakekey_basicmembers_screen">fakekey_basicmembers_screen</string>
+ <string name="preference_screen_main">fakekey_main_screen</string>
+ <string name="preference_screen_services">fakekey_services_screen</string>
+ <string name="preference_screen_gc">preference_screen_gc</string>
+ <string name="preference_screen_basicmembers">fakekey_basicmembers_screen</string>
+ <string name="preference_screen_ocde">preference_screen_ocde</string>
+ <string name="preference_screen_ocpl">preference_screen_ocpl</string>
+ <string name="preference_screen_ec">preference_screen_ec</string>
+ <string name="preference_screen_twitter">preference_screen_twitter</string>
+ <string name="preference_screen_navigation_menu">fakekey_navigation_menu_screen</string>
<string name="pref_fakekey_ocde_authorization">fakekey_ocde_authorization</string>
<string name="pref_fakekey_ocpl_authorization">fakekey_ocpl_authorization</string>
<string name="pref_fakekey_twitter_authorization">fakekey_twitter_authorization</string>
- <string name="pref_fakekey_navigation_menu_screen">fakekey_navigation_menu_screen</string>
<string name="pref_connectorGCActive">connectorGCActive</string>
<string name="pref_username">username</string>
<string name="pref_password">password</string>
@@ -60,6 +65,7 @@
<string name="pref_fakekey_preference_backup_info">fakekey_preference_backup_info</string>
<string name="pref_fakekey_preference_backup">fakekey_preference_backup</string>
<string name="pref_fakekey_preference_restore">fakekey_preference_restore</string>
+ <string name="pref_fakekey_preference_maintenance_directories">pref_fakekey_preference_maintenance_directories</string>
<string name="pref_dbonsdcard">dbonsdcard</string>
<string name="pref_debug">debug</string>
<!-- preferences used internally -->
diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml
index 7b40811..38a2a8e 100644
--- a/main/res/values/strings.xml
+++ b/main/res/values/strings.xml
@@ -45,7 +45,9 @@
<string name="cache_size_virtual">Virtual</string>
<string name="cache_size_notchosen">Not chosen</string>
<string name="cache_size_unknown">Unknown</string>
-
+ <string name="cache_size_nano">Nano</string>
+ <string name="cache_size_very_large">Very large</string>
+
<!-- waypoints -->
<string name="wp_final">Final Location</string>
<string name="wp_stage">Stage of a Multicache</string>
@@ -145,7 +147,6 @@
<!-- errors, warnings, info toasts -->
<string name="err_none">OK</string>
- <string name="err_start">Communication not started</string>
<string name="err_parse">Failed Login page parsing</string>
<string name="err_server">Unable to contact Geocaching.com. The website may be down or your internet connection not working.</string>
<string name="err_server_ec">Unable to contact Extremcaching.com. The website may be down or your internet connection not working.</string>
@@ -202,7 +203,6 @@
<string name="err_log_load_data">c:geo can\'t load data required to log visit.</string>
<string name="err_log_load_data_again">c:geo can\'t load data required to log visit. Trying again.</string>
<string name="err_log_load_data_still">c:geo is still loading data required to post log. Please wait a little while longer.</string>
- <string name="err_log_failed_server">c:geo failed to post log because server is not responding.</string>
<string name="err_log_post_failed">It seems that your log was not posted. Please check it on Geocaching.com.</string>
<string name="err_log_post_failed_ec">It seems that your log was not posted. Please check it on Extremcaching.com.</string>
<string name="err_logimage_post_failed">It seems that your log image was not uploaded. Please check it on Geocaching.com.</string>
@@ -360,7 +360,8 @@
<string name="list_dialog_remove_err">c:geo failed to remove the current list</string>
<string name="list_dialog_rename_title">Rename list</string>
<string name="list_dialog_rename">Rename</string>
-
+ <string name="list_not_available">List no longer available, switching to standard list</string>
+
<!-- about -->
<string name="about_version">Version</string>
<string name="about_changelog">Changelog</string>
@@ -525,6 +526,9 @@
<string name="init_use_native_ua">Android browser</string>
<string name="init_summary_use_native_ua">Identify as Android browser. Solves login problems when using certain network providers.</string>
<string name="init_rendertheme_folder">Map Themes Directory</string>
+ <string name="init_maintenance">Maintenance</string>
+ <string name="init_maintenance_directories_note">c:geo stores images, log images and other files related to a cache in a separate directory. In some cases (like importing/exporting the database) this directory may contain outdated files, which can be deleted here.</string>
+ <string name="init_maintenance_directories">Delete orphaned files</string>
<string name="settings_open_website">Open website</string>
<string name="settings_settings">Settings</string>
<string name="settings_information">Information</string>
@@ -719,7 +723,6 @@
<string name="cache_coordinates">Coordinates</string>
<string name="cache_coordinates_original">Original Coordinates</string>
<string name="cache_spoiler_images_title">Spoiler images</string>
- <string name="cache_images_title">Images</string>
<string name="cache_log_types">Log types</string>
<string name="cache_coordinates_no">This cache has no coordinates.</string>
<string name="cache_clear_history">Clear history</string>
@@ -939,6 +942,8 @@
<string name="helper_calendar_missing">c:geo calendar add-on not installed.</string>
<string name="helper_calendar_description">Enables you to export event caches to the calendar on your device.</string>
<string name="helper_sendtocgeo_title">Send to c:geo</string>
+ <string name="helper_contacts_title">c:geo contacts add-on</string>
+ <string name="helper_contacts_description">Enables you to open a contact card (of your address book) directly from a log entry, so you can more easily ask friends for help.</string>
<string name="helper_sendtocgeo_description">Send to c:geo is a browser extension <strong>for your PC</strong>. When browsing geocaching.com, you can send caches to your smartphone with the click of a button directly inside the browser.</string>
<string name="helper_locus_title">Locus</string>
<string name="helper_locus_description">Simple, usable application which shows online maps and allows you to download them directly into Offline mode (raster maps only). Also supports track recording, POI handling and many other useful functions.</string>
@@ -1262,5 +1267,6 @@
<string name="percent_favorite_points">%\ favorites</string>
<!-- shortcuts -->
+ <string name="cgeo_shortcut">c:geo shortcut</string>
<string name="create_shortcut">Create shortcut</string>
</resources>
diff --git a/main/res/xml/preferences.xml b/main/res/xml/preferences.xml
index de0914e..ddd3dff 100644
--- a/main/res/xml/preferences.xml
+++ b/main/res/xml/preferences.xml
@@ -1,14 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cgeo="http://schemas.android.com/apk/res/cgeo.geocaching"
- android:key="@string/pref_fakekey_main_screen" >
+ android:key="@string/preference_screen_main" >
<PreferenceScreen
android:icon="?attr/settings_cloud"
- android:key="@string/pref_fakekey_services_screen"
+ android:key="@string/preference_screen_services"
android:title="@string/settings_title_services" >
<PreferenceCategory android:title="@string/settings_category_geocaching" >
- <PreferenceScreen android:title="@string/settings_title_gc" >
+ <PreferenceScreen
+ android:key="@string/preference_screen_gc"
+ android:title="@string/settings_title_gc" >
<PreferenceCategory android:title="@string/settings_settings" >
<cgeo.geocaching.settings.CheckBoxWithPopupPreference
android:defaultValue="true"
@@ -44,7 +46,7 @@
<PreferenceScreen
android:dependency="@string/pref_connectorGCActive"
- android:key="@string/pref_fakekey_basicmembers_screen"
+ android:key="@string/preference_screen_basicmembers"
android:title="@string/settings_title_basicmembers" >
<CheckBoxPreference
android:defaultValue="false"
@@ -74,7 +76,9 @@
android:title="@string/settings_open_website" />
</PreferenceCategory>
</PreferenceScreen>
- <PreferenceScreen android:title="@string/init_oc" >
+ <PreferenceScreen
+ android:key="@string/preference_screen_ocde"
+ android:title="@string/init_oc" >
<PreferenceCategory android:title="@string/settings_settings" >
<CheckBoxPreference
android:defaultValue="false"
@@ -94,12 +98,15 @@
<cgeo.geocaching.settings.CapabilitiesPreference
android:title="@string/settings_features"
cgeo:connector="OC" />
+
<Preference
android:key="@string/pref_fakekey_ocde_website"
android:title="@string/settings_open_website" />
</PreferenceCategory>
</PreferenceScreen>
- <PreferenceScreen android:title="@string/init_oc_pl" >
+ <PreferenceScreen
+ android:key="@string/preference_screen_ocpl"
+ android:title="@string/init_oc_pl" >
<PreferenceCategory android:title="@string/settings_settings" >
<CheckBoxPreference
android:defaultValue="false"
@@ -119,13 +126,13 @@
<cgeo.geocaching.settings.CapabilitiesPreference
android:title="@string/settings_features"
cgeo:connector="OP" />
+
<Preference
android:key="@string/pref_fakekey_ocpl_website"
android:title="@string/settings_open_website" />
</PreferenceCategory>
</PreferenceScreen>
-
- <PreferenceScreen android:title="@string/settings_title_ec" >
+ <PreferenceScreen android:title="@string/settings_title_ec" android:key="@string/preference_screen_ec">
<PreferenceCategory android:title="@string/settings_settings" >
<CheckBoxPreference
android:defaultValue="false"
@@ -150,30 +157,31 @@
android:key="@string/pref_ecpassword"
android:singleLine="true"
android:title="@string/init_password" />
+
<cgeo.geocaching.settings.CheckECCredentialsPreference
android:dependency="@string/pref_connectorECActive"
android:title="@string/init_login" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/settings_title_appearance" >
- <ListPreference
- android:dependency="@string/pref_connectorECActive"
- android:defaultValue="1"
- android:dialogTitle="@string/init_ec_icons"
- android:key="@string/pref_ec_icons"
- android:title="@string/init_ec_icons"
- android:entries="@array/ECIcons"
- android:entryValues="@array/ECIconsValues" />
+ <ListPreference
+ android:defaultValue="1"
+ android:dependency="@string/pref_connectorECActive"
+ android:dialogTitle="@string/init_ec_icons"
+ android:entries="@array/ECIcons"
+ android:entryValues="@array/ECIconsValues"
+ android:key="@string/pref_ec_icons"
+ android:title="@string/init_ec_icons" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/settings_information" >
<cgeo.geocaching.settings.CapabilitiesPreference
android:title="@string/settings_features"
cgeo:connector="EC" />
+
<Preference
android:key="@string/pref_fakekey_ec_website"
android:title="@string/settings_open_website" />
</PreferenceCategory>
</PreferenceScreen>
-
<PreferenceScreen android:title="@string/settings_title_ox" >
<PreferenceCategory android:title="@string/settings_settings" >
<CheckBoxPreference
@@ -185,12 +193,12 @@
<cgeo.geocaching.settings.CapabilitiesPreference
android:title="@string/settings_features"
cgeo:connector="OX" />
+
<Preference
android:key="@string/pref_fakekey_ox_website"
android:title="@string/settings_open_website" />
</PreferenceCategory>
</PreferenceScreen>
-
<PreferenceScreen android:title="@string/init_gcvote" >
<PreferenceCategory android:title="@string/settings_settings" >
<cgeo.geocaching.settings.EditPasswordPreference
@@ -233,7 +241,9 @@
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory android:title="@string/settings_category_social" >
- <PreferenceScreen android:title="@string/init_twitter" >
+ <PreferenceScreen
+ android:key="@string/preference_screen_twitter"
+ android:title="@string/init_twitter" >
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/pref_twitter"
@@ -470,7 +480,7 @@
android:text="@string/init_navigation_menu_description" />
<PreferenceScreen
- android:key="@string/pref_fakekey_navigation_menu_screen"
+ android:key="@string/preference_screen_navigation_menu"
android:title="@string/settings_title_navigation_menu" >
<CheckBoxPreference
android:defaultValue="true"
@@ -609,6 +619,15 @@
android:key="@string/pref_dbonsdcard"
android:title="@string/init_dbonsdcard" />
</PreferenceCategory>
+ <PreferenceCategory android:title="@string/init_maintenance" >
+ <cgeo.geocaching.settings.TextPreference
+ android:layout="@layout/text_preference"
+ android:text="@string/init_maintenance_directories_note" />
+
+ <Preference
+ android:key="@string/pref_fakekey_preference_maintenance_directories"
+ android:title="@string/init_maintenance_directories" />
+ </PreferenceCategory>
<PreferenceCategory android:title="@string/init_debug_title" >
<cgeo.geocaching.settings.TextPreference
android:layout="@layout/text_preference"
diff --git a/main/res/xml/searchable.xml b/main/res/xml/searchable.xml
index 13e34c5..a3844cf 100644
--- a/main/res/xml/searchable.xml
+++ b/main/res/xml/searchable.xml
@@ -6,6 +6,7 @@
android:inputType="textNoSuggestions"
android:label="@string/app_name"
android:searchSettingsDescription="@string/search_bar_desc"
+ android:searchSuggestAuthority="cgeo.geocaching.search.SuggestionProvider"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
</searchable> \ No newline at end of file
diff --git a/main/src/cgeo/calendar/CalendarAddon.java b/main/src/cgeo/calendar/CalendarAddon.java
new file mode 100644
index 0000000..117fb9a
--- /dev/null
+++ b/main/src/cgeo/calendar/CalendarAddon.java
@@ -0,0 +1,58 @@
+package cgeo.calendar;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
+import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.ui.dialog.Dialogs;
+import cgeo.geocaching.utils.ProcessUtils;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.app.Activity;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+
+import java.util.Date;
+
+public class CalendarAddon {
+ public static boolean isAvailable() {
+ return ProcessUtils.isIntentAvailable(ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST));
+ }
+
+ public static void addToCalendarWithIntent(final Activity activity, final Geocache cache) {
+ final Resources res = activity.getResources();
+ if (CalendarAddon.isAvailable()) {
+ final Date hiddenDate = cache.getHiddenDate();
+ final Parameters params = new Parameters(
+ ICalendar.PARAM_NAME, cache.getName(),
+ ICalendar.PARAM_NOTE, StringUtils.defaultString(cache.getPersonalNote()),
+ ICalendar.PARAM_HIDDEN_DATE, hiddenDate != null ? String.valueOf(hiddenDate.getTime()) : StringUtils.EMPTY,
+ ICalendar.PARAM_URL, StringUtils.defaultString(cache.getUrl()),
+ ICalendar.PARAM_COORDS, cache.getCoords() == null ? "" : cache.getCoords().format(GeopointFormatter.Format.LAT_LON_DECMINUTE_RAW),
+ ICalendar.PARAM_LOCATION, StringUtils.defaultString(cache.getLocation()),
+ ICalendar.PARAM_SHORT_DESC, StringUtils.defaultString(cache.getShortDescription()),
+ ICalendar.PARAM_START_TIME_MINUTES, StringUtils.defaultString(cache.guessEventTimeMinutes())
+ );
+
+ activity.startActivity(new Intent(ICalendar.INTENT,
+ Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST + "?" + params.toString())));
+ } else {
+ // Inform user the calendar add-on is not installed and let them get it from Google Play
+ Dialogs.confirmYesNo(activity, R.string.addon_missing_title, new StringBuilder(res.getString(R.string.helper_calendar_missing))
+ .append(' ')
+ .append(res.getString(R.string.addon_download_prompt))
+ .toString(), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ final Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(ICalendar.CALENDAR_ADDON_URI));
+ activity.startActivity(intent);
+ }
+ });
+ }
+ }
+
+}
diff --git a/main/src/cgeo/calendar/ICalendar.java b/main/src/cgeo/calendar/ICalendar.java
index 933d248..6ecb6d5 100644
--- a/main/src/cgeo/calendar/ICalendar.java
+++ b/main/src/cgeo/calendar/ICalendar.java
@@ -14,6 +14,6 @@ public interface ICalendar {
static final String PARAM_NOTE = "note"; // personal note
static final String PARAM_NAME = "name"; // cache name
static final String PARAM_LOCATION = "location"; // cache location, or empty string
- static final String PARAM_COORDS = "coords"; // cache coords, or empty string
+ static final String PARAM_COORDS = "coords"; // cache coordinates, or empty string
static final String PARAM_START_TIME_MINUTES = "time"; // time of start
}
diff --git a/main/src/cgeo/contacts/IContacts.java b/main/src/cgeo/contacts/IContacts.java
index d46a5a4..d68b78a 100644
--- a/main/src/cgeo/contacts/IContacts.java
+++ b/main/src/cgeo/contacts/IContacts.java
@@ -1,8 +1,6 @@
package cgeo.contacts;
public interface IContacts {
- static final String CALENDAR_ADDON_URI = "market://details?id=cgeo.contacts";
-
static final String INTENT = "cgeo.contacts.FIND";
static final String URI_SCHEME = "find";
diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java
index 5f24030..38e37da 100644
--- a/main/src/cgeo/geocaching/AbstractPopupActivity.java
+++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java
@@ -40,7 +40,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity implements
private final GeoDirHandler geoUpdate = new GeoDirHandler() {
@Override
- protected void updateGeoData(final IGeoData geo) {
+ public void updateGeoData(final IGeoData geo) {
try {
if (geo.getCoords() != null && cache != null && cache.getCoords() != null) {
cacheDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(cache.getCoords())));
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index 4068e38..6962317 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -3,6 +3,7 @@ package cgeo.geocaching;
import butterknife.ButterKnife;
import butterknife.InjectView;
+import cgeo.calendar.CalendarAddon;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.AbstractViewPagerActivity;
import cgeo.geocaching.activity.Progress;
@@ -45,7 +46,6 @@ import cgeo.geocaching.utils.HtmlUtils;
import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
-import cgeo.geocaching.utils.RunnableWithArgument;
import cgeo.geocaching.utils.SimpleCancellableHandler;
import cgeo.geocaching.utils.SimpleHandler;
import cgeo.geocaching.utils.TextUtils;
@@ -57,6 +57,14 @@ import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
+import rx.Observable;
+import rx.Observable.OnSubscribeFunc;
+import rx.Observer;
+import rx.Subscription;
+import rx.android.observables.AndroidObservable;
+import rx.concurrency.Schedulers;
+import rx.subscriptions.Subscriptions;
+import rx.util.functions.Action1;
import android.R.color;
import android.app.AlertDialog;
@@ -80,7 +88,6 @@ import android.text.Editable;
import android.text.Html;
import android.text.Spannable;
import android.text.Spanned;
-import android.text.format.DateUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
@@ -109,7 +116,6 @@ import android.widget.TextView.BufferType;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
@@ -176,24 +182,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// set title in code, as the activity needs a hard coded title due to the intent filters
setTitle(res.getString(R.string.cache));
- String geocode = null;
-
- // TODO Why can it happen that search is not null? onCreate should be called only once and it is not set before.
- if (search != null) {
- cache = search.getFirstCacheFromResult(LoadFlags.LOAD_ALL_DB_ONLY);
- if (cache != null && cache.getGeocode() != null) {
- geocode = cache.getGeocode();
- }
- }
-
// get parameters
final Bundle extras = getIntent().getExtras();
final Uri uri = getIntent().getData();
// try to get data from extras
String name = null;
+ String geocode = null;
String guid = null;
- if (geocode == null && extras != null) {
+ if (extras != null) {
geocode = extras.getString(Intents.EXTRA_GEOCODE);
name = extras.getString(Intents.EXTRA_NAME);
guid = extras.getString(Intents.EXTRA_GUID);
@@ -327,6 +324,14 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
@Override
+ public void onDestroy() {
+ if (imagesList != null) {
+ imagesList.removeAllViews();
+ }
+ super.onDestroy();
+ }
+
+ @Override
public void onStop() {
if (cache != null) {
cache.setChangeNotificationHandler(null);
@@ -382,6 +387,12 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
clickedItemText = ((TextView) view).getText();
buildDetailsContextMenu(menu, res.getString(R.string.cache_logs), false);
break;
+ case R.id.date: // event date
+ assert view instanceof TextView;
+ clickedItemText = ((TextView) view).getText();
+ buildDetailsContextMenu(menu, res.getString(R.string.cache_event), true);
+ menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar());
+ break;
case R.id.waypoint:
menu.setHeaderTitle(selectedWaypoint.getName() + " (" + res.getString(R.string.waypoint) + ")");
getMenuInflater().inflate(R.menu.waypoint_options, menu);
@@ -484,6 +495,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
new ResetCoordsThread(cache, handler, selectedWaypoint, true, false, progressDialog).start();
}
return true;
+ case R.id.menu_calendar:
+ CalendarAddon.addToCalendarWithIntent(this, cache);
+ return true;
default:
break;
}
@@ -542,20 +556,19 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) {
updateStatusMsg((String) msg.obj);
} else {
- CacheDetailActivity activity = ((CacheDetailActivity) activityRef.get());
+ final CacheDetailActivity activity = ((CacheDetailActivity) activityRef.get());
if (activity == null) {
return;
}
- SearchResult search = activity.getSearch();
- if (search == null) {
+ if (activity.search == null) {
showToast(R.string.err_dwld_details_failed);
dismissProgress();
finishActivity();
return;
}
- if (search.getError() != null) {
- activity.showToast(activity.getResources().getString(R.string.err_dwld_details_failed) + " " + search.getError().getErrorString(activity.getResources()) + ".");
+ if (activity.search.getError() != null) {
+ activity.showToast(activity.getResources().getString(R.string.err_dwld_details_failed) + " " + activity.search.getError().getErrorString(activity.getResources()) + ".");
dismissProgress();
finishActivity();
return;
@@ -972,17 +985,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
ownerView.setOnClickListener(new OwnerActionsClickListener(cache));
}
- // cache hidden
- final Date hiddenDate = cache.getHiddenDate();
- if (hiddenDate != null) {
- final long time = hiddenDate.getTime();
- if (time > 0) {
- String dateString = Formatter.formatFullDate(time);
- if (cache.isEventCache()) {
- dateString = DateUtils.formatDateTime(CgeoApplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY) + ", " + dateString;
- }
- details.add(cache.isEventCache() ? R.string.cache_event : R.string.cache_hidden, dateString);
- }
+ // hidden or event date
+ final TextView hiddenView = details.addHiddenDate(cache);
+ if (hiddenView != null) {
+ registerForContextMenu(hiddenView);
}
// cache location
@@ -1051,9 +1057,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (Settings.getChooseList()) {
// let user select list to store cache in
new StoredList.UserInterface(CacheDetailActivity.this).promptForListSelection(R.string.list_title,
- new RunnableWithArgument<Integer>() {
+ new Action1<Integer>() {
@Override
- public void run(final Integer selectedListId) {
+ public void call(final Integer selectedListId) {
storeCache(selectedListId, new StoreCacheHandler(CacheDetailActivity.this, progress));
}
}, true, StoredList.TEMPORARY_LIST_ID);
@@ -1302,9 +1308,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
@Override
public void onClick(View view) {
new StoredList.UserInterface(CacheDetailActivity.this).promptForListSelection(R.string.list_title,
- new RunnableWithArgument<Integer>() {
+ new Action1<Integer>() {
@Override
- public void run(final Integer selectedListId) {
+ public void call(final Integer selectedListId) {
switchListById(selectedListId);
}
}, true, cache.getListId());
@@ -1368,7 +1374,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final LinearLayout layout = (LinearLayout) view.findViewById(R.id.favpoint_box);
final boolean supportsFavoritePoints = cache.supportsFavoritePoints();
layout.setVisibility(supportsFavoritePoints ? View.VISIBLE : View.GONE);
- if (!supportsFavoritePoints || cache.isOwner() || !Settings.isPremiumMember()) {
+ if (!supportsFavoritePoints || cache.isOwner() || !Settings.isGCPremiumMember()) {
return;
}
final Button buttonAdd = (Button) view.findViewById(R.id.add_to_favpoint);
@@ -1470,6 +1476,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
protected class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
@InjectView(R.id.personalnote) protected TextView personalNoteView;
+ @InjectView(R.id.shortdesc) protected IndexOutOfBoundsAvoidingTextView shortDescView;
+ @InjectView(R.id.longdesc) protected IndexOutOfBoundsAvoidingTextView longDescView;
+ @InjectView(R.id.show_description) protected Button showDesc;
+ @InjectView(R.id.loading) protected View loadingView;
@Override
public ScrollView getDispatchedView() {
@@ -1483,7 +1493,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// cache short description
if (StringUtils.isNotBlank(cache.getShortDescription())) {
- new LoadDescriptionTask(cache.getShortDescription(), view.findViewById(R.id.shortdesc), null, null).execute();
+ loadDescription(cache.getShortDescription(), shortDescView, null);
}
// long description
@@ -1491,7 +1501,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (Settings.isAutoLoadDescription()) {
loadLongDescription();
} else {
- final Button showDesc = (Button) view.findViewById(R.id.show_description);
showDesc.setVisibility(View.VISIBLE);
showDesc.setOnClickListener(new View.OnClickListener() {
@Override
@@ -1605,12 +1614,23 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
private void loadLongDescription() {
- final Button showDesc = (Button) view.findViewById(R.id.show_description);
showDesc.setVisibility(View.GONE);
showDesc.setOnClickListener(null);
view.findViewById(R.id.loading).setVisibility(View.VISIBLE);
- new LoadDescriptionTask(cache.getDescription(), view.findViewById(R.id.longdesc), view.findViewById(R.id.loading), view.findViewById(R.id.shortdesc)).execute();
+ final String longDescription = cache.getDescription();
+ loadDescription(longDescription, longDescView, loadingView);
+
+ // Hide the short description, if it is contained somewhere at the start of the long description.
+ if (shortDescView != null) {
+ final String shortDescription = cache.getShortDescription();
+ if (StringUtils.isNotBlank(shortDescription)) {
+ final int index = longDescription.indexOf(shortDescription);
+ if (index >= 0 && index < 200) {
+ shortDescView.setVisibility(View.GONE);
+ }
+ }
+ }
}
private void warnPersonalNoteNeedsStoring() {
@@ -1641,148 +1661,119 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
- /**
- * Loads the description in background. <br />
- * <br />
- * Params:
- * <ol>
- * <li>description string (String)</li>
- * <li>target description view (TextView)</li>
- * <li>loading indicator view (View, may be null)</li>
- * </ol>
- */
- private class LoadDescriptionTask extends AsyncTask<Object, Void, Void> {
- private final View loadingIndicatorView;
- private final IndexOutOfBoundsAvoidingTextView descriptionView;
- private final String descriptionString;
- private Spanned description;
- private final View shortDescView;
+ /**
+ * Load the description in the background.
+ * @param descriptionString the HTML description as retrieved from the connector
+ * @param descriptionView the view to fill
+ * @param loadingIndicatorView the loading indicator view, will be hidden when completed
+ */
+ private void loadDescription(final String descriptionString, final IndexOutOfBoundsAvoidingTextView descriptionView, final View loadingIndicatorView) {
+ // The producer produces successives (without then with images) versions of the description.
+ final Observable<Spanned> producer = Observable.create(new OnSubscribeFunc<Spanned>() {
+ @Override
+ public Subscription onSubscribe(final Observer<? super Spanned> observer) {
+ try {
+ // Fast preview: parse only HTML without loading any images
+ final HtmlImageCounter imageCounter = new HtmlImageCounter();
+ final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler();
+ Spanned description = Html.fromHtml(descriptionString, imageCounter, unknownTagsHandler);
+ addWarning(unknownTagsHandler, description);
+ observer.onNext(description);
+
+ if (imageCounter.getImageCount() > 0) {
+ // Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview
+ description = Html.fromHtml(descriptionString, new HtmlImage(cache.getGeocode(), true, cache.getListId(), false), unknownTagsHandler);
+ addWarning(unknownTagsHandler, description);
+ observer.onNext(description);
+ }
- public LoadDescriptionTask(final String description, final View descriptionView, final View loadingIndicatorView, final View shortDescView) {
- assert descriptionView instanceof IndexOutOfBoundsAvoidingTextView;
- this.descriptionString = description;
- this.descriptionView = (IndexOutOfBoundsAvoidingTextView) descriptionView;
- this.loadingIndicatorView = loadingIndicatorView;
- this.shortDescView = shortDescView;
- }
+ observer.onCompleted();
+ } catch (final Exception e) {
+ Log.e("loadDescription", e);
+ observer.onError(e);
+ }
+ return Subscriptions.empty();
+ }
- @Override
- protected Void doInBackground(Object... params) {
- try {
- // Fast preview: parse only HTML without loading any images
- final HtmlImageCounter imageCounter = new HtmlImageCounter();
- final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler();
- description = Html.fromHtml(descriptionString, imageCounter, unknownTagsHandler);
- publishProgress();
-
- boolean needsRefresh = false;
- if (imageCounter.getImageCount() > 0) {
- // Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview
- description = Html.fromHtml(descriptionString, new HtmlImage(cache.getGeocode(), true, cache.getListId(), false), unknownTagsHandler);
- needsRefresh = true;
- }
-
- // If description has an HTML construct which may be problematic to render, add a note at the end of the long description.
- // Technically, it may not be a table, but a pre, which has the same problems as a table, so the message is ok even though
- // sometimes technically incorrect.
- if (unknownTagsHandler.isProblematicDetected() && descriptionView != null) {
+ // If description has an HTML construct which may be problematic to render, add a note at the end of the long description.
+ // Technically, it may not be a table, but a pre, which has the same problems as a table, so the message is ok even though
+ // sometimes technically incorrect.
+ private void addWarning(final UnknownTagsHandler unknownTagsHandler, final Spanned description) {
+ if (unknownTagsHandler.isProblematicDetected()) {
final int startPos = description.length();
final IConnector connector = ConnectorFactory.getConnector(cache);
final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>"));
((Editable) description).append("\n\n").append(tableNote);
((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- needsRefresh = true;
- }
-
- if (needsRefresh) {
- publishProgress();
- }
- } catch (final Exception e) {
- Log.e("LoadDescriptionTask: ", e);
- }
- return null;
- }
-
- @Override
- protected void onProgressUpdate(Void... values) {
- if (description == null) {
- showToast(res.getString(R.string.err_load_descr_failed));
- return;
- }
- if (StringUtils.isNotBlank(descriptionString)) {
- try {
- descriptionView.setText(description, TextView.BufferType.SPANNABLE);
- } catch (final Exception e) {
- // On 4.1, there is sometimes a crash on measuring the layout: https://code.google.com/p/android/issues/detail?id=35412
- Log.e("Android bug setting text: ", e);
- // remove the formatting by converting to a simple string
- descriptionView.setText(description.toString());
}
- descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
- fixTextColor(descriptionView, descriptionString);
- descriptionView.setVisibility(View.VISIBLE);
- registerForContextMenu(descriptionView);
-
- hideDuplicatedShortDescription();
}
- }
+ });
- /**
- * Hide the short description, if it is contained somewhere at the start of the long description.
- */
- private void hideDuplicatedShortDescription() {
- if (shortDescView != null) {
- final String shortDescription = cache.getShortDescription();
- if (StringUtils.isNotBlank(shortDescription)) {
- final int index = descriptionString.indexOf(shortDescription);
- if (index >= 0 && index < 200) {
- shortDescView.setVisibility(View.GONE);
+ AndroidObservable.fromActivity(this, producer.subscribeOn(Schedulers.threadPoolForIO()))
+ .subscribe(new Observer<Spanned>() {
+ @Override
+ public void onCompleted() {
+ if (null != loadingIndicatorView) {
+ loadingIndicatorView.setVisibility(View.GONE);
+ }
}
- }
- }
- }
- @Override
- protected void onPostExecute(Void result) {
- if (null != loadingIndicatorView) {
- loadingIndicatorView.setVisibility(View.GONE);
- }
- }
+ @Override
+ public void onError(final Throwable throwable) {
+ showToast(res.getString(R.string.err_load_descr_failed));
+ }
- /**
- * Handle caches with black font color in dark skin and white font color in light skin
- * by changing background color of the view
- *
- * @param view
- * containing the text
- * @param text
- * to be checked
- */
- private void fixTextColor(final TextView view, final String text) {
- int backcolor;
- if (Settings.isLightSkin()) {
- backcolor = color.white;
-
- for (final Pattern pattern : LIGHT_COLOR_PATTERNS) {
- final MatcherWrapper matcher = new MatcherWrapper(pattern, text);
- if (matcher.find()) {
- view.setBackgroundResource(color.darker_gray);
- return;
+ @Override
+ public void onNext(final Spanned description) {
+ if (StringUtils.isNotBlank(descriptionString)) {
+ try {
+ descriptionView.setText(description, TextView.BufferType.SPANNABLE);
+ } catch (final Exception e) {
+ // On 4.1, there is sometimes a crash on measuring the layout: https://code.google.com/p/android/issues/detail?id=35412
+ Log.e("Android bug setting text: ", e);
+ // remove the formatting by converting to a simple string
+ descriptionView.setText(description.toString());
+ }
+ descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
+ fixTextColor(descriptionString);
+ descriptionView.setVisibility(View.VISIBLE);
+ registerForContextMenu(descriptionView);
+ }
}
- }
- } else {
- backcolor = color.black;
- for (final Pattern pattern : DARK_COLOR_PATTERNS) {
- final MatcherWrapper matcher = new MatcherWrapper(pattern, text);
- if (matcher.find()) {
- view.setBackgroundResource(color.darker_gray);
- return;
+ /**
+ * Handle caches with black font color in dark skin and white font color in light skin
+ * by changing background color of the view
+ *
+ * @param text
+ * to be checked
+ */
+ private void fixTextColor(final String text) {
+ int backcolor;
+ if (Settings.isLightSkin()) {
+ backcolor = color.white;
+
+ for (final Pattern pattern : LIGHT_COLOR_PATTERNS) {
+ final MatcherWrapper matcher = new MatcherWrapper(pattern, text);
+ if (matcher.find()) {
+ descriptionView.setBackgroundResource(color.darker_gray);
+ return;
+ }
+ }
+ } else {
+ backcolor = color.black;
+
+ for (final Pattern pattern : DARK_COLOR_PATTERNS) {
+ final MatcherWrapper matcher = new MatcherWrapper(pattern, text);
+ if (matcher.find()) {
+ descriptionView.setBackgroundResource(color.darker_gray);
+ return;
+ }
+ }
+ }
+ descriptionView.setBackgroundResource(backcolor);
}
- }
- }
- view.setBackgroundResource(backcolor);
- }
+ });
}
private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ListView> {
@@ -2255,10 +2246,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return cache;
}
- public SearchResult getSearch() {
- return search;
- }
-
private static class StoreCacheHandler extends SimpleCancellableHandler {
public StoreCacheHandler(CacheDetailActivity activity, Progress progress) {
diff --git a/main/src/cgeo/geocaching/CacheListActivity.java b/main/src/cgeo/geocaching/CacheListActivity.java
index cc8b178..50c6ab7 100644
--- a/main/src/cgeo/geocaching/CacheListActivity.java
+++ b/main/src/cgeo/geocaching/CacheListActivity.java
@@ -18,11 +18,13 @@ import cgeo.geocaching.files.GPXImporter;
import cgeo.geocaching.filter.FilterUserInterface;
import cgeo.geocaching.filter.IFilter;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.list.PseudoList;
import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.loaders.AbstractSearchLoader;
import cgeo.geocaching.loaders.AbstractSearchLoader.CacheListLoaderType;
import cgeo.geocaching.loaders.AddressGeocacheListLoader;
import cgeo.geocaching.loaders.CoordsGeocacheListLoader;
+import cgeo.geocaching.loaders.FinderGeocacheListLoader;
import cgeo.geocaching.loaders.HistoryGeocacheListLoader;
import cgeo.geocaching.loaders.KeywordGeocacheListLoader;
import cgeo.geocaching.loaders.NextPageGeocacheListLoader;
@@ -30,7 +32,6 @@ import cgeo.geocaching.loaders.OfflineGeocacheListLoader;
import cgeo.geocaching.loaders.OwnerGeocacheListLoader;
import cgeo.geocaching.loaders.PocketGeocacheListLoader;
import cgeo.geocaching.loaders.RemoveFromHistoryLoader;
-import cgeo.geocaching.loaders.FinderGeocacheListLoader;
import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.network.Cookies;
import cgeo.geocaching.network.Network;
@@ -43,10 +44,10 @@ import cgeo.geocaching.ui.LoggingUI;
import cgeo.geocaching.ui.WeakReferenceHandler;
import cgeo.geocaching.ui.dialog.Dialogs;
import cgeo.geocaching.utils.AsyncTaskWithProgress;
+import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.DateUtils;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RunnableWithArgument;
import ch.boye.httpclientandroidlib.HttpResponse;
@@ -55,6 +56,8 @@ import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
+import rx.util.functions.Action1;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@@ -93,7 +96,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private static final int MAX_LIST_ITEMS = 1000;
private static final int MSG_DONE = -1;
- private static final int MSG_CANCEL = -99;
private static final int REQUEST_CODE_IMPORT_GPX = 1;
@@ -111,8 +113,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private int detailTotal = 0;
private int detailProgress = 0;
private long detailProgressTime = 0L;
- private LoadDetailsThread threadDetails = null;
- private LoadFromWebThread threadWeb = null;
private int listId = StoredList.TEMPORARY_LIST_ID; // Only meaningful for the OFFLINE type
private final GeoDirHandler geoDirHandler = new GeoDirHandler() {
@@ -267,10 +267,10 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
}
- private final Handler loadDetailsHandler = new Handler() {
+ private final CancellableHandler loadDetailsHandler = new CancellableHandler() {
@Override
- public void handleMessage(Message msg) {
+ public void handleRegularMessage(Message msg) {
setAdapter();
if (msg.what > -1) {
@@ -287,10 +287,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
} else {
progress.setMessage(res.getString(R.string.caches_downloading) + " " + minutesRemaining + " " + res.getQuantityString(R.plurals.caches_eta_mins, minutesRemaining));
}
- } else if (msg.what == MSG_CANCEL) {
- if (threadDetails != null) {
- threadDetails.kill();
- }
} else {
if (search != null) {
final Set<Geocache> cacheListTmp = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
@@ -304,13 +300,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
showProgress(false);
progress.dismiss();
-
- if (!isPaused()) {
- // If the current activity has been paused, then we do not want to fiddle with the
- // GPS and direction states. If the activity later gets resumed, its onResume()
- // function will take care of turning the GPS back on.
- startGeoAndDir();
- }
}
}
};
@@ -318,9 +307,9 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
/**
* TODO Possibly parts should be a Thread not a Handler
*/
- private final Handler downloadFromWebHandler = new Handler() {
+ private final CancellableHandler downloadFromWebHandler = new CancellableHandler() {
@Override
- public void handleMessage(Message msg) {
+ public void handleRegularMessage(Message msg) {
setAdapter();
adapter.notifyDataSetChanged();
@@ -340,10 +329,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
progress.dismiss();
showToast(res.getString(R.string.sendToCgeo_no_registration));
finish();
- } else if (msg.what == MSG_CANCEL) {
- if (threadWeb != null) {
- threadWeb.kill();
- }
} else {
adapter.setSelectMode(false);
@@ -353,19 +338,17 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
}
};
- private final Handler clearOfflineLogsHandler = new Handler() {
+ private final CancellableHandler clearOfflineLogsHandler = new CancellableHandler() {
@Override
- public void handleMessage(Message msg) {
- if (msg.what != MSG_CANCEL) {
- adapter.setSelectMode(false);
+ public void handleRegularMessage(Message msg) {
+ adapter.setSelectMode(false);
- refreshCurrentList();
+ refreshCurrentList();
- replaceCacheListFromSearch();
+ replaceCacheListFromSearch();
- progress.dismiss();
- }
+ progress.dismiss();
}
};
@@ -402,7 +385,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
if (isInvokedFromAttachment()) {
type = CacheListType.OFFLINE;
if (coords == null) {
- coords = new Geopoint(0.0, 0.0);
+ coords = Geopoint.ZERO;
}
}
@@ -458,10 +441,10 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
private void importGpxAttachement() {
- new StoredList.UserInterface(this).promptForListSelection(R.string.gpx_import_select_list_title, new RunnableWithArgument<Integer>() {
+ new StoredList.UserInterface(this).promptForListSelection(R.string.gpx_import_select_list_title, new Action1<Integer>() {
@Override
- public void run(Integer listId) {
+ public void call(Integer listId) {
new GPXImporter(CacheListActivity.this, listId, importGpxAttachementFinishedHandler).importGPX();
switchListById(listId);
}
@@ -472,12 +455,15 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
public void onResume() {
super.onResume();
- startGeoAndDir();
+ geoDirHandler.startGeo();
+ if (Settings.isLiveMap()) {
+ geoDirHandler.startDir();
+ }
adapter.setSelectMode(false);
setAdapterCurrentCoordinates(true);
- if (loadCachesHandler != null && search != null) {
+ if (search != null) {
replaceCacheListFromSearch();
loadCachesHandler.sendEmptyMessage(0);
}
@@ -503,8 +489,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
@Override
public void onPause() {
- removeGeoAndDir();
-
+ geoDirHandler.stopGeoAndDir();
super.onPause();
}
@@ -675,9 +660,9 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
return true;
case R.id.menu_sort:
final CacheComparator oldComparator = adapter.getCacheComparator();
- new ComparatorUserInterface(this).selectComparator(oldComparator, new RunnableWithArgument<CacheComparator>() {
+ new ComparatorUserInterface(this).selectComparator(oldComparator, new Action1<CacheComparator>() {
@Override
- public void run(CacheComparator selectedComparator) {
+ public void call(CacheComparator selectedComparator) {
// selecting the same sorting twice will toggle the order
if (selectedComparator != null && oldComparator != null && selectedComparator.getClass().equals(oldComparator.getClass())) {
adapter.toggleInverseSort();
@@ -728,7 +713,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
public void clearOfflineLogs() {
- progress.show(this, null, res.getString(R.string.caches_clear_offlinelogs_progress), true, clearOfflineLogsHandler.obtainMessage(MSG_CANCEL));
+ progress.show(this, null, res.getString(R.string.caches_clear_offlinelogs_progress), true, clearOfflineLogsHandler.cancelMessage());
new ClearOfflineLogsThread(clearOfflineLogsHandler).start();
}
@@ -737,13 +722,12 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
*/
@Override
public void showFilterMenu(final View view) {
- new FilterUserInterface(this).selectFilter(new RunnableWithArgument<IFilter>() {
+ new FilterUserInterface(this).selectFilter(new Action1<IFilter>() {
@Override
- public void run(IFilter selectedFilter) {
+ public void call(IFilter selectedFilter) {
if (selectedFilter != null) {
setFilter(selectedFilter);
- }
- else {
+ } else {
// clear filter
setFilter(null);
}
@@ -793,10 +777,10 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
private void moveCachesToOtherList() {
- new StoredList.UserInterface(this).promptForListSelection(R.string.cache_menu_move_list, new RunnableWithArgument<Integer>() {
+ new StoredList.UserInterface(this).promptForListSelection(R.string.cache_menu_move_list, new Action1<Integer>() {
@Override
- public void run(Integer newListId) {
+ public void call(Integer newListId) {
DataStore.moveToList(adapter.getCheckedOrAllCaches(), newListId);
adapter.setSelectMode(false);
@@ -850,10 +834,10 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
});
break;
case R.id.menu_move_to_list:
- new StoredList.UserInterface(this).promptForListSelection(R.string.cache_menu_move_list, new RunnableWithArgument<Integer>() {
+ new StoredList.UserInterface(this).promptForListSelection(R.string.cache_menu_move_list, new Action1<Integer>() {
@Override
- public void run(Integer newListId) {
+ public void call(Integer newListId) {
DataStore.moveToList(Collections.singletonList(cache), newListId);
adapter.setSelectMode(false);
refreshCurrentList();
@@ -960,7 +944,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
boolean enableMore = (type != CacheListType.OFFLINE && cacheList.size() < MAX_LIST_ITEMS);
if (enableMore && search != null) {
final int count = search.getTotalCountGC();
- enableMore = enableMore && count > 0 && cacheList.size() < count;
+ enableMore = count > 0 && cacheList.size() < count;
}
if (enableMore) {
@@ -973,17 +957,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
listFooter.setClickable(enableMore);
}
- private void startGeoAndDir() {
- geoDirHandler.startGeo();
- if (Settings.isLiveMap()) {
- geoDirHandler.startDir();
- }
- }
-
- private void removeGeoAndDir() {
- geoDirHandler.stopGeoAndDir();
- }
-
private void importGpx() {
GpxFileListActivity.startSubActivity(this, listId);
}
@@ -1002,7 +975,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
// provided to this method as a parameter. Pull that uri using "resultData.getData()"
if (data != null) {
final Uri uri = data.getData();
- new GPXImporter(CacheListActivity.this, listId, importGpxAttachementFinishedHandler).importGPX(uri, null, getDisplayName(uri));
+ new GPXImporter(this, listId, importGpxAttachementFinishedHandler).importGPX(uri, null, getDisplayName(uri));
}
}
@@ -1038,9 +1011,9 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
if (Settings.getChooseList() && type != CacheListType.OFFLINE) {
// let user select list to store cache in
new StoredList.UserInterface(this).promptForListSelection(R.string.list_title,
- new RunnableWithArgument<Integer>() {
+ new Action1<Integer>() {
@Override
- public void run(final Integer selectedListId) {
+ public void call(final Integer selectedListId) {
refreshStored(caches, selectedListId);
}
}, true, StoredList.TEMPORARY_LIST_ID, newListName);
@@ -1062,12 +1035,12 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
message = res.getString(R.string.caches_downloading) + " " + etaTime + " " + res.getQuantityString(R.plurals.caches_eta_mins, etaTime);
}
- progress.show(this, null, message, ProgressDialog.STYLE_HORIZONTAL, loadDetailsHandler.obtainMessage(MSG_CANCEL));
+ progress.show(this, null, message, ProgressDialog.STYLE_HORIZONTAL, loadDetailsHandler.cancelMessage());
progress.setMaxProgressAndReset(detailTotal);
detailProgressTime = System.currentTimeMillis();
- threadDetails = new LoadDetailsThread(loadDetailsHandler, caches, storeListId);
+ final LoadDetailsThread threadDetails = new LoadDetailsThread(loadDetailsHandler, caches, storeListId);
threadDetails.start();
}
@@ -1098,9 +1071,9 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
detailProgress = 0;
showProgress(false);
- progress.show(this, null, res.getString(R.string.web_import_waiting), true, downloadFromWebHandler.obtainMessage(MSG_CANCEL));
+ progress.show(this, null, res.getString(R.string.web_import_waiting), true, downloadFromWebHandler.cancelMessage());
- threadWeb = new LoadFromWebThread(downloadFromWebHandler, listId);
+ final LoadFromWebThread threadWeb = new LoadFromWebThread(downloadFromWebHandler, listId);
threadWeb.start();
}
@@ -1127,26 +1100,20 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private class LoadDetailsThread extends Thread {
- final private Handler handler;
+ final private CancellableHandler handler;
final private int listIdLD;
- private volatile boolean needToStop = false;
final private List<Geocache> caches;
- public LoadDetailsThread(Handler handlerIn, List<Geocache> caches, int listId) {
- handler = handlerIn;
+ public LoadDetailsThread(CancellableHandler handler, List<Geocache> caches, int listId) {
+ this.handler = handler;
this.caches = caches;
// in case of online lists, set the list id to the standard list
this.listIdLD = Math.max(listId, StoredList.STANDARD_LIST_ID);
}
- public void kill() {
- needToStop = true;
- }
-
@Override
public void run() {
- removeGeoAndDir();
// First refresh caches that do not yet have static maps to get them a chance to get a copy
// before the limit expires, unless we do not want to store offline maps.
final List<Geocache> allCaches = Settings.isStoreOfflineMaps() ?
@@ -1173,7 +1140,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
*/
private boolean refreshCache(Geocache cache) {
try {
- if (needToStop) {
+ if (handler.isCancelled()) {
throw new InterruptedException("Stopped storing process.");
}
detailProgress++;
@@ -1190,31 +1157,23 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
}
- private class LoadFromWebThread extends Thread {
+ private static class LoadFromWebThread extends Thread {
- final private Handler handler;
+ final private CancellableHandler handler;
final private int listIdLFW;
- private volatile boolean needToStop = false;
- public LoadFromWebThread(Handler handlerIn, int listId) {
- handler = handlerIn;
+ public LoadFromWebThread(CancellableHandler handler, int listId) {
+ this.handler = handler;
listIdLFW = StoredList.getConcreteList(listId);
}
- public void kill() {
- needToStop = true;
- }
-
@Override
public void run() {
-
- removeGeoAndDir();
-
int delay = -1;
int times = 0;
int ret = MSG_DONE;
- while (!needToStop && times < 3 * 60 / 5) { // maximum: 3 minutes, every 5 seconds
+ while (!handler.isCancelled() && times < 3 * 60 / 5) { // maximum: 3 minutes, every 5 seconds
//download new code
String deviceCode = Settings.getWebDeviceCode();
if (deviceCode == null) {
@@ -1238,7 +1197,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
//Server returned RG (registration) and this device no longer registered.
Settings.setWebNameCode(null, null);
ret = -3;
- needToStop = true;
+ handler.cancel();
break;
} else {
delay = 0;
@@ -1248,7 +1207,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
if (responseFromWeb == null || responseFromWeb.getStatusLine().getStatusCode() != 200) {
ret = -2;
- needToStop = true;
+ handler.cancel();
break;
}
@@ -1267,8 +1226,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
handler.sendEmptyMessage(ret);
-
- startGeoAndDir();
}
}
@@ -1283,9 +1240,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
@Override
protected Void doInBackgroundInternal(Geocache[] caches) {
- removeGeoAndDir();
DataStore.markDropped(Arrays.asList(caches));
- startGeoAndDir();
return null;
}
@@ -1349,11 +1304,11 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
@NonNull
- private RunnableWithArgument<Integer> getListSwitchingRunnable() {
- return new RunnableWithArgument<Integer>() {
+ private Action1<Integer> getListSwitchingRunnable() {
+ return new Action1<Integer>() {
@Override
- public void run(final Integer selectedListId) {
+ public void call(final Integer selectedListId) {
switchListById(selectedListId);
}
};
@@ -1364,6 +1319,12 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
return;
}
+ if (id == PseudoList.HISTORY_LIST.id) {
+ CacheListActivity.startActivityHistory(this);
+ finish();
+ return;
+ }
+
final StoredList list = DataStore.getList(id);
if (list == null) {
return;
@@ -1606,6 +1567,9 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
} else {
final StoredList list = DataStore.getList(listId);
// list.id may be different if listId was not valid
+ if (list.id != listId) {
+ showToast(getString(R.string.list_not_available));
+ }
listId = list.id;
title = list.title;
}
@@ -1670,8 +1634,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
break;
case POCKET:
final String guid = extras.getString(Intents.EXTRA_POCKET_GUID);
- final String pocket_name = extras.getString(Intents.EXTRA_NAME);
- title = pocket_name;
+ title = extras.getString(Intents.EXTRA_NAME);
loader = new PocketGeocacheListLoader(app, guid);
break;
}
diff --git a/main/src/cgeo/geocaching/CacheMenuHandler.java b/main/src/cgeo/geocaching/CacheMenuHandler.java
index 84a08f5..ab11765 100644
--- a/main/src/cgeo/geocaching/CacheMenuHandler.java
+++ b/main/src/cgeo/geocaching/CacheMenuHandler.java
@@ -1,27 +1,17 @@
package cgeo.geocaching;
-import cgeo.calendar.ICalendar;
+import cgeo.calendar.CalendarAddon;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
-import cgeo.geocaching.geopoint.GeopointFormatter;
-import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.ui.AbstractUIFactory;
-import cgeo.geocaching.ui.dialog.Dialogs;
-import cgeo.geocaching.utils.ProcessUtils;
-
-import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.Uri;
import android.view.Menu;
import android.view.MenuItem;
-import java.util.Date;
-
/**
- * Shared menu handling for all activities having menu items related to a cache.
- *
+ * Shared menu handling for all activities having menu items related to a cache. <br>
+ * TODO: replace by a fragment
+ *
*/
public class CacheMenuHandler extends AbstractUIFactory {
@@ -58,7 +48,7 @@ public class CacheMenuHandler extends AbstractUIFactory {
cache.shareCache(activity, res);
return true;
case R.id.menu_calendar:
- addToCalendarWithIntent(activity, cache);
+ CalendarAddon.addToCalendarWithIntent(activity, cache);
return true;
default:
return false;
@@ -80,39 +70,4 @@ public class CacheMenuHandler extends AbstractUIFactory {
activity.getMenuInflater().inflate(R.menu.cache_options, menu);
onPrepareOptionsMenu(menu, cache);
}
-
- private static void addToCalendarWithIntent(final Activity activity, final Geocache cache) {
- final boolean calendarAddOnAvailable = ProcessUtils.isIntentAvailable(ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST));
-
- if (calendarAddOnAvailable) {
- final Date hiddenDate = cache.getHiddenDate();
- final Parameters params = new Parameters(
- ICalendar.PARAM_NAME, cache.getName(),
- ICalendar.PARAM_NOTE, StringUtils.defaultString(cache.getPersonalNote()),
- ICalendar.PARAM_HIDDEN_DATE, hiddenDate != null ? String.valueOf(hiddenDate.getTime()) : StringUtils.EMPTY,
- ICalendar.PARAM_URL, StringUtils.defaultString(cache.getUrl()),
- ICalendar.PARAM_COORDS, cache.getCoords() == null ? "" : cache.getCoords().format(GeopointFormatter.Format.LAT_LON_DECMINUTE_RAW),
- ICalendar.PARAM_LOCATION, StringUtils.defaultString(cache.getLocation()),
- ICalendar.PARAM_SHORT_DESC, StringUtils.defaultString(cache.getShortDescription()),
- ICalendar.PARAM_START_TIME_MINUTES, StringUtils.defaultString(cache.guessEventTimeMinutes())
- );
-
- activity.startActivity(new Intent(ICalendar.INTENT,
- Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST + "?" + params.toString())));
- } else {
- // Inform user the calendar add-on is not installed and let them get it from Google Play
- Dialogs.confirmYesNo(activity, R.string.addon_missing_title, new StringBuilder(res.getString(R.string.helper_calendar_missing))
- .append(' ')
- .append(res.getString(R.string.addon_download_prompt))
- .toString(), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- final Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(ICalendar.CALENDAR_ADDON_URI));
- activity.startActivity(intent);
- }
- });
- }
- }
-
}
diff --git a/main/src/cgeo/geocaching/CachePopup.java b/main/src/cgeo/geocaching/CachePopup.java
index 9186497..5d04ab0 100644
--- a/main/src/cgeo/geocaching/CachePopup.java
+++ b/main/src/cgeo/geocaching/CachePopup.java
@@ -9,9 +9,9 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RunnableWithArgument;
import org.apache.commons.lang3.StringUtils;
+import rx.util.functions.Action1;
import android.content.Context;
import android.content.Intent;
@@ -110,9 +110,9 @@ public class CachePopup extends AbstractPopupActivity {
if (Settings.getChooseList()) {
// let user select list to store cache in
new StoredList.UserInterface(CachePopup.this).promptForListSelection(R.string.list_title,
- new RunnableWithArgument<Integer>() {
+ new Action1<Integer>() {
@Override
- public void run(final Integer selectedListId) {
+ public void call(final Integer selectedListId) {
storeCache(selectedListId);
}
}, true, StoredList.TEMPORARY_LIST_ID);
diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java
index 2500d10..1cea5f1 100644
--- a/main/src/cgeo/geocaching/CgeoApplication.java
+++ b/main/src/cgeo/geocaching/CgeoApplication.java
@@ -1,10 +1,10 @@
package cgeo.geocaching;
-import cgeo.geocaching.network.StatusUpdater;
import cgeo.geocaching.ui.dialog.Dialogs;
-import cgeo.geocaching.utils.IObserver;
import cgeo.geocaching.utils.Log;
+import rx.Observable;
+
import android.app.Activity;
import android.app.Application;
import android.app.ProgressDialog;
@@ -14,12 +14,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class CgeoApplication extends Application {
- private volatile GeoDataProvider geo;
- private volatile DirectionProvider dir;
+ private volatile Observable<IGeoData> geo;
+ private volatile Observable<Float> dir;
private boolean forceRelog = false; // c:geo needs to log into cache providers
public boolean showLoginToast = true; //login toast shown just once.
private boolean liveMapHintShown = false; // livemap hint has been shown
- final private StatusUpdater statusUpdater = new StatusUpdater();
private static CgeoApplication instance;
public CgeoApplication() {
@@ -35,26 +34,11 @@ public class CgeoApplication extends Application {
}
@Override
- public void onCreate() {
- new Thread(statusUpdater).start();
- }
-
- @Override
public void onLowMemory() {
Log.i("Cleaning applications cache.");
DataStore.removeAllFromCache();
}
- @Override
- public void onTerminate() {
- Log.d("Terminating c:geo…");
-
- DataStore.clean();
- DataStore.closeDb();
-
- super.onTerminate();
- }
-
/**
* Move the database to/from external cgdata in a new thread,
* showing a progress window
@@ -82,29 +66,11 @@ public class CgeoApplication extends Application {
}.start();
}
- /**
- * Register an observer to receive GeoData information.
- * <br/>
- * If there is a chance that no observers are registered before this
- * method is called, it is necessary to call it from a task implementing
- * a looper interface as the data provider will use listeners that
- * require a looper thread to run.
- *
- * @param observer a geodata observer
- */
- public void addGeoObserver(final IObserver<? super IGeoData> observer) {
- currentGeoObject().addObserver(observer);
- }
-
- public void deleteGeoObserver(final IObserver<? super IGeoData> observer) {
- currentGeoObject().deleteObserver(observer);
- }
-
- private GeoDataProvider currentGeoObject() {
+ public Observable<IGeoData> currentGeoObject() {
if (geo == null) {
synchronized(this) {
if (geo == null) {
- geo = new GeoDataProvider(this);
+ geo = GeoDataProvider.create(this);
}
}
}
@@ -112,22 +78,14 @@ public class CgeoApplication extends Application {
}
public IGeoData currentGeo() {
- return currentGeoObject().getMemory();
+ return currentGeoObject().first().toBlockingObservable().single();
}
- public void addDirectionObserver(final IObserver<? super Float> observer) {
- currentDirObject().addObserver(observer);
- }
-
- public void deleteDirectionObserver(final IObserver<? super Float> observer) {
- currentDirObject().deleteObserver(observer);
- }
-
- private DirectionProvider currentDirObject() {
+ public Observable<Float> currentDirObject() {
if (dir == null) {
synchronized(this) {
if (dir == null) {
- dir = new DirectionProvider(this);
+ dir = DirectionProvider.create(this);
}
}
}
@@ -135,11 +93,7 @@ public class CgeoApplication extends Application {
}
public Float currentDirection() {
- return currentDirObject().getMemory();
- }
-
- public StatusUpdater getStatusUpdater() {
- return statusUpdater;
+ return currentDirObject().first().toBlockingObservable().single();
}
public boolean isLiveMapHintShown() {
diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java
index 8955afd..6fc2de1 100644
--- a/main/src/cgeo/geocaching/CompassActivity.java
+++ b/main/src/cgeo/geocaching/CompassActivity.java
@@ -150,12 +150,13 @@ public class CompassActivity extends AbstractActivity {
final CgeoApplication app = CgeoApplication.getInstance();
final IGeoData geo = app.currentGeo();
if (geo != null) {
- geoDirHandler.update(geo);
+ geoDirHandler.updateGeoData(geo);
}
final Float dir = app.currentDirection();
if (dir != null) {
- geoDirHandler.update(dir);
+ geoDirHandler.updateDirection(dir);
}
+
}
@Override
diff --git a/main/src/cgeo/geocaching/CreateShortcutActivity.java b/main/src/cgeo/geocaching/CreateShortcutActivity.java
index 7b91ba1..0b91da0 100644
--- a/main/src/cgeo/geocaching/CreateShortcutActivity.java
+++ b/main/src/cgeo/geocaching/CreateShortcutActivity.java
@@ -1,8 +1,10 @@
package cgeo.geocaching;
import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.list.PseudoList;
import cgeo.geocaching.list.StoredList;
-import cgeo.geocaching.utils.RunnableWithArgument;
+
+import rx.util.functions.Action1;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
@@ -21,17 +23,17 @@ public class CreateShortcutActivity extends AbstractActivity {
}
private void promptForShortcut() {
- new StoredList.UserInterface(this).promptForListSelection(R.string.create_shortcut, new RunnableWithArgument<Integer>() {
+ new StoredList.UserInterface(this).promptForListSelection(R.string.create_shortcut, new Action1<Integer>() {
@Override
- public void run(final Integer listId) {
+ public void call(final Integer listId) {
final Intent shortcut = createShortcut(listId.intValue());
setResult(RESULT_OK, shortcut);
// finish activity to return the shortcut
finish();
}
- });
+ }, false, PseudoList.HISTORY_LIST.id);
}
protected Intent createShortcut(int listId) {
diff --git a/main/src/cgeo/geocaching/DataStore.java b/main/src/cgeo/geocaching/DataStore.java
index 6da1af8..11c5a9a 100644
--- a/main/src/cgeo/geocaching/DataStore.java
+++ b/main/src/cgeo/geocaching/DataStore.java
@@ -25,17 +25,20 @@ import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
+import android.app.SearchManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.DatabaseUtils;
+import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteDoneException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
+import android.provider.BaseColumns;
import java.io.File;
import java.io.FilenameFilter;
@@ -811,12 +814,19 @@ public class DataStore {
/**
* Remove obsolete cache directories in c:geo private storage.
+ */
+ public static void removeObsoleteCacheDirectories() {
+ removeObsoleteCacheDirectories(database);
+ }
+
+ /**
+ * Remove obsolete cache directories in c:geo private storage.
*
* @param db
* the read-write database to use
*/
private static void removeObsoleteCacheDirectories(final SQLiteDatabase db) {
- final Pattern oldFilePattern = Pattern.compile("^[GC|TB|O][A-Z0-9]{4,7}$");
+ final Pattern oldFilePattern = Pattern.compile("^[GC|TB|EC|GK|O][A-Z0-9]{4,7}$");
final SQLiteStatement select = db.compileStatement("select count(*) from " + dbTableCaches + " where geocode = ?");
final File[] files = LocalStorage.getStorage().listFiles();
final ArrayList<File> toRemove = new ArrayList<File>(files.length);
@@ -868,28 +878,6 @@ public class DataStore {
db.execSQL("drop table if exists " + dbTableTrackables);
}
- public static String[] getRecentGeocodesForSearch() {
- init();
-
- try {
- long timestamp = System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED;
- final Cursor cursor = database.query(
- dbTableCaches,
- new String[]{"geocode"},
- "(detailed = 1 and detailedupdate > ?) or reason > 0",
- new String[]{Long.toString(timestamp)},
- null,
- null,
- "detailedupdate desc",
- "100");
-
- return getFirstColumn(cursor);
- } catch (final Exception e) {
- Log.e("DataStore.allDetailedThere", e);
- return new String[0];
- }
- }
-
public static boolean isThere(String geocode, String guid, boolean detailed, boolean checkTime) {
init();
@@ -2302,11 +2290,6 @@ public class DataStore {
return new SearchResult(geocodes);
}
- /** delete caches from the DB store 3 days or more before */
- public static void clean() {
- clean(false);
- }
-
/**
* Remove caches with listId = 0
*
@@ -2355,6 +2338,8 @@ public class DataStore {
cursor.close();
+ geocodes = exceptCachesWithOfflineLog(geocodes);
+
if (!geocodes.isEmpty()) {
Log.d("Database clean: removing " + geocodes.size() + " geocaches from listId=0");
removeCaches(geocodes, LoadFlags.REMOVE_ALL);
@@ -2367,6 +2352,33 @@ public class DataStore {
databaseCleaned = true;
}
+ /**
+ * remove all geocodes from the given list of geocodes where an offline log exists
+ *
+ * @param geocodes
+ * @return
+ */
+ private static Set<String> exceptCachesWithOfflineLog(Set<String> geocodes) {
+ if (geocodes.isEmpty()) {
+ return geocodes;
+ }
+
+ init();
+ final Cursor cursor = database.query(
+ dbTableLogsOffline,
+ new String[] { "geocode" },
+ null,
+ null,
+ null,
+ null,
+ null);
+
+ final List<String> geocodesWithOfflineLog = Arrays.asList(getFirstColumn(cursor));
+
+ geocodes.removeAll(geocodesWithOfflineLog);
+ return geocodes;
+ }
+
public static void removeAllFromCache() {
// clean up CacheCache
cacheCache.removeAllFromCache();
@@ -2897,21 +2909,6 @@ public class DataStore {
return waypoints;
}
- public static String[] getTrackableCodes() {
- init();
-
- final Cursor cursor = database.query(
- dbTableTrackables,
- new String[] { "tbcode" },
- null,
- null,
- null,
- null,
- "updated DESC",
- "100");
- return getFirstColumn(cursor);
- }
-
/**
* Extract the first column of the cursor rows and close the cursor.
*
@@ -3098,4 +3095,113 @@ public class DataStore {
return missingFromSearch;
}
+ public static Cursor findSuggestions(final String searchTerm) {
+ // require 3 characters, otherwise there are to many results
+ if (StringUtils.length(searchTerm) < 3) {
+ return null;
+ }
+ init();
+ final MatrixCursor resultCursor = new MatrixCursor(new String[] {
+ BaseColumns._ID,
+ SearchManager.SUGGEST_COLUMN_TEXT_1,
+ SearchManager.SUGGEST_COLUMN_TEXT_2,
+ SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
+ SearchManager.SUGGEST_COLUMN_QUERY
+ });
+ try {
+ final String selectionArg = getSuggestionArgument(searchTerm);
+ findCaches(resultCursor, selectionArg);
+ findTrackables(resultCursor, selectionArg);
+ } catch (final Exception e) {
+ Log.e("DataStore.loadBatchOfStoredGeocodes", e);
+ }
+ return resultCursor;
+ }
+
+ private static void findCaches(final MatrixCursor resultCursor, final String selectionArg) {
+ Cursor cursor = database.query(
+ dbTableCaches,
+ new String[] { "geocode", "name" },
+ "geocode IS NOT NULL AND geocode != '' AND (geocode LIKE ? OR name LIKE ?)",
+ new String[] { selectionArg, selectionArg },
+ null,
+ null,
+ "name");
+ while (cursor.moveToNext()) {
+ final String geocode = cursor.getString(0);
+ resultCursor.addRow(new String[] {
+ String.valueOf(resultCursor.getCount()),
+ cursor.getString(1),
+ geocode,
+ Intents.ACTION_GEOCACHE,
+ geocode
+ });
+ }
+ cursor.close();
+ }
+
+ private static String getSuggestionArgument(String input) {
+ return "%" + StringUtils.trim(input) + "%";
+ }
+
+ private static void findTrackables(final MatrixCursor resultCursor, final String selectionArg) {
+ Cursor cursor = database.query(
+ dbTableTrackables,
+ new String[] { "tbcode", "title" },
+ "tbcode IS NOT NULL AND tbcode != '' AND (tbcode LIKE ? OR title LIKE ?)",
+ new String[] { selectionArg, selectionArg },
+ null,
+ null,
+ "title");
+ while (cursor.moveToNext()) {
+ final String tbcode = cursor.getString(0);
+ resultCursor.addRow(new String[] {
+ String.valueOf(resultCursor.getCount()),
+ cursor.getString(1),
+ tbcode,
+ Intents.ACTION_TRACKABLE,
+ tbcode
+ });
+ }
+ cursor.close();
+ }
+
+ public static String[] getSuggestions(final String table, final String column, final String input) {
+ Cursor cursor = database.query(
+ true,
+ table,
+ new String[] { column },
+ column + " LIKE ?",
+ new String[] { getSuggestionArgument(input) },
+ null,
+ null,
+ column,
+ null);
+ return getFirstColumn(cursor);
+ }
+
+ public static String[] getSuggestionsOwnerName(String input) {
+ return getSuggestions(dbTableCaches, "owner", input);
+ }
+
+ public static String[] getSuggestionsTrackableCode(String input) {
+ return getSuggestions(dbTableTrackables, "tbcode", input);
+ }
+
+ public static String[] getSuggestionsFinderName(String input) {
+ return getSuggestions(dbTableLogs, "author", input);
+ }
+
+ public static String[] getSuggestionsGeocode(String input) {
+ return getSuggestions(dbTableCaches, "geocode", input);
+ }
+
+ public static String[] getSuggestionsKeyword(String input) {
+ return getSuggestions(dbTableCaches, "name", input);
+ }
+
+ public static String[] getSuggestionsAddress(String input) {
+ return getSuggestions(dbTableCaches, "location", input);
+ }
+
}
diff --git a/main/src/cgeo/geocaching/DirectionProvider.java b/main/src/cgeo/geocaching/DirectionProvider.java
index ae58fed..cc44155 100644
--- a/main/src/cgeo/geocaching/DirectionProvider.java
+++ b/main/src/cgeo/geocaching/DirectionProvider.java
@@ -1,9 +1,13 @@
package cgeo.geocaching;
import cgeo.geocaching.compatibility.Compatibility;
-import cgeo.geocaching.utils.MemorySubject;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import rx.Observable;
+import rx.Observable.OnSubscribeFunc;
+import rx.Observer;
+import rx.Subscription;
+import rx.observables.ConnectableObservable;
+import rx.subjects.BehaviorSubject;
import android.app.Activity;
import android.content.Context;
@@ -12,58 +16,61 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
-public class DirectionProvider extends MemorySubject<Float> implements SensorEventListener {
+public class DirectionProvider implements OnSubscribeFunc<Float> {
private final SensorManager sensorManager;
+ private final BehaviorSubject<Float> subject = BehaviorSubject.create(0.0f);
- // Previous values signaled to observers to avoid re-sending the same value when the
- // device doesn't change orientation. The orientation is usually given with a 1 degree
- // precision by Android, so it is not uncommon to obtain exactly the same value several
- // times.
- private float previous = -1;
-
- public DirectionProvider(final Context context) {
- sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
-
+ static public Observable<Float> create(final Context context) {
+ return new DirectionProvider((SensorManager) context.getSystemService(Context.SENSOR_SERVICE)).worker.refCount();
}
- @Override
- protected void onFirstObserver() {
- @SuppressWarnings("deprecation")
- // This will be removed when using a new location service. Until then, it is okay to be used.
- final Sensor defaultSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
- sensorManager.registerListener(this, defaultSensor, SensorManager.SENSOR_DELAY_NORMAL);
+ private DirectionProvider(final SensorManager sensorManager) {
+ this.sensorManager = sensorManager;
}
@Override
- protected void onLastObserver() {
- sensorManager.unregisterListener(this);
+ public Subscription onSubscribe(final Observer<? super Float> observer) {
+ return subject.distinctUntilChanged().subscribe(observer);
}
- @Override
- public void onAccuracyChanged(final Sensor sensor, int accuracy) {
- /*
- * There is a bug in Android, which apparently causes this method to be called every
- * time the sensor _value_ changed, even if the _accuracy_ did not change. So logging
- * this event leads to the log being flooded with multiple entries _per second_,
- * which I experienced when running cgeo in a building (with GPS and network being
- * unreliable).
- *
- * See for example https://code.google.com/p/android/issues/detail?id=14792
- */
+ private final ConnectableObservable<Float> worker = new ConnectableObservable<Float>(this) {
+ @Override
+ public Subscription connect() {
+ @SuppressWarnings("deprecation")
+ // This will be removed when using a new location service. Until then, it is okay to be used.
+ final Sensor defaultSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
+ final SensorEventListener listener = new SensorEventListener() {
+ @Override
+ public void onSensorChanged(final SensorEvent event) {
+ subject.onNext(event.values[0]);
+ }
- //Log.i(Settings.tag, "Compass' accuracy is low (" + accuracy + ")");
- }
+ @Override
+ public void onAccuracyChanged(final Sensor sensor, final int accuracy) {
+ /*
+ * There is a bug in Android, which apparently causes this method to be called every
+ * time the sensor _value_ changed, even if the _accuracy_ did not change. So logging
+ * this event leads to the log being flooded with multiple entries _per second_,
+ * which I experienced when running cgeo in a building (with GPS and network being
+ * unreliable).
+ *
+ * See for example https://code.google.com/p/android/issues/detail?id=14792
+ */
- @Override
- @SuppressFBWarnings("FE_FLOATING_POINT_EQUALITY")
- public void onSensorChanged(final SensorEvent event) {
- final float direction = event.values[0];
- if (direction != previous) {
- notifyObservers(direction);
- previous = direction;
+ //Log.i(Settings.tag, "Compass' accuracy is low (" + accuracy + ")");
+ }
+ };
+
+ sensorManager.registerListener(listener, defaultSensor, SensorManager.SENSOR_DELAY_NORMAL);
+ return new Subscription() {
+ @Override
+ public void unsubscribe() {
+ sensorManager.unregisterListener(listener);
+ }
+ };
}
- }
+ };
/**
* Take the phone rotation (through a given activity) in account and adjust the direction.
@@ -72,6 +79,7 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve
* @param direction the unadjusted direction in degrees, in the [0, 360[ range
* @return the adjusted direction in degrees, in the [0, 360[ range
*/
+
public static float getDirectionNow(final Activity activity, final float direction) {
return Compatibility.getDirectionNow(direction, activity);
}
diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java
index 6d0f822..df6e9c5 100644
--- a/main/src/cgeo/geocaching/EditWaypointActivity.java
+++ b/main/src/cgeo/geocaching/EditWaypointActivity.java
@@ -21,7 +21,6 @@ import com.googlecode.androidannotations.annotations.EActivity;
import com.googlecode.androidannotations.annotations.Extra;
import com.googlecode.androidannotations.annotations.InstanceState;
import com.googlecode.androidannotations.annotations.ViewById;
-
import org.apache.commons.lang3.StringUtils;
import android.app.ProgressDialog;
diff --git a/main/src/cgeo/geocaching/GeoDataProvider.java b/main/src/cgeo/geocaching/GeoDataProvider.java
index 73aefce..c61b7e7 100644
--- a/main/src/cgeo/geocaching/GeoDataProvider.java
+++ b/main/src/cgeo/geocaching/GeoDataProvider.java
@@ -3,9 +3,14 @@ package cgeo.geocaching;
import cgeo.geocaching.enumerations.LocationProviderType;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.MemorySubject;
import org.apache.commons.lang3.StringUtils;
+import rx.Observable;
+import rx.Observable.OnSubscribeFunc;
+import rx.Observer;
+import rx.Subscription;
+import rx.observables.ConnectableObservable;
+import rx.subjects.BehaviorSubject;
import android.content.Context;
import android.location.GpsSatellite;
@@ -15,22 +20,14 @@ import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Provide information about the user location. This class should be instantiated only once per application.
- */
-class GeoDataProvider extends MemorySubject<IGeoData> {
+class GeoDataProvider implements OnSubscribeFunc<IGeoData> {
private static final String LAST_LOCATION_PSEUDO_PROVIDER = "last";
private final LocationManager geoManager;
- private final GpsStatus.Listener gpsStatusListener = new GpsStatusListener();
private final LocationData gpsLocation = new LocationData();
private final LocationData netLocation = new LocationData();
- private final Listener networkListener = new Listener(LocationManager.NETWORK_PROVIDER, netLocation);
- private final Listener gpsListener = new Listener(LocationManager.GPS_PROVIDER, gpsLocation);
- private final Unregisterer unregisterer = new Unregisterer();
+ private final BehaviorSubject<IGeoData> subject;
+
public boolean gpsEnabled = false;
public int satellitesVisible = 0;
public int satellitesFixed = 0;
@@ -111,51 +108,6 @@ class GeoDataProvider extends MemorySubject<IGeoData> {
}
}
- private class Unregisterer extends Thread {
-
- private boolean unregisterRequested = false;
- private final ArrayBlockingQueue<Boolean> queue = new ArrayBlockingQueue<Boolean>(1);
-
- public void cancelUnregister() {
- try {
- queue.put(false);
- } catch (final InterruptedException e) {
- // Do nothing
- }
- }
-
- public void lateUnregister() {
- try {
- queue.put(true);
- } catch (final InterruptedException e) {
- // Do nothing
- }
- }
-
- @Override
- public void run() {
- try {
- while (true) {
- if (unregisterRequested) {
- final Boolean element = queue.poll(2500, TimeUnit.MILLISECONDS);
- if (element == null) {
- // Timeout
- unregisterListeners();
- unregisterRequested = false;
- } else {
- unregisterRequested = element;
- }
- } else {
- unregisterRequested = queue.take();
- }
- }
- } catch (final InterruptedException e) {
- // Do nothing
- }
- }
-
- }
-
/**
* Build a new geo data provider object.
* <p/>
@@ -164,10 +116,50 @@ class GeoDataProvider extends MemorySubject<IGeoData> {
*
* @param context the context used to retrieve the system services
*/
- GeoDataProvider(final Context context) {
+ protected GeoDataProvider(final Context context) {
geoManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
- unregisterer.start();
+ subject = BehaviorSubject.create(findInitialLocation());
+ }
+
+ public static Observable<IGeoData> create(final Context context) {
+ final GeoDataProvider provider = new GeoDataProvider(context);
+ return provider.worker.refCount();
+ }
+ @Override
+ public Subscription onSubscribe(final Observer<? super IGeoData> observer) {
+ return subject.subscribe(observer);
+ }
+
+ final ConnectableObservable<IGeoData> worker = new ConnectableObservable<IGeoData>(this) {
+ @Override
+ public Subscription connect() {
+ final GpsStatus.Listener gpsStatusListener = new GpsStatusListener();
+ geoManager.addGpsStatusListener(gpsStatusListener);
+
+ final Listener networkListener = new Listener(LocationManager.NETWORK_PROVIDER, netLocation);
+ final Listener gpsListener = new Listener(LocationManager.GPS_PROVIDER, gpsLocation);
+
+ for (final Listener listener : new Listener[] { networkListener, gpsListener }) {
+ try {
+ geoManager.requestLocationUpdates(listener.locationProvider, 0, 0, listener);
+ } catch (final Exception e) {
+ Log.w("There is no location provider " + listener.locationProvider);
+ }
+ }
+
+ return new Subscription() {
+ @Override
+ public void unsubscribe() {
+ geoManager.removeUpdates(networkListener);
+ geoManager.removeUpdates(gpsListener);
+ geoManager.removeGpsStatusListener(gpsStatusListener);
+ }
+ };
+ }
+ };
+
+ private IGeoData findInitialLocation() {
final Location initialLocation = new Location(LAST_LOCATION_PSEUDO_PROVIDER);
try {
// Try to find a sensible initial location from the last locations known to Android.
@@ -195,45 +187,13 @@ class GeoDataProvider extends MemorySubject<IGeoData> {
}
// Start with an historical GeoData just in case someone queries it before we get
// a chance to get any information.
- notifyObservers(new GeoData(initialLocation, false, 0, 0));
+ return new GeoData(initialLocation, false, 0, 0);
}
private static void copyCoords(final Location target, final Location source) {
target.setLatitude(source.getLatitude());
target.setLongitude(source.getLongitude());
}
- private void registerListeners() {
- geoManager.addGpsStatusListener(gpsStatusListener);
-
- for (final Listener listener : new Listener[] { networkListener, gpsListener }) {
- try {
- geoManager.requestLocationUpdates(listener.locationProvider, 0, 0, listener);
- } catch (final Exception e) {
- Log.w("There is no location provider " + listener.locationProvider);
- }
- }
- }
-
- private synchronized void unregisterListeners() {
- // This method must be synchronized because it will be called asynchronously from the Unregisterer thread.
- // We check that no observers have been re-added to prevent a race condition.
- if (sizeObservers() == 0) {
- geoManager.removeUpdates(networkListener);
- geoManager.removeUpdates(gpsListener);
- geoManager.removeGpsStatusListener(gpsStatusListener);
- }
- }
-
- @Override
- protected void onFirstObserver() {
- unregisterer.cancelUnregister();
- registerListeners();
- }
-
- @Override
- protected void onLastObserver() {
- unregisterer.lateUnregister();
- }
private class Listener implements LocationListener {
private final String locationProvider;
@@ -336,7 +296,7 @@ class GeoDataProvider extends MemorySubject<IGeoData> {
// We do not necessarily get signalled when satellites go to 0/0.
final int visible = gpsLocation.isRecent() ? satellitesVisible : 0;
final IGeoData current = new GeoData(locationData.location, gpsEnabled, visible, satellitesFixed);
- notifyObservers(current);
+ subject.onNext(current);
}
}
diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java
index 156c4b6..42b8f0a 100644
--- a/main/src/cgeo/geocaching/Geocache.java
+++ b/main/src/cgeo/geocaching/Geocache.java
@@ -817,13 +817,7 @@ public class Geocache implements ICache, IWaypoint {
}
public boolean showSize() {
- if (size == CacheSize.NOT_CHOSEN) {
- return false;
- }
- if (isEventCache() || isVirtual()) {
- return false;
- }
- return true;
+ return !(size == CacheSize.NOT_CHOSEN || isEventCache() || isVirtual());
}
public long getUpdated() {
@@ -1373,17 +1367,6 @@ public class Geocache implements ICache, IWaypoint {
}
/**
- * Retrieve a given waypoint.
- *
- * @param index
- * the index of the waypoint
- * @return waypoint or <code>null</code> if index is out of range
- */
- public Waypoint getWaypoint(final int index) {
- return index >= 0 && index < waypoints.size() ? waypoints.get(index) : null;
- }
-
- /**
* Lookup a waypoint by its id.
*
* @param id
@@ -1660,6 +1643,8 @@ public class Geocache implements ICache, IWaypoint {
StaticMapsProvider.downloadMaps(cache);
+ imgGetter.waitForBackgroundLoading(handler);
+
if (handler != null) {
handler.sendMessage(Message.obtain());
}
diff --git a/main/src/cgeo/geocaching/Intents.java b/main/src/cgeo/geocaching/Intents.java
index d9d9829..5c969a1 100644
--- a/main/src/cgeo/geocaching/Intents.java
+++ b/main/src/cgeo/geocaching/Intents.java
@@ -29,4 +29,8 @@ public class Intents {
public static final String EXTRA_WAYPOINT_ID = PREFIX + "waypoint_id";
public static final String EXTRA_CACHELIST = PREFIX + "cache_list";
public static final String EXTRA_POCKET_GUID = PREFIX + "pocket_guid";
+
+ private static final String PREFIX_ACTION = "cgeo.geocaching.intent.action.";
+ public static final String ACTION_GEOCACHE = PREFIX_ACTION + "GEOCACHE";
+ public static final String ACTION_TRACKABLE = PREFIX_ACTION + "TRACKABLE";
}
diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java
index f17a008..c8b785c 100644
--- a/main/src/cgeo/geocaching/LogCacheActivity.java
+++ b/main/src/cgeo/geocaching/LogCacheActivity.java
@@ -151,7 +151,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
final TextView actionButton = (TextView) inventoryItem.findViewById(R.id.action);
actionButton.setId(tb.id);
actionButtons.put(actionButton.getId(), tb);
- actionButton.setText(res.getString(tb.action.resourceId) + " ▼");
+ actionButton.setText(tb.action.getLabel() + " ▼");
actionButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -632,11 +632,11 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
alert.create().show();
}
- private String[] getTBLogTypes() {
+ private static String[] getTBLogTypes() {
final LogTypeTrackable[] logTypeValues = LogTypeTrackable.values();
String[] logTypes = new String[logTypeValues.length];
for (int i = 0; i < logTypes.length; i++) {
- logTypes[i] = res.getString(logTypeValues[i].resourceId);
+ logTypes[i] = logTypeValues[i].getLabel();
}
return logTypes;
}
diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java
index 5246fa9..50a837a 100644
--- a/main/src/cgeo/geocaching/LogTrackableActivity.java
+++ b/main/src/cgeo/geocaching/LogTrackableActivity.java
@@ -3,8 +3,8 @@ package cgeo.geocaching;
import butterknife.ButterKnife;
import butterknife.InjectView;
-import cgeo.geocaching.connector.gc.GCParser;
import cgeo.geocaching.connector.gc.GCLogin;
+import cgeo.geocaching.connector.gc.GCParser;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.network.Network;
diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java
index 924c66d..3ffc631 100644
--- a/main/src/cgeo/geocaching/MainActivity.java
+++ b/main/src/cgeo/geocaching/MainActivity.java
@@ -10,6 +10,7 @@ import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Units;
+import cgeo.geocaching.list.PseudoList;
import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.settings.Settings;
@@ -19,15 +20,22 @@ import cgeo.geocaching.ui.dialog.Dialogs;
import cgeo.geocaching.utils.DatabaseBackupUtils;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RunnableWithArgument;
import cgeo.geocaching.utils.Version;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
-import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import rx.Observable;
+import rx.Observable.OnSubscribeFunc;
+import rx.Observer;
+import rx.Subscription;
+import rx.android.observables.AndroidObservable;
+import rx.concurrency.Schedulers;
+import rx.subscriptions.Subscriptions;
+import rx.util.functions.Action1;
+
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.SearchManager;
@@ -48,7 +56,6 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -77,8 +84,6 @@ public class MainActivity extends AbstractActivity {
private boolean cleanupRunning = false;
private int countBubbleCnt = 0;
private Geopoint addCoords = null;
- private List<Address> addresses = null;
- private boolean addressObtaining = false;
private boolean initialized = false;
private final UpdateLocation locationUpdater = new UpdateLocation();
@@ -104,7 +109,7 @@ public class MainActivity extends AbstractActivity {
if (conn.isLoggedIn()) {
userInfo.append(conn.getUserName());
if (conn.getCachesFound() >= 0) {
- userInfo.append(" (").append(String.valueOf(conn.getCachesFound())).append(')');
+ userInfo.append(" (").append(conn.getCachesFound()).append(')');
}
userInfo.append(Formatter.SEPARATOR);
}
@@ -115,40 +120,24 @@ public class MainActivity extends AbstractActivity {
}
};
- private Handler obtainAddressHandler = new Handler() {
-
- @Override
- public void handleMessage(final Message msg) {
- try {
- if (CollectionUtils.isNotEmpty(addresses)) {
- final Address address = addresses.get(0);
- final ArrayList<String> addressParts = new ArrayList<String>();
-
- final String countryName = address.getCountryName();
- if (countryName != null) {
- addressParts.add(countryName);
- }
- final String locality = address.getLocality();
- if (locality != null) {
- addressParts.add(locality);
- } else {
- final String adminArea = address.getAdminArea();
- if (adminArea != null) {
- addressParts.add(adminArea);
- }
- }
-
- addCoords = app.currentGeo().getCoords();
+ private static String formatAddress(final Address address) {
+ final ArrayList<String> addressParts = new ArrayList<String>();
- navLocation.setText(StringUtils.join(addressParts, ", "));
- }
- } catch (RuntimeException e) {
- // nothing
+ final String countryName = address.getCountryName();
+ if (countryName != null) {
+ addressParts.add(countryName);
+ }
+ final String locality = address.getLocality();
+ if (locality != null) {
+ addressParts.add(locality);
+ } else {
+ final String adminArea = address.getAdminArea();
+ if (adminArea != null) {
+ addressParts.add(adminArea);
}
-
- addresses = null;
}
- };
+ return StringUtils.join(addressParts, ", ");
+ }
private class SatellitesHandler extends GeoDirHandler {
@@ -285,7 +274,7 @@ public class MainActivity extends AbstractActivity {
@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
super.onPrepareOptionsMenu(menu);
- menu.findItem(R.id.menu_pocket_queries).setVisible(Settings.isPremiumMember());
+ menu.findItem(R.id.menu_pocket_queries).setVisible(Settings.isGCPremiumMember());
return true;
}
@@ -309,13 +298,13 @@ public class MainActivity extends AbstractActivity {
startScannerApplication();
return true;
case R.id.menu_pocket_queries:
- if (!Settings.isPremiumMember()) {
+ if (!Settings.isGCPremiumMember()) {
return true;
}
- new PocketQueryList.UserInterface(MainActivity.this).promptForListSelection(new RunnableWithArgument<PocketQueryList>() {
+ PocketQueryList.promptForListSelection(this, new Action1<PocketQueryList>() {
@Override
- public void run(final PocketQueryList pql) {
+ public void call(final PocketQueryList pql) {
CacheListActivity.startActivityPocket(MainActivity.this, pql);
}
});
@@ -388,14 +377,14 @@ public class MainActivity extends AbstractActivity {
@Override
public boolean onLongClick(final View v) {
- new StoredList.UserInterface(MainActivity.this).promptForListSelection(R.string.list_title, new RunnableWithArgument<Integer>() {
+ new StoredList.UserInterface(MainActivity.this).promptForListSelection(R.string.list_title, new Action1<Integer>() {
@Override
- public void run(final Integer selectedListId) {
+ public void call(final Integer selectedListId) {
Settings.saveLastList(selectedListId);
CacheListActivity.startActivityOffline(MainActivity.this);
}
- });
+ }, false, PseudoList.HISTORY_LIST.id);
return true;
}
});
@@ -525,52 +514,61 @@ public class MainActivity extends AbstractActivity {
@Override
public void updateGeoData(final IGeoData geo) {
- try {
- if (geo.getCoords() != null) {
- if (!nearestView.isClickable()) {
- nearestView.setFocusable(true);
- nearestView.setClickable(true);
- nearestView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(final View v) {
- cgeoFindNearest(v);
- }
- });
- nearestView.setBackgroundResource(R.drawable.main_nearby);
+ if (!nearestView.isClickable()) {
+ nearestView.setFocusable(true);
+ nearestView.setClickable(true);
+ nearestView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ cgeoFindNearest(v);
}
+ });
+ nearestView.setBackgroundResource(R.drawable.main_nearby);
+ }
- navType.setText(res.getString(geo.getLocationProvider().resourceId));
+ navType.setText(res.getString(geo.getLocationProvider().resourceId));
- if (geo.getAccuracy() >= 0) {
- int speed = Math.round(geo.getSpeed()) * 60 * 60 / 1000;
- navAccuracy.setText("±" + Units.getDistanceFromMeters(geo.getAccuracy()) + Formatter.SEPARATOR + Units.getSpeed(speed));
- } else {
- navAccuracy.setText(null);
- }
+ if (geo.getAccuracy() >= 0) {
+ int speed = Math.round(geo.getSpeed()) * 60 * 60 / 1000;
+ navAccuracy.setText("±" + Units.getDistanceFromMeters(geo.getAccuracy()) + Formatter.SEPARATOR + Units.getSpeed(speed));
+ } else {
+ navAccuracy.setText(null);
+ }
- if (Settings.isShowAddress()) {
- if (addCoords == null) {
- navLocation.setText(res.getString(R.string.loc_no_addr));
- }
- if (addCoords == null || (geo.getCoords().distanceTo(addCoords) > 0.5 && !addressObtaining)) {
- (new ObtainAddressThread()).start();
+ if (Settings.isShowAddress()) {
+ if (addCoords == null) {
+ navLocation.setText(R.string.loc_no_addr);
+ }
+ if (addCoords == null || (geo.getCoords().distanceTo(addCoords) > 0.5)) {
+ final Observable<String> address = Observable.create(new OnSubscribeFunc<String>() {
+ @Override
+ public Subscription onSubscribe(final Observer<? super String> observer) {
+ try {
+ addCoords = geo.getCoords();
+ final Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
+ final Geopoint coords = app.currentGeo().getCoords();
+ final List<Address> addresses = geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 1);
+ if (!addresses.isEmpty()) {
+ observer.onNext(formatAddress(addresses.get(0)));
+ }
+ observer.onCompleted();
+ } catch (final Exception e) {
+ observer.onError(e);
+ }
+ return Subscriptions.empty();
}
- } else {
- navLocation.setText(geo.getCoords().toString());
- }
- } else {
- if (nearestView.isClickable()) {
- nearestView.setFocusable(false);
- nearestView.setClickable(false);
- nearestView.setOnClickListener(null);
- nearestView.setBackgroundResource(R.drawable.main_nearby_disabled);
- }
- navType.setText(null);
- navAccuracy.setText(null);
- navLocation.setText(res.getString(R.string.loc_trying));
+ }).subscribeOn(Schedulers.threadPoolForIO());
+ AndroidObservable.fromActivity(MainActivity.this, address)
+ .onErrorResumeNext(Observable.from(geo.getCoords().toString()))
+ .subscribe(new Action1<String>() {
+ @Override
+ public void call(final String address) {
+ navLocation.setText(address);
+ }
+ });
}
- } catch (RuntimeException e) {
- Log.w("Failed to update location.");
+ } else {
+ navLocation.setText(geo.getCoords().toString());
}
}
}
@@ -714,35 +712,6 @@ public class MainActivity extends AbstractActivity {
}
}
- private class ObtainAddressThread extends Thread {
-
- public ObtainAddressThread() {
- setPriority(Thread.MIN_PRIORITY);
- }
-
- @Override
- public void run() {
- if (addressObtaining) {
- return;
- }
- addressObtaining = true;
-
- try {
- final Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
- final Geopoint coords = app.currentGeo().getCoords();
- addresses = geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 1);
- } catch (final IOException e) {
- Log.i("Failed to obtain address");
- } catch (final IllegalArgumentException e) {
- Log.w("ObtainAddressThread.run", e);
- }
-
- obtainAddressHandler.sendEmptyMessage(0);
-
- addressObtaining = false;
- }
- }
-
/**
* @param view
* unused here but needed since this method is referenced from XML layout
diff --git a/main/src/cgeo/geocaching/PocketQueryList.java b/main/src/cgeo/geocaching/PocketQueryList.java
index 9d1110d..6613441 100644
--- a/main/src/cgeo/geocaching/PocketQueryList.java
+++ b/main/src/cgeo/geocaching/PocketQueryList.java
@@ -2,15 +2,22 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.connector.gc.GCParser;
-import cgeo.geocaching.utils.RunnableWithArgument;
+
+import org.apache.commons.collections4.CollectionUtils;
+import rx.Observable;
+import rx.Observable.OnSubscribeFunc;
+import rx.Observer;
+import rx.Subscription;
+import rx.android.observables.AndroidObservable;
+import rx.concurrency.Schedulers;
+import rx.subscriptions.Subscriptions;
+import rx.util.functions.Action1;
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
-import android.content.res.Resources;
-import android.os.Handler;
-import android.os.Message;
import java.util.List;
@@ -20,105 +27,63 @@ public final class PocketQueryList {
private final int maxCaches;
private final String name;
- public PocketQueryList(String guid, String name, int maxCaches) {
+ public PocketQueryList(final String guid, final String name, final int maxCaches) {
this.guid = guid;
this.name = name;
this.maxCaches = maxCaches;
}
- public static class UserInterface {
-
- List<PocketQueryList> pocketQueryList = null;
- RunnableWithArgument<PocketQueryList> runAfterwards;
-
- private Handler loadPocketQueryHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- if ((pocketQueryList == null) || (pocketQueryList.size() == 0)) {
- if (waitDialog != null) {
- waitDialog.dismiss();
- }
-
- ActivityMixin.showToast(activity, res.getString(R.string.warn_no_pocket_query_found));
-
- return;
- }
-
- if (waitDialog != null) {
- waitDialog.dismiss();
- }
-
- final CharSequence[] items = new CharSequence[pocketQueryList.size()];
-
- for (int i = 0; i < pocketQueryList.size(); i++) {
- PocketQueryList pq = pocketQueryList.get(i);
- items[i] = pq.name;
- }
+ public String getGuid() {
+ return guid;
+ }
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(res.getString(R.string.search_pocket_select));
- builder.setItems(items, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialogInterface, int itemId) {
- final PocketQueryList query = pocketQueryList.get(itemId);
- dialogInterface.dismiss();
- runAfterwards.run(query);
- }
- });
- builder.create().show();
+ public int getMaxCaches() {
+ return maxCaches;
+ }
- }
- };
+ public String getName() {
+ return name;
+ }
- private class LoadPocketQueryListThread extends Thread {
- final private Handler handler;
+ public static void promptForListSelection(final Activity activity, final Action1<PocketQueryList> runAfterwards) {
+ final Dialog waitDialog = ProgressDialog.show(activity, activity.getString(R.string.search_pocket_title), activity.getString(R.string.search_pocket_loading), true, true);
- public LoadPocketQueryListThread(Handler handlerIn) {
- handler = handlerIn;
+ AndroidObservable.fromActivity(activity, Observable.create(new OnSubscribeFunc<List<PocketQueryList>>() {
+ @Override
+ public Subscription onSubscribe(final Observer<? super List<PocketQueryList>> observer) {
+ observer.onNext(GCParser.searchPocketQueryList());
+ observer.onCompleted();
+ return Subscriptions.empty();
}
-
+ }).subscribeOn(Schedulers.threadPoolForIO())).subscribe(new Action1<List<PocketQueryList>>() {
@Override
- public void run() {
- pocketQueryList = GCParser.searchPocketQueryList();
- handler.sendMessage(Message.obtain());
+ public void call(final List<PocketQueryList> pocketQueryLists) {
+ waitDialog.dismiss();
+ selectFromPocketQueries(activity, pocketQueryLists, runAfterwards);
}
+ });
+ }
+ private static void selectFromPocketQueries(final Activity activity, final List<PocketQueryList> pocketQueryList, final Action1<PocketQueryList> runAfterwards) {
+ if (CollectionUtils.isEmpty(pocketQueryList)) {
+ ActivityMixin.showToast(activity, activity.getString(R.string.warn_no_pocket_query_found));
+ return;
}
- private final Activity activity;
- private final CgeoApplication app;
- private final Resources res;
- private ProgressDialog waitDialog = null;
-
- public UserInterface(final Activity activity) {
- this.activity = activity;
- app = CgeoApplication.getInstance();
- res = app.getResources();
- }
-
- public void promptForListSelection(final RunnableWithArgument<PocketQueryList> runAfterwards) {
+ final CharSequence[] items = new CharSequence[pocketQueryList.size()];
- this.runAfterwards = runAfterwards;
-
- waitDialog = ProgressDialog.show(activity, res.getString(R.string.search_pocket_title), res.getString(R.string.search_pocket_loading), true, true);
-
- LoadPocketQueryListThread thread = new LoadPocketQueryListThread(loadPocketQueryHandler);
- thread.start();
+ for (int i = 0; i < pocketQueryList.size(); i++) {
+ items[i] = pocketQueryList.get(i).name;
}
-
- }
-
- public String getGuid() {
- return guid;
- }
-
- public int getMaxCaches() {
- return maxCaches;
- }
-
- public String getName() {
- return name;
+ new AlertDialog.Builder(activity)
+ .setTitle(activity.getString(R.string.search_pocket_select))
+ .setItems(items, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(final DialogInterface dialogInterface, final int itemId) {
+ dialogInterface.dismiss();
+ runAfterwards.call(pocketQueryList.get(itemId));
+ }
+ }).create().show();
}
}
diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java
index 0648073..3193a2e 100644
--- a/main/src/cgeo/geocaching/SearchActivity.java
+++ b/main/src/cgeo/geocaching/SearchActivity.java
@@ -10,6 +10,7 @@ import cgeo.geocaching.connector.capability.ISearchByGeocode;
import cgeo.geocaching.connector.trackable.TrackableConnector;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.search.AutoCompleteAdapter;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
import cgeo.geocaching.ui.dialog.Dialogs;
@@ -17,6 +18,8 @@ import cgeo.geocaching.utils.EditUtils;
import org.apache.commons.lang3.StringUtils;
+import rx.util.functions.Func1;
+
import android.app.Activity;
import android.app.SearchManager;
import android.content.Intent;
@@ -26,10 +29,8 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
-import android.widget.EditText;
import java.util.Locale;
@@ -39,19 +40,19 @@ public class SearchActivity extends AbstractActivity {
@InjectView(R.id.buttonLongitude) protected Button buttonLongitude;
@InjectView(R.id.search_coordinates) protected Button buttonSearchCoords;
- @InjectView(R.id.address) protected EditText addressEditText;
+ @InjectView(R.id.address) protected AutoCompleteTextView addressEditText;
@InjectView(R.id.search_address) protected Button buttonSearchAddress;
@InjectView(R.id.geocode) protected AutoCompleteTextView geocodeEditText;
@InjectView(R.id.display_geocode) protected Button buttonSearchGeocode;
- @InjectView(R.id.keyword) protected EditText keywordEditText;
+ @InjectView(R.id.keyword) protected AutoCompleteTextView keywordEditText;
@InjectView(R.id.search_keyword) protected Button buttonSearchKeyword;
- @InjectView(R.id.finder) protected EditText finderNameEditText;
+ @InjectView(R.id.finder) protected AutoCompleteTextView finderNameEditText;
@InjectView(R.id.search_finder) protected Button buttonSearchFinder;
- @InjectView(R.id.owner) protected EditText ownerNameEditText;
+ @InjectView(R.id.owner) protected AutoCompleteTextView ownerNameEditText;
@InjectView(R.id.search_owner) protected Button buttonSearchOwner;
@InjectView(R.id.trackable) protected AutoCompleteTextView trackableEditText;
@@ -60,9 +61,23 @@ public class SearchActivity extends AbstractActivity {
@Override
public final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ final Intent intent = getIntent();
+
+ // search suggestion for a cache
+ if (Intents.ACTION_GEOCACHE.equals(intent.getAction())) {
+ CacheDetailActivity.startActivity(this, intent.getStringExtra(SearchManager.QUERY));
+ finish();
+ return;
+ }
+
+ // search suggestion for a trackable
+ if (Intents.ACTION_TRACKABLE.equals(intent.getAction())) {
+ TrackableActivity.startActivity(this, null, intent.getStringExtra(SearchManager.QUERY), null);
+ finish();
+ return;
+ }
// search query
- final Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
hideKeyboard();
final String query = intent.getStringExtra(SearchManager.QUERY);
@@ -173,6 +188,12 @@ public class SearchActivity extends AbstractActivity {
public void run() {
findByAddressFn();
}
+ }, new Func1<String, String[]>() {
+
+ @Override
+ public String[] call(final String input) {
+ return DataStore.getSuggestionsAddress(input);
+ }
});
setSearchAction(geocodeEditText, buttonSearchGeocode, new Runnable() {
@@ -181,8 +202,13 @@ public class SearchActivity extends AbstractActivity {
public void run() {
findByGeocodeFn();
}
+ }, new Func1<String, String[]>() {
+
+ @Override
+ public String[] call(final String input) {
+ return DataStore.getSuggestionsGeocode(input);
+ }
});
- addHistoryEntries(geocodeEditText, DataStore.getRecentGeocodesForSearch());
setSearchAction(keywordEditText, buttonSearchKeyword, new Runnable() {
@@ -190,6 +216,12 @@ public class SearchActivity extends AbstractActivity {
public void run() {
findByKeywordFn();
}
+ }, new Func1<String, String[]>() {
+
+ @Override
+ public String[] call(final String input) {
+ return DataStore.getSuggestionsKeyword(input);
+ }
});
setSearchAction(finderNameEditText, buttonSearchFinder, new Runnable() {
@@ -198,6 +230,12 @@ public class SearchActivity extends AbstractActivity {
public void run() {
findByFinderFn();
}
+ }, new Func1<String, String[]>() {
+
+ @Override
+ public String[] call(final String input) {
+ return DataStore.getSuggestionsFinderName(input);
+ }
});
setSearchAction(ownerNameEditText, buttonSearchOwner, new Runnable() {
@@ -206,6 +244,12 @@ public class SearchActivity extends AbstractActivity {
public void run() {
findByOwnerFn();
}
+ }, new Func1<String, String[]>() {
+
+ @Override
+ public String[] call(final String input) {
+ return DataStore.getSuggestionsOwnerName(input);
+ }
});
setSearchAction(trackableEditText, buttonSearchTrackable, new Runnable() {
@@ -214,12 +258,16 @@ public class SearchActivity extends AbstractActivity {
public void run() {
findTrackableFn();
}
+ }, new Func1<String, String[]>() {
+
+ @Override
+ public String[] call(final String input) {
+ return DataStore.getSuggestionsTrackableCode(input);
+ }
});
- addHistoryEntries(trackableEditText, DataStore.getTrackableCodes());
- disableSuggestions(trackableEditText);
}
- private static void setSearchAction(final EditText editText, final Button button, final Runnable runnable) {
+ private static void setSearchAction(final AutoCompleteTextView editText, final Button button, final Runnable runnable, final Func1<String, String[]> suggestionFunction) {
EditUtils.setActionListener(editText, runnable);
button.setOnClickListener(new View.OnClickListener() {
@Override
@@ -227,13 +275,7 @@ public class SearchActivity extends AbstractActivity {
runnable.run();
}
});
- }
-
- private void addHistoryEntries(final AutoCompleteTextView textView, final String[] entries) {
- if (entries != null) {
- final ArrayAdapter<String> historyAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, entries);
- textView.setAdapter(historyAdapter);
- }
+ editText.setAdapter(new AutoCompleteAdapter(editText.getContext(), android.R.layout.simple_dropdown_item_1line, suggestionFunction));
}
private class FindByCoordsAction implements OnClickListener {
diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java
index 131a01c..46ac38e 100644
--- a/main/src/cgeo/geocaching/SearchResult.java
+++ b/main/src/cgeo/geocaching/SearchResult.java
@@ -10,6 +10,7 @@ import cgeo.geocaching.gcvote.GCVote;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -228,6 +229,7 @@ public class SearchResult implements Parcelable {
return result;
}
+ @Nullable
public Geocache getFirstCacheFromResult(final EnumSet<LoadFlag> loadFlags) {
return CollectionUtils.isNotEmpty(geocodes) ? DataStore.loadCache(geocodes.iterator().next(), loadFlags) : null;
}
diff --git a/main/src/cgeo/geocaching/StaticMapsActivity.java b/main/src/cgeo/geocaching/StaticMapsActivity.java
index 7811da5..f19ce29 100644
--- a/main/src/cgeo/geocaching/StaticMapsActivity.java
+++ b/main/src/cgeo/geocaching/StaticMapsActivity.java
@@ -8,7 +8,6 @@ import com.googlecode.androidannotations.annotations.EActivity;
import com.googlecode.androidannotations.annotations.Extra;
import com.googlecode.androidannotations.annotations.OptionsItem;
import com.googlecode.androidannotations.annotations.OptionsMenu;
-
import org.apache.commons.collections4.CollectionUtils;
import android.app.ProgressDialog;
diff --git a/main/src/cgeo/geocaching/StatusFragment.java b/main/src/cgeo/geocaching/StatusFragment.java
index 4f70f0e..a4b5973 100644
--- a/main/src/cgeo/geocaching/StatusFragment.java
+++ b/main/src/cgeo/geocaching/StatusFragment.java
@@ -1,15 +1,17 @@
package cgeo.geocaching;
+import cgeo.geocaching.network.StatusUpdater;
import cgeo.geocaching.network.StatusUpdater.Status;
-import cgeo.geocaching.utils.IObserver;
import cgeo.geocaching.utils.Log;
+import rx.Subscription;
+import rx.android.observables.AndroidObservable;
+import rx.util.functions.Action1;
+
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
@@ -20,91 +22,68 @@ import android.widget.TextView;
public class StatusFragment extends Fragment {
- private ViewGroup status;
- private ImageView statusIcon;
- private TextView statusMessage;
-
- final private StatusHandler statusHandler = new StatusHandler();
+ private Subscription statusSubscription;
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
- status = (ViewGroup) inflater.inflate(R.layout.status, container, false);
- statusIcon = (ImageView) status.findViewById(R.id.status_icon);
- statusMessage = (TextView) status.findViewById(R.id.status_message);
- return status;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- CgeoApplication.getInstance().getStatusUpdater().addObserver(statusHandler);
- }
-
- @Override
- public void onPause() {
- CgeoApplication.getInstance().getStatusUpdater().deleteObserver(statusHandler);
- super.onPause();
- }
-
- private class StatusHandler extends Handler implements IObserver<Status> {
-
- @Override
- public void update(final Status data) {
- obtainMessage(0, data).sendToTarget();
- }
-
- @Override
- public void handleMessage(final Message msg) {
- final Status data = (Status) msg.obj;
- updateDisplay(data != null && data.message != null ? data : Status.defaultStatus());
- }
-
- private void updateDisplay(final Status data) {
-
- if (data == null) {
- status.setVisibility(View.INVISIBLE);
- return;
- }
-
- final Resources res = getResources();
- final String packageName = getActivity().getPackageName();
+ final ViewGroup statusGroup = (ViewGroup) inflater.inflate(R.layout.status, container, false);
+ final ImageView statusIcon = (ImageView) statusGroup.findViewById(R.id.status_icon);
+ final TextView statusMessage = (TextView) statusGroup.findViewById(R.id.status_message);
+ statusSubscription = AndroidObservable.fromFragment(this, StatusUpdater.latestStatus).subscribe(new Action1<Status>() {
+ @Override
+ public void call(final Status status) {
+ if (status == null) {
+ statusGroup.setVisibility(View.INVISIBLE);
+ return;
+ }
- if (data.icon != null) {
- final int iconId = res.getIdentifier(data.icon, "drawable", packageName);
- if (iconId != 0) {
- statusIcon.setImageResource(iconId);
- statusIcon.setVisibility(View.VISIBLE);
+ final Resources res = getResources();
+ final String packageName = getActivity().getPackageName();
+
+ if (status.icon != null) {
+ final int iconId = res.getIdentifier(status.icon, "drawable", packageName);
+ if (iconId != 0) {
+ statusIcon.setImageResource(iconId);
+ statusIcon.setVisibility(View.VISIBLE);
+ } else {
+ Log.w("StatusHandler: could not find icon corresponding to @drawable/" + status.icon);
+ statusIcon.setVisibility(View.GONE);
+ }
} else {
- Log.w("StatusHandler: could not find icon corresponding to @drawable/" + data.icon);
statusIcon.setVisibility(View.GONE);
}
- } else {
- statusIcon.setVisibility(View.GONE);
- }
- String message = data.message;
- if (data.messageId != null) {
- final int messageId = res.getIdentifier(data.messageId, "string", packageName);
- if (messageId != 0) {
- message = res.getString(messageId);
+ String message = status.message;
+ if (status.messageId != null) {
+ final int messageId = res.getIdentifier(status.messageId, "string", packageName);
+ if (messageId != 0) {
+ message = res.getString(messageId);
+ }
}
- }
- statusMessage.setText(message);
- status.setVisibility(View.VISIBLE);
+ statusMessage.setText(message);
+ statusGroup.setVisibility(View.VISIBLE);
- if (data.url != null) {
- status.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(final View v) {
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(data.url)));
- }
- });
- } else {
- status.setClickable(false);
+ if (status.url != null) {
+ statusGroup.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(status.url)));
+ }
+ });
+ } else {
+ statusGroup.setClickable(false);
+ }
}
- }
+ });
+ return statusGroup;
+ }
+ @Override
+ public void onDestroy() {
+ statusSubscription.unsubscribe();
+ super.onDestroy();
}
+
}
diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java
index dcfd80a..34f546a 100644
--- a/main/src/cgeo/geocaching/TrackableActivity.java
+++ b/main/src/cgeo/geocaching/TrackableActivity.java
@@ -130,6 +130,8 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
// try to get data from URI
if (geocode == null && guid == null && id == null && uri != null) {
+ geocode = ConnectorFactory.getTrackableFromURL(uri.toString());
+
final String uriHost = uri.getHost().toLowerCase(Locale.US);
if (uriHost.contains("geocaching.com")) {
geocode = uri.getQueryParameter("tracker");
diff --git a/main/src/cgeo/geocaching/UsefulAppsActivity.java b/main/src/cgeo/geocaching/UsefulAppsActivity.java
index c70143f..39c527d 100644
--- a/main/src/cgeo/geocaching/UsefulAppsActivity.java
+++ b/main/src/cgeo/geocaching/UsefulAppsActivity.java
@@ -62,6 +62,7 @@ public class UsefulAppsActivity extends AbstractActivity {
private static final HelperApp[] HELPER_APPS = {
new HelperApp(R.string.helper_calendar_title, R.string.helper_calendar_description, R.drawable.cgeo, "cgeo.calendar"),
new HelperApp(R.string.helper_sendtocgeo_title, R.string.helper_sendtocgeo_description, R.drawable.cgeo, "http://send2.cgeo.org"),
+ new HelperApp(R.string.helper_contacts_title, R.string.helper_contacts_description, R.drawable.cgeo, "cgeo.contacts"),
new HelperApp(R.string.helper_pocketquery_title, R.string.helper_pocketquery_description, R.drawable.helper_pocketquery, "org.pquery"),
new HelperApp(R.string.helper_locus_title, R.string.helper_locus_description, R.drawable.helper_locus, "menion.android.locus"),
new HelperApp(R.string.helper_google_translate_title, R.string.helper_google_translate_description, R.drawable.helper_google_translate, "com.google.android.apps.translate"),
diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
index 2adae7a..a5d5c14 100644
--- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
@@ -11,7 +11,6 @@ public abstract class AbstractListActivity extends FragmentListActivity implemen
IAbstractActivity {
private boolean keepScreenOn = false;
- private boolean paused = true;
protected CgeoApplication app = null;
protected Resources res = null;
@@ -85,26 +84,4 @@ public abstract class AbstractListActivity extends FragmentListActivity implemen
// initialize action bar title with activity title
ActivityMixin.setTitle(this, getTitle());
}
-
- @Override
- public void onResume() {
- paused = false;
- super.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- paused = true;
- }
-
- /**
- * Check if the current activity is paused. This must be called and acted
- * upon only from the UI thread.
- *
- * @return <code>true</code> if the current activity is paused
- */
- protected boolean isPaused() {
- return paused;
- }
}
diff --git a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
index c7d4507..6e2900d 100644
--- a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
@@ -5,7 +5,6 @@ import cgeo.geocaching.utils.Log;
import com.viewpagerindicator.TitlePageIndicator;
import com.viewpagerindicator.TitleProvider;
-
import org.apache.commons.lang3.tuple.Pair;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
index d6c2fe6..c26a24d 100644
--- a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
+++ b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
@@ -13,7 +13,6 @@ import menion.android.locus.addon.publiclib.geoData.Point;
import menion.android.locus.addon.publiclib.geoData.PointGeocachingData;
import menion.android.locus.addon.publiclib.geoData.PointGeocachingDataWaypoint;
import menion.android.locus.addon.publiclib.geoData.PointsData;
-
import org.apache.commons.lang3.time.FastDateFormat;
import android.app.Activity;
diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java
index ac5809e..40c4d92 100644
--- a/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java
+++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.apps.cachelist;
-import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.SearchResult;
import cgeo.geocaching.apps.App;
import android.app.Activity;
diff --git a/main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java b/main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java
index 76379de..0da198b 100644
--- a/main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java
+++ b/main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java
@@ -1,5 +1,7 @@
package cgeo.geocaching.concurrent;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.concurrent.ThreadFactory;
/**
@@ -12,6 +14,7 @@ public class PriorityThreadFactory implements ThreadFactory {
this.priority = priority;
}
+ @NonNull
@Override
public Thread newThread(Runnable r) {
Thread result = new Thread(r);
diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java
index 53a3bcb..eeacb5b 100644
--- a/main/src/cgeo/geocaching/connector/AbstractConnector.java
+++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java
@@ -16,10 +16,10 @@ import cgeo.geocaching.connector.capability.ISearchByViewPort;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.utils.RunnableWithArgument;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
+import rx.util.functions.Action1;
import java.util.ArrayList;
import java.util.Collection;
@@ -255,20 +255,20 @@ public abstract class AbstractConnector implements IConnector {
List<UserAction> actions = getDefaultUserActions();
if (this instanceof ISearchByOwner) {
- actions.add(new UserAction(R.string.user_menu_view_hidden, new RunnableWithArgument<UserAction.Context>() {
+ actions.add(new UserAction(R.string.user_menu_view_hidden, new Action1<Context>() {
@Override
- public void run(Context context) {
+ public void call(Context context) {
CacheListActivity.startActivityOwner(context.activity, context.userName);
}
}));
}
if (this instanceof ISearchByFinder) {
- actions.add(new UserAction(R.string.user_menu_view_found, new RunnableWithArgument<UserAction.Context>() {
+ actions.add(new UserAction(R.string.user_menu_view_found, new Action1<UserAction.Context>() {
@Override
- public void run(Context context) {
+ public void call(Context context) {
CacheListActivity.startActivityUserName(context.activity, context.userName);
}
}));
@@ -283,10 +283,10 @@ public abstract class AbstractConnector implements IConnector {
public List<UserAction> getDefaultUserActions() {
final ArrayList<UserAction> actions = new ArrayList<UserAction>();
if (ContactsAddon.isAvailable()) {
- actions.add(new UserAction(R.string.user_menu_open_contact, new RunnableWithArgument<UserAction.Context>() {
+ actions.add(new UserAction(R.string.user_menu_open_contact, new Action1<UserAction.Context>() {
@Override
- public void run(Context context) {
+ public void call(Context context) {
ContactsAddon.openContactCard(context.activity, context.userName);
}
}));
diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
index 0081951..68e3142 100644
--- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java
+++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
@@ -27,6 +27,10 @@ import cgeo.geocaching.geopoint.Viewport;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import rx.Observable;
+import rx.concurrency.Schedulers;
+import rx.util.functions.Func1;
+import rx.util.functions.Func2;
import java.util.ArrayList;
import java.util.Arrays;
@@ -176,14 +180,30 @@ public final class ConnectorFactory {
}
/** @see ISearchByViewPort#searchByViewport */
- public static SearchResult searchByViewport(final @NonNull Viewport viewport, final MapTokens tokens) {
- final SearchResult result = new SearchResult();
- for (final ISearchByViewPort connector : searchByViewPortConns) {
- if (connector.isActive()) {
- result.addSearchResult(connector.searchByViewport(viewport, tokens));
+ public static Observable<SearchResult> searchByViewport(final @NonNull Viewport viewport, final MapTokens tokens) {
+ return Observable.from(searchByViewPortConns).filter(new Func1<ISearchByViewPort, Boolean>() {
+ @Override
+ public Boolean call(final ISearchByViewPort connector) {
+ return connector.isActive();
}
- }
- return result;
+ }).parallel(new Func1<Observable<ISearchByViewPort>, Observable<SearchResult>>() {
+ @Override
+ public Observable<SearchResult> call(final Observable<ISearchByViewPort> connector) {
+ return connector.map(new Func1<ISearchByViewPort, SearchResult>() {
+ @Override
+ public SearchResult call(final ISearchByViewPort connector) {
+ return connector.searchByViewport(viewport, tokens);
+ }
+ });
+ }
+ }, Schedulers.threadPoolForIO()).reduce(new SearchResult(), new Func2<SearchResult, SearchResult, SearchResult>() {
+
+ @Override
+ public SearchResult call(final SearchResult result, final SearchResult searchResult) {
+ result.addSearchResult(searchResult);
+ return result;
+ }
+ });
}
public static String getGeocodeFromURL(final String url) {
@@ -200,6 +220,12 @@ public final class ConnectorFactory {
return TRACKABLE_CONNECTORS;
}
+ /**
+ * Get the geocode of a trackable from a URL.
+ *
+ * @param url
+ * @return {@code null} if the URL cannot be decoded
+ */
public static String getTrackableFromURL(final String url) {
if (url == null) {
return null;
diff --git a/main/src/cgeo/geocaching/connector/UserAction.java b/main/src/cgeo/geocaching/connector/UserAction.java
index d0c97bb..da03a95 100644
--- a/main/src/cgeo/geocaching/connector/UserAction.java
+++ b/main/src/cgeo/geocaching/connector/UserAction.java
@@ -1,8 +1,7 @@
package cgeo.geocaching.connector;
-import cgeo.geocaching.utils.RunnableWithArgument;
-
import org.eclipse.jdt.annotation.NonNull;
+import rx.util.functions.Action1;
import android.app.Activity;
@@ -19,14 +18,15 @@ public class UserAction {
}
public final int displayResourceId;
- private final @NonNull RunnableWithArgument<Context> runnable;
+ private final @NonNull
+ Action1<Context> runnable;
- public UserAction(int displayResourceId, final @NonNull RunnableWithArgument<UserAction.Context> runnable) {
+ public UserAction(int displayResourceId, final @NonNull Action1<Context> runnable) {
this.displayResourceId = displayResourceId;
this.runnable = runnable;
}
public void run(Context context) {
- runnable.run(context);
+ runnable.call(context);
}
}
diff --git a/main/src/cgeo/geocaching/connector/ec/ECApi.java b/main/src/cgeo/geocaching/connector/ec/ECApi.java
index 03fce4d..9d786ea 100644
--- a/main/src/cgeo/geocaching/connector/ec/ECApi.java
+++ b/main/src/cgeo/geocaching/connector/ec/ECApi.java
@@ -17,7 +17,6 @@ import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
-
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
diff --git a/main/src/cgeo/geocaching/connector/ec/ECConnector.java b/main/src/cgeo/geocaching/connector/ec/ECConnector.java
index 6da076b..71716fe 100644
--- a/main/src/cgeo/geocaching/connector/ec/ECConnector.java
+++ b/main/src/cgeo/geocaching/connector/ec/ECConnector.java
@@ -140,7 +140,7 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode,
// invoke settings activity to insert login details
if (status == StatusCode.NO_LOGIN_INFO_STORED && fromActivity != null) {
- SettingsActivity.jumpToServicesPage(fromActivity);
+ SettingsActivity.openForScreen(R.string.preference_screen_ec, fromActivity);
}
}
return status == StatusCode.NO_ERROR;
diff --git a/main/src/cgeo/geocaching/connector/ec/ECLogin.java b/main/src/cgeo/geocaching/connector/ec/ECLogin.java
index 52bd423..012bdc9 100644
--- a/main/src/cgeo/geocaching/connector/ec/ECLogin.java
+++ b/main/src/cgeo/geocaching/connector/ec/ECLogin.java
@@ -10,7 +10,6 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
-
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index e946748..a62b1f6 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -27,12 +27,12 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.settings.SettingsActivity;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RunnableWithArgument;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import rx.util.functions.Action1;
import android.content.Context;
import android.content.Intent;
@@ -91,7 +91,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
@Override
public boolean supportsPersonalNote() {
- return Settings.isPremiumMember();
+ return Settings.isGCPremiumMember();
}
@Override
@@ -285,7 +285,22 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
@Override
protected String getCacheUrlPrefix() {
- return CACHE_URL_SHORT;
+ return null; // UNUSED
+ }
+
+ @Override
+ public String getGeocodeFromUrl(String url) {
+ // coord.info URLs
+ String code = StringUtils.substringAfterLast(url, "coord.info/");
+ if (code != null && canHandle(code)) {
+ return code;
+ }
+ // expanded geocaching.com URLs
+ code = StringUtils.substringBetween(url, "/geocache/", "_");
+ if (code != null && canHandle(code)) {
+ return code;
+ }
+ return null;
}
@Override
@@ -316,7 +331,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
// invoke settings activity to insert login details
if (status == StatusCode.NO_LOGIN_INFO_STORED && fromActivity != null) {
- SettingsActivity.jumpToServicesPage(fromActivity);
+ SettingsActivity.openForScreen(R.string.preference_screen_gc, fromActivity);
}
}
return status == StatusCode.NO_ERROR;
@@ -379,17 +394,17 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public @NonNull
List<UserAction> getUserActions() {
List<UserAction> actions = super.getUserActions();
- actions.add(new UserAction(R.string.user_menu_open_browser, new RunnableWithArgument<UserAction.Context>() {
+ actions.add(new UserAction(R.string.user_menu_open_browser, new Action1<UserAction.Context>() {
@Override
- public void run(cgeo.geocaching.connector.UserAction.Context context) {
+ public void call(cgeo.geocaching.connector.UserAction.Context context) {
context.activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(context.userName))));
}
}));
- actions.add(new UserAction(R.string.user_menu_send_message, new RunnableWithArgument<UserAction.Context>() {
+ actions.add(new UserAction(R.string.user_menu_send_message, new Action1<UserAction.Context>() {
@Override
- public void run(cgeo.geocaching.connector.UserAction.Context context) {
+ public void call(cgeo.geocaching.connector.UserAction.Context context) {
context.activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/email/?u=" + Network.encode(context.userName))));
}
}));
diff --git a/main/src/cgeo/geocaching/connector/gc/GCLogin.java b/main/src/cgeo/geocaching/connector/gc/GCLogin.java
index a7cf6cf..92d488d 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCLogin.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCLogin.java
@@ -14,7 +14,6 @@ import cgeo.geocaching.utils.MatcherWrapper;
import cgeo.geocaching.utils.TextUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
-
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
@@ -97,7 +96,7 @@ public class GCLogin extends AbstractLogin {
}
if (getLoginStatus(loginData)) {
- Log.i("Already logged in Geocaching.com as " + username + " (" + Settings.getMemberStatus() + ')');
+ Log.i("Already logged in Geocaching.com as " + username + " (" + Settings.getGCMemberStatus() + ')');
if (switchToEnglish(loginData) && retry) {
return login(false);
}
@@ -132,7 +131,7 @@ public class GCLogin extends AbstractLogin {
assert loginData != null; // Caught above
if (getLoginStatus(loginData)) {
- Log.i("Successfully logged in Geocaching.com as " + username + " (" + Settings.getMemberStatus() + ')');
+ Log.i("Successfully logged in Geocaching.com as " + username + " (" + Settings.getGCMemberStatus() + ')');
if (switchToEnglish(loginData) && retry) {
return login(false);
@@ -204,9 +203,9 @@ public class GCLogin extends AbstractLogin {
Log.e("getLoginStatus: bad cache count", e);
}
setActualCachesFound(cachesCount);
- Settings.setMemberStatus(TextUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, null));
+ Settings.setGCMemberStatus(TextUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, null));
if ( page.contains(GCConstants.MEMBER_STATUS_RENEW) ) {
- Settings.setMemberStatus(GCConstants.MEMBER_STATUS_PM);
+ Settings.setGCMemberStatus(GCConstants.MEMBER_STATUS_PM);
}
return true;
}
@@ -259,9 +258,9 @@ public class GCLogin extends AbstractLogin {
final String responseData = StringUtils.defaultString(Network.getResponseData(Network.getRequest("http://www.geocaching.com/my/")));
final String profile = TextUtils.replaceWhitespace(responseData);
- Settings.setMemberStatus(TextUtils.getMatch(profile, GCConstants.PATTERN_MEMBER_STATUS, true, null));
+ Settings.setGCMemberStatus(TextUtils.getMatch(profile, GCConstants.PATTERN_MEMBER_STATUS, true, null));
if (profile.contains(GCConstants.MEMBER_STATUS_RENEW)) {
- Settings.setMemberStatus(GCConstants.MEMBER_STATUS_PM);
+ Settings.setGCMemberStatus(GCConstants.MEMBER_STATUS_PM);
}
setActualCachesFound(Integer.parseInt(TextUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", "")));
diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index 6c94150..2782b64 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCMap.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -368,7 +368,7 @@ public class GCMap {
}
}
- if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY) && Settings.isPremiumMember()) {
+ if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY) && Settings.isGCPremiumMember()) {
final Geopoint center = viewport.getCenter();
if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) {
//FIXME We don't have a RecaptchaReceiver!?
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index 62ccb14..70c3b2a 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -36,7 +36,6 @@ import cgeo.geocaching.utils.SynchronizedDateFormat;
import cgeo.geocaching.utils.TextUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
-
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringEscapeUtils;
@@ -282,7 +281,7 @@ public abstract class GCParser {
recaptchaText = thread.getText();
}
- if (!cids.isEmpty() && (Settings.isPremiumMember() || showCaptcha) && ((thread == null || StringUtils.isBlank(thread.getChallenge())) || StringUtils.isNotBlank(recaptchaText))) {
+ if (!cids.isEmpty() && (Settings.isGCPremiumMember() || showCaptcha) && ((thread == null || StringUtils.isBlank(thread.getChallenge())) || StringUtils.isNotBlank(recaptchaText))) {
Log.i("Trying to get .loc for " + cids.size() + " caches");
try {
@@ -347,6 +346,9 @@ public abstract class GCParser {
// attention: parseCacheFromText already stores implicitly through searchResult.addCache
if (searchResult != null && !searchResult.getGeocodes().isEmpty()) {
final Geocache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
+ if (cache == null) {
+ return null;
+ }
getExtraOnlineInfo(cache, page, handler);
// too late: it is already stored through parseCacheFromText
cache.setDetailedUpdatedNow();
@@ -741,7 +743,7 @@ public abstract class GCParser {
cache.parseWaypointsFromNote();
// logs
- cache.setLogs(loadLogsFromDetails(page, cache, false, true));
+ cache.setLogs(getLogsFromDetails(page, false));
// last check for necessary cache conditions
if (StringUtils.isBlank(cache.getGeocode())) {
@@ -1380,8 +1382,7 @@ public abstract class GCParser {
}
private static boolean changeFavorite(final Geocache cache, final boolean add) {
- final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
- final String userToken = TextUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
+ final String userToken = getUserToken(cache);
if (StringUtils.isEmpty(userToken)) {
return false;
}
@@ -1400,6 +1401,11 @@ public abstract class GCParser {
return false;
}
+ private static String getUserToken(final Geocache cache) {
+ final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
+ return TextUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
+ }
+
/**
* Removes the cache from the favorites.
*
@@ -1613,19 +1619,20 @@ public abstract class GCParser {
}
/**
- * Load logs from a cache details page.
+ * Extract 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
+ * return friends logs only (will require a network request)
+ * @return a list of log entries or <code>null</code> if the logs could not be retrieved
+ *
*/
- private static List<LogEntry> loadLogsFromDetails(final String page, final Geocache cache, final boolean friends, final boolean getDataFromPage) {
+ @Nullable
+ private static List<LogEntry> getLogsFromDetails(final String page, final boolean friends) {
String rawResponse;
- if (!getDataFromPage) {
+ if (friends) {
final MatcherWrapper userTokenMatcher = new MatcherWrapper(GCConstants.PATTERN_USERTOKEN, page);
if (!userTokenMatcher.find()) {
Log.e("GCParser.loadLogsFromDetails: unable to extract userToken");
@@ -1712,7 +1719,7 @@ public abstract class GCParser {
final JSONArray images = entry.getJSONArray("Images");
for (int i = 0; i < images.length(); i++) {
final JSONObject image = images.getJSONObject(i);
- final String url = "http://img.geocaching.com/cache/log/large/" + image.getString("FileName");
+ final String url = "http://imgcdn.geocaching.com/cache/log/large/" + image.getString("FileName");
final String title = TextUtils.removeControlCharacters(image.getString("Name"));
final Image logImage = new Image(url, title);
logDone.addLogImage(logImage);
@@ -1825,7 +1832,7 @@ public abstract class GCParser {
if (Settings.isFriendLogsWanted()) {
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs);
final List<LogEntry> allLogs = cache.getLogs();
- final List<LogEntry> friendLogs = loadLogsFromDetails(page, cache, true, false);
+ final List<LogEntry> friendLogs = getLogsFromDetails(page, true);
if (friendLogs != null) {
for (final LogEntry log : friendLogs) {
if (allLogs.contains(log)) {
@@ -1860,8 +1867,7 @@ public abstract class GCParser {
}
public static boolean editModifiedCoordinates(Geocache cache, Geopoint wpt) {
- final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
- final String userToken = TextUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
+ final String userToken = getUserToken(cache);
if (StringUtils.isEmpty(userToken)) {
return false;
}
@@ -1896,8 +1902,7 @@ public abstract class GCParser {
}
public static boolean uploadPersonalNote(Geocache cache) {
- final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
- final String userToken = TextUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
+ final String userToken = getUserToken(cache);
if (StringUtils.isEmpty(userToken)) {
return false;
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 2175935..c33a90e 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -75,7 +75,8 @@ final class OkapiClient {
private static final String CACHE_STATUS_ARCHIVED = "Archived";
private static final String CACHE_STATUS_DISABLED = "Temporarily unavailable";
private static final String CACHE_IS_FOUND = "is_found";
- private static final String CACHE_SIZE = "size";
+ private static final String CACHE_SIZE_DEPRECATED = "size";
+ private static final String CACHE_SIZE2 = "size2";
private static final String CACHE_VOTES = "rating_votes";
private static final String CACHE_NOTFOUNDS = "notfounds";
private static final String CACHE_FOUNDS = "founds";
@@ -112,7 +113,7 @@ final class OkapiClient {
// the several realms of possible fields for cache retrieval:
// Core: for livemap requests (L3 - only with level 3 auth)
// Additional: additional fields for full cache (L3 - only for level 3 auth, current - only for connectors with current api)
- private static final String SERVICE_CACHE_CORE_FIELDS = "code|name|location|type|status|difficulty|terrain|size|date_hidden";
+ private static final String SERVICE_CACHE_CORE_FIELDS = "code|name|location|type|status|difficulty|terrain|size|size2|date_hidden";
private static final String SERVICE_CACHE_CORE_L3_FIELDS = "is_found";
private static final String SERVICE_CACHE_ADDITIONAL_FIELDS = "owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|alt_wpts|attrnames|req_passwd";
private static final String SERVICE_CACHE_ADDITIONAL_CURRENT_FIELDS = "gc_code|attribution_note|attr_acodes";
@@ -152,19 +153,14 @@ final class OkapiClient {
}
public static List<Geocache> getCachesByOwner(final String username, final OCApiConnector connector) {
- final Parameters params = new Parameters("search_method", METHOD_SEARCH_ALL);
- final Map<String, String> valueMap = new LinkedHashMap<String, String>();
- final @Nullable
- String uuid = getUserUUID(connector, username);
- if (StringUtils.isEmpty(uuid)) {
- return Collections.emptyList();
- }
- valueMap.put("owner_uuid", uuid);
-
- return requestCaches(connector, params, valueMap);
+ return getCachesByUser(username, connector, "owner_uuid");
}
public static List<Geocache> getCachesByFinder(final String username, final OCApiConnector connector) {
+ return getCachesByUser(username, connector, "found_by");
+ }
+
+ private static List<Geocache> getCachesByUser(final String username, final OCApiConnector connector, final String userRequestParam) {
final Parameters params = new Parameters("search_method", METHOD_SEARCH_ALL);
final Map<String, String> valueMap = new LinkedHashMap<String, String>();
final @Nullable
@@ -172,7 +168,7 @@ final class OkapiClient {
if (StringUtils.isEmpty(uuid)) {
return Collections.emptyList();
}
- valueMap.put("found_by", uuid);
+ valueMap.put(userRequestParam, uuid);
return requestCaches(connector, params, valueMap);
}
@@ -567,12 +563,25 @@ final class OkapiClient {
}
private static CacheSize getCacheSize(final JSONObject response) {
- if (response.isNull(CACHE_SIZE)) {
+ if (response.isNull(CACHE_SIZE2)) {
+ return getCacheSizeDeprecated(response);
+ }
+ try {
+ final String size = response.getString(CACHE_SIZE2);
+ return CacheSize.getById(size);
+ } catch (JSONException e) {
+ Log.e("OkapiClient.getCacheSize", e);
+ return getCacheSizeDeprecated(response);
+ }
+ }
+
+ private static CacheSize getCacheSizeDeprecated(final JSONObject response) {
+ if (response.isNull(CACHE_SIZE_DEPRECATED)) {
return CacheSize.NOT_CHOSEN;
}
double size = 0;
try {
- size = response.getDouble(CACHE_SIZE);
+ size = response.getDouble(CACHE_SIZE_DEPRECATED);
} catch (final JSONException e) {
Log.e("OkapiClient.getCacheSize", e);
}
@@ -586,7 +595,7 @@ final class OkapiClient {
case 4:
return CacheSize.LARGE;
case 5:
- return CacheSize.LARGE;
+ return CacheSize.VERY_LARGE;
default:
break;
}
diff --git a/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java b/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java
index f72b698..5f11a11 100644
--- a/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java
+++ b/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java
@@ -28,10 +28,10 @@ public class OXGPXParser extends GPX10Parser {
/**
* The short description of OX caches contains "title by owner, type(T/D/Awesomeness)". That is a lot of
* duplication.
- *
+ *
* @param cache
*/
private static void removeTitleFromShortDescription(final @NonNull Geocache cache) {
- cache.setShortDescription(StringUtils.substringAfterLast(cache.getShortDescription(), ","));
+ cache.setShortDescription(StringUtils.trim(StringUtils.substringAfterLast(cache.getShortDescription(), ",")));
}
}
diff --git a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
index 2defc52..0137af4 100644
--- a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
+++ b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
@@ -11,7 +11,6 @@ import cgeo.geocaching.utils.CryptUtils;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
-
import org.apache.commons.collections4.CollectionUtils;
import org.eclipse.jdt.annotation.NonNull;
diff --git a/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java
index 69efddc..fb554b9 100644
--- a/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java
+++ b/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java
@@ -4,6 +4,7 @@ import cgeo.geocaching.connector.AbstractConnector;
import cgeo.geocaching.connector.UserAction;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import java.util.List;
@@ -15,7 +16,8 @@ public abstract class AbstractTrackableConnector implements TrackableConnector {
}
@Override
- public String getTrackableCodeFromUrl(@NonNull String url) {
+ public @Nullable
+ String getTrackableCodeFromUrl(@NonNull String url) {
return null;
}
diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java
index 8387076..03052f9 100644
--- a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java
+++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java
@@ -4,6 +4,10 @@ import cgeo.geocaching.Trackable;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.utils.Log;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
import java.util.regex.Pattern;
public class GeokretyConnector extends AbstractTrackableConnector {
@@ -29,7 +33,7 @@ public class GeokretyConnector extends AbstractTrackableConnector {
return GeokretyParser.parse(page);
}
- private static int getId(String geocode) {
+ protected static int getId(String geocode) {
try {
final String hex = geocode.substring(2);
return Integer.parseInt(hex, 16);
@@ -39,4 +43,25 @@ public class GeokretyConnector extends AbstractTrackableConnector {
return -1;
}
+ @Override
+ public @Nullable
+ String getTrackableCodeFromUrl(@NonNull String url) {
+ // http://geokrety.org/konkret.php?id=38545
+ String id = StringUtils.substringAfterLast(url, "konkret.php?id=");
+ if (StringUtils.isNumeric(id)) {
+ return geocode(Integer.parseInt(id));
+ }
+ return null;
+ }
+
+ /**
+ * Get geocode from geokrety id
+ *
+ * @param id
+ * @return
+ */
+ public static String geocode(final int id) {
+ return String.format("GK%04X", id);
+ }
+
}
diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
index ee8c8c0..0e64abd 100644
--- a/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
+++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
@@ -37,8 +37,8 @@ public class GeokretyParser {
public void start(Attributes attributes) {
try {
final String kretyId = attributes.getValue("id");
- if (StringUtils.isNotBlank(kretyId)) {
- trackable.setGeocode(geocode(Integer.parseInt(kretyId)));
+ if (StringUtils.isNumeric(kretyId)) {
+ trackable.setGeocode(GeokretyConnector.geocode(Integer.parseInt(kretyId)));
}
final String distance = attributes.getValue("dist");
if (StringUtils.isNotBlank(distance)) {
@@ -88,8 +88,4 @@ public class GeokretyParser {
}
return null;
}
-
- protected static String geocode(final int id) {
- return String.format("GK%04X", id);
- }
}
diff --git a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java
index 0990d96..6071b5f 100644
--- a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java
+++ b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java
@@ -4,6 +4,7 @@ import cgeo.geocaching.Trackable;
import cgeo.geocaching.connector.UserAction;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import java.util.List;
@@ -21,7 +22,8 @@ public interface TrackableConnector {
public Trackable searchTrackable(String geocode, String guid, String id);
- public String getTrackableCodeFromUrl(final @NonNull String url);
+ public @Nullable
+ String getTrackableCodeFromUrl(final @NonNull String url);
public @NonNull
List<UserAction> getUserActions();
diff --git a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java
index dad285c..77848d7 100644
--- a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java
+++ b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java
@@ -7,6 +7,7 @@ import cgeo.geocaching.connector.gc.GCParser;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import java.util.List;
import java.util.regex.Pattern;
@@ -20,7 +21,7 @@ public class TravelBugConnector extends AbstractTrackableConnector {
@Override
public boolean canHandleTrackable(String geocode) {
- return TravelBugConnector.PATTERN_TB_CODE.matcher(geocode).matches();
+ return TravelBugConnector.PATTERN_TB_CODE.matcher(geocode).matches() && !StringUtils.startsWithIgnoreCase(geocode, "GC");
}
@Override
@@ -54,8 +55,18 @@ public class TravelBugConnector extends AbstractTrackableConnector {
}
@Override
- public String getTrackableCodeFromUrl(@NonNull String url) {
- return StringUtils.substringAfterLast(url, "?tracker=");
+ public @Nullable
+ String getTrackableCodeFromUrl(@NonNull String url) {
+ // coord.info URLs
+ String code = StringUtils.substringAfterLast(url, "coord.info/");
+ if (code != null && canHandleTrackable(code)) {
+ return code;
+ }
+ code = StringUtils.substringAfterLast(url, "?tracker=");
+ if (code != null && canHandleTrackable(code)) {
+ return code;
+ }
+ return null;
}
@Override
diff --git a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
index 472bad5..0703c3c 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
@@ -164,15 +164,11 @@ public enum CacheAttribute {
}
private final static Map<String, CacheAttribute> FIND_BY_GCRAWNAME;
- private final static SparseArray<CacheAttribute> FIND_BY_GCID = new SparseArray<CacheAttribute>();
private final static SparseArray<CacheAttribute> FIND_BY_OCACODE = new SparseArray<CacheAttribute>();
static {
final HashMap<String, CacheAttribute> mapGcRawNames = new HashMap<String, CacheAttribute>();
for (CacheAttribute attr : values()) {
mapGcRawNames.put(attr.rawName, attr);
- if (attr.gcid != NO_ID) {
- FIND_BY_GCID.put(attr.gcid, attr);
- }
if (attr.ocacode != NO_ID) {
FIND_BY_OCACODE.put(attr.ocacode, attr);
}
@@ -184,10 +180,6 @@ public enum CacheAttribute {
return rawName != null ? FIND_BY_GCRAWNAME.get(rawName) : null;
}
- public static CacheAttribute getByGcId(final int gcid) {
- return FIND_BY_GCID.get(gcid);
- }
-
public static CacheAttribute getByOcACode(final int ocAcode) {
return FIND_BY_OCACODE.get(ocAcode);
}
diff --git a/main/src/cgeo/geocaching/enumerations/CacheListType.java b/main/src/cgeo/geocaching/enumerations/CacheListType.java
index f482d5b..7efd705 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheListType.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheListType.java
@@ -17,7 +17,7 @@ public enum CacheListType {
*/
public final boolean canSwitch;
- private CacheListType(final boolean canSwitch) {
+ CacheListType(final boolean canSwitch) {
this.canSwitch = canSwitch;
}
}
diff --git a/main/src/cgeo/geocaching/enumerations/CacheSize.java b/main/src/cgeo/geocaching/enumerations/CacheSize.java
index ee42c66..1255455 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheSize.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheSize.java
@@ -12,30 +12,38 @@ import java.util.Map;
* Enum listing cache sizes
*/
public enum CacheSize {
- MICRO("Micro", 1, R.string.cache_size_micro),
- SMALL("Small", 2, R.string.cache_size_small),
- REGULAR("Regular", 3, R.string.cache_size_regular),
- LARGE("Large", 4, R.string.cache_size_large),
- VIRTUAL("Virtual", 0, R.string.cache_size_virtual),
- NOT_CHOSEN("Not chosen", 0, R.string.cache_size_notchosen),
- OTHER("Other", 0, R.string.cache_size_other),
- UNKNOWN("Unknown", 0, R.string.cache_size_unknown); // CacheSize not init. yet
+ NANO("Nano", 0, R.string.cache_size_nano, "nano"), // used by OC only
+ MICRO("Micro", 1, R.string.cache_size_micro, "micro"),
+ SMALL("Small", 2, R.string.cache_size_small, "small"),
+ REGULAR("Regular", 3, R.string.cache_size_regular, "regular"),
+ LARGE("Large", 4, R.string.cache_size_large, "large"),
+ VERY_LARGE("Very large", 5, R.string.cache_size_very_large, "xlarge"), // used by OC only
+ NOT_CHOSEN("Not chosen", 6, R.string.cache_size_notchosen, ""),
+ VIRTUAL("Virtual", 7, R.string.cache_size_virtual, "none"),
+ OTHER("Other", 8, R.string.cache_size_other, "other"),
+ UNKNOWN("Unknown", -1, R.string.cache_size_unknown, ""); // CacheSize not init. yet
public final String id;
public final int comparable;
private final int stringId;
+ /**
+ * lookup for OC JSON requests (the numeric size is deprecated for OC)
+ */
+ private final String ocSize2;
- CacheSize(String id, int comparable, int stringId) {
+ CacheSize(final String id, final int comparable, final int stringId, final String ocSize2) {
this.id = id;
this.comparable = comparable;
this.stringId = stringId;
+ this.ocSize2 = ocSize2;
}
final private static Map<String, CacheSize> FIND_BY_ID;
static {
final HashMap<String, CacheSize> mapping = new HashMap<String, CacheSize>();
- for (CacheSize cs : values()) {
+ for (final CacheSize cs : values()) {
mapping.put(cs.id.toLowerCase(Locale.US), cs);
+ mapping.put(cs.ocSize2.toLowerCase(Locale.US), cs);
}
// add medium as additional string for Regular
mapping.put("medium", CacheSize.REGULAR);
@@ -61,21 +69,21 @@ public enum CacheSize {
/**
* Bad GPX files can contain the container size encoded as number.
- *
+ *
* @param id
* @return
*/
private static CacheSize getByNumber(final String id) {
try {
- int numerical = Integer.parseInt(id);
+ final int numerical = Integer.parseInt(id);
if (numerical != 0) {
- for (CacheSize size : CacheSize.values()) {
+ for (final CacheSize size : CacheSize.values()) {
if (size.comparable == numerical) {
return size;
}
}
}
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
// ignore, as this might be a number or not
}
return UNKNOWN;
@@ -85,4 +93,3 @@ public enum CacheSize {
return 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 c952ba0..35fe7a1 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheType.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheType.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.enumerations;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.ICache;
import cgeo.geocaching.R;
-import cgeo.geocaching.CgeoApplication;
import java.util.Collections;
import java.util.HashMap;
diff --git a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java b/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java
index 710c3ba..5bcaf4a 100644
--- a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java
+++ b/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.enumerations;
-import cgeo.geocaching.R;
import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.R;
import java.util.EnumSet;
diff --git a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java
index 68a17a5..e008294 100644
--- a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java
+++ b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java
@@ -1,29 +1,22 @@
package cgeo.geocaching.enumerations;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
public enum LogTypeTrackable {
- DO_NOTHING(0, "", R.string.log_tb_nothing),
- VISITED(1, "_Visited", R.string.log_tb_visit),
- DROPPED_OFF(2, "_DroppedOff", R.string.log_tb_drop);
+ DO_NOTHING("", R.string.log_tb_nothing),
+ VISITED("_Visited", R.string.log_tb_visit),
+ DROPPED_OFF("_DroppedOff", R.string.log_tb_drop);
- final public int id;
final public String action;
- final public int resourceId;
+ final private int resourceId;
- LogTypeTrackable(int id, String action, int resourceId) {
- this.id = id;
+ LogTypeTrackable(String action, int resourceId) {
this.action = action;
this.resourceId = resourceId;
}
- public static LogTypeTrackable findById(int id) {
- for (LogTypeTrackable logType : values()) {
- if (logType.id == id) {
- return logType;
- }
- }
- return DO_NOTHING;
+ public String getLabel() {
+ return CgeoApplication.getInstance().getString(resourceId);
}
-
}
diff --git a/main/src/cgeo/geocaching/enumerations/StatusCode.java b/main/src/cgeo/geocaching/enumerations/StatusCode.java
index e1a1aaa..8bda371 100644
--- a/main/src/cgeo/geocaching/enumerations/StatusCode.java
+++ b/main/src/cgeo/geocaching/enumerations/StatusCode.java
@@ -6,7 +6,6 @@ import android.content.res.Resources;
public enum StatusCode {
- 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),
@@ -24,7 +23,6 @@ public enum StatusCode {
LOG_POST_ERROR(R.string.err_log_post_failed),
LOG_POST_ERROR_EC(R.string.err_log_post_failed_ec),
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),
LOGIMAGE_POST_ERROR(R.string.err_logimage_post_failed);
diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java
index a2e0f93..08fca0b 100644
--- a/main/src/cgeo/geocaching/export/GpxExport.java
+++ b/main/src/cgeo/geocaching/export/GpxExport.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.export;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.AsyncTaskWithProgress;
diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java
index edbecf6..133f39a 100644
--- a/main/src/cgeo/geocaching/files/LocalStorage.java
+++ b/main/src/cgeo/geocaching/files/LocalStorage.java
@@ -7,7 +7,6 @@ import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpResponse;
-
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.Nullable;
@@ -122,7 +121,7 @@ public final class LocalStorage {
* the geocode
* @return the cache directory
*/
- public static File getStorageDir(final String geocode) {
+ public static File getStorageDir(@Nullable final String geocode) {
return storageDir(getStorage(), geocode);
}
@@ -134,11 +133,11 @@ public final class LocalStorage {
* the geocode
* @return the cache directory
*/
- private static File getStorageSecDir(final String geocode) {
+ private static File getStorageSecDir(@Nullable final String geocode) {
return storageDir(getStorageSec(), geocode);
}
- private static File storageDir(final File base, final String geocode) {
+ private static File storageDir(final File base, @Nullable final String geocode) {
return new File(base, StringUtils.defaultIfEmpty(geocode, "_others"));
}
@@ -155,7 +154,7 @@ public final class LocalStorage {
* true if an url was given, false if a file name was given
* @return the file
*/
- public static File getStorageFile(final String geocode, final String fileNameOrUrl, final boolean isUrl, final boolean createDirs) {
+ public static File getStorageFile(@Nullable final String geocode, final String fileNameOrUrl, final boolean isUrl, final boolean createDirs) {
return buildFile(getStorageDir(geocode), fileNameOrUrl, isUrl, createDirs);
}
diff --git a/main/src/cgeo/geocaching/files/SimpleDirChooser.java b/main/src/cgeo/geocaching/files/SimpleDirChooser.java
index 3e09cc4..e63c09f 100644
--- a/main/src/cgeo/geocaching/files/SimpleDirChooser.java
+++ b/main/src/cgeo/geocaching/files/SimpleDirChooser.java
@@ -89,9 +89,9 @@ public class SimpleDirChooser extends AbstractListActivity {
}
public void editPath() {
- AlertDialog.Builder builder = new AlertDialog.Builder(SimpleDirChooser.this);
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.simple_dir_chooser_current_path);
- final EditText input = new EditText(SimpleDirChooser.this);
+ final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setText(currentDir.getPath());
builder.setView(input);
diff --git a/main/src/cgeo/geocaching/filter/DistanceFilter.java b/main/src/cgeo/geocaching/filter/DistanceFilter.java
index 54225d2..cddcf72 100644
--- a/main/src/cgeo/geocaching/filter/DistanceFilter.java
+++ b/main/src/cgeo/geocaching/filter/DistanceFilter.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.filter;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.R;
-import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.geopoint.Geopoint;
import java.util.ArrayList;
diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
index d77341b..0033b9a 100644
--- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java
+++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
@@ -5,7 +5,8 @@ import cgeo.geocaching.R;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RunnableWithArgument;
+
+import rx.util.functions.Action1;
import android.app.Activity;
import android.app.AlertDialog;
@@ -77,7 +78,7 @@ public final class FilterUserInterface {
registry.add(new FactoryEntry(res.getString(resourceId), factoryClass));
}
- public void selectFilter(final RunnableWithArgument<IFilter> runAfterwards) {
+ public void selectFilter(final Action1<IFilter> runAfterwards) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.caches_filter_title);
@@ -89,7 +90,7 @@ public final class FilterUserInterface {
FactoryEntry entry = adapter.getItem(itemIndex);
// reset?
if (entry.filterFactory == null) {
- runAfterwards.run(null);
+ runAfterwards.call(null);
}
else {
try {
@@ -105,10 +106,10 @@ public final class FilterUserInterface {
builder.create().show();
}
- private void selectFromFactory(final IFilterFactory factory, final String menuTitle, final RunnableWithArgument<IFilter> runAfterwards) {
+ private void selectFromFactory(final IFilterFactory factory, final String menuTitle, final Action1<IFilter> runAfterwards) {
final List<IFilter> filters = Collections.unmodifiableList(factory.getFilters());
if (filters.size() == 1) {
- runAfterwards.run(filters.get(0));
+ runAfterwards.call(filters.get(0));
return;
}
@@ -119,7 +120,7 @@ public final class FilterUserInterface {
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int item) {
- runAfterwards.run(filters.get(item));
+ runAfterwards.call(filters.get(item));
}
});
diff --git a/main/src/cgeo/geocaching/filter/ModifiedFilter.java b/main/src/cgeo/geocaching/filter/ModifiedFilter.java
index d976b69..2ac088a 100644
--- a/main/src/cgeo/geocaching/filter/ModifiedFilter.java
+++ b/main/src/cgeo/geocaching/filter/ModifiedFilter.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.filter;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.CgeoApplication;
import java.util.Collections;
import java.util.List;
diff --git a/main/src/cgeo/geocaching/geopoint/Geopoint.java b/main/src/cgeo/geocaching/geopoint/Geopoint.java
index f21df01..e91a93d 100644
--- a/main/src/cgeo/geocaching/geopoint/Geopoint.java
+++ b/main/src/cgeo/geocaching/geopoint/Geopoint.java
@@ -4,6 +4,7 @@ import cgeo.geocaching.ICoordinates;
import cgeo.geocaching.R;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import android.location.Location;
import android.os.Build;
@@ -11,10 +12,13 @@ import android.os.Parcel;
import android.os.Parcelable;
/**
- * Abstraction of geographic point.
+ * Abstraction of geographic point. This class is immutable.
*/
public final class Geopoint implements ICoordinates, Parcelable {
- public static final Geopoint ZERO = new Geopoint(0.0, 0.0);
+ /**
+ * Reusable default object
+ */
+ public static final @NonNull Geopoint ZERO = new Geopoint(0.0, 0.0);
private static final double DEG_TO_RAD = Math.PI / 180;
private static final double RAD_TO_DEG = 180 / Math.PI;
@@ -64,7 +68,6 @@ public final class Geopoint implements ICoordinates, Parcelable {
* longitude string to parse
* @throws Geopoint.ParseException
* if any argument string cannot be parsed
- * @see GeopointParser#parse(String, String)
*/
public Geopoint(final String latText, final String lonText) {
this(GeopointParser.parseLatitude(latText), GeopointParser.parseLongitude(lonText));
@@ -273,19 +276,6 @@ public final class Geopoint implements ICoordinates, Parcelable {
}
/**
- * Checks if given Geopoint is similar to this Geopoint with tolerance.
- *
- * @param gp
- * Geopoint to check
- * @param tolerance
- * tolerance in km
- * @return true if similar, false otherwise
- */
- public boolean isEqualTo(Geopoint gp, double tolerance) {
- return null != gp && distanceTo(gp) <= tolerance;
- }
-
- /**
* Returns formatted coordinates.
*
* @param format
@@ -300,7 +290,7 @@ public final class Geopoint implements ICoordinates, Parcelable {
/**
* Returns formatted coordinates with default format.
* Default format is decimalminutes, e.g. N 52° 36.123 E 010° 03.456
- *
+ *
* @return formatted coordinates
*/
@Override
@@ -365,7 +355,7 @@ public final class Geopoint implements ICoordinates, Parcelable {
/**
* Get longitude character (E or W).
- *
+ *
* @return
*/
public char getLonDir() {
diff --git a/main/src/cgeo/geocaching/geopoint/GeopointParser.java b/main/src/cgeo/geocaching/geopoint/GeopointParser.java
index c043d6f..120e02e 100644
--- a/main/src/cgeo/geocaching/geopoint/GeopointParser.java
+++ b/main/src/cgeo/geocaching/geopoint/GeopointParser.java
@@ -70,37 +70,11 @@ class GeopointParser {
}
/**
- * Parses a pair of coordinates (latitude and longitude) out of a String.
- * Accepts following formats and combinations of it:
- * X DD
- * X DD°
- * X DD° MM
- * X DD° MM.MMM
- * X DD° MM SS
- *
- * as well as:
- * DD.DDDDDDD
- *
- * Both . and , are accepted, also variable count of spaces (also 0)
- *
- * @param latitude
- * the latitude string to parse
- * @param longitude
- * the longitude string to parse
- * @return an Geopoint with parsed latitude and longitude
- * @throws Geopoint.ParseException
- * if lat or lon could not be parsed
- */
- public static Geopoint parse(final String latitude, final String longitude) {
- final double lat = parseLatitude(latitude);
- final double lon = parseLongitude(longitude);
-
- return new Geopoint(lat, lon);
- }
-
- /*
- * (non JavaDoc)
- * Helper for coordinates-parsing.
+ * Helper for coordinates-parsing
+ *
+ * @param text
+ * @param latlon
+ * @return
*/
private static ResultWrapper parseHelper(final String text, final LatLon latlon) {
diff --git a/main/src/cgeo/geocaching/geopoint/Viewport.java b/main/src/cgeo/geocaching/geopoint/Viewport.java
index 9d55f69..ba0e040 100644
--- a/main/src/cgeo/geocaching/geopoint/Viewport.java
+++ b/main/src/cgeo/geocaching/geopoint/Viewport.java
@@ -5,16 +5,15 @@ import cgeo.geocaching.ICoordinates;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
-import java.util.Set;
+import java.util.Collection;
-
-public class Viewport {
+public final class Viewport {
public final @NonNull Geopoint center;
public final @NonNull Geopoint bottomLeft;
public final @NonNull Geopoint topRight;
- public Viewport(final ICoordinates point1, final ICoordinates point2) {
+ public Viewport(final @NonNull ICoordinates point1, final @NonNull ICoordinates point2) {
final Geopoint gp1 = point1.getCoords();
final Geopoint gp2 = point2.getCoords();
this.bottomLeft = new Geopoint(Math.min(gp1.getLatitude(), gp2.getLatitude()),
@@ -25,7 +24,7 @@ public class Viewport {
(gp1.getLongitude() + gp2.getLongitude()) / 2);
}
- public Viewport(final ICoordinates center, final double latSpan, final double lonSpan) {
+ public Viewport(final @NonNull ICoordinates center, final double latSpan, final double lonSpan) {
this.center = center.getCoords();
final double centerLat = this.center.getLatitude();
final double centerLon = this.center.getLongitude();
@@ -71,7 +70,7 @@ public class Viewport {
* the coordinates to check
* @return true if the point is contained in this viewport, false otherwise or if the point contains no coordinates
*/
- public boolean contains(final ICoordinates point) {
+ public boolean contains(final @NonNull ICoordinates point) {
final Geopoint coords = point.getCoords();
return coords != null
&& coords.getLongitudeE6() >= bottomLeft.getLongitudeE6()
@@ -87,12 +86,12 @@ public class Viewport {
/**
* Check whether another viewport is fully included into the current one.
- *
+ *
* @param vp
* the other viewport
- * @return true if the vp is fully included into this one, false otherwise
+ * @return true if the viewport is fully included into this one, false otherwise
*/
- public boolean includes(final Viewport vp) {
+ public boolean includes(final @NonNull Viewport vp) {
return contains(vp.bottomLeft) && contains(vp.topRight);
}
@@ -124,46 +123,37 @@ public class Viewport {
}
/**
- * Return a viewport that contains the current viewport as well as another point.
- *
- * @param point
- * 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;
- }
-
- 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));
- }
-
- /**
* 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;
+ static public @Nullable
+ Viewport containing(final Collection<? extends ICoordinates> points) {
+ boolean valid = false;
+ double latMin = Double.MAX_VALUE;
+ double latMax = -Double.MAX_VALUE;
+ double lonMin = Double.MAX_VALUE;
+ double lonMax = -Double.MAX_VALUE;
for (final ICoordinates point : points) {
- if (point != null && point.getCoords() != null) {
- if (viewport == null) {
- viewport = new Viewport(point, point);
- } else {
- viewport = viewport.expand(point);
+ if (point != null) {
+ final Geopoint coords = point.getCoords();
+ if (coords != null) {
+ valid = true;
+ final double latitude = coords.getLatitude();
+ final double longitude = coords.getLongitude();
+ latMin = Math.min(latMin, latitude);
+ latMax = Math.max(latMax, latitude);
+ lonMin = Math.min(lonMin, longitude);
+ lonMax = Math.max(lonMax, longitude);
}
}
}
- return viewport;
+ if (!valid) {
+ return null;
+ }
+ return new Viewport(new Geopoint(latMin, lonMin), new Geopoint(latMax, lonMax));
}
@Override
diff --git a/main/src/cgeo/geocaching/list/PseudoList.java b/main/src/cgeo/geocaching/list/PseudoList.java
index 365d6fd..f2cc7ed 100644
--- a/main/src/cgeo/geocaching/list/PseudoList.java
+++ b/main/src/cgeo/geocaching/list/PseudoList.java
@@ -17,6 +17,12 @@ public class PseudoList extends AbstractList {
*/
public static final AbstractList NEW_LIST = new PseudoList(NEW_LIST_ID, R.string.list_menu_create);
+ private static final int HISTORY_LIST_ID = 4;
+ /**
+ * list entry to create a new list
+ */
+ public static final AbstractList HISTORY_LIST = new PseudoList(HISTORY_LIST_ID, R.string.menu_history);
+
/**
* private constructor to have all instances as constants in the class
*/
diff --git a/main/src/cgeo/geocaching/list/StoredList.java b/main/src/cgeo/geocaching/list/StoredList.java
index 8106073..ba8ce35 100644
--- a/main/src/cgeo/geocaching/list/StoredList.java
+++ b/main/src/cgeo/geocaching/list/StoredList.java
@@ -5,11 +5,12 @@ import cgeo.geocaching.DataStore;
import cgeo.geocaching.R;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.ui.dialog.Dialogs;
-import cgeo.geocaching.utils.RunnableWithArgument;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
+import rx.util.functions.Action1;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
@@ -67,15 +68,15 @@ public final class StoredList extends AbstractList {
res = app.getResources();
}
- public void promptForListSelection(final int titleId, @NonNull final RunnableWithArgument<Integer> runAfterwards) {
+ public void promptForListSelection(final int titleId, @NonNull final Action1<Integer> runAfterwards) {
promptForListSelection(titleId, runAfterwards, false, -1);
}
- public void promptForListSelection(final int titleId, @NonNull final RunnableWithArgument<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId) {
+ public void promptForListSelection(final int titleId, @NonNull final Action1<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId) {
promptForListSelection(titleId, runAfterwards, onlyConcreteLists, exceptListId, StringUtils.EMPTY);
}
- public void promptForListSelection(final int titleId, @NonNull final RunnableWithArgument<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId, final String newListName) {
+ public void promptForListSelection(final int titleId, @NonNull final Action1<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId, final String newListName) {
final List<AbstractList> lists = new ArrayList<AbstractList>();
lists.addAll(getSortedLists());
@@ -87,7 +88,12 @@ public final class StoredList extends AbstractList {
}
if (!onlyConcreteLists) {
- lists.add(PseudoList.ALL_LIST);
+ if (exceptListId != PseudoList.ALL_LIST.id) {
+ lists.add(PseudoList.ALL_LIST);
+ }
+ if (exceptListId != PseudoList.HISTORY_LIST.id) {
+ lists.add(PseudoList.HISTORY_LIST);
+ }
}
lists.add(PseudoList.NEW_LIST);
@@ -109,7 +115,7 @@ public final class StoredList extends AbstractList {
promptForListCreation(runAfterwards, newListName);
}
else {
- runAfterwards.run(lists.get(itemId).id);
+ runAfterwards.call(lists.get(itemId).id);
}
}
});
@@ -138,17 +144,17 @@ public final class StoredList extends AbstractList {
return lists;
}
- public void promptForListCreation(@NonNull final RunnableWithArgument<Integer> runAfterwards, String newListName) {
- handleListNameInput(newListName, R.string.list_dialog_create_title, R.string.list_dialog_create, new RunnableWithArgument<String>() {
+ public void promptForListCreation(@NonNull final Action1<Integer> runAfterwards, String newListName) {
+ handleListNameInput(newListName, R.string.list_dialog_create_title, R.string.list_dialog_create, new Action1<String>() {
@Override
- public void run(final String listName) {
+ public void call(final String listName) {
final int newId = DataStore.createList(listName);
new StoredList(newId, listName, 0);
if (newId >= DataStore.customListIdOffset) {
ActivityMixin.showToast(activity, res.getString(R.string.list_dialog_create_ok));
- runAfterwards.run(newId);
+ runAfterwards.call(newId);
} else {
ActivityMixin.showToast(activity, res.getString(R.string.list_dialog_create_err));
}
@@ -156,15 +162,15 @@ public final class StoredList extends AbstractList {
});
}
- private void handleListNameInput(final String defaultValue, int dialogTitle, int buttonTitle, final RunnableWithArgument<String> runnable) {
- Dialogs.input(activity, dialogTitle, defaultValue, buttonTitle, new RunnableWithArgument<String>() {
+ private void handleListNameInput(final String defaultValue, int dialogTitle, int buttonTitle, final Action1<String> runnable) {
+ Dialogs.input(activity, dialogTitle, defaultValue, buttonTitle, new Action1<String>() {
@Override
- public void run(final String input) {
+ public void call(final String input) {
// remove whitespaces added by autocompletion of Android keyboard
String listName = StringUtils.trim(input);
if (StringUtils.isNotBlank(listName)) {
- runnable.run(listName);
+ runnable.call(listName);
}
}
});
@@ -172,10 +178,10 @@ public final class StoredList extends AbstractList {
public void promptForListRename(final int listId, @NonNull final Runnable runAfterRename) {
final StoredList list = DataStore.getList(listId);
- handleListNameInput(list.title, R.string.list_dialog_rename_title, R.string.list_dialog_rename, new RunnableWithArgument<String>() {
+ handleListNameInput(list.title, R.string.list_dialog_rename_title, R.string.list_dialog_rename, new Action1<String>() {
@Override
- public void run(final String listName) {
+ public void call(final String listName) {
DataStore.renameList(listId, listName);
runAfterRename.run();
}
@@ -197,7 +203,7 @@ public final class StoredList extends AbstractList {
* Return the given list, if it is a concrete list. Return the default list otherwise.
*/
public static int getConcreteList(int listId) {
- if (listId == PseudoList.ALL_LIST.id || listId == TEMPORARY_LIST_ID) {
+ if (listId == PseudoList.ALL_LIST.id || listId == TEMPORARY_LIST_ID || listId == PseudoList.HISTORY_LIST.id) {
return STANDARD_LIST_ID;
}
return listId;
diff --git a/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java
index dd7c7a6..e1573c9 100644
--- a/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java
+++ b/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.loaders;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.connector.gc.GCParser;
+import cgeo.geocaching.settings.Settings;
import android.content.Context;
diff --git a/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java
index 605f461..fdb35f2 100644
--- a/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java
+++ b/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java
@@ -2,9 +2,9 @@ package cgeo.geocaching.loaders;
import cgeo.geocaching.DataStore;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.settings.Settings;
import android.content.Context;
diff --git a/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java
index 1104f83..05eac18 100644
--- a/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java
+++ b/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.loaders;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.connector.gc.GCParser;
+import cgeo.geocaching.settings.Settings;
import android.content.Context;
diff --git a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java
index 5088484..b80a1b8 100644
--- a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java
+++ b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.loaders;
-import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.DataStore;
+import cgeo.geocaching.SearchResult;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.settings.Settings;
import android.content.Context;
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index c98ba72..722b3eb 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -38,11 +38,11 @@ import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.LeastRecentlyUsedSet;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RunnableWithArgument;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.HashCodeBuilder;
+import rx.util.functions.Action1;
import android.app.Activity;
import android.app.AlertDialog;
@@ -661,9 +661,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (Settings.getChooseList()) {
// let user select list to store cache in
new StoredList.UserInterface(activity).promptForListSelection(R.string.list_title,
- new RunnableWithArgument<Integer>() {
+ new Action1<Integer>() {
@Override
- public void run(final Integer selectedListId) {
+ public void call(final Integer selectedListId) {
storeCaches(geocodes, selectedListId);
}
}, true, StoredList.TEMPORARY_LIST_ID);
@@ -898,7 +898,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private long timeLastPositionOverlayCalculation = 0;
@Override
- protected void updateGeoData(final IGeoData geo) {
+ public void updateGeoData(final IGeoData geo) {
if (geo.isPseudoLocation()) {
locationValid = false;
} else {
@@ -1182,7 +1182,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
}
- final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens);
+ final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens).toBlockingObservable().single();
downloaded = true;
Set<Geocache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
diff --git a/main/src/cgeo/geocaching/maps/MapProviderFactory.java b/main/src/cgeo/geocaching/maps/MapProviderFactory.java
index 2e43e19..b928a1e 100644
--- a/main/src/cgeo/geocaching/maps/MapProviderFactory.java
+++ b/main/src/cgeo/geocaching/maps/MapProviderFactory.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.maps;
-import cgeo.geocaching.R;
import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.R;
import cgeo.geocaching.maps.google.GoogleMapProvider;
import cgeo.geocaching.maps.interfaces.MapProvider;
import cgeo.geocaching.maps.interfaces.MapSource;
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlay.java b/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlay.java
index 3339650..d14c687 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlay.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlay.java
@@ -77,11 +77,6 @@ public class GoogleCacheOverlay extends ItemizedOverlay<GoogleCacheOverlayItem>
}
@Override
- public Drawable superBoundCenter(Drawable markerIn) {
- return ItemizedOverlay.boundCenter(markerIn);
- }
-
- @Override
public Drawable superBoundCenterBottom(Drawable marker) {
return ItemizedOverlay.boundCenterBottom(marker);
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java b/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java
index cb95b2c..38d7d96 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.maps.google;
-import cgeo.geocaching.R;
import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.R;
import cgeo.geocaching.maps.AbstractMapProvider;
import cgeo.geocaching.maps.AbstractMapSource;
import cgeo.geocaching.maps.interfaces.MapItemFactory;
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
index d02e3c2..471e061 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
@@ -11,13 +11,11 @@ import cgeo.geocaching.maps.interfaces.MapControllerImpl;
import cgeo.geocaching.maps.interfaces.MapProjectionImpl;
import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OnMapDragListener;
-import cgeo.geocaching.maps.interfaces.OverlayImpl;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
-import com.google.android.maps.Overlay;
import org.apache.commons.lang3.reflect.MethodUtils;
@@ -54,7 +52,7 @@ public class GoogleMapView extends MapView implements MapViewImpl {
}
@Override
- public void draw(Canvas canvas) {
+ public void draw(final Canvas canvas) {
try {
if (getMapZoomLevel() > 22) { // to avoid too close zoom level (mostly on Samsung Galaxy S series)
getController().setZoom(22);
@@ -102,11 +100,6 @@ public class GoogleMapView extends MapView implements MapViewImpl {
}
@Override
- public void addOverlay(OverlayImpl ovl) {
- getOverlays().add((Overlay) ovl);
- }
-
- @Override
public void clearOverlays() {
getOverlays().clear();
}
diff --git a/main/src/cgeo/geocaching/maps/interfaces/ItemizedOverlayImpl.java b/main/src/cgeo/geocaching/maps/interfaces/ItemizedOverlayImpl.java
index 90c5b31..ee61f12 100644
--- a/main/src/cgeo/geocaching/maps/interfaces/ItemizedOverlayImpl.java
+++ b/main/src/cgeo/geocaching/maps/interfaces/ItemizedOverlayImpl.java
@@ -18,8 +18,6 @@ public interface ItemizedOverlayImpl extends OverlayImpl {
void superSetLastFocusedItemIndex(int i);
- Drawable superBoundCenter(Drawable markerIn);
-
Drawable superBoundCenterBottom(Drawable marker);
boolean superOnTap(int index);
diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java b/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java
index cb7ddc6..c30f65f 100644
--- a/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java
+++ b/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java
@@ -22,8 +22,6 @@ public interface MapViewImpl {
void clearOverlays();
- void addOverlay(OverlayImpl ovl);
-
MapControllerImpl getMapController();
void destroyDrawingCache();
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java
index 9e14e36..b9e40d7 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java
@@ -70,11 +70,6 @@ public class MapsforgeCacheOverlay extends ItemizedOverlay<MapsforgeCacheOverlay
}
@Override
- public Drawable superBoundCenter(Drawable markerIn) {
- return ItemizedOverlay.boundCenter(markerIn);
- }
-
- @Override
public Drawable superBoundCenterBottom(Drawable marker) {
return ItemizedOverlay.boundCenterBottom(marker);
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
index 78aa47d..e993548 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
@@ -11,7 +11,6 @@ import cgeo.geocaching.maps.interfaces.MapProjectionImpl;
import cgeo.geocaching.maps.interfaces.MapSource;
import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OnMapDragListener;
-import cgeo.geocaching.maps.interfaces.OverlayImpl;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
@@ -86,11 +85,6 @@ public class MapsforgeMapView extends MapView implements MapViewImpl {
}
@Override
- public void addOverlay(OverlayImpl ovl) {
- getOverlays().add((Overlay) ovl);
- }
-
- @Override
public void clearOverlays() {
getOverlays().clear();
}
@@ -229,7 +223,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl {
@Override
public void setMapTheme() {
String customRenderTheme = Settings.getCustomRenderThemeFilePath();
- if (!StringUtils.isEmpty(customRenderTheme)) {
+ if (StringUtils.isNotEmpty(customRenderTheme)) {
try {
setRenderTheme(new File(customRenderTheme));
} catch (FileNotFoundException e) {
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java
index 30355fd..a8111ed 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java
@@ -70,11 +70,6 @@ public class MapsforgeCacheOverlay extends ItemizedOverlay<MapsforgeCacheOverlay
}
@Override
- public Drawable superBoundCenter(Drawable markerIn) {
- return ItemizedOverlay.boundCenter(markerIn);
- }
-
- @Override
public Drawable superBoundCenterBottom(Drawable marker) {
return ItemizedOverlay.boundCenterBottom(marker);
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
index c741a31..6573304 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
@@ -10,7 +10,6 @@ import cgeo.geocaching.maps.interfaces.MapControllerImpl;
import cgeo.geocaching.maps.interfaces.MapProjectionImpl;
import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OnMapDragListener;
-import cgeo.geocaching.maps.interfaces.OverlayImpl;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
@@ -77,11 +76,6 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl {
}
@Override
- public void addOverlay(OverlayImpl ovl) {
- getOverlays().add((Overlay) ovl);
- }
-
- @Override
public void clearOverlays() {
getOverlays().clear();
}
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java
index 0daa588..774dbf6 100644
--- a/main/src/cgeo/geocaching/network/HtmlImage.java
+++ b/main/src/cgeo/geocaching/network/HtmlImage.java
@@ -6,6 +6,7 @@ import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.files.LocalStorage;
import cgeo.geocaching.list.StoredList;
+import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
@@ -14,6 +15,17 @@ import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.androidextra.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.Nullable;
+import rx.Observable;
+import rx.Observable.OnSubscribeFunc;
+import rx.Observer;
+import rx.Scheduler;
+import rx.Subscription;
+import rx.concurrency.Schedulers;
+import rx.subjects.PublishSubject;
+import rx.subscriptions.CompositeSubscription;
+import rx.subscriptions.Subscriptions;
+import rx.util.functions.Func1;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -31,6 +43,11 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
public class HtmlImage implements Html.ImageGetter {
@@ -64,6 +81,14 @@ public class HtmlImage implements Html.ImageGetter {
final private int maxHeight;
final private Resources resources;
+ // Background loading
+ final private PublishSubject<Observable<String>> loading = PublishSubject.create();
+ final Observable<String> waitForEnd = Observable.merge(loading).publish().refCount();
+ final CompositeSubscription subscription = new CompositeSubscription(waitForEnd.subscribe());
+ final private Scheduler downloadScheduler = Schedulers.executor(new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>()));
+ final private Set<String> downloading = new HashSet<String>();
+
public HtmlImage(final String geocode, final boolean returnErrorImage, final int listId, final boolean onlySave) {
this.geocode = geocode;
this.returnErrorImage = returnErrorImage;
@@ -80,60 +105,71 @@ public class HtmlImage implements Html.ImageGetter {
this.resources = CgeoApplication.getInstance().getResources();
}
+ @Nullable
@Override
public BitmapDrawable getDrawable(final String url) {
+ if (!onlySave) {
+ return loadDrawable(url);
+ } else {
+ synchronized(downloading) {
+ if (!downloading.contains(url)) {
+ loading.onNext(fetchDrawable(url).map(new Func1<BitmapDrawable, String>() {
+ @Override
+ public String call(final BitmapDrawable bitmapDrawable) {
+ return url;
+ }
+ }));
+ downloading.add(url);
+ }
+ return null;
+ }
+ }
+ }
+
+ public Observable<BitmapDrawable> fetchDrawable(final String url) {
+ return Observable.create(new OnSubscribeFunc<BitmapDrawable>() {
+ @Override
+ public Subscription onSubscribe(final Observer<? super BitmapDrawable> observer) {
+ if (!subscription.isUnsubscribed()) {
+ observer.onNext(loadDrawable(url));
+ }
+ observer.onCompleted();
+ return Subscriptions.empty();
+ }
+ }).subscribeOn(downloadScheduler);
+ }
+
+ public void waitForBackgroundLoading(@Nullable final CancellableHandler handler) {
+ if (handler != null) {
+ handler.unsubscribeIfCancelled(subscription);
+ }
+ loading.onCompleted();
+ waitForEnd.toBlockingObservable().lastOrDefault(null);
+ }
+
+ private BitmapDrawable loadDrawable(final String url) {
// Reject empty and counter images URL
if (StringUtils.isBlank(url) || isCounter(url)) {
- return new BitmapDrawable(resources, getTransparent1x1Image());
+ return getTransparent1x1Image(resources);
}
final boolean shared = url.contains("/images/icons/icon_");
final String pseudoGeocode = shared ? SHARED : geocode;
- Bitmap imagePre = loadImageFromStorage(url, pseudoGeocode, shared);
+ Bitmap image = loadImageFromStorage(url, pseudoGeocode, shared);
// Download image and save it to the cache
- if (imagePre == null) {
+ if (image == null) {
final File file = LocalStorage.getStorageFile(pseudoGeocode, url, true, true);
if (url.startsWith("data:image/")) {
if (url.contains(";base64,")) {
- // TODO: when we use SDK level 8 or above, we can use the streaming version of the base64
- // Android utilities.
- byte[] decoded = Base64.decode(StringUtils.substringAfter(url, ";base64,"), Base64.DEFAULT);
- OutputStream out = null;
- try {
- out = new FileOutputStream(file);
- out.write(decoded);
- } catch (final IOException e) {
- Log.e("HtmlImage.getDrawable: cannot write file for decoded inline image", e);
- return null;
- } finally {
- IOUtils.closeQuietly(out);
- }
+ saveBase64ToFile(url, file);
} else {
Log.e("HtmlImage.getDrawable: unable to decode non-base64 inline image");
return null;
}
} else {
- final String absoluteURL = makeAbsoluteURL(url);
-
- if (absoluteURL != null) {
- try {
- final HttpResponse httpResponse = Network.getRequest(absoluteURL, null, file);
- if (httpResponse != null) {
- final int statusCode = httpResponse.getStatusLine().getStatusCode();
- if (statusCode == 200) {
- LocalStorage.saveEntityToFile(httpResponse, file);
- } else if (statusCode == 304) {
- if (!file.setLastModified(System.currentTimeMillis())) {
- makeFreshCopy(file);
- }
- }
- }
- } catch (Exception e) {
- Log.e("HtmlImage.getDrawable (downloading from web)", e);
- }
- }
+ downloadOrRefreshCopy(url, file);
}
}
@@ -142,22 +178,56 @@ public class HtmlImage implements Html.ImageGetter {
}
// now load the newly downloaded image
- if (imagePre == null) {
- imagePre = loadImageFromStorage(url, pseudoGeocode, shared);
+ if (image == null) {
+ image = loadImageFromStorage(url, pseudoGeocode, shared);
}
// get image and return
- if (imagePre == null) {
+ if (image == null) {
Log.d("HtmlImage.getDrawable: Failed to obtain image");
- if (returnErrorImage) {
- imagePre = BitmapFactory.decodeResource(resources, R.drawable.image_not_loaded);
- } else {
- imagePre = getTransparent1x1Image();
+ return returnErrorImage
+ ? new BitmapDrawable(resources, BitmapFactory.decodeResource(resources, R.drawable.image_not_loaded))
+ : getTransparent1x1Image(resources);
+ }
+
+ return ImageUtils.scaleBitmapToFitDisplay(image);
+ }
+
+ private void downloadOrRefreshCopy(final String url, final File file) {
+ final String absoluteURL = makeAbsoluteURL(url);
+
+ if (absoluteURL != null) {
+ try {
+ final HttpResponse httpResponse = Network.getRequest(absoluteURL, null, file);
+ if (httpResponse != null) {
+ final int statusCode = httpResponse.getStatusLine().getStatusCode();
+ if (statusCode == 200) {
+ LocalStorage.saveEntityToFile(httpResponse, file);
+ } else if (statusCode == 304) {
+ if (!file.setLastModified(System.currentTimeMillis())) {
+ makeFreshCopy(file);
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e("HtmlImage.downloadOrRefreshCopy", e);
}
}
+ }
- return imagePre != null ? ImageUtils.scaleBitmapToFitDisplay(imagePre) : null;
+ private static void saveBase64ToFile(final String url, final File file) {
+ // TODO: when we use SDK level 8 or above, we can use the streaming version of the base64
+ // Android utilities.
+ OutputStream out = null;
+ try {
+ out = new FileOutputStream(file);
+ out.write(Base64.decode(StringUtils.substringAfter(url, ";base64,"), Base64.DEFAULT));
+ } catch (final IOException e) {
+ Log.e("HtmlImage.saveBase64ToFile: cannot write file for decoded inline image", e);
+ } finally {
+ IOUtils.closeQuietly(out);
+ }
}
/**
@@ -180,10 +250,11 @@ public class HtmlImage implements Html.ImageGetter {
}
}
- private Bitmap getTransparent1x1Image() {
- return BitmapFactory.decodeResource(resources, R.drawable.image_no_placement);
+ private BitmapDrawable getTransparent1x1Image(final Resources res) {
+ return new BitmapDrawable(res, BitmapFactory.decodeResource(resources, R.drawable.image_no_placement));
}
+ @Nullable
private Bitmap loadImageFromStorage(final String url, final String pseudoGeocode, final boolean forceKeep) {
try {
final File file = LocalStorage.getStorageFile(pseudoGeocode, url, true, false);
@@ -194,11 +265,12 @@ public class HtmlImage implements Html.ImageGetter {
final File fileSec = LocalStorage.getStorageSecFile(pseudoGeocode, url, true);
return loadCachedImage(fileSec, forceKeep);
} catch (Exception e) {
- Log.w("HtmlImage.getDrawable (reading cache)", e);
+ Log.w("HtmlImage.loadImageFromStorage", e);
}
return null;
}
+ @Nullable
private String makeAbsoluteURL(final String url) {
// Check if uri is absolute or not, if not attach the connector hostname
// FIXME: that should also include the scheme
@@ -222,6 +294,7 @@ public class HtmlImage implements Html.ImageGetter {
return null;
}
+ @Nullable
private Bitmap loadCachedImage(final File file, final boolean forceKeep) {
if (file.exists()) {
if (listId >= StoredList.STANDARD_LIST_ID || file.lastModified() > (new Date().getTime() - (24 * 60 * 60 * 1000)) || forceKeep) {
diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java
index e891d3b..b737fd2 100644
--- a/main/src/cgeo/geocaching/network/Network.java
+++ b/main/src/cgeo/geocaching/network/Network.java
@@ -34,7 +34,6 @@ import ch.boye.httpclientandroidlib.params.CoreProtocolPNames;
import ch.boye.httpclientandroidlib.params.HttpParams;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.EntityUtils;
-
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/main/src/cgeo/geocaching/network/OAuth.java b/main/src/cgeo/geocaching/network/OAuth.java
index c033660..1e22551 100644
--- a/main/src/cgeo/geocaching/network/OAuth.java
+++ b/main/src/cgeo/geocaching/network/OAuth.java
@@ -3,7 +3,6 @@ package cgeo.geocaching.network;
import cgeo.geocaching.utils.CryptUtils;
import ch.boye.httpclientandroidlib.NameValuePair;
-
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
index 888cf77..fd6ccc6 100644
--- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
@@ -10,7 +10,6 @@ import cgeo.geocaching.utils.MatcherWrapper;
import ch.boye.httpclientandroidlib.ParseException;
import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity;
import ch.boye.httpclientandroidlib.util.EntityUtils;
-
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.eclipse.jdt.annotation.NonNull;
diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java
index cb4c7f4..2d565bf 100644
--- a/main/src/cgeo/geocaching/network/StatusUpdater.java
+++ b/main/src/cgeo/geocaching/network/StatusUpdater.java
@@ -1,21 +1,22 @@
package cgeo.geocaching.network;
import cgeo.geocaching.CgeoApplication;
-import cgeo.geocaching.utils.MemorySubject;
-import cgeo.geocaching.utils.PeriodicHandler;
-import cgeo.geocaching.utils.PeriodicHandler.PeriodicHandlerListener;
import cgeo.geocaching.utils.Version;
import org.json.JSONException;
import org.json.JSONObject;
+import rx.Observable;
+import rx.concurrency.Schedulers;
+import rx.subjects.BehaviorSubject;
+import rx.util.functions.Func1;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
-import android.os.Looper;
import java.util.Locale;
+import java.util.concurrent.TimeUnit;
-public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implements Runnable, PeriodicHandlerListener {
+public class StatusUpdater {
static public class Status {
final public String message;
@@ -30,24 +31,41 @@ public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implement
this.url = url;
}
+ Status(final JSONObject response) {
+ message = get(response, "message");
+ messageId = get(response, "message_id");
+ icon = get(response, "icon");
+ url = get(response, "url");
+ }
+
final static public Status closeoutStatus =
new Status("", "status_closeout_warning", "attribute_abandonedbuilding", "http://faq.cgeo.org/#7_69");
- final static public Status defaultStatus() {
+ final static public Status defaultStatus(final Status upToDate) {
+ if (upToDate != null && upToDate.message != null) {
+ return upToDate;
+ }
return VERSION.SDK_INT < VERSION_CODES.ECLAIR_MR1 ? closeoutStatus : null;
}
}
- @Override
- public void onPeriodic() {
- final JSONObject response =
- Network.requestJSON("http://status.cgeo.org/api/status.json",
- new Parameters("version_code", String.valueOf(Version.getVersionCode(CgeoApplication.getInstance())),
- "version_name", Version.getVersionName(CgeoApplication.getInstance()),
- "locale", Locale.getDefault().toString()));
- if (response != null) {
- notifyObservers(new Status(get(response, "message"), get(response, "message_id"), get(response, "icon"), get(response, "url")));
- }
+ final static private Observable<Status> statusObservable =
+ Observable.interval(1800, TimeUnit.SECONDS).startWith(-1L).flatMap(new Func1<Long, Observable<Status>>() {
+ @Override
+ public Observable<Status> call(Long id) {
+ final JSONObject response =
+ Network.requestJSON("http://status.cgeo.org/api/status.json",
+ new Parameters("version_code", String.valueOf(Version.getVersionCode(CgeoApplication.getInstance())),
+ "version_name", Version.getVersionName(CgeoApplication.getInstance()),
+ "locale", Locale.getDefault().toString()));
+ return response != null ? Observable.from(Status.defaultStatus((new Status(response)))) : Observable.<Status>empty();
+ }
+ }).subscribeOn(Schedulers.threadPoolForIO());
+
+ final static public BehaviorSubject<Status> latestStatus = BehaviorSubject.create(Status.defaultStatus(null));
+
+ static {
+ statusObservable.subscribe(latestStatus);
}
private static String get(final JSONObject json, final String key) {
@@ -58,11 +76,4 @@ public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implement
}
}
- @Override
- public void run() {
- Looper.prepare();
- new PeriodicHandler(1800000L, this).start();
- Looper.loop();
- }
-
}
diff --git a/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java b/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java
new file mode 100644
index 0000000..123469c
--- /dev/null
+++ b/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java
@@ -0,0 +1,71 @@
+package cgeo.geocaching.search;
+
+import org.apache.commons.lang3.StringUtils;
+
+import rx.util.functions.Func1;
+
+import android.content.Context;
+import android.widget.ArrayAdapter;
+import android.widget.Filter;
+
+/**
+ * The standard auto completion only matches user input at word boundaries. Therefore searching "est" will not match
+ * "test". This adapter matches everywhere.
+ *
+ */
+public class AutoCompleteAdapter extends ArrayAdapter<String> {
+
+ private String[] suggestions;
+ private final Func1<String, String[]> suggestionFunction;
+
+ public AutoCompleteAdapter(Context context, int textViewResourceId, final Func1<String, String[]> suggestionFunction) {
+ super(context, textViewResourceId);
+ this.suggestionFunction = suggestionFunction;
+ }
+
+ @Override
+ public int getCount() {
+ return suggestions.length;
+ }
+
+ @Override
+ public String getItem(int index) {
+ return suggestions[index];
+ }
+
+ @Override
+ public Filter getFilter() {
+ Filter filter = new Filter() {
+
+ @Override
+ protected FilterResults performFiltering(CharSequence constraint) {
+ FilterResults filterResults = new FilterResults();
+ if (constraint == null) {
+ return filterResults;
+ }
+ String trimmed = StringUtils.trim(constraint.toString());
+ if (StringUtils.length(trimmed) >= 2) {
+ String[] newResults = suggestionFunction.call(trimmed);
+
+ // Assign the data to the FilterResults, but do not yet store in the global member.
+ // Otherwise we might invalidate the adapter and cause an IllegalStateException.
+ filterResults.values = newResults;
+ filterResults.count = newResults.length;
+ }
+ return filterResults;
+ }
+
+ @Override
+ protected void publishResults(CharSequence constraint, FilterResults filterResults) {
+ if (filterResults != null && filterResults.count > 0) {
+ suggestions = (String[]) filterResults.values;
+ notifyDataSetChanged();
+ }
+ else {
+ notifyDataSetInvalidated();
+ }
+ }
+ };
+ return filter;
+ }
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/search/SuggestionProvider.java b/main/src/cgeo/geocaching/search/SuggestionProvider.java
new file mode 100644
index 0000000..c0a7728
--- /dev/null
+++ b/main/src/cgeo/geocaching/search/SuggestionProvider.java
@@ -0,0 +1,57 @@
+package cgeo.geocaching.search;
+
+import cgeo.geocaching.DataStore;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.app.SearchManager;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class SuggestionProvider extends ContentProvider {
+
+ private static Cursor lastCursor;
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public String getType(final Uri arg0) {
+ return SearchManager.SUGGEST_MIME_TYPE;
+ }
+
+ @Override
+ public Cursor query(final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, final String sortOrder) {
+ final String searchTerm = uri.getLastPathSegment();
+ // can be empty when deleting the query
+ if (StringUtils.equals(searchTerm, SearchManager.SUGGEST_URI_PATH_QUERY)) {
+ return lastCursor;
+ }
+ return getSuggestions(searchTerm);
+ }
+
+ private static Cursor getSuggestions(final String searchTerm) {
+ lastCursor = DataStore.findSuggestions(searchTerm);
+ return lastCursor;
+ }
+
+ @Override
+ public int delete(final Uri uri, final String selection, final String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Uri insert(final Uri uri, final ContentValues values) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int update(final Uri uri, final ContentValues values, final String selection, final String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/settings/OAuthPreference.java b/main/src/cgeo/geocaching/settings/OAuthPreference.java
index 3550947..06982f5 100644
--- a/main/src/cgeo/geocaching/settings/OAuthPreference.java
+++ b/main/src/cgeo/geocaching/settings/OAuthPreference.java
@@ -23,8 +23,8 @@ public class OAuthPreference extends Preference {
OCPL(R.string.pref_fakekey_ocpl_authorization, OCPLAuthorizationActivity.class),
TWITTER(R.string.pref_fakekey_twitter_authorization, TwitterAuthorizationActivity.class);
- public int prefKeyId;
- public Class<?> authActivity;
+ public final int prefKeyId;
+ public final Class<?> authActivity;
OAuthActivityMapping(int prefKeyId, Class<?> clazz) {
this.prefKeyId = prefKeyId;
diff --git a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
index 3e838ab..2ca8df1 100644
--- a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
+++ b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
@@ -8,7 +8,6 @@ import cgeo.geocaching.ui.dialog.Dialogs;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
-
import org.apache.commons.lang3.StringUtils;
import android.app.ProgressDialog;
diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java
index 0732866..ee97c13 100644
--- a/main/src/cgeo/geocaching/settings/Settings.java
+++ b/main/src/cgeo/geocaching/settings/Settings.java
@@ -313,16 +313,16 @@ public class Settings {
return getBoolean(R.string.pref_connectorOXActive, false);
}
- public static boolean isPremiumMember() {
+ public static boolean isGCPremiumMember() {
// Basic Member, Premium Member, ???
- return GCConstants.MEMBER_STATUS_PM.equalsIgnoreCase(Settings.getMemberStatus());
+ return GCConstants.MEMBER_STATUS_PM.equalsIgnoreCase(Settings.getGCMemberStatus());
}
- public static String getMemberStatus() {
+ public static String getGCMemberStatus() {
return getString(R.string.pref_memberstatus, "");
}
- public static boolean setMemberStatus(final String memberStatus) {
+ public static boolean setGCMemberStatus(final String memberStatus) {
if (StringUtils.isBlank(memberStatus)) {
return remove(R.string.pref_memberstatus);
}
@@ -478,7 +478,7 @@ public class Settings {
}
public static boolean getLoadDirImg() {
- return !isPremiumMember() && getBoolean(R.string.pref_loaddirectionimg, true);
+ return !isGCPremiumMember() && getBoolean(R.string.pref_loaddirectionimg, true);
}
public static void setGcCustomDate(final String format) {
@@ -506,7 +506,7 @@ public class Settings {
}
public static boolean isShowCaptcha() {
- return !isPremiumMember() && getBoolean(R.string.pref_showcaptcha, false);
+ return !isGCPremiumMember() && getBoolean(R.string.pref_showcaptcha, false);
}
public static boolean isExcludeDisabledCaches() {
diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java
index 58acfc1..bcf6715 100644
--- a/main/src/cgeo/geocaching/settings/SettingsActivity.java
+++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.settings;
import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Intents;
import cgeo.geocaching.R;
import cgeo.geocaching.SelectMapfileActivity;
@@ -19,8 +20,10 @@ import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
import org.openintents.intents.FileManagerIntents;
+import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -52,8 +55,7 @@ import java.util.Locale;
*/
public class SettingsActivity extends PreferenceActivity {
- private static final String INTENT_GOTO = "GOTO";
- private static final int INTENT_GOTO_SERVICES = 1;
+ private static final String INTENT_OPEN_SCREEN = "OPEN_SCREEN";
/**
* Enumeration for directory choosers. This is how we can retrieve information about the
@@ -89,18 +91,21 @@ public class SettingsActivity extends PreferenceActivity {
initPreferences();
Intent intent = getIntent();
- int gotoPage = intent.getIntExtra(INTENT_GOTO, 0);
- if (gotoPage == INTENT_GOTO_SERVICES) {
- // start with services screen
- PreferenceScreen main = (PreferenceScreen) getPreference(R.string.pref_fakekey_main_screen);
- try {
- if (main != null) {
- int index = getPreference(R.string.pref_fakekey_services_screen).getOrder();
- main.onItemClick(null, null, index, 0);
- }
- } catch (RuntimeException e) {
- Log.e("could not open services preferences", e);
- }
+ openInitialScreen(intent.getIntExtra(INTENT_OPEN_SCREEN, 0));
+ }
+
+ private void openInitialScreen(int initialScreen) {
+ if (initialScreen == 0) {
+ return;
+ }
+ PreferenceScreen screen = (PreferenceScreen) getPreference(initialScreen);
+ if (screen == null) {
+ return;
+ }
+ try {
+ setPreferenceScreen(screen);
+ } catch (RuntimeException e) {
+ Log.e("could not open preferences " + initialScreen, e);
}
}
@@ -121,6 +126,7 @@ public class SettingsActivity extends PreferenceActivity {
initSend2CgeoPreferences();
initServicePreferences();
initNavigationMenuPreferences();
+ initMaintenanceButtons();
for (int k : new int[] { R.string.pref_username, R.string.pref_password,
R.string.pref_pass_vote, R.string.pref_signature,
@@ -141,9 +147,9 @@ public class SettingsActivity extends PreferenceActivity {
getPreference(appEnum.preferenceKey).setEnabled(true);
}
}
- getPreference(R.string.pref_fakekey_basicmembers_screen)
- .setEnabled(!Settings.isPremiumMember());
- redrawScreen(R.string.pref_fakekey_navigation_menu_screen);
+ getPreference(R.string.preference_screen_basicmembers)
+ .setEnabled(!Settings.isGCPremiumMember());
+ redrawScreen(R.string.preference_screen_navigation_menu);
}
private void initServicePreferences() {
@@ -310,6 +316,35 @@ public class SettingsActivity extends PreferenceActivity {
});
}
+ public void initMaintenanceButtons() {
+ Preference dirMaintenance = getPreference(R.string.pref_fakekey_preference_maintenance_directories);
+ dirMaintenance.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(final Preference preference) {
+ // disable the button, as the cleanup runs in background and should not be invoked a second time
+ preference.setEnabled(false);
+
+ Resources res = getResources();
+ final SettingsActivity activity = SettingsActivity.this;
+ final ProgressDialog dialog = ProgressDialog.show(activity, res.getString(R.string.init_maintenance), res.getString(R.string.init_maintenance_directories), true, false);
+ new Thread() {
+ @Override
+ public void run() {
+ DataStore.removeObsoleteCacheDirectories();
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ dialog.dismiss();
+ }
+ });
+ }
+ }.start();
+
+ return true;
+ }
+ });
+ }
+
private void initDbLocationPreference() {
Preference p = getPreference(R.string.pref_dbonsdcard);
p.setPersistent(false);
@@ -336,21 +371,29 @@ public class SettingsActivity extends PreferenceActivity {
}
void initBasicMemberPreferences() {
- getPreference(R.string.pref_fakekey_basicmembers_screen)
- .setEnabled(!Settings.isPremiumMember());
+ getPreference(R.string.preference_screen_basicmembers)
+ .setEnabled(!Settings.isGCPremiumMember());
getPreference(R.string.pref_loaddirectionimg)
- .setEnabled(!Settings.isPremiumMember());
+ .setEnabled(!Settings.isGCPremiumMember());
getPreference(R.string.pref_showcaptcha)
- .setEnabled(!Settings.isPremiumMember());
+ .setEnabled(!Settings.isGCPremiumMember());
- redrawScreen(R.string.pref_fakekey_services_screen);
+ redrawScreen(R.string.preference_screen_services);
}
- void redrawScreen(int key) {
- PreferenceScreen screen = (PreferenceScreen) getPreference(key);
- if (screen == null) {
+ /**
+ * Refresh a preference screen. Has no effect when called for a preference, that is not actually a preference
+ * screen.
+ *
+ * @param key
+ * Key of a preference screen.
+ */
+ void redrawScreen(final int key) {
+ final Preference preference = getPreference(key);
+ if (!(preference instanceof PreferenceScreen)) {
return;
}
+ final PreferenceScreen screen = (PreferenceScreen) preference;
ListAdapter adapter = screen.getRootAdapter();
if (adapter instanceof BaseAdapter) {
((BaseAdapter) adapter).notifyDataSetChanged();
@@ -399,9 +442,9 @@ public class SettingsActivity extends PreferenceActivity {
: R.string.settings_authorize));
}
- public static void jumpToServicesPage(final Context fromActivity) {
+ public static void openForScreen(final int preferenceScreenKey, final Context fromActivity) {
final Intent intent = new Intent(fromActivity, SettingsActivity.class);
- intent.putExtra(INTENT_GOTO, INTENT_GOTO_SERVICES);
+ intent.putExtra(INTENT_OPEN_SCREEN, preferenceScreenKey);
fromActivity.startActivity(intent);
}
@@ -445,15 +488,15 @@ public class SettingsActivity extends PreferenceActivity {
break;
case R.string.pref_fakekey_ocde_authorization:
setOCDEAuthTitle();
- redrawScreen(R.string.pref_fakekey_services_screen);
+ redrawScreen(R.string.preference_screen_ocde);
break;
case R.string.pref_fakekey_ocpl_authorization:
setOCPLAuthTitle();
- redrawScreen(R.string.pref_fakekey_services_screen);
+ redrawScreen(R.string.preference_screen_ocpl);
break;
case R.string.pref_fakekey_twitter_authorization:
setTwitterAuthTitle();
- redrawScreen(R.string.pref_fakekey_services_screen);
+ redrawScreen(R.string.preference_screen_twitter);
break;
default:
throw new IllegalArgumentException();
@@ -582,6 +625,13 @@ public class SettingsActivity extends PreferenceActivity {
preferenceActivity.addPreferencesFromResource(preferencesResId);
}
+ @SuppressWarnings("deprecation")
+ @Override
+ public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+ // TODO replace with fragment based code
+ super.setPreferenceScreen(preferenceScreen);
+ }
+
private static boolean isPreference(final Preference preference, int preferenceKeyId) {
return getKey(preferenceKeyId).equals(preference.getKey());
}
diff --git a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java
index a1c04a4..2b171b4 100644
--- a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java
+++ b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java
@@ -3,6 +3,7 @@ package cgeo.geocaching.sorting;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.utils.Log;
+import org.apache.commons.lang3.StringUtils;
/**
* abstract super implementation for all cache comparators
@@ -13,25 +14,35 @@ public abstract class AbstractCacheComparator implements CacheComparator {
@Override
public final int compare(final Geocache cache1, final Geocache cache2) {
try {
- // first check that we have all necessary data for the comparison
- if (!canCompare(cache1, cache2)) {
- return 0;
+ final boolean canCompare1 = canCompare(cache1);
+ final boolean canCompare2 = canCompare(cache2);
+ if (!canCompare1) {
+ return canCompare2 ? 1 : fallbackToGeocode(cache1, cache2);
}
- return compareCaches(cache1, cache2);
- } catch (Exception e) {
+ return canCompare2 ? compareCaches(cache1, cache2) : -1;
+ } catch (final Exception e) {
Log.e("AbstractCacheComparator.compare", e);
+ // This may violate the Comparator interface if the exception is not systematic.
+ return fallbackToGeocode(cache1, cache2);
}
- return 0;
+ }
+
+ private static int fallbackToGeocode(final Geocache cache1, final Geocache cache2) {
+ return StringUtils.defaultString(cache1.getGeocode()).compareToIgnoreCase(StringUtils.defaultString(cache2.getGeocode()));
}
/**
- * Check necessary preconditions (like missing fields) before running the comparison itself
- *
- * @param cache1
- * @param cache2
- * @return
+ * Check necessary preconditions (like missing fields) before running the comparison itself.
+ * Caches not filling the conditions will be placed last, sorted by Geocode.
+ *
+ * The default returns <code>true</code> and can be overridden if needed in child classes.
+ *
+ * @param cache
+ * @return <code>true</code> if the cache holds the necessary data to be compared meaningfully
*/
- protected abstract boolean canCompare(final Geocache cache1, final Geocache cache2);
+ protected boolean canCompare(final Geocache cache) {
+ return true;
+ }
/**
* Compares two caches. Logging and exception handling is implemented outside this method already.
diff --git a/main/src/cgeo/geocaching/sorting/CacheComparator.java b/main/src/cgeo/geocaching/sorting/CacheComparator.java
index 7932729..b06a4b0 100644
--- a/main/src/cgeo/geocaching/sorting/CacheComparator.java
+++ b/main/src/cgeo/geocaching/sorting/CacheComparator.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.sorting;
-import java.util.Comparator;
-
import cgeo.geocaching.Geocache;
+import java.util.Comparator;
+
public interface CacheComparator extends Comparator<Geocache> {
}
diff --git a/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java b/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
index 99a535a..8cf3d9d 100644
--- a/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
+++ b/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
@@ -2,7 +2,8 @@ package cgeo.geocaching.sorting;
import cgeo.geocaching.R;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RunnableWithArgument;
+
+import rx.util.functions.Action1;
import android.app.Activity;
import android.app.AlertDialog;
@@ -70,7 +71,7 @@ public class ComparatorUserInterface {
registry.add(new ComparatorEntry(res.getString(resourceId), comparatorClass));
}
- public void selectComparator(final CacheComparator current, final RunnableWithArgument<CacheComparator> runAfterwards) {
+ public void selectComparator(final CacheComparator current, final Action1<CacheComparator> runAfterwards) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.caches_sort_title);
@@ -85,11 +86,11 @@ public class ComparatorUserInterface {
ComparatorEntry entry = registry.get(itemIndex);
try {
if (entry.cacheComparator == null) {
- runAfterwards.run(null);
+ runAfterwards.call(null);
}
else {
CacheComparator comparator = entry.cacheComparator.newInstance();
- runAfterwards.run(comparator);
+ runAfterwards.call(comparator);
}
} catch (InstantiationException e) {
Log.e("selectComparator", e);
diff --git a/main/src/cgeo/geocaching/sorting/DateComparator.java b/main/src/cgeo/geocaching/sorting/DateComparator.java
index 091f6a4..9df70f9 100644
--- a/main/src/cgeo/geocaching/sorting/DateComparator.java
+++ b/main/src/cgeo/geocaching/sorting/DateComparator.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.Geocache;
import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.Geocache;
import java.util.ArrayList;
import java.util.Date;
@@ -12,11 +12,6 @@ import java.util.Date;
public class DateComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(Geocache cache1, Geocache cache2) {
- return true;
- }
-
- @Override
protected int compareCaches(Geocache cache1, Geocache cache2) {
final Date date1 = cache1.getHiddenDate();
final Date date2 = cache2.getHiddenDate();
diff --git a/main/src/cgeo/geocaching/sorting/DifficultyComparator.java b/main/src/cgeo/geocaching/sorting/DifficultyComparator.java
index 73d12fa..459f38d 100644
--- a/main/src/cgeo/geocaching/sorting/DifficultyComparator.java
+++ b/main/src/cgeo/geocaching/sorting/DifficultyComparator.java
@@ -9,8 +9,8 @@ import cgeo.geocaching.Geocache;
public class DifficultyComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(Geocache cache1, Geocache cache2) {
- return cache1.getDifficulty() != 0.0 && cache2.getDifficulty() != 0.0;
+ protected boolean canCompare(Geocache cache) {
+ return cache.getDifficulty() != 0.0;
}
@Override
diff --git a/main/src/cgeo/geocaching/sorting/DistanceComparator.java b/main/src/cgeo/geocaching/sorting/DistanceComparator.java
index 731e356..541ce48 100644
--- a/main/src/cgeo/geocaching/sorting/DistanceComparator.java
+++ b/main/src/cgeo/geocaching/sorting/DistanceComparator.java
@@ -36,11 +36,6 @@ public class DistanceComparator extends AbstractCacheComparator {
}
@Override
- protected boolean canCompare(Geocache cache1, Geocache cache2) {
- return true;
- }
-
- @Override
protected int compareCaches(final Geocache cache1, final Geocache cache2) {
calculateAllDistances();
final Float distance1 = cache1.getDistance();
diff --git a/main/src/cgeo/geocaching/sorting/FindsComparator.java b/main/src/cgeo/geocaching/sorting/FindsComparator.java
index c889776..7f2ef50 100644
--- a/main/src/cgeo/geocaching/sorting/FindsComparator.java
+++ b/main/src/cgeo/geocaching/sorting/FindsComparator.java
@@ -5,8 +5,8 @@ import cgeo.geocaching.Geocache;
public class FindsComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(Geocache cache1, Geocache cache2) {
- return cache1.getLogCounts() != null && cache2.getLogCounts() != null;
+ protected boolean canCompare(Geocache cache) {
+ return cache.getLogCounts() != null;
}
@Override
diff --git a/main/src/cgeo/geocaching/sorting/GeocodeComparator.java b/main/src/cgeo/geocaching/sorting/GeocodeComparator.java
index fff26c6..e700f13 100644
--- a/main/src/cgeo/geocaching/sorting/GeocodeComparator.java
+++ b/main/src/cgeo/geocaching/sorting/GeocodeComparator.java
@@ -2,23 +2,20 @@ package cgeo.geocaching.sorting;
import cgeo.geocaching.Geocache;
-import org.apache.commons.lang3.StringUtils;
-
/**
* sorts caches by geo code, therefore effectively sorting by cache age
- *
+ *
*/
public class GeocodeComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(Geocache cache1, Geocache cache2) {
- return StringUtils.isNotBlank(cache1.getGeocode())
- && StringUtils.isNotBlank(cache2.getGeocode());
+ protected boolean canCompare(final Geocache cache) {
+ // This will fall back to geocode comparisons.
+ return false;
}
@Override
protected int compareCaches(final Geocache cache1, final Geocache cache2) {
- final int lengthDiff = cache1.getGeocode().length() - cache2.getGeocode().length();
- return lengthDiff != 0 ? lengthDiff : cache1.getGeocode().compareToIgnoreCase(cache2.getGeocode());
+ throw new RuntimeException("should never be called");
}
}
diff --git a/main/src/cgeo/geocaching/sorting/InventoryComparator.java b/main/src/cgeo/geocaching/sorting/InventoryComparator.java
index 73ea2c5..9d19b64 100644
--- a/main/src/cgeo/geocaching/sorting/InventoryComparator.java
+++ b/main/src/cgeo/geocaching/sorting/InventoryComparator.java
@@ -8,11 +8,6 @@ import cgeo.geocaching.Geocache;
public class InventoryComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
- return true;
- }
-
- @Override
protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return cache2.getInventoryItems() - cache1.getInventoryItems();
}
diff --git a/main/src/cgeo/geocaching/sorting/NameComparator.java b/main/src/cgeo/geocaching/sorting/NameComparator.java
index b432ad0..2941b1c 100644
--- a/main/src/cgeo/geocaching/sorting/NameComparator.java
+++ b/main/src/cgeo/geocaching/sorting/NameComparator.java
@@ -11,8 +11,8 @@ import org.apache.commons.lang3.StringUtils;
public class NameComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(Geocache cache1, Geocache cache2) {
- return StringUtils.isNotBlank(cache1.getName()) && StringUtils.isNotBlank(cache2.getName());
+ protected boolean canCompare(Geocache cache) {
+ return StringUtils.isNotBlank(cache.getName());
}
@Override
diff --git a/main/src/cgeo/geocaching/sorting/PopularityComparator.java b/main/src/cgeo/geocaching/sorting/PopularityComparator.java
index e256654..2dbee68 100644
--- a/main/src/cgeo/geocaching/sorting/PopularityComparator.java
+++ b/main/src/cgeo/geocaching/sorting/PopularityComparator.java
@@ -9,11 +9,6 @@ import cgeo.geocaching.Geocache;
public class PopularityComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
- return true;
- }
-
- @Override
protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return cache2.getFavoritePoints() - cache1.getFavoritePoints();
}
diff --git a/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java b/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java
index f438762..1ed8e68 100644
--- a/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java
+++ b/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java
@@ -11,11 +11,6 @@ import cgeo.geocaching.Geocache;
public class PopularityRatioComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
- return true;
- }
-
- @Override
protected int compareCaches(final Geocache cache1, final Geocache cache2) {
float ratio1 = 0.0f;
diff --git a/main/src/cgeo/geocaching/sorting/RatingComparator.java b/main/src/cgeo/geocaching/sorting/RatingComparator.java
index 72cf6c8..6f2c615 100644
--- a/main/src/cgeo/geocaching/sorting/RatingComparator.java
+++ b/main/src/cgeo/geocaching/sorting/RatingComparator.java
@@ -9,11 +9,6 @@ import cgeo.geocaching.Geocache;
public class RatingComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
- return true;
- }
-
- @Override
protected int compareCaches(final Geocache cache1, final Geocache cache2) {
final float rating1 = cache1.getRating();
final float rating2 = cache2.getRating();
diff --git a/main/src/cgeo/geocaching/sorting/SizeComparator.java b/main/src/cgeo/geocaching/sorting/SizeComparator.java
index d128822..c8de586 100644
--- a/main/src/cgeo/geocaching/sorting/SizeComparator.java
+++ b/main/src/cgeo/geocaching/sorting/SizeComparator.java
@@ -9,8 +9,8 @@ import cgeo.geocaching.Geocache;
public class SizeComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(Geocache cache1, Geocache cache2) {
- return cache1.getSize() != null && cache2.getSize() != null;
+ protected boolean canCompare(Geocache cache) {
+ return cache.getSize() != null;
}
@Override
diff --git a/main/src/cgeo/geocaching/sorting/StateComparator.java b/main/src/cgeo/geocaching/sorting/StateComparator.java
index b99c3c0..9488bd9 100644
--- a/main/src/cgeo/geocaching/sorting/StateComparator.java
+++ b/main/src/cgeo/geocaching/sorting/StateComparator.java
@@ -9,11 +9,6 @@ import cgeo.geocaching.Geocache;
public class StateComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
- return true;
- }
-
- @Override
protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return getState(cache1) - getState(cache2);
}
diff --git a/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java b/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java
index 78ba742..b718d3b 100644
--- a/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java
+++ b/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java
@@ -5,11 +5,6 @@ import cgeo.geocaching.Geocache;
public class StorageTimeComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(Geocache cache1, Geocache cache2) {
- return true;
- }
-
- @Override
protected int compareCaches(Geocache cache1, Geocache cache2) {
if (cache1.getUpdated() < cache2.getUpdated()) {
return -1;
diff --git a/main/src/cgeo/geocaching/sorting/TerrainComparator.java b/main/src/cgeo/geocaching/sorting/TerrainComparator.java
index be1e9bb..9bbb5f7 100644
--- a/main/src/cgeo/geocaching/sorting/TerrainComparator.java
+++ b/main/src/cgeo/geocaching/sorting/TerrainComparator.java
@@ -9,8 +9,8 @@ import cgeo.geocaching.Geocache;
public class TerrainComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
- return cache1.getTerrain() != 0.0 && cache2.getTerrain() != 0.0;
+ protected boolean canCompare(final Geocache cache) {
+ return cache.getTerrain() != 0.0;
}
@Override
diff --git a/main/src/cgeo/geocaching/sorting/VisitComparator.java b/main/src/cgeo/geocaching/sorting/VisitComparator.java
index 27d3170..1589a4c 100644
--- a/main/src/cgeo/geocaching/sorting/VisitComparator.java
+++ b/main/src/cgeo/geocaching/sorting/VisitComparator.java
@@ -9,11 +9,6 @@ import cgeo.geocaching.Geocache;
public class VisitComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
- return true;
- }
-
- @Override
protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return Long.valueOf(cache2.getVisitedDate()).compareTo(cache1.getVisitedDate());
}
diff --git a/main/src/cgeo/geocaching/sorting/VoteComparator.java b/main/src/cgeo/geocaching/sorting/VoteComparator.java
index dc0304b..cd4ad7e 100644
--- a/main/src/cgeo/geocaching/sorting/VoteComparator.java
+++ b/main/src/cgeo/geocaching/sorting/VoteComparator.java
@@ -8,11 +8,6 @@ import cgeo.geocaching.Geocache;
public class VoteComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(Geocache cache1, Geocache cache2) {
- return true;
- }
-
- @Override
protected int compareCaches(Geocache cache1, Geocache cache2) {
// if there is no vote available, put that cache at the end of the list
return Float.compare(cache2.getMyVote(), cache1.getMyVote());
diff --git a/main/src/cgeo/geocaching/speech/SpeechService.java b/main/src/cgeo/geocaching/speech/SpeechService.java
index 2a72bbf..8c650c3 100644
--- a/main/src/cgeo/geocaching/speech/SpeechService.java
+++ b/main/src/cgeo/geocaching/speech/SpeechService.java
@@ -47,7 +47,7 @@ public class SpeechService extends Service implements OnInitListener {
GeoDirHandler geoHandler = new GeoDirHandler() {
@Override
- protected void updateDirection(float newDirection) {
+ public void updateDirection(float newDirection) {
if (CgeoApplication.getInstance().currentGeo().getSpeed() <= 5) {
direction = DirectionProvider.getDirectionNow(startingActivity, newDirection);
directionInitialized = true;
@@ -56,7 +56,7 @@ public class SpeechService extends Service implements OnInitListener {
}
@Override
- protected void updateGeoData(cgeo.geocaching.IGeoData newGeo) {
+ public void updateGeoData(cgeo.geocaching.IGeoData newGeo) {
position = newGeo.getCoords();
positionInitialized = true;
if (!Settings.isUseCompass() || newGeo.getSpeed() > 5) {
diff --git a/main/src/cgeo/geocaching/speech/TextFactory.java b/main/src/cgeo/geocaching/speech/TextFactory.java
index 2a3b6d7..eb780c6 100644
--- a/main/src/cgeo/geocaching/speech/TextFactory.java
+++ b/main/src/cgeo/geocaching/speech/TextFactory.java
@@ -2,9 +2,9 @@ package cgeo.geocaching.speech;
import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.IConversion;
+import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.AngleUtils;
import java.util.Locale;
diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java
index 7213789..1caa2d4 100644
--- a/main/src/cgeo/geocaching/twitter/Twitter.java
+++ b/main/src/cgeo/geocaching/twitter/Twitter.java
@@ -17,7 +17,6 @@ import cgeo.geocaching.utils.LogTemplateProvider;
import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
import ch.boye.httpclientandroidlib.HttpResponse;
-
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java
index ed5d182..0c67384 100644
--- a/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java
+++ b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java
@@ -3,7 +3,6 @@ package cgeo.geocaching.ui;
import cgeo.geocaching.activity.AbstractViewPagerActivity.PageViewCreator;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/main/src/cgeo/geocaching/ui/AnchorAwareLinkMovementMethod.java b/main/src/cgeo/geocaching/ui/AnchorAwareLinkMovementMethod.java
index db82e5c..d4c2e10 100644
--- a/main/src/cgeo/geocaching/ui/AnchorAwareLinkMovementMethod.java
+++ b/main/src/cgeo/geocaching/ui/AnchorAwareLinkMovementMethod.java
@@ -8,7 +8,7 @@ import android.widget.TextView;
/**
* <code>LinkMovementMethod</code> with built-in suppression of errors for links, where the URL cannot be handled
* correctly by Android.
- *
+ *
*/
public class AnchorAwareLinkMovementMethod extends LinkMovementMethod {
diff --git a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
index 7fe77c4..5d8ebef 100644
--- a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
+++ b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
@@ -39,6 +39,11 @@ public final class CacheDetailsCreator {
parentView.removeAllViews();
}
+ /**
+ * @param nameId
+ * @param value
+ * @return the view containing the displayed string (i.e. the right side one from the pair of "label": "value")
+ */
public TextView add(final int nameId, final CharSequence value) {
final RelativeLayout layout = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.cache_information_item, null);
final TextView nameView = (TextView) layout.findViewById(R.id.name);
@@ -188,14 +193,24 @@ public final class CacheDetailsCreator {
if (!cache.isEventCache()) {
return;
}
+ addHiddenDate(cache);
+ }
+
+ public TextView addHiddenDate(final @NonNull Geocache cache) {
final Date hiddenDate = cache.getHiddenDate();
if (hiddenDate == null) {
- return;
+ return null;
}
final long time = hiddenDate.getTime();
if (time > 0) {
- final String dateString = DateUtils.formatDateTime(CgeoApplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY) + ", " + Formatter.formatFullDate(time);
- add(R.string.cache_event, dateString);
+ String dateString = Formatter.formatFullDate(time);
+ if (cache.isEventCache()) {
+ dateString = DateUtils.formatDateTime(CgeoApplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY) + ", " + dateString;
+ }
+ final TextView view = add(cache.isEventCache() ? R.string.cache_event : R.string.cache_hidden, dateString);
+ view.setId(R.id.date);
+ return view;
}
+ return null;
}
}
diff --git a/main/src/cgeo/geocaching/ui/ImagesList.java b/main/src/cgeo/geocaching/ui/ImagesList.java
index 4eaf06d..f564583 100644
--- a/main/src/cgeo/geocaching/ui/ImagesList.java
+++ b/main/src/cgeo/geocaching/ui/ImagesList.java
@@ -9,6 +9,9 @@ import cgeo.geocaching.utils.Log;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
+import rx.android.concurrency.AndroidSchedulers;
+import rx.subscriptions.CompositeSubscription;
+import rx.util.functions.Action1;
import android.app.Activity;
import android.content.Intent;
@@ -18,7 +21,6 @@ import android.graphics.Bitmap.CompressFormat;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
-import android.os.AsyncTask;
import android.text.Html;
import android.util.SparseArray;
import android.view.ContextMenu;
@@ -41,11 +43,11 @@ public class ImagesList {
private BitmapDrawable currentDrawable;
private Image currentImage;
+ private CompositeSubscription subscriptions = new CompositeSubscription();
public enum ImageType {
LogImages(R.string.cache_log_images_title),
- SpoilerImages(R.string.cache_spoiler_images_title),
- AllImages(R.string.cache_images_title);
+ SpoilerImages(R.string.cache_spoiler_images_title);
private final int titleResId;
@@ -76,11 +78,13 @@ public class ImagesList {
}
public void loadImages(final View parentView, final List<Image> images, final boolean offline) {
-
imagesView = (LinearLayout) parentView.findViewById(R.id.spoiler_list);
+ final HtmlImage imgGetter = new HtmlImage(geocode, true, offline ? StoredList.STANDARD_LIST_ID : StoredList.TEMPORARY_LIST_ID, false);
+
for (final Image img : images) {
- LinearLayout rowView = (LinearLayout) inflater.inflate(R.layout.cache_image_item, null);
+ final LinearLayout rowView = (LinearLayout) inflater.inflate(R.layout.cache_image_item, null);
+ assert(rowView != null);
if (StringUtils.isNotBlank(img.getTitle())) {
((TextView) rowView.findViewById(R.id.title)).setText(Html.fromHtml(img.getTitle()));
@@ -93,66 +97,56 @@ public class ImagesList {
descView.setVisibility(View.VISIBLE);
}
- new AsyncImgLoader(rowView, img, offline).execute();
+ subscriptions.add(imgGetter.fetchDrawable(img.getUrl())
+ .observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<BitmapDrawable>() {
+ @Override
+ public void call(final BitmapDrawable image) {
+ display(image, img, rowView);
+ }
+ }));
+
imagesView.addView(rowView);
}
}
- private class AsyncImgLoader extends AsyncTask<Void, Void, BitmapDrawable> {
+ private void display(final BitmapDrawable image, final Image img, final LinearLayout view) {
+ if (image != null) {
+ bitmaps.add(image.getBitmap());
+ final ImageView imageView = (ImageView) inflater.inflate(R.layout.image_item, null);
+ assert(imageView != null);
- final private LinearLayout view;
- final private Image img;
- final boolean offline;
+ final Rect bounds = image.getBounds();
- public AsyncImgLoader(final LinearLayout view, final Image img, final boolean offline) {
- this.view = view;
- this.img = img;
- this.offline = offline;
- }
+ imageView.setImageResource(R.drawable.image_not_loaded);
+ imageView.setClickable(true);
+ imageView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ viewImageInStandardApp(image);
+ }
+ });
+ activity.registerForContextMenu(imageView);
+ imageView.setImageDrawable(image);
+ imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+ imageView.setLayoutParams(new LayoutParams(bounds.width(), bounds.height()));
- @Override
- protected BitmapDrawable doInBackground(Void... params) {
- final HtmlImage imgGetter = new HtmlImage(geocode, true, offline ? StoredList.STANDARD_LIST_ID : StoredList.TEMPORARY_LIST_ID, false);
- return imgGetter.getDrawable(img.getUrl());
- }
+ view.findViewById(R.id.progress_bar).setVisibility(View.GONE);
+ view.addView(imageView);
- @Override
- protected void onPostExecute(final BitmapDrawable image) {
- if (image != null) {
- bitmaps.add(image.getBitmap());
- final ImageView imageView = (ImageView) inflater.inflate(R.layout.image_item, null);
-
- final Rect bounds = image.getBounds();
-
- imageView.setImageResource(R.drawable.image_not_loaded);
- imageView.setClickable(true);
- imageView.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View arg0) {
- viewImageInStandardApp(image);
- }
- });
- activity.registerForContextMenu(imageView);
- imageView.setImageDrawable(image);
- imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
- imageView.setLayoutParams(new LayoutParams(bounds.width(), bounds.height()));
-
- view.findViewById(R.id.progress_bar).setVisibility(View.GONE);
- view.addView(imageView);
-
- imageView.setId(image.hashCode());
- images.put(imageView.getId(), img);
- }
+ imageView.setId(image.hashCode());
+ images.put(imageView.getId(), img);
}
}
public void removeAllViews() {
- imagesView.removeAllViews();
for (final Bitmap b : bitmaps) {
b.recycle();
}
bitmaps.clear();
+
+ // Stop loading images if some are still in progress
+ subscriptions.unsubscribe();
+ imagesView.removeAllViews();
}
public void onCreateContextMenu(ContextMenu menu, View v) {
diff --git a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
index 93f50e1..651ff6e 100644
--- a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
@@ -54,7 +54,7 @@ public class CoordinatesInputDialog extends NoTitleDialog {
} else if (geo != null && geo.getCoords() != null) {
this.gp = geo.getCoords();
} else {
- this.gp = new Geopoint(0.0, 0.0);
+ this.gp = Geopoint.ZERO;
}
}
@@ -396,7 +396,7 @@ public class CoordinatesInputDialog extends NoTitleDialog {
if (geo != null && geo.getCoords() != null) {
gp = geo.getCoords();
} else {
- gp = new Geopoint(0.0, 0.0);
+ gp = Geopoint.ZERO;
}
}
}
diff --git a/main/src/cgeo/geocaching/ui/dialog/Dialogs.java b/main/src/cgeo/geocaching/ui/dialog/Dialogs.java
index 865ba70..4f6de39 100644
--- a/main/src/cgeo/geocaching/ui/dialog/Dialogs.java
+++ b/main/src/cgeo/geocaching/ui/dialog/Dialogs.java
@@ -1,10 +1,10 @@
package cgeo.geocaching.ui.dialog;
import cgeo.geocaching.CgeoApplication;
-import cgeo.geocaching.utils.RunnableWithArgument;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.Nullable;
+import rx.util.functions.Action1;
import android.app.Activity;
import android.app.AlertDialog;
@@ -310,7 +310,7 @@ public final class Dialogs {
* @param okayListener
* listener to be run on okay
*/
- public static void input(final Activity context, final int title, final String defaultValue, final int buttonTitle, final RunnableWithArgument<String> okayListener) {
+ public static void input(final Activity context, final int title, final String defaultValue, final int buttonTitle, final Action1<String> okayListener) {
final EditText input = new EditText(context);
input.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_CLASS_TEXT);
input.setText(defaultValue);
@@ -322,7 +322,7 @@ public final class Dialogs {
@Override
public void onClick(DialogInterface dialog, int which) {
- okayListener.run(input.getText().toString());
+ okayListener.call(input.getText().toString());
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
diff --git a/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java b/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java
index 6ad59ec..702b85d 100644
--- a/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java
+++ b/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.ui.dialog;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.CgeoApplication;
import android.app.Activity;
import android.app.AlertDialog;
diff --git a/main/src/cgeo/geocaching/utils/CancellableHandler.java b/main/src/cgeo/geocaching/utils/CancellableHandler.java
index cb4b9db..01fb568 100644
--- a/main/src/cgeo/geocaching/utils/CancellableHandler.java
+++ b/main/src/cgeo/geocaching/utils/CancellableHandler.java
@@ -2,6 +2,9 @@ package cgeo.geocaching.utils;
import cgeo.geocaching.CgeoApplication;
+import rx.Subscription;
+import rx.subscriptions.CompositeSubscription;
+
import android.os.Handler;
import android.os.Message;
@@ -13,6 +16,7 @@ public abstract class CancellableHandler extends Handler {
protected static final int UPDATE_LOAD_PROGRESS_DETAIL = 42186;
private volatile boolean cancelled = false;
+ private static CompositeSubscription subscriptions = new CompositeSubscription();
private static class CancelHolder {
final Object payload;
@@ -30,6 +34,7 @@ public abstract class CancellableHandler extends Handler {
if (message.obj instanceof CancelHolder) {
cancelled = true;
+ subscriptions.unsubscribe();
handleCancel(((CancelHolder) message.obj).payload);
} else {
handleRegularMessage(message);
@@ -37,6 +42,17 @@ public abstract class CancellableHandler extends Handler {
}
/**
+ * Add a subscription to the list of subscriptions to be subscribed at cancellation time.
+ */
+ final public void unsubscribeIfCancelled(final Subscription subscription) {
+ subscriptions.add(subscription);
+ if (cancelled) {
+ // Protect against race conditions
+ subscriptions.unsubscribe();
+ }
+ }
+
+ /**
* Handle a non-cancel message.<br>
* Subclasses must implement this to handle messages.
*
diff --git a/main/src/cgeo/geocaching/utils/GeoDirHandler.java b/main/src/cgeo/geocaching/utils/GeoDirHandler.java
index c85648b..b9c605b 100644
--- a/main/src/cgeo/geocaching/utils/GeoDirHandler.java
+++ b/main/src/cgeo/geocaching/utils/GeoDirHandler.java
@@ -4,12 +4,15 @@ import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.settings.Settings;
-import android.os.Handler;
-import android.os.Message;
+import rx.Observable;
+import rx.Subscription;
+import rx.android.concurrency.AndroidSchedulers;
+import rx.util.functions.Action1;
+
+import java.util.concurrent.TimeUnit;
/**
- * GeoData and Direction handler. Manipulating geodata and direction information
- * through a GeoDirHandler ensures that all listeners are registered from a {@link android.os.Looper} thread.
+ * GeoData and Direction handler.
* <p>
* To use this class, override at least one of {@link #updateDirection(float)} or {@link #updateGeoData(IGeoData)}. You
* need to start the handler using one of
@@ -21,47 +24,11 @@ import android.os.Message;
* A good place might be the {@code onResume} method of the Activity. Stop the Handler accordingly in {@code onPause}.
* </p>
*/
-public abstract class GeoDirHandler extends Handler implements IObserver<Object> {
-
- private static final int OBSERVABLE = 1 << 1;
- private static final int START_GEO = 1 << 2;
- private static final int START_DIR = 1 << 3;
- private static final int STOP_GEO = 1 << 4;
- private static final int STOP_DIR = 1 << 5;
-
+public abstract class GeoDirHandler {
private static final CgeoApplication app = CgeoApplication.getInstance();
- @Override
- final public void handleMessage(final Message message) {
- if ((message.what & START_GEO) != 0) {
- app.addGeoObserver(this);
- }
-
- if ((message.what & START_DIR) != 0) {
- app.addDirectionObserver(this);
- }
-
- if ((message.what & STOP_GEO) != 0) {
- app.deleteGeoObserver(this);
- }
-
- if ((message.what & STOP_DIR) != 0) {
- app.deleteDirectionObserver(this);
- }
-
- if ((message.what & OBSERVABLE) != 0) {
- if (message.obj instanceof IGeoData) {
- updateGeoData((IGeoData) message.obj);
- } else {
- updateDirection((Float) message.obj);
- }
- }
- }
-
- @Override
- final public void update(final Object o) {
- obtainMessage(OBSERVABLE, o).sendToTarget();
- }
+ private Subscription dirSubscription = null;
+ private Subscription geoSubscription = null;
/**
* Update method called when new IGeoData is available.
@@ -69,7 +36,7 @@ public abstract class GeoDirHandler extends Handler implements IObserver<Object>
* @param data
* the new data
*/
- protected void updateGeoData(final IGeoData data) {
+ public void updateGeoData(final IGeoData data) {
// Override this in children
}
@@ -79,24 +46,38 @@ public abstract class GeoDirHandler extends Handler implements IObserver<Object>
* @param direction
* the new direction
*/
- protected void updateDirection(final float direction) {
+ public void updateDirection(final float direction) {
// Override this in children
}
/**
* Register the current GeoDirHandler for GeoData information.
*/
- public void startGeo() {
- sendEmptyMessage(START_GEO);
+ public synchronized void startGeo() {
+ geoSubscription = app.currentGeoObject()
+ .subscribeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Action1<IGeoData>() {
+ @Override
+ public void call(final IGeoData geoData) {
+ updateGeoData(geoData);
+ }
+ });
}
/**
* Register the current GeoDirHandler for direction information if the preferences
* allow it.
*/
- public void startDir() {
+ public synchronized void startDir() {
if (Settings.isUseCompass()) {
- sendEmptyMessage(START_DIR);
+ dirSubscription = app.currentDirObject()
+ .subscribeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Action1<Float>() {
+ @Override
+ public void call(final Float direction) {
+ updateDirection(direction);
+ }
+ });
}
}
@@ -105,27 +86,43 @@ public abstract class GeoDirHandler extends Handler implements IObserver<Object>
* preferences allow it).
*/
public void startGeoAndDir() {
- sendEmptyMessage(START_GEO | (Settings.isUseCompass() ? START_DIR : 0));
+ startGeo();
+ startDir();
}
/**
* Unregister the current GeoDirHandler for GeoData information.
*/
- public void stopGeo() {
- sendEmptyMessage(STOP_GEO);
+ public synchronized void stopGeo() {
+ // Delay the unsubscription by 2.5 seconds, so that another activity has
+ // the time to subscribe and the GPS receiver will not be turned down.
+ if (geoSubscription != null) {
+ final Subscription subscription = geoSubscription;
+ geoSubscription = null;
+ Observable.interval(2500, TimeUnit.MILLISECONDS).take(1).subscribe(new Action1<Long>() {
+ @Override
+ public void call(final Long aLong) {
+ subscription.unsubscribe();
+ }
+ });
+ }
}
/**
* Unregister the current GeoDirHandler for direction information.
*/
- public void stopDir() {
- sendEmptyMessage(STOP_DIR);
+ public synchronized void stopDir() {
+ if (dirSubscription != null) {
+ dirSubscription.unsubscribe();
+ dirSubscription = null;
+ }
}
/**
* Unregister the current GeoDirHandler for GeoData and direction information.
*/
public void stopGeoAndDir() {
- sendEmptyMessage(STOP_GEO | STOP_DIR);
+ stopGeo();
+ stopDir();
}
}
diff --git a/main/src/cgeo/geocaching/utils/IObserver.java b/main/src/cgeo/geocaching/utils/IObserver.java
deleted file mode 100644
index bfcc798..0000000
--- a/main/src/cgeo/geocaching/utils/IObserver.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package cgeo.geocaching.utils;
-
-/**
- * Observer interface.
- * <p/>
- * An observer will receive updates about the observed object (implementing the {@link ISubject} interface) through its
- * {@link #update(Object)} method.
- *
- * @param <T>
- * the kind of data to observe
- */
-public interface IObserver<T> {
-
- /**
- * Called when an observed object has updated its data.
- *
- * @param data
- * the updated data
- */
- void update(final T data);
-
-}
diff --git a/main/src/cgeo/geocaching/utils/ISubject.java b/main/src/cgeo/geocaching/utils/ISubject.java
deleted file mode 100644
index c325db0..0000000
--- a/main/src/cgeo/geocaching/utils/ISubject.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package cgeo.geocaching.utils;
-
-/**
- * Interface for subjects objects. Those can be observed by objects implementing the {@link IObserver} interface.
- *
- * @param <T>
- * the kind of data to observe
- */
-
-public interface ISubject<T> {
-
- /**
- * Add an observer to the observers list.
- * <p/>
- * Observers will be notified with no particular order.
- *
- * @param observer
- * the observer to add
- * @return true if the observer has been added, false if it was present already
- */
- public boolean addObserver(final IObserver<? super T> observer);
-
- /**
- * Delete an observer from the observers list.
- *
- * @param observer
- * the observer to remove
- * @return true if the observer has been removed, false if it was not in the list of observers
- */
- public boolean deleteObserver(final IObserver<? super T> observer);
-
- /**
- * Number of observers currently observing the object.
- *
- * @return the number of observers
- */
- public int sizeObservers();
-
- /**
- * Notify all the observers that new data is available.
- * <p/>
- * The {@link IObserver#update(Object)} method of each observer will be called with no particular order.
- *
- * @param data
- * the updated data
- * @return true if at least one observer was notified, false if there were no observers
- */
- public boolean notifyObservers(final T data);
-
- /**
- * Clear the observers list.
- *
- * @return true if there were observers before calling this method, false if the observers list was empty
- */
- public boolean clearObservers();
-
-}
diff --git a/main/src/cgeo/geocaching/utils/ImageUtils.java b/main/src/cgeo/geocaching/utils/ImageUtils.java
index 73f322c..9f47ead 100644
--- a/main/src/cgeo/geocaching/utils/ImageUtils.java
+++ b/main/src/cgeo/geocaching/utils/ImageUtils.java
@@ -78,7 +78,7 @@ public final class ImageUtils {
* @return BitmapDrawable The scaled image
*/
@NonNull
- public static BitmapDrawable scaleBitmapTo(@NonNull final Bitmap image, final int maxWidth, final int maxHeight) {
+ private static BitmapDrawable scaleBitmapTo(@NonNull final Bitmap image, final int maxWidth, final int maxHeight) {
final CgeoApplication app = CgeoApplication.getInstance();
Bitmap result = image;
int width = image.getWidth();
diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java
index 708dff0..259e94a 100644
--- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java
+++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java
@@ -1,5 +1,7 @@
package cgeo.geocaching.utils;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
@@ -42,6 +44,7 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E>
*
* @see HashSet
*/
+ @NonNull
@Override
public Iterator<E> iterator() {
return map.keySet().iterator();
diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
index 76fa0f7..5fa0982 100644
--- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
+++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
@@ -47,10 +47,6 @@ public final class LogTemplateProvider {
this.logEntry = logEntry;
}
- public LogContext(final boolean offline) {
- this(null, null, offline);
- }
-
public LogContext(final Geocache cache, LogEntry logEntry, final boolean offline) {
this.cache = cache;
this.offline = offline;
diff --git a/main/src/cgeo/geocaching/utils/MemorySubject.java b/main/src/cgeo/geocaching/utils/MemorySubject.java
deleted file mode 100644
index c424528..0000000
--- a/main/src/cgeo/geocaching/utils/MemorySubject.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package cgeo.geocaching.utils;
-
-/**
- * Synchronized implementation of the {@link ISubject} interface with an added pull interface.
- *
- * @param <T>
- * the kind of data to observe
- */
-public class MemorySubject<T> extends Subject<T> {
-
- /**
- * The latest version of the observed data.
- * <p/>
- * A child class implementation may want to set this field from its constructors, in case early observers request
- * the data before it got a chance to get updated. Otherwise, <code>null</code> will be returned until updated
- * data is available.
- */
- private T memory;
-
- @Override
- public synchronized boolean addObserver(final IObserver<? super T> observer) {
- final boolean added = super.addObserver(observer);
- if (added && memory != null) {
- observer.update(memory);
- }
- return added;
- }
-
- @Override
- public synchronized boolean notifyObservers(final T data) {
- memory = data;
- return super.notifyObservers(data);
- }
-
- /**
- * Get the memorized version of the data.
- *
- * @return the initial data set by the subject (which may be <code>null</code>),
- * or the updated data if it is available
- */
- public synchronized T getMemory() {
- return memory;
- }
-
-}
diff --git a/main/src/cgeo/geocaching/utils/RunnableWithArgument.java b/main/src/cgeo/geocaching/utils/RunnableWithArgument.java
deleted file mode 100644
index 6137efd..0000000
--- a/main/src/cgeo/geocaching/utils/RunnableWithArgument.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package cgeo.geocaching.utils;
-
-public interface RunnableWithArgument<T> {
-
- abstract void run(final T argument);
-
-}
diff --git a/main/src/cgeo/geocaching/utils/Subject.java b/main/src/cgeo/geocaching/utils/Subject.java
deleted file mode 100644
index b1754cc..0000000
--- a/main/src/cgeo/geocaching/utils/Subject.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package cgeo.geocaching.utils;
-
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-/**
- * Synchronized implementation of the {@link ISubject} interface.
- *
- * @param <T>
- * the kind of data to observe
- */
-public class Subject<T> implements ISubject<T> {
-
- /**
- * Collection of observers.
- */
- protected final Set<IObserver<? super T>> observers = new LinkedHashSet<IObserver<? super T>>();
-
- @Override
- public synchronized boolean addObserver(final IObserver<? super T> observer) {
- final boolean added = observers.add(observer);
- if (added && observers.size() == 1) {
- onFirstObserver();
- }
- return added;
- }
-
- @Override
- public synchronized boolean deleteObserver(final IObserver<? super T> observer) {
- final boolean removed = observers.remove(observer);
- if (removed && observers.isEmpty()) {
- onLastObserver();
- }
- return removed;
- }
-
- @Override
- public synchronized boolean notifyObservers(final T arg) {
- final boolean nonEmpty = !observers.isEmpty();
- for (final IObserver<? super T> observer : observers) {
- observer.update(arg);
- }
- return nonEmpty;
- }
-
- @Override
- public synchronized int sizeObservers() {
- return observers.size();
- }
-
- @Override
- public synchronized boolean clearObservers() {
- final boolean nonEmpty = !observers.isEmpty();
- for (final IObserver<? super T> observer : observers) {
- deleteObserver(observer);
- }
- return nonEmpty;
- }
-
- /**
- * Method called when the collection of observers goes from empty to non-empty.
- * <p/>
- * The default implementation does nothing and may be overwritten by child classes.
- */
- protected void onFirstObserver() {
- }
-
- /**
- * Method called when the collection of observers goes from non-empty to empty.
- * <p/>
- * The default implementation does nothing and may be overwritten by child classes.
- */
- protected void onLastObserver() {
- }
-
-}
diff --git a/main/src/cgeo/geocaching/utils/TextUtils.java b/main/src/cgeo/geocaching/utils/TextUtils.java
index efbb2d7..c4e1128 100644
--- a/main/src/cgeo/geocaching/utils/TextUtils.java
+++ b/main/src/cgeo/geocaching/utils/TextUtils.java
@@ -4,7 +4,6 @@
package cgeo.geocaching.utils;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
import org.eclipse.jdt.annotation.Nullable;
import java.util.regex.Matcher;
diff --git a/main/thirdparty/android/support/v4/app/FragmentListActivity.java b/main/thirdparty/android/support/v4/app/FragmentListActivity.java
index e3ed42c..fa425ab 100644
--- a/main/thirdparty/android/support/v4/app/FragmentListActivity.java
+++ b/main/thirdparty/android/support/v4/app/FragmentListActivity.java
@@ -16,6 +16,8 @@
package android.support.v4.app;
+import org.eclipse.jdt.annotation.NonNull;
+
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
@@ -215,7 +217,7 @@ public class FragmentListActivity extends FragmentActivity {
*@see Activity#onRestoreInstanceState(Bundle)
*/
@Override
- protected void onRestoreInstanceState(Bundle state) {
+ protected void onRestoreInstanceState(@NonNull Bundle state) {
ensureList();
super.onRestoreInstanceState(state);
}
diff --git a/main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java b/main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java
index 94ac962..0f922c5 100644
--- a/main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java
+++ b/main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java
@@ -19,6 +19,8 @@ package com.viewpagerindicator;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -445,7 +447,7 @@ public class TitlePageIndicator extends View implements PageIndicator {
}
@Override
- public boolean onTouchEvent(android.view.MotionEvent ev) {
+ public boolean onTouchEvent(@NonNull android.view.MotionEvent ev) {
if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) {
return false;
}
@@ -751,7 +753,7 @@ public class TitlePageIndicator extends View implements PageIndicator {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(currentPage);
}
diff --git a/tests/.settings/org.eclipse.jdt.core.prefs b/tests/.settings/org.eclipse.jdt.core.prefs
index 5385520..6ba1bbd 100644
--- a/tests/.settings/org.eclipse.jdt.core.prefs
+++ b/tests/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,10 @@
eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
-org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
@@ -11,7 +12,7 @@ org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=ignore
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
@@ -20,13 +21,13 @@ org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
@@ -47,37 +48,39 @@ org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warni
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
-org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=error
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=error
org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=warning
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
@@ -90,6 +93,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.6
diff --git a/tests/libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar b/tests/libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar
new file mode 100644
index 0000000..daca164
--- /dev/null
+++ b/tests/libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar
Binary files differ
diff --git a/tests/src/cgeo/geocaching/CgeoApplicationTest.java b/tests/src/cgeo/geocaching/CgeoApplicationTest.java
index 183b246..cd80889 100644
--- a/tests/src/cgeo/geocaching/CgeoApplicationTest.java
+++ b/tests/src/cgeo/geocaching/CgeoApplicationTest.java
@@ -26,7 +26,6 @@ import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
import cgeo.test.Compare;
-import junit.framework.Assert;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
@@ -35,6 +34,8 @@ import android.test.suitebuilder.annotation.SmallTest;
import java.util.GregorianCalendar;
+import junit.framework.Assert;
+
/**
* The c:geo application test. It can be used for tests that require an
* application and/or context.
@@ -72,6 +73,7 @@ public class CgeoApplicationTest extends CGeoTestCase {
public static void testSearchTrackable() {
final Trackable tb = GCParser.searchTrackable("TB2J1VZ", null, null);
assertNotNull(tb);
+ assert (tb != null); // eclipse bug
// fix data
assertEquals("aefffb86-099f-444f-b132-605436163aa8", tb.getGuid());
assertEquals("TB2J1VZ", tb.getGeocode());
@@ -112,7 +114,7 @@ public class CgeoApplicationTest extends CGeoTestCase {
public static Geocache testSearchByGeocode(final String geocode) {
final SearchResult search = Geocache.searchByGeocode(geocode, null, 0, true, null);
assertNotNull(search);
- if (Settings.isPremiumMember() || search.getError() == null) {
+ if (Settings.isGCPremiumMember() || search.getError() == null) {
assertEquals(1, search.getGeocodes().size());
assertTrue(search.getGeocodes().contains(geocode));
return DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
@@ -138,14 +140,14 @@ public class CgeoApplicationTest extends CGeoTestCase {
*/
private static void withMockedLoginDo(final Runnable runnable) {
final ImmutablePair<String, String> login = Settings.getGcCredentials();
- final String memberStatus = Settings.getMemberStatus();
+ final String memberStatus = Settings.getGCMemberStatus();
try {
runnable.run();
} finally {
// restore user and password
TestSettings.setLogin(login.left, login.right);
- Settings.setMemberStatus(memberStatus);
+ Settings.setGCMemberStatus(memberStatus);
GCLogin.getInstance().login();
}
}
@@ -169,6 +171,8 @@ public class CgeoApplicationTest extends CGeoTestCase {
assertTrue(search.getGeocodes().contains(cache.getGeocode()));
final Geocache searchedCache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
// coords must be null if the user is not logged in
+ assertNotNull(searchedCache);
+ assert (searchedCache != null); // eclipse bug
assertNull(searchedCache.getCoords());
// premium cache. Not visible to guests
@@ -303,25 +307,25 @@ public class CgeoApplicationTest extends CGeoTestCase {
// check coords for DETAILED
Settings.setLiveMapStrategy(Strategy.DETAILED);
- SearchResult search = ConnectorFactory.searchByViewport(viewport, tokens);
+ SearchResult search = ConnectorFactory.searchByViewport(viewport, tokens).toBlockingObservable().single();
assertNotNull(search);
assertTrue(search.getGeocodes().contains(mockedCache.getGeocode()));
Geocache parsedCache = DataStore.loadCache(mockedCache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB);
- assertEquals(Settings.isPremiumMember(), mockedCache.getCoords().equals(parsedCache.getCoords()));
- assertEquals(Settings.isPremiumMember(), parsedCache.isReliableLatLon());
+ assertEquals(Settings.isGCPremiumMember(), mockedCache.getCoords().equals(parsedCache.getCoords()));
+ assertEquals(Settings.isGCPremiumMember(), parsedCache.isReliableLatLon());
// check update after switch strategy to FAST
Settings.setLiveMapStrategy(Strategy.FAST);
Tile.Cache.removeFromTileCache(mockedCache);
- search = ConnectorFactory.searchByViewport(viewport, tokens);
+ search = ConnectorFactory.searchByViewport(viewport, tokens).toBlockingObservable().single();
assertNotNull(search);
assertTrue(search.getGeocodes().contains(mockedCache.getGeocode()));
parsedCache = DataStore.loadCache(mockedCache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB);
- assertEquals(Settings.isPremiumMember(), mockedCache.getCoords().equals(parsedCache.getCoords()));
- assertEquals(Settings.isPremiumMember(), parsedCache.isReliableLatLon());
+ assertEquals(Settings.isGCPremiumMember(), mockedCache.getCoords().equals(parsedCache.getCoords()));
+ assertEquals(Settings.isGCPremiumMember(), parsedCache.isReliableLatLon());
} finally {
// restore user settings
@@ -354,7 +358,7 @@ public class CgeoApplicationTest extends CGeoTestCase {
Settings.setCacheType(CacheType.ALL);
Viewport viewport = new Viewport(cache, 0.003, 0.003);
- SearchResult search = ConnectorFactory.searchByViewport(viewport, INVALID_TOKEN);
+ SearchResult search = ConnectorFactory.searchByViewport(viewport, INVALID_TOKEN).toBlockingObservable().single();
assertNotNull(search);
assertTrue(search.getGeocodes().contains(cache.getGeocode()));
@@ -362,7 +366,7 @@ public class CgeoApplicationTest extends CGeoTestCase {
final Geocache cacheFromViewport = DataStore.loadCache(cache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB);
Log.d("cgeoApplicationTest.testSearchByViewportNotLoggedIn: Coords expected = " + cache.getCoords());
Log.d("cgeoApplicationTest.testSearchByViewportNotLoggedIn: Coords actual = " + cacheFromViewport.getCoords());
- assertFalse(cache.getCoords().isEqualTo(cacheFromViewport.getCoords(), 1e-3));
+ assertFalse(cache.getCoords().distanceTo(cacheFromViewport.getCoords()) <= 1e-3);
// depending on the chosen strategy the coords can be reliable or not
assertEquals(testStrategy == Strategy.DETAILED, cacheFromViewport.isReliableLatLon());
@@ -371,7 +375,7 @@ public class CgeoApplicationTest extends CGeoTestCase {
deleteCacheFromDBAndLogout(cache.getGeocode());
viewport = new Viewport(cache, 0.003, 0.003);
- search = ConnectorFactory.searchByViewport(viewport, INVALID_TOKEN);
+ search = ConnectorFactory.searchByViewport(viewport, INVALID_TOKEN).toBlockingObservable().single();
assertNotNull(search);
// depending on the chosen strategy the cache is part of the search or not
@@ -421,7 +425,7 @@ public class CgeoApplicationTest extends CGeoTestCase {
GCLogin.getInstance().logout();
// Modify login data to avoid an automatic login again
TestSettings.setLogin("c:geo", "c:geo");
- Settings.setMemberStatus("Basic member");
+ Settings.setGCMemberStatus("Basic member");
}
}
diff --git a/tests/src/cgeo/geocaching/SettingsTest.java b/tests/src/cgeo/geocaching/SettingsTest.java
index c58db08..90a0209 100644
--- a/tests/src/cgeo/geocaching/SettingsTest.java
+++ b/tests/src/cgeo/geocaching/SettingsTest.java
@@ -27,7 +27,7 @@ public class SettingsTest extends ActivityInstrumentationTestCase2<MainActivity>
public static void testSettings() {
// unfortunately, several other tests depend on being a premium member and will fail if run by a basic member
- assertEquals(GCConstants.MEMBER_STATUS_PM, Settings.getMemberStatus());
+ assertEquals(GCConstants.MEMBER_STATUS_PM, Settings.getGCMemberStatus());
}
public static void testDeviceHasNormalLogin() {
diff --git a/tests/src/cgeo/geocaching/connector/ConnectorFactoryTest.java b/tests/src/cgeo/geocaching/connector/ConnectorFactoryTest.java
index e41e316..725f718 100644
--- a/tests/src/cgeo/geocaching/connector/ConnectorFactoryTest.java
+++ b/tests/src/cgeo/geocaching/connector/ConnectorFactoryTest.java
@@ -63,8 +63,32 @@ public class ConnectorFactoryTest extends AbstractResourceInstrumentationTestCas
public static void testGetGeocodeFromUrl() {
assertEquals("GC34PLO", ConnectorFactory.getGeocodeFromURL("http://coord.info/GC34PLO"));
+ assertEquals("GC34PLO", ConnectorFactory.getGeocodeFromURL("http://www.coord.info/GC34PLO"));
assertEquals("OX1234", ConnectorFactory.getGeocodeFromURL("http://www.opencaching.com/#!geocache/OX1234"));
+
+ assertEquals("GC12ABC", GCConnector.getInstance().getGeocodeFromUrl("http://coord.info/GC12ABC"));
+ assertEquals("GC12ABC", GCConnector.getInstance().getGeocodeFromUrl("http://www.coord.info/GC12ABC"));
+ assertEquals("GC12ABC", GCConnector.getInstance().getGeocodeFromUrl("http://www.geocaching.com/geocache/GC12ABC_die-muhlen-im-schondratal-muhle-munchau"));
+ assertEquals("GC12ABC", GCConnector.getInstance().getGeocodeFromUrl("http://geocaching.com/geocache/GC12ABC_die-muhlen-im-schondratal-muhle-munchau"));
+
+ // trackable URLs
+ assertNull(GCConnector.getInstance().getGeocodeFromUrl("http://coord.info/TB1234"));
+ assertNull(GCConnector.getInstance().getGeocodeFromUrl("http://www.coord.info/TB1234"));
+
// make sure that a mixture of different connector and geocode is recognized as invalid
assertNull(ConnectorFactory.getGeocodeFromURL("http://www.opencaching.com/#!geocache/" + "GC12345"));
}
+
+ public static void testGetTrackableFromURL() throws Exception {
+ assertEquals("GK78FA", ConnectorFactory.getTrackableFromURL("http://www.geokrety.org/konkret.php?id=30970"));
+ assertEquals("GK78FA", ConnectorFactory.getTrackableFromURL("http://geokrety.org/konkret.php?id=30970"));
+ assertEquals("TB1234", ConnectorFactory.getTrackableFromURL("http://coord.info/TB1234"));
+ assertEquals("TB1234", ConnectorFactory.getTrackableFromURL("http://www.coord.info/TB1234"));
+ assertEquals("TB1234", ConnectorFactory.getTrackableFromURL("http://geocaching.com/track/details.aspx?tracker=TB1234"));
+ assertEquals("TB1234", ConnectorFactory.getTrackableFromURL("http://www.geocaching.com/track/details.aspx?tracker=TB1234"));
+
+ // cache URLs
+ assertNull(ConnectorFactory.getTrackableFromURL("http://coord.info/GC1234"));
+ assertNull(ConnectorFactory.getTrackableFromURL("http://www.coord.info/GC1234"));
+ }
}
diff --git a/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java b/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java
index a5b9a44..47c3f6f 100644
--- a/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java
+++ b/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java
@@ -26,7 +26,7 @@ public class GCConnectorTest extends AbstractResourceInstrumentationTestCase {
{
final Viewport viewport = new Viewport(new Geopoint("N 52° 25.369 E 9° 35.499"), new Geopoint("N 52° 25.600 E 9° 36.200"));
- final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport, tokens);
+ final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport, tokens).toBlockingObservable().single();
assertNotNull(searchResult);
assertFalse(searchResult.isEmpty());
assertTrue(searchResult.getGeocodes().contains("GC4ER5H"));
@@ -35,7 +35,7 @@ public class GCConnectorTest extends AbstractResourceInstrumentationTestCase {
{
final Viewport viewport = new Viewport(new Geopoint("N 52° 24.000 E 9° 34.500"), new Geopoint("N 52° 26.000 E 9° 38.500"));
- final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport, tokens);
+ final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport, tokens).toBlockingObservable().single();
assertNotNull(searchResult);
assertTrue(searchResult.getGeocodes().contains("GC4ER5H"));
}
@@ -88,5 +88,11 @@ public class GCConnectorTest extends AbstractResourceInstrumentationTestCase {
public static void testGetGeocodeFromUrl() {
assertNull(GCConnector.getInstance().getGeocodeFromUrl("some string"));
assertEquals("GC12ABC", GCConnector.getInstance().getGeocodeFromUrl("http://coord.info/GC12ABC"));
+ assertEquals("GC12ABC", GCConnector.getInstance().getGeocodeFromUrl("http://www.coord.info/GC12ABC"));
+ assertEquals("GC12ABC", GCConnector.getInstance().getGeocodeFromUrl("http://www.geocaching.com/geocache/GC12ABC_die-muhlen-im-schondratal-muhle-munchau"));
+ assertEquals("GC12ABC", GCConnector.getInstance().getGeocodeFromUrl("http://geocaching.com/geocache/GC12ABC_die-muhlen-im-schondratal-muhle-munchau"));
+
+ assertNull(GCConnector.getInstance().getGeocodeFromUrl("http://coord.info/TB1234"));
+ assertNull(GCConnector.getInstance().getGeocodeFromUrl("http://www.coord.info/TB1234"));
}
}
diff --git a/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java b/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java
index 43b6d01..1509563 100644
--- a/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java
+++ b/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java
@@ -56,6 +56,8 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase {
assertNotNull(result);
assertEquals(1, result.getCount());
final Geocache cache = result.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
+ assertNotNull(cache);
+ assert (cache != null); // eclipse bug
assertEquals(cacheName, cache.getName());
}
@@ -158,6 +160,8 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase {
cache.drop(new Handler());
final String page = GCParser.requestHtmlPage(cache.getGeocode(), null, "n", "0");
final Geocache cache2 = GCParser.parseCacheFromText(page, null).getFirstCacheFromResult(LoadFlags.LOAD_CACHE_ONLY);
+ assertNotNull(cache2);
+ assert (cache2 != null); // eclipse bug
assertTrue(cache2.hasUserModifiedCoords());
assertEquals(new Geopoint("N51 21.544", "E07 02.566"), cache2.getCoords());
// delete coordinates
@@ -165,6 +169,8 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase {
cache2.drop(new Handler());
final String page2 = GCParser.requestHtmlPage(cache.getGeocode(), null, "n", "0");
final Geocache cache3 = GCParser.parseCacheFromText(page2, null).getFirstCacheFromResult(LoadFlags.LOAD_CACHE_ONLY);
+ assertNotNull(cache3);
+ assert (cache3 != null); // eclipse bug
assertFalse(cache3.hasUserModifiedCoords());
}
@@ -172,9 +178,10 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase {
cache.setPersonalNote(note);
cache.setWaypoints(new ArrayList<Waypoint>(), false);
cache.parseWaypointsFromNote();
- assertEquals(expected.length, cache.getWaypoints().size());
+ final List<Waypoint> waypoints = cache.getWaypoints();
+ assertEquals(expected.length, waypoints.size());
for (int i = 0; i < expected.length; i++) {
- assertTrue(expected[i].equals(cache.getWaypoint(i).getCoords()));
+ assertTrue(expected[i].equals(waypoints.get(i).getCoords()));
}
}
diff --git a/tests/src/cgeo/geocaching/connector/trackable/GeokretyConnectorTest.java b/tests/src/cgeo/geocaching/connector/trackable/GeokretyConnectorTest.java
index f08fb6b..d3633cb 100644
--- a/tests/src/cgeo/geocaching/connector/trackable/GeokretyConnectorTest.java
+++ b/tests/src/cgeo/geocaching/connector/trackable/GeokretyConnectorTest.java
@@ -11,4 +11,17 @@ public class GeokretyConnectorTest extends TestCase {
assertFalse(new GeokretyConnector().canHandleTrackable("UNKNOWN"));
}
+ public static void testGetTrackableCodeFromUrl() throws Exception {
+ assertEquals("GK78FA", new GeokretyConnector().getTrackableCodeFromUrl("http://www.geokrety.org/konkret.php?id=30970"));
+ assertEquals("GK78FA", new GeokretyConnector().getTrackableCodeFromUrl("http://geokrety.org/konkret.php?id=30970"));
+ }
+
+ public static void testGeocode() throws Exception {
+ assertEquals("GK97C1", GeokretyConnector.geocode(38849));
+ }
+
+ public static void testGetId() throws Exception {
+ assertEquals(38849, GeokretyConnector.getId("GK97C1"));
+ }
+
}
diff --git a/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java b/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java
index ef2821d..7e85b71 100644
--- a/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java
+++ b/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java
@@ -38,4 +38,15 @@ public class TravelBugConnectorTest extends TestCase {
private static TravelBugConnector getConnector() {
return TravelBugConnector.getInstance();
}
+
+ public static void testGetTrackableCodeFromUrl() throws Exception {
+ assertEquals("TB1234", TravelBugConnector.getInstance().getTrackableCodeFromUrl("http://coord.info/TB1234"));
+ assertEquals("TB1234", TravelBugConnector.getInstance().getTrackableCodeFromUrl("http://www.coord.info/TB1234"));
+ assertEquals("TB1234", TravelBugConnector.getInstance().getTrackableCodeFromUrl("http://geocaching.com/track/details.aspx?tracker=TB1234"));
+ assertEquals("TB1234", TravelBugConnector.getInstance().getTrackableCodeFromUrl("http://www.geocaching.com/track/details.aspx?tracker=TB1234"));
+
+ // do not match coord.info URLs of caches
+ assertNull(TravelBugConnector.getInstance().getTrackableCodeFromUrl("http://coord.info/GC1234"));
+ assertNull(TravelBugConnector.getInstance().getTrackableCodeFromUrl("http://www.coord.info/GC1234"));
+ }
}
diff --git a/tests/src/cgeo/geocaching/enumerations/CacheAttributeTest.java b/tests/src/cgeo/geocaching/enumerations/CacheAttributeTest.java
index 54db279..d126c0b 100644
--- a/tests/src/cgeo/geocaching/enumerations/CacheAttributeTest.java
+++ b/tests/src/cgeo/geocaching/enumerations/CacheAttributeTest.java
@@ -25,7 +25,7 @@ public class CacheAttributeTest extends AndroidTestCase {
public static void testGetL10n() {
final CacheAttribute attribute = CacheAttribute.HIKING;
- // This test is language dependend. It does not make sense to test it
+ // This test is language dependent. It does not make sense to test it
// with every attribute. We just want to know if getL10n works
// correctly
assertFalse("_yes and _no must not have the same translation",
@@ -37,7 +37,6 @@ public class CacheAttributeTest extends AndroidTestCase {
assertTrue("Test cannot be run with this attribute", attribute.gcid >= 0);
assertTrue("Test cannot be run with this attribute", attribute.ocacode >= 0);
assertSame(CacheAttribute.getByRawName(attribute.rawName), attribute);
- assertSame(CacheAttribute.getByGcId(attribute.gcid), attribute);
assertSame(CacheAttribute.getByOcACode(attribute.ocacode), attribute);
}
diff --git a/tests/src/cgeo/geocaching/enumerations/CacheSizeTest.java b/tests/src/cgeo/geocaching/enumerations/CacheSizeTest.java
index 2f11dfc..26a1953 100644
--- a/tests/src/cgeo/geocaching/enumerations/CacheSizeTest.java
+++ b/tests/src/cgeo/geocaching/enumerations/CacheSizeTest.java
@@ -30,8 +30,6 @@ public class CacheSizeTest extends AndroidTestCase {
public static void testGetByIdNumeric() {
assertEquals(CacheSize.REGULAR, CacheSize.getById("3"));
- assertEquals(CacheSize.UNKNOWN, CacheSize.getById("0"));
- assertEquals(CacheSize.UNKNOWN, CacheSize.getById("9"));
assertEquals(CacheSize.UNKNOWN, CacheSize.getById("-1"));
}
}
diff --git a/tests/src/cgeo/geocaching/enumerations/LogTypeTrackableTest.java b/tests/src/cgeo/geocaching/enumerations/LogTypeTrackableTest.java
index 667eefb..d6b7d33 100644
--- a/tests/src/cgeo/geocaching/enumerations/LogTypeTrackableTest.java
+++ b/tests/src/cgeo/geocaching/enumerations/LogTypeTrackableTest.java
@@ -1,11 +1,15 @@
package cgeo.geocaching.enumerations;
+import org.apache.commons.lang3.StringUtils;
+
import android.test.AndroidTestCase;
public class LogTypeTrackableTest extends AndroidTestCase {
public static void testFindById() {
- assertEquals(LogTypeTrackable.DO_NOTHING, LogTypeTrackable.findById(12345));
+ for (LogTypeTrackable logTypeTrackable : LogTypeTrackable.values()) {
+ assertTrue(StringUtils.isNotEmpty(logTypeTrackable.getLabel()));
+ }
}
}
diff --git a/tests/src/cgeo/geocaching/geopoint/GeoPointParserTest.java b/tests/src/cgeo/geocaching/geopoint/GeoPointParserTest.java
index 1de2e26..28dbe77 100644
--- a/tests/src/cgeo/geocaching/geopoint/GeoPointParserTest.java
+++ b/tests/src/cgeo/geocaching/geopoint/GeoPointParserTest.java
@@ -19,7 +19,13 @@ public class GeoPointParserTest extends AndroidTestCase {
public static void testFullCoordinates() {
final Geopoint goal = new Geopoint(refLatitude, refLongitude);
- assertTrue(goal.isEqualTo(GeopointParser.parse("N 49° 56.031 | E 8° 38.564"), 1e-6));
+ assertEquals(goal, GeopointParser.parse("N 49° 56.031 | E 8° 38.564"), 1e-6);
+ }
+
+ private static void assertEquals(final Geopoint expected, Geopoint actual, double tolerance) {
+ assertNotNull(expected);
+ assertNotNull(actual);
+ assertTrue(expected.distanceTo(actual) <= tolerance);
}
public static void testCoordinateMissingPart() {
@@ -48,18 +54,18 @@ public class GeoPointParserTest extends AndroidTestCase {
public static void testVariousFormats() {
final Geopoint goal1 = GeopointParser.parse("N 49° 43' 57\" | E 2 12' 35");
final Geopoint goal2 = GeopointParser.parse("N 49 43.95 E2°12.5833333333");
- assertTrue(goal1.isEqualTo(goal2, 1e-6));
+ assertEquals(goal1, goal2, 1e-6);
}
public static void testParseOurOwnSeparator() {
final Geopoint separator = GeopointParser.parse("N 49° 43' 57\"" + Formatter.SEPARATOR + "E 2 12' 35");
final Geopoint noSeparator = GeopointParser.parse("N 49 43.95 E2°12.5833333333");
- assertTrue(separator.isEqualTo(noSeparator, 1e-6));
+ assertEquals(separator, noSeparator, 1e-6);
}
public static void testInSentence() {
final Geopoint p1 = GeopointParser.parse("Station3: N51 21.523 / E07 02.680");
- final Geopoint p2 = GeopointParser.parse("N51 21.523", "E07 02.680");
+ final Geopoint p2 = GeopointParser.parse("N51 21.523 E07 02.680");
assertNotNull(p1);
assertNotNull(p2);
assertEquals(p1, p2);
@@ -106,6 +112,6 @@ public class GeoPointParserTest extends AndroidTestCase {
}
public static void testEquatorMeridian() {
- assertEquals(new Geopoint(0, 0), GeopointParser.parse("00° 00.000 00° 00.000"));
+ assertEquals(Geopoint.ZERO, GeopointParser.parse("00° 00.000 00° 00.000"));
}
}
diff --git a/tests/src/cgeo/geocaching/geopoint/ViewportTest.java b/tests/src/cgeo/geocaching/geopoint/ViewportTest.java
index 60766b4..11f78ad 100644
--- a/tests/src/cgeo/geocaching/geopoint/ViewportTest.java
+++ b/tests/src/cgeo/geocaching/geopoint/ViewportTest.java
@@ -2,6 +2,8 @@ package cgeo.geocaching.geopoint;
import cgeo.geocaching.ICoordinates;
+import org.eclipse.jdt.annotation.NonNull;
+
import android.test.AndroidTestCase;
import java.util.Collections;
@@ -11,7 +13,8 @@ import java.util.Set;
public class ViewportTest extends AndroidTestCase {
- final private static Viewport vpRef = new Viewport(new Geopoint(-1.0, -2.0), new Geopoint(3.0, 4.0));
+ final private static @NonNull
+ Viewport vpRef = new Viewport(new Geopoint(-1.0, -2.0), new Geopoint(3.0, 4.0));
public static void assertBounds(final Viewport vp) {
assertEquals(new Geopoint(1.0, 1.0), vp.center);
@@ -49,7 +52,7 @@ public class ViewportTest extends AndroidTestCase {
public static void testInViewport() {
assertFalse(vpRef.contains(new Geopoint(-2.0, -2.0)));
assertFalse(vpRef.contains(new Geopoint(4.0, 4.0)));
- assertTrue(vpRef.contains(new Geopoint(0.0, 0.0)));
+ assertTrue(vpRef.contains(Geopoint.ZERO));
assertTrue(vpRef.contains(new Geopoint(-1.0, -2.0)));
assertTrue(vpRef.contains(new Geopoint(3.0, 4.0)));
}
@@ -86,16 +89,6 @@ public class ViewportTest extends AndroidTestCase {
assertFalse(vpRef.includes(vpRef.resize(2.0)));
}
- public static void testExpands() {
- assertEquals(vpRef, vpRef.expand(new Geopoint(0, 0)));
- final Viewport vp1 = vpRef.expand(new Geopoint(-4.0, 0.0));
- assertEquals(new Geopoint(-4.0, -2.0), vp1.bottomLeft);
- assertEquals(new Geopoint(3.0, 4.0), vp1.topRight);
- final Viewport vp2 = vpRef.expand(new Geopoint(-10.0, 10.0));
- assertEquals(new Geopoint(-10.0, -2.0), vp2.bottomLeft);
- assertEquals(new Geopoint(3.0, 10.0), vp2.topRight);
- }
-
public static void testContaining() {
assertNull(Viewport.containing(Collections.singleton((ICoordinates) null)));
final Set<Geopoint> points = new HashSet<Geopoint>();
diff --git a/tests/src/cgeo/geocaching/network/OAuthTest.java b/tests/src/cgeo/geocaching/network/OAuthTest.java
index fa0104f..6888cec 100644
--- a/tests/src/cgeo/geocaching/network/OAuthTest.java
+++ b/tests/src/cgeo/geocaching/network/OAuthTest.java
@@ -1,5 +1,7 @@
package cgeo.geocaching.network;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.ArrayList;
import java.util.List;
@@ -26,7 +28,8 @@ public class OAuthTest extends TestCase {
public static void testUnreservedCharactersMustNotBeEncoded() {
for (Character c : UNRESERVED) {
- final String charAsString = String.valueOf(c);
+ final @NonNull
+ String charAsString = String.valueOf(c);
assertEquals("wrong OAuth encoding for " + c, charAsString, OAuth.percentEncode(charAsString));
}
}
@@ -35,7 +38,8 @@ public class OAuthTest extends TestCase {
for (int i = 32; i < 127; i++) {
final Character c = (char) i;
if (!UNRESERVED.contains(c)) {
- final String charAsString = String.valueOf(c);
+ final @NonNull
+ String charAsString = String.valueOf(c);
final String encoded = OAuth.percentEncode(charAsString);
assertFalse("Character '" + charAsString + "' not encoded", charAsString.equals(encoded));
assertTrue(encoded.startsWith("%"));
diff --git a/tests/src/cgeo/geocaching/sorting/DistanceComparatorTest.java b/tests/src/cgeo/geocaching/sorting/DistanceComparatorTest.java
index 2db3f59..0cfee49 100644
--- a/tests/src/cgeo/geocaching/sorting/DistanceComparatorTest.java
+++ b/tests/src/cgeo/geocaching/sorting/DistanceComparatorTest.java
@@ -20,7 +20,7 @@ public class DistanceComparatorTest extends AndroidTestCase {
}
caches.add(cache);
}
- Collections.sort(caches, new DistanceComparator(new Geopoint(0, 0), caches));
+ Collections.sort(caches, new DistanceComparator(Geopoint.ZERO, caches));
}
}
diff --git a/tests/src/cgeo/geocaching/utils/LogTemplateProviderTest.java b/tests/src/cgeo/geocaching/utils/LogTemplateProviderTest.java
index 5911218..249cbb1 100644
--- a/tests/src/cgeo/geocaching/utils/LogTemplateProviderTest.java
+++ b/tests/src/cgeo/geocaching/utils/LogTemplateProviderTest.java
@@ -10,11 +10,11 @@ public class LogTemplateProviderTest extends TestCase {
public static void testApplyTemplates() {
final String noTemplates = " no templates ";
- assertEquals(noTemplates, LogTemplateProvider.applyTemplates(noTemplates, new LogContext(true)));
+ assertEquals(noTemplates, LogTemplateProvider.applyTemplates(noTemplates, new LogContext(null, null, true)));
// This test can occasionally fail if the current year changes right after the next line.
final String currentYear = Integer.toString(Calendar.YEAR);
- assertTrue(LogTemplateProvider.applyTemplates("[DATE]", new LogContext(true)).contains(currentYear));
+ assertTrue(LogTemplateProvider.applyTemplates("[DATE]", new LogContext(null, null, true)).contains(currentYear));
}
}
diff --git a/tests/src/cgeo/geocaching/utils/MemorySubjectTest.java b/tests/src/cgeo/geocaching/utils/MemorySubjectTest.java
deleted file mode 100644
index ee46950..0000000
--- a/tests/src/cgeo/geocaching/utils/MemorySubjectTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package cgeo.geocaching.utils;
-
-import android.test.AndroidTestCase;
-
-public class MemorySubjectTest extends AndroidTestCase {
-
- private static class Observer implements IObserver<Integer> {
- private int times = 0;
- private Integer value;
-
- @Override
- public void update(final Integer data) {
- value = data;
- times++;
- }
- }
-
- private Observer observer;
- private MemorySubject<Integer> memorySubject;
-
- @Override
- public void setUp() throws Exception {
- super.setUp();
- observer = new Observer();
- memorySubject = new MemorySubject<Integer>();
- }
-
- public void testInitial() {
- assertNull(observer.value);
- assertEquals(0, observer.times);
- assertNull(memorySubject.getMemory());
- }
-
- public void testMemory() {
- memorySubject.addObserver(observer);
- memorySubject.notifyObservers(10);
- assertEquals(Integer.valueOf(10), observer.value);
- assertEquals(1, observer.times);
- assertEquals(Integer.valueOf(10), memorySubject.getMemory());
- memorySubject.notifyObservers(20);
- assertEquals(Integer.valueOf(20), observer.value);
- assertEquals(2, observer.times);
- assertEquals(Integer.valueOf(20), memorySubject.getMemory());
- }
-
- public void testAttach() {
- memorySubject.notifyObservers(10);
- assertNull(observer.value);
- assertEquals(0, observer.times);
- memorySubject.addObserver(observer);
- assertEquals(Integer.valueOf(10), observer.value);
- assertEquals(1, observer.times);
- memorySubject.notifyObservers(20);
- assertEquals(Integer.valueOf(20), observer.value);
- assertEquals(2, observer.times);
- }
-
- public void testDetach() {
- memorySubject.addObserver(observer);
- memorySubject.notifyObservers(10);
- assertEquals(Integer.valueOf(10), observer.value);
- assertEquals(1, observer.times);
- assertEquals(Integer.valueOf(10), memorySubject.getMemory());
- memorySubject.deleteObserver(observer);
- memorySubject.notifyObservers(20);
- assertEquals(Integer.valueOf(10), observer.value);
- assertEquals(1, observer.times);
- assertEquals(Integer.valueOf(20), memorySubject.getMemory());
- }
-
- public void testMultiple() {
- final Observer otherObserver = new Observer();
- memorySubject.addObserver(otherObserver);
- testDetach();
- assertEquals(Integer.valueOf(20), otherObserver.value);
- assertEquals(2, otherObserver.times);
- }
-
-}
diff --git a/tests/src/cgeo/test/Compare.java b/tests/src/cgeo/test/Compare.java
index 4a296bd..2ce8d49 100644
--- a/tests/src/cgeo/test/Compare.java
+++ b/tests/src/cgeo/test/Compare.java
@@ -11,6 +11,8 @@ import cgeo.geocaching.utils.CryptUtils;
import org.apache.commons.lang3.StringUtils;
+import java.util.Date;
+
public abstract class Compare {
public static void assertCompareCaches(ICache expected, Geocache actual, boolean all) {
@@ -27,7 +29,9 @@ public abstract class Compare {
assertEquals("Cache " + geocode + ": name wrong", expected.getName(), actual.getName());
assertEquals("Cache " + geocode + ": guid wrong", expected.getGuid(), actual.getGuid());
assertTrue("Cache " + geocode + ": fav points wrong", expected.getFavoritePoints() <= actual.getFavoritePoints());
- assertEquals("Cache " + geocode + ": hidden date wrong", expected.getHiddenDate().toString(), actual.getHiddenDate().toString());
+ final Date hiddenDate = actual.getHiddenDate();
+ assertNotNull(hiddenDate);
+ assertEquals("Cache " + geocode + ": hidden date wrong", expected.getHiddenDate().toString(), hiddenDate.toString());
assertEquals("Cache " + geocode + ": premium only wrong", expected.isPremiumMembersOnly(), actual.isPremiumMembersOnly());
if (all) {