aboutsummaryrefslogtreecommitdiffstats
path: root/main/src
diff options
context:
space:
mode:
Diffstat (limited to 'main/src')
-rw-r--r--main/src/cgeo/geocaching/AboutActivity.java4
-rw-r--r--main/src/cgeo/geocaching/AbstractPopupActivity.java80
-rw-r--r--main/src/cgeo/geocaching/AddressListActivity.java4
-rw-r--r--main/src/cgeo/geocaching/CacheCache.java2
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java579
-rw-r--r--main/src/cgeo/geocaching/CacheListActivity.java (renamed from main/src/cgeo/geocaching/cgeocaches.java)432
-rw-r--r--main/src/cgeo/geocaching/CacheMenuHandler.java126
-rw-r--r--main/src/cgeo/geocaching/CachePopup.java5
-rw-r--r--main/src/cgeo/geocaching/CgeoApplication.java (renamed from main/src/cgeo/geocaching/cgeoapplication.java)45
-rw-r--r--main/src/cgeo/geocaching/CompassActivity.java34
-rw-r--r--main/src/cgeo/geocaching/DataStore.java (renamed from main/src/cgeo/geocaching/cgData.java)101
-rw-r--r--main/src/cgeo/geocaching/EditWaypointActivity.java74
-rw-r--r--main/src/cgeo/geocaching/GeoDataProvider.java3
-rw-r--r--main/src/cgeo/geocaching/Geocache.java145
-rw-r--r--main/src/cgeo/geocaching/GpxFileListActivity.java1
-rw-r--r--main/src/cgeo/geocaching/ImageSelectActivity.java5
-rw-r--r--main/src/cgeo/geocaching/ImagesActivity.java4
-rw-r--r--main/src/cgeo/geocaching/LogCacheActivity.java72
-rw-r--r--main/src/cgeo/geocaching/LogEntry.java4
-rw-r--r--main/src/cgeo/geocaching/LogTrackableActivity.java8
-rw-r--r--main/src/cgeo/geocaching/MainActivity.java31
-rw-r--r--main/src/cgeo/geocaching/NavigateAnyPointActivity.java25
-rw-r--r--main/src/cgeo/geocaching/PocketQueryList.java9
-rw-r--r--main/src/cgeo/geocaching/SearchActivity.java200
-rw-r--r--main/src/cgeo/geocaching/SearchResult.java12
-rw-r--r--main/src/cgeo/geocaching/SelectMapfileActivity.java55
-rw-r--r--main/src/cgeo/geocaching/StaticMapsActivity.java6
-rw-r--r--main/src/cgeo/geocaching/StaticMapsProvider.java9
-rw-r--r--main/src/cgeo/geocaching/StatusFragment.java4
-rw-r--r--main/src/cgeo/geocaching/TrackableActivity.java18
-rw-r--r--main/src/cgeo/geocaching/UsefulAppsActivity.java1
-rw-r--r--main/src/cgeo/geocaching/Waypoint.java5
-rw-r--r--main/src/cgeo/geocaching/WaypointPopup.java8
-rw-r--r--main/src/cgeo/geocaching/WaypointViewHolder.java23
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractActivity.java17
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractListActivity.java6
-rw-r--r--main/src/cgeo/geocaching/activity/ActivityMixin.java10
-rw-r--r--main/src/cgeo/geocaching/apps/AbstractApp.java19
-rw-r--r--main/src/cgeo/geocaching/apps/AbstractLocusApp.java22
-rw-r--r--main/src/cgeo/geocaching/apps/App.java10
-rw-r--r--main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/GccApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java24
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java10
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java8
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java6
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java10
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java9
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java69
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java6
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/SygicNavigationApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/AbstractLocusCacheListApp.java (renamed from main/src/cgeo/geocaching/apps/cachelist/LocusCacheListApp.java)10
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java50
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/LocusExportCacheListApp.java11
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/LocusShowCacheListApp.java11
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel13.java4
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java4
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractConnector.java42
-rw-r--r--main/src/cgeo/geocaching/connector/ConnectorFactory.java16
-rw-r--r--main/src/cgeo/geocaching/connector/IConnector.java12
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java5
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java5
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByKeyword.java12
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java5
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java33
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConstants.java9
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java12
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java72
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Login.java29
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Tile.java5
-rw-r--r--main/src/cgeo/geocaching/connector/gc/UTFGrid.java16
-rw-r--r--main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java9
-rw-r--r--main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java29
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java23
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java75
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCConnector.java14
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java7
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java2
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java7
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java2
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java137
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiError.java87
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java23
-rw-r--r--main/src/cgeo/geocaching/connector/oc/UserInfo.java18
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java4
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java26
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheAttribute.java4
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheListType.java29
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheSize.java4
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheType.java6
-rw-r--r--main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java4
-rw-r--r--main/src/cgeo/geocaching/enumerations/LogType.java4
-rw-r--r--main/src/cgeo/geocaching/enumerations/WaypointType.java4
-rw-r--r--main/src/cgeo/geocaching/export/AbstractExport.java6
-rw-r--r--main/src/cgeo/geocaching/export/ExportFactory.java1
-rw-r--r--main/src/cgeo/geocaching/export/FieldnoteExport.java28
-rw-r--r--main/src/cgeo/geocaching/export/GpxExport.java4
-rw-r--r--main/src/cgeo/geocaching/export/GpxSerializer.java8
-rw-r--r--main/src/cgeo/geocaching/files/AbstractFileListActivity.java12
-rw-r--r--main/src/cgeo/geocaching/files/FileParser.java5
-rw-r--r--main/src/cgeo/geocaching/files/GPXImporter.java4
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java27
-rw-r--r--main/src/cgeo/geocaching/files/LocParser.java4
-rw-r--r--main/src/cgeo/geocaching/files/LocalStorage.java42
-rw-r--r--main/src/cgeo/geocaching/files/ProgressInputStream.java18
-rw-r--r--main/src/cgeo/geocaching/files/SimpleDirChooser.java30
-rw-r--r--main/src/cgeo/geocaching/filter/AbstractRangeFilter.java4
-rw-r--r--main/src/cgeo/geocaching/filter/AttributeFilter.java10
-rw-r--r--main/src/cgeo/geocaching/filter/DistanceFilter.java6
-rw-r--r--main/src/cgeo/geocaching/filter/FilterUserInterface.java4
-rw-r--r--main/src/cgeo/geocaching/filter/ModifiedFilter.java4
-rw-r--r--main/src/cgeo/geocaching/filter/StateFilter.java4
-rw-r--r--main/src/cgeo/geocaching/filter/TrackablesFilter.java4
-rw-r--r--main/src/cgeo/geocaching/gcvote/GCVote.java52
-rw-r--r--main/src/cgeo/geocaching/gcvote/GCVoteRating.java2
-rw-r--r--main/src/cgeo/geocaching/geopoint/Geopoint.java6
-rw-r--r--main/src/cgeo/geocaching/geopoint/GeopointParser.java19
-rw-r--r--main/src/cgeo/geocaching/list/AbstractList.java28
-rw-r--r--main/src/cgeo/geocaching/list/PseudoList.java37
-rw-r--r--main/src/cgeo/geocaching/list/StoredList.java (renamed from main/src/cgeo/geocaching/StoredList.java)87
-rw-r--r--main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java4
-rw-r--r--main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java17
-rw-r--r--main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java4
-rw-r--r--main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java10
-rw-r--r--main/src/cgeo/geocaching/maps/AbstractItemizedOverlay.java4
-rw-r--r--main/src/cgeo/geocaching/maps/CGeoMap.java62
-rw-r--r--main/src/cgeo/geocaching/maps/CachesOverlay.java4
-rw-r--r--main/src/cgeo/geocaching/maps/MapProviderFactory.java4
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java4
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java40
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java5
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java2
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java3
-rw-r--r--main/src/cgeo/geocaching/network/HtmlImage.java64
-rw-r--r--main/src/cgeo/geocaching/network/Network.java100
-rw-r--r--main/src/cgeo/geocaching/network/OAuth.java20
-rw-r--r--main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java195
-rw-r--r--main/src/cgeo/geocaching/network/Parameters.java9
-rw-r--r--main/src/cgeo/geocaching/network/StatusUpdater.java6
-rw-r--r--main/src/cgeo/geocaching/settings/AuthorizeTwitterPreference.java46
-rw-r--r--main/src/cgeo/geocaching/settings/LogSignaturePreference.java60
-rw-r--r--main/src/cgeo/geocaching/settings/OAuthPreference.java (renamed from main/src/cgeo/geocaching/settings/AuthorizeOcPreference.java)46
-rw-r--r--main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java2
-rw-r--r--main/src/cgeo/geocaching/settings/Settings.java118
-rw-r--r--main/src/cgeo/geocaching/settings/SettingsActivity.java114
-rw-r--r--main/src/cgeo/geocaching/settings/TemplateTextPreference.java111
-rw-r--r--main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java1
-rw-r--r--main/src/cgeo/geocaching/sorting/DateComparator.java4
-rw-r--r--main/src/cgeo/geocaching/sorting/FindsComparator.java4
-rw-r--r--main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java56
-rw-r--r--main/src/cgeo/geocaching/speech/SpeechService.java6
-rw-r--r--main/src/cgeo/geocaching/speech/TextFactory.java13
-rw-r--r--main/src/cgeo/geocaching/twitter/Twitter.java65
-rw-r--r--main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java78
-rw-r--r--main/src/cgeo/geocaching/ui/AbstractUIFactory.java4
-rw-r--r--main/src/cgeo/geocaching/ui/AbstractUserClickListener.java6
-rw-r--r--main/src/cgeo/geocaching/ui/AddressListAdapter.java8
-rw-r--r--main/src/cgeo/geocaching/ui/CacheDetailsCreator.java18
-rw-r--r--main/src/cgeo/geocaching/ui/CacheListAdapter.java16
-rw-r--r--main/src/cgeo/geocaching/ui/CompassMiniView.java10
-rw-r--r--main/src/cgeo/geocaching/ui/CompassView.java1
-rw-r--r--main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java3
-rw-r--r--main/src/cgeo/geocaching/ui/DecryptTextClickListener.java24
-rw-r--r--main/src/cgeo/geocaching/ui/DirectionImage.java2
-rw-r--r--main/src/cgeo/geocaching/ui/Formatter.java26
-rw-r--r--main/src/cgeo/geocaching/ui/ImagesList.java5
-rw-r--r--main/src/cgeo/geocaching/ui/LoggingUI.java6
-rw-r--r--main/src/cgeo/geocaching/ui/UserNameClickListener.java18
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java7
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java4
-rw-r--r--main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java4
-rw-r--r--main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java4
-rw-r--r--main/src/cgeo/geocaching/utils/ApplicationSettings.java2
-rw-r--r--main/src/cgeo/geocaching/utils/CancellableHandler.java4
-rw-r--r--main/src/cgeo/geocaching/utils/ClipboardUtils.java4
-rw-r--r--main/src/cgeo/geocaching/utils/CryptUtils.java14
-rw-r--r--main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java43
-rw-r--r--main/src/cgeo/geocaching/utils/GeoDirHandler.java4
-rw-r--r--main/src/cgeo/geocaching/utils/HtmlUtils.java5
-rw-r--r--main/src/cgeo/geocaching/utils/IOUtils.java22
-rw-r--r--main/src/cgeo/geocaching/utils/ImageUtils.java28
-rw-r--r--main/src/cgeo/geocaching/utils/Log.java1
-rw-r--r--main/src/cgeo/geocaching/utils/LogTemplateProvider.java57
-rw-r--r--main/src/cgeo/geocaching/utils/ProcessUtils.java39
-rw-r--r--main/src/cgeo/geocaching/utils/SynchronizedDateFormat.java18
-rw-r--r--main/src/cgeo/geocaching/utils/TextUtils.java6
-rw-r--r--main/src/cgeo/geocaching/utils/TranslationUtils.java22
199 files changed, 2958 insertions, 2493 deletions
diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java
index 9dcd099..3ab9904 100644
--- a/main/src/cgeo/geocaching/AboutActivity.java
+++ b/main/src/cgeo/geocaching/AboutActivity.java
@@ -120,7 +120,7 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page>
final ScrollView view = (ScrollView) getLayoutInflater().inflate(R.layout.about_version_page, null);
Views.inject(this, view);
version.setText(Version.getVersionName(AboutActivity.this));
- setClickListener(donateButton, "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FMLNN8GXZKJEE");
+ setClickListener(donateButton, "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=AQBS7UP76CXW2");
return view;
}
}
@@ -140,7 +140,7 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page>
}
@Override
- public final void onCreate(final Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.viewpager_activity);
createViewPager(0, null);
reinitializeViewPager();
diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java
index 03f0680..5b9b509 100644
--- a/main/src/cgeo/geocaching/AbstractPopupActivity.java
+++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java
@@ -2,7 +2,6 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.ActivityMixin;
-import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.gcvote.GCVote;
@@ -17,12 +16,8 @@ import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
-import android.content.Intent;
import android.graphics.Rect;
-import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
@@ -33,7 +28,7 @@ import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
-public abstract class AbstractPopupActivity extends AbstractActivity {
+public abstract class AbstractPopupActivity extends AbstractActivity implements CacheMenuHandler.ActivityInterface {
protected Geocache cache = null;
protected String geocode = null;
@@ -42,18 +37,6 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
private TextView cacheDistance = null;
private final int layout;
- private final Handler ratingHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- try {
- details.addRating(cache);
- } catch (final Exception e) {
- // nothing
- }
- }
- };
-
private final GeoDirHandler geoUpdate = new GeoDirHandler() {
@Override
@@ -91,8 +74,8 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
if (!cache.supportsGCVote()) {
return;
}
- (new Thread("Load GCVote") {
+ (new Thread("Load GCVote") {
@Override
public void run() {
final GCVoteRating rating = GCVote.getRating(cache.getGuid(), geocode);
@@ -102,14 +85,17 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
}
cache.setRating(rating.getRating());
cache.setVotes(rating.getVotes());
- final Message msg = Message.obtain();
- ratingHandler.sendMessage(msg);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ details.addRating(cache); }
+ });
}
}).start();
}
protected void init() {
- cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
if (cache == null) {
showToast(res.getString(R.string.err_detail_cache_find));
@@ -121,11 +107,8 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
geocode = cache.getGeocode();
}
- private void showInBrowser() {
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(cache.getUrl())));
- }
-
- protected abstract void navigateTo();
+ @Override
+ public abstract void navigateTo();
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -161,31 +144,17 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.abstract_popup_activity, menu);
+ CacheMenuHandler.addMenuItems(this, menu, cache);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- final int menuItem = item.getItemId();
-
- switch (menuItem) {
- case R.id.menu_default_navigation:
- navigateTo();
- return true;
- case R.id.menu_navigate:
- showNavigationMenu();
- return true;
- case R.id.menu_caches_around:
- cachesAround();
- return true;
- case R.id.menu_show_in_browser:
- showInBrowser();
- return true;
- default:
- if (LoggingUI.onMenuItemSelected(item, this, cache)) {
- return true;
- }
+ if (CacheMenuHandler.onMenuItemSelected(item, this, cache)) {
+ return true;
+ }
+ if (LoggingUI.onMenuItemSelected(item, this, cache)) {
+ return true;
}
return true;
@@ -202,12 +171,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
super.onPrepareOptionsMenu(menu);
try {
- final boolean visible = getCoordinates() != null;
- menu.findItem(R.id.menu_default_navigation).setVisible(visible);
- menu.findItem(R.id.menu_navigate).setVisible(visible);
- menu.findItem(R.id.menu_caches_around).setVisible(visible);
-
- menu.findItem(R.id.menu_default_navigation).setTitle(NavigationAppFactory.getDefaultNavigationApplication().getName());
+ CacheMenuHandler.onPrepareOptionsMenu(menu, cache);
LoggingUI.onPrepareOptionsMenu(menu, cache);
} catch (final RuntimeException e) {
// nothing
@@ -238,11 +202,13 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
return super.onTouchEvent(event);
}
- protected abstract void showNavigationMenu();
+ @Override
+ public abstract void showNavigationMenu();
protected abstract void startDefaultNavigation2();
protected final void addCacheDetails() {
+ assert cache != null;
// cache type
final String cacheType = cache.getType().getL10n();
final String cacheSize = cache.getSize() != CacheSize.UNKNOWN ? " (" + cache.getSize().getL10n() + ")" : "";
@@ -256,6 +222,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
details.addDifficulty(cache);
details.addTerrain(cache);
+ details.addEventDate(cache);
// rating
if (cache.getRating() > 0) {
@@ -279,13 +246,14 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
});
}
- private void cachesAround() {
+ @Override
+ public void cachesAround() {
final Geopoint coords = getCoordinates();
if (coords == null) {
showToast(res.getString(R.string.err_location_unknown));
return;
}
- cgeocaches.startActivityCoordinates(this, coords);
+ CacheListActivity.startActivityCoordinates(this, coords);
finish();
}
diff --git a/main/src/cgeo/geocaching/AddressListActivity.java b/main/src/cgeo/geocaching/AddressListActivity.java
index c984d28..dc0239f 100644
--- a/main/src/cgeo/geocaching/AddressListActivity.java
+++ b/main/src/cgeo/geocaching/AddressListActivity.java
@@ -4,7 +4,7 @@ import cgeo.geocaching.activity.AbstractListActivity;
import cgeo.geocaching.ui.AddressListAdapter;
import cgeo.geocaching.utils.Log;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.ProgressDialog;
@@ -66,7 +66,7 @@ public class AddressListActivity extends AbstractListActivity {
}
} else {
finish();
- cgeocaches.startActivityAddress(AddressListActivity.this, null, keyword);
+ CacheListActivity.startActivityAddress(AddressListActivity.this, null, keyword);
}
}
diff --git a/main/src/cgeo/geocaching/CacheCache.java b/main/src/cgeo/geocaching/CacheCache.java
index e70b7a0..b3c674c 100644
--- a/main/src/cgeo/geocaching/CacheCache.java
+++ b/main/src/cgeo/geocaching/CacheCache.java
@@ -1,6 +1,6 @@
package cgeo.geocaching;
-import cgeo.geocaching.cgData.StorageLocation;
+import cgeo.geocaching.DataStore.StorageLocation;
import cgeo.geocaching.connector.gc.Tile;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.geopoint.Viewport;
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index 4b34f8d..4eddba4 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -3,7 +3,6 @@ package cgeo.geocaching;
import butterknife.InjectView;
import butterknife.Views;
-import cgeo.calendar.ICalendar;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.AbstractViewPagerActivity;
import cgeo.geocaching.activity.Progress;
@@ -16,11 +15,10 @@ import cgeo.geocaching.enumerations.CacheAttribute;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.WaypointType;
-import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.geopoint.Units;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.network.Network;
-import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.AbstractCachingPageViewCreator;
import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
@@ -52,7 +50,7 @@ import cgeo.geocaching.utils.TextUtils;
import cgeo.geocaching.utils.TranslationUtils;
import cgeo.geocaching.utils.UnknownTagsHandler;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
@@ -64,8 +62,6 @@ import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Typeface;
@@ -89,7 +85,6 @@ import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.SubMenu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
@@ -121,25 +116,7 @@ import java.util.regex.Pattern;
*
* e.g. details, description, logs, waypoints, inventory...
*/
-public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailActivity.Page> {
-
- private static final int MENU_FIELD_COPY = 1;
- private static final int MENU_FIELD_TRANSLATE = 2;
- private static final int MENU_FIELD_TRANSLATE_EN = 3;
- private static final int MENU_FIELD_SHARE = 4;
- private static final int MENU_SHARE = 12;
- private static final int MENU_CALENDAR = 11;
- private static final int MENU_CACHES_AROUND = 10;
- private static final int MENU_BROWSER = 7;
- private static final int MENU_DEFAULT_NAVIGATION = 13;
-
- private static final int CONTEXT_MENU_WAYPOINT_EDIT = 1234;
- private static final int CONTEXT_MENU_WAYPOINT_DUPLICATE = 1235;
- private static final int CONTEXT_MENU_WAYPOINT_DELETE = 1236;
- private static final int CONTEXT_MENU_WAYPOINT_NAVIGATE = 1238;
- private static final int CONTEXT_MENU_WAYPOINT_CACHES_AROUND = 1239;
- private static final int CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION = 1240;
- private static final int CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES = 1241;
+public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailActivity.Page> implements CacheMenuHandler.ActivityInterface {
private static final int MESSAGE_FAILED = -1;
private static final int MESSAGE_SUCCEEDED = 1;
@@ -173,7 +150,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
};
private CharSequence clickedItemText = null;
- private int contextMenuWPIndex = -1;
/**
* If another activity is called and can modify the data of this activity, we refresh it on resume.
@@ -184,6 +160,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private TextView cacheDistanceView;
protected ImagesList imagesList;
+ /**
+ * waypoint selected in context menu. This variable will be gone when the waypoint context menu is a fragment.
+ */
+ private Waypoint selectedWaypoint;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -360,18 +340,20 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) {
super.onCreateContextMenu(menu, view, info);
final int viewId = view.getId();
- contextMenuWPIndex = -1;
switch (viewId) {
case R.id.value: // coordinates, gc-code, name
+ assert view instanceof TextView;
clickedItemText = ((TextView) view).getText();
final String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText();
- buildOptionsContextmenu(menu, viewId, itemTitle, true);
+ buildDetailsContextMenu(menu, itemTitle, true);
break;
case R.id.shortdesc:
+ assert view instanceof TextView;
clickedItemText = ((TextView) view).getText();
- buildOptionsContextmenu(menu, viewId, res.getString(R.string.cache_description), false);
+ buildDetailsContextMenu(menu, res.getString(R.string.cache_description), false);
break;
case R.id.longdesc:
+ assert view instanceof TextView;
// combine short and long description
final String shortDesc = cache.getShortDescription();
if (StringUtils.isBlank(shortDesc)) {
@@ -379,52 +361,38 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
} else {
clickedItemText = shortDesc + "\n\n" + ((TextView) view).getText();
}
- buildOptionsContextmenu(menu, viewId, res.getString(R.string.cache_description), false);
+ buildDetailsContextMenu(menu, res.getString(R.string.cache_description), false);
break;
case R.id.personalnote:
+ assert view instanceof TextView;
clickedItemText = ((TextView) view).getText();
- buildOptionsContextmenu(menu, viewId, res.getString(R.string.cache_personal_note), true);
+ buildDetailsContextMenu(menu, res.getString(R.string.cache_personal_note), true);
break;
case R.id.hint:
+ assert view instanceof TextView;
clickedItemText = ((TextView) view).getText();
- buildOptionsContextmenu(menu, viewId, res.getString(R.string.cache_hint), false);
+ buildDetailsContextMenu(menu, res.getString(R.string.cache_hint), false);
break;
case R.id.log:
+ assert view instanceof TextView;
clickedItemText = ((TextView) view).getText();
- buildOptionsContextmenu(menu, viewId, res.getString(R.string.cache_logs), false);
+ buildDetailsContextMenu(menu, res.getString(R.string.cache_logs), false);
break;
- case -1:
- if (null != cache.getWaypoints()) {
- try {
- final ViewGroup parent = ((ViewGroup) view.getParent());
- for (int i = 0; i < parent.getChildCount(); i++) {
- if (parent.getChildAt(i) == view) {
- final List<Waypoint> sortedWaypoints = new ArrayList<Waypoint>(cache.getWaypoints());
- Collections.sort(sortedWaypoints);
- final Waypoint waypoint = sortedWaypoints.get(i);
- final int index = cache.getWaypoints().indexOf(waypoint);
- menu.setHeaderTitle(res.getString(R.string.waypoint));
- if (waypoint.getWaypointType().equals(WaypointType.ORIGINAL)) {
- menu.add(CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES, index, 0, R.string.waypoint_reset_cache_coords);
- } else {
- menu.add(CONTEXT_MENU_WAYPOINT_EDIT, index, 0, R.string.waypoint_edit);
- menu.add(CONTEXT_MENU_WAYPOINT_DUPLICATE, index, 0, R.string.waypoint_duplicate);
- }
- contextMenuWPIndex = index;
- if (waypoint.isUserDefined() && !waypoint.getWaypointType().equals(WaypointType.ORIGINAL)) {
- menu.add(CONTEXT_MENU_WAYPOINT_DELETE, index, 0, R.string.waypoint_delete);
- }
- if (waypoint.getCoords() != null) {
- menu.add(CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION, index, 0, NavigationAppFactory.getDefaultNavigationApplication().getName());
- menu.add(CONTEXT_MENU_WAYPOINT_NAVIGATE, index, 0, R.string.cache_menu_navigate).setIcon(R.drawable.ic_menu_mapmode);
- menu.add(CONTEXT_MENU_WAYPOINT_CACHES_AROUND, index, 0, R.string.cache_menu_around);
- }
- break;
- }
- }
- } catch (final RuntimeException e) {
- }
- }
+ case R.id.waypoint:
+ menu.setHeaderTitle(res.getString(R.string.waypoint));
+ getMenuInflater().inflate(R.menu.waypoint_options, menu);
+ final boolean isOriginalWaypoint = selectedWaypoint.getWaypointType().equals(WaypointType.ORIGINAL);
+ menu.findItem(R.id.menu_waypoint_reset_cache_coords).setVisible(isOriginalWaypoint);
+ menu.findItem(R.id.menu_waypoint_edit).setVisible(!isOriginalWaypoint);
+ menu.findItem(R.id.menu_waypoint_duplicate).setVisible(!isOriginalWaypoint);
+ final boolean userDefined = selectedWaypoint.isUserDefined() && !selectedWaypoint.getWaypointType().equals(WaypointType.ORIGINAL);
+ menu.findItem(R.id.menu_waypoint_delete).setVisible(userDefined);
+ final boolean hasCoords = selectedWaypoint.getCoords() != null;
+ final MenuItem defaultNavigationMenu = menu.findItem(R.id.menu_waypoint_navigate_default);
+ defaultNavigationMenu.setVisible(hasCoords);
+ defaultNavigationMenu.setTitle(NavigationAppFactory.getDefaultNavigationApplication().getName());
+ menu.findItem(R.id.menu_waypoint_navigate).setVisible(hasCoords);
+ menu.findItem(R.id.menu_waypoint_caches_around).setVisible(hasCoords);
break;
default:
if (imagesList != null) {
@@ -434,171 +402,118 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- private void buildOptionsContextmenu(ContextMenu menu, int viewId, String fieldTitle, boolean copyOnly) {
+ private void buildDetailsContextMenu(ContextMenu menu, String fieldTitle, boolean copyOnly) {
menu.setHeaderTitle(fieldTitle);
- menu.add(viewId, MENU_FIELD_COPY, 0, res.getString(android.R.string.copy));
+ getMenuInflater().inflate(R.menu.details_context, menu);
+ menu.findItem(R.id.menu_translate_to_sys_lang).setVisible(!copyOnly);
if (!copyOnly) {
- if (clickedItemText.length() > TranslationUtils.translationTextLengthToWarn) {
+ if (clickedItemText.length() > TranslationUtils.TRANSLATION_TEXT_LENGTH_WARN) {
showToast(res.getString(R.string.translate_length_warning));
}
- menu.add(viewId, MENU_FIELD_TRANSLATE, 0, res.getString(R.string.translate_to_sys_lang, Locale.getDefault().getDisplayLanguage()));
- if (Settings.isUseEnglish() && !StringUtils.equals(Locale.getDefault().getLanguage(), Locale.ENGLISH.getLanguage())) {
- menu.add(viewId, MENU_FIELD_TRANSLATE_EN, 0, res.getString(R.string.translate_to_english));
- }
-
+ menu.findItem(R.id.menu_translate_to_sys_lang).setTitle(res.getString(R.string.translate_to_sys_lang, Locale.getDefault().getDisplayLanguage()));
}
- menu.add(viewId, MENU_FIELD_SHARE, 0, res.getString(R.string.cache_share_field));
+ final boolean localeIsEnglish = StringUtils.equals(Locale.getDefault().getLanguage(), Locale.ENGLISH.getLanguage());
+ menu.findItem(R.id.menu_translate_to_english).setVisible(!copyOnly && !localeIsEnglish);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
- final int groupId = item.getGroupId();
- final int index = item.getItemId();
- switch (groupId) {
- case R.id.value:
- case R.id.shortdesc:
- case R.id.longdesc:
- case R.id.personalnote:
- case R.id.hint:
- case R.id.log:
- switch (index) {
- case MENU_FIELD_COPY:
- ClipboardUtils.copyToClipboard(clickedItemText);
- showToast(res.getString(R.string.clipboard_copy_ok));
- return true;
- case MENU_FIELD_TRANSLATE:
- TranslationUtils.startActivityTranslate(this, Locale.getDefault().getLanguage(), HtmlUtils.extractText(clickedItemText));
- return true;
- case MENU_FIELD_TRANSLATE_EN:
- TranslationUtils.startActivityTranslate(this, Locale.ENGLISH.getLanguage(), HtmlUtils.extractText(clickedItemText));
- return true;
- case MENU_FIELD_SHARE:
- final Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType("text/plain");
- intent.putExtra(Intent.EXTRA_TEXT, clickedItemText.toString());
- startActivity(Intent.createChooser(intent, res.getText(R.string.cache_share_field)));
- return true;
- default:
- break;
- }
-
- break;
- case CONTEXT_MENU_WAYPOINT_EDIT:
- final Waypoint waypointEdit = cache.getWaypoint(index);
- if (waypointEdit != null) {
- EditWaypointActivity.startActivityEditWaypoint(this, waypointEdit.getId());
+ switch (item.getItemId()) {
+ // detail fields
+ case R.id.menu_copy:
+ ClipboardUtils.copyToClipboard(clickedItemText);
+ showToast(res.getString(R.string.clipboard_copy_ok));
+ return true;
+ case R.id.menu_translate_to_sys_lang:
+ TranslationUtils.startActivityTranslate(this, Locale.getDefault().getLanguage(), HtmlUtils.extractText(clickedItemText));
+ return true;
+ case R.id.menu_translate_to_english:
+ TranslationUtils.startActivityTranslate(this, Locale.ENGLISH.getLanguage(), HtmlUtils.extractText(clickedItemText));
+ return true;
+ case R.id.menu_cache_share_field:
+ final Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setType("text/plain");
+ intent.putExtra(Intent.EXTRA_TEXT, clickedItemText.toString());
+ startActivity(Intent.createChooser(intent, res.getText(R.string.cache_share_field)));
+ return true;
+ // waypoints
+ case R.id.menu_waypoint_edit:
+ if (selectedWaypoint != null) {
+ EditWaypointActivity.startActivityEditWaypoint(this, cache, selectedWaypoint.getId());
refreshOnResume = true;
}
- break;
- case CONTEXT_MENU_WAYPOINT_DUPLICATE:
- final Waypoint waypointDuplicate = cache.getWaypoint(index);
- if (cache.duplicateWaypoint(waypointDuplicate)) {
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ return true;
+ case R.id.menu_waypoint_duplicate:
+ if (cache.duplicateWaypoint(selectedWaypoint)) {
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
notifyDataSetChanged();
}
- break;
- case CONTEXT_MENU_WAYPOINT_DELETE:
- final Waypoint waypointDelete = cache.getWaypoint(index);
- if (cache.deleteWaypoint(waypointDelete)) {
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ return true;
+ case R.id.menu_waypoint_delete:
+ if (cache.deleteWaypoint(selectedWaypoint)) {
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
notifyDataSetChanged();
}
- break;
- case CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION:
- final Waypoint waypointNavigation = cache.getWaypoint(index);
- if (waypointNavigation != null) {
- NavigationAppFactory.startDefaultNavigationApplication(1, this, waypointNavigation);
+ return true;
+ case R.id.menu_waypoint_navigate_default:
+ if (selectedWaypoint != null) {
+ NavigationAppFactory.startDefaultNavigationApplication(1, this, selectedWaypoint);
}
- break;
- case CONTEXT_MENU_WAYPOINT_NAVIGATE:
- final Waypoint waypointNav = cache.getWaypoint(contextMenuWPIndex);
- if (waypointNav != null) {
- NavigationAppFactory.showNavigationMenu(this, null, waypointNav, null);
+ return true;
+ case R.id.menu_waypoint_navigate:
+ if (selectedWaypoint != null) {
+ NavigationAppFactory.showNavigationMenu(this, null, selectedWaypoint, null);
}
- break;
- case CONTEXT_MENU_WAYPOINT_CACHES_AROUND:
- final Waypoint waypointAround = cache.getWaypoint(index);
- if (waypointAround != null) {
- cgeocaches.startActivityCoordinates(this, waypointAround.getCoords());
+ return true;
+ case R.id.menu_waypoint_caches_around:
+ if (selectedWaypoint != null) {
+ CacheListActivity.startActivityCoordinates(this, selectedWaypoint.getCoords());
}
- break;
-
- case CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES:
- final Waypoint waypointReset = cache.getWaypoint(index);
+ return true;
+ case R.id.menu_waypoint_reset_cache_coords:
if (ConnectorFactory.getConnector(cache).supportsOwnCoordinates()) {
- createResetCacheCoordinatesDialog(cache, waypointReset).show();
+ createResetCacheCoordinatesDialog(cache, selectedWaypoint).show();
}
else {
final ProgressDialog progressDialog = ProgressDialog.show(this, getString(R.string.cache), getString(R.string.waypoint_reset), true);
final HandlerResetCoordinates handler = new HandlerResetCoordinates(this, progressDialog, false);
- new ResetCoordsThread(cache, handler, waypointReset, true, false, progressDialog).start();
+ new ResetCoordsThread(cache, handler, selectedWaypoint, true, false, progressDialog).start();
}
- break;
-
+ return true;
default:
- if (imagesList != null && imagesList.onContextItemSelected(item)) {
- return true;
- }
- return onOptionsItemSelected(item);
+ break;
}
- return false;
+ if (imagesList != null && imagesList.onContextItemSelected(item)) {
+ return true;
+ }
+ return onOptionsItemSelected(item);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- if (null != cache) {
- menu.add(0, MENU_DEFAULT_NAVIGATION, 0, NavigationAppFactory.getDefaultNavigationApplication().getName()).setIcon(R.drawable.ic_menu_compass); // default navigation tool
-
- final SubMenu subMenu = menu.addSubMenu(0, 0, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode);
- NavigationAppFactory.addMenuItems(subMenu, cache);
-
- menu.add(0, MENU_CALENDAR, 0, res.getString(R.string.cache_menu_event)).setIcon(R.drawable.ic_menu_agenda); // add event to calendar
- LoggingUI.addMenuItems(this, menu, cache);
- menu.add(0, MENU_CACHES_AROUND, 0, res.getString(R.string.cache_menu_around)).setIcon(R.drawable.ic_menu_rotate); // caches around
- menu.add(0, MENU_BROWSER, 0, res.getString(R.string.cache_menu_browser)).setIcon(R.drawable.ic_menu_globe); // browser
- menu.add(0, MENU_SHARE, 0, res.getString(R.string.cache_menu_share)).setIcon(R.drawable.ic_menu_share); // share cache
- }
+ CacheMenuHandler.addMenuItems(this, menu, cache);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- if (cache != null) {
- menu.findItem(MENU_DEFAULT_NAVIGATION).setVisible(null != cache.getCoords());
- menu.findItem(MENU_CALENDAR).setVisible(cache.canBeAddedToCalendar());
- menu.findItem(MENU_CACHES_AROUND).setVisible(null != cache.getCoords() && cache.supportsCachesAround());
- menu.findItem(MENU_BROWSER).setVisible(cache.canOpenInBrowser());
- LoggingUI.onPrepareOptionsMenu(menu, cache);
- }
+ CacheMenuHandler.onPrepareOptionsMenu(menu, cache);
+ LoggingUI.onPrepareOptionsMenu(menu, cache);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
+ if (CacheMenuHandler.onMenuItemSelected(item, this, cache)) {
+ return true;
+ }
+
final int menuItem = item.getItemId();
switch (menuItem) {
case 0:
// no menu selected, but a new sub menu shown
return false;
- case MENU_DEFAULT_NAVIGATION:
- startDefaultNavigation();
- return true;
- case MENU_BROWSER:
- cache.openInBrowser(this);
- return true;
- case MENU_CACHES_AROUND:
- cgeocaches.startActivityCoordinates(this, cache.getCoords());
- return true;
- case MENU_CALENDAR:
- addToCalendarWithIntent();
- return true;
- case MENU_SHARE:
- if (cache != null) {
- cache.shareCache(this, res);
- return true;
- }
- return false;
default:
if (NavigationAppFactory.onMenuItemSelected(item, this, cache)) {
return true;
@@ -732,80 +647,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
/**
- * Indicates whether the specified action can be used as an intent. This
- * method queries the package manager for installed packages that can
- * respond to an intent with the specified action. If no suitable package is
- * found, this method returns false.
- *
- * @param context
- * The application's environment.
- * @param action
- * The Intent action to check for availability.
- * @param uri
- * The Intent URI to check for availability.
- *
- * @return True if an Intent with the specified action can be sent and
- * responded to, false otherwise.
- */
- private static boolean isIntentAvailable(Context context, String action, Uri uri) {
- final PackageManager packageManager = context.getPackageManager();
- final Intent intent;
- if (uri == null) {
- intent = new Intent(action);
- } else {
- intent = new Intent(action, uri);
- }
- final List<ResolveInfo> list = packageManager.queryIntentActivities(intent,
- PackageManager.MATCH_DEFAULT_ONLY);
- return !list.isEmpty();
- }
-
- private void addToCalendarWithIntent() {
-
- final boolean calendarAddOnAvailable = isIntentAvailable(this, ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST));
-
- if (calendarAddOnAvailable) {
- final Parameters params = new Parameters(
- ICalendar.PARAM_NAME, cache.getName(),
- ICalendar.PARAM_NOTE, StringUtils.defaultString(cache.getPersonalNote()),
- ICalendar.PARAM_HIDDEN_DATE, String.valueOf(cache.getHiddenDate().getTime()),
- 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())
- );
-
- 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
- new AlertDialog.Builder(this)
- .setTitle(res.getString(R.string.addon_missing_title))
- .setMessage(new StringBuilder(res.getString(R.string.helper_calendar_missing))
- .append(' ')
- .append(res.getString(R.string.addon_download_prompt))
- .toString())
- .setPositiveButton(getString(android.R.string.yes), 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));
- startActivity(intent);
- }
- })
- .setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- })
- .create()
- .show();
- }
- }
-
- /**
* Tries to navigate to the {@link Geocache} of this activity.
*/
private void startDefaultNavigation() {
@@ -1134,7 +975,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (time > 0) {
String dateString = Formatter.formatFullDate(time);
if (cache.isEventCache()) {
- dateString = DateUtils.formatDateTime(cgeoapplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY) + ", " + dateString;
+ 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);
}
@@ -1480,7 +1321,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
Settings.saveLastList(listId);
- cgData.moveToList(cache, listId);
+ DataStore.moveToList(cache, listId);
updateListBox();
}
@@ -1563,7 +1404,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// update text
final TextView text = (TextView) view.findViewById(R.id.list_text);
- final StoredList list = cgData.getList(cache.getListId());
+ final StoredList list = DataStore.getList(cache.getListId());
if (list != null) {
text.setText(res.getString(R.string.cache_list_text) + " " + list.title);
} else {
@@ -1706,12 +1547,16 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
hintView.setVisibility(View.VISIBLE);
hintView.setClickable(true);
- hintView.setOnClickListener(new DecryptTextClickListener());
+ hintView.setOnClickListener(new DecryptTextClickListener(hintView));
+ hintBoxView.setOnClickListener(new DecryptTextClickListener(hintView));
+ hintBoxView.setClickable(true);
registerForContextMenu(hintView);
} else {
hintView.setVisibility(View.GONE);
hintView.setClickable(false);
hintView.setOnClickListener(null);
+ hintBoxView.setClickable(false);
+ hintBoxView.setOnClickListener(null);
}
final TextView spoilerlinkView = ((TextView) view.findViewById(R.id.hint_spoilerlink));
@@ -1808,6 +1653,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private final View shortDescView;
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;
@@ -1933,122 +1779,138 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
+ private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ListView> {
@Override
- public ScrollView getDispatchedView() {
+ public ListView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
}
- view = (ScrollView) getLayoutInflater().inflate(R.layout.cachedetail_waypoints_page, null);
-
- final LinearLayout waypoints = (LinearLayout) view.findViewById(R.id.waypoints);
-
// sort waypoints: PP, Sx, FI, OWN
final List<Waypoint> sortedWaypoints = new ArrayList<Waypoint>(cache.getWaypoints());
Collections.sort(sortedWaypoints);
- for (final Waypoint wpt : sortedWaypoints) {
- final LinearLayout waypointView = (LinearLayout) getLayoutInflater().inflate(R.layout.waypoint_item, null);
+ view = (ListView) getLayoutInflater().inflate(R.layout.cachedetail_waypoints_page, null);
+ view.setClickable(true);
+ View addWaypointButton = getLayoutInflater().inflate(R.layout.cachedetail_waypoints_footer, null);
+ view.addFooterView(addWaypointButton);
+ addWaypointButton.setOnClickListener(new View.OnClickListener() {
- // coordinates
- if (null != wpt.getCoords()) {
- final TextView coordinatesView = (TextView) waypointView.findViewById(R.id.coordinates);
- coordinatesView.setOnClickListener(new CoordinatesFormatSwitcher(wpt.getCoords()));
- coordinatesView.setText(wpt.getCoords().toString());
- coordinatesView.setVisibility(View.VISIBLE);
+ @Override
+ public void onClick(View v) {
+ EditWaypointActivity.startActivityAddWaypoint(CacheDetailActivity.this, cache);
+ refreshOnResume = true;
}
+ });
- // info
- final String waypointInfo = Formatter.formatWaypointInfo(wpt);
- if (StringUtils.isNotBlank(waypointInfo)) {
- final TextView infoView = (TextView) waypointView.findViewById(R.id.info);
- infoView.setText(waypointInfo);
- infoView.setVisibility(View.VISIBLE);
- }
+ view.setAdapter(new ArrayAdapter<Waypoint>(CacheDetailActivity.this, R.layout.waypoint_item, sortedWaypoints) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View rowView = convertView;
+ if (null == rowView) {
+ rowView = getLayoutInflater().inflate(R.layout.waypoint_item, null);
+ rowView.setClickable(true);
+ rowView.setLongClickable(true);
+ }
+ WaypointViewHolder holder = (WaypointViewHolder) rowView.getTag();
+ if (null == holder) {
+ holder = new WaypointViewHolder(rowView);
+ }
- // title
- final TextView nameView = (TextView) waypointView.findViewById(R.id.name);
- if (StringUtils.isNotBlank(wpt.getName())) {
- nameView.setText(StringEscapeUtils.unescapeHtml4(wpt.getName()));
- } else if (null != wpt.getCoords()) {
- nameView.setText(wpt.getCoords().toString());
- } else {
- nameView.setText(res.getString(R.string.waypoint));
+ final Waypoint waypoint = getItem(position);
+ fillViewHolder(rowView, holder, waypoint);
+ return rowView;
}
- wpt.setIcon(res, nameView);
+ });
- // visited
- if (wpt.isVisited()) {
- final TypedValue a = new TypedValue();
- getTheme().resolveAttribute(R.attr.text_color_grey, a, true);
- if (a.type >= TypedValue.TYPE_FIRST_COLOR_INT && a.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- // really should be just a color!
- nameView.setTextColor(a.data);
- }
- }
+ return view;
+ }
- // note
- if (StringUtils.isNotBlank(wpt.getNote())) {
- final TextView noteView = (TextView) waypointView.findViewById(R.id.note);
- noteView.setVisibility(View.VISIBLE);
- if (TextUtils.containsHtml(wpt.getNote())) {
- noteView.setText(Html.fromHtml(wpt.getNote()), TextView.BufferType.SPANNABLE);
- }
- else {
- noteView.setText(wpt.getNote());
- }
- }
+ protected void fillViewHolder(View rowView, final WaypointViewHolder holder, final Waypoint wpt) {
+ // coordinates
+ if (null != wpt.getCoords()) {
+ final TextView coordinatesView = holder.coordinatesView;
+ coordinatesView.setOnClickListener(new CoordinatesFormatSwitcher(wpt.getCoords()));
+ coordinatesView.setText(wpt.getCoords().toString());
+ coordinatesView.setVisibility(View.VISIBLE);
+ }
- final View wpNavView = waypointView.findViewById(R.id.wpDefaultNavigation);
- wpNavView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- NavigationAppFactory.startDefaultNavigationApplication(1, CacheDetailActivity.this, wpt);
- }
- });
- wpNavView.setOnLongClickListener(new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- NavigationAppFactory.startDefaultNavigationApplication(2, CacheDetailActivity.this, wpt);
- return true;
- }
- });
+ // info
+ final String waypointInfo = Formatter.formatWaypointInfo(wpt);
+ if (StringUtils.isNotBlank(waypointInfo)) {
+ final TextView infoView = holder.infoView;
+ infoView.setText(waypointInfo);
+ infoView.setVisibility(View.VISIBLE);
+ }
- registerForContextMenu(waypointView);
- waypointView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- openContextMenu(v);
- }
- });
+ // title
+ final TextView nameView = holder.nameView;
+ if (StringUtils.isNotBlank(wpt.getName())) {
+ nameView.setText(StringEscapeUtils.unescapeHtml4(wpt.getName()));
+ } else if (null != wpt.getCoords()) {
+ nameView.setText(wpt.getCoords().toString());
+ } else {
+ nameView.setText(res.getString(R.string.waypoint));
+ }
+ wpt.setIcon(res, nameView);
- waypointView.setOnLongClickListener(new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- EditWaypointActivity.startActivityEditWaypoint(CacheDetailActivity.this, wpt.getId());
- refreshOnResume = true;
- return true;
- }
- });
+ // visited
+ if (wpt.isVisited()) {
+ final TypedValue a = new TypedValue();
+ getTheme().resolveAttribute(R.attr.text_color_grey, a, true);
+ if (a.type >= TypedValue.TYPE_FIRST_COLOR_INT && a.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+ // really should be just a color!
+ nameView.setTextColor(a.data);
+ }
+ }
- waypoints.addView(waypointView);
+ // note
+ if (StringUtils.isNotBlank(wpt.getNote())) {
+ final TextView noteView = holder.noteView;
+ noteView.setVisibility(View.VISIBLE);
+ if (TextUtils.containsHtml(wpt.getNote())) {
+ noteView.setText(Html.fromHtml(wpt.getNote()), TextView.BufferType.SPANNABLE);
+ }
+ else {
+ noteView.setText(wpt.getNote());
+ }
}
- final Button addWaypoint = (Button) view.findViewById(R.id.add_waypoint);
- addWaypoint.setClickable(true);
- addWaypoint.setOnClickListener(new View.OnClickListener() {
+ final View wpNavView = holder.wpNavView;
+ wpNavView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ NavigationAppFactory.startDefaultNavigationApplication(1, CacheDetailActivity.this, wpt);
+ }
+ });
+ wpNavView.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ NavigationAppFactory.startDefaultNavigationApplication(2, CacheDetailActivity.this, wpt);
+ return true;
+ }
+ });
+ registerForContextMenu(rowView);
+ rowView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- EditWaypointActivity.startActivityAddWaypoint(CacheDetailActivity.this, cache);
- refreshOnResume = true;
+ selectedWaypoint = wpt;
+ openContextMenu(v);
}
});
- return view;
+ rowView.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ selectedWaypoint = wpt;
+ EditWaypointActivity.startActivityEditWaypoint(CacheDetailActivity.this, cache, wpt.getId());
+ refreshOnResume = true;
+ return true;
+ }
+ });
}
}
@@ -2197,7 +2059,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
cache.setCoords(wpt.getCoords());
cache.setUserModifiedCoords(false);
cache.deleteWaypointForce(wpt);
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
handler.sendEmptyMessage(LOCAL);
}
@@ -2491,7 +2353,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
cache.parseWaypointsFromNote();
TextView personalNoteView = (TextView) activity.findViewById(R.id.personalnote);
setPersonalNote(personalNoteView, note);
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
activity.notifyDataSetChanged();
}
};
@@ -2509,4 +2371,19 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
personalNoteView.setVisibility(View.GONE);
}
}
+
+ @Override
+ public void navigateTo() {
+ startDefaultNavigation();
+ }
+
+ @Override
+ public void showNavigationMenu() {
+ NavigationAppFactory.showNavigationMenu(this, cache, null, null);
+ }
+
+ @Override
+ public void cachesAround() {
+ CacheListActivity.startActivityCoordinates(this, cache.getCoords());
+ }
}
diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/CacheListActivity.java
index 4ffe7ed..59f7297 100644
--- a/main/src/cgeo/geocaching/cgeocaches.java
+++ b/main/src/cgeo/geocaching/CacheListActivity.java
@@ -16,6 +16,7 @@ import cgeo.geocaching.files.GPXImporter;
import cgeo.geocaching.filter.FilterUserInterface;
import cgeo.geocaching.filter.IFilter;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.loaders.AbstractSearchLoader;
import cgeo.geocaching.loaders.AbstractSearchLoader.CacheListLoaderType;
import cgeo.geocaching.loaders.AddressGeocacheListLoader;
@@ -46,8 +47,10 @@ import cgeo.geocaching.utils.RunnableWithArgument;
import ch.boye.httpclientandroidlib.HttpResponse;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@@ -67,7 +70,6 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.SubMenu;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
@@ -81,37 +83,9 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-public class cgeocaches extends AbstractListActivity implements FilteredActivity, LoaderManager.LoaderCallbacks<SearchResult> {
+public class CacheListActivity extends AbstractListActivity implements FilteredActivity, LoaderManager.LoaderCallbacks<SearchResult> {
private static final int MAX_LIST_ITEMS = 1000;
- private static final int MENU_REFRESH_STORED = 2;
- private static final int MENU_CACHE_DETAILS = 4;
- private static final int MENU_DROP_CACHES = 5;
- private static final int MENU_IMPORT_GPX = 6;
- private static final int MENU_CREATE_LIST = 7;
- private static final int MENU_DROP_LIST = 8;
- private static final int MENU_INVERT_SELECTION = 9;
- private static final int MENU_SWITCH_LIST = 17;
- private static final int MENU_IMPORT_WEB = 21;
- private static final int MENU_EXPORT = 22;
- private static final int MENU_REMOVE_FROM_HISTORY = 23;
- private static final int MENU_DROP_CACHE = 24;
- private static final int MENU_MOVE_TO_LIST = 25;
- private static final int MENU_REFRESH = 26;
- private static final int MENU_SWITCH_SELECT_MODE = 52;
- private static final int SUBMENU_SHOW_MAP = 54;
- private static final int SUBMENU_MANAGE_LISTS = 55;
- private static final int SUBMENU_MANAGE_OFFLINE = 56;
- private static final int MENU_SORT = 57;
- private static final int SUBMENU_MANAGE_HISTORY = 60;
- private static final int MENU_RENAME_LIST = 64;
- private static final int MENU_DROP_CACHES_AND_LIST = 65;
- private static final int MENU_DEFAULT_NAVIGATION = 66;
- private static final int MENU_NAVIGATION = 69;
- private static final int MENU_STORE_CACHE = 73;
- private static final int MENU_FILTER = 74;
- private static final int MENU_DELETE_EVENTS = 75;
- private static final int MENU_CLEAR_OFFLINE_LOGS = 76;
private static final int MSG_DONE = -1;
private static final int MSG_RESTART_GEO_AND_DIR = -2;
@@ -153,7 +127,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
if (app.currentGeo().getSpeed() <= 5) { // use compass when speed is lower than 18 km/h) {
- final float northHeading = DirectionProvider.getDirectionNow(cgeocaches.this, direction);
+ final float northHeading = DirectionProvider.getDirectionNow(CacheListActivity.this, direction);
adapter.setActualHeading(northHeading);
}
}
@@ -161,10 +135,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
};
private ContextMenuInfo lastMenuInfo;
private String contextMenuGeocode = "";
- /**
- * the navigation menu item for the cache list (not the context menu!), or <code>null</code>
- */
- private MenuItem navigationMenu;
// FIXME: This method has mostly been replaced by the loaders. But it still contains a license agreement check.
public void handleCachesLoaded() {
@@ -212,7 +182,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
setAdapterCurrentCoordinates(false);
} catch (final Exception e) {
showToast(res.getString(R.string.err_detail_cache_find_any));
- Log.e("cgeocaches.loadCachesHandler", e);
+ Log.e("CacheListActivity.loadCachesHandler", e);
hideLoading();
showProgress(false);
@@ -225,7 +195,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
hideLoading();
showProgress(false);
} catch (final Exception e2) {
- Log.e("cgeocaches.loadCachesHandler.2", e2);
+ Log.e("CacheListActivity.loadCachesHandler.2", e2);
}
adapter.setSelectMode(false);
@@ -233,15 +203,15 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
private final Handler loadCachesHandler = new LoadCachesHandler(this);
- private static class LoadCachesHandler extends WeakReferenceHandler<cgeocaches> {
+ private static class LoadCachesHandler extends WeakReferenceHandler<CacheListActivity> {
- protected LoadCachesHandler(cgeocaches activity) {
+ protected LoadCachesHandler(CacheListActivity activity) {
super(activity);
}
@Override
public void handleMessage(Message msg) {
- final cgeocaches activity = getActivity();
+ final CacheListActivity activity = getActivity();
if (activity == null) {
return;
}
@@ -399,7 +369,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
private AbstractSearchLoader currentLoader;
private String newListName = StringUtils.EMPTY;
- public cgeocaches() {
+ public CacheListActivity() {
super(true);
}
@@ -434,7 +404,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
@Override
public void onClick(View v) {
- selectList(v);
+ selectList();
}
});
@@ -470,7 +440,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
private boolean isConcreteList() {
return type == CacheListType.OFFLINE &&
- (listId == StoredList.STANDARD_LIST_ID || listId >= cgData.customListIdOffset);
+ (listId == StoredList.STANDARD_LIST_ID || listId >= DataStore.customListIdOffset);
}
private boolean isInvokedFromAttachment() {
@@ -482,7 +452,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
@Override
public void run(Integer listId) {
- new GPXImporter(cgeocaches.this, listId, importGpxAttachementFinishedHandler).importGPX();
+ new GPXImporter(CacheListActivity.this, listId, importGpxAttachementFinishedHandler).importGPX();
switchListById(listId);
}
}, true, 0);
@@ -504,7 +474,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
// refresh standard list if it has changed (new caches downloaded)
if (type == CacheListType.OFFLINE && listId >= StoredList.STANDARD_LIST_ID && search != null) {
- final SearchResult newSearch = cgData.getBatchOfStoredCaches(coords, Settings.getCacheType(), listId);
+ final SearchResult newSearch = DataStore.getBatchOfStoredCaches(coords, Settings.getCacheType(), listId);
if (newSearch.getTotal() != search.getTotal()) {
refreshCurrentList();
}
@@ -530,134 +500,83 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_FILTER, 0, res.getString(R.string.caches_filter)).setIcon(R.drawable.ic_menu_filter);
-
- if (type != CacheListType.HISTORY) {
- menu.add(0, MENU_SORT, 0, res.getString(R.string.caches_sort)).setIcon(R.drawable.ic_menu_sort_alphabetically);
- }
-
- menu.add(0, MENU_SWITCH_SELECT_MODE, 0, res.getString(R.string.caches_select_mode)).setIcon(R.drawable.ic_menu_agenda);
- menu.add(0, MENU_INVERT_SELECTION, 0, res.getString(R.string.caches_select_invert)).setIcon(R.drawable.ic_menu_mark);
- if (type == CacheListType.OFFLINE) {
- final SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_OFFLINE, 0, res.getString(R.string.caches_manage)).setIcon(R.drawable.ic_menu_save);
- subMenu.add(0, MENU_DROP_CACHES, 0, res.getString(R.string.caches_drop_all)); // delete saved caches
- subMenu.add(0, MENU_DROP_CACHES_AND_LIST, 0, res.getString(R.string.caches_drop_all_and_list));
- subMenu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.cache_offline_refresh)); // download details for all caches
- subMenu.add(0, MENU_MOVE_TO_LIST, 0, res.getString(R.string.cache_menu_move_list));
- subMenu.add(0, MENU_DELETE_EVENTS, 0, res.getString(R.string.caches_delete_events));
- subMenu.add(0, MENU_CLEAR_OFFLINE_LOGS, 0, res.getString(R.string.caches_clear_offlinelogs));
-
- //TODO: add submenu/AlertDialog and use R.string.gpx_import_title
- subMenu.add(0, MENU_IMPORT_GPX, 0, res.getString(R.string.gpx_import_title));
- if (Settings.getWebDeviceCode() != null) {
- subMenu.add(0, MENU_IMPORT_WEB, 0, res.getString(R.string.web_import_title));
- }
-
- subMenu.add(0, MENU_EXPORT, 0, res.getString(R.string.export)); // export caches
- } else {
- if (type == CacheListType.HISTORY) {
- final SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_HISTORY, 0, res.getString(R.string.caches_manage)).setIcon(R.drawable.ic_menu_save);
- subMenu.add(0, MENU_EXPORT, 0, res.getString(R.string.export)); // export caches
- subMenu.add(0, MENU_REMOVE_FROM_HISTORY, 0, res.getString(R.string.cache_clear_history)); // remove from history
- subMenu.add(0, MENU_CLEAR_OFFLINE_LOGS, 0, res.getString(R.string.caches_clear_offlinelogs));
- menu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.cache_offline_refresh)).setIcon(R.drawable.ic_menu_set_as);
- } else {
- menu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.caches_store_offline)).setIcon(R.drawable.ic_menu_set_as); // download details for all caches
- }
- }
+ getMenuInflater().inflate(R.menu.cache_list_options, menu);
- navigationMenu = CacheListAppFactory.addMenuItems(menu, this, res);
-
- if (type == CacheListType.OFFLINE) {
- final SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_LISTS, 0, res.getString(R.string.list_menu)).setIcon(R.drawable.ic_menu_more);
- subMenu.add(0, MENU_CREATE_LIST, 0, res.getString(R.string.list_menu_create));
- subMenu.add(0, MENU_DROP_LIST, 0, res.getString(R.string.list_menu_drop));
- subMenu.add(0, MENU_RENAME_LIST, 0, res.getString(R.string.list_menu_rename));
- subMenu.add(0, MENU_SWITCH_LIST, 0, res.getString(R.string.list_menu_change));
- }
+ CacheListAppFactory.addMenuItems(menu, this, res);
return true;
}
private static void setVisible(final Menu menu, final int itemId, final boolean visible) {
- final MenuItem item = menu.findItem(itemId);
- if (item != null) {
- item.setVisible(visible);
- }
+ menu.findItem(itemId).setVisible(visible);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
+ final boolean isHistory = type == CacheListType.HISTORY;
+ final boolean isOffline = type == CacheListType.OFFLINE;
+ final boolean isEmpty = cacheList.isEmpty();
+ final boolean isConcrete = isConcreteList();
+
try {
if (adapter.isSelectMode()) {
- menu.findItem(MENU_SWITCH_SELECT_MODE).setTitle(res.getString(R.string.caches_select_mode_exit))
+ menu.findItem(R.id.menu_switch_select_mode).setTitle(res.getString(R.string.caches_select_mode_exit))
.setIcon(R.drawable.ic_menu_clear_playlist);
- menu.findItem(MENU_INVERT_SELECTION).setVisible(true);
} else {
- menu.findItem(MENU_SWITCH_SELECT_MODE).setTitle(res.getString(R.string.caches_select_mode))
+ menu.findItem(R.id.menu_switch_select_mode).setTitle(res.getString(R.string.caches_select_mode))
.setIcon(R.drawable.ic_menu_agenda);
- menu.findItem(MENU_INVERT_SELECTION).setVisible(false);
}
-
- final boolean isEmpty = cacheList.isEmpty();
- final boolean isConcrete = isConcreteList();
-
- setVisible(menu, MENU_SWITCH_SELECT_MODE, !isEmpty);
- setVisible(menu, SUBMENU_MANAGE_HISTORY, !isEmpty);
- setVisible(menu, SUBMENU_SHOW_MAP, !isEmpty);
- setVisible(menu, MENU_SORT, !isEmpty);
- setVisible(menu, MENU_REFRESH_STORED, !isEmpty && (isConcrete || type != CacheListType.OFFLINE));
- setVisible(menu, MENU_DROP_CACHES, !isEmpty);
- setVisible(menu, MENU_DROP_CACHES_AND_LIST, isConcrete && !isEmpty);
- setVisible(menu, MENU_DELETE_EVENTS, isConcrete && !isEmpty && containsEvents());
- setVisible(menu, MENU_MOVE_TO_LIST, !isEmpty);
- setVisible(menu, MENU_EXPORT, !isEmpty);
- setVisible(menu, MENU_REMOVE_FROM_HISTORY, !isEmpty);
- setVisible(menu, MENU_CLEAR_OFFLINE_LOGS, !isEmpty && containsOfflineLogs());
-
- if (navigationMenu != null) {
- navigationMenu.setVisible(!isEmpty);
+ menu.findItem(R.id.menu_invert_selection).setVisible(adapter.isSelectMode());
+
+
+ setVisible(menu, R.id.menu_switch_select_mode, !isEmpty);
+ setVisible(menu, R.id.submenu_manage, (isHistory && !isEmpty) || isOffline);
+ setVisible(menu, R.id.submenu_manage_lists, isOffline);
+
+ setVisible(menu, R.id.menu_sort, !isEmpty && !isHistory);
+ setVisible(menu, R.id.menu_refresh_stored, !isEmpty && (isConcrete || type != CacheListType.OFFLINE));
+ setVisible(menu, R.id.menu_drop_caches, !isEmpty && isOffline);
+ setVisible(menu, R.id.menu_drop_caches_and_list, isConcrete && !isEmpty && isOffline);
+ setVisible(menu, R.id.menu_delete_events, isConcrete && !isEmpty && containsEvents());
+ setVisible(menu, R.id.menu_move_to_list, isOffline && !isEmpty);
+ setVisible(menu, R.id.menu_export, !isEmpty && (isHistory || isOffline));
+ setVisible(menu, R.id.menu_remove_from_history, !isEmpty && isHistory);
+ setVisible(menu, R.id.menu_clear_offline_logs, !isEmpty && containsOfflineLogs() && (isHistory || isOffline));
+ setVisible(menu, R.id.menu_import_web, isOffline && Settings.getWebDeviceCode() != null);
+ setVisible(menu, R.id.menu_import_gpx, isOffline);
+ setVisible(menu, R.id.menu_refresh_stored_top, !isOffline && !isEmpty);
+
+ if (!isOffline && !isHistory) {
+ menu.findItem(R.id.menu_refresh_stored_top).setTitle(R.string.caches_store_offline);
}
final boolean hasSelection = adapter != null && adapter.getCheckedCount() > 0;
final boolean isNonDefaultList = isConcrete && listId != StoredList.STANDARD_LIST_ID;
- if (type == CacheListType.OFFLINE || type == CacheListType.HISTORY) { // only offline list
- setMenuItemLabel(menu, MENU_DROP_CACHES, R.string.caches_drop_selected, R.string.caches_drop_all);
- setMenuItemLabel(menu, MENU_REFRESH_STORED, R.string.caches_refresh_selected, R.string.caches_refresh_all);
- setMenuItemLabel(menu, MENU_MOVE_TO_LIST, R.string.caches_move_selected, R.string.caches_move_all);
+ if (isOffline || type == CacheListType.HISTORY) { // only offline list
+ setMenuItemLabel(menu, R.id.menu_drop_caches, R.string.caches_drop_selected, R.string.caches_drop_all);
+ setMenuItemLabel(menu, R.id.menu_refresh_stored, R.string.caches_refresh_selected, R.string.caches_refresh_all);
+ setMenuItemLabel(menu, R.id.menu_move_to_list, R.string.caches_move_selected, R.string.caches_move_all);
} else { // search and global list (all other than offline and history)
- setMenuItemLabel(menu, MENU_REFRESH_STORED, R.string.caches_store_selected, R.string.caches_store_offline);
- }
- if (type == CacheListType.OFFLINE) {
- menu.findItem(MENU_DROP_CACHES_AND_LIST).setVisible(!hasSelection && isNonDefaultList && !adapter.isFiltered());
+ setMenuItemLabel(menu, R.id.menu_refresh_stored, R.string.caches_store_selected, R.string.caches_store_offline);
}
- MenuItem item = menu.findItem(MENU_DROP_LIST);
- if (item != null) {
- item.setVisible(isNonDefaultList);
- }
- item = menu.findItem(MENU_RENAME_LIST);
- if (item != null) {
- item.setVisible(isNonDefaultList);
- }
+ // make combined list deletion only possible when there are no filters, as that leads to confusion for the hidden caches
+ menu.findItem(R.id.menu_drop_caches_and_list).setVisible(isOffline && !hasSelection && isNonDefaultList && !adapter.isFiltered() && Settings.getCacheType() == CacheType.ALL);
- final boolean multipleLists = cgData.getLists().size() >= 2;
- item = menu.findItem(MENU_SWITCH_LIST);
- if (item != null) {
- item.setVisible(multipleLists);
- }
- item = menu.findItem(MENU_MOVE_TO_LIST);
- if (item != null) {
- item.setVisible(!isEmpty);
- }
+ menu.findItem(R.id.menu_drop_list).setVisible(isNonDefaultList);
+ menu.findItem(R.id.menu_rename_list).setVisible(isNonDefaultList);
- setMenuItemLabel(menu, MENU_REMOVE_FROM_HISTORY, R.string.cache_remove_from_history, R.string.cache_clear_history);
- setMenuItemLabel(menu, MENU_EXPORT, R.string.export, R.string.export);
+ final boolean multipleLists = DataStore.getLists().size() >= 2;
+ menu.findItem(R.id.menu_switch_list).setVisible(multipleLists);
+ menu.findItem(R.id.menu_move_to_list).setVisible(!isEmpty);
+
+ setMenuItemLabel(menu, R.id.menu_remove_from_history, R.string.cache_remove_from_history, R.string.cache_clear_history);
+ setMenuItemLabel(menu, R.id.menu_export, R.string.export, R.string.export);
} catch (final RuntimeException e) {
- Log.e("cgeocaches.onPrepareOptionsMenu", e);
+ Log.e("CacheListActivity.onPrepareOptionsMenu", e);
}
return true;
@@ -696,51 +615,51 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- final int itemId = item.getItemId();
- switch (itemId) {
- case MENU_SWITCH_SELECT_MODE:
+ switch (item.getItemId()) {
+ case R.id.menu_switch_select_mode:
adapter.switchSelectMode();
invalidateOptionsMenuCompatible();
return true;
- case MENU_REFRESH_STORED:
+ case R.id.menu_refresh_stored_top:
+ case R.id.menu_refresh_stored:
refreshStored(adapter.getCheckedOrAllCaches());
invalidateOptionsMenuCompatible();
return true;
- case MENU_DROP_CACHES:
+ case R.id.menu_drop_caches:
dropStored(false);
invalidateOptionsMenuCompatible();
return false;
- case MENU_DROP_CACHES_AND_LIST:
+ case R.id.menu_drop_caches_and_list:
dropStored(true);
invalidateOptionsMenuCompatible();
return true;
- case MENU_IMPORT_GPX:
+ case R.id.menu_import_gpx:
importGpx();
invalidateOptionsMenuCompatible();
return false;
- case MENU_CREATE_LIST:
+ case R.id.menu_create_list:
new StoredList.UserInterface(this).promptForListCreation(getListSwitchingRunnable(), newListName);
invalidateOptionsMenuCompatible();
return false;
- case MENU_DROP_LIST:
+ case R.id.menu_drop_list:
removeList(true);
invalidateOptionsMenuCompatible();
return false;
- case MENU_RENAME_LIST:
+ case R.id.menu_rename_list:
renameList();
return false;
- case MENU_INVERT_SELECTION:
+ case R.id.menu_invert_selection:
adapter.invertSelection();
invalidateOptionsMenuCompatible();
return false;
- case MENU_SWITCH_LIST:
- selectList(null);
+ case R.id.menu_switch_list:
+ selectList();
invalidateOptionsMenuCompatible();
return false;
- case MENU_FILTER:
+ case R.id.menu_filter:
showFilterMenu(null);
return true;
- case MENU_SORT:
+ case R.id.menu_sort:
final CacheComparator oldComparator = adapter.getCacheComparator();
new ComparatorUserInterface(this).selectComparator(oldComparator, new RunnableWithArgument<CacheComparator>() {
@Override
@@ -757,25 +676,25 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
});
return true;
- case MENU_IMPORT_WEB:
+ case R.id.menu_import_web:
importWeb();
return false;
- case MENU_EXPORT:
+ case R.id.menu_export:
ExportFactory.showExportMenu(adapter.getCheckedOrAllCaches(), this);
return false;
- case MENU_REMOVE_FROM_HISTORY:
+ case R.id.menu_remove_from_history:
removeFromHistoryCheck();
invalidateOptionsMenuCompatible();
return false;
- case MENU_MOVE_TO_LIST:
+ case R.id.menu_move_to_list:
moveCachesToOtherList();
invalidateOptionsMenuCompatible();
return true;
- case MENU_DELETE_EVENTS:
+ case R.id.menu_delete_events:
deletePastEvents();
invalidateOptionsMenuCompatible();
return true;
- case MENU_CLEAR_OFFLINE_LOGS:
+ case R.id.menu_clear_offline_logs:
clearOfflineLogs();
invalidateOptionsMenuCompatible();
return true;
@@ -833,7 +752,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
try {
adapterInfo = (AdapterContextMenuInfo) info;
} catch (final Exception e) {
- Log.w("cgeocaches.onCreateContextMenu", e);
+ Log.w("CacheListActivity.onCreateContextMenu", e);
}
if (adapterInfo == null || adapterInfo.position >= adapter.getCount()) {
@@ -845,21 +764,21 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
contextMenuGeocode = cache.getGeocode();
- if (cache.getCoords() != null) {
- menu.add(0, MENU_DEFAULT_NAVIGATION, 0, NavigationAppFactory.getDefaultNavigationApplication().getName());
- menu.add(1, MENU_NAVIGATION, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode);
- LoggingUI.addMenuItems(this, menu, cache);
- menu.add(0, MENU_CACHE_DETAILS, 0, res.getString(R.string.cache_menu_details));
- }
- if (cache.isOffline()) {
- menu.add(0, MENU_DROP_CACHE, 0, res.getString(R.string.cache_offline_drop));
- menu.add(0, MENU_MOVE_TO_LIST, 0, res.getString(R.string.cache_menu_move_list));
- menu.add(0, MENU_EXPORT, 0, res.getString(R.string.export));
- menu.add(0, MENU_REFRESH, 0, res.getString(R.string.cache_menu_refresh));
- }
- else {
- menu.add(0, MENU_STORE_CACHE, 0, res.getString(R.string.cache_offline_store));
- }
+ getMenuInflater().inflate(R.menu.cache_list_context, menu);
+
+ menu.findItem(R.id.menu_default_navigation).setTitle(NavigationAppFactory.getDefaultNavigationApplication().getName());
+ final boolean hasCoords = cache.getCoords() != null;
+ menu.findItem(R.id.menu_default_navigation).setVisible(hasCoords);
+ menu.findItem(R.id.menu_navigate).setVisible(hasCoords);
+ menu.findItem(R.id.menu_cache_details).setVisible(hasCoords);
+ final boolean isOffline = cache.isOffline();
+ menu.findItem(R.id.menu_drop_cache).setVisible(isOffline);
+ menu.findItem(R.id.menu_move_to_list).setVisible(isOffline);
+ menu.findItem(R.id.menu_export).setVisible(isOffline);
+ menu.findItem(R.id.menu_refresh).setVisible(isOffline);
+ menu.findItem(R.id.menu_store_cache).setVisible(!isOffline);
+
+ LoggingUI.onPrepareOptionsMenu(menu, cache);
}
private void moveCachesToOtherList() {
@@ -867,7 +786,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
@Override
public void run(Integer newListId) {
- cgData.moveToList(adapter.getCheckedOrAllCaches(), newListId);
+ DataStore.moveToList(adapter.getCheckedOrAllCaches(), newListId);
adapter.setSelectMode(false);
refreshCurrentList();
@@ -890,7 +809,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
try {
adapterInfo = (AdapterContextMenuInfo) info;
} catch (final Exception e) {
- Log.w("cgeocaches.onContextItemSelected", e);
+ Log.w("CacheListActivity.onContextItemSelected", e);
}
final Geocache cache = adapterInfo != null ? getCacheFromAdapter(adapterInfo) : null;
@@ -900,18 +819,17 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
return true;
}
- final int id = item.getItemId();
- switch (id) {
- case MENU_DEFAULT_NAVIGATION:
+ switch (item.getItemId()) {
+ case R.id.menu_default_navigation:
NavigationAppFactory.startDefaultNavigationApplication(1, this, cache);
break;
- case MENU_NAVIGATION:
+ case R.id.menu_navigate:
NavigationAppFactory.showNavigationMenu(this, cache, null, null);
break;
- case MENU_CACHE_DETAILS:
+ case R.id.menu_cache_details:
CacheDetailActivity.startActivity(this, cache.getGeocode(), cache.getName());
break;
- case MENU_DROP_CACHE:
+ case R.id.menu_drop_cache:
cache.drop(new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -920,22 +838,22 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
});
break;
- case MENU_MOVE_TO_LIST:
+ case R.id.menu_move_to_list:
new StoredList.UserInterface(this).promptForListSelection(R.string.cache_menu_move_list, new RunnableWithArgument<Integer>() {
@Override
public void run(Integer newListId) {
- cgData.moveToList(Collections.singletonList(cache), newListId);
+ DataStore.moveToList(Collections.singletonList(cache), newListId);
adapter.setSelectMode(false);
refreshCurrentList();
}
}, true, listId, newListName);
break;
- case MENU_STORE_CACHE:
- case MENU_REFRESH:
+ case R.id.menu_store_cache:
+ case R.id.menu_refresh:
refreshStored(Collections.singletonList(cache));
break;
- case MENU_EXPORT:
+ case R.id.menu_export:
ExportFactory.showExportMenu(Collections.singletonList(cache), this);
return false;
default:
@@ -1201,7 +1119,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
final private Handler handler;
final private int listIdLD;
private volatile boolean needToStop = false;
- private long last = 0L;
final private List<Geocache> caches;
public LoadDetailsThread(Handler handlerIn, List<Geocache> caches, int listId) {
@@ -1219,21 +1136,14 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
@Override
public void run() {
removeGeoAndDir();
-
- final List<Geocache> cachesWithStaticMaps = new ArrayList<Geocache>(this.caches.size());
- for (final Geocache cache : this.caches) {
- if (Settings.isStoreOfflineMaps() && cache.hasStaticMap()) {
- cachesWithStaticMaps.add(cache);
- continue;
- }
- if (!refreshCache(cache)) {
- // in case of interruption avoid the second loop
- cachesWithStaticMaps.clear();
- break;
- }
- }
-
- for (final Geocache cache : cachesWithStaticMaps) {
+ // 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() ?
+ ListUtils.union(ListUtils.selectRejected(caches, Geocache.hasStaticMap),
+ ListUtils.select(caches, Geocache.hasStaticMap)) :
+ caches;
+
+ for (final Geocache cache : allCaches) {
if (!refreshCache(cache)) {
break;
}
@@ -1256,38 +1166,16 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
if (needToStop) {
throw new InterruptedException("Stopped storing process.");
}
-
- if ((System.currentTimeMillis() - last) < 1500) {
- try {
- int delay = 1000 + ((Double) (Math.random() * 1000)).intValue() - (int) (System.currentTimeMillis() - last);
- if (delay < 0) {
- delay = 500;
- }
-
- Log.i("Waiting for next cache " + delay + " ms");
- } catch (final Exception e) {
- Log.e("cgeocaches.LoadDetailsThread.sleep", e);
- }
- }
-
- if (needToStop) {
- throw new InterruptedException("Stopped storing process.");
- }
-
detailProgress++;
cache.refresh(listIdLD, null);
-
handler.sendEmptyMessage(cacheList.indexOf(cache));
-
- yield();
} catch (final InterruptedException e) {
Log.i(e.getMessage());
return false;
} catch (final Exception e) {
- Log.e("cgeocaches.LoadDetailsThread", e);
+ Log.e("CacheListActivity.LoadDetailsThread", e);
}
- last = System.currentTimeMillis();
return true;
}
}
@@ -1327,7 +1215,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
if (responseFromWeb != null && responseFromWeb.getStatusLine().getStatusCode() == 200) {
final String response = Network.getResponseData(responseFromWeb);
- if (response.length() > 2) {
+ if (response != null && response.length() > 2) {
delay = 1;
handler.sendMessage(handler.obtainMessage(1, response));
yield();
@@ -1364,7 +1252,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
times = 0;
}
} catch (final InterruptedException e) {
- Log.e("cgeocaches.LoadFromWebThread.sleep", e);
+ Log.e("CacheListActivity.LoadFromWebThread.sleep", e);
}
}
@@ -1379,14 +1267,14 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
private final boolean removeListAfterwards;
public DropDetailsTask(boolean removeListAfterwards) {
- super(cgeocaches.this, null, res.getString(R.string.caches_drop_progress), true);
+ super(CacheListActivity.this, null, res.getString(R.string.caches_drop_progress), true);
this.removeListAfterwards = removeListAfterwards;
}
@Override
protected Void doInBackgroundInternal(Geocache[] caches) {
removeGeoAndDir();
- cgData.markDropped(Arrays.asList(caches));
+ DataStore.markDropped(Arrays.asList(caches));
startGeoAndDir();
return null;
}
@@ -1417,7 +1305,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
@Override
public void run() {
- cgData.clearLogsOffline(selected);
+ DataStore.clearLogsOffline(selected);
handler.sendEmptyMessage(MSG_DONE);
}
}
@@ -1430,7 +1318,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
showFooterLoadingCaches();
listFooter.setOnClickListener(null);
- getSupportLoaderManager().restartLoader(CacheListLoaderType.NEXT_PAGE.ordinal(), null, cgeocaches.this);
+ getSupportLoaderManager().restartLoader(CacheListLoaderType.NEXT_PAGE.ordinal(), null, CacheListActivity.this);
}
}
@@ -1443,17 +1331,14 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
}
- /**
- * @param view
- * unused here but needed since this method is referenced from XML layout
- */
- public void selectList(View view) {
- if (type != CacheListType.OFFLINE) {
+ public void selectList() {
+ if (!type.canSwitch) {
return;
}
new StoredList.UserInterface(this).promptForListSelection(R.string.list_title, getListSwitchingRunnable());
}
+ @NonNull
private RunnableWithArgument<Integer> getListSwitchingRunnable() {
return new RunnableWithArgument<Integer>() {
@@ -1469,7 +1354,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
return;
}
- final StoredList list = cgData.getList(id);
+ final StoredList list = DataStore.getList(id);
if (list == null) {
return;
}
@@ -1481,7 +1366,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
showProgress(true);
showFooterLoadingCaches();
- cgData.moveToList(adapter.getCheckedCaches(), listId);
+ DataStore.moveToList(adapter.getCheckedCaches(), listId);
currentLoader = (OfflineGeocacheListLoader) getSupportLoaderManager().initLoader(CacheListType.OFFLINE.ordinal(), new Bundle(), this);
currentLoader.reset();
@@ -1504,7 +1389,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
private void removeListInternal() {
- if (cgData.removeList(listId)) {
+ if (DataStore.removeList(listId)) {
showToast(res.getString(R.string.list_dialog_remove_ok));
switchListById(StoredList.STANDARD_LIST_ID);
} else {
@@ -1577,7 +1462,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
public static void startActivityOffline(final Context context) {
- final Intent cachesIntent = new Intent(context, cgeocaches.class);
+ final Intent cachesIntent = new Intent(context, CacheListActivity.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.OFFLINE);
context.startActivity(cachesIntent);
}
@@ -1586,7 +1471,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
if (!isValidUsername(context, userName)) {
return;
}
- final Intent cachesIntent = new Intent(context, cgeocaches.class);
+ final Intent cachesIntent = new Intent(context, CacheListActivity.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.OWNER);
cachesIntent.putExtra(Intents.EXTRA_USERNAME, userName);
context.startActivity(cachesIntent);
@@ -1594,7 +1479,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
private static boolean isValidUsername(AbstractActivity context, String username) {
if (StringUtils.isBlank(username)) {
- context.showToast(cgeoapplication.getInstance().getString(R.string.warn_no_username));
+ context.showToast(CgeoApplication.getInstance().getString(R.string.warn_no_username));
return false;
}
return true;
@@ -1604,7 +1489,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
if (!isValidUsername(context, userName)) {
return;
}
- final Intent cachesIntent = new Intent(context, cgeocaches.class);
+ final Intent cachesIntent = new Intent(context, CacheListActivity.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.USERNAME);
cachesIntent.putExtra(Intents.EXTRA_USERNAME, userName);
context.startActivity(cachesIntent);
@@ -1630,20 +1515,20 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
if (!isValidCoords(context, coordsNow)) {
return;
}
- final Intent cachesIntent = new Intent(context, cgeocaches.class);
+ final Intent cachesIntent = new Intent(context, CacheListActivity.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.NEAREST);
cachesIntent.putExtra(Intents.EXTRA_COORDS, coordsNow);
context.startActivity(cachesIntent);
}
public static void startActivityHistory(Context context) {
- final Intent cachesIntent = new Intent(context, cgeocaches.class);
+ final Intent cachesIntent = new Intent(context, CacheListActivity.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.HISTORY);
context.startActivity(cachesIntent);
}
public static void startActivityAddress(final Context context, final Geopoint coords, final String address) {
- final Intent addressIntent = new Intent(context, cgeocaches.class);
+ final Intent addressIntent = new Intent(context, CacheListActivity.class);
addressIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.ADDRESS);
addressIntent.putExtra(Intents.EXTRA_COORDS, coords);
addressIntent.putExtra(Intents.EXTRA_ADDRESS, address);
@@ -1654,7 +1539,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
if (!isValidCoords(context, coords)) {
return;
}
- final Intent cachesIntent = new Intent(context, cgeocaches.class);
+ final Intent cachesIntent = new Intent(context, CacheListActivity.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.COORDINATE);
cachesIntent.putExtra(Intents.EXTRA_COORDS, coords);
context.startActivity(cachesIntent);
@@ -1662,7 +1547,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
private static boolean isValidCoords(AbstractActivity context, Geopoint coords) {
if (coords == null) {
- context.showToast(cgeoapplication.getInstance().getString(R.string.warn_no_coordinates));
+ context.showToast(CgeoApplication.getInstance().getString(R.string.warn_no_coordinates));
return false;
}
return true;
@@ -1670,34 +1555,35 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
public static void startActivityKeyword(final AbstractActivity context, final String keyword) {
if (keyword == null) {
- context.showToast(cgeoapplication.getInstance().getString(R.string.warn_no_keyword));
+ context.showToast(CgeoApplication.getInstance().getString(R.string.warn_no_keyword));
return;
}
- final Intent cachesIntent = new Intent(context, cgeocaches.class);
+ final Intent cachesIntent = new Intent(context, CacheListActivity.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.KEYWORD);
cachesIntent.putExtra(Intents.EXTRA_KEYWORD, keyword);
context.startActivity(cachesIntent);
}
- public static void startActivityPocket(final AbstractActivity context, final String guid, final String name) {
+ public static void startActivityMap(final Context context, final SearchResult search) {
+ final Intent cachesIntent = new Intent(context, CacheListActivity.class);
+ cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.MAP);
+ cachesIntent.putExtra(Intents.EXTRA_SEARCH, search);
+ context.startActivity(cachesIntent);
+ }
+
+ public static void startActivityPocket(final AbstractActivity context, final @NonNull PocketQueryList pq) {
+ final String guid = pq.getGuid();
if (guid == null) {
- context.showToast(cgeoapplication.getInstance().getString(R.string.warn_pocket_query_select));
+ context.showToast(CgeoApplication.getInstance().getString(R.string.warn_pocket_query_select));
return;
}
- final Intent cachesIntent = new Intent(context, cgeocaches.class);
+ final Intent cachesIntent = new Intent(context, CacheListActivity.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.POCKET);
- cachesIntent.putExtra(Intents.EXTRA_NAME, name);
+ cachesIntent.putExtra(Intents.EXTRA_NAME, pq.getName());
cachesIntent.putExtra(Intents.EXTRA_POCKET_GUID, guid);
context.startActivity(cachesIntent);
}
- public static void startActivityMap(final Context context, final SearchResult search) {
- final Intent cachesIntent = new Intent(context, cgeocaches.class);
- cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.MAP);
- cachesIntent.putExtra(Intents.EXTRA_SEARCH, search);
- context.startActivity(cachesIntent);
- }
-
// Loaders
@Override
@@ -1714,7 +1600,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
listId = StoredList.STANDARD_LIST_ID;
title = res.getString(R.string.stored_caches_button);
} else {
- final StoredList list = cgData.getList(listId);
+ final StoredList list = DataStore.getList(listId);
// list.id may be different if listId was not valid
listId = list.id;
title = list.title;
@@ -1784,6 +1670,8 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
title = pocket_name;
loader = new PocketGeocacheListLoader(app, guid);
break;
+ default:
+ throw new IllegalStateException();
}
setTitle(title);
showProgress(true);
diff --git a/main/src/cgeo/geocaching/CacheMenuHandler.java b/main/src/cgeo/geocaching/CacheMenuHandler.java
new file mode 100644
index 0000000..9326a73
--- /dev/null
+++ b/main/src/cgeo/geocaching/CacheMenuHandler.java
@@ -0,0 +1,126 @@
+package cgeo.geocaching;
+
+import cgeo.calendar.ICalendar;
+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.utils.ProcessUtils;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.view.Menu;
+import android.view.MenuItem;
+
+/**
+ * Shared menu handling for all activities having menu items related to a cache.
+ *
+ */
+public class CacheMenuHandler extends AbstractUIFactory {
+
+ /**
+ * Methods to be implemented by the activity to react to the cache menu selections.
+ *
+ */
+ protected interface ActivityInterface {
+ public void navigateTo();
+
+ public void showNavigationMenu();
+
+ public void cachesAround();
+
+ }
+
+ public static boolean onMenuItemSelected(MenuItem item, CacheMenuHandler.ActivityInterface activityInterface, Geocache cache) {
+ assert activityInterface instanceof Activity;
+ final Activity activity = (Activity) activityInterface;
+ switch (item.getItemId()) {
+ case R.id.menu_default_navigation:
+ activityInterface.navigateTo();
+ return true;
+ case R.id.menu_navigate:
+ activityInterface.showNavigationMenu();
+ return true;
+ case R.id.menu_caches_around:
+ activityInterface.cachesAround();
+ return true;
+ case R.id.menu_show_in_browser:
+ cache.openInBrowser(activity);
+ return true;
+ case R.id.menu_share:
+ cache.shareCache(activity, res);
+ return true;
+ case R.id.menu_calendar:
+ addToCalendarWithIntent(activity, cache);
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static void onPrepareOptionsMenu(final Menu menu, final Geocache cache) {
+ final boolean hasCoords = cache.getCoords() != null;
+ menu.findItem(R.id.menu_default_navigation).setVisible(hasCoords);
+ menu.findItem(R.id.menu_navigate).setVisible(hasCoords);
+ menu.findItem(R.id.menu_caches_around).setVisible(hasCoords && cache.supportsCachesAround());
+ menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar());
+ menu.findItem(R.id.menu_show_in_browser).setVisible(cache.canOpenInBrowser());
+
+ menu.findItem(R.id.menu_default_navigation).setTitle(NavigationAppFactory.getDefaultNavigationApplication().getName());
+ }
+
+ public static void addMenuItems(Activity activity, Menu menu, Geocache cache) {
+ 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 Parameters params = new Parameters(
+ ICalendar.PARAM_NAME, cache.getName(),
+ ICalendar.PARAM_NOTE, StringUtils.defaultString(cache.getPersonalNote()),
+ ICalendar.PARAM_HIDDEN_DATE, String.valueOf(cache.getHiddenDate().getTime()),
+ 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
+ new AlertDialog.Builder(activity)
+ .setTitle(res.getString(R.string.addon_missing_title))
+ .setMessage(new StringBuilder(res.getString(R.string.helper_calendar_missing))
+ .append(' ')
+ .append(res.getString(R.string.addon_download_prompt))
+ .toString())
+ .setPositiveButton(activity.getString(android.R.string.yes), 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);
+ }
+ })
+ .setNegativeButton(activity.getString(android.R.string.no), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ })
+ .create()
+ .show();
+ }
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/CachePopup.java b/main/src/cgeo/geocaching/CachePopup.java
index 873801e..020c604 100644
--- a/main/src/cgeo/geocaching/CachePopup.java
+++ b/main/src/cgeo/geocaching/CachePopup.java
@@ -3,6 +3,7 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.CacheDetailsCreator;
@@ -70,7 +71,7 @@ public class CachePopup extends AbstractPopupActivity {
}
@Override
- protected void showNavigationMenu() {
+ public void showNavigationMenu() {
NavigationAppFactory.showNavigationMenu(this, cache, null, null);
}
@@ -215,7 +216,7 @@ public class CachePopup extends AbstractPopupActivity {
}
@Override
- protected void navigateTo() {
+ public void navigateTo() {
NavigationAppFactory.startDefaultNavigationApplication(1, this, cache);
}
diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/CgeoApplication.java
index 5a793f5..2c419cf 100644
--- a/main/src/cgeo/geocaching/cgeoapplication.java
+++ b/main/src/cgeo/geocaching/CgeoApplication.java
@@ -9,12 +9,10 @@ import android.app.Activity;
import android.app.Application;
import android.app.ProgressDialog;
import android.content.res.Resources;
-import android.os.Handler;
-import android.os.Message;
import java.util.concurrent.atomic.AtomicBoolean;
-public class cgeoapplication extends Application {
+public class CgeoApplication extends Application {
private volatile GeoDataProvider geo;
private volatile DirectionProvider dir;
@@ -22,17 +20,17 @@ public class cgeoapplication extends Application {
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;
+ private static CgeoApplication instance;
- public cgeoapplication() {
+ public CgeoApplication() {
setInstance(this);
}
- private static void setInstance(final cgeoapplication application) {
+ private static void setInstance(final CgeoApplication application) {
instance = application;
}
- public static cgeoapplication getInstance() {
+ public static CgeoApplication getInstance() {
return instance;
}
@@ -46,15 +44,15 @@ public class cgeoapplication extends Application {
@Override
public void onLowMemory() {
Log.i("Cleaning applications cache.");
- cgData.removeAllFromCache();
+ DataStore.removeAllFromCache();
}
@Override
public void onTerminate() {
Log.d("Terminating c:geoโ€ฆ");
- cgData.clean();
- cgData.closeDb();
+ DataStore.clean();
+ DataStore.closeDb();
super.onTerminate();
}
@@ -69,24 +67,21 @@ public class cgeoapplication extends Application {
final Resources res = this.getResources();
final ProgressDialog dialog = ProgressDialog.show(fromActivity, res.getString(R.string.init_dbmove_dbmove), res.getString(R.string.init_dbmove_running), true, false);
final AtomicBoolean atomic = new AtomicBoolean(false);
- Thread moveThread = new Thread() {
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- dialog.dismiss();
- boolean success = atomic.get();
- String message = success ? res.getString(R.string.init_dbmove_success) : res.getString(R.string.init_dbmove_failed);
- ActivityMixin.helpDialog(fromActivity, res.getString(R.string.init_dbmove_dbmove), message);
- }
- };
-
+ new Thread() {
@Override
public void run() {
- atomic.set(cgData.moveDatabase());
- handler.sendMessage(handler.obtainMessage());
+ atomic.set(DataStore.moveDatabase());
+ fromActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ dialog.dismiss();
+ boolean success = atomic.get();
+ String message = success ? res.getString(R.string.init_dbmove_success) : res.getString(R.string.init_dbmove_failed);
+ ActivityMixin.helpDialog(fromActivity, res.getString(R.string.init_dbmove_dbmove), message);
+ }
+ });
}
- };
- moveThread.start();
+ }.start();
}
/**
diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java
index c8579e1..a176b7d 100644
--- a/main/src/cgeo/geocaching/CompassActivity.java
+++ b/main/src/cgeo/geocaching/CompassActivity.java
@@ -4,16 +4,20 @@ import butterknife.InjectView;
import butterknife.Views;
import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.speech.SpeechService;
import cgeo.geocaching.ui.CompassView;
+import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.ui.LoggingUI;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
@@ -34,6 +38,8 @@ import java.util.List;
public class CompassActivity extends AbstractActivity {
+ private static final int COORDINATES_OFFSET = 10;
+
@InjectView(R.id.nav_type) protected TextView navType;
@InjectView(R.id.nav_accuracy) protected TextView navAccuracy;
@InjectView(R.id.nav_satellites) protected TextView navSatellites;
@@ -49,8 +55,11 @@ public class CompassActivity extends AbstractActivity {
private static final String EXTRAS_GEOCODE = "geocode";
private static final String EXTRAS_CACHE_INFO = "cacheinfo";
private static final List<IWaypoint> coordinates = new ArrayList<IWaypoint>();
- private static final int COORDINATES_OFFSET = 10;
- private static final int REQUEST_TTS_DATA_CHECK = 1;
+
+ /**
+ * Destination of the compass, or null (if the compass is used for a waypoint only).
+ */
+ private @Nullable Geocache cache = null;
private Geopoint dstCoords = null;
private float cacheHeading = 0;
private String title = null;
@@ -70,7 +79,11 @@ public class CompassActivity extends AbstractActivity {
// get parameters
Bundle extras = getIntent().getExtras();
if (extras != null) {
- title = extras.getString(EXTRAS_GEOCODE);
+ final String geocode = extras.getString(EXTRAS_GEOCODE);
+ if (StringUtils.isNotEmpty(geocode)) {
+ cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ }
+ title = geocode;
final String name = extras.getString(EXTRAS_NAME);
dstCoords = extras.getParcelable(EXTRAS_COORDS);
info = extras.getString(EXTRAS_CACHE_INFO);
@@ -105,7 +118,7 @@ public class CompassActivity extends AbstractActivity {
public void onResume() {
super.onResume();
- // sensor & geolocation manager
+ // sensor and geolocation manager
geoDirHandler.startGeoAndDir();
}
@@ -134,7 +147,7 @@ public class CompassActivity extends AbstractActivity {
setCacheInfo();
// Force a refresh of location and direction when data is available.
- final cgeoapplication app = cgeoapplication.getInstance();
+ final CgeoApplication app = CgeoApplication.getInstance();
final IGeoData geo = app.currentGeo();
if (geo != null) {
geoDirHandler.update(geo);
@@ -158,6 +171,9 @@ public class CompassActivity extends AbstractActivity {
} else {
menu.findItem(R.id.menu_select_destination).setVisible(false);
}
+ if (cache != null) {
+ LoggingUI.addMenuItems(this, menu, cache);
+ }
return true;
}
@@ -200,6 +216,9 @@ public class CompassActivity extends AbstractActivity {
SpeechService.stopService(this);
return true;
default:
+ if (LoggingUI.onMenuItemSelected(item, this, cache)) {
+ return true;
+ }
int coordinatesIndex = id - COORDINATES_OFFSET;
if (coordinatesIndex >= 0 && coordinatesIndex < coordinates.size()) {
final IWaypoint coordinate = coordinates.get(coordinatesIndex);
@@ -326,4 +345,9 @@ public class CompassActivity extends AbstractActivity {
CompassActivity.startActivity(context, geocode, displayedName, coords, coordinatesWithType, null);
}
+ public static void startActivity(final Context context, final Geocache cache) {
+ startActivity(context, cache.getGeocode(), cache.getName(), cache.getCoords(), null,
+ Formatter.formatCacheInfoShort(cache));
+ }
+
}
diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/DataStore.java
index a925597..7c19a83 100644
--- a/main/src/cgeo/geocaching/cgData.java
+++ b/main/src/cgeo/geocaching/DataStore.java
@@ -13,12 +13,15 @@ import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.files.LocalStorage;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
+import cgeo.geocaching.list.AbstractList;
+import cgeo.geocaching.list.PseudoList;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.collections.MapUtils;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
@@ -52,9 +55,9 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;
-public class cgData {
+public class DataStore {
- private cgData() {
+ private DataStore() {
// utility class
}
@@ -294,10 +297,10 @@ public class cgData {
}
try {
- final DbHelper dbHelper = new DbHelper(new DBContext(cgeoapplication.getInstance()));
+ final DbHelper dbHelper = new DbHelper(new DBContext(CgeoApplication.getInstance()));
database = dbHelper.getWritableDatabase();
} catch (Exception e) {
- Log.e("cgData.init: unable to open database for R/W", e);
+ Log.e("DataStore.init: unable to open database for R/W", e);
}
}
@@ -757,7 +760,7 @@ public class cgData {
// to NPE traces.
final int staleHistorySearches = db.delete(dbTableSearchDestionationHistory, "date is null", null);
if (staleHistorySearches > 0) {
- Log.w(String.format(Locale.getDefault(), "cgData.dbHelper.onOpen: removed %d bad search history entries", staleHistorySearches));
+ Log.w(String.format(Locale.getDefault(), "DataStore.dbHelper.onOpen: removed %d bad search history entries", staleHistorySearches));
}
}
@@ -860,7 +863,7 @@ public class cgData {
return getFirstColumn(cursor);
} catch (final Exception e) {
- Log.e("cgData.allDetailedThere", e);
+ Log.e("DataStore.allDetailedThere", e);
return new String[0];
}
}
@@ -907,7 +910,7 @@ public class cgData {
cursor.close();
} catch (final Exception e) {
- Log.e("cgData.isThere", e);
+ Log.e("DataStore.isThere", e);
}
if (detailed && dataDetailed == 0) {
@@ -954,7 +957,7 @@ public class cgData {
} catch (SQLiteDoneException e) {
// Do nothing, it only means we have no information on the cache
} catch (Exception e) {
- Log.e("cgData.isOffline", e);
+ Log.e("DataStore.isOffline", e);
}
return false;
@@ -975,7 +978,7 @@ public class cgData {
} catch (SQLiteDoneException e) {
// Do nothing, it only means we have no information on the cache
} catch (Exception e) {
- Log.e("cgData.getGeocodeForGuid", e);
+ Log.e("DataStore.getGeocodeForGuid", e);
}
return null;
@@ -996,7 +999,7 @@ public class cgData {
} catch (SQLiteDoneException e) {
// Do nothing, it only means we have no information on the cache
} catch (Exception e) {
- Log.e("cgData.getCacheidForGeocode", e);
+ Log.e("DataStore.getCacheidForGeocode", e);
}
return null;
@@ -1497,7 +1500,7 @@ public class cgData {
}
if (remaining.size() >= 1) {
- Log.d("cgData.loadCaches(" + remaining.toString() + ") returned no results");
+ Log.d("DataStore.loadCaches(" + remaining.toString() + ") returned no results");
}
return result;
}
@@ -1528,7 +1531,7 @@ public class cgData {
}
query.append(" WHERE ").append(dbTableCaches).append('.');
- query.append(cgData.whereGeocodeIn(geocodes));
+ query.append(DataStore.whereGeocodeIn(geocodes));
Cursor cursor = database.rawQuery(query.toString(), null);
try {
@@ -1536,7 +1539,7 @@ public class cgData {
int logIndex = -1;
while (cursor.moveToNext()) {
- Geocache cache = cgData.createCacheFromDatabaseContent(cursor);
+ Geocache cache = DataStore.createCacheFromDatabaseContent(cursor);
if (loadFlags.contains(LoadFlag.LOAD_ATTRIBUTES)) {
cache.setAttributes(loadAttributes(cache.getGeocode()));
@@ -1717,7 +1720,7 @@ public class cgData {
null,
"1");
- Log.d("cgData.loadWaypoint(" + id + ")");
+ Log.d("DataStore.loadWaypoint(" + id + ")");
final Waypoint waypoint = cursor.moveToFirst() ? createWaypointFromDatabaseContent(cursor) : null;
@@ -2019,7 +2022,7 @@ public class cgData {
reasonIndex = 1;
}
String listKey;
- if (list == StoredList.ALL_LIST_ID) {
+ if (list == PseudoList.ALL_LIST.id) {
sql.append(" and reason > 0");
listKey = "all_list";
} else {
@@ -2033,12 +2036,12 @@ public class cgData {
if (cacheType != CacheType.ALL) {
compiledStmnt.bindString(1, cacheType.id);
}
- if (list != StoredList.ALL_LIST_ID) {
+ if (list != PseudoList.ALL_LIST.id) {
compiledStmnt.bindLong(reasonIndex, list);
}
return (int) compiledStmnt.simpleQueryForLong();
} catch (Exception e) {
- Log.e("cgData.loadAllStoredCachesCount", e);
+ Log.e("DataStore.loadAllStoredCachesCount", e);
}
return 0;
@@ -2050,7 +2053,7 @@ public class cgData {
try {
return (int) PreparedStatements.getCountHistoryCaches().simpleQueryForLong();
} catch (Exception e) {
- Log.e("cgData.getAllHistoricCachesCount", e);
+ Log.e("DataStore.getAllHistoricCachesCount", e);
}
return 0;
@@ -2076,7 +2079,7 @@ public class cgData {
final StringBuilder selection = new StringBuilder();
selection.append("reason ");
- selection.append(listId != StoredList.ALL_LIST_ID ? "=" + Math.max(listId, 1) : ">= " + StoredList.STANDARD_LIST_ID);
+ selection.append(listId != PseudoList.ALL_LIST.id ? "=" + Math.max(listId, 1) : ">= " + StoredList.STANDARD_LIST_ID);
selection.append(" and detailed = 1 ");
String[] selectionArgs = null;
@@ -2115,7 +2118,7 @@ public class cgData {
cursor.close();
} catch (final Exception e) {
- Log.e("cgData.loadBatchOfStoredGeocodes", e);
+ Log.e("DataStore.loadBatchOfStoredGeocodes", e);
}
return geocodes;
@@ -2152,7 +2155,7 @@ public class cgData {
}
cursor.close();
} catch (Exception e) {
- Log.e("cgData.loadBatchOfHistoricGeocodes", e);
+ Log.e("DataStore.loadBatchOfHistoricGeocodes", e);
}
return geocodes;
@@ -2222,7 +2225,7 @@ public class cgData {
cursor.close();
} catch (final Exception e) {
- Log.e("cgData.loadInViewport", e);
+ Log.e("DataStore.loadInViewport", e);
}
return new SearchResult(geocodes);
@@ -2286,7 +2289,7 @@ public class cgData {
removeCaches(geocodes, LoadFlags.REMOVE_ALL);
}
} catch (final Exception e) {
- Log.w("cgData.clean", e);
+ Log.w("DataStore.clean", e);
}
Log.d("Database clean: finished");
@@ -2357,11 +2360,11 @@ public class cgData {
public static boolean saveLogOffline(String geocode, Date date, LogType type, String log) {
if (StringUtils.isBlank(geocode)) {
- Log.e("cgData.saveLogOffline: cannot log a blank geocode");
+ Log.e("DataStore.saveLogOffline: cannot log a blank geocode");
return false;
}
if (LogType.UNKNOWN == type && StringUtils.isBlank(log)) {
- Log.e("cgData.saveLogOffline: cannot log an unknown log type and no message");
+ Log.e("DataStore.saveLogOffline: cannot log an unknown log type and no message");
return false;
}
@@ -2452,7 +2455,7 @@ public class cgData {
return logCount.simpleQueryForLong() > 0;
}
} catch (Exception e) {
- Log.e("cgData.hasLogOffline", e);
+ Log.e("DataStore.hasLogOffline", e);
}
return false;
@@ -2480,11 +2483,11 @@ public class cgData {
}
}
- public static @NonNull
- List<StoredList> getLists() {
+ @NonNull
+ public static List<StoredList> getLists() {
init();
- final Resources res = cgeoapplication.getInstance().getResources();
+ final Resources res = CgeoApplication.getInstance().getResources();
final List<StoredList> lists = new ArrayList<StoredList>();
lists.add(new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatements.getCountCachesOnStandardList().simpleQueryForLong()));
@@ -2500,7 +2503,7 @@ public class cgData {
lists.addAll(storedLists);
cursor.close();
} catch (final Exception e) {
- Log.e("cgData.readLists", e);
+ Log.e("DataStore.readLists", e);
}
return lists;
}
@@ -2536,9 +2539,9 @@ public class cgData {
}
}
- Resources res = cgeoapplication.getInstance().getResources();
- if (id == StoredList.ALL_LIST_ID) {
- return new StoredList(StoredList.ALL_LIST_ID, res.getString(R.string.list_all_lists), getAllCachesCount());
+ Resources res = CgeoApplication.getInstance().getResources();
+ if (id == PseudoList.ALL_LIST.id) {
+ return new StoredList(PseudoList.ALL_LIST.id, res.getString(R.string.list_all_lists), getAllCachesCount());
}
// fall back to standard list in case of invalid list id
@@ -2653,7 +2656,11 @@ public class cgData {
}
public static void moveToList(final List<Geocache> caches, final int listId) {
- if (listId == StoredList.ALL_LIST_ID) {
+ final AbstractList list = AbstractList.getListById(listId);
+ if (list == null) {
+ return;
+ }
+ if (!list.isConcrete()) {
return;
}
if (caches.isEmpty()) {
@@ -2740,7 +2747,7 @@ public class cgData {
} catch (SQLiteDoneException e) {
// Do nothing, it only means we have no information on the cache
} catch (Exception e) {
- Log.e("cgData.getCacheDescription", e);
+ Log.e("DataStore.getCacheDescription", e);
}
return partial;
@@ -2850,7 +2857,7 @@ public class cgData {
}
public static boolean saveChangedCache(Geocache cache) {
- return cgData.saveCache(cache, cache.getStorageLocation().contains(StorageLocation.DATABASE) ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.SAVE_CACHE));
+ return DataStore.saveCache(cache, cache.getStorageLocation().contains(StorageLocation.DATABASE) ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.SAVE_CACHE));
}
private static class PreparedStatements {
@@ -2912,7 +2919,7 @@ public class cgData {
}
private static SQLiteStatement getLogCountOfGeocode() {
- return getStatement("LogCountFromGeocode", "SELECT count(_id) FROM " + cgData.dbTableLogsOffline + " WHERE geocode = ?");
+ return getStatement("LogCountFromGeocode", "SELECT count(_id) FROM " + DataStore.dbTableLogsOffline + " WHERE geocode = ?");
}
private static SQLiteStatement getCountCachesOnStandardList() {
@@ -2962,7 +2969,7 @@ public class cgData {
return null;
}
- return cgData.getBounds(Collections.singleton(geocode));
+ return DataStore.getBounds(Collections.singleton(geocode));
}
public static void clearVisitDate(String[] selected) {
@@ -2970,18 +2977,18 @@ public class cgData {
}
public static SearchResult getBatchOfStoredCaches(Geopoint coords, CacheType cacheType, int listId) {
- final Set<String> geocodes = cgData.loadBatchOfStoredGeocodes(coords, cacheType, listId);
- return new SearchResult(geocodes, cgData.getAllStoredCachesCount(cacheType, listId));
+ final Set<String> geocodes = DataStore.loadBatchOfStoredGeocodes(coords, cacheType, listId);
+ return new SearchResult(geocodes, DataStore.getAllStoredCachesCount(cacheType, listId));
}
public static SearchResult getHistoryOfCaches(boolean detailedOnly, CacheType cacheType) {
- final Set<String> geocodes = cgData.loadBatchOfHistoricGeocodes(detailedOnly, cacheType);
- return new SearchResult(geocodes, cgData.getAllHistoryCachesCount());
+ final Set<String> geocodes = DataStore.loadBatchOfHistoricGeocodes(detailedOnly, cacheType);
+ return new SearchResult(geocodes, DataStore.getAllHistoryCachesCount());
}
public static boolean saveWaypoint(int id, String geocode, Waypoint waypoint) {
- if (cgData.saveWaypointInternal(id, geocode, waypoint)) {
- cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ if (DataStore.saveWaypointInternal(id, geocode, waypoint)) {
+ DataStore.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
return true;
}
return false;
@@ -2989,7 +2996,7 @@ public class cgData {
public static Set<String> getCachedMissingFromSearch(final SearchResult searchResult, final Set<Tile> tiles, final IConnector connector, final int maxZoom) {
- // get cached cgeocaches
+ // get cached CacheListActivity
final Set<String> cachedGeocodes = new HashSet<String>();
for (Tile tile : tiles) {
cachedGeocodes.addAll(cacheCache.getInViewport(tile.getViewport(), CacheType.ALL));
diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java
index 59666e9..c31ad40 100644
--- a/main/src/cgeo/geocaching/EditWaypointActivity.java
+++ b/main/src/cgeo/geocaching/EditWaypointActivity.java
@@ -48,6 +48,8 @@ import java.util.List;
@EActivity
public class EditWaypointActivity extends AbstractActivity {
+ private static final ArrayList<WaypointType> POSSIBLE_WAYPOINT_TYPES = new ArrayList<WaypointType>(WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL);
+
@ViewById(R.id.buttonLatitude) protected Button buttonLat;
@ViewById(R.id.buttonLongitude) protected Button buttonLon;
@ViewById(R.id.add_waypoint) protected Button addWaypoint;
@@ -70,14 +72,21 @@ public class EditWaypointActivity extends AbstractActivity {
@Extra(Intents.EXTRA_COUNT) protected int wpCount = 0;
@InstanceState protected int waypointTypeSelectorPosition = -1;
+
private ProgressDialog waitDialog = null;
private Waypoint waypoint = null;
private String prefix = "OWN";
private String lookup = "---";
private boolean own = true;
- ArrayList<WaypointType> wpTypes = null;
ArrayList<String> distanceUnits = null;
+ /**
+ * {@code true} if the activity is newly created, {@code false} if it is restored from an instance state
+ */
private boolean initViews = true;
+ /**
+ * This is the cache that the waypoint belongs to.
+ */
+ private Geocache cache;
private Handler loadWaypointHandler = new Handler() {
@@ -107,7 +116,7 @@ public class EditWaypointActivity extends AbstractActivity {
note.setText(StringUtils.trimToEmpty(waypoint.getNote()));
}
}
- final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_ONLY);
+ final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_ONLY);
setCoordsModificationVisibility(ConnectorFactory.getConnector(geocode), cache);
}
@@ -158,6 +167,10 @@ public class EditWaypointActivity extends AbstractActivity {
initViews = false;
}
+ if (geocode != null) {
+ cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ setCoordsModificationVisibility(ConnectorFactory.getConnector(geocode), cache);
+ }
if (id > 0) { // existing waypoint
waitDialog = ProgressDialog.show(this, null, res.getString(R.string.waypoint_loading), true);
waitDialog.setCancelable(true);
@@ -166,11 +179,6 @@ public class EditWaypointActivity extends AbstractActivity {
} else { // new waypoint
initializeWaypointTypeSelector();
-
- if (geocode != null) {
- final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
- setCoordsModificationVisibility(ConnectorFactory.getConnector(geocode), cache);
- }
}
initializeDistanceUnitSelector();
@@ -202,8 +210,7 @@ public class EditWaypointActivity extends AbstractActivity {
}
private void initializeWaypointTypeSelector() {
- wpTypes = new ArrayList<WaypointType>(WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL);
- ArrayAdapter<WaypointType> wpAdapter = new ArrayAdapter<WaypointType>(this, android.R.layout.simple_spinner_item, wpTypes.toArray(new WaypointType[wpTypes.size()]));
+ ArrayAdapter<WaypointType> wpAdapter = new ArrayAdapter<WaypointType>(this, android.R.layout.simple_spinner_item, POSSIBLE_WAYPOINT_TYPES.toArray(new WaypointType[POSSIBLE_WAYPOINT_TYPES.size()]));
wpAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
waypointTypeSelector.setAdapter(wpAdapter);
@@ -218,17 +225,30 @@ public class EditWaypointActivity extends AbstractActivity {
}
});
- if (initViews) {
- int typeIndex = -1;
- if (waypoint != null) {
- typeIndex = wpTypes.indexOf(waypoint.getWaypointType());
- }
- waypointTypeSelector.setSelection(typeIndex >= 0 ? typeIndex : wpTypes.indexOf(WaypointType.WAYPOINT));
- } else {
- waypointTypeSelector.setSelection(waypointTypeSelectorPosition);
+ waypointTypeSelector.setSelection(getDefaultWaypointType());
+ waypointTypeSelector.setVisibility(View.VISIBLE);
+ }
+
+ private int getDefaultWaypointType() {
+ // potentially restore saved instance state
+ if (waypointTypeSelectorPosition >= 0) {
+ return waypointTypeSelectorPosition;
}
- waypointTypeSelector.setVisibility(View.VISIBLE);
+ // when editing, use the existing type
+ if (waypoint != null) {
+ return POSSIBLE_WAYPOINT_TYPES.indexOf(waypoint.getWaypointType());
+ }
+
+ // make default for new waypoint depend on cache type
+ switch (cache.getType()) {
+ case MYSTERY:
+ return POSSIBLE_WAYPOINT_TYPES.indexOf(WaypointType.FINAL);
+ case MULTI:
+ return POSSIBLE_WAYPOINT_TYPES.indexOf(WaypointType.STAGE);
+ default:
+ return POSSIBLE_WAYPOINT_TYPES.indexOf(WaypointType.WAYPOINT);
+ }
}
private void initializeDistanceUnitSelector() {
@@ -259,7 +279,7 @@ public class EditWaypointActivity extends AbstractActivity {
@Override
public void run() {
try {
- waypoint = cgData.loadWaypoint(id);
+ waypoint = DataStore.loadWaypoint(id);
loadWaypointHandler.sendMessage(Message.obtain());
} catch (Exception e) {
@@ -278,7 +298,7 @@ public class EditWaypointActivity extends AbstractActivity {
} catch (Geopoint.ParseException e) {
// button text is blank when creating new waypoint
}
- Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(EditWaypointActivity.this, cache, gp, app.currentGeo());
coordsDialog.setCancelable(true);
coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
@@ -361,7 +381,7 @@ public class EditWaypointActivity extends AbstractActivity {
final String noteText = note.getText().toString().trim();
final Geopoint coordsToSave = coords;
final int selectedTypeIndex = waypointTypeSelector.getSelectedItemPosition();
- final WaypointType type = selectedTypeIndex >= 0 ? wpTypes.get(selectedTypeIndex) : waypoint.getWaypointType();
+ final WaypointType type = selectedTypeIndex >= 0 ? POSSIBLE_WAYPOINT_TYPES.get(selectedTypeIndex) : waypoint.getWaypointType();
final boolean visited = visitedCheckBox.isChecked();
final ProgressDialog progress = ProgressDialog.show(EditWaypointActivity.this, getString(R.string.cache), getString(R.string.waypoint_being_saved), true);
final Handler finishHandler = new Handler() {
@@ -416,14 +436,14 @@ public class EditWaypointActivity extends AbstractActivity {
waypoint.setVisited(visited);
waypoint.setId(id);
- Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
if (cache == null) {
finishHandler.sendEmptyMessage(SAVE_ERROR);
return null;
}
Waypoint oldWaypoint = cache.getWaypointById(id);
if (cache.addOrChangeWaypoint(waypoint, true)) {
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
if (!StaticMapsProvider.hasAllStaticMapsForWaypoint(geocode, waypoint)) {
StaticMapsProvider.removeWpStaticMaps(oldWaypoint, geocode);
if (Settings.isStoreOfflineWpMaps()) {
@@ -432,13 +452,13 @@ public class EditWaypointActivity extends AbstractActivity {
}
if (modifyLocal.isChecked() || modifyBoth.isChecked()) {
if (!cache.hasUserModifiedCoords()) {
- final Waypoint origWaypoint = new Waypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false);
+ final Waypoint origWaypoint = new Waypoint(CgeoApplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false);
origWaypoint.setCoords(cache.getCoords());
cache.addOrChangeWaypoint(origWaypoint, false);
cache.setUserModifiedCoords(true);
}
cache.setCoords(waypoint.getCoords());
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
if (modifyBoth.isChecked() && waypoint.getCoords() != null) {
finishHandler.sendEmptyMessage(UPLOAD_START);
@@ -468,8 +488,8 @@ public class EditWaypointActivity extends AbstractActivity {
return con.supportsOwnCoordinates() && con.uploadModifiedCoordinates(cache, waypointUploaded);
}
- public static void startActivityEditWaypoint(final Context context, final int waypointId) {
- EditWaypointActivity_.intent(context).id(waypointId).start();
+ public static void startActivityEditWaypoint(final Context context, final Geocache cache, final int waypointId) {
+ EditWaypointActivity_.intent(context).geocode(cache.getGeocode()).id(waypointId).start();
}
public static void startActivityAddWaypoint(final Context context, final Geocache cache) {
diff --git a/main/src/cgeo/geocaching/GeoDataProvider.java b/main/src/cgeo/geocaching/GeoDataProvider.java
index f615630..73aefce 100644
--- a/main/src/cgeo/geocaching/GeoDataProvider.java
+++ b/main/src/cgeo/geocaching/GeoDataProvider.java
@@ -272,6 +272,7 @@ class GeoDataProvider extends MemorySubject<IGeoData> {
public void onGpsStatusChanged(final int event) {
boolean changed = false;
switch (event) {
+ case GpsStatus.GPS_EVENT_FIRST_FIX:
case GpsStatus.GPS_EVENT_SATELLITE_STATUS: {
final GpsStatus status = geoManager.getGpsStatus(null);
int visible = 0;
@@ -303,6 +304,8 @@ class GeoDataProvider extends MemorySubject<IGeoData> {
changed = true;
}
break;
+ default:
+ throw new IllegalStateException();
}
if (changed) {
diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java
index 7aceed4..35d6c17 100644
--- a/main/src/cgeo/geocaching/Geocache.java
+++ b/main/src/cgeo/geocaching/Geocache.java
@@ -1,6 +1,6 @@
package cgeo.geocaching;
-import cgeo.geocaching.cgData.StorageLocation;
+import cgeo.geocaching.DataStore.StorageLocation;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
@@ -21,6 +21,7 @@ import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.files.GPXParser;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.CancellableHandler;
@@ -31,7 +32,8 @@ import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
import cgeo.geocaching.utils.MatcherWrapper;
import cgeo.geocaching.utils.UncertainProperty;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@@ -112,20 +114,20 @@ public class Geocache implements ICache, IWaypoint {
private final List<String> attributes = new LazyInitializedList<String>() {
@Override
public List<String> call() {
- return cgData.loadAttributes(geocode);
+ return DataStore.loadAttributes(geocode);
}
};
private final List<Waypoint> waypoints = new LazyInitializedList<Waypoint>() {
@Override
public List<Waypoint> call() {
- return cgData.loadWaypoints(geocode);
+ return DataStore.loadWaypoints(geocode);
}
};
private List<Image> spoilers = null;
private final List<LogEntry> logs = new LazyInitializedList<LogEntry>() {
@Override
public List<LogEntry> call() {
- return cgData.loadLogs(geocode);
+ return DataStore.loadLogs(geocode);
}
};
private List<Trackable> inventory = null;
@@ -461,7 +463,7 @@ public class Geocache implements ICache, IWaypoint {
public void logOffline(final Activity fromActivity, final LogType logType) {
final boolean mustIncludeSignature = StringUtils.isNotBlank(Settings.getSignature()) && Settings.isAutoInsertSignature();
- final String initial = mustIncludeSignature ? LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(this, true)) : "";
+ final String initial = mustIncludeSignature ? LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(this, null, true)) : "";
logOffline(fromActivity, initial, Calendar.getInstance(), logType);
}
@@ -469,12 +471,12 @@ public class Geocache implements ICache, IWaypoint {
if (logType == LogType.UNKNOWN) {
return;
}
- final boolean status = cgData.saveLogOffline(geocode, date.getTime(), logType, log);
+ final boolean status = DataStore.saveLogOffline(geocode, date.getTime(), logType, log);
final Resources res = fromActivity.getResources();
if (status) {
ActivityMixin.showToast(fromActivity, res.getString(R.string.info_log_saved));
- cgData.saveVisitDate(geocode);
+ DataStore.saveVisitDate(geocode);
logOffline = Boolean.TRUE;
notifyChange();
@@ -484,44 +486,12 @@ public class Geocache implements ICache, IWaypoint {
}
public void clearOfflineLog() {
- cgData.clearLogOffline(geocode);
+ DataStore.clearLogOffline(geocode);
notifyChange();
}
public List<LogType> getPossibleLogTypes() {
- final List<LogType> logTypes = new ArrayList<LogType>();
- if (isEventCache()) {
- logTypes.add(LogType.WILL_ATTEND);
- logTypes.add(LogType.ATTENDED);
- if (isOwner()) {
- logTypes.add(LogType.ANNOUNCEMENT);
- }
- } else if (CacheType.WEBCAM == cacheType.getValue()) {
- logTypes.add(LogType.WEBCAM_PHOTO_TAKEN);
- } else {
- logTypes.add(LogType.FOUND_IT);
- }
- if (!isEventCache()) {
- logTypes.add(LogType.DIDNT_FIND_IT);
- }
- logTypes.add(LogType.NOTE);
- if (!isEventCache()) {
- logTypes.add(LogType.NEEDS_MAINTENANCE);
- }
- if (isOwner()) {
- logTypes.add(LogType.OWNER_MAINTENANCE);
- if (isDisabled()) {
- logTypes.add(LogType.ENABLE_LISTING);
- }
- else {
- logTypes.add(LogType.TEMP_DISABLE_LISTING);
- }
- logTypes.add(LogType.ARCHIVE);
- }
- if (!isArchived() && !isOwner()) {
- logTypes.add(LogType.NEEDS_ARCHIVE);
- }
- return logTypes;
+ return getConnector().getPossibleLogTypes(this);
}
public void openInBrowser(Activity fromActivity) {
@@ -664,7 +634,7 @@ public class Geocache implements ICache, IWaypoint {
*/
private void initializeCacheTexts() {
if (description == null || shortdesc == null || hint == null || location == null) {
- final Geocache partial = cgData.loadCacheTexts(this.getGeocode());
+ final Geocache partial = DataStore.loadCacheTexts(this.getGeocode());
if (description == null) {
setDescription(partial.getDescription());
}
@@ -841,7 +811,13 @@ public class Geocache implements ICache, IWaypoint {
}
public boolean showSize() {
- return !((isEventCache() || isVirtual()) && size == CacheSize.NOT_CHOSEN);
+ if (size == CacheSize.NOT_CHOSEN) {
+ return false;
+ }
+ if (isEventCache() || isVirtual()) {
+ return false;
+ }
+ return true;
}
public long getUpdated() {
@@ -1028,7 +1004,7 @@ public class Geocache implements ICache, IWaypoint {
}
}
}
- return saveToDatabase && cgData.saveWaypoints(this);
+ return saveToDatabase && DataStore.saveWaypoints(this);
}
/**
@@ -1244,7 +1220,7 @@ public class Geocache implements ICache, IWaypoint {
// when waypoint was edited, finalDefined may have changed
resetFinalDefined();
}
- return saveToDatabase && cgData.saveWaypoint(waypoint.getId(), geocode, waypoint);
+ return saveToDatabase && DataStore.saveWaypoint(waypoint.getId(), geocode, waypoint);
}
public boolean hasWaypoints() {
@@ -1295,9 +1271,9 @@ public class Geocache implements ICache, IWaypoint {
final int index = getWaypointIndex(original);
final Waypoint copy = new Waypoint(original);
copy.setUserDefined();
- copy.setName(cgeoapplication.getInstance().getString(R.string.waypoint_copy_of) + " " + copy.getName());
+ copy.setName(CgeoApplication.getInstance().getString(R.string.waypoint_copy_of) + " " + copy.getName());
waypoints.add(index + 1, copy);
- return cgData.saveWaypoint(-1, geocode, copy);
+ return DataStore.saveWaypoint(-1, geocode, copy);
}
/**
@@ -1317,8 +1293,8 @@ public class Geocache implements ICache, IWaypoint {
if (waypoint.isUserDefined()) {
final int index = getWaypointIndex(waypoint);
waypoints.remove(index);
- cgData.deleteWaypoint(waypoint.getId());
- cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ DataStore.deleteWaypoint(waypoint.getId());
+ DataStore.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
// Check status if Final is defined
if (waypoint.isFinalWithCoords()) {
resetFinalDefined();
@@ -1337,8 +1313,8 @@ public class Geocache implements ICache, IWaypoint {
public void deleteWaypointForce(Waypoint waypoint) {
final int index = getWaypointIndex(waypoint);
waypoints.remove(index);
- cgData.deleteWaypoint(waypoint.getId());
- cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ DataStore.deleteWaypoint(waypoint.getId());
+ DataStore.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
resetFinalDefined();
}
@@ -1406,7 +1382,7 @@ public class Geocache implements ICache, IWaypoint {
if (point.getLatitudeE6() != 0 && point.getLongitudeE6() != 0 &&
((point.getLatitudeE6() % 1000) != 0 || (point.getLongitudeE6() % 1000) != 0) &&
!hasIdenticalWaypoint(point)) {
- final String name = cgeoapplication.getInstance().getString(R.string.cache_personal_note) + " " + count;
+ final String name = CgeoApplication.getInstance().getString(R.string.cache_personal_note) + " " + count;
final String potentialWaypointType = note.substring(Math.max(0, matcher.start() - 15));
final Waypoint waypoint = new Waypoint(name, parseWaypointType(potentialWaypointType), false);
waypoint.setCoords(point);
@@ -1511,8 +1487,8 @@ public class Geocache implements ICache, IWaypoint {
public void drop(Handler handler) {
try {
- cgData.markDropped(Collections.singletonList(this));
- cgData.removeCache(getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ DataStore.markDropped(Collections.singletonList(this));
+ DataStore.removeCache(getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE));
handler.sendMessage(Message.obtain());
} catch (final Exception e) {
@@ -1563,7 +1539,7 @@ public class Geocache implements ICache, IWaypoint {
}
public void refresh(int newListId, CancellableHandler handler) {
- cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ DataStore.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
storeCache(null, geocode, newListId, true, handler);
}
@@ -1639,7 +1615,7 @@ public class Geocache implements ICache, IWaypoint {
}
cache.setListId(listId);
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
if (CancellableHandler.isCancelled(handler)) {
return;
@@ -1661,9 +1637,9 @@ public class Geocache implements ICache, IWaypoint {
return null;
}
- if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (cgData.isOffline(geocode, guid) || cgData.isThere(geocode, guid, true, true))) {
+ if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (DataStore.isOffline(geocode, guid) || DataStore.isThere(geocode, guid, true, true))) {
final SearchResult search = new SearchResult();
- final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : cgData.getGeocodeForGuid(guid);
+ final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : DataStore.getGeocodeForGuid(guid);
search.addGeocode(realGeocode);
return search;
}
@@ -1693,30 +1669,30 @@ public class Geocache implements ICache, IWaypoint {
if (!isEventCache()) {
return null;
}
+
+ final String hourLocalized = CgeoApplication.getInstance().getString(R.string.cache_time_full_hours);
+ ArrayList<Pattern> patterns = new ArrayList<Pattern>();
+
// 12:34
- final Pattern time = Pattern.compile("\\b(\\d{1,2})\\:(\\d\\d)\\b");
- final MatcherWrapper matcher = new MatcherWrapper(time, getDescription());
- while (matcher.find()) {
- try {
- final int hours = Integer.valueOf(matcher.group(1));
- final int minutes = Integer.valueOf(matcher.group(2));
- if (hours >= 0 && hours < 24 && minutes >= 0 && minutes < 60) {
- return String.valueOf(hours * 60 + minutes);
- }
- } catch (final NumberFormatException e) {
- // cannot happen, but static code analysis doesn't know
- }
- }
- // 12 o'clock
- final String hourLocalized = cgeoapplication.getInstance().getString(R.string.cache_time_full_hours);
+ patterns.add(Pattern.compile("\\b(\\d{1,2})\\:(\\d\\d)\\b"));
if (StringUtils.isNotBlank(hourLocalized)) {
- final Pattern fullHours = Pattern.compile("\\b(\\d{1,2})\\s+" + Pattern.quote(hourLocalized), Pattern.CASE_INSENSITIVE);
- final MatcherWrapper matcherHours = new MatcherWrapper(fullHours, getDescription());
- if (matcherHours.find()) {
+ // 17 - 20 o'clock
+ patterns.add(Pattern.compile("\\b(\\d{1,2})(?:\\.00)?" + "\\s*-\\s*" + "(?:\\d{1,2})(?:\\.00)?" + "\\s+" + Pattern.quote(hourLocalized), Pattern.CASE_INSENSITIVE));
+ // 12 o'clock, 12.00 o'clock
+ patterns.add(Pattern.compile("\\b(\\d{1,2})(?:\\.00)?\\s+" + Pattern.quote(hourLocalized), Pattern.CASE_INSENSITIVE));
+ }
+
+ for (Pattern pattern : patterns) {
+ final MatcherWrapper matcher = new MatcherWrapper(pattern, getDescription());
+ while (matcher.find()) {
try {
- final int hours = Integer.valueOf(matcherHours.group(1));
- if (hours >= 0 && hours < 24) {
- return String.valueOf(hours * 60);
+ final int hours = Integer.valueOf(matcher.group(1));
+ int minutes = 0;
+ if (matcher.groupCount() >= 2) {
+ minutes = Integer.valueOf(matcher.group(2));
+ }
+ if (hours >= 0 && hours < 24 && minutes >= 0 && minutes < 60) {
+ return String.valueOf(hours * 60 + minutes);
}
} catch (final NumberFormatException e) {
// cannot happen, but static code analysis doesn't know
@@ -1735,7 +1711,7 @@ public class Geocache implements ICache, IWaypoint {
* @return
*/
public boolean hasAttribute(CacheAttribute attribute, boolean yes) {
- Geocache fullCache = cgData.loadCache(getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES));
+ Geocache fullCache = DataStore.loadCache(getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES));
if (fullCache == null) {
fullCache = this;
}
@@ -1746,6 +1722,13 @@ public class Geocache implements ICache, IWaypoint {
return StaticMapsProvider.hasStaticMap(this);
}
+ public static final Predicate<Geocache> hasStaticMap = new Predicate<Geocache>() {
+ @Override
+ public boolean evaluate(final Geocache cache) {
+ return cache.hasStaticMap();
+ }
+ };
+
public List<Image> getImages() {
final List<Image> result = new ArrayList<Image>();
result.addAll(getSpoilers());
diff --git a/main/src/cgeo/geocaching/GpxFileListActivity.java b/main/src/cgeo/geocaching/GpxFileListActivity.java
index 8b10d5b..dae52c4 100644
--- a/main/src/cgeo/geocaching/GpxFileListActivity.java
+++ b/main/src/cgeo/geocaching/GpxFileListActivity.java
@@ -4,6 +4,7 @@ import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.files.AbstractFileListActivity;
import cgeo.geocaching.files.GPXImporter;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.GPXListAdapter;
diff --git a/main/src/cgeo/geocaching/ImageSelectActivity.java b/main/src/cgeo/geocaching/ImageSelectActivity.java
index e24c34a..790741f 100644
--- a/main/src/cgeo/geocaching/ImageSelectActivity.java
+++ b/main/src/cgeo/geocaching/ImageSelectActivity.java
@@ -9,6 +9,8 @@ import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import android.content.Intent;
import android.database.Cursor;
@@ -263,7 +265,8 @@ public class ImageSelectActivity extends AbstractActivity {
* @param filePath
* @return the scaled image path, or <tt>null</tt> if the image cannot be decoded
*/
- private String writeScaledImage(final String filePath) {
+ @Nullable
+ private String writeScaledImage(@NonNull final String filePath) {
scaleChoiceIndex = scaleView.getSelectedItemPosition();
final int maxXY = getResources().getIntArray(R.array.log_image_scale_values)[scaleChoiceIndex];
return ImageUtils.readScaleAndWriteImage(filePath, maxXY);
diff --git a/main/src/cgeo/geocaching/ImagesActivity.java b/main/src/cgeo/geocaching/ImagesActivity.java
index 0b80d53..29bc8c7 100644
--- a/main/src/cgeo/geocaching/ImagesActivity.java
+++ b/main/src/cgeo/geocaching/ImagesActivity.java
@@ -5,7 +5,7 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.ImagesList;
import cgeo.geocaching.ui.ImagesList.ImageType;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import android.content.Context;
import android.content.Intent;
@@ -58,7 +58,7 @@ public class ImagesActivity extends AbstractActivity {
return;
}
- offline = cgData.isOffline(geocode, null) && (imgType == ImageType.SpoilerImages
+ offline = DataStore.isOffline(geocode, null) && (imgType == ImageType.SpoilerImages
|| Settings.isStoreLogImages());
}
diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java
index c9baac1..34f036c 100644
--- a/main/src/cgeo/geocaching/LogCacheActivity.java
+++ b/main/src/cgeo/geocaching/LogCacheActivity.java
@@ -3,6 +3,7 @@ package cgeo.geocaching;
import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.ImageResult;
import cgeo.geocaching.connector.LogResult;
+import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.LogTypeTrackable;
@@ -18,7 +19,7 @@ import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.LogTemplateProvider;
import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
@@ -46,7 +47,6 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
-import java.util.Locale;
public class LogCacheActivity extends AbstractLoggingActivity implements DateDialog.DateDialogParent {
static final String EXTRAS_GEOCODE = "geocode";
@@ -79,7 +79,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
private ILoggingManager loggingManager;
// Data to be saved while reconfiguring
- private double rating;
+ private float rating;
private LogType typeSelected;
private Calendar date;
private String imageCaption;
@@ -214,13 +214,13 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
if (!postButton.isEnabled()) {
return res.getString(R.string.log_post_not_possible);
}
- if (typeSelected != LogType.FOUND_IT || !Settings.isGCvoteLogin() || !cache.supportsGCVote()) {
+ if (!GCVote.isVotingPossible(cache)) {
return res.getString(R.string.log_post);
}
- if (rating == 0) {
- return res.getString(R.string.log_post_no_rate);
+ if (GCVote.isValidRating(rating)) {
+ return res.getString(R.string.log_post_rate) + " " + GCVote.getRatingText(rating) + "*";
}
- return res.getString(R.string.log_post_rate) + " " + ratingTextValue(rating) + "*";
+ return res.getString(R.string.log_post_no_rate);
}
@Override
@@ -235,13 +235,13 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
if ((StringUtils.isBlank(cacheid)) && StringUtils.isNotBlank(geocode)) {
- cacheid = cgData.getCacheidForGeocode(geocode);
+ cacheid = DataStore.getCacheidForGeocode(geocode);
}
if (StringUtils.isBlank(geocode) && StringUtils.isNotBlank(cacheid)) {
- geocode = cgData.getGeocodeForGuid(cacheid);
+ geocode = DataStore.getGeocodeForGuid(cacheid);
}
- cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
possibleLogTypes = cache.getPossibleLogTypes();
if (StringUtils.isNotBlank(cache.getName())) {
@@ -261,7 +261,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
// Restore previous state
if (savedInstanceState != null) {
- rating = savedInstanceState.getDouble(SAVED_STATE_RATING);
+ rating = savedInstanceState.getFloat(SAVED_STATE_RATING);
typeSelected = LogType.getById(savedInstanceState.getInt(SAVED_STATE_TYPE));
date.setTimeInMillis(savedInstanceState.getLong(SAVED_STATE_DATE));
imageCaption = savedInstanceState.getString(SAVED_STATE_IMAGE_CAPTION);
@@ -269,7 +269,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
imageUri = Uri.parse(savedInstanceState.getString(SAVED_STATE_IMAGE_URI));
} else {
// If log had been previously saved, load it now, otherwise initialize signature as needed
- final LogEntry log = cgData.loadLogOffline(geocode);
+ final LogEntry log = DataStore.loadLogOffline(geocode);
if (log != null) {
typeSelected = log.type;
date.setTime(new Date(log.date));
@@ -277,7 +277,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
} else if (StringUtils.isNotBlank(Settings.getSignature())
&& Settings.isAutoInsertSignature()
&& StringUtils.isBlank(currentLogText())) {
- insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(cache)), false);
+ insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(cache, null)), false);
}
}
updatePostButtonText();
@@ -341,28 +341,25 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
private void setDefaultValues() {
date = Calendar.getInstance();
- rating = 0.0;
+ rating = GCVote.NO_RATING;
if (cache.isEventCache()) {
final Date eventDate = cache.getHiddenDate();
- boolean expired = DateUtils.daysSince(eventDate.getTime()) > 0;
+ boolean expired = DateUtils.daysSince(eventDate.getTime()) >= 0;
if (cache.hasOwnLog(LogType.WILL_ATTEND) || expired) {
- if (cache.hasOwnLog(LogType.ATTENDED)) {
- typeSelected = LogType.NOTE;
- }
- else {
- typeSelected = LogType.ATTENDED;
- }
- }
- else {
+ typeSelected = cache.hasOwnLog(LogType.ATTENDED) ? LogType.NOTE : LogType.ATTENDED;
+ } else {
typeSelected = LogType.WILL_ATTEND;
}
- }
- else {
+ // it this is an attended event log, use the event date by default instead of the current date
+ if (expired && typeSelected == LogType.ATTENDED) {
+ date.setTime(eventDate);
+ }
+ } else {
if (cache.isFound()) {
typeSelected = LogType.NOTE;
} else {
- typeSelected = LogType.FOUND_IT;
+ typeSelected = cache.getType() == CacheType.WEBCAM ? LogType.WEBCAM_PHOTO_TAKEN : LogType.FOUND_IT;
}
}
text = null;
@@ -424,8 +421,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- final boolean voteAvailable = Settings.isGCvoteLogin() && (typeSelected == LogType.FOUND_IT || typeSelected == LogType.ATTENDED || typeSelected == LogType.WEBCAM_PHOTO_TAKEN) && StringUtils.isNotBlank(cache.getGuid()) && cache.supportsGCVote();
- menu.findItem(SUBMENU_VOTE).setVisible(voteAvailable);
+ menu.findItem(SUBMENU_VOTE).setVisible(GCVote.isVotingPossible(cache));
return true;
}
@@ -438,9 +434,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
final int id = item.getItemId();
if (id >= 10 && id <= 19) {
- rating = (id - 9) / 2.0;
- if (rating < 1) {
- rating = 0;
+ rating = (id - 9) / 2.0f;
+ if (!GCVote.isValidRating(rating)) {
+ rating = GCVote.NO_RATING;
}
updatePostButtonText();
return true;
@@ -449,10 +445,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
return false;
}
- private static String ratingTextValue(final double rating) {
- return String.format(Locale.getDefault(), "%.1f", rating);
- }
-
@Override
protected void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
@@ -548,13 +540,15 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
cache.setVisitedDate(new Date().getTime());
}
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
cache.clearOfflineLog();
if (typeSelected == LogType.FOUND_IT) {
if (tweetCheck.isChecked() && tweetBox.getVisibility() == View.VISIBLE) {
- Twitter.postTweetCache(geocode);
+ Twitter.postTweetCache(geocode, logNow);
}
+ }
+ if (GCVote.isValidRating(rating)) {
GCVote.setRating(cache, rating);
}
@@ -563,7 +557,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
final String uploadedImageUrl = imageResult.getImageUri();
if (StringUtils.isNotEmpty(uploadedImageUrl)) {
logNow.addLogImage(new Image(uploadedImageUrl, imageCaption, imageDescription));
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return imageResult.getPostResult();
}
@@ -615,7 +609,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
@Override
protected LogContext getLogContext() {
- return new LogContext(cache);
+ return new LogContext(cache, null);
}
private void selectAllTrackablesAction() {
diff --git a/main/src/cgeo/geocaching/LogEntry.java b/main/src/cgeo/geocaching/LogEntry.java
index a01c431..b922398 100644
--- a/main/src/cgeo/geocaching/LogEntry.java
+++ b/main/src/cgeo/geocaching/LogEntry.java
@@ -5,7 +5,7 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.DateUtils;
import cgeo.geocaching.utils.MatcherWrapper;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
@@ -89,7 +89,7 @@ public final class LogEntry {
}
}
if (titles.isEmpty()) {
- titles.add(cgeoapplication.getInstance().getString(R.string.cache_log_image_default_title));
+ titles.add(CgeoApplication.getInstance().getString(R.string.cache_log_image_default_title));
}
return StringUtils.join(titles, ", ");
}
diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java
index a45d584..dd3fa78 100644
--- a/main/src/cgeo/geocaching/LogTrackableActivity.java
+++ b/main/src/cgeo/geocaching/LogTrackableActivity.java
@@ -16,7 +16,7 @@ import cgeo.geocaching.ui.dialog.DateDialog;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.Dialog;
@@ -130,7 +130,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
}
}
- trackable = cgData.loadTrackable(geocode);
+ trackable = DataStore.loadTrackable(geocode);
if (StringUtils.isNotBlank(trackable.getName())) {
setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getName());
@@ -335,7 +335,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
if (status == StatusCode.NO_ERROR && Settings.isUseTwitter() &&
Settings.isTwitterLoginValid() &&
tweetCheck.isChecked() && tweetBox.getVisibility() == View.VISIBLE) {
- Twitter.postTweetTrackable(geocode);
+ Twitter.postTweetTrackable(geocode, new LogEntry(0, typeSelected, log));
}
return status;
@@ -356,6 +356,6 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
@Override
protected LogContext getLogContext() {
- return new LogContext(trackable);
+ return new LogContext(trackable, null);
}
}
diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java
index 1b9fe46..0daa124 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.StoredList;
import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.settings.SettingsActivity;
@@ -24,8 +25,9 @@ import cgeo.geocaching.utils.Version;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
@@ -284,7 +286,7 @@ public class MainActivity extends AbstractActivity {
startActivity(new Intent(this, SettingsActivity.class));
return true;
case R.id.menu_history:
- cgeocaches.startActivityHistory(this);
+ CacheListActivity.startActivityHistory(this);
return true;
case R.id.menu_scan:
startScannerApplication();
@@ -367,7 +369,7 @@ public class MainActivity extends AbstractActivity {
@Override
public void run(final Integer selectedListId) {
Settings.saveLastList(selectedListId);
- cgeocaches.startActivityOffline(MainActivity.this);
+ CacheListActivity.startActivityOffline(MainActivity.this);
}
});
return true;
@@ -469,7 +471,7 @@ public class MainActivity extends AbstractActivity {
}
private void checkRestore() {
- if (!cgData.isNewlyCreatedDatebase() || null == DatabaseBackupUtils.getRestoreFile()) {
+ if (!DataStore.isNewlyCreatedDatebase() || null == DatabaseBackupUtils.getRestoreFile()) {
return;
}
new AlertDialog.Builder(this)
@@ -480,7 +482,7 @@ public class MainActivity extends AbstractActivity {
@Override
public void onClick(final DialogInterface dialog, final int id) {
dialog.dismiss();
- cgData.resetNewlyCreatedDatabase();
+ DataStore.resetNewlyCreatedDatabase();
DatabaseBackupUtils.restoreDatabase(MainActivity.this);
}
})
@@ -488,7 +490,7 @@ public class MainActivity extends AbstractActivity {
@Override
public void onClick(final DialogInterface dialog, final int id) {
dialog.cancel();
- cgData.resetNewlyCreatedDatabase();
+ DataStore.resetNewlyCreatedDatabase();
}
})
.create()
@@ -516,11 +518,14 @@ public class MainActivity extends AbstractActivity {
@Override
public boolean onLongClick(View v) {
+ if (!Settings.isPremiumMember()) {
+ return true;
+ }
new PocketQueryList.UserInterface(MainActivity.this).promptForListSelection(new RunnableWithArgument<PocketQueryList>() {
@Override
- public void run(PocketQueryList pql) {
- cgeocaches.startActivityPocket(MainActivity.this, pql.getGuid(), pql.getName());
+ public void run(final @NonNull PocketQueryList pql) {
+ CacheListActivity.startActivityPocket(MainActivity.this, pql);
}
});
return true;
@@ -585,7 +590,7 @@ public class MainActivity extends AbstractActivity {
}
nearestView.setPressed(true);
- cgeocaches.startActivityNearest(this, app.currentGeo().getCoords());
+ CacheListActivity.startActivityNearest(this, app.currentGeo().getCoords());
}
/**
@@ -594,7 +599,7 @@ public class MainActivity extends AbstractActivity {
*/
public void cgeoFindByOffline(final View v) {
findByOffline.setPressed(true);
- cgeocaches.startActivityOffline(this);
+ CacheListActivity.startActivityOffline(this);
}
/**
@@ -658,7 +663,7 @@ public class MainActivity extends AbstractActivity {
}
int checks = 0;
- while (!cgData.isInitialized()) {
+ while (!DataStore.isInitialized()) {
try {
wait(500);
checks++;
@@ -671,7 +676,7 @@ public class MainActivity extends AbstractActivity {
}
}
- countBubbleCnt = cgData.getAllCachesCount();
+ countBubbleCnt = DataStore.getAllCachesCount();
countBubbleHandler.sendEmptyMessage(0);
}
@@ -696,7 +701,7 @@ public class MainActivity extends AbstractActivity {
}
cleanupRunning = true;
- cgData.clean(more);
+ DataStore.clean(more);
cleanupRunning = false;
if (version > 0) {
diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
index 87d7ba7..d0733e5 100644
--- a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
+++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
@@ -1,6 +1,7 @@
package cgeo.geocaching;
import butterknife.InjectView;
+import butterknife.Optional;
import butterknife.Views;
import cgeo.geocaching.activity.AbstractActivity;
@@ -43,13 +44,15 @@ import java.util.List;
public class NavigateAnyPointActivity extends AbstractActivity {
- @InjectView(R.id.buttonLatitude) protected Button latButton;
- @InjectView(R.id.buttonLongitude) protected Button lonButton;
- @InjectView(R.id.current) protected Button buttonCurrent;
@InjectView(R.id.historyList) protected ListView historyListView;
- @InjectView(R.id.distanceUnit) protected Spinner distanceUnitSelector;
- @InjectView(R.id.bearing) protected EditText bearingEditText;
- @InjectView(R.id.distance) protected EditText distanceEditText;
+
+ // list header fields are optional, due to being expanded later than the list itself
+ @Optional @InjectView(R.id.buttonLatitude) protected Button latButton;
+ @Optional @InjectView(R.id.buttonLongitude) protected Button lonButton;
+ @Optional @InjectView(R.id.distance) protected EditText distanceEditText;
+ @Optional @InjectView(R.id.distanceUnit) protected Spinner distanceUnitSelector;
+ @Optional @InjectView(R.id.current) protected Button buttonCurrent;
+ @Optional @InjectView(R.id.bearing) protected EditText bearingEditText;
private boolean changed = false;
private List<Destination> historyOfSearchedLocations;
@@ -214,7 +217,7 @@ public class NavigateAnyPointActivity extends AbstractActivity {
private List<Destination> getHistoryOfSearchedLocations() {
if (historyOfSearchedLocations == null) {
// Load from database
- historyOfSearchedLocations = cgData.loadHistoryOfSearchedLocations();
+ historyOfSearchedLocations = DataStore.loadHistoryOfSearchedLocations();
}
return historyOfSearchedLocations;
@@ -377,7 +380,7 @@ public class NavigateAnyPointActivity extends AbstractActivity {
getHistoryOfSearchedLocations().add(0, loc);
// Save location
- cgData.saveSearchedDestination(loc);
+ DataStore.saveSearchedDestination(loc);
// Ensure to remove the footer
historyListView.removeFooterView(getEmptyHistoryFooter());
@@ -396,7 +399,7 @@ public class NavigateAnyPointActivity extends AbstractActivity {
getHistoryOfSearchedLocations().remove(destination);
// Save
- cgData.removeSearchedDestination(destination);
+ DataStore.removeSearchedDestination(destination);
if (getHistoryOfSearchedLocations().isEmpty()) {
if (historyListView.getFooterViewsCount() == 0) {
@@ -415,7 +418,7 @@ public class NavigateAnyPointActivity extends AbstractActivity {
getHistoryOfSearchedLocations().clear();
// Save
- cgData.clearSearchedDestinations();
+ DataStore.clearSearchedDestinations();
if (historyListView.getFooterViewsCount() == 0) {
historyListView.addFooterView(getEmptyHistoryFooter());
@@ -443,7 +446,7 @@ public class NavigateAnyPointActivity extends AbstractActivity {
return;
}
- cgeocaches.startActivityCoordinates(this, coords);
+ CacheListActivity.startActivityCoordinates(this, coords);
finish();
}
diff --git a/main/src/cgeo/geocaching/PocketQueryList.java b/main/src/cgeo/geocaching/PocketQueryList.java
index cef4463..e1a921c 100644
--- a/main/src/cgeo/geocaching/PocketQueryList.java
+++ b/main/src/cgeo/geocaching/PocketQueryList.java
@@ -55,7 +55,6 @@ public final class PocketQueryList {
PocketQueryList pq = pocketQueryList.get(i);
items[i] = pq.name + " (" + pq.maxCaches + ")";
-
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
@@ -63,7 +62,9 @@ public final class PocketQueryList {
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int itemId) {
- runAfterwards.run(pocketQueryList.get(itemId));
+ final PocketQueryList query = pocketQueryList.get(itemId);
+ dialogInterface.dismiss();
+ runAfterwards.run(query);
}
});
builder.create().show();
@@ -86,13 +87,13 @@ public final class PocketQueryList {
}
private final Activity activity;
- private final cgeoapplication app;
+ private final CgeoApplication app;
private final Resources res;
private ProgressDialog waitDialog = null;
public UserInterface(final Activity activity) {
this.activity = activity;
- app = cgeoapplication.getInstance();
+ app = CgeoApplication.getInstance();
res = app.getResources();
}
diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java
index 8f58bcd..fe48fda 100644
--- a/main/src/cgeo/geocaching/SearchActivity.java
+++ b/main/src/cgeo/geocaching/SearchActivity.java
@@ -13,8 +13,6 @@ import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
import cgeo.geocaching.utils.EditUtils;
-import cgeo.geocaching.utils.GeoDirHandler;
-import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
@@ -38,26 +36,28 @@ public class SearchActivity extends AbstractActivity {
@InjectView(R.id.buttonLatitude) protected Button buttonLatitude;
@InjectView(R.id.buttonLongitude) protected Button buttonLongitude;
- @InjectView(R.id.search_coordinates) protected Button findByCoords;
- @InjectView(R.id.search_address) protected Button findByAddress;
- @InjectView(R.id.geocode) protected AutoCompleteTextView geocodeEdit;
- @InjectView(R.id.display_geocode) protected Button displayByGeocode;
- @InjectView(R.id.search_keyword) protected Button findByKeyword;
- @InjectView(R.id.search_username) protected Button findByUserName;
- @InjectView(R.id.search_owner) protected Button findByOwner;
- @InjectView(R.id.trackable) protected AutoCompleteTextView trackable;
- @InjectView(R.id.display_trackable) protected Button displayTrackable;
- @InjectView(R.id.latitude) protected EditText latEdit;
- @InjectView(R.id.longitude) protected EditText lonEdit;
- @InjectView(R.id.keyword) protected EditText keywordEditText;
+ @InjectView(R.id.search_coordinates) protected Button buttonSearchCoords;
+
@InjectView(R.id.address) protected EditText 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.search_keyword) protected Button buttonSearchKeyword;
+
@InjectView(R.id.username) protected EditText userNameEditText;
+ @InjectView(R.id.search_username) protected Button buttonSearchUserName;
+
@InjectView(R.id.owner) protected EditText ownerNameEditText;
- @InjectView(R.id.geocode) protected EditText geocodeEditText;
- @InjectView(R.id.trackable) protected EditText trackableEditText;
+ @InjectView(R.id.search_owner) protected Button buttonSearchOwner;
+
+ @InjectView(R.id.trackable) protected AutoCompleteTextView trackableEditText;
+ @InjectView(R.id.display_trackable) protected Button buttonSearchTrackable;
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// search query
@@ -89,25 +89,18 @@ public class SearchActivity extends AbstractActivity {
}
@Override
- public void onConfigurationChanged(Configuration newConfig) {
+ public final void onConfigurationChanged(final Configuration newConfig) {
super.onConfigurationChanged(newConfig);
init();
}
@Override
- public void onResume() {
+ public final void onResume() {
super.onResume();
- geoDirHandler.startGeo();
init();
}
- @Override
- public void onPause() {
- geoDirHandler.stopGeo();
- super.onPause();
- }
-
/**
* Performs a search for query either as geocode, trackable code or keyword
*
@@ -142,7 +135,7 @@ public class SearchActivity extends AbstractActivity {
}
if (keywordSearch) { // keyword fallback, if desired by caller
- cgeocaches.startActivityKeyword(this, query.trim());
+ CacheListActivity.startActivityKeyword(this, query.trim());
return true;
}
@@ -150,73 +143,77 @@ public class SearchActivity extends AbstractActivity {
}
private void init() {
-
buttonLatitude.setOnClickListener(new FindByCoordsAction());
buttonLongitude.setOnClickListener(new FindByCoordsAction());
- findByCoords.setOnClickListener(new FindByCoordsListener());
- EditUtils.setActionListener((EditText) findViewById(R.id.address), new Runnable() {
+ buttonSearchCoords.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(final View arg0) {
+ findByCoordsFn();
+ }
+ });
+
+ setSearchAction(addressEditText, buttonSearchAddress, new Runnable() {
@Override
public void run() {
findByAddressFn();
}
});
- findByAddress.setOnClickListener(new FindByAddressListener());
- EditUtils.setActionListener(geocodeEdit, new Runnable() {
+ setSearchAction(geocodeEditText, buttonSearchGeocode, new Runnable() {
@Override
public void run() {
findByGeocodeFn();
}
});
- addHistoryEntries(geocodeEdit, cgData.getRecentGeocodesForSearch());
- displayByGeocode.setOnClickListener(new FindByGeocodeListener());
+ addHistoryEntries(geocodeEditText, DataStore.getRecentGeocodesForSearch());
- EditUtils.setActionListener((EditText) findViewById(R.id.keyword), new Runnable() {
+ setSearchAction(keywordEditText, buttonSearchKeyword, new Runnable() {
@Override
public void run() {
findByKeywordFn();
}
});
- findByKeyword.setOnClickListener(new FindByKeywordListener());
- EditUtils.setActionListener((EditText) findViewById(R.id.username), new Runnable() {
+ setSearchAction(userNameEditText, buttonSearchUserName, new Runnable() {
@Override
public void run() {
findByUsernameFn();
}
});
- findByUserName.setOnClickListener(new FindByUsernameListener());
- EditUtils.setActionListener((EditText) findViewById(R.id.owner), new Runnable() {
+ setSearchAction(ownerNameEditText, buttonSearchOwner, new Runnable() {
@Override
public void run() {
findByOwnerFn();
}
});
- findByOwner.setOnClickListener(new OnClickListener() {
+
+ setSearchAction(trackableEditText, buttonSearchTrackable, new Runnable() {
@Override
- public void onClick(View arg0) {
- findByOwnerFn();
+ public void run() {
+ findTrackableFn();
}
});
+ addHistoryEntries(trackableEditText, DataStore.getTrackableCodes());
+ disableSuggestions(trackableEditText);
+ }
- EditUtils.setActionListener(trackable, new Runnable() {
-
+ private static void setSearchAction(final EditText editText, final Button button, final Runnable runnable) {
+ EditUtils.setActionListener(editText, runnable);
+ button.setOnClickListener(new View.OnClickListener() {
@Override
- public void run() {
- findTrackableFn();
+ public void onClick(final View arg0) {
+ runnable.run();
}
});
- addHistoryEntries(trackable, cgData.getTrackableCodes());
- disableSuggestions(trackable);
- displayTrackable.setOnClickListener(new FindTrackableListener());
}
private void addHistoryEntries(final AutoCompleteTextView textView, final String[] entries) {
@@ -226,33 +223,15 @@ public class SearchActivity extends AbstractActivity {
}
}
- private final GeoDirHandler geoDirHandler = new GeoDirHandler() {
- @Override
- public void updateGeoData(final IGeoData geo) {
- try {
- if (geo.getCoords() != null) {
- if (latEdit != null) {
- latEdit.setHint(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE_RAW));
- }
- if (lonEdit != null) {
- lonEdit.setHint(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE_RAW));
- }
- }
- } catch (final RuntimeException e) {
- Log.w("Failed to update location.");
- }
- }
- };
-
private class FindByCoordsAction implements OnClickListener {
@Override
- public void onClick(View arg0) {
+ public void onClick(final View arg0) {
final CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(SearchActivity.this, null, null, app.currentGeo());
coordsDialog.setCancelable(true);
coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
@Override
- public void update(Geopoint gp) {
+ public void update(final Geopoint gp) {
buttonLatitude.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
buttonLongitude.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
}
@@ -261,17 +240,9 @@ public class SearchActivity extends AbstractActivity {
}
}
- private class FindByCoordsListener implements View.OnClickListener {
-
- @Override
- public void onClick(View arg0) {
- findByCoordsFn();
- }
- }
-
private void findByCoordsFn() {
- final String latText = buttonLatitude.getText().toString();
- final String lonText = buttonLongitude.getText().toString();
+ final String latText = StringUtils.trim(buttonLatitude.getText().toString());
+ final String lonText = StringUtils.trim(buttonLongitude.getText().toString());
if (StringUtils.isEmpty(latText) || StringUtils.isEmpty(lonText)) {
final IGeoData geo = app.currentGeo();
@@ -281,42 +252,27 @@ public class SearchActivity extends AbstractActivity {
}
} else {
try {
- cgeocaches.startActivityCoordinates(this, new Geopoint(StringUtils.trim(latText), StringUtils.trim(lonText)));
+ CacheListActivity.startActivityCoordinates(this, new Geopoint(latText, lonText));
} catch (final Geopoint.ParseException e) {
showToast(res.getString(e.resource));
}
}
}
- private class FindByKeywordListener implements View.OnClickListener {
-
- @Override
- public void onClick(View arg0) {
- findByKeywordFn();
- }
- }
-
private void findByKeywordFn() {
// find caches by coordinates
- final String keyText = keywordEditText.getText().toString();
+ final String keyText = StringUtils.trim(keywordEditText.getText().toString());
if (StringUtils.isBlank(keyText)) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_keyword));
return;
}
- cgeocaches.startActivityKeyword(this, StringUtils.trim(keyText));
- }
-
- private class FindByAddressListener implements View.OnClickListener {
- @Override
- public void onClick(View arg0) {
- findByAddressFn();
- }
+ CacheListActivity.startActivityKeyword(this, keyText);
}
private void findByAddressFn() {
- final String addText = addressEditText.getText().toString();
+ final String addText = StringUtils.trim(addressEditText.getText().toString());
if (StringUtils.isBlank(addText)) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_address));
@@ -324,34 +280,26 @@ public class SearchActivity extends AbstractActivity {
}
final Intent addressesIntent = new Intent(this, AddressListActivity.class);
- addressesIntent.putExtra(Intents.EXTRA_KEYWORD, StringUtils.trim(addText));
+ addressesIntent.putExtra(Intents.EXTRA_KEYWORD, addText);
startActivity(addressesIntent);
}
- private class FindByUsernameListener implements View.OnClickListener {
-
- @Override
- public void onClick(View arg0) {
- findByUsernameFn();
- }
- }
-
- public void findByUsernameFn() {
- final String usernameText = userNameEditText.getText().toString();
+ public final void findByUsernameFn() {
+ final String usernameText = StringUtils.trim(userNameEditText.getText().toString());
if (StringUtils.isBlank(usernameText)) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_user));
return;
}
- cgeocaches.startActivityUserName(this, StringUtils.trim(usernameText));
+ CacheListActivity.startActivityUserName(this, usernameText);
}
private void findByOwnerFn() {
findByOwnerFn(ownerNameEditText.getText().toString());
}
- private void findByOwnerFn(String userName) {
+ private void findByOwnerFn(final String userName) {
final String usernameText = StringUtils.trimToEmpty(userName);
if (StringUtils.isBlank(usernameText)) {
@@ -359,38 +307,22 @@ public class SearchActivity extends AbstractActivity {
return;
}
- cgeocaches.startActivityOwner(this, StringUtils.trim(usernameText));
- }
-
- private class FindByGeocodeListener implements View.OnClickListener {
-
- @Override
- public void onClick(View arg0) {
- findByGeocodeFn();
- }
+ CacheListActivity.startActivityOwner(this, usernameText);
}
private void findByGeocodeFn() {
- final String geocodeText = geocodeEditText.getText().toString();
+ final String geocodeText = StringUtils.trim(geocodeEditText.getText().toString());
if (StringUtils.isBlank(geocodeText) || geocodeText.equalsIgnoreCase("GC")) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_gccode));
return;
}
- CacheDetailActivity.startActivity(this, StringUtils.trim(geocodeText));
- }
-
- private class FindTrackableListener implements View.OnClickListener {
-
- @Override
- public void onClick(View arg0) {
- findTrackableFn();
- }
+ CacheDetailActivity.startActivity(this, geocodeText);
}
private void findTrackableFn() {
- final String trackableText = trackableEditText.getText().toString();
+ final String trackableText = StringUtils.trim(trackableEditText.getText().toString());
if (StringUtils.isBlank(trackableText) || trackableText.equalsIgnoreCase("TB")) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_tb));
@@ -398,18 +330,18 @@ public class SearchActivity extends AbstractActivity {
}
final Intent trackablesIntent = new Intent(this, TrackableActivity.class);
- trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, StringUtils.trim(trackableText).toUpperCase(Locale.US));
+ trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, trackableText.toUpperCase(Locale.US));
startActivity(trackablesIntent);
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ public final boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.search_activity_options, menu);
return true;
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public final boolean onOptionsItemSelected(final MenuItem item) {
if (item.getItemId() == R.id.menu_search_own_caches) {
findByOwnerFn(Settings.getUsername());
return true;
diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java
index e637d1f..0bdf6c6 100644
--- a/main/src/cgeo/geocaching/SearchResult.java
+++ b/main/src/cgeo/geocaching/SearchResult.java
@@ -8,7 +8,7 @@ import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.gcvote.GCVote;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.os.Parcel;
@@ -199,7 +199,7 @@ public class SearchResult implements Parcelable {
SearchResult result = new SearchResult(this);
result.geocodes.clear();
final ArrayList<Geocache> cachesForVote = new ArrayList<Geocache>();
- final Set<Geocache> caches = cgData.loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB);
+ final Set<Geocache> caches = DataStore.loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB);
int excluded = 0;
for (Geocache cache : caches) {
// Is there any reason to exclude the cache from the list?
@@ -220,11 +220,11 @@ public class SearchResult implements Parcelable {
}
public Geocache getFirstCacheFromResult(final EnumSet<LoadFlag> loadFlags) {
- return CollectionUtils.isNotEmpty(geocodes) ? cgData.loadCache(geocodes.iterator().next(), loadFlags) : null;
+ return CollectionUtils.isNotEmpty(geocodes) ? DataStore.loadCache(geocodes.iterator().next(), loadFlags) : null;
}
public Set<Geocache> getCachesFromSearchResult(final EnumSet<LoadFlag> loadFlags) {
- return cgData.loadCaches(geocodes, loadFlags);
+ return DataStore.loadCaches(geocodes, loadFlags);
}
/** Add the geocode to the search. No cache is loaded into the CacheCache */
@@ -243,7 +243,7 @@ public class SearchResult implements Parcelable {
/** Add the cache geocode to the search and store the cache in the CacheCache */
public boolean addAndPutInCache(final Geocache cache) {
addGeocode(cache.getGeocode());
- return cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
+ return DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
}
public boolean isEmpty() {
@@ -252,7 +252,7 @@ public class SearchResult implements Parcelable {
public boolean hasUnsavedCaches() {
for (final String geocode : getGeocodes()) {
- if (!cgData.isOffline(geocode, null)) {
+ if (!DataStore.isOffline(geocode, null)) {
return true;
}
}
diff --git a/main/src/cgeo/geocaching/SelectMapfileActivity.java b/main/src/cgeo/geocaching/SelectMapfileActivity.java
index 8b50c1f..9d86fa5 100644
--- a/main/src/cgeo/geocaching/SelectMapfileActivity.java
+++ b/main/src/cgeo/geocaching/SelectMapfileActivity.java
@@ -1,14 +1,23 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.files.AbstractFileListActivity;
import cgeo.geocaching.files.IFileSelectionView;
import cgeo.geocaching.files.LocalStorage;
+import cgeo.geocaching.files.SimpleDirChooser;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.FileSelectionListAdapter;
+import org.openintents.intents.FileManagerIntents;
+
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
import java.io.File;
import java.util.ArrayList;
@@ -20,12 +29,40 @@ public class SelectMapfileActivity extends AbstractFileListActivity<FileSelectio
super("map");
}
+ @InjectView(R.id.select_dir) protected Button selectDirectory;
+
private String mapFile;
+ private static int REQUEST_DIRECTORY = 1;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ Views.inject(this);
+
mapFile = Settings.getMapFile();
+
+ selectDirectory.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ try {
+ final Intent dirChooser = new Intent(FileManagerIntents.ACTION_PICK_DIRECTORY);
+ dirChooser.putExtra(FileManagerIntents.EXTRA_TITLE,
+ getString(R.string.simple_dir_chooser_title));
+ dirChooser.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT,
+ getString(android.R.string.ok));
+ startActivityForResult(dirChooser, REQUEST_DIRECTORY);
+ } catch (android.content.ActivityNotFoundException ex) {
+ // OI file manager not available
+ final Intent dirChooser = new Intent(SelectMapfileActivity.this, SimpleDirChooser.class);
+ dirChooser.putExtra(Intents.EXTRA_START_DIR, LocalStorage.getStorage().getAbsolutePath());
+ startActivityForResult(dirChooser, REQUEST_DIRECTORY);
+ }
+ }
+ });
+ selectDirectory.setText(getResources().getString(R.string.simple_dir_chooser_title));
+ selectDirectory.setVisibility(View.VISIBLE);
}
@Override
@@ -70,4 +107,22 @@ public class SelectMapfileActivity extends AbstractFileListActivity<FileSelectio
return this;
}
+ @Override
+ protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (resultCode != RESULT_OK) {
+ return;
+ }
+
+ if (requestCode == REQUEST_DIRECTORY) {
+ final String directory = new File(data.getData().getPath()).getAbsolutePath();
+ mapFile = directory;
+ close();
+ }
+ }
+
+ @Override
+ protected boolean requireFiles() {
+ return false;
+ }
}
diff --git a/main/src/cgeo/geocaching/StaticMapsActivity.java b/main/src/cgeo/geocaching/StaticMapsActivity.java
index 2268df9..7811da5 100644
--- a/main/src/cgeo/geocaching/StaticMapsActivity.java
+++ b/main/src/cgeo/geocaching/StaticMapsActivity.java
@@ -9,7 +9,7 @@ import com.googlecode.androidannotations.annotations.Extra;
import com.googlecode.androidannotations.annotations.OptionsItem;
import com.googlecode.androidannotations.annotations.OptionsMenu;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import android.app.ProgressDialog;
import android.content.Context;
@@ -117,7 +117,7 @@ public class StaticMapsActivity extends AbstractActivity {
for (int level = 1; level <= StaticMapsProvider.MAPS_LEVEL_MAX; level++) {
try {
if (waypointId != null) {
- final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
final Bitmap image = StaticMapsProvider.getWaypointMap(geocode, cache.getWaypointById(waypointId), level);
if (image != null) {
maps.add(image);
@@ -151,7 +151,7 @@ public class StaticMapsActivity extends AbstractActivity {
}
private boolean downloadStaticMaps() {
- final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
if (waypointId == null) {
showToast(res.getString(R.string.info_storing_static_maps));
StaticMapsProvider.storeCacheStaticMap(cache, true);
diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java
index cf279c0..d5cbb13 100644
--- a/main/src/cgeo/geocaching/StaticMapsProvider.java
+++ b/main/src/cgeo/geocaching/StaticMapsProvider.java
@@ -11,8 +11,8 @@ import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
-
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -245,11 +245,8 @@ public final class StaticMapsProvider {
* @param cache
* @return <code>true</code> if at least one map file exists; <code>false</code> otherwise
*/
- public static boolean hasStaticMap(final Geocache cache) {
- if (cache == null) {
- return false;
- }
- final String geocode = cache.getGeocode();
+ public static boolean hasStaticMap(@NonNull final Geocache cache) {
+ final String geocode = cache.getGeocode();
if (StringUtils.isBlank(geocode)) {
return false;
}
diff --git a/main/src/cgeo/geocaching/StatusFragment.java b/main/src/cgeo/geocaching/StatusFragment.java
index e0e714a..4f70f0e 100644
--- a/main/src/cgeo/geocaching/StatusFragment.java
+++ b/main/src/cgeo/geocaching/StatusFragment.java
@@ -38,12 +38,12 @@ public class StatusFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
- cgeoapplication.getInstance().getStatusUpdater().addObserver(statusHandler);
+ CgeoApplication.getInstance().getStatusUpdater().addObserver(statusHandler);
}
@Override
public void onPause() {
- cgeoapplication.getInstance().getStatusUpdater().deleteObserver(statusHandler);
+ CgeoApplication.getInstance().getStatusUpdater().deleteObserver(statusHandler);
super.onPause();
}
diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java
index 20a9ccf..69123fe 100644
--- a/main/src/cgeo/geocaching/TrackableActivity.java
+++ b/main/src/cgeo/geocaching/TrackableActivity.java
@@ -16,6 +16,7 @@ import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.ui.UserActionsClickListener;
+import cgeo.geocaching.ui.UserNameClickListener;
import cgeo.geocaching.ui.logs.TrackableLogsViewCreator;
import cgeo.geocaching.utils.HtmlUtils;
import cgeo.geocaching.utils.Log;
@@ -233,7 +234,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
@Override
public void run() {
if (StringUtils.isNotEmpty(geocode)) {
- trackable = cgData.loadTrackable(geocode);
+ trackable = DataStore.loadTrackable(geocode);
if (trackable == null || trackable.isLoggable()) {
// iterate over the connectors as some codes may be handled by multiple connectors
@@ -418,11 +419,22 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
spotted.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
- CacheDetailActivity.startActivityGuid(TrackableActivity.this, trackable.getSpottedGuid(), trackable.getSpottedName());
+ if (StringUtils.isNotBlank(trackable.getSpottedGuid())) {
+ CacheDetailActivity.startActivityGuid(TrackableActivity.this, trackable.getSpottedGuid(), trackable.getSpottedName());
+ }
+ else {
+ // for geokrety we only know the cache geocode
+ final String cacheCode = trackable.getSpottedName();
+ if (ConnectorFactory.canHandle(cacheCode)) {
+ CacheDetailActivity.startActivity(TrackableActivity.this, cacheCode);
+ }
+ }
}
});
} else if (Trackable.SPOTTED_USER == trackable.getSpottedType()) {
- spotted.setOnClickListener(new UserActionsClickListener());
+ spotted.setOnClickListener(new UserNameClickListener(Html.fromHtml(trackable.getSpottedName()).toString()));
+ } else if (Trackable.SPOTTED_OWNER == trackable.getSpottedType()) {
+ spotted.setOnClickListener(new UserNameClickListener(Html.fromHtml(trackable.getOwner()).toString()));
}
}
diff --git a/main/src/cgeo/geocaching/UsefulAppsActivity.java b/main/src/cgeo/geocaching/UsefulAppsActivity.java
index 41ea96e..08206ff 100644
--- a/main/src/cgeo/geocaching/UsefulAppsActivity.java
+++ b/main/src/cgeo/geocaching/UsefulAppsActivity.java
@@ -60,6 +60,7 @@ public class UsefulAppsActivity extends AbstractActivity {
new HelperApp(R.string.helper_calendar_title, R.string.helper_calendar_description, R.drawable.cgeo, "cgeo.calendar"),
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"),
new HelperApp(R.string.helper_gpsstatus_title, R.string.helper_gpsstatus_description, R.drawable.helper_gpsstatus, "com.eclipsim.gpsstatus2"),
new HelperApp(R.string.helper_bluetoothgps_title, R.string.helper_bluetoothgps_description, R.drawable.helper_bluetoothgps, "googoo.android.btgps"),
new HelperApp(R.string.helper_barcode_title, R.string.helper_barcode_description, R.drawable.helper_barcode, "com.google.zxing.client.android"),
diff --git a/main/src/cgeo/geocaching/Waypoint.java b/main/src/cgeo/geocaching/Waypoint.java
index e39d26a..b204bdd 100644
--- a/main/src/cgeo/geocaching/Waypoint.java
+++ b/main/src/cgeo/geocaching/Waypoint.java
@@ -14,6 +14,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+/**
+ * Note: this class has a natural ordering that is inconsistent with equals.
+ */
public class Waypoint implements IWaypoint, Comparable<Waypoint> {
public static final String PREFIX_OWN = "OWN";
@@ -35,7 +38,7 @@ public class Waypoint implements IWaypoint, Comparable<Waypoint> {
public static void initializeScale() {
// Calculate visited inset based on screen density
- VISITED_INSET = (int) (6.6f * cgeoapplication.getInstance().getResources().getDisplayMetrics().density + 0.5f);
+ VISITED_INSET = (int) (6.6f * CgeoApplication.getInstance().getResources().getDisplayMetrics().density + 0.5f);
}
/**
diff --git a/main/src/cgeo/geocaching/WaypointPopup.java b/main/src/cgeo/geocaching/WaypointPopup.java
index a1ab36a..b1e4b92 100644
--- a/main/src/cgeo/geocaching/WaypointPopup.java
+++ b/main/src/cgeo/geocaching/WaypointPopup.java
@@ -56,7 +56,7 @@ public class WaypointPopup extends AbstractPopupActivity {
@Override
protected void init() {
super.init();
- waypoint = cgData.loadWaypoint(waypointId);
+ waypoint = DataStore.loadWaypoint(waypointId);
try {
if (StringUtils.isNotBlank(waypoint.getName())) {
setTitle(waypoint.getName());
@@ -78,7 +78,7 @@ public class WaypointPopup extends AbstractPopupActivity {
@Override
public void onClick(View arg0) {
- EditWaypointActivity.startActivityEditWaypoint(WaypointPopup.this, waypoint.getId());
+ EditWaypointActivity.startActivityEditWaypoint(WaypointPopup.this, cache, waypoint.getId());
finish();
}
});
@@ -94,7 +94,7 @@ public class WaypointPopup extends AbstractPopupActivity {
}
@Override
- protected void navigateTo() {
+ public void navigateTo() {
NavigationAppFactory.startDefaultNavigationApplication(1, this, waypoint);
}
@@ -119,7 +119,7 @@ public class WaypointPopup extends AbstractPopupActivity {
}
@Override
- protected void showNavigationMenu() {
+ public void showNavigationMenu() {
NavigationAppFactory.showNavigationMenu(this, null, waypoint, null);
}
diff --git a/main/src/cgeo/geocaching/WaypointViewHolder.java b/main/src/cgeo/geocaching/WaypointViewHolder.java
new file mode 100644
index 0000000..33b606e
--- /dev/null
+++ b/main/src/cgeo/geocaching/WaypointViewHolder.java
@@ -0,0 +1,23 @@
+package cgeo.geocaching;
+
+import butterknife.InjectView;
+
+import cgeo.geocaching.ui.AbstractViewHolder;
+
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class WaypointViewHolder extends AbstractViewHolder {
+
+ @InjectView(R.id.coordinates) protected TextView coordinatesView;
+ @InjectView(R.id.info) protected TextView infoView;
+ @InjectView(R.id.name) protected TextView nameView;
+ @InjectView(R.id.note) protected TextView noteView;
+ @InjectView(R.id.wpDefaultNavigation) protected ImageView wpNavView;
+
+ public WaypointViewHolder(View rowView) {
+ super(rowView);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java
index 28c0cdd..6e74928 100644
--- a/main/src/cgeo/geocaching/activity/AbstractActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.activity;
import butterknife.Views;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.network.Cookies;
import cgeo.geocaching.settings.Settings;
@@ -18,7 +18,7 @@ import android.widget.EditText;
public abstract class AbstractActivity extends FragmentActivity implements IAbstractActivity {
- protected cgeoapplication app = null;
+ protected CgeoApplication app = null;
protected Resources res = null;
private boolean keepScreenOn = false;
@@ -86,12 +86,21 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
}
protected void onCreate(final Bundle savedInstanceState, final int resourceLayoutID) {
+ onCreate(savedInstanceState, resourceLayoutID, false);
+ }
+
+ protected void onCreate(final Bundle savedInstanceState, final int resourceLayoutID, boolean useDialogTheme) {
+
super.onCreate(savedInstanceState);
initializeCommonFields();
// non declarative part of layout
- setTheme();
+ if (useDialogTheme) {
+ setTheme(ActivityMixin.getDialogTheme());
+ } else {
+ setTheme();
+ }
setContentView(resourceLayoutID);
// create view variables
@@ -101,7 +110,7 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
private void initializeCommonFields() {
// initialize commonly used members
res = this.getResources();
- app = (cgeoapplication) this.getApplication();
+ app = (CgeoApplication) this.getApplication();
// only needed in some activities, but implemented in super class nonetheless
Cookies.restoreCookieStore(Settings.getCookieStore());
diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
index 93e9b7f..d2bc0b4 100644
--- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.activity;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
@@ -13,7 +13,7 @@ public abstract class AbstractListActivity extends FragmentListActivity implemen
private boolean keepScreenOn = false;
- protected cgeoapplication app = null;
+ protected CgeoApplication app = null;
protected Resources res = null;
protected AbstractListActivity() {
@@ -65,7 +65,7 @@ public abstract class AbstractListActivity extends FragmentListActivity implemen
private void initializeCommonFields() {
// init
res = this.getResources();
- app = (cgeoapplication) this.getApplication();
+ app = (CgeoApplication) this.getApplication();
ActivityMixin.keepScreenOn(this, keepScreenOn);
}
diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java
index 699d5ab..9b1e433 100644
--- a/main/src/cgeo/geocaching/activity/ActivityMixin.java
+++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java
@@ -2,8 +2,8 @@ package cgeo.geocaching.activity;
import cgeo.geocaching.MainActivity;
import cgeo.geocaching.R;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.compatibility.Compatibility;
+import cgeo.geocaching.settings.Settings;
import org.apache.commons.lang3.StringUtils;
@@ -63,14 +63,6 @@ public final class ActivityMixin {
}
}
- public static int getTheme() {
- if (Settings.isLightSkin()) {
- return R.style.light;
- }
-
- return R.style.dark;
- }
-
public static int getDialogTheme() {
// Light theme dialogs don't work on Android Api < 11
if (Settings.isLightSkin() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
diff --git a/main/src/cgeo/geocaching/apps/AbstractApp.java b/main/src/cgeo/geocaching/apps/AbstractApp.java
index 7b6b3d9..494e245 100644
--- a/main/src/cgeo/geocaching/apps/AbstractApp.java
+++ b/main/src/cgeo/geocaching/apps/AbstractApp.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.apps;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.utils.ProcessUtils;
import org.apache.commons.lang3.StringUtils;
@@ -13,16 +13,21 @@ public abstract class AbstractApp implements App {
private final String packageName;
private final String intent;
private final String name;
+ /**
+ * a unique id, defined in res/values/ids.xml
+ */
+ private final int id;
- protected AbstractApp(final String name, final String intent,
+ protected AbstractApp(final String name, final int id, final String intent,
final String packageName) {
this.name = name;
+ this.id = id;
this.intent = intent;
this.packageName = packageName;
}
- protected AbstractApp(final String name, final String intent) {
- this(name, intent, null);
+ protected AbstractApp(final String name, final int id, final String intent) {
+ this(name, id, intent, null);
}
@Override
@@ -38,7 +43,7 @@ public abstract class AbstractApp implements App {
}
@Override
- public boolean isDefaultNavigationApp() {
+ public boolean isUsableAsDefaultNavigationApp() {
return true;
}
@@ -49,11 +54,11 @@ public abstract class AbstractApp implements App {
@Override
public int getId() {
- return getName().hashCode();
+ return id;
}
protected static String getString(int ressourceId) {
- return cgeoapplication.getInstance().getString(ressourceId);
+ return CgeoApplication.getInstance().getString(ressourceId);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
index 53620e4..4b524bf 100644
--- a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
+++ b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
@@ -1,9 +1,8 @@
package cgeo.geocaching.apps;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.WaypointType;
@@ -15,11 +14,11 @@ 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;
-import android.content.Intent;
import android.location.Location;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -30,25 +29,20 @@ import java.util.Locale;
* @see <a href="http://forum.asamm.cz/viewtopic.php?f=29&t=767">Locus forum</a>
*/
public abstract class AbstractLocusApp extends AbstractApp {
- private static final String INTENT = Intent.ACTION_VIEW;
- private static final SimpleDateFormat ISO8601DATE = new SimpleDateFormat("yyyy-MM-dd'T'", Locale.US);
-
- protected AbstractLocusApp() {
- super(getString(R.string.caches_map_locus), INTENT);
- }
+ private static final FastDateFormat ISO8601DATE = FastDateFormat.getInstance("yyyy-MM-dd'T'", Locale.US);
- protected AbstractLocusApp(final String text, final String intent) {
- super(text, intent);
+ protected AbstractLocusApp(final String text, int id, final String intent) {
+ super(text, id, intent);
}
@Override
public boolean isInstalled() {
- return LocusUtils.isLocusAvailable(cgeoapplication.getInstance());
+ return LocusUtils.isLocusAvailable(CgeoApplication.getInstance());
}
/**
* Display a list of caches / waypoints in Locus
- *
+ *
* @param objectsToShow
* which caches/waypoints to show
* @param withCacheWaypoints
diff --git a/main/src/cgeo/geocaching/apps/App.java b/main/src/cgeo/geocaching/apps/App.java
index bc99526..7e70581 100644
--- a/main/src/cgeo/geocaching/apps/App.java
+++ b/main/src/cgeo/geocaching/apps/App.java
@@ -5,14 +5,20 @@ import cgeo.geocaching.Geocache;
public interface App {
public boolean isInstalled();
- public boolean isDefaultNavigationApp();
+ /**
+ * Whether or not an application can be used as the default navigation.
+ */
+ public boolean isUsableAsDefaultNavigationApp();
public String getName();
+ /**
+ * @return the unique ID of the application, defined in res/values/ids.xml
+ */
int getId();
/**
- * whether or not the app can be used with the given cache (may depend on properties of the cache)
+ * Whether or not the app can be used with the given cache (may depend on properties of the cache).
*
* @param cache
* @return
diff --git a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java
index fd7d4b5..c4f2723 100644
--- a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java
@@ -9,8 +9,8 @@ import android.content.Intent;
abstract class AbstractGeneralApp extends AbstractApp implements CacheNavigationApp {
- protected AbstractGeneralApp(String name, String packageName) {
- super(name, null, packageName);
+ protected AbstractGeneralApp(final String name, final int id, final String packageName) {
+ super(name, id, null, packageName);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java b/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java
index 9cfafb4..34c9074 100644
--- a/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java
@@ -7,7 +7,7 @@ import cgeo.geocaching.enumerations.CacheAttribute;
public class CacheBeaconApp extends AbstractGeneralApp {
public CacheBeaconApp() {
- super(getString(R.string.cache_menu_cachebeacon), "de.fun2code.android.cachebeacon");
+ super(getString(R.string.cache_menu_cachebeacon), R.id.cache_app_cache_beacon, "de.fun2code.android.cachebeacon");
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/GccApp.java b/main/src/cgeo/geocaching/apps/cache/GccApp.java
index 0bbc2dd..4423977 100644
--- a/main/src/cgeo/geocaching/apps/cache/GccApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/GccApp.java
@@ -10,7 +10,7 @@ public class GccApp extends AbstractGeneralApp {
private static final String PACKAGE_PRO = "eisbehr.gcc.pro";
public GccApp() {
- super(getString(R.string.cache_menu_gcc), null);
+ super(getString(R.string.cache_menu_gcc), R.id.cache_app_gcc, null);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java
index 39e1963..79a5975 100644
--- a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java
@@ -1,12 +1,12 @@
package cgeo.geocaching.apps.cache;
-import cgeo.geocaching.R;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
import cgeo.geocaching.enumerations.CacheType;
public class WhereYouGoApp extends AbstractGeneralApp {
public WhereYouGoApp() {
- super(getString(R.string.cache_menu_whereyougo), "menion.android.whereyougo");
+ super(getString(R.string.cache_menu_whereyougo), R.id.cache_app_whereyougo, "menion.android.whereyougo");
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java
index a3ea57e..75ea056 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java
@@ -1,8 +1,11 @@
package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.apps.AbstractApp;
+import cgeo.geocaching.geopoint.Geopoint;
import android.app.Activity;
@@ -11,21 +14,32 @@ import android.app.Activity;
*/
abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp, GeopointNavigationApp {
- protected AbstractPointNavigationApp(String name, String intent) {
- super(name, intent);
+ protected AbstractPointNavigationApp(final String name, final int id, final String intent) {
+ super(name, id, intent);
}
- protected AbstractPointNavigationApp(String name, String intent, String packageName) {
- super(name, intent, packageName);
+ protected AbstractPointNavigationApp(final String name, final int id, final String intent, final String packageName) {
+ super(name, id, intent, packageName);
}
@Override
public void navigate(Activity activity, Geocache cache) {
- navigate(activity, cache.getCoords());
+ final Geopoint coords = cache.getCoords();
+ if (coords != null) {
+ navigate(activity, coords);
+ } else {
+ ActivityMixin.showToast(activity, activity.getResources().getString(R.string.err_nav_no_coordinates));
+ }
}
@Override
public void navigate(Activity activity, Waypoint waypoint) {
+ final Geopoint coords = waypoint.getCoords();
+ if (coords != null) {
+ navigate(activity, coords);
+ } else {
+ ActivityMixin.showToast(activity, activity.getResources().getString(R.string.err_nav_no_coordinates));
+ }
navigate(activity, waypoint.getCoords());
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
index d898d7e..c42c2a2 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
@@ -1,12 +1,12 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.ILogable;
import cgeo.geocaching.R;
import cgeo.geocaching.StaticMapsActivity;
import cgeo.geocaching.StaticMapsProvider;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.apps.AbstractApp;
@@ -15,8 +15,8 @@ import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp {
- protected AbstractStaticMapsApp(String name) {
- super(name, null);
+ protected AbstractStaticMapsApp(final String name, final int id) {
+ super(name, id, null);
}
@Override
@@ -25,7 +25,7 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat
}
@Override
- public boolean isDefaultNavigationApp() {
+ public boolean isUsableAsDefaultNavigationApp() {
return false;
}
@@ -34,7 +34,7 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat
return false;
}
String geocode = waypoint.getGeocode();
- if (StringUtils.isNotEmpty(geocode) && cgData.isOffline(geocode, null)) {
+ if (StringUtils.isNotEmpty(geocode) && DataStore.isOffline(geocode, null)) {
return StaticMapsProvider.hasStaticMapForWaypoint(geocode, waypoint);
}
return false;
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
index 47010df..03d2220 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
@@ -1,18 +1,17 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.CompassActivity;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.CompassActivity;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.ui.Formatter;
import android.app.Activity;
class CompassApp extends AbstractPointNavigationApp {
CompassApp() {
- super(getString(R.string.compass_title), null);
+ super(getString(R.string.compass_title), R.id.cache_app_compass, null);
}
@Override
@@ -33,8 +32,7 @@ class CompassApp extends AbstractPointNavigationApp {
@Override
public void navigate(Activity activity, Geocache cache) {
- CompassActivity.startActivity(activity, cache.getGeocode(), cache.getName(), cache.getCoords(), null,
- Formatter.formatCacheInfoShort(cache));
+ CompassActivity.startActivity(activity, cache);
}
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
index bc422d4..19b5e02 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
@@ -9,7 +9,7 @@ import android.app.Activity;
class DownloadStaticMapsApp extends AbstractStaticMapsApp {
DownloadStaticMapsApp() {
- super(getString(R.string.cache_menu_download_map_static));
+ super(getString(R.string.cache_menu_download_map_static), R.id.cache_app_download_static_maps);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java
index 4cbfa00..60d6e31 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java
@@ -12,7 +12,7 @@ import android.net.Uri;
class GoogleMapsApp extends AbstractPointNavigationApp {
GoogleMapsApp() {
- super(getString(R.string.cache_menu_map_ext), null);
+ super(getString(R.string.cache_menu_map_ext), R.id.cache_app_google_maps, null);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java
index a84b7e8..c4351bb 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.maps.MapProviderFactory;
import cgeo.geocaching.utils.Log;
@@ -14,7 +14,7 @@ import android.net.Uri;
public class GoogleMapsDirectionApp extends AbstractPointNavigationApp {
protected GoogleMapsDirectionApp() {
- super(getString(R.string.cache_menu_maps_directions), null);
+ super(getString(R.string.cache_menu_maps_directions), R.id.cache_app_google_maps_direction, null);
}
@Override
@@ -25,7 +25,7 @@ public class GoogleMapsDirectionApp extends AbstractPointNavigationApp {
@Override
public void navigate(Activity activity, Geopoint coords) {
try {
- IGeoData geo = cgeoapplication.getInstance().currentGeo();
+ IGeoData geo = CgeoApplication.getInstance().currentGeo();
final Geopoint coordsNow = geo == null ? null : geo.getCoords();
if (coordsNow != null) {
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
index a3532a5..902eebf 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
@@ -12,8 +12,8 @@ abstract class GoogleNavigationApp extends AbstractPointNavigationApp {
private final String mode;
- protected GoogleNavigationApp(final int nameResourceId, final String mode) {
- super(getString(nameResourceId), null);
+ protected GoogleNavigationApp(final int nameResourceId, final int id, final String mode) {
+ super(getString(nameResourceId), id, null);
this.mode = mode;
}
@@ -36,19 +36,19 @@ abstract class GoogleNavigationApp extends AbstractPointNavigationApp {
static class GoogleNavigationWalkingApp extends GoogleNavigationApp {
GoogleNavigationWalkingApp() {
- super(R.string.cache_menu_navigation_walk, "w");
+ super(R.string.cache_menu_navigation_walk, R.id.cache_app_google_navigation_walk, "w");
}
}
static class GoogleNavigationDrivingApp extends GoogleNavigationApp {
GoogleNavigationDrivingApp() {
- super(R.string.cache_menu_navigation_drive, "d");
+ super(R.string.cache_menu_navigation_drive, R.id.cache_app_google_navigation_drive, "d");
}
}
static class GoogleNavigationBikeApp extends GoogleNavigationApp {
GoogleNavigationBikeApp() {
- super(R.string.cache_menu_navigation_bike, "b");
+ super(R.string.cache_menu_navigation_bike, R.id.cache_app_google_navigation_bike, "b");
}
}
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java b/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java
index cdf14f0..540b025 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java
@@ -12,7 +12,7 @@ import android.app.Activity;
class InternalMap extends AbstractPointNavigationApp {
InternalMap() {
- super(getString(R.string.cache_menu_map), null);
+ super(getString(R.string.cache_menu_map), R.id.cache_app_internal_map, null);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java b/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java
index 8b64ac8..b60d78a 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java
@@ -1,15 +1,24 @@
package cgeo.geocaching.apps.cache.navi;
+
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
import cgeo.geocaching.apps.AbstractLocusApp;
import android.app.Activity;
+import android.content.Intent;
import java.util.Collections;
class LocusApp extends AbstractLocusApp implements CacheNavigationApp, WaypointNavigationApp {
+ private static final String INTENT = Intent.ACTION_VIEW;
+
+ protected LocusApp() {
+ super(getString(R.string.caches_map_locus), R.id.cache_app_locus, INTENT);
+ }
+
@Override
public boolean isEnabled(Waypoint waypoint) {
return waypoint.getCoords() != null;
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
index ec6b3e1..dd02bc1 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.apps.AbstractAppFactory;
import cgeo.geocaching.apps.App;
@@ -16,10 +16,11 @@ import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationWalki
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.settings.Settings;
+import org.eclipse.jdt.annotation.Nullable;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
-import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
@@ -214,7 +215,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
public static List<NavigationAppsEnum> getInstalledDefaultNavigationApps() {
final List<NavigationAppsEnum> installedNavigationApps = new ArrayList<NavigationAppsEnum>();
for (final NavigationAppsEnum appEnum : NavigationAppsEnum.values()) {
- if (appEnum.app.isInstalled() && appEnum.app.isDefaultNavigationApp()) {
+ if (appEnum.app.isInstalled() && appEnum.app.isUsableAsDefaultNavigationApp()) {
installedNavigationApps.add(appEnum);
}
}
@@ -222,46 +223,9 @@ public final class NavigationAppFactory extends AbstractAppFactory {
}
/**
- * This offset is used to build unique menu ids to avoid collisions of ids in menus
- */
- private static final int MENU_ITEM_OFFSET = 12345;
-
-
- /**
- * Adds the installed navigation tools to the given menu.
- * Use {@link #onMenuItemSelected(MenuItem, Activity, cgeo.geocaching.Geocache)} on
- * selection event to start the selected navigation tool.
- *
- * <b>Only use this way if {@link #showNavigationMenu(Activity, cgeo.geocaching.Geocache, cgeo.geocaching.Waypoint, Geopoint, boolean, boolean)} is
- * not suitable for the given usecase.</b>
- *
- * @param menu
- */
- public static void addMenuItems(final Menu menu, final Geocache cache) {
- for (final NavigationAppsEnum navApp : getInstalledNavigationApps()) {
- if (navApp.app instanceof CacheNavigationApp) {
- final CacheNavigationApp cacheApp = (CacheNavigationApp) navApp.app;
- if (cacheApp.isEnabled(cache) && Settings.isUseNavigationApp(navApp)) {
- menu.add(0, MENU_ITEM_OFFSET + navApp.id, 0, navApp.app.getName());
- }
- }
- }
- }
-
- public static void addMenuItems(final Menu menu, final Waypoint waypoint) {
- for (final NavigationAppsEnum navApp : getInstalledNavigationApps()) {
- if (navApp.app instanceof WaypointNavigationApp) {
- final WaypointNavigationApp waypointApp = (WaypointNavigationApp) navApp.app;
- if (waypointApp.isEnabled(waypoint) && Settings.isUseNavigationApp(navApp)) {
- menu.add(0, MENU_ITEM_OFFSET + navApp.id, 0, navApp.app.getName());
- }
- }
- }
- }
-
- /**
- * Handles menu selections for menu entries created with {@link #addMenuItems(Menu, cgeo.geocaching.Geocache)}.
- *
+ * Handles menu selections for menu entries created with
+ * {@link #showNavigationMenu(Activity, Geocache, Waypoint, Geopoint)}.
+ *
* @param item
* @param activity
* @param cache
@@ -273,20 +237,14 @@ public final class NavigationAppFactory extends AbstractAppFactory {
return menuItem != null;
}
- private static void navigateCache(Activity activity, Geocache cache, App app) {
+ private static void navigateCache(Activity activity, Geocache cache, @Nullable App app) {
if (app instanceof CacheNavigationApp) {
final CacheNavigationApp cacheApp = (CacheNavigationApp) app;
cacheApp.navigate(activity, cache);
}
}
- public static boolean onMenuItemSelected(final MenuItem item, Activity activity, Waypoint waypoint) {
- final App menuItem = getAppFromMenuItem(item);
- navigateWaypoint(activity, waypoint, menuItem);
- return menuItem != null;
- }
-
- private static void navigateWaypoint(Activity activity, Waypoint waypoint, App app) {
+ private static void navigateWaypoint(Activity activity, Waypoint waypoint, @Nullable App app) {
if (app instanceof WaypointNavigationApp) {
final WaypointNavigationApp waypointApp = (WaypointNavigationApp) app;
waypointApp.navigate(activity, waypoint);
@@ -300,10 +258,11 @@ public final class NavigationAppFactory extends AbstractAppFactory {
}
}
+ @Nullable
private static App getAppFromMenuItem(MenuItem item) {
final int id = item.getItemId();
for (final NavigationAppsEnum navApp : NavigationAppsEnum.values()) {
- if (MENU_ITEM_OFFSET + navApp.id == id) {
+ if (navApp.id == id) {
return navApp.app;
}
}
@@ -320,7 +279,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
*/
public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, Geocache cache) {
if (cache == null || cache.getCoords() == null) {
- ActivityMixin.showToast(activity, cgeoapplication.getInstance().getString(R.string.err_location_unknown));
+ ActivityMixin.showToast(activity, CgeoApplication.getInstance().getString(R.string.err_location_unknown));
return;
}
@@ -342,7 +301,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
*/
public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, Waypoint waypoint) {
if (waypoint == null || waypoint.getCoords() == null) {
- ActivityMixin.showToast(activity, cgeoapplication.getInstance().getString(R.string.err_location_unknown));
+ ActivityMixin.showToast(activity, CgeoApplication.getInstance().getString(R.string.err_location_unknown));
return;
}
navigateWaypoint(activity, waypoint, getDefaultNavigationApplication(defaultNavigation));
@@ -356,7 +315,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
*/
public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, final Geopoint destination) {
if (destination == null) {
- ActivityMixin.showToast(activity, cgeoapplication.getInstance().getString(R.string.err_location_unknown));
+ ActivityMixin.showToast(activity, CgeoApplication.getInstance().getString(R.string.err_location_unknown));
return;
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
index 7966733..da988aa 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
@@ -13,7 +13,7 @@ class NavigonApp extends AbstractPointNavigationApp {
private static final String INTENT_EXTRA_KEY_LONGITUDE = "longitude";
NavigonApp() {
- super(getString(R.string.cache_menu_navigon), INTENT);
+ super(getString(R.string.cache_menu_navigon), R.id.cache_app_navigon, INTENT);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java
index 24ef81b..5d645f7 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java
@@ -11,7 +11,7 @@ class OruxMapsApp extends AbstractPointNavigationApp {
private static final String INTENT = "com.oruxmaps.VIEW_MAP_ONLINE";
OruxMapsApp() {
- super(getString(R.string.cache_menu_oruxmaps), INTENT);
+ super(getString(R.string.cache_menu_oruxmaps), R.id.cache_app_orux_maps, INTENT);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java
index b203aeb..82d144e 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java
@@ -16,7 +16,7 @@ class RMapsApp extends AbstractPointNavigationApp {
private static final String INTENT = "com.robert.maps.action.SHOW_POINTS";
RMapsApp() {
- super(getString(R.string.cache_menu_rmaps), INTENT);
+ super(getString(R.string.cache_menu_rmaps), R.id.cache_app_rmaps, INTENT);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java b/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java
index b01539c..ffa6650 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java
@@ -12,7 +12,7 @@ class RadarApp extends AbstractPointNavigationApp {
private static final String PACKAGE_NAME = "com.eclipsim.gpsstatus2";
RadarApp() {
- super(getString(R.string.cache_menu_radar), INTENT, PACKAGE_NAME);
+ super(getString(R.string.cache_menu_radar), R.id.cache_app_radar, INTENT, PACKAGE_NAME);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java b/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
index 1dd57a3..9e1b3f0 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
@@ -1,15 +1,15 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.Geocache;
import android.app.Activity;
class StaticMapApp extends AbstractStaticMapsApp {
StaticMapApp() {
- super(getString(R.string.cache_menu_map_static));
+ super(getString(R.string.cache_menu_map_static), R.id.cache_app_show_static_maps);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java b/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java
index e2c0828..7294a40 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.utils.ProcessUtils;
@@ -17,7 +17,7 @@ class StreetviewApp extends AbstractPointNavigationApp {
private static final boolean INSTALLED = ProcessUtils.isInstalled(PACKAGE_NAME_STREET_VIEW);
StreetviewApp() {
- super(getString(R.string.cache_menu_streetview), null);
+ super(getString(R.string.cache_menu_streetview), R.id.cache_app_street_view, null);
}
@Override
@@ -31,7 +31,7 @@ class StreetviewApp extends AbstractPointNavigationApp {
activity.startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("google.streetview:cbll=" + point.getLatitude() + "," + point.getLongitude())));
} catch (final ActivityNotFoundException e) {
- ActivityMixin.showToast(activity, cgeoapplication.getInstance().getString(R.string.err_application_no));
+ ActivityMixin.showToast(activity, CgeoApplication.getInstance().getString(R.string.err_application_no));
}
}
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/SygicNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/SygicNavigationApp.java
index e30bfc1..76b7f0e 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/SygicNavigationApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/SygicNavigationApp.java
@@ -17,7 +17,7 @@ public class SygicNavigationApp extends AbstractPointNavigationApp {
private static final String PACKAGE = "com.sygic.aura";
SygicNavigationApp() {
- super(getString(R.string.cache_menu_sygic), null, PACKAGE);
+ super(getString(R.string.cache_menu_sygic), R.id.cache_app_sygic, null, PACKAGE);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cachelist/LocusCacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/AbstractLocusCacheListApp.java
index cd0289a..6411758 100644
--- a/main/src/cgeo/geocaching/apps/cachelist/LocusCacheListApp.java
+++ b/main/src/cgeo/geocaching/apps/cachelist/AbstractLocusCacheListApp.java
@@ -1,23 +1,23 @@
package cgeo.geocaching.apps.cachelist;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.Geocache;
import cgeo.geocaching.apps.AbstractLocusApp;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import android.app.Activity;
import android.content.Intent;
import java.util.List;
-class LocusCacheListApp extends AbstractLocusApp implements CacheListApp {
+abstract class AbstractLocusCacheListApp extends AbstractLocusApp implements CacheListApp {
private boolean export;
- public LocusCacheListApp(boolean export) {
- super(getString(export ? R.string.caches_map_locus_export : R.string.caches_map_locus), Intent.ACTION_VIEW);
+ public AbstractLocusCacheListApp(final int id, boolean export) {
+ super(getString(export ? R.string.caches_map_locus_export : R.string.caches_map_locus), id, Intent.ACTION_VIEW);
this.export = export;
}
diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java
index ca06c52..4df9d26 100644
--- a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java
@@ -20,8 +20,8 @@ public final class CacheListAppFactory extends AbstractAppFactory {
private static class LazyHolder {
public static final CacheListApp[] apps = {
new InternalCacheListMap(),
- new LocusCacheListApp(false),
- new LocusCacheListApp(true)
+ new LocusShowCacheListApp(),
+ new LocusExportCacheListApp()
};
}
@@ -29,35 +29,45 @@ public final class CacheListAppFactory extends AbstractAppFactory {
* @param menu
* @param activity
* @param res
- * @return the added menu item (also for a sub menu, then the menu item in the parent menu is returned)
*/
- public static MenuItem addMenuItems(final Menu menu, final Activity activity, final Resources res) {
+ public static void addMenuItems(final Menu menu, final Activity activity, final Resources res) {
+ final List<CacheListApp> activeApps = getActiveApps();
+ if (activeApps.isEmpty()) {
+ return;
+ }
+ if (activeApps.size() == 1) {
+ final MenuItem subItem = menu.findItem(R.id.menu_cache_list_app);
+ subItem.setVisible(true);
+ subItem.setTitle(activeApps.get(0).getName());
+ } else {
+ final MenuItem subItem = menu.findItem(R.id.submenu_cache_list_app);
+ subItem.setVisible(true);
+ final SubMenu subMenu = subItem.getSubMenu();
+ for (final CacheListApp app : activeApps) {
+ subMenu.add(0, app.getId(), 0, app.getName());
+ }
+ }
+ }
+
+ private static List<CacheListApp> getActiveApps() {
final List<CacheListApp> activeApps = new ArrayList<CacheListApp>(LazyHolder.apps.length);
for (final CacheListApp app : LazyHolder.apps) {
if (app.isInstalled()) {
activeApps.add(app);
}
}
- // use a new sub menu, if more than one app is available
- switch (activeApps.size()) {
- case 0:
- return null;
- case 1:
- return menu.add(0, activeApps.get(0).getId(), 0,
- activeApps.get(0).getName()).setIcon(R.drawable.ic_menu_mapmode);
- default:
- final SubMenu subMenu = menu.addSubMenu(0, 101, 0,
- res.getString(R.string.caches_on_map)).setIcon(R.drawable.ic_menu_mapmode);
- for (final CacheListApp app : activeApps) {
- subMenu.add(0, app.getId(), 0, app.getName());
- }
- return subMenu.getItem();
- }
+ return activeApps;
}
public static boolean onMenuItemSelected(final MenuItem item, final List<Geocache> caches, final Activity activity,
final SearchResult search) {
- final CacheListApp app = (CacheListApp) getAppFromMenuItem(item, LazyHolder.apps);
+ CacheListApp app;
+ if (item.getItemId() == R.id.menu_cache_list_app) {
+ app = getActiveApps().get(0);
+ }
+ else {
+ app = (CacheListApp) getAppFromMenuItem(item, LazyHolder.apps);
+ }
if (app != null) {
try {
boolean result = app.invoke(caches, activity, search);
diff --git a/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java b/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java
index 38fb499..9216bc0 100644
--- a/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java
+++ b/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.apps.cachelist;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.Geocache;
import cgeo.geocaching.apps.AbstractApp;
import cgeo.geocaching.maps.CGeoMap;
@@ -13,7 +13,7 @@ import java.util.List;
class InternalCacheListMap extends AbstractApp implements CacheListApp {
InternalCacheListMap() {
- super(getString(R.string.cache_menu_map), null);
+ super(getString(R.string.cache_menu_map), R.id.cache_list_app_map, null);
}
@Override
diff --git a/main/src/cgeo/geocaching/apps/cachelist/LocusExportCacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/LocusExportCacheListApp.java
new file mode 100644
index 0000000..adaa849
--- /dev/null
+++ b/main/src/cgeo/geocaching/apps/cachelist/LocusExportCacheListApp.java
@@ -0,0 +1,11 @@
+package cgeo.geocaching.apps.cachelist;
+
+import cgeo.geocaching.R;
+
+final class LocusExportCacheListApp extends AbstractLocusCacheListApp {
+
+ public LocusExportCacheListApp() {
+ super(R.id.cache_list_app_locus_export, true);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/apps/cachelist/LocusShowCacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/LocusShowCacheListApp.java
new file mode 100644
index 0000000..32c5cb6
--- /dev/null
+++ b/main/src/cgeo/geocaching/apps/cachelist/LocusShowCacheListApp.java
@@ -0,0 +1,11 @@
+package cgeo.geocaching.apps.cachelist;
+
+import cgeo.geocaching.R;
+
+final class LocusShowCacheListApp extends AbstractLocusCacheListApp {
+
+ public LocusShowCacheListApp() {
+ super(R.id.cache_list_app_locus_show, false);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java
index f08ac22..eb2be4b 100644
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.compatibility;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import android.annotation.TargetApi;
import android.content.Context;
@@ -18,7 +18,7 @@ public class AndroidLevel13 implements AndroidLevel13Interface {
@Override
public Point getDisplaySize() {
Point dimensions = new Point();
- ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE))
+ ((WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay().getSize(dimensions);
return dimensions;
}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java
index ded20cb..56c784f 100644
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.compatibility;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import android.content.Context;
import android.graphics.Point;
@@ -22,7 +22,7 @@ public class AndroidLevel13Emulation implements AndroidLevel13Interface {
}
private static Display getDisplay() {
- return ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE))
+ return ((WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
}
}
diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java
index b93cda0..3ec0580 100644
--- a/main/src/cgeo/geocaching/connector/AbstractConnector.java
+++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java
@@ -3,10 +3,15 @@ package cgeo.geocaching.connector;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogCacheActivity;
import cgeo.geocaching.R;
+import cgeo.geocaching.enumerations.CacheType;
+import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.geopoint.Geopoint;
import org.apache.commons.lang3.StringUtils;
+import java.util.ArrayList;
+import java.util.List;
+
public abstract class AbstractConnector implements IConnector {
@Override
@@ -146,4 +151,41 @@ public abstract class AbstractConnector implements IConnector {
}
return R.drawable.marker_other;
}
+
+ @Override
+ public List<LogType> getPossibleLogTypes(Geocache geocache) {
+ final List<LogType> logTypes = new ArrayList<LogType>();
+ if (geocache.isEventCache()) {
+ logTypes.add(LogType.WILL_ATTEND);
+ logTypes.add(LogType.ATTENDED);
+ if (geocache.isOwner()) {
+ logTypes.add(LogType.ANNOUNCEMENT);
+ }
+ } else if (CacheType.WEBCAM == geocache.getType()) {
+ logTypes.add(LogType.WEBCAM_PHOTO_TAKEN);
+ } else {
+ logTypes.add(LogType.FOUND_IT);
+ }
+ if (!geocache.isEventCache()) {
+ logTypes.add(LogType.DIDNT_FIND_IT);
+ }
+ logTypes.add(LogType.NOTE);
+ if (!geocache.isEventCache()) {
+ logTypes.add(LogType.NEEDS_MAINTENANCE);
+ }
+ if (geocache.isOwner()) {
+ logTypes.add(LogType.OWNER_MAINTENANCE);
+ if (geocache.isDisabled()) {
+ logTypes.add(LogType.ENABLE_LISTING);
+ }
+ else {
+ logTypes.add(LogType.TEMP_DISABLE_LISTING);
+ }
+ logTypes.add(LogType.ARCHIVE);
+ }
+ if (!geocache.isArchived() && !geocache.isOwner()) {
+ logTypes.add(LogType.NEEDS_ARCHIVE);
+ }
+ return logTypes;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
index 54e3447..3fdc11b 100644
--- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java
+++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
@@ -6,6 +6,7 @@ import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Trackable;
import cgeo.geocaching.connector.capability.ILogin;
import cgeo.geocaching.connector.capability.ISearchByCenter;
+import cgeo.geocaching.connector.capability.ISearchByKeyword;
import cgeo.geocaching.connector.capability.ISearchByViewPort;
import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.connector.oc.OCApiConnector;
@@ -60,6 +61,8 @@ public final class ConnectorFactory {
private static final ISearchByCenter[] searchByCenterConns;
+ private static final ISearchByKeyword[] searchByKeywordConns;
+
static {
final List<ISearchByViewPort> vpConns = new ArrayList<ISearchByViewPort>();
for (final IConnector conn : CONNECTORS) {
@@ -77,6 +80,15 @@ public final class ConnectorFactory {
}
}
searchByCenterConns = centerConns.toArray(new ISearchByCenter[centerConns.size()]);
+
+ final List<ISearchByKeyword> keywordConns = new ArrayList<ISearchByKeyword>();
+ for (final IConnector conn : CONNECTORS) {
+ // GCConnector is handled specially, omit it here!
+ if (conn instanceof ISearchByKeyword && !(conn instanceof GCConnector)) {
+ keywordConns.add((ISearchByKeyword) conn);
+ }
+ }
+ searchByKeywordConns = keywordConns.toArray(new ISearchByKeyword[keywordConns.size()]);
}
public static IConnector[] getConnectors() {
@@ -87,6 +99,10 @@ public final class ConnectorFactory {
return searchByCenterConns;
}
+ public static ISearchByKeyword[] getSearchByKeywordConnectors() {
+ return searchByKeywordConns;
+ }
+
public static ILogin[] getActiveLiveConnectors() {
final List<ILogin> liveConns = new ArrayList<ILogin>();
for (final IConnector conn : CONNECTORS) {
diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java
index 4ab7bde..2262e47 100644
--- a/main/src/cgeo/geocaching/connector/IConnector.java
+++ b/main/src/cgeo/geocaching/connector/IConnector.java
@@ -3,8 +3,11 @@ package cgeo.geocaching.connector;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.ICache;
import cgeo.geocaching.LogCacheActivity;
+import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.geopoint.Geopoint;
+import java.util.List;
+
public interface IConnector {
/**
* get name for display (currently only used in links)
@@ -208,4 +211,13 @@ public interface IConnector {
* Whether to return the enabled or disabled marker type
*/
public int getCacheMapMarkerId(boolean disabled);
+
+ /**
+ * Get the list of <b>potentially</b> possible log types for a cache. Those may still be filter further during the
+ * actual logging activity.
+ *
+ * @param geocache
+ * @return
+ */
+ public List<LogType> getPossibleLogTypes(Geocache geocache);
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
index 3fdd61f..91dd094 100644
--- a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
@@ -1,14 +1,13 @@
package cgeo.geocaching.connector.capability;
import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.geopoint.Geopoint;
/**
* connector capability for online searching caches around a center coordinate, sorted by distance
*
*/
-public interface ISearchByCenter {
+public interface ISearchByCenter extends IConnector {
public SearchResult searchByCenter(final Geopoint center);
-
- public boolean isActivated();
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java b/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java
index c3d6bba..4c16049 100644
--- a/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java
@@ -1,12 +1,13 @@
package cgeo.geocaching.connector.capability;
import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.utils.CancellableHandler;
/**
* connector capability of searching online for a cache by geocode
- *
+ *
*/
-public interface ISearchByGeocode {
+public interface ISearchByGeocode extends IConnector {
public SearchResult searchByGeocode(final String geocode, final String guid, final CancellableHandler handler);
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByKeyword.java b/main/src/cgeo/geocaching/connector/capability/ISearchByKeyword.java
new file mode 100644
index 0000000..09b2423
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByKeyword.java
@@ -0,0 +1,12 @@
+package cgeo.geocaching.connector.capability;
+
+import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.connector.IConnector;
+
+/**
+ * connector capability of searching online for a cache by name
+ *
+ */
+public interface ISearchByKeyword extends IConnector {
+ public SearchResult searchByName(final String name);
+}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
index f1bd2ce..4954017 100644
--- a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
@@ -1,10 +1,9 @@
package cgeo.geocaching.connector.capability;
import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.geopoint.Viewport;
-public interface ISearchByViewPort {
+public interface ISearchByViewPort extends IConnector {
public SearchResult searchByViewport(final Viewport viewport, final String[] tokens);
-
- public boolean isActivated();
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index 9ac9c9d..d5f7bf4 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -1,12 +1,12 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.ICache;
import cgeo.geocaching.LogCacheActivity;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.AbstractConnector;
import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.capability.ILogin;
@@ -21,7 +21,7 @@ import cgeo.geocaching.settings.SettingsActivity;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.content.Context;
@@ -80,7 +80,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
@Override
public boolean supportsPersonalNote() {
- return true;
+ return Settings.isPremiumMember();
}
@Override
@@ -137,10 +137,10 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
if (StringUtils.isEmpty(page)) {
final SearchResult search = new SearchResult();
- if (cgData.isThere(geocode, guid, true, false)) {
+ if (DataStore.isThere(geocode, guid, true, false)) {
if (StringUtils.isBlank(geocode) && StringUtils.isNotBlank(guid)) {
Log.i("Loading old cache from cache.");
- search.addGeocode(cgData.getGeocodeForGuid(guid));
+ search.addGeocode(DataStore.getGeocodeForGuid(guid));
} else {
search.addGeocode(geocode);
}
@@ -152,6 +152,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
search.setError(StatusCode.COMMUNICATION_ERROR);
return search;
}
+ assert page != null;
final SearchResult searchResult = GCParser.parseCache(page, handler);
@@ -189,7 +190,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean addToWatchlist(Geocache cache) {
final boolean added = GCParser.addToWatchlist(cache);
if (added) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return added;
}
@@ -198,7 +199,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean removeFromWatchlist(Geocache cache) {
final boolean removed = GCParser.removeFromWatchlist(cache);
if (removed) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return removed;
}
@@ -215,7 +216,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public static boolean addToFavorites(Geocache cache) {
final boolean added = GCParser.addToFavorites(cache);
if (added) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return added;
}
@@ -232,7 +233,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public static boolean removeFromFavorites(Geocache cache) {
final boolean removed = GCParser.removeFromFavorites(cache);
if (removed) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return removed;
}
@@ -241,7 +242,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) {
final boolean uploaded = GCParser.uploadModifiedCoordinates(cache, wpt);
if (uploaded) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return uploaded;
}
@@ -250,7 +251,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean deleteModifiedCoordinates(Geocache cache) {
final boolean deleted = GCParser.deleteModifiedCoordinates(cache);
if (deleted) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return deleted;
}
@@ -259,7 +260,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean uploadPersonalNote(Geocache cache) {
final boolean uploaded = GCParser.uploadPersonalNote(cache);
if (uploaded) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return uploaded;
}
@@ -299,13 +300,13 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
final StatusCode status = Login.login();
if (status == StatusCode.NO_ERROR) {
- cgeoapplication.getInstance().checkLogin = false;
+ CgeoApplication.getInstance().checkLogin = false;
Login.detectGcCustomDate();
}
- if (cgeoapplication.getInstance().showLoginToast && handler != null) {
+ if (CgeoApplication.getInstance().showLoginToast && handler != null) {
handler.sendMessage(handler.obtainMessage(0, status));
- cgeoapplication.getInstance().showLoginToast = false;
+ CgeoApplication.getInstance().showLoginToast = false;
// invoke settings activity to insert login details
if (status == StatusCode.NO_LOGIN_INFO_STORED && fromActivity != null) {
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
index 84c27fe..152b8a2 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
@@ -58,7 +58,7 @@ public final class GCConstants {
public final static Pattern PATTERN_ATTRIBUTES = Pattern.compile("Attributes\\s*</h3>[^<]*<div class=\"WidgetBody\">((?:[^<]*<img src=\"[^\"]+\" alt=\"[^\"]+\"[^>]*>)+?)[^<]*<p");
/** Two groups ! */
public final static Pattern PATTERN_ATTRIBUTESINSIDE = Pattern.compile("[^<]*<img src=\"([^\"]+)\" alt=\"([^\"]+?)\"");
- public final static Pattern PATTERN_SPOILER_IMAGE = Pattern.compile("<a href=\"(http://img\\.geocaching\\.com[^.]+\\.(jpg|jpeg|png|gif))\"[^>]+>([^<]+)</a>(?:<br />([^<]+)<br /><br />)?");
+ public final static Pattern PATTERN_SPOILER_IMAGE = Pattern.compile("<a href=\"(http://imgcdn\\.geocaching\\.com[^.]+\\.(jpg|jpeg|png|gif))\"[^>]+>([^<]+)</a>(?:<br />([^<]+)<br /><br />)?");
public final static Pattern PATTERN_INVENTORY = Pattern.compile("<span id=\"ctl00_ContentBody_uxTravelBugList_uxInventoryLabel\">\\W*Inventory[^<]*</span>[^<]*</h3>[^<]*<div class=\"WidgetBody\">([^<]*<ul>(([^<]*<li>[^<]*<a href=\"[^\"]+\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>[^<]+<\\/span>[^<]*<\\/a>[^<]*<\\/li>)+)[^<]*<\\/ul>)?");
public final static Pattern PATTERN_INVENTORYINSIDE = Pattern.compile("[^<]*<li>[^<]*<a href=\"[a-z0-9\\-\\_\\.\\?\\/\\:\\@]*\\/track\\/details\\.aspx\\?guid=([0-9a-z\\-]+)[^\"]*\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>([^<]+)<\\/span>[^<]*<\\/a>[^<]*<\\/li>");
public final static Pattern PATTERN_WATCHLIST = Pattern.compile(Pattern.quote("watchlist.aspx") + ".{1,50}" + Pattern.quote("action=rem"));
@@ -69,7 +69,7 @@ public final class GCConstants {
public static final String MEMBER_STATUS_RENEW = "<a id=\"ctl00_hlRenew";
public static final String MEMBER_STATUS_PM = "Premium Member";
/** Use replaceAll("[,.]","") on the resulting string before converting to an int */
- public static final Pattern PATTERN_CACHES_FOUND = Pattern.compile("<strong[^>]*>.*?([\\d,.]+) Caches Found", Pattern.DOTALL);
+ public static final Pattern PATTERN_CACHES_FOUND = Pattern.compile("<strong[^>]*>.*?([\\d,.]+) Caches? Found", Pattern.DOTALL);
public static final Pattern PATTERN_AVATAR_IMAGE_PROFILE_PAGE = Pattern.compile("<img src=\"(http://img.geocaching.com/user/avatar/[0-9a-f-]+\\.jpg)\"[^>]*\\salt=\"Avatar\"");
public static final Pattern PATTERN_LOGIN_NAME_LOGIN_PAGE = Pattern.compile("ctl00_ContentBody_lbUsername\">.*<strong>(.*)</strong>");
public static final Pattern PATTERN_CUSTOMDATE = Pattern.compile("<option selected=\"selected\" value=\"([ /Mdy-]+)\">");
@@ -135,12 +135,12 @@ public final class GCConstants {
public final static Pattern PATTERN_WPTYPE = Pattern.compile("\\/wpttypes\\/sm\\/(.+)\\.jpg");
public final static Pattern PATTERN_WPPREFIXORLOOKUPORLATLON = Pattern.compile(">([^<]*<[^>]+>)?([^<]+)(<[^>]+>[^<]*)?<\\/td>");
public final static Pattern PATTERN_WPNAME = Pattern.compile(">[^<]*<a[^>]+>([^<]*)<\\/a>");
- public final static Pattern PATTERN_WPNOTE = Pattern.compile("colspan=\"6\">(.*)<\\/td>");
+ public final static Pattern PATTERN_WPNOTE = Pattern.compile("colspan=\"6\">(.*)" + Pattern.quote("</td>"), Pattern.DOTALL);
/**
* Patterns for different purposes
*/
- /** replace linebreak and paragraph tags */
+ /** replace line break and paragraph tags */
public final static Pattern PATTERN_LINEBREAK = Pattern.compile("<(br|p)[^>]*>");
public final static Pattern PATTERN_TYPEBOX = Pattern.compile("<select name=\"ctl00\\$ContentBody\\$LogBookPanel1\\$ddLogType\" id=\"ctl00_ContentBody_LogBookPanel1_ddLogType\"[^>]*>"
+ "(([^<]*<option[^>]*>[^<]+</option>)+)[^<]*</select>", Pattern.CASE_INSENSITIVE);
@@ -168,7 +168,6 @@ public final class GCConstants {
public final static String STRING_PREMIUMONLY_2 = "Sorry, the owner of this listing has made it viewable to Premium Members only.";
public final static String STRING_PREMIUMONLY_1 = "has chosen to make this cache listing visible to Premium Members only.";
- public final static String STRING_UNPUBLISHED_OWNER = "cache has not been published yet";
public final static String STRING_UNPUBLISHED_OTHER = "you cannot view this cache listing until it has been published";
public final static String STRING_UNPUBLISHED_FROM_SEARCH = "UnpublishedCacheSearchWidget";
public final static String STRING_UNKNOWN_ERROR = "An Error Has Occurred";
diff --git a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
index dfb1f55..8bed2ea 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
@@ -17,6 +17,7 @@ import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.Nullable;
import android.net.Uri;
import android.os.Bundle;
@@ -42,6 +43,7 @@ public class GCLoggingManager implements ILoggingManager, LoaderManager.LoaderCa
this.cache = cache;
}
+ @Nullable
@Override
public Loader<String> onCreateLoader(int arg0, Bundle arg1) {
if (!Settings.isLogin()) { // allow offline logging
diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index 27d8a77..e2c7dfa 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCMap.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy;
@@ -19,7 +19,7 @@ import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.utils.LeastRecentlyUsedMap;
import cgeo.geocaching.utils.Log;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
@@ -255,7 +255,7 @@ public class GCMap {
* @return
*/
public static SearchResult searchByViewport(final Viewport viewport, final String[] tokens) {
- int speed = (int) cgeoapplication.getInstance().currentGeo().getSpeed() * 60 * 60 / 1000; // in km/h
+ int speed = (int) CgeoApplication.getInstance().currentGeo().getSpeed() * 60 * 60 / 1000; // in km/h
Strategy strategy = Settings.getLiveMapStrategy();
if (strategy == Strategy.AUTO) {
strategy = speed >= 30 ? Strategy.FAST : Strategy.DETAILED;
@@ -361,7 +361,7 @@ public class GCMap {
// Check for vanished found caches
if (tiles.iterator().next().getZoomLevel() >= Tile.ZOOMLEVEL_MIN_PERSONALIZED) {
- searchResult.addFilteredGeocodes(cgData.getCachedMissingFromSearch(searchResult, tiles, GCConnector.getInstance(), Tile.ZOOMLEVEL_MIN_PERSONALIZED - 1));
+ searchResult.addFilteredGeocodes(DataStore.getCachedMissingFromSearch(searchResult, tiles, GCConnector.getInstance(), Tile.ZOOMLEVEL_MIN_PERSONALIZED - 1));
}
}
@@ -372,7 +372,7 @@ public class GCMap {
SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false, null);
if (search != null && !search.isEmpty()) {
final Set<String> geocodes = search.getGeocodes();
- lastSearchViewport = cgData.getBounds(geocodes);
+ lastSearchViewport = DataStore.getBounds(geocodes);
searchResult.addGeocodes(geocodes);
}
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index bd20216..869d27d 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -1,5 +1,7 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.Image;
import cgeo.geocaching.LogEntry;
@@ -9,8 +11,6 @@ import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Trackable;
import cgeo.geocaching.TrackableLog;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
@@ -32,15 +32,18 @@ import cgeo.geocaching.ui.DirectionImage;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
+import cgeo.geocaching.utils.SynchronizedDateFormat;
import cgeo.geocaching.utils.TextUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -50,7 +53,6 @@ import android.text.Html;
import java.io.File;
import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
@@ -62,8 +64,8 @@ import java.util.Locale;
import java.util.Set;
public abstract class GCParser {
- private final static SimpleDateFormat dateTbIn1 = new SimpleDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009
- private final static SimpleDateFormat dateTbIn2 = new SimpleDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009
+ private final static SynchronizedDateFormat dateTbIn1 = new SynchronizedDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009
+ private final static SynchronizedDateFormat dateTbIn2 = new SynchronizedDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009
private static SearchResult parseSearch(final String url, final String pageContent, final boolean showCaptcha, RecaptchaReceiver thread) {
if (StringUtils.isBlank(pageContent)) {
@@ -309,14 +311,10 @@ public abstract class GCParser {
final String coordinates = Network.getResponseData(Network.postRequest("http://www.geocaching.com/seek/nearest.aspx", params), false);
- if (StringUtils.isNotBlank(coordinates)) {
- if (coordinates.contains("You have not agreed to the license agreement. The license agreement is required before you can start downloading GPX or LOC files from Geocaching.com")) {
- Log.i("User has not agreed to the license agreement. Can\'t download .loc file.");
-
- searchResult.setError(StatusCode.UNAPPROVED_LICENSE);
-
- return searchResult;
- }
+ if (StringUtils.contains(coordinates, "You have not agreed to the license agreement. The license agreement is required before you can start downloading GPX or LOC files from Geocaching.com")) {
+ Log.i("User has not agreed to the license agreement. Can\'t download .loc file.");
+ searchResult.setError(StatusCode.UNAPPROVED_LICENSE);
+ return searchResult;
}
LocParser.parseLoc(searchResult, coordinates);
@@ -346,7 +344,7 @@ public abstract class GCParser {
static SearchResult parseCache(final String page, final CancellableHandler handler) {
final SearchResult searchResult = parseCacheFromText(page, handler);
- // attention: parseCacheFromText already stores implicitely through searchResult.addCache
+ // attention: parseCacheFromText already stores implicitly through searchResult.addCache
if (searchResult != null && !searchResult.getGeocodes().isEmpty()) {
final Geocache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
getExtraOnlineInfo(cache, page, handler);
@@ -358,7 +356,7 @@ public abstract class GCParser {
// save full detailed caches
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_cache);
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
// update progress message so user knows we're still working. This is more of a place holder than
// actual indication of what the program is doing
@@ -377,7 +375,7 @@ public abstract class GCParser {
final SearchResult searchResult = new SearchResult();
- if (pageIn.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_OWNER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) {
+ if (pageIn.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) {
searchResult.setError(StatusCode.UNPUBLISHED_CACHE);
return searchResult;
}
@@ -668,7 +666,7 @@ public abstract class GCParser {
final String originalCoords = TextUtils.getMatch(page, GCConstants.PATTERN_LATLON_ORIG, false, null);
if (null != originalCoords) {
- final Waypoint waypoint = new Waypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false);
+ final Waypoint waypoint = new Waypoint(CgeoApplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false);
waypoint.setCoords(new Geopoint(originalCoords));
cache.addOrChangeWaypoint(waypoint, false);
cache.setUserModifiedCoords(true);
@@ -707,7 +705,7 @@ public abstract class GCParser {
// waypoint name
// res is null during the unit tests
- final String name = TextUtils.getMatch(wp[6], GCConstants.PATTERN_WPNAME, true, 1, cgeoapplication.getInstance().getString(R.string.waypoint), true);
+ final String name = TextUtils.getMatch(wp[6], GCConstants.PATTERN_WPNAME, true, 1, CgeoApplication.getInstance().getString(R.string.waypoint), true);
// waypoint type
final String resulttype = TextUtils.getMatch(wp[3], GCConstants.PATTERN_WPTYPE, null);
@@ -720,7 +718,7 @@ public abstract class GCParser {
// waypoint lookup
waypoint.setLookup(TextUtils.getMatch(wp[5], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, true, 2, waypoint.getLookup(), false));
- // waypoint latitude and logitude
+ // waypoint latitude and longitude
latlon = Html.fromHtml(TextUtils.getMatch(wp[7], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, false, 2, "", false)).toString().trim();
if (!StringUtils.startsWith(latlon, "???")) {
waypoint.setLatlon(latlon);
@@ -848,6 +846,7 @@ public abstract class GCParser {
* @param recaptchaReceiver
* @return
*/
+ @Nullable
private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, RecaptchaReceiver recaptchaReceiver) {
insertCacheType(params, cacheType);
@@ -859,6 +858,7 @@ public abstract class GCParser {
Log.e("GCParser.searchByAny: No data from server");
return null;
}
+ assert page != null;
final SearchResult searchResult = parseSearch(fullUri, page, showCaptcha, recaptchaReceiver);
if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) {
@@ -956,6 +956,7 @@ public abstract class GCParser {
return null;
}
+ @Nullable
public static Trackable searchTrackable(final String geocode, final String guid, final String id) {
if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid) && StringUtils.isBlank(id)) {
Log.w("GCParser.searchTrackable: No geocode nor guid nor id given");
@@ -980,6 +981,7 @@ public abstract class GCParser {
Log.e("GCParser.searchTrackable: No data from server");
return trackable;
}
+ assert page != null;
trackable = parseTrackable(page, geocode);
if (trackable == null) {
@@ -1019,7 +1021,9 @@ public abstract class GCParser {
maxCaches = 0;
Log.e("GCParser.searchPocketQueryList: Unable to parse max caches", e);
}
- final PocketQueryList pqList = new PocketQueryList(matcherPocket.group(2), matcherPocket.group(3), maxCaches);
+ final String guid = Html.fromHtml(matcherPocket.group(2)).toString();
+ final String name = Html.fromHtml(matcherPocket.group(3)).toString();
+ final PocketQueryList pqList = new PocketQueryList(guid, name, maxCaches);
list.add(pqList);
}
@@ -1142,7 +1146,7 @@ public abstract class GCParser {
Log.i("Log successfully posted to cache #" + cacheid);
if (geocode != null) {
- cgData.saveVisitDate(geocode);
+ DataStore.saveVisitDate(geocode);
}
Login.getLoginStatus(page);
@@ -1184,6 +1188,7 @@ public abstract class GCParser {
Log.e("GCParser.uploadLogImage: No data from server");
return new ImmutablePair<StatusCode, String>(StatusCode.UNKNOWN_ERROR, null);
}
+ assert page != null;
final String[] viewstates = Login.getViewstates(page);
@@ -1341,7 +1346,8 @@ public abstract class GCParser {
return !guidOnPage; // on watch list (=error) / not on watch list
}
- static String requestHtmlPage(final String geocode, final String guid, final String log, final String numlogs) {
+ @Nullable
+ static String requestHtmlPage(@Nullable final String geocode, @Nullable final String guid, final String log, final String numlogs) {
final Parameters params = new Parameters("decrypt", "y");
if (StringUtils.isNotBlank(geocode)) {
params.put("wp", geocode);
@@ -1529,7 +1535,7 @@ public abstract class GCParser {
Log.w("GCParser.parseTrackable: Failed to parse trackable details & image");
}
if (StringUtils.isEmpty(trackable.getDetails()) && page.contains(GCConstants.ERROR_TB_NOT_ACTIVATED)) {
- trackable.setDetails(cgeoapplication.getInstance().getString(R.string.trackable_not_activated));
+ trackable.setDetails(CgeoApplication.getInstance().getString(R.string.trackable_not_activated));
}
// trackable logs
@@ -1586,8 +1592,8 @@ public abstract class GCParser {
trackable.setTrackingcode(possibleTrackingcode);
}
- if (cgeoapplication.getInstance() != null) {
- cgData.saveTrackable(trackable);
+ if (CgeoApplication.getInstance() != null) {
+ DataStore.saveTrackable(trackable);
}
return trackable;
@@ -1649,8 +1655,17 @@ public abstract class GCParser {
rawResponse = TextUtils.getMatch(page, GCConstants.PATTERN_LOGBOOK, "");
}
+ return parseLogs(friends, rawResponse);
+ }
+
+ private static List<LogEntry> parseLogs(final boolean friends, String rawResponse) {
final List<LogEntry> logs = new ArrayList<LogEntry>();
+ // for non logged in users the log book is not shown
+ if (StringUtils.isBlank(rawResponse)) {
+ return logs;
+ }
+
try {
final JSONObject resp = new JSONObject(rawResponse);
if (!resp.getString("status").equals("success")) {
@@ -1677,7 +1692,7 @@ public abstract class GCParser {
// TODO: we should update our log data structure to be able to record
// proper coordinates, and make them clickable. In the meantime, it is
// better to integrate those coordinates into the text rather than not
- // display them as all.
+ // display them at all.
final String latLon = entry.getString("LatLonString");
final LogEntry logDone = new LogEntry(
entry.getString("UserName"),
@@ -1706,9 +1721,10 @@ public abstract class GCParser {
return logs;
}
+ @NonNull
public static List<LogType> parseTypes(String page) {
if (StringUtils.isEmpty(page)) {
- return null;
+ return Collections.emptyList();
}
final List<LogType> types = new ArrayList<LogType>();
diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java
index 0d8fb05..beb49f1 100644
--- a/main/src/cgeo/geocaching/connector/gc/Login.java
+++ b/main/src/cgeo/geocaching/connector/gc/Login.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.network.Cookies;
import cgeo.geocaching.network.HtmlImage;
@@ -13,10 +13,11 @@ 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;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import android.graphics.drawable.BitmapDrawable;
@@ -76,7 +77,7 @@ public abstract class Login {
return StatusCode.NO_LOGIN_INFO_STORED;
}
- Login.setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_working));
+ Login.setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_working));
HttpResponse loginResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx");
String loginData = Network.getResponseData(loginResponse);
if (loginResponse != null && loginResponse.getStatusLine().getStatusCode() == 503 && TextUtils.matches(loginData, GCConstants.PATTERN_MAINTENANCE)) {
@@ -119,6 +120,7 @@ public abstract class Login {
// FIXME: should it be CONNECTION_FAILED to match the first attempt?
return StatusCode.COMMUNICATION_ERROR; // no login page
}
+ assert loginData != null; // Caught above
if (Login.getLoginStatus(loginData)) {
Log.i("Successfully logged in Geocaching.com as " + login.left + " (" + Settings.getMemberStatus() + ')');
@@ -171,7 +173,7 @@ public abstract class Login {
resetLoginStatus();
setActualCachesFound(-1);
- setActualStatus(cgeoapplication.getInstance().getString(R.string.err_login));
+ setActualStatus(CgeoApplication.getInstance().getString(R.string.err_login));
}
static void setActualCachesFound(final int found) {
@@ -212,13 +214,14 @@ public abstract class Login {
* @param page
* @return <code>true</code> if user is logged in, <code>false</code> otherwise
*/
- public static boolean getLoginStatus(final String page) {
+ public static boolean getLoginStatus(@Nullable final String page) {
if (StringUtils.isBlank(page)) {
Log.e("Login.checkLogin: No page given");
return false;
}
+ assert page != null;
- setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_ok));
+ setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_ok));
// on every page except login page
setActualLoginStatus(TextUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME));
@@ -246,7 +249,7 @@ public abstract class Login {
return true;
}
- setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_failed));
+ setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_failed));
return false;
}
@@ -276,7 +279,8 @@ public abstract class Login {
public static BitmapDrawable downloadAvatarAndGetMemberStatus() {
try {
- final String profile = TextUtils.replaceWhitespace(Network.getResponseData(Network.getRequest("http://www.geocaching.com/my/")));
+ 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));
if (profile.contains(GCConstants.MEMBER_STATUS_RENEW)) {
@@ -473,10 +477,13 @@ public abstract class Login {
* @param params
* @return
*/
- public static String getRequestLogged(final String uri, final Parameters params) {
- final String data = Network.getResponseData(Network.getRequest(uri, params), canRemoveWhitespace(uri));
+ @Nullable
+ public static String getRequestLogged(@NonNull final String uri, @Nullable final Parameters params) {
+ final HttpResponse response = Network.getRequest(uri, params);
+ final String data = Network.getResponseData(response, canRemoveWhitespace(uri));
- if (getLoginStatus(data)) {
+ // A page not found will not be found if the user logs in either
+ if (Network.isPageNotFound(response) || getLoginStatus(data)) {
return data;
}
diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java
index 4ed53c9..623730a 100644
--- a/main/src/cgeo/geocaching/connector/gc/Tile.java
+++ b/main/src/cgeo/geocaching/connector/gc/Tile.java
@@ -29,11 +29,6 @@ import java.util.Set;
*/
public class Tile {
- public static final double LATITUDE_MIN = -85.05112878;
- public static final double LATITUDE_MAX = 85.05112878;
- public static final double LONGITUDE_MIN = -180;
- public static final double LONGITUDE_MAX = 180;
-
public static final int TILE_SIZE = 256;
public static final int ZOOMLEVEL_MAX = 18;
public static final int ZOOMLEVEL_MIN = 0;
diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGrid.java b/main/src/cgeo/geocaching/connector/gc/UTFGrid.java
index 6d20eb6..89a3de8 100644
--- a/main/src/cgeo/geocaching/connector/gc/UTFGrid.java
+++ b/main/src/cgeo/geocaching/connector/gc/UTFGrid.java
@@ -12,22 +12,6 @@ public final class UTFGrid {
public static final int GRID_MAXX = 63;
public static final int GRID_MAXY = 63;
- /**
- * Convert a value from a JSON grid object into an id that can be used as an index
- * It's not used at the moment due to optimizations.
- * But maybe we need it some day...
- */
- public static short getUTFGridId(final char value) {
- short result = (short) value;
- if (result >= 93) {
- result--;
- }
- if (result >= 35) {
- result--;
- }
- return (short) (result - 32);
- }
-
/** Calculate from a list of positions (x/y) the coords */
public static UTFGridPosition getPositionInGrid(List<UTFGridPosition> positions) {
int minX = GRID_MAXX;
diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
index 5965fff..eff193a 100644
--- a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
+++ b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
@@ -15,9 +15,12 @@ public final class UTFGridPosition {
private final static Pattern PATTERN_JSON_KEY = Pattern.compile("[^\\d]*" + "(\\d+),\\s*(\\d+)" + "[^\\d]*"); // (12, 34)
public UTFGridPosition(final int x, final int y) {
- assert x >= 0 && x <= UTFGrid.GRID_MAXX : "x outside bounds";
- assert y >= 0 && y <= UTFGrid.GRID_MAXY : "y outside bounds";
-
+ if (x < 0 || x > UTFGrid.GRID_MAXX) {
+ throw new IllegalArgumentException("x outside bounds");
+ }
+ if (y < 0 || y > UTFGrid.GRID_MAXY) {
+ throw new IllegalArgumentException("y outside bounds");
+ }
this.x = x;
this.y = y;
}
diff --git a/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java b/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java
index 5a140a1..dacb626 100644
--- a/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java
+++ b/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java
@@ -3,58 +3,65 @@ package cgeo.geocaching.connector.oc;
public interface IOCAuthParams {
/**
- * The site name: 'www.openaching...'
- *
+ * The site name: 'www.opencaching...'
+ *
* @return
*/
String getSite();
/**
* ResId of the Consumer key
- *
+ *
* @return
*/
int getCKResId();
/**
* ResId of the Consumer secret
- *
+ *
* @return
*/
int getCSResId();
/**
- * ResId ot the Authorization title
- *
+ * ResId of the Authorization title
+ *
* @return
*/
- int getAuthTitelResId();
+ int getAuthTitleResId();
/**
* Preference key of the public token
- *
+ *
* @return
*/
int getTokenPublicPrefKey();
/**
* Preference key of the secret token
- *
+ *
* @return
*/
int getTokenSecretPrefKey();
/**
* Preference key of the temporary public token (OAuth)
- *
+ *
* @return
*/
int getTempTokenPublicPrefKey();
/**
* Preference key of the temporary secret token (OAuth)
- *
+ *
* @return
*/
int getTempTokenSecretPrefKey();
+
+ /**
+ * The URI to use as a callback (OAuth)
+ *
+ * @return
+ */
+ String getCallbackUri();
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
index 663bbf7..b1b9088 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
@@ -1,13 +1,14 @@
package cgeo.geocaching.connector.oc;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogCacheActivity;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.capability.ILogin;
import cgeo.geocaching.connector.capability.ISearchByCenter;
+import cgeo.geocaching.connector.capability.ISearchByKeyword;
import cgeo.geocaching.connector.capability.ISearchByViewPort;
import cgeo.geocaching.connector.oc.UserInfo.UserInfoStatus;
import cgeo.geocaching.geopoint.Geopoint;
@@ -20,7 +21,7 @@ import org.apache.commons.lang3.StringUtils;
import android.content.Context;
import android.os.Handler;
-public class OCApiLiveConnector extends OCApiConnector implements ISearchByCenter, ISearchByViewPort, ILogin {
+public class OCApiLiveConnector extends OCApiConnector implements ISearchByCenter, ISearchByViewPort, ILogin, ISearchByKeyword {
private final String cS;
private final int isActivePrefKeyId;
@@ -29,9 +30,9 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
private UserInfo userInfo = new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.NOT_RETRIEVED);
public OCApiLiveConnector(String name, String host, String prefix, String licenseString, int cKResId, int cSResId, int isActivePrefKeyId, int tokenPublicPrefKeyId, int tokenSecretPrefKeyId, ApiSupport apiSupport) {
- super(name, host, prefix, CryptUtils.rot13(cgeoapplication.getInstance().getResources().getString(cKResId)), licenseString, apiSupport);
+ super(name, host, prefix, CryptUtils.rot13(CgeoApplication.getInstance().getResources().getString(cKResId)), licenseString, apiSupport);
- cS = CryptUtils.rot13(cgeoapplication.getInstance().getResources().getString(cSResId));
+ cS = CryptUtils.rot13(CgeoApplication.getInstance().getResources().getString(cSResId));
this.isActivePrefKeyId = isActivePrefKeyId;
this.tokenPublicPrefKeyId = tokenPublicPrefKeyId;
this.tokenSecretPrefKeyId = tokenSecretPrefKeyId;
@@ -87,7 +88,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
final boolean added = OkapiClient.setWatchState(cache, true, this);
if (added) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return added;
@@ -98,7 +99,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
final boolean removed = OkapiClient.setWatchState(cache, false, this);
if (removed) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return removed;
@@ -145,11 +146,17 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
@Override
public String getLoginStatusString() {
- return cgeoapplication.getInstance().getString(userInfo.getStatus().resId);
+ return CgeoApplication.getInstance().getString(userInfo.getStatus().resId);
}
@Override
public boolean isLoggedIn() {
return userInfo.getStatus() == UserInfoStatus.SUCCESSFUL;
}
+
+ @Override
+ public SearchResult searchByName(final String name) {
+ final Geopoint currentPos = CgeoApplication.getInstance().currentGeo().getCoords();
+ return new SearchResult(OkapiClient.getCachesNamed(currentPos, name, this));
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java
index 10d6a66..c082bac 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java
@@ -1,13 +1,14 @@
package cgeo.geocaching.connector.oc;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.network.OAuthAuthorizationActivity;
import cgeo.geocaching.settings.Settings;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.Nullable;
-public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
+public abstract class OCAuthorizationActivity extends OAuthAuthorizationActivity {
final IOCAuthParams authParams;
@@ -17,8 +18,9 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
"/okapi/services/oauth/authorize",
"/okapi/services/oauth/access_token",
false,
- cgeoapplication.getInstance().getResources().getString(authParams.getCKResId()),
- cgeoapplication.getInstance().getResources().getString(authParams.getCSResId()));
+ CgeoApplication.getInstance().getResources().getString(authParams.getCKResId()),
+ CgeoApplication.getInstance().getResources().getString(authParams.getCSResId()),
+ authParams.getCallbackUri());
this.authParams = authParams;
}
@@ -28,12 +30,12 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
}
@Override
- protected void setTempTokens(String tokenPublic, String tokenSecret) {
+ protected void setTempTokens(@Nullable final String tokenPublic, @Nullable final String tokenSecret) {
Settings.setTokens(authParams.getTempTokenPublicPrefKey(), tokenPublic, authParams.getTempTokenSecretPrefKey(), tokenSecret);
}
@Override
- protected void setTokens(String tokenPublic, String tokenSecret, boolean enable) {
+ protected void setTokens(@Nullable final String tokenPublic, @Nullable final String tokenSecret, final boolean enable) {
Settings.setTokens(authParams.getTokenPublicPrefKey(), tokenPublic, authParams.getTokenSecretPrefKey(), tokenSecret);
if (tokenPublic != null) {
Settings.setTokens(authParams.getTempTokenPublicPrefKey(), null, authParams.getTempTokenSecretPrefKey(), null);
@@ -42,22 +44,7 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
@Override
protected String getAuthTitle() {
- return res.getString(authParams.getAuthTitelResId());
- }
-
- @Override
- protected String getAuthAgain() {
- return res.getString(R.string.auth_again_oc);
- }
-
- @Override
- protected String getErrAuthInitialize() {
- return res.getString(R.string.err_auth_initialize);
- }
-
- @Override
- protected String getAuthStart() {
- return res.getString(R.string.auth_start_oc);
+ return res.getString(authParams.getAuthTitleResId());
}
@Override
@@ -65,48 +52,4 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
return res.getString(R.string.auth_dialog_completed_oc, getAuthTitle());
}
- @Override
- protected String getErrAuthProcess() {
- return res.getString(R.string.err_auth_process);
- }
-
- @Override
- protected String getAuthDialogWait() {
- return res.getString(R.string.auth_dialog_wait_oc, getAuthTitle());
- }
-
- @Override
- protected String getAuthDialogPinTitle() {
- return res.getString(R.string.auth_dialog_pin_title_oc);
- }
-
- @Override
- protected String getAuthDialogPinMessage() {
- return res.getString(R.string.auth_dialog_pin_message_oc, getAuthTitle());
- }
-
- @Override
- protected String getAboutAuth1() {
- return res.getString(R.string.about_auth_1_oc, getAuthTitle());
- }
-
- @Override
- protected String getAboutAuth2() {
- return res.getString(R.string.about_auth_2_oc, getAuthTitle(), getAuthTitle());
- }
-
- @Override
- protected String getAuthAuthorize() {
- return res.getString(R.string.auth_authorize_oc);
- }
-
- @Override
- protected String getAuthPinHint() {
- return res.getString(R.string.auth_pin_hint_oc, getAuthTitle());
- }
-
- @Override
- protected String getAuthFinish() {
- return res.getString(R.string.auth_finish_oc);
- }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCConnector.java b/main/src/cgeo/geocaching/connector/oc/OCConnector.java
index 29cdd10..b5c62ea 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCConnector.java
@@ -4,7 +4,10 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.ICache;
import cgeo.geocaching.R;
import cgeo.geocaching.connector.AbstractConnector;
+import cgeo.geocaching.enumerations.LogType;
+import java.util.Arrays;
+import java.util.List;
import java.util.regex.Pattern;
public class OCConnector extends AbstractConnector {
@@ -14,6 +17,9 @@ public class OCConnector extends AbstractConnector {
private final Pattern codePattern;
private static final Pattern GPX_ZIP_FILE_PATTERN = Pattern.compile("oc[a-z]{2,3}\\d{5,}\\.zip", Pattern.CASE_INSENSITIVE);
+ private static final List<LogType> STANDARD_LOG_TYPES = Arrays.asList(LogType.FOUND_IT, LogType.DIDNT_FIND_IT, LogType.NOTE);
+ private static final List<LogType> EVENT_LOG_TYPES = Arrays.asList(LogType.WILL_ATTEND, LogType.ATTENDED, LogType.NOTE);
+
public OCConnector(final String name, final String host, final String prefix) {
this.name = name;
this.host = host;
@@ -66,4 +72,12 @@ public class OCConnector extends AbstractConnector {
return R.drawable.marker_oc;
}
+ @Override
+ public final List<LogType> getPossibleLogTypes(Geocache cache) {
+ if (cache.isEventCache()) {
+ return EVENT_LOG_TYPES;
+ }
+
+ return STANDARD_LOG_TYPES;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java b/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java
index 734b383..17c1cb8 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java
@@ -20,7 +20,7 @@ public class OCDEAuthParams implements IOCAuthParams {
}
@Override
- public int getAuthTitelResId() {
+ public int getAuthTitleResId() {
return R.string.auth_ocde;
}
@@ -43,4 +43,9 @@ public class OCDEAuthParams implements IOCAuthParams {
public int getTempTokenSecretPrefKey() {
return R.string.pref_temp_ocde_token_secret;
}
+
+ @Override
+ public String getCallbackUri() {
+ return "callback://www.cgeo.org/opencaching.de/";
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java
index caf114c..1d2aa49 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.connector.oc;
-public class OCDEAuthorizationActivity extends OCAuthorizationActivity {
+public final class OCDEAuthorizationActivity extends OCAuthorizationActivity {
public OCDEAuthorizationActivity() {
super(new OCDEAuthParams());
diff --git a/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java b/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java
index 117e990..dfe03e5 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java
@@ -20,7 +20,7 @@ public class OCPLAuthParams implements IOCAuthParams {
}
@Override
- public int getAuthTitelResId() {
+ public int getAuthTitleResId() {
return R.string.auth_ocpl;
}
@@ -43,4 +43,9 @@ public class OCPLAuthParams implements IOCAuthParams {
public int getTempTokenSecretPrefKey() {
return R.string.pref_temp_ocpl_token_secret;
}
+
+ @Override
+ public String getCallbackUri() {
+ return "callback://www.cgeo.org/opencaching.pl/";
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java
index 4f9ef96..30ea150 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.connector.oc;
-public class OCPLAuthorizationActivity extends OCAuthorizationActivity {
+public final class OCPLAuthorizationActivity extends OCAuthorizationActivity {
public OCPLAuthorizationActivity() {
super(new OCPLAuthParams());
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 189b6a4..686e314 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -1,12 +1,12 @@
package cgeo.geocaching.connector.oc;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.Image;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.connector.LogResult;
@@ -29,9 +29,15 @@ import cgeo.geocaching.network.OAuth;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.SynchronizedDateFormat;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -39,7 +45,6 @@ import org.json.JSONObject;
import android.net.Uri;
import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
@@ -56,12 +61,8 @@ final class OkapiClient {
private static final char SEPARATOR = '|';
private static final String SEPARATOR_STRING = Character.toString(SEPARATOR);
- private static final SimpleDateFormat LOG_DATE_FORMAT;
- static {
- LOG_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", Locale.US);
- LOG_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
- }
- private static final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
+ private static final FastDateFormat LOG_DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSSZ", TimeZone.getTimeZone("UTC"), Locale.US);
+ private static final SynchronizedDateFormat ISO8601DATEFORMAT = new SynchronizedDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
private static final String CACHE_ATTRNAMES = "attrnames";
private static final String WPT_LOCATION = "location";
@@ -81,7 +82,6 @@ final class OkapiClient {
private static final String CACHE_LATEST_LOGS = "latest_logs";
private static final String CACHE_IMAGE_URL = "url";
private static final String CACHE_IMAGE_CAPTION = "caption";
- private static final String CACHE_IMAGE_IS_SPOILER = "is_spoiler";
private static final String CACHE_IMAGES = "images";
private static final String CACHE_HINT = "hint";
private static final String CACHE_DESCRIPTION = "description";
@@ -110,14 +110,15 @@ 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";
+ 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_L3_FIELDS = "is_found";
- private static final String SERVICE_CACHE_ADDITIONAL_FIELDS = "owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|date_hidden|alt_wpts|attrnames|req_passwd";
+ 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";
private static final String SERVICE_CACHE_ADDITIONAL_L3_FIELDS = "is_watched|my_notes";
- private static final String METHOD_SEARCH_NEAREST = "services/caches/search/nearest";
+ private static final String METHOD_SEARCH_ALL = "services/caches/search/all";
private static final String METHOD_SEARCH_BBOX = "services/caches/search/bbox";
+ private static final String METHOD_SEARCH_NEAREST = "services/caches/search/nearest";
private static final String METHOD_RETRIEVE_CACHES = "services/caches/geocaches";
public static Geocache getCache(final String geoCode) {
@@ -132,13 +133,9 @@ final class OkapiClient {
params.add("fields", getFullFields(ocapiConn));
params.add("attribution_append", "none");
- final JSONObject data = request(ocapiConn, OkapiService.SERVICE_CACHE, params);
-
- if (data == null) {
- return null;
- }
+ final JSONResult result = request(ocapiConn, OkapiService.SERVICE_CACHE, params);
- return parseCache(data);
+ return result.isSuccess ? parseCache(result.data) : null;
}
public static List<Geocache> getCachesAround(final Geopoint center, final OCApiConnector connector) {
@@ -152,12 +149,38 @@ final class OkapiClient {
return requestCaches(connector, params, valueMap);
}
+ public static List<Geocache> getCachesNamed(final Geopoint center, final String namePart, final OCApiConnector connector) {
+ final Map<String, String> valueMap = new LinkedHashMap<String, String>();
+ final Parameters params;
+
+ // search around current position, if there is a position
+ if (center != null) {
+ final String centerString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center) + SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center);
+ params = new Parameters("search_method", METHOD_SEARCH_NEAREST);
+ valueMap.put("center", centerString);
+ valueMap.put("limit", "20");
+ }
+ else {
+ params = new Parameters("search_method", METHOD_SEARCH_ALL);
+ valueMap.put("limit", "20");
+ }
+
+ // full wildcard search, maybe we need to change this after some testing and evaluation
+ valueMap.put("name", "*" + namePart + "*");
+ return requestCaches(connector, params, valueMap);
+ }
+
private static List<Geocache> requestCaches(final OCApiConnector connector, final Parameters params, final Map<String, String> valueMap) {
+ // if a global type filter is set, and OKAPI does not know that type, then return an empty list instead of all caches
+ if (Settings.getCacheType() != CacheType.ALL && StringUtils.isBlank(getFilterFromType())) {
+ return Collections.emptyList();
+ }
+
addFilterParams(valueMap, connector);
params.add("search_params", new JSONObject(valueMap).toString());
addRetrieveParams(params, connector);
- final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params);
+ final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params).data;
if (data == null) {
return Collections.emptyList();
@@ -166,7 +189,9 @@ final class OkapiClient {
return parseCaches(data);
}
- // Assumes level 3 OAuth
+ /**
+ * Assumes level 3 OAuth.
+ */
public static List<Geocache> getCachesBBox(final Viewport viewport, final OCApiConnector connector) {
if (viewport.getLatitudeSpan() == 0 || viewport.getLongitudeSpan() == 0) {
@@ -188,7 +213,7 @@ final class OkapiClient {
final Parameters params = new Parameters("cache_code", cache.getGeocode());
params.add("watched", watched ? "true" : "false");
- final JSONObject data = request(connector, OkapiService.SERVICE_MARK_CACHE, params);
+ final JSONObject data = request(connector, OkapiService.SERVICE_MARK_CACHE, params).data;
if (data == null) {
return false;
@@ -212,7 +237,7 @@ final class OkapiClient {
params.add("password", logPassword);
}
- final JSONObject data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params);
+ final JSONObject data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params).data;
if (data == null) {
return new LogResult(StatusCode.LOG_POST_ERROR, "");
@@ -265,7 +290,7 @@ final class OkapiClient {
parseCoreCache(response, cache);
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
} catch (final JSONException e) {
Log.e("OkapiClient.parseSmallCache", e);
}
@@ -297,7 +322,7 @@ final class OkapiClient {
final StringBuilder description = new StringBuilder(500);
if (!response.isNull("gc_code")) {
final String gccode = response.getString("gc_code");
- description.append(cgeoapplication.getInstance().getResources()
+ description.append(CgeoApplication.getInstance().getResources()
.getString(R.string.cache_listed_on, GCConnector.getInstance().getName()))
.append(": <a href=\"http://coord.info/")
.append(gccode)
@@ -316,17 +341,15 @@ final class OkapiClient {
if (images != null) {
for (int i = 0; i < images.length(); i++) {
final JSONObject imageResponse = images.getJSONObject(i);
- if (imageResponse.getBoolean(CACHE_IMAGE_IS_SPOILER)) {
- final String title = imageResponse.getString(CACHE_IMAGE_CAPTION);
- final String url = absoluteUrl(imageResponse.getString(CACHE_IMAGE_URL), cache.getGeocode());
- cache.addSpoiler(new Image(url, title));
- }
+ final String title = imageResponse.getString(CACHE_IMAGE_CAPTION);
+ final String url = absoluteUrl(imageResponse.getString(CACHE_IMAGE_URL), cache.getGeocode());
+ // all images are added as spoiler images, although OKAPI has spoiler and non spoiler images
+ cache.addSpoiler(new Image(url, title));
}
}
cache.setAttributes(parseAttributes(response.getJSONArray(CACHE_ATTRNAMES)));
cache.setLogs(parseLogs(response.getJSONArray(CACHE_LATEST_LOGS)));
- cache.setHidden(parseDate(response.getString(CACHE_HIDDEN)));
//TODO: Store license per cache
//cache.setLicense(response.getString("attribution_note"));
cache.setWaypoints(parseWaypoints(response.getJSONArray(CACHE_WPTS)), false);
@@ -340,7 +363,7 @@ final class OkapiClient {
cache.setDetailedUpdatedNow();
// save full detailed caches
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
} catch (final JSONException e) {
Log.e("OkapiClient.parseCache", e);
}
@@ -365,6 +388,7 @@ final class OkapiClient {
if (!response.isNull(CACHE_IS_FOUND)) {
cache.setFound(response.getBoolean(CACHE_IS_FOUND));
}
+ cache.setHidden(parseDate(response.getString(CACHE_HIDDEN)));
}
private static String absoluteUrl(final String url, final String geocode) {
@@ -599,14 +623,15 @@ final class OkapiClient {
return res.toString();
}
- private static JSONObject request(final OCApiConnector connector, final OkapiService service, final Parameters params) {
+ @NonNull
+ private static JSONResult request(final OCApiConnector connector, final OkapiService service, final Parameters params) {
if (connector == null) {
- return null;
+ return new JSONResult(null);
}
final String host = connector.getHost();
if (StringUtils.isBlank(host)) {
- return null;
+ return new JSONResult(null);
}
params.add("langpref", getPreferredLanguage());
@@ -619,7 +644,7 @@ final class OkapiClient {
}
final String uri = "http://" + host + service.methodName;
- return Network.requestJSON(uri, params);
+ return new JSONResult(Network.getRequest(uri, params));
}
private static String getPreferredLanguage() {
@@ -639,7 +664,7 @@ final class OkapiClient {
valueMap.put("found_status", "notfound_only");
}
if (Settings.getCacheType() != CacheType.ALL) {
- valueMap.put("type", getFilterFromType(Settings.getCacheType()));
+ valueMap.put("type", getFilterFromType());
}
}
@@ -649,8 +674,8 @@ final class OkapiClient {
params.add("wrap", "true");
}
- private static String getFilterFromType(final CacheType cacheType) {
- switch (cacheType) {
+ private static String getFilterFromType() {
+ switch (Settings.getCacheType()) {
case EVENT:
return "Event";
case MULTI:
@@ -671,12 +696,16 @@ final class OkapiClient {
public static UserInfo getUserInfo(final OCApiLiveConnector connector) {
final Parameters params = new Parameters("fields", USER_INFO_FIELDS);
- final JSONObject data = request(connector, OkapiService.SERVICE_USER, params);
+ final JSONResult result = request(connector, OkapiService.SERVICE_USER, params);
- if (data == null) {
- return new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.FAILED);
+ if (!result.isSuccess) {
+ final OkapiError error = new OkapiError(result.data);
+ Log.e("OkapiClient.getUserInfo: error getting user info: '" + error.getMessage() + "'");
+ return new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.getFromOkapiError(error.getResult()));
}
+ JSONObject data = result.data;
+
String name = StringUtils.EMPTY;
boolean successUserName = false;
@@ -704,4 +733,28 @@ final class OkapiClient {
return new UserInfo(name, finds, successUserName && successFinds ? UserInfoStatus.SUCCESSFUL : UserInfoStatus.FAILED);
}
+ /**
+ * Encapsulates response state and content of an HTTP-request that expects a JSON result. <code>isSuccess</code> is
+ * only true, if the response state was success and <code>data</code> is not null.
+ */
+ private static class JSONResult {
+
+ public final boolean isSuccess;
+ public final JSONObject data;
+
+ public JSONResult(final @Nullable HttpResponse response) {
+ boolean isSuccess = Network.isSuccess(response);
+ final String responseData = Network.getResponseDataAlways(response);
+ JSONObject data = null;
+ if (responseData != null) {
+ try {
+ data = new JSONObject(responseData);
+ } catch (final JSONException e) {
+ Log.w("JSONResult", e);
+ }
+ }
+ this.data = data;
+ this.isSuccess = isSuccess && data != null;
+ }
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiError.java b/main/src/cgeo/geocaching/connector/oc/OkapiError.java
new file mode 100644
index 0000000..7faf2c7
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiError.java
@@ -0,0 +1,87 @@
+package cgeo.geocaching.connector.oc;
+
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Handles the JSON error response from OKAPI
+ */
+public class OkapiError {
+
+ /**
+ * List of detected errors OKAPI might return
+ */
+ public enum OkapiErrors {
+ NO_ERROR,
+ UNSPECIFIED,
+ INVALID_TIMESTAMP,
+ INVALID_TOKEN;
+ }
+
+ @NonNull private final OkapiErrors state;
+ @NonNull private final String message;
+
+ public OkapiError(@Nullable JSONObject data) {
+
+ // A null-response is by definition an error (some exception occurred somewhere in the flow)
+ if (data == null) {
+ state = OkapiErrors.UNSPECIFIED;
+ message = StringUtils.EMPTY;
+ return;
+ }
+ // Second possibility: we get an error object as return (@see http://opencaching.pl/okapi/introduction.html#errors)
+ if (data.has("error")) {
+ String localmessage = null;
+ OkapiErrors localstate = OkapiErrors.UNSPECIFIED;
+ try {
+ JSONObject error = data.getJSONObject("error");
+ // Check reason_stack element to look for the specific oauth problems we want to report back
+ if (error.has("reason_stack")) {
+ String reason = error.getString("reason_stack");
+ if (StringUtils.contains(reason, "invalid_oauth_request")) {
+ if (StringUtils.contains(reason, "invalid_timestamp")) {
+ localstate = OkapiErrors.INVALID_TIMESTAMP;
+ } else if (StringUtils.contains(reason, "invalid_token")) {
+ localstate = OkapiErrors.INVALID_TOKEN;
+ }
+ }
+ }
+ // Check if we can extract a message as well
+ if (error.has("developer_message")) {
+ localmessage = error.getString("developer_message");
+ assert localmessage != null; // by virtue of defaultString
+ }
+ } catch (JSONException ex) {
+ Log.d("OkapiError: Failed to parse JSON", ex);
+ localstate = OkapiErrors.UNSPECIFIED;
+ }
+ state = localstate;
+ message = StringUtils.defaultString(localmessage);
+ return;
+ }
+
+ // Third possibility: some other response, everything is fine!
+ state = OkapiErrors.NO_ERROR;
+ message = StringUtils.EMPTY;
+ }
+
+ public boolean isError() {
+ return state != OkapiErrors.NO_ERROR;
+ }
+
+ @NonNull
+ public OkapiErrors getResult() {
+ return state;
+ }
+
+ @NonNull
+ public String getMessage() {
+ return message;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
index 9ffe7a2..c6be3cb 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
@@ -11,7 +11,6 @@ import cgeo.geocaching.enumerations.StatusCode;
import android.net.Uri;
-import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
@@ -22,48 +21,42 @@ public class OkapiLoggingManager implements ILoggingManager {
private final Geocache cache;
private LogCacheActivity activity;
- private final static List<LogType> standardLogTypes = Arrays.asList(LogType.FOUND_IT, LogType.DIDNT_FIND_IT, LogType.NOTE);
- private final static List<LogType> eventLogTypes = Arrays.asList(LogType.WILL_ATTEND, LogType.ATTENDED, LogType.NOTE);
-
- public OkapiLoggingManager(final LogCacheActivity activity, OCApiLiveConnector connector, Geocache cache) {
+ public OkapiLoggingManager(final LogCacheActivity activity, final OCApiLiveConnector connector, final Geocache cache) {
this.connector = connector;
this.cache = cache;
this.activity = activity;
}
@Override
- public void init() {
+ public final void init() {
activity.onLoadFinished();
}
@Override
- public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, String logPassword, List<TrackableLog> trackableLogs) {
+ public final LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log, final String logPassword, final List<TrackableLog> trackableLogs) {
final LogResult result = OkapiClient.postLog(cache, logType, date, log, logPassword, connector);
connector.login(null, null);
return result;
}
@Override
- public ImageResult postLogImage(String logId, String imageCaption, String imageDescription, Uri imageUri) {
+ public final ImageResult postLogImage(final String logId, final String imageCaption, final String imageDescription, final Uri imageUri) {
return new ImageResult(StatusCode.LOG_POST_ERROR, "");
}
@Override
- public boolean hasLoaderError() {
+ public final boolean hasLoaderError() {
return false;
}
@Override
- public List<TrackableLog> getTrackables() {
+ public final List<TrackableLog> getTrackables() {
return Collections.emptyList();
}
@Override
public List<LogType> getPossibleLogTypes() {
- if (cache.isEventCache()) {
- return eventLogTypes;
- }
-
- return standardLogTypes;
+ return connector.getPossibleLogTypes(cache);
}
+
}
diff --git a/main/src/cgeo/geocaching/connector/oc/UserInfo.java b/main/src/cgeo/geocaching/connector/oc/UserInfo.java
index 0dc0440..c8b37cd 100644
--- a/main/src/cgeo/geocaching/connector/oc/UserInfo.java
+++ b/main/src/cgeo/geocaching/connector/oc/UserInfo.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.connector.oc;
import cgeo.geocaching.R;
+import cgeo.geocaching.connector.oc.OkapiError.OkapiErrors;
public class UserInfo {
@@ -8,13 +9,28 @@ public class UserInfo {
NOT_RETRIEVED(R.string.init_login_popup_working),
SUCCESSFUL(R.string.init_login_popup_ok),
FAILED(R.string.init_login_popup_failed),
- NOT_SUPPORTED(R.string.init_login_popup_not_authorized);
+ NOT_SUPPORTED(R.string.init_login_popup_not_authorized),
+ INVALID_TIMESTAMP(R.string.init_login_popup_invalid_timestamp),
+ INVALID_TOKEN(R.string.init_login_popup_invalid_token);
public final int resId;
UserInfoStatus(int resId) {
this.resId = resId;
}
+
+ public static UserInfoStatus getFromOkapiError(OkapiErrors result) {
+ switch (result) {
+ case NO_ERROR:
+ return SUCCESSFUL;
+ case INVALID_TIMESTAMP:
+ return INVALID_TIMESTAMP;
+ case INVALID_TOKEN:
+ return INVALID_TOKEN;
+ default:
+ return FAILED;
+ }
+ }
}
private final String name;
diff --git a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
index f25e289..9d1dfc7 100644
--- a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
+++ b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.connector.ox;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.StoredList;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.CryptUtils;
@@ -11,7 +11,7 @@ import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import java.util.Collection;
import java.util.Collections;
diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
index 66ca5f7..67180b3 100644
--- a/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
+++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.connector.trackable;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import cgeo.geocaching.Trackable;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.utils.Log;
import org.xml.sax.Attributes;
@@ -35,15 +35,23 @@ public class GeokretyParser {
@Override
public void start(Attributes attributes) {
try {
- if (attributes.getIndex("id") > -1) {
+ final int indexId = attributes.getIndex("id");
+ if (indexId > -1) {
trackable.setGeocode(geocode(Integer.valueOf(attributes.getValue("id"))));
}
- if (attributes.getIndex("dist") > -1) {
+ final int indexDist = attributes.getIndex("dist");
+ if (indexDist > -1) {
trackable.setDistance(Float.valueOf(attributes.getValue("dist")));
}
- if (attributes.getIndex("type") > -1) {
+ final int indexType = attributes.getIndex("type");
+ if (indexType > -1) {
trackable.setType(getType(Integer.valueOf(attributes.getValue("type"))));
}
+ final int indexWaypoint = attributes.getIndex("waypoint");
+ if (indexWaypoint > -1) {
+ trackable.setSpottedName(attributes.getValue(indexWaypoint));
+ trackable.setSpottedType(Trackable.SPOTTED_CACHE);
+ }
} catch (final NumberFormatException e) {
Log.e("Parsing geokret", e);
}
@@ -63,15 +71,15 @@ public class GeokretyParser {
protected static String getType(int type) {
switch (type) {
case 0:
- return cgeoapplication.getInstance().getString(R.string.geokret_type_traditional);
+ return CgeoApplication.getInstance().getString(R.string.geokret_type_traditional);
case 1:
- return cgeoapplication.getInstance().getString(R.string.geokret_type_book_or_media);
+ return CgeoApplication.getInstance().getString(R.string.geokret_type_book_or_media);
case 2:
- return cgeoapplication.getInstance().getString(R.string.geokret_type_human);
+ return CgeoApplication.getInstance().getString(R.string.geokret_type_human);
case 3:
- return cgeoapplication.getInstance().getString(R.string.geokret_type_coin);
+ return CgeoApplication.getInstance().getString(R.string.geokret_type_coin);
case 4:
- return cgeoapplication.getInstance().getString(R.string.geokret_type_post);
+ return CgeoApplication.getInstance().getString(R.string.geokret_type_post);
}
return null;
}
diff --git a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
index 243f63d..1ddfeaf 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.enumerations;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import org.apache.commons.lang3.StringUtils;
@@ -143,7 +143,7 @@ public enum CacheAttribute {
* @return the localized text
*/
public String getL10n(final boolean enabled) {
- return cgeoapplication.getInstance().getResources().getString(
+ return CgeoApplication.getInstance().getResources().getString(
enabled ? stringIdYes : stringIdNo);
}
diff --git a/main/src/cgeo/geocaching/enumerations/CacheListType.java b/main/src/cgeo/geocaching/enumerations/CacheListType.java
index 5c326a3..f482d5b 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheListType.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheListType.java
@@ -1,14 +1,23 @@
package cgeo.geocaching.enumerations;
public enum CacheListType {
- OFFLINE,
- POCKET,
- HISTORY,
- NEAREST,
- COORDINATE,
- KEYWORD,
- ADDRESS,
- USERNAME,
- OWNER,
- MAP;
+ OFFLINE(true),
+ POCKET(false),
+ HISTORY(true),
+ NEAREST(false),
+ COORDINATE(false),
+ KEYWORD(false),
+ ADDRESS(false),
+ USERNAME(false),
+ OWNER(false),
+ MAP(false);
+
+ /**
+ * whether or not this list allows switching to another list
+ */
+ public final boolean canSwitch;
+
+ private 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 726ebe2..a6f8df3 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheSize.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheSize.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.enumerations;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import java.util.Collections;
import java.util.HashMap;
@@ -60,7 +60,7 @@ public enum CacheSize {
}
public final String getL10n() {
- return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId);
+ 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 c7a9130..c952ba0 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheType.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheType.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.enumerations;
import cgeo.geocaching.ICache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import java.util.Collections;
import java.util.HashMap;
@@ -85,7 +85,7 @@ public enum CacheType {
}
public final String getL10n() {
- return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId);
+ return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId);
}
public boolean isEvent() {
@@ -114,7 +114,7 @@ public enum CacheType {
}
public boolean applyDistanceRule() {
- return !isVirtual() && !isEvent();
+ return TRADITIONAL == this || PROJECT_APE == this || GCHQ == this;
}
public boolean isVirtual() {
diff --git a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java b/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java
index 5f5b2c9..710c3ba 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.CgeoApplication;
import java.util.EnumSet;
@@ -42,7 +42,7 @@ public interface LiveMapStrategy {
}
public final String getL10n() {
- return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId);
+ return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId);
}
}
}
diff --git a/main/src/cgeo/geocaching/enumerations/LogType.java b/main/src/cgeo/geocaching/enumerations/LogType.java
index 9902d3f..543f83d 100644
--- a/main/src/cgeo/geocaching/enumerations/LogType.java
+++ b/main/src/cgeo/geocaching/enumerations/LogType.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.enumerations;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import java.util.Collections;
import java.util.HashMap;
@@ -102,6 +102,6 @@ public enum LogType {
}
public final String getL10n() {
- return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId);
+ return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId);
}
}
diff --git a/main/src/cgeo/geocaching/enumerations/WaypointType.java b/main/src/cgeo/geocaching/enumerations/WaypointType.java
index 79c8106..272b2f2 100644
--- a/main/src/cgeo/geocaching/enumerations/WaypointType.java
+++ b/main/src/cgeo/geocaching/enumerations/WaypointType.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.enumerations;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import java.util.Collections;
import java.util.HashMap;
@@ -65,7 +65,7 @@ public enum WaypointType {
}
public final String getL10n() {
- return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId);
+ return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId);
}
@Override
diff --git a/main/src/cgeo/geocaching/export/AbstractExport.java b/main/src/cgeo/geocaching/export/AbstractExport.java
index e4ba5f0..5d15ecb 100644
--- a/main/src/cgeo/geocaching/export/AbstractExport.java
+++ b/main/src/cgeo/geocaching/export/AbstractExport.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.export;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
abstract class AbstractExport implements Export {
private final String name;
@@ -23,7 +23,7 @@ abstract class AbstractExport implements Export {
* @return localized string
*/
protected static String getString(int resourceId) {
- return cgeoapplication.getInstance().getString(resourceId);
+ return CgeoApplication.getInstance().getString(resourceId);
}
/**
@@ -36,7 +36,7 @@ abstract class AbstractExport implements Export {
* @return localized string
*/
protected static String getString(int resourceId, Object... params) {
- return cgeoapplication.getInstance().getString(resourceId, params);
+ return CgeoApplication.getInstance().getString(resourceId, params);
}
@Override
diff --git a/main/src/cgeo/geocaching/export/ExportFactory.java b/main/src/cgeo/geocaching/export/ExportFactory.java
index a3ecb0c..e743eb2 100644
--- a/main/src/cgeo/geocaching/export/ExportFactory.java
+++ b/main/src/cgeo/geocaching/export/ExportFactory.java
@@ -56,6 +56,7 @@ public abstract class ExportFactory {
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
+ dialog.dismiss();
final Export selectedExport = adapter.getItem(item);
selectedExport.export(caches, activity);
}
diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java
index d0040a9..1ae97f3 100644
--- a/main/src/cgeo/geocaching/export/FieldnoteExport.java
+++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.export;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.connector.gc.Login;
import cgeo.geocaching.enumerations.StatusCode;
@@ -13,11 +13,12 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.utils.AsyncTaskWithProgress;
import cgeo.geocaching.utils.FileUtils;
-import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.Log;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
import android.app.Activity;
import android.app.AlertDialog;
@@ -42,7 +43,7 @@ import java.util.Locale;
import java.util.TimeZone;
/**
- * Exports offline-logs in the Groundspeak Field Note format.<br>
+ * Exports offline logs in the Groundspeak Field Note format.<br>
* <br>
*
* Field Notes are simple plain text files, but poorly documented. Syntax:<br>
@@ -50,10 +51,7 @@ import java.util.TimeZone;
*/
class FieldnoteExport extends AbstractExport {
private static final File exportLocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/field-notes");
- private static final SimpleDateFormat fieldNoteDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
- static {
- fieldNoteDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- }
+ private static final FastDateFormat fieldNoteDateFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("UTC"), Locale.US);
protected FieldnoteExport() {
super(getString(R.string.export_fieldnotes));
@@ -80,22 +78,24 @@ class FieldnoteExport extends AbstractExport {
builder.setView(layout);
final CheckBox uploadOption = (CheckBox) layout.findViewById(R.id.upload);
+ uploadOption.setChecked(Settings.getFieldNoteExportUpload());
final CheckBox onlyNewOption = (CheckBox) layout.findViewById(R.id.onlynew);
+ onlyNewOption.setChecked(Settings.getFieldNoteExportOnlyNew());
if (Settings.getFieldnoteExportDate() > 0) {
- onlyNewOption.setText(getString(R.string.export_fieldnotes_onlynew) + "\n(" + Formatter.formatShortDateTime(Settings.getFieldnoteExportDate()) + ')');
+ onlyNewOption.setText(getString(R.string.export_fieldnotes_onlynew) + " (" + Formatter.formatDateTime(Settings.getFieldnoteExportDate()) + ')');
}
builder.setPositiveButton(R.string.export, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
+ final boolean upload = uploadOption.isChecked();
+ final boolean onlyNew = onlyNewOption.isChecked();
+ Settings.setFieldNoteExportUpload(upload);
+ Settings.setFieldNoteExportOnlyNew(onlyNew);
dialog.dismiss();
- new ExportTask(
- activity,
- uploadOption.isChecked(),
- onlyNewOption.isChecked())
- .execute(caches);
+ new ExportTask(activity, upload, onlyNew).execute(caches);
}
});
@@ -134,7 +134,7 @@ class FieldnoteExport extends AbstractExport {
int i = 0;
for (final Geocache cache : caches) {
if (cache.isLogOffline()) {
- final LogEntry log = cgData.loadLogOffline(cache.getGeocode());
+ final LogEntry log = DataStore.loadLogOffline(cache.getGeocode());
if (!onlyNew || log.date > Settings.getFieldnoteExportDate()) {
appendFieldNote(fieldNoteBuffer, cache, log);
}
diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java
index 36e43a0..a2e0f93 100644
--- a/main/src/cgeo/geocaching/export/GpxExport.java
+++ b/main/src/cgeo/geocaching/export/GpxExport.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.export;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.AsyncTaskWithProgress;
@@ -125,7 +125,7 @@ class GpxExport extends AbstractExport {
final List<String> allGeocodes = new ArrayList<String>(Arrays.asList(geocodes));
- setMessage(cgeoapplication.getInstance().getResources().getQuantityString(R.plurals.cache_counts, allGeocodes.size(), allGeocodes.size()));
+ setMessage(CgeoApplication.getInstance().getResources().getQuantityString(R.plurals.cache_counts, allGeocodes.size(), allGeocodes.size()));
final File exportFile = getExportFile();
BufferedWriter writer = null;
diff --git a/main/src/cgeo/geocaching/export/GpxSerializer.java b/main/src/cgeo/geocaching/export/GpxSerializer.java
index 1e39be4..da179da 100644
--- a/main/src/cgeo/geocaching/export/GpxSerializer.java
+++ b/main/src/cgeo/geocaching/export/GpxSerializer.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.export;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.enumerations.CacheAttribute;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.geopoint.Geopoint;
@@ -13,11 +13,11 @@ import cgeo.org.kxml2.io.KXmlSerializer;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.Writer;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -27,7 +27,7 @@ import java.util.Set;
public final class GpxSerializer {
- private static final SimpleDateFormat dateFormatZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
+ private static final FastDateFormat dateFormatZ = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
public static final String PREFIX_XSI = "http://www.w3.org/2001/XMLSchema-instance";
public static final String PREFIX_GPX = "http://www.topografix.com/GPX/1/0";
public static final String PREFIX_GROUNDSPEAK = "http://www.groundspeak.com/cache/1/0";
@@ -81,7 +81,7 @@ public final class GpxSerializer {
}
private void exportBatch(final XmlSerializer gpx, Collection<String> geocodesOfBatch) throws IOException {
- final Set<Geocache> caches = cgData.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY);
+ final Set<Geocache> caches = DataStore.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY);
for (final Geocache cache : caches) {
gpx.startTag(PREFIX_GPX, "wpt");
gpx.attribute("", "lat", Double.toString(cache.getCoords().getLatitude()));
diff --git a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
index b0aba58..35e6265 100644
--- a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
+++ b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
@@ -2,12 +2,12 @@ package cgeo.geocaching.files;
import cgeo.geocaching.Intents;
import cgeo.geocaching.R;
-import cgeo.geocaching.StoredList;
import cgeo.geocaching.activity.AbstractListActivity;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.ProgressDialog;
@@ -66,7 +66,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
if (waitDialog != null) {
waitDialog.dismiss();
}
- if (CollectionUtils.isEmpty(files)) {
+ if (CollectionUtils.isEmpty(files) && requireFiles()) {
showToast(res.getString(R.string.file_list_no_files));
finish();
} else if (adapter != null) {
@@ -104,7 +104,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
if (searchingThread != null && searchingThread.isAlive()) {
searchingThread.notifyEnd();
}
- if (files.isEmpty()) {
+ if (files.isEmpty() && requireFiles()) {
finish();
}
}
@@ -121,6 +121,10 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
}
+ protected boolean requireFiles() {
+ return true;
+ }
+
protected abstract T getAdapter(List<File> files);
private void setAdapter() {
diff --git a/main/src/cgeo/geocaching/files/FileParser.java b/main/src/cgeo/geocaching/files/FileParser.java
index f979d74..396a589 100644
--- a/main/src/cgeo/geocaching/files/FileParser.java
+++ b/main/src/cgeo/geocaching/files/FileParser.java
@@ -2,7 +2,8 @@ package cgeo.geocaching.files;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.utils.CancellableHandler;
-import cgeo.geocaching.utils.IOUtils;
+
+import org.apache.commons.io.IOUtils;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
@@ -51,7 +52,7 @@ public abstract class FileParser {
protected static StringBuilder readStream(InputStream is, CancellableHandler progressHandler) throws IOException {
final StringBuilder buffer = new StringBuilder();
ProgressInputStream progressInputStream = new ProgressInputStream(is);
- final BufferedReader input = new BufferedReader(new InputStreamReader(progressInputStream));
+ final BufferedReader input = new BufferedReader(new InputStreamReader(progressInputStream, "UTF-8"));
try {
String line;
diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java
index 3f11c26..bf0aa72 100644
--- a/main/src/cgeo/geocaching/files/GPXImporter.java
+++ b/main/src/cgeo/geocaching/files/GPXImporter.java
@@ -4,7 +4,7 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.StaticMapsProvider;
-import cgeo.geocaching.cgData;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.enumerations.LoadFlags;
@@ -175,7 +175,7 @@ public class GPXImporter {
private boolean importStaticMaps(final SearchResult importedCaches) {
int storedCacheMaps = 0;
for (final String geocode : importedCaches.getGeocodes()) {
- final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
if (cache != null) {
Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode);
StaticMapsProvider.downloadMaps(cache);
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
index 3358759..e01c191 100644
--- a/main/src/cgeo/geocaching/files/GPXParser.java
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -1,13 +1,12 @@
package cgeo.geocaching.files;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
-import cgeo.geocaching.StoredList;
import cgeo.geocaching.Trackable;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
@@ -17,9 +16,11 @@ import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
+import cgeo.geocaching.utils.SynchronizedDateFormat;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.Attributes;
@@ -35,7 +36,6 @@ import android.util.Xml;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -47,9 +47,9 @@ import java.util.regex.Pattern;
public abstract class GPXParser extends FileParser {
- private static final SimpleDateFormat formatSimple = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US); // 2010-04-20T07:00:00
- private static final SimpleDateFormat formatSimpleZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); // 2010-04-20T07:00:00Z
- private static final SimpleDateFormat formatTimezone = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US); // 2010-04-20T01:01:03-04:00
+ private static final SynchronizedDateFormat formatSimple = new SynchronizedDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US); // 2010-04-20T07:00:00
+ private static final SynchronizedDateFormat formatSimpleZ = new SynchronizedDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); // 2010-04-20T07:00:00Z
+ private static final SynchronizedDateFormat formatTimezone = new SynchronizedDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US); // 2010-04-20T01:01:03-04:00
/**
* Attention: case sensitive geocode pattern to avoid matching normal words in the name or description of the cache.
@@ -205,7 +205,7 @@ public abstract class GPXParser extends FileParser {
// get text for string
String stringName;
try {
- stringName = cgeoapplication.getInstance().getResources().getResourceName(stringId);
+ stringName = CgeoApplication.getInstance().getResources().getResourceName(stringId);
} catch (final NullPointerException e) {
return null;
}
@@ -312,10 +312,10 @@ public abstract class GPXParser extends FileParser {
// finally store the cache in the database
result.add(geocode);
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
// avoid the cachecache using lots of memory for caches which the user did not actually look at
- cgData.removeAllFromCache();
+ DataStore.removeAllFromCache();
showProgressMessage(progressHandler, progressStream.getProgress());
} else if (StringUtils.isNotBlank(cache.getName())
&& StringUtils.containsIgnoreCase(type, "waypoint")) {
@@ -331,7 +331,7 @@ public abstract class GPXParser extends FileParser {
if (cache.getName().length() > 2) {
final String cacheGeocodeForWaypoint = "GC" + cache.getName().substring(2).toUpperCase(Locale.US);
// lookup cache for waypoint in already parsed caches
- final Geocache cacheForWaypoint = cgData.loadCache(cacheGeocodeForWaypoint, LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cacheForWaypoint = DataStore.loadCache(cacheGeocodeForWaypoint, LoadFlags.LOAD_CACHE_OR_DB);
if (cacheForWaypoint != null) {
final Waypoint waypoint = new Waypoint(cache.getShortDescription(), convertWaypointSym2Type(sym), false);
waypoint.setId(-1);
@@ -349,7 +349,7 @@ public abstract class GPXParser extends FileParser {
newPoints.add(waypoint);
Waypoint.mergeWayPoints(newPoints, mergedWayPoints, true);
cacheForWaypoint.setWaypoints(newPoints, false);
- cgData.saveCache(cacheForWaypoint, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cacheForWaypoint, EnumSet.of(SaveFlag.SAVE_DB));
showProgressMessage(progressHandler, progressStream.getProgress());
}
}
@@ -785,9 +785,8 @@ public abstract class GPXParser extends FileParser {
try {
progressStream = new ProgressInputStream(stream);
Xml.parse(progressStream, Xml.Encoding.UTF_8, root.getContentHandler());
- return cgData.loadCaches(result, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL));
+ return DataStore.loadCaches(result, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL));
} catch (final SAXException e) {
- Log.w("Cannot parse .gpx file as GPX " + version + ": could not parse XML - ", e);
throw new ParserException("Cannot parse .gpx file as GPX " + version + ": could not parse XML", e);
}
}
diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java
index 1cfb2a3..3d01c1b 100644
--- a/main/src/cgeo/geocaching/files/LocParser.java
+++ b/main/src/cgeo/geocaching/files/LocParser.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.files;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
@@ -59,7 +59,7 @@ public final class LocParser extends FileParser {
contained.add(geocode);
}
}
- Set<Geocache> caches = cgData.loadCaches(contained, LoadFlags.LOAD_CACHE_OR_DB);
+ Set<Geocache> caches = DataStore.loadCaches(contained, LoadFlags.LOAD_CACHE_OR_DB);
for (Geocache cache : caches) {
Geocache coord = cidCoords.get(cache.getGeocode());
copyCoordToCache(coord, cache);
diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java
index fc82409..edbecf6 100644
--- a/main/src/cgeo/geocaching/files/LocalStorage.java
+++ b/main/src/cgeo/geocaching/files/LocalStorage.java
@@ -1,15 +1,16 @@
package cgeo.geocaching.files;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.utils.CryptUtils;
import cgeo.geocaching.utils.FileUtils;
-import cgeo.geocaching.utils.IOUtils;
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;
import android.os.Environment;
@@ -21,11 +22,13 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
-import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
@@ -35,6 +38,7 @@ import java.util.List;
*/
public final class LocalStorage {
+ private static final String FILE_SYSTEM_TABLE_PATH = "/system/etc/vold.fstab";
public static final String HEADER_LAST_MODIFIED = "last-modified";
public static final String HEADER_ETAG = "etag";
@@ -86,7 +90,7 @@ public final class LocalStorage {
private static File getInternalStorageBase() {
if (internalStorageBase == null) {
// A race condition will do no harm as the operation is idempotent. No need to synchronize.
- internalStorageBase = cgeoapplication.getInstance().getApplicationContext().getFilesDir().getParentFile();
+ internalStorageBase = CgeoApplication.getInstance().getApplicationContext().getFilesDir().getParentFile();
}
return internalStorageBase;
}
@@ -99,7 +103,14 @@ public final class LocalStorage {
* @return the file extension, including the leading dot, or the empty string if none could be determined
*/
static String getExtension(final String url) {
- final String urlExt = StringUtils.substringAfterLast(url, ".");
+ String urlExt;
+ if (url.startsWith("data:")) {
+ // "data:image/png;base64,i53โ€ฆ" -> ".png"
+ urlExt = StringUtils.substringAfter(StringUtils.substringBefore(url, ";"), "/");
+ } else {
+ // "http://example.com/foo/bar.png" -> ".png"
+ urlExt = StringUtils.substringAfterLast(url, ".");
+ }
return urlExt.length() >= 1 && urlExt.length() <= 4 ? "." + urlExt : "";
}
@@ -198,13 +209,19 @@ public final class LocalStorage {
return false;
}
- private static void saveHeader(final String name, final HttpResponse response, final File baseFile) {
+ private static void saveHeader(final String name, @Nullable final HttpResponse response, final File baseFile) {
final Header header = response != null ? response.getFirstHeader(name) : null;
final File file = filenameForHeader(baseFile, name);
if (header == null) {
FileUtils.deleteIgnoringFailure(file);
} else {
- saveToFile(new ByteArrayInputStream(header.getValue().getBytes()), file);
+ try {
+ saveToFile(new ByteArrayInputStream(header.getValue().getBytes("UTF-8")), file);
+ } catch (final UnsupportedEncodingException e) {
+ // Do not try to display the header in the log message, as our default encoding is
+ // likely to be UTF-8 and it will fail as well.
+ Log.e("LocalStorage.saveHeader: unable to decode header", e);
+ }
}
}
@@ -219,12 +236,13 @@ public final class LocalStorage {
* the name of the cached resource
* @param name
* the name of the header ("etag" or "last-modified")
- * @return null if no value has been cached, the value otherwise
+ * @return the cached value, or <tt>null</tt> if none has been cached
*/
+ @Nullable
public static String getSavedHeader(final File baseFile, final String name) {
try {
final File file = filenameForHeader(baseFile, name);
- final FileReader f = new FileReader(file);
+ final Reader f = new InputStreamReader(new FileInputStream(file), "UTF-8");
try {
// No header will be more than 256 bytes
final char[] value = new char[256];
@@ -408,12 +426,12 @@ public final class LocalStorage {
String extStorage = Environment.getExternalStorageDirectory().getAbsolutePath();
List<File> storages = new ArrayList<File>();
storages.add(new File(extStorage));
- File file = new File("/system/etc/vold.fstab");
+ File file = new File(FILE_SYSTEM_TABLE_PATH);
if (file.canRead()) {
- FileReader fr = null;
+ Reader fr = null;
BufferedReader br = null;
try {
- fr = new FileReader(file);
+ fr = new InputStreamReader(new FileInputStream(file), "UTF-8");
br = new BufferedReader(fr);
String s = br.readLine();
while (s != null) {
diff --git a/main/src/cgeo/geocaching/files/ProgressInputStream.java b/main/src/cgeo/geocaching/files/ProgressInputStream.java
index 593949b..552aee0 100644
--- a/main/src/cgeo/geocaching/files/ProgressInputStream.java
+++ b/main/src/cgeo/geocaching/files/ProgressInputStream.java
@@ -4,6 +4,14 @@ import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
+/**
+ * Stream to measure progress of reading automatically.
+ * <p>
+ * The method @link ProgressInputStream#read(byte[]) does not need to be overridden as it delegates to @link
+ * ProgressInputStream#read(byte[], int, int) anyway.
+ * </p>
+ *
+ */
public class ProgressInputStream extends FilterInputStream {
private int progress = 0;
@@ -15,17 +23,13 @@ public class ProgressInputStream extends FilterInputStream {
@Override
public int read() throws IOException {
final int read = super.read();
- progress += read;
+ if (read >= 0) {
+ progress++;
+ }
return read;
}
@Override
- public int read(byte[] buffer) throws IOException {
- return super.read(buffer);
- // don't increment here, this calls another read implementation which we already measure
- }
-
- @Override
public int read(byte[] buffer, int offset, int count) throws IOException {
final int read = super.read(buffer, offset, count);
progress += read;
diff --git a/main/src/cgeo/geocaching/files/SimpleDirChooser.java b/main/src/cgeo/geocaching/files/SimpleDirChooser.java
index 8f69b88..e59287d 100644
--- a/main/src/cgeo/geocaching/files/SimpleDirChooser.java
+++ b/main/src/cgeo/geocaching/files/SimpleDirChooser.java
@@ -32,17 +32,20 @@ import java.util.List;
* Dialog for choosing a file or directory.
*/
public class SimpleDirChooser extends AbstractListActivity {
+ public static final String EXTRA_CHOOSE_FOR_WRITING = "chooseForWriting";
private static final String PARENT_DIR = ".. ";
private File currentDir;
private FileArrayAdapter adapter;
private Button okButton = null;
private int lastPosition = -1;
+ private boolean chooseForWriting = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle extras = getIntent().getExtras();
currentDir = dirContaining(extras.getString(Intents.EXTRA_START_DIR));
+ chooseForWriting = extras.getBoolean(SimpleDirChooser.EXTRA_CHOOSE_FOR_WRITING, false);
ActivityMixin.setTheme(this);
setContentView(R.layout.simple_dir_chooser);
@@ -85,19 +88,20 @@ public class SimpleDirChooser extends AbstractListActivity {
}
private void fill(File dir) {
+ lastPosition = -1;
EditText path = (EditText) findViewById(R.id.simple_dir_chooser_path);
path.setText(this.getResources().getString(R.string.simple_dir_chooser_current_path) + " " + dir.getAbsolutePath());
final File[] dirs = dir.listFiles(new DirOnlyFilenameFilter());
List<Option> listDirs = new ArrayList<Option>();
try {
for (File currentDir : dirs) {
- listDirs.add(new Option(currentDir.getName(), currentDir.getAbsolutePath()));
+ listDirs.add(new Option(currentDir.getName(), currentDir.getAbsolutePath(), currentDir.canWrite()));
}
} catch (RuntimeException e) {
}
Collections.sort(listDirs);
if (dir.getParent() != null) {
- listDirs.add(0, new Option(PARENT_DIR, dir.getParent()));
+ listDirs.add(0, new Option(PARENT_DIR, dir.getParent(), false));
}
this.adapter = new FileArrayAdapter(this, R.layout.simple_dir_item, listDirs);
this.setListAdapter(adapter);
@@ -138,8 +142,13 @@ public class SimpleDirChooser extends AbstractListActivity {
}
CheckBox check = (CheckBox) v.findViewById(R.id.CheckBox);
if (check != null) {
- check.setOnClickListener(new OnCheckBoxClickListener(position));
- check.setChecked(option.isChecked());
+ if (!chooseForWriting || option.isWriteable()) {
+ check.setOnClickListener(new OnCheckBoxClickListener(position));
+ check.setChecked(option.isChecked());
+ check.setEnabled(true);
+ } else {
+ check.setEnabled(false);
+ }
}
}
return v;
@@ -196,14 +205,19 @@ public class SimpleDirChooser extends AbstractListActivity {
}
}
+ /**
+ * Note: this class has a natural ordering that is inconsistent with equals.
+ */
public static class Option implements Comparable<Option> {
private final String name;
private final String path;
private boolean checked = false;
+ private boolean writeable = false;
- public Option(String name, String path) {
+ public Option(String name, String path, boolean writeable) {
this.name = name;
this.path = path;
+ this.writeable = writeable;
}
public String getName() {
@@ -222,6 +236,10 @@ public class SimpleDirChooser extends AbstractListActivity {
this.checked = checked;
}
+ public boolean isWriteable() {
+ return writeable;
+ }
+
@Override
public int compareTo(Option other) {
if (other != null && this.name != null) {
@@ -236,7 +254,7 @@ public class SimpleDirChooser extends AbstractListActivity {
@Override
public boolean accept(File dir, String filename) {
File file = new File(dir, filename);
- return file.isDirectory() && file.canWrite();
+ return file.isDirectory() && file.canRead();
}
}
diff --git a/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java b/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java
index 96d256a..cafb92b 100644
--- a/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java
+++ b/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.filter;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
abstract class AbstractRangeFilter extends AbstractFilter {
@@ -9,7 +9,7 @@ abstract class AbstractRangeFilter extends AbstractFilter {
protected final float rangeMax;
protected AbstractRangeFilter(final int ressourceId, final int range) {
- super(cgeoapplication.getInstance().getResources().getString(ressourceId) + ' ' + (range == 5 ? '5' : range + " + " + String.format("%.1f", range + 0.5)));
+ super(CgeoApplication.getInstance().getResources().getString(ressourceId) + ' ' + (range == 5 ? '5' : range + " + " + String.format("%.1f", range + 0.5)));
this.rangeMin = range;
rangeMax = rangeMin + 1f;
}
diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java
index cadcf49..6f0d5da 100644
--- a/main/src/cgeo/geocaching/filter/AttributeFilter.java
+++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.filter;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.LoadFlags.LoadFlag;
import android.content.res.Resources;
@@ -29,7 +29,7 @@ class AttributeFilter extends AbstractFilter {
@Override
public boolean accepts(final Geocache cache) {
- Geocache fullCache = cgData.loadCache(cache.getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES));
+ Geocache fullCache = DataStore.loadCache(cache.getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES));
if (fullCache == null) {
fullCache = cache;
}
@@ -40,8 +40,8 @@ class AttributeFilter extends AbstractFilter {
@Override
public List<IFilter> getFilters() {
- final String packageName = cgeoapplication.getInstance().getBaseContext().getPackageName();
- final Resources res = cgeoapplication.getInstance().getResources();
+ final String packageName = CgeoApplication.getInstance().getBaseContext().getPackageName();
+ final Resources res = CgeoApplication.getInstance().getResources();
final List<IFilter> filters = new LinkedList<IFilter>();
for (final String id: res.getStringArray(R.array.attribute_ids)) {
diff --git a/main/src/cgeo/geocaching/filter/DistanceFilter.java b/main/src/cgeo/geocaching/filter/DistanceFilter.java
index 4d00b65..54225d2 100644
--- a/main/src/cgeo/geocaching/filter/DistanceFilter.java
+++ b/main/src/cgeo/geocaching/filter/DistanceFilter.java
@@ -3,7 +3,7 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.geopoint.Geopoint;
import java.util.ArrayList;
@@ -18,7 +18,7 @@ class DistanceFilter extends AbstractFilter {
super(name);
this.minDistance = minDistance;
this.maxDistance = maxDistance;
- geo = cgeoapplication.getInstance().currentGeo();
+ geo = CgeoApplication.getInstance().currentGeo();
}
@Override
@@ -51,7 +51,7 @@ class DistanceFilter extends AbstractFilter {
maxRange = Integer.MAX_VALUE;
}
final String range = maxRange == Integer.MAX_VALUE ? "> " + minRange : minRange + " - " + maxRange;
- final String name = cgeoapplication.getInstance().getResources().getQuantityString(R.plurals.tts_kilometers, maxRange, range);
+ final String name = CgeoApplication.getInstance().getResources().getQuantityString(R.plurals.tts_kilometers, maxRange, range);
filters.add(new DistanceFilter(name, minRange, maxRange));
}
return filters;
diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
index 2404f44..8ff700a 100644
--- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java
+++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.filter;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
@@ -41,7 +41,7 @@ public final class FilterUserInterface {
public FilterUserInterface(final Activity activity) {
this.activity = activity;
- this.res = cgeoapplication.getInstance().getResources();
+ this.res = CgeoApplication.getInstance().getResources();
registry = new ArrayList<FactoryEntry>();
if (Settings.getCacheType() == CacheType.ALL) {
diff --git a/main/src/cgeo/geocaching/filter/ModifiedFilter.java b/main/src/cgeo/geocaching/filter/ModifiedFilter.java
index 74befda..d976b69 100644
--- a/main/src/cgeo/geocaching/filter/ModifiedFilter.java
+++ b/main/src/cgeo/geocaching/filter/ModifiedFilter.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import java.util.Collections;
import java.util.List;
@@ -10,7 +10,7 @@ import java.util.List;
class ModifiedFilter extends AbstractFilter implements IFilterFactory {
public ModifiedFilter() {
- super(cgeoapplication.getInstance().getString(R.string.caches_filter_modified));
+ super(CgeoApplication.getInstance().getString(R.string.caches_filter_modified));
}
@Override
diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java
index 98589ab..d5b3027 100644
--- a/main/src/cgeo/geocaching/filter/StateFilter.java
+++ b/main/src/cgeo/geocaching/filter/StateFilter.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 android.content.res.Resources;
@@ -13,7 +13,7 @@ import java.util.List;
abstract class StateFilter extends AbstractFilter {
- static final Resources res = cgeoapplication.getInstance().getResources();
+ static final Resources res = CgeoApplication.getInstance().getResources();
protected StateFilter(final String name) {
super(name);
diff --git a/main/src/cgeo/geocaching/filter/TrackablesFilter.java b/main/src/cgeo/geocaching/filter/TrackablesFilter.java
index 74f43be..d836a0f 100644
--- a/main/src/cgeo/geocaching/filter/TrackablesFilter.java
+++ b/main/src/cgeo/geocaching/filter/TrackablesFilter.java
@@ -1,15 +1,15 @@
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;
class TrackablesFilter extends AbstractFilter implements IFilterFactory {
public TrackablesFilter() {
- super(cgeoapplication.getInstance().getString(R.string.caches_filter_track));
+ super(CgeoApplication.getInstance().getString(R.string.caches_filter_track));
}
@Override
diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java
index c3c7b8d..b245aa9 100644
--- a/main/src/cgeo/geocaching/gcvote/GCVote.java
+++ b/main/src/cgeo/geocaching/gcvote/GCVote.java
@@ -8,7 +8,7 @@ import cgeo.geocaching.utils.LeastRecentlyUsedMap;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
-import org.apache.commons.collections.MapUtils;
+import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
@@ -16,10 +16,12 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
public final class GCVote {
+ public static final float NO_RATING = 0;
private static final Pattern PATTERN_LOG_IN = Pattern.compile("loggedIn='([^']+)'", Pattern.CASE_INSENSITIVE);
private static final Pattern PATTERN_GUID = Pattern.compile("cacheId='([^']+)'", Pattern.CASE_INSENSITIVE);
private static final Pattern PATTERN_WAYPOINT = Pattern.compile("waypoint='([^']+)'", Pattern.CASE_INSENSITIVE);
@@ -30,6 +32,12 @@ public final class GCVote {
private static final int MAX_CACHED_RATINGS = 1000;
private static final LeastRecentlyUsedMap<String, GCVoteRating> RATINGS_CACHE = new LeastRecentlyUsedMap.LruCache<String, GCVoteRating>(MAX_CACHED_RATINGS);
+ private static final float MIN_RATING = 1;
+ private static final float MAX_RATING = 5;
+
+ private GCVote() {
+ // utility class
+ }
/**
* Get user rating for a given guid or geocode. For a guid first the ratings cache is checked
@@ -39,7 +47,7 @@ public final class GCVote {
* @param geocode
* @return
*/
- public static GCVoteRating getRating(String guid, String geocode) {
+ public static GCVoteRating getRating(final String guid, final String geocode) {
if (StringUtils.isNotBlank(guid) && RATINGS_CACHE.containsKey(guid)) {
return RATINGS_CACHE.get(guid);
}
@@ -59,7 +67,7 @@ public final class GCVote {
* @param geocodes
* @return
*/
- public static Map<String, GCVoteRating> getRating(List<String> guids, List<String> geocodes) {
+ public static Map<String, GCVoteRating> getRating(final List<String> guids, final List<String> geocodes) {
if (guids == null && geocodes == null) {
return null;
}
@@ -128,7 +136,7 @@ public final class GCVote {
}
}
- float rating = 0;
+ float rating = NO_RATING;
try {
final MatcherWrapper matcherRating = new MatcherWrapper(PATTERN_RATING, voteData);
if (matcherRating.find()) {
@@ -137,7 +145,7 @@ public final class GCVote {
} catch (NumberFormatException e) {
Log.w("GCVote.getRating: Failed to parse rating");
}
- if (rating <= 0) {
+ if (!isValidRating(rating)) {
continue;
}
@@ -154,7 +162,7 @@ public final class GCVote {
continue;
}
- float myVote = 0;
+ float myVote = NO_RATING;
if (loggedIn) {
try {
final MatcherWrapper matcherVote = new MatcherWrapper(PATTERN_VOTE, voteData);
@@ -186,18 +194,11 @@ public final class GCVote {
* @param vote
* @return {@code true} if the rating was submitted successfully
*/
- public static boolean setRating(Geocache cache, double vote) {
- if (!Settings.isGCvoteLogin()) {
- return false;
- }
- if (!cache.supportsGCVote()) {
+ public static boolean setRating(final Geocache cache, final float vote) {
+ if (!isVotingPossible(cache)) {
return false;
}
- String guid = cache.getGuid();
- if (StringUtils.isBlank(guid)) {
- return false;
- }
- if (vote <= 0.0 || vote > 5.0) {
+ if (!isValidRating(vote)) {
return false;
}
@@ -209,16 +210,16 @@ public final class GCVote {
final Parameters params = new Parameters(
"userName", login.left,
"password", login.right,
- "cacheId", guid,
+ "cacheId", cache.getGuid(),
"voteUser", String.format("%.1f", vote).replace(',', '.'),
"version", "cgeo");
final String result = Network.getResponseData(Network.getRequest("http://gcvote.com/setVote.php", params));
- return result.trim().equalsIgnoreCase("ok");
+ return result != null && result.trim().equalsIgnoreCase("ok");
}
- public static void loadRatings(ArrayList<Geocache> caches) {
+ public static void loadRatings(final ArrayList<Geocache> caches) {
if (!Settings.isRatingWanted()) {
return;
}
@@ -254,4 +255,17 @@ public final class GCVote {
Log.e("GCvote.loadRatings", e);
}
}
+
+ public static boolean isValidRating(final float rating) {
+ return rating >= MIN_RATING && rating <= MAX_RATING;
+ }
+
+ public static String getRatingText(final float rating) {
+ return String.format(Locale.getDefault(), "%.1f", rating);
+ }
+
+ public static boolean isVotingPossible(final Geocache cache) {
+ return Settings.isGCvoteLogin() && StringUtils.isNotBlank(cache.getGuid()) && cache.supportsGCVote();
+ }
+
}
diff --git a/main/src/cgeo/geocaching/gcvote/GCVoteRating.java b/main/src/cgeo/geocaching/gcvote/GCVoteRating.java
index f6813a2..1e65589 100644
--- a/main/src/cgeo/geocaching/gcvote/GCVoteRating.java
+++ b/main/src/cgeo/geocaching/gcvote/GCVoteRating.java
@@ -5,7 +5,7 @@ public final class GCVoteRating {
private final int votes;
private final float myVote;
- public GCVoteRating(float rating, int votes, float myVote) {
+ public GCVoteRating(final float rating, final int votes, final float myVote) {
this.rating = rating;
this.votes = votes;
this.myVote = myVote;
diff --git a/main/src/cgeo/geocaching/geopoint/Geopoint.java b/main/src/cgeo/geocaching/geopoint/Geopoint.java
index 547ad29..f21df01 100644
--- a/main/src/cgeo/geocaching/geopoint/Geopoint.java
+++ b/main/src/cgeo/geocaching/geopoint/Geopoint.java
@@ -300,7 +300,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
@@ -364,8 +364,8 @@ public final class Geopoint implements ICoordinates, Parcelable {
}
/**
- * Get longitude chararcter (E or W).
- *
+ * 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 ba86e70..c043d6f 100644
--- a/main/src/cgeo/geocaching/geopoint/GeopointParser.java
+++ b/main/src/cgeo/geocaching/geopoint/GeopointParser.java
@@ -25,8 +25,8 @@ class GeopointParser {
}
// ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 )
- private static final Pattern PATTERN_LAT = Pattern.compile("\\b([NS])\\s*(\\d+)ยฐ?(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE);
- private static final Pattern PATTERN_LON = Pattern.compile("\\b([WE])\\s*(\\d+)ยฐ?(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE);
+ private static final Pattern PATTERN_LAT = Pattern.compile("\\b([NS]|)\\s*(\\d+)ยฐ?(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE);
+ private static final Pattern PATTERN_LON = Pattern.compile("\\b([WE]|)\\s*(\\d+)ยฐ?(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE);
private static final Pattern PATTERN_BAD_BLANK = Pattern.compile("(\\d)[,.] (\\d{2,})");
@@ -110,6 +110,12 @@ class GeopointParser {
final Pattern pattern = LatLon.LAT == latlon ? PATTERN_LAT : PATTERN_LON;
matcher = new MatcherWrapper(pattern, replaceSpaceAfterComma);
+ try {
+ return new ResultWrapper(Double.valueOf(replaceSpaceAfterComma), 0, text.length());
+ } catch (NumberFormatException e1) {
+ // fall through to advanced parsing
+ }
+
if (matcher.find()) {
final double sign = matcher.group(1).equalsIgnoreCase("S") || matcher.group(1).equalsIgnoreCase("W") ? -1.0 : 1.0;
final double degree = Integer.valueOf(matcher.group(2)).doubleValue();
@@ -131,13 +137,14 @@ class GeopointParser {
}
- // Nothing found with "N 52...", try to match string as decimaldegree
+ // Nothing found with "N 52...", try to match string as decimal degree parts (i.e. multiple doubles)
try {
final String[] items = StringUtils.split(text.trim());
- if (items.length > 0) {
+ if (items.length > 0 && items.length <= 2) {
final int index = (latlon == LatLon.LON ? items.length - 1 : 0);
- final int pos = (latlon == LatLon.LON ? text.lastIndexOf(items[index]) : text.indexOf(items[index]));
- return new ResultWrapper(Double.parseDouble(items[index]), pos, items[index].length());
+ final String textPart = items[index];
+ final int pos = (latlon == LatLon.LON ? text.lastIndexOf(textPart) : text.indexOf(textPart));
+ return new ResultWrapper(Double.parseDouble(textPart), pos, textPart.length());
}
} catch (NumberFormatException e) {
// The right exception will be raised below.
diff --git a/main/src/cgeo/geocaching/list/AbstractList.java b/main/src/cgeo/geocaching/list/AbstractList.java
new file mode 100644
index 0000000..ec783eb
--- /dev/null
+++ b/main/src/cgeo/geocaching/list/AbstractList.java
@@ -0,0 +1,28 @@
+package cgeo.geocaching.list;
+
+import org.eclipse.jdt.annotation.Nullable;
+
+import android.util.SparseArray;
+
+public abstract class AbstractList {
+
+ public final int id;
+ public final String title;
+ private static SparseArray<AbstractList> LISTS = new SparseArray<AbstractList>();
+
+ public AbstractList(final int id, final String title) {
+ this.id = id;
+ this.title = title;
+ LISTS.put(id, this);
+ }
+
+ public abstract String getTitleAndCount();
+
+ public abstract boolean isConcrete();
+
+ @Nullable
+ public static AbstractList getListById(int listId) {
+ return LISTS.get(listId);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/list/PseudoList.java b/main/src/cgeo/geocaching/list/PseudoList.java
new file mode 100644
index 0000000..365d6fd
--- /dev/null
+++ b/main/src/cgeo/geocaching/list/PseudoList.java
@@ -0,0 +1,37 @@
+package cgeo.geocaching.list;
+
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.R;
+
+public class PseudoList extends AbstractList {
+
+ private static final int ALL_LIST_ID = 2;
+ /**
+ * list entry to show all caches
+ */
+ public static final PseudoList ALL_LIST = new PseudoList(ALL_LIST_ID, R.string.list_all_lists);
+
+ private static final int NEW_LIST_ID = 3;
+ /**
+ * list entry to create a new list
+ */
+ public static final AbstractList NEW_LIST = new PseudoList(NEW_LIST_ID, R.string.list_menu_create);
+
+ /**
+ * private constructor to have all instances as constants in the class
+ */
+ private PseudoList(int id, final int titleResourceId) {
+ super(id, CgeoApplication.getInstance().getResources().getString(titleResourceId));
+ }
+
+ @Override
+ public String getTitleAndCount() {
+ return "<" + title + ">";
+ }
+
+ @Override
+ public boolean isConcrete() {
+ return false;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/StoredList.java b/main/src/cgeo/geocaching/list/StoredList.java
index e080af9..d3729c0 100644
--- a/main/src/cgeo/geocaching/StoredList.java
+++ b/main/src/cgeo/geocaching/list/StoredList.java
@@ -1,5 +1,8 @@
-package cgeo.geocaching;
+package cgeo.geocaching.list;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
+import cgeo.geocaching.R;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.utils.RunnableWithArgument;
@@ -19,21 +22,18 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-public final class StoredList {
+public final class StoredList extends AbstractList {
public static final int TEMPORARY_LIST_ID = 0;
+ public static final StoredList TEMPORARY_LIST = new StoredList(TEMPORARY_LIST_ID, "<temporary>", 0); // Never displayed
public static final int STANDARD_LIST_ID = 1;
- public static final int ALL_LIST_ID = 2;
-
- public final int id;
- public final String title;
private final int count; // this value is only valid as long as the list is not changed by other database operations
public StoredList(int id, String title, int count) {
- this.id = id;
- this.title = title;
+ super(id, title);
this.count = count;
}
+ @Override
public String getTitleAndCount() {
return title + " [" + count + "]";
}
@@ -59,41 +59,43 @@ public final class StoredList {
public static class UserInterface {
private final Activity activity;
- private final cgeoapplication app;
+ private final CgeoApplication app;
private final Resources res;
public UserInterface(final Activity activity) {
this.activity = activity;
- app = cgeoapplication.getInstance();
+ app = CgeoApplication.getInstance();
res = app.getResources();
}
- public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards) {
+ public void promptForListSelection(final int titleId, @NonNull final RunnableWithArgument<Integer> runAfterwards) {
promptForListSelection(titleId, runAfterwards, false, -1);
}
- public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId) {
+ public void promptForListSelection(final int titleId, @NonNull final RunnableWithArgument<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId) {
promptForListSelection(titleId, runAfterwards, onlyConcreteLists, exceptListId, StringUtils.EMPTY);
}
- public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId, final String newListName) {
- final List<StoredList> lists = getSortedLists();
+ public void promptForListSelection(final int titleId, @NonNull final RunnableWithArgument<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId, final String newListName) {
+ final List<AbstractList> lists = new ArrayList<AbstractList>();
+ lists.addAll(getSortedLists());
if (exceptListId > StoredList.TEMPORARY_LIST_ID) {
- StoredList exceptList = cgData.getList(exceptListId);
+ StoredList exceptList = DataStore.getList(exceptListId);
if (exceptList != null) {
lists.remove(exceptList);
}
}
+ if (!onlyConcreteLists) {
+ lists.add(PseudoList.ALL_LIST);
+ }
+ lists.add(PseudoList.NEW_LIST);
+
final List<CharSequence> listsTitle = new ArrayList<CharSequence>();
- for (StoredList list : lists) {
+ for (AbstractList list : lists) {
listsTitle.add(list.getTitleAndCount());
}
- if (!onlyConcreteLists) {
- listsTitle.add("<" + res.getString(R.string.list_menu_all_lists) + ">");
- }
- listsTitle.add("<" + res.getString(R.string.list_menu_create) + ">");
final CharSequence[] items = new CharSequence[listsTitle.size()];
@@ -102,27 +104,23 @@ public final class StoredList {
builder.setItems(listsTitle.toArray(items), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int itemId) {
- if (itemId == lists.size() && !onlyConcreteLists) {
- // all lists
- runAfterwards.run(StoredList.ALL_LIST_ID);
- } else if (itemId >= lists.size()) {
+ final AbstractList list = lists.get(itemId);
+ if (list == PseudoList.NEW_LIST) {
// create new list on the fly
promptForListCreation(runAfterwards, newListName);
}
else {
- if (runAfterwards != null) {
- runAfterwards.run(lists.get(itemId).id);
- }
+ runAfterwards.run(lists.get(itemId).id);
}
}
});
builder.create().show();
}
- private static @NonNull
- List<StoredList> getSortedLists() {
+ @NonNull
+ private static List<StoredList> getSortedLists() {
final Collator collator = Collator.getInstance();
- final List<StoredList> lists = cgData.getLists();
+ final List<StoredList> lists = DataStore.getLists();
Collections.sort(lists, new Comparator<StoredList>() {
@Override
@@ -141,18 +139,17 @@ public final class StoredList {
return lists;
}
- public void promptForListCreation(final RunnableWithArgument<Integer> runAfterwards, String newListName) {
+ 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>() {
@Override
public void run(final String listName) {
- final int newId = cgData.createList(listName);
+ final int newId = DataStore.createList(listName);
+ new StoredList(newId, listName, 0);
- if (newId >= cgData.customListIdOffset) {
+ if (newId >= DataStore.customListIdOffset) {
ActivityMixin.showToast(activity, res.getString(R.string.list_dialog_create_ok));
- if (runAfterwards != null) {
- runAfterwards.run(newId);
- }
+ runAfterwards.run(newId);
} else {
ActivityMixin.showToast(activity, res.getString(R.string.list_dialog_create_err));
}
@@ -188,16 +185,14 @@ public final class StoredList {
alert.show();
}
- public void promptForListRename(final int listId, final Runnable runAfterRename) {
- final StoredList list = cgData.getList(listId);
+ 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>() {
@Override
public void run(final String listName) {
- cgData.renameList(listId, listName);
- if (runAfterRename != null) {
- runAfterRename.run();
- }
+ DataStore.renameList(listId, listName);
+ runAfterRename.run();
}
});
}
@@ -216,9 +211,15 @@ public final class StoredList {
* Return the given list, if it is a concrete list. Return the default list otherwise.
*/
public static int getConcreteList(int listId) {
- if (listId == ALL_LIST_ID || listId == TEMPORARY_LIST_ID) {
+ if (listId == PseudoList.ALL_LIST.id || listId == TEMPORARY_LIST_ID) {
return STANDARD_LIST_ID;
}
return listId;
}
+
+ @Override
+ public boolean isConcrete() {
+ return true;
+ }
+
}
diff --git a/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java
index 722f9f5..605f461 100644
--- a/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java
+++ b/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.loaders;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.geopoint.Geopoint;
@@ -18,7 +18,7 @@ public class HistoryGeocacheListLoader extends AbstractSearchLoader {
@Override
public SearchResult runSearch() {
- return cgData.getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL);
+ return DataStore.getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL);
}
}
diff --git a/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java
index adfc423..c8132e7 100644
--- a/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java
+++ b/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java
@@ -1,8 +1,10 @@
package cgeo.geocaching.loaders;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.connector.ConnectorFactory;
+import cgeo.geocaching.connector.capability.ISearchByKeyword;
import cgeo.geocaching.connector.gc.GCParser;
+import cgeo.geocaching.settings.Settings;
import android.content.Context;
@@ -17,7 +19,18 @@ public class KeywordGeocacheListLoader extends AbstractSearchLoader {
@Override
public SearchResult runSearch() {
- return GCParser.searchByKeyword(keyword, Settings.getCacheType(), Settings.isShowCaptcha(), this);
+ SearchResult searchResult = new SearchResult();
+ if (Settings.isGCConnectorActive()) {
+ searchResult = GCParser.searchByKeyword(keyword, Settings.getCacheType(), Settings.isShowCaptcha(), this);
+ }
+
+ for (ISearchByKeyword connector : ConnectorFactory.getSearchByKeywordConnectors()) {
+ if (connector.isActivated()) {
+ searchResult.addSearchResult(connector.searchByName(keyword));
+ }
+ }
+
+ return searchResult;
}
}
diff --git a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java
index ab8ba6a..5088484 100644
--- a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java
+++ b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.loaders;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.cgData;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.geopoint.Geopoint;
import android.content.Context;
@@ -20,7 +20,7 @@ public class OfflineGeocacheListLoader extends AbstractSearchLoader {
@Override
public SearchResult runSearch() {
- return cgData.getBatchOfStoredCaches(searchCenter, Settings.getCacheType(), listId);
+ return DataStore.getBatchOfStoredCaches(searchCenter, Settings.getCacheType(), listId);
}
public void setListId(int listId) {
diff --git a/main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java b/main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java
index 2229afe..dc1a5df 100644
--- a/main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java
+++ b/main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java
@@ -1,10 +1,10 @@
package cgeo.geocaching.loaders;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.settings.Settings;
import android.content.Context;
@@ -15,14 +15,14 @@ public class RemoveFromHistoryLoader extends AbstractSearchLoader {
public RemoveFromHistoryLoader(Context context, String[] selected, Geopoint coords) {
super(context);
- this.selected = selected;
+ this.selected = selected.clone();
this.coords = coords;
}
@Override
public SearchResult runSearch() {
- cgData.clearVisitDate(selected);
- return cgData.getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL);
+ DataStore.clearVisitDate(selected);
+ return DataStore.getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL);
}
}
diff --git a/main/src/cgeo/geocaching/maps/AbstractItemizedOverlay.java b/main/src/cgeo/geocaching/maps/AbstractItemizedOverlay.java
index 464c2b2..747618b 100644
--- a/main/src/cgeo/geocaching/maps/AbstractItemizedOverlay.java
+++ b/main/src/cgeo/geocaching/maps/AbstractItemizedOverlay.java
@@ -31,10 +31,6 @@ public abstract class AbstractItemizedOverlay implements GeneralOverlay {
return ovlImpl.superOnTap(index);
}
- Drawable boundCenter(Drawable markerIn) {
- return ovlImpl.superBoundCenter(markerIn);
- }
-
Drawable boundCenterBottom(Drawable markerIn) {
return ovlImpl.superBoundCenterBottom(markerIn);
}
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index 0703dd8..28e1b71 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -1,15 +1,14 @@
package cgeo.geocaching.maps;
+import cgeo.geocaching.CacheListActivity;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.DirectionProvider;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.StoredList;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
-import cgeo.geocaching.cgeocaches;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.gc.Login;
@@ -22,6 +21,7 @@ import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl;
import cgeo.geocaching.maps.interfaces.GeoPointImpl;
import cgeo.geocaching.maps.interfaces.MapActivityImpl;
@@ -40,7 +40,7 @@ import cgeo.geocaching.utils.LeastRecentlyUsedSet;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.RunnableWithArgument;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -128,7 +128,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private MapItemFactory mapItemFactory = null;
private Activity activity = null;
private MapViewImpl mapView = null;
- private cgeoapplication app = null;
+ private CgeoApplication app = null;
final private GeoDirHandler geoDirUpdate = new UpdateLoc();
private SearchResult searchIntent = null;
private String geocodeIntent = null;
@@ -359,9 +359,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
// class init
res = this.getResources();
activity = this.getActivity();
- app = (cgeoapplication) activity.getApplication();
+ app = (CgeoApplication) activity.getApplication();
- int countBubbleCnt = cgData.getAllCachesCount();
+ int countBubbleCnt = DataStore.getAllCachesCount();
caches = new LeastRecentlyUsedSet<Geocache>(MAX_CACHES + countBubbleCnt);
final MapProvider mapProvider = Settings.getMapProvider();
@@ -491,7 +491,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (!CollectionUtils.isEmpty(dirtyCaches)) {
for (String geocode : dirtyCaches) {
- Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
if (cache != null) {
// new collection type needs to remove first
caches.remove(cache);
@@ -592,7 +592,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
item = menu.findItem(R.id.menu_theme_mode); // show theme selection
item.setVisible(mapView.hasMapThemes());
- menu.findItem(R.id.menu_as_list).setEnabled(isLiveEnabled && !isLoading());
+ menu.findItem(R.id.menu_as_list).setEnabled(!isLoading());
menu.findItem(R.id.submenu_strategy).setEnabled(isLiveEnabled);
@@ -641,7 +641,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final List<String> geocodes = new ArrayList<String>();
for (final String geocode : geocodesInViewport) {
- if (!cgData.isOffline(geocode, null)) {
+ if (!DataStore.isOffline(geocode, null)) {
geocodes.add(geocode);
}
}
@@ -690,7 +690,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
selectMapTheme();
return true;
case R.id.menu_as_list: {
- cgeocaches.startActivityMap(activity, new SearchResult(getGeocodesForCachesInViewport()));
+ CacheListActivity.startActivityMap(activity, new SearchResult(getGeocodesForCachesInViewport()));
return true;
}
case R.id.menu_strategy_fastest: {
@@ -1090,7 +1090,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
SearchResult searchResult;
if (mapMode == MapMode.LIVE) {
- searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(cgData.loadStoredInViewport(viewport, Settings.getCacheType()));
+ searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(DataStore.loadStoredInViewport(viewport, Settings.getCacheType()));
} else {
// map started from another activity
searchResult = searchIntent != null ? new SearchResult(searchIntent) : new SearchResult();
@@ -1100,7 +1100,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
// live mode search result
if (isLiveEnabled) {
- searchResult.addSearchResult(cgData.loadCachedInViewport(viewport, Settings.getCacheType()));
+ searchResult.addSearchResult(DataStore.loadCachedInViewport(viewport, Settings.getCacheType()));
}
downloaded = true;
@@ -1123,7 +1123,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
|| mapMode == MapMode.COORDS) {
//All visible waypoints
CacheType type = Settings.getCacheType();
- Set<Waypoint> waypointsInViewport = cgData.loadWaypoints(viewport, excludeMine, excludeDisabled, type);
+ Set<Waypoint> waypointsInViewport = DataStore.loadWaypoints(viewport, excludeMine, excludeDisabled, type);
waypoints.addAll(waypointsInViewport);
}
else {
@@ -1196,8 +1196,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
// first remove filtered out
final Set<String> filteredCodes = searchResult.getFilteredGeocodes();
Log.d("Filtering out " + filteredCodes.size() + " caches: " + filteredCodes.toString());
- caches.removeAll(cgData.loadCaches(filteredCodes, LoadFlags.LOAD_CACHE_ONLY));
- cgData.removeCaches(filteredCodes, EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ caches.removeAll(DataStore.loadCaches(filteredCodes, LoadFlags.LOAD_CACHE_ONLY));
+ DataStore.removeCaches(filteredCodes, EnumSet.of(RemoveFlag.REMOVE_CACHE));
// new collection type needs to remove first to refresh
caches.removeAll(result);
caches.addAll(result);
@@ -1383,7 +1383,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final private CancellableHandler handler;
final private List<String> geocodes;
final private int listId;
- private long last = 0L;
public LoadDetails(final CancellableHandler handler, final List<String> geocodes, final int listId) {
this.handler = handler;
@@ -1409,26 +1408,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
break;
}
- if (!cgData.isOffline(geocode, null)) {
- if ((System.currentTimeMillis() - last) < 1500) {
- try {
- int delay = 1000 + (int) (Math.random() * 1000.0) - (int) (System.currentTimeMillis() - last);
- if (delay < 0) {
- delay = 500;
- }
-
- sleep(delay);
- } catch (InterruptedException e) {
- // nothing
- }
- }
-
- if (handler.isCancelled()) {
- Log.i("Stopped storing process.");
-
- break;
- }
-
+ if (!DataStore.isOffline(geocode, null)) {
Geocache.storeCache(null, geocode, listId, false, handler);
}
} catch (Exception e) {
@@ -1441,8 +1421,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
// FIXME: what does this yield() do here?
yield();
-
- last = System.currentTimeMillis();
}
// we're done
@@ -1512,9 +1490,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
Viewport viewport = null;
if (geocodeCenter != null) {
- viewport = cgData.getBounds(geocodeCenter);
+ viewport = DataStore.getBounds(geocodeCenter);
} else if (searchCenter != null) {
- viewport = cgData.getBounds(searchCenter.getGeocodes());
+ viewport = DataStore.getBounds(searchCenter.getGeocodes());
}
if (viewport == null) {
diff --git a/main/src/cgeo/geocaching/maps/CachesOverlay.java b/main/src/cgeo/geocaching/maps/CachesOverlay.java
index 8fbb3db..cd2ff75 100644
--- a/main/src/cgeo/geocaching/maps/CachesOverlay.java
+++ b/main/src/cgeo/geocaching/maps/CachesOverlay.java
@@ -5,7 +5,7 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.IWaypoint;
import cgeo.geocaching.R;
import cgeo.geocaching.WaypointPopup;
-import cgeo.geocaching.cgData;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.connector.gc.GCMap;
import cgeo.geocaching.enumerations.CacheType;
@@ -228,7 +228,7 @@ public class CachesOverlay extends AbstractItemizedOverlay {
final IWaypoint coordinate = item.getCoord();
if (StringUtils.isNotBlank(coordinate.getCoordType()) && coordinate.getCoordType().equalsIgnoreCase("cache") && StringUtils.isNotBlank(coordinate.getGeocode())) {
- Geocache cache = cgData.loadCache(coordinate.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB);
+ Geocache cache = DataStore.loadCache(coordinate.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB);
RequestDetailsThread requestDetailsThread = new RequestDetailsThread(cache);
if (!requestDetailsThread.requestRequired()) {
// don't show popup if we have enough details
diff --git a/main/src/cgeo/geocaching/maps/MapProviderFactory.java b/main/src/cgeo/geocaching/maps/MapProviderFactory.java
index a03fc47..2e43e19 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.CgeoApplication;
import cgeo.geocaching.maps.google.GoogleMapProvider;
import cgeo.geocaching.maps.interfaces.MapProvider;
import cgeo.geocaching.maps.interfaces.MapSource;
@@ -31,7 +31,7 @@ public class MapProviderFactory {
public static boolean isGoogleMapsInstalled() {
// Check if API key is available
- if (StringUtils.isBlank(cgeoapplication.getInstance().getString(R.string.maps_api_key))) {
+ if (StringUtils.isBlank(CgeoApplication.getInstance().getString(R.string.maps_api_key))) {
Log.w("No Google API key available.");
return false;
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java b/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java
index 1fa38ad..cb95b2c 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.CgeoApplication;
import cgeo.geocaching.maps.AbstractMapProvider;
import cgeo.geocaching.maps.AbstractMapSource;
import cgeo.geocaching.maps.interfaces.MapItemFactory;
@@ -20,7 +20,7 @@ public final class GoogleMapProvider extends AbstractMapProvider {
private final MapItemFactory mapItemFactory;
private GoogleMapProvider() {
- final Resources resources = cgeoapplication.getInstance().getResources();
+ final Resources resources = CgeoApplication.getInstance().getResources();
registerMapSource(new GoogleMapSource(this, resources.getString(R.string.map_source_google_map)));
registerMapSource(new GoogleSatelliteSource(this, resources.getString(R.string.map_source_google_satellite)));
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java
index 7c6865d..c5ef40c 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java
@@ -1,8 +1,7 @@
package cgeo.geocaching.maps.mapsforge;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.maps.AbstractMapProvider;
import cgeo.geocaching.maps.MapProviderFactory;
import cgeo.geocaching.maps.interfaces.MapItemFactory;
@@ -10,6 +9,7 @@ import cgeo.geocaching.maps.interfaces.MapProvider;
import cgeo.geocaching.maps.interfaces.MapSource;
import cgeo.geocaching.maps.mapsforge.v024.MapsforgeMapActivity024;
import cgeo.geocaching.maps.mapsforge.v024.MapsforgeMapItemFactory024;
+import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
@@ -33,7 +33,7 @@ public final class MapsforgeMapProvider extends AbstractMapProvider {
private MapItemFactory mapItemFactory = new MapsforgeMapItemFactory();
private MapsforgeMapProvider() {
- final Resources resources = cgeoapplication.getInstance().getResources();
+ final Resources resources = CgeoApplication.getInstance().getResources();
registerMapSource(new MapsforgeMapSource(MAPSFORGE_MAPNIK_ID, this, resources.getString(R.string.map_source_osm_mapnik), MapGeneratorInternal.MAPNIK));
registerMapSource(new MapsforgeMapSource(MAPSFORGE_CYCLEMAP_ID, this, resources.getString(R.string.map_source_osm_cyclemap), MapGeneratorInternal.OPENCYCLEMAP));
@@ -50,25 +50,27 @@ public final class MapsforgeMapProvider extends AbstractMapProvider {
}
public static List<String> getOfflineMaps() {
- final String mapFile = Settings.getMapFile();
- if (StringUtils.isEmpty(mapFile)) {
+ final String directoryPath = Settings.getMapFileDirectory();
+ if (StringUtils.isBlank(directoryPath)) {
return Collections.emptyList();
}
- try {
- File directory = new File(mapFile).getParentFile();
- ArrayList<String> mapFileList = new ArrayList<String>();
- for (File file : directory.listFiles()) {
- if (file.getName().endsWith(".map")) {
- if (MapsforgeMapProvider.isValidMapFile(file.getAbsolutePath())) {
- mapFileList.add(file.getAbsolutePath());
+ File directory = new File(directoryPath);
+ if (directory.isDirectory()) {
+ try {
+ ArrayList<String> mapFileList = new ArrayList<String>();
+ for (File file : directory.listFiles()) {
+ if (file.getName().endsWith(".map")) {
+ if (MapsforgeMapProvider.isValidMapFile(file.getAbsolutePath())) {
+ mapFileList.add(file.getAbsolutePath());
+ }
}
}
+ Collections.sort(mapFileList, String.CASE_INSENSITIVE_ORDER);
+ return mapFileList;
+ } catch (Exception e) {
+ Log.e("MapsforgeMapProvider.getOfflineMaps: ", e);
}
- Collections.sort(mapFileList, String.CASE_INSENSITIVE_ORDER);
- return mapFileList;
- } catch (Exception e) {
- Log.e("MapsforgeMapProvider.getOfflineMaps: ", e);
}
return Collections.emptyList();
}
@@ -163,15 +165,11 @@ public final class MapsforgeMapProvider extends AbstractMapProvider {
public void updateOfflineMaps() {
MapProviderFactory.deleteOfflineMapSources();
- final Resources resources = cgeoapplication.getInstance().getResources();
+ final Resources resources = CgeoApplication.getInstance().getResources();
final List<String> offlineMaps = getOfflineMaps();
for (String mapFile : offlineMaps) {
final String mapName = StringUtils.capitalize(StringUtils.substringBeforeLast(new File(mapFile).getName(), "."));
registerMapSource(new OfflineMapSource(mapFile, this, mapName + " (" + resources.getString(R.string.map_source_osm_offline) + ")", MapGeneratorInternal.DATABASE_RENDERER));
}
- // have a default entry, if no map files are available. otherwise we cannot select "offline" in the settings
- if (offlineMaps.isEmpty()) {
- registerMapSource(new OfflineMapSource("", this, resources.getString(R.string.map_source_osm_offline), MapGeneratorInternal.DATABASE_RENDERER));
- }
}
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
index aa11405..dc4e82c 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
@@ -1,7 +1,6 @@
package cgeo.geocaching.maps.mapsforge;
import cgeo.geocaching.R;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.maps.CachesOverlay;
import cgeo.geocaching.maps.PositionOverlay;
@@ -15,6 +14,7 @@ import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OnMapDragListener;
import cgeo.geocaching.maps.interfaces.OverlayImpl;
import cgeo.geocaching.maps.interfaces.OverlayImpl.OverlayType;
+import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
@@ -46,6 +46,9 @@ public class MapsforgeMapView extends MapView implements MapViewImpl {
public MapsforgeMapView(Context context, AttributeSet attrs) {
super(context, attrs);
gestureDetector = new GestureDetector(context, new GestureListener());
+ if (Settings.isScaleMapsforgeText()) {
+ this.setTextScale(getResources().getDisplayMetrics().density);
+ }
}
@Override
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
index a94b988..f61e523 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
@@ -31,7 +31,7 @@ public class MapsforgeOverlay extends Overlay implements OverlayImpl {
overlayBase = new ScaleOverlay(activityIn, this);
break;
default:
- throw new IllegalArgumentException();
+ throw new IllegalStateException();
}
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java
index bdaac98..8c9e0c3 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java
@@ -29,6 +29,9 @@ public class MapsforgeOverlay extends Overlay implements OverlayImpl {
break;
case ScaleOverlay:
overlayBase = new ScaleOverlay(activityIn, this);
+ break;
+ default:
+ throw new IllegalStateException();
}
}
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java
index 797e67d..0daa588 100644
--- a/main/src/cgeo/geocaching/network/HtmlImage.java
+++ b/main/src/cgeo/geocaching/network/HtmlImage.java
@@ -1,18 +1,18 @@
package cgeo.geocaching.network;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.StoredList;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.files.LocalStorage;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.utils.FileUtils;
-import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
-
+import ch.boye.httpclientandroidlib.androidextra.Base64;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import android.content.res.Resources;
@@ -27,6 +27,9 @@ import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
import java.util.Date;
public class HtmlImage implements Html.ImageGetter {
@@ -74,7 +77,7 @@ public class HtmlImage implements Html.ImageGetter {
Point displaySize = Compatibility.getDisplaySize();
this.maxWidth = displaySize.x - 25;
this.maxHeight = displaySize.y - 25;
- this.resources = cgeoapplication.getInstance().getResources();
+ this.resources = CgeoApplication.getInstance().getResources();
}
@Override
@@ -91,24 +94,45 @@ public class HtmlImage implements Html.ImageGetter {
// Download image and save it to the cache
if (imagePre == null) {
- final String absoluteURL = makeAbsoluteURL(url);
-
- if (absoluteURL != null) {
- try {
- final File file = LocalStorage.getStorageFile(pseudoGeocode, url, true, true);
- 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);
+ 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);
+ }
+ } 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);
}
- } catch (Exception e) {
- Log.e("HtmlImage.getDrawable (downloading from web)", e);
}
}
}
diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java
index 2d2ab0b..e891d3b 100644
--- a/main/src/cgeo/geocaching/network/Network.java
+++ b/main/src/cgeo/geocaching/network/Network.java
@@ -37,6 +37,7 @@ import ch.boye.httpclientandroidlib.util.EntityUtils;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.Nullable;
import org.json.JSONException;
import org.json.JSONObject;
@@ -54,8 +55,6 @@ import java.nio.charset.Charset;
public abstract class Network {
- private static final int NB_DOWNLOAD_RETRIES = 4;
-
/** User agent id */
private final static String PC_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1";
/** Native user agent, taken from a Android 2.2 Nexus **/
@@ -75,7 +74,7 @@ public abstract class Network {
static {
Network.clientParams.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, CharEncoding.UTF_8);
Network.clientParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000);
- Network.clientParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000);
+ Network.clientParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, 90000);
Network.clientParams.setParameter(ClientPNames.HANDLE_REDIRECTS, true);
}
@@ -150,6 +149,7 @@ public abstract class Network {
* @param params the parameters to add to the POST request
* @return the HTTP response, or null in case of an encoding error params
*/
+ @Nullable
public static HttpResponse postRequest(final String uri, final Parameters params) {
return request("POST", uri, params, null, null);
}
@@ -162,6 +162,7 @@ public abstract class Network {
* @params headers the headers to add to the request
* @return the HTTP response, or null in case of an encoding error params
*/
+ @Nullable
public static HttpResponse postRequest(final String uri, final Parameters params, final Parameters headers) {
return request("POST", uri, params, headers, null);
}
@@ -173,18 +174,19 @@ public abstract class Network {
* @param json the json object to add to the POST request
* @return the HTTP response, or null in case of an encoding error params
*/
+ @Nullable
public static HttpResponse postJsonRequest(final String uri, final JSONObject json) {
HttpPost request = new HttpPost(uri);
request.addHeader("Content-Type", "application/json; charset=utf-8");
if (json != null) {
try {
- request.setEntity(new StringEntity(json.toString()));
+ request.setEntity(new StringEntity(json.toString(), CharEncoding.UTF_8));
} catch (UnsupportedEncodingException e) {
Log.e("postJsonRequest:JSON Entity: UnsupportedEncodingException");
return null;
}
}
- return doRepeatedRequests(request);
+ return doLogRequest(request);
}
/**
@@ -197,6 +199,7 @@ public abstract class Network {
* @param file the file to include in the request
* @return the HTTP response, or null in case of an encoding error param
*/
+ @Nullable
public static HttpResponse postRequest(final String uri, final Parameters params,
final String fileFieldName, final String fileContentType, final File file) {
final MultipartEntity entity = new MultipartEntity();
@@ -214,7 +217,7 @@ public abstract class Network {
request.setEntity(entity);
addHeaders(request, null, null);
- return doRepeatedRequests(request);
+ return doLogRequest(request);
}
/**
@@ -232,7 +235,9 @@ public abstract class Network {
* the cache file used to cache this query
* @return the HTTP response, or null in case of an encoding error in a POST request arguments
*/
- private static HttpResponse request(final String method, final String uri, final Parameters params, final Parameters headers, final File cacheFile) {
+ @Nullable
+ private static HttpResponse request(final String method, final String uri,
+ @Nullable final Parameters params, @Nullable final Parameters headers, @Nullable final File cacheFile) {
HttpRequestBase request;
if (method.equals("GET")) {
final String fullUri = params == null ? uri : Uri.parse(uri).buildUpon().encodedQuery(params.toString()).build().toString();
@@ -251,7 +256,7 @@ public abstract class Network {
addHeaders(request, headers, cacheFile);
- return doRepeatedRequests(request);
+ return doLogRequest(request);
}
/**
@@ -263,7 +268,7 @@ public abstract class Network {
* @param cacheFile
* if non-null, the file to take ETag and If-Modified-Since information from
*/
- private static void addHeaders(final HttpRequestBase request, final Parameters headers, final File cacheFile) {
+ private static void addHeaders(final HttpRequestBase request, @Nullable final Parameters headers, @Nullable final File cacheFile) {
for (final NameValuePair header : Parameters.extend(Parameters.merge(headers, cacheHeaders(cacheFile)),
"Accept-Charset", "utf-8,iso-8859-1;q=0.8,utf-16;q=0.8,*;q=0.7",
"Accept-Language", "en-US,*;q=0.9",
@@ -275,44 +280,39 @@ public abstract class Network {
}
/**
- * Retry a request for a few times.
+ * Perform an HTTP request and log it.
*
* @param request
* the request to try
* @return
* the response, or null if there has been a failure
*/
- private static HttpResponse doRepeatedRequests(final HttpRequestBase request) {
+ @Nullable
+ private static HttpResponse doLogRequest(final HttpRequestBase request) {
final String reqLogStr = request.getMethod() + " " + Network.hidePassword(request.getURI().toString());
Log.d(reqLogStr);
final HttpClient client = Network.getHttpClient();
- for (int i = 0; i <= Network.NB_DOWNLOAD_RETRIES; i++) {
- final long before = System.currentTimeMillis();
- try {
- final HttpResponse response = client.execute(request);
- int status = response.getStatusLine().getStatusCode();
- if (status == 200) {
- Log.d(status + Network.formatTimeSpan(before) + reqLogStr);
- } else {
- Log.w(status + " [" + response.getStatusLine().getReasonPhrase() + "]" + Network.formatTimeSpan(before) + reqLogStr);
- }
- return response;
- } catch (IOException e) {
- final String timeSpan = Network.formatTimeSpan(before);
- final String tries = (i + 1) + "/" + (Network.NB_DOWNLOAD_RETRIES + 1);
- if (i == Network.NB_DOWNLOAD_RETRIES) {
- Log.w("Failure " + tries + timeSpan + reqLogStr + " (" + e.toString() + ")");
- } else {
- Log.w("Failure " + tries + " (" + e.toString() + ")" + timeSpan + "- retrying " + reqLogStr);
- }
+ final long before = System.currentTimeMillis();
+ try {
+ final HttpResponse response = client.execute(request);
+ int status = response.getStatusLine().getStatusCode();
+ if (status == 200) {
+ Log.d(status + Network.formatTimeSpan(before) + reqLogStr);
+ } else {
+ Log.w(status + " [" + response.getStatusLine().getReasonPhrase() + "]" + Network.formatTimeSpan(before) + reqLogStr);
}
+ return response;
+ } catch (final IOException e) {
+ final String timeSpan = Network.formatTimeSpan(before);
+ Log.w("Failure" + timeSpan + reqLogStr + " (" + e.toString() + ")");
}
return null;
}
- private static Parameters cacheHeaders(final File cacheFile) {
+ @Nullable
+ private static Parameters cacheHeaders(@Nullable final File cacheFile) {
if (cacheFile == null || !cacheFile.exists()) {
return null;
}
@@ -343,7 +343,8 @@ public abstract class Network {
* the name of the file storing the cached resource, or null not to use one
* @return the HTTP response
*/
- public static HttpResponse getRequest(final String uri, final Parameters params, final File cacheFile) {
+ @Nullable
+ public static HttpResponse getRequest(final String uri, @Nullable final Parameters params, @Nullable final File cacheFile) {
return request("GET", uri, params, null, cacheFile);
}
@@ -357,7 +358,8 @@ public abstract class Network {
* the parameters to add the the GET request
* @return the HTTP response
*/
- public static HttpResponse getRequest(final String uri, final Parameters params) {
+ @Nullable
+ public static HttpResponse getRequest(final String uri, @Nullable final Parameters params) {
return request("GET", uri, params, null, null);
}
@@ -372,7 +374,8 @@ public abstract class Network {
* the headers to add to the GET request
* @return the HTTP response
*/
- public static HttpResponse getRequest(final String uri, final Parameters params, final Parameters headers) {
+ @Nullable
+ public static HttpResponse getRequest(final String uri, @Nullable final Parameters params, @Nullable final Parameters headers) {
return request("GET", uri, params, headers, null);
}
@@ -383,6 +386,7 @@ public abstract class Network {
* the URI to request
* @return the HTTP response
*/
+ @Nullable
public static HttpResponse getRequest(final String uri) {
return request("GET", uri, null, null, null);
}
@@ -392,10 +396,14 @@ public abstract class Network {
return " (" + (System.currentTimeMillis() - before) + " ms) ";
}
- static public boolean isSuccess(final HttpResponse response) {
+ static public boolean isSuccess(@Nullable final HttpResponse response) {
return response != null && response.getStatusLine().getStatusCode() == 200;
}
+ static public boolean isPageNotFound(@Nullable final HttpResponse response) {
+ return response != null && response.getStatusLine().getStatusCode() == 404;
+ }
+
/**
* Get the result of a GET HTTP request returning a JSON body.
*
@@ -403,7 +411,8 @@ public abstract class Network {
* @param params the query parameters, or <code>null</code> if there are none
* @return a JSON object if the request was successful and the body could be decoded, <code>null</code> otherwise
*/
- public static JSONObject requestJSON(final String uri, final Parameters params) {
+ @Nullable
+ public static JSONObject requestJSON(final String uri, @Nullable final Parameters params) {
final HttpResponse response = request("GET", uri, params, new Parameters("Accept", "application/json, text/javascript, */*; q=0.01"), null);
final String responseData = Network.getResponseData(response, false);
if (responseData != null) {
@@ -417,6 +426,7 @@ public abstract class Network {
return null;
}
+ @Nullable
private static String getResponseDataNoError(final HttpResponse response, boolean replaceWhitespace) {
try {
String data = EntityUtils.toString(response.getEntity(), CharEncoding.UTF_8);
@@ -435,10 +445,16 @@ public abstract class Network {
* @param response a HTTP response, which can be null
* @return the body if the response comes from a successful HTTP request, <code>null</code> otherwise
*/
- public static String getResponseData(final HttpResponse response) {
+ @Nullable
+ public static String getResponseData(@Nullable final HttpResponse response) {
return Network.getResponseData(response, true);
}
+ @Nullable
+ public static String getResponseDataAlways(@Nullable final HttpResponse response) {
+ return response != null ? getResponseDataNoError(response, false) : null;
+ }
+
/**
* Get the body of a HTTP response.
*
@@ -447,17 +463,22 @@ public abstract class Network {
* should be called on the body
* @return the body if the response comes from a successful HTTP request, <code>null</code> otherwise
*/
- public static String getResponseData(final HttpResponse response, boolean replaceWhitespace) {
+ @Nullable
+ public static String getResponseData(@Nullable final HttpResponse response, boolean replaceWhitespace) {
if (!isSuccess(response)) {
return null;
}
+ assert response != null; // Caught above
return getResponseDataNoError(response, replaceWhitespace);
}
+ @Nullable
public static String rfc3986URLEncode(String text) {
- return StringUtils.replace(Network.encode(text).replace("+", "%20"), "%7E", "~");
+ final String encoded = Network.encode(text);
+ return encoded != null ? StringUtils.replace(encoded.replace("+", "%20"), "%7E", "~") : null;
}
+ @Nullable
public static String decode(final String text) {
try {
return URLDecoder.decode(text, CharEncoding.UTF_8);
@@ -467,6 +488,7 @@ public abstract class Network {
return null;
}
+ @Nullable
public static String encode(final String text) {
try {
return URLEncoder.encode(text, CharEncoding.UTF_8);
diff --git a/main/src/cgeo/geocaching/network/OAuth.java b/main/src/cgeo/geocaching/network/OAuth.java
index 6740096..c033660 100644
--- a/main/src/cgeo/geocaching/network/OAuth.java
+++ b/main/src/cgeo/geocaching/network/OAuth.java
@@ -5,6 +5,8 @@ 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;
import java.util.ArrayList;
import java.util.Date;
@@ -16,8 +18,8 @@ public class OAuth {
final String method,
final boolean https,
final Parameters params,
- final String token,
- final String tokenSecret,
+ @Nullable final String token,
+ @Nullable final String tokenSecret,
final String consumerKey,
final String consumerSecret) {
params.put(
@@ -31,11 +33,21 @@ public class OAuth {
final List<String> paramsEncoded = new ArrayList<String>();
for (final NameValuePair nameValue : params) {
- paramsEncoded.add(nameValue.getName() + "=" + Network.rfc3986URLEncode(nameValue.getValue()));
+ paramsEncoded.add(nameValue.getName() + "=" + OAuth.percentEncode(nameValue.getValue()));
}
final String keysPacked = consumerSecret + "&" + StringUtils.defaultString(tokenSecret); // both even if empty some of them!
- final String requestPacked = method + "&" + Network.rfc3986URLEncode((https ? "https" : "http") + "://" + host + path) + "&" + Network.rfc3986URLEncode(StringUtils.join(paramsEncoded.toArray(), '&'));
+ final String requestPacked = method + "&" + OAuth.percentEncode((https ? "https" : "http") + "://" + host + path) + "&" + OAuth.percentEncode(StringUtils.join(paramsEncoded.toArray(), '&'));
params.put("oauth_signature", CryptUtils.base64Encode(CryptUtils.hashHmac(requestPacked, keysPacked)));
}
+
+ /**
+ * percent encode following http://tools.ietf.org/html/rfc5849#section-3.6
+ *
+ * @param url
+ * @return
+ */
+ static String percentEncode(@NonNull String url) {
+ return StringUtils.replace(Network.rfc3986URLEncode(url), "*", "%2A");
+ }
}
diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
index 221147c..888cf77 100644
--- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
@@ -1,5 +1,7 @@
package cgeo.geocaching.network;
+import butterknife.InjectView;
+
import cgeo.geocaching.R;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.utils.Log;
@@ -11,6 +13,8 @@ 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;
+import org.eclipse.jdt.annotation.Nullable;
import android.app.ProgressDialog;
import android.content.Intent;
@@ -20,7 +24,6 @@ import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
-import android.widget.EditText;
import android.widget.TextView;
import java.io.IOException;
@@ -28,20 +31,24 @@ import java.util.regex.Pattern;
public abstract class OAuthAuthorizationActivity extends AbstractActivity {
- private String host;
- private String pathRequest;
- private String pathAuthorize;
- private String pathAccess;
- private boolean https;
- private String consumerKey;
- private String consumerSecret;
+ public static final int NOT_AUTHENTICATED = 0;
+ public static final int AUTHENTICATED = 1;
+
+ @NonNull final private String host;
+ @NonNull final private String pathRequest;
+ @NonNull final private String pathAuthorize;
+ @NonNull final private String pathAccess;
+ private final boolean https;
+ @NonNull final private String consumerKey;
+ @NonNull final private String consumerSecret;
+ @NonNull final private String callback;
private String OAtoken = null;
private String OAtokenSecret = null;
private final Pattern paramsPattern1 = Pattern.compile("oauth_token=([a-zA-Z0-9\\-\\_.]+)");
private final Pattern paramsPattern2 = Pattern.compile("oauth_token_secret=([a-zA-Z0-9\\-\\_.]+)");
- private Button startButton = null;
- private EditText pinEntry = null;
- private Button pinEntryButton = null;
+ @InjectView(R.id.start) protected Button startButton;
+ @InjectView(R.id.auth_1) protected TextView auth_1;
+ @InjectView(R.id.auth_2) protected TextView auth_2;
private ProgressDialog requestTokenDialog = null;
private ProgressDialog changeTokensDialog = null;
private Handler requestTokenHandler = new Handler() {
@@ -57,10 +64,6 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity {
if (msg.what == 1) {
startButton.setText(getAuthAgain());
-
- pinEntry.setVisibility(View.VISIBLE);
- pinEntryButton.setVisibility(View.VISIBLE);
- pinEntryButton.setOnClickListener(new ConfirmPINListener());
} else {
showToast(getErrAuthInitialize());
startButton.setText(getAuthStart());
@@ -76,33 +79,26 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity {
changeTokensDialog.dismiss();
}
- pinEntryButton.setOnClickListener(new ConfirmPINListener());
- pinEntryButton.setEnabled(true);
-
- if (msg.what == 1) {
+ if (msg.what == AUTHENTICATED) {
showToast(getAuthDialogCompleted());
-
- pinEntryButton.setVisibility(View.GONE);
-
setResult(RESULT_OK);
finish();
} else {
showToast(getErrAuthProcess());
-
- pinEntry.setVisibility(View.GONE);
- pinEntryButton.setVisibility(View.GONE);
startButton.setText(getAuthStart());
}
}
};
- public OAuthAuthorizationActivity(String host,
- String pathRequest,
- String pathAuthorize,
- String pathAccess,
- boolean https,
- String consumerKey,
- String consumerSecret) {
+ public OAuthAuthorizationActivity
+ (@NonNull String host,
+ @NonNull String pathRequest,
+ @NonNull String pathAuthorize,
+ @NonNull String pathAccess,
+ boolean https,
+ @NonNull String consumerKey,
+ @NonNull String consumerSecret,
+ @NonNull String callback) {
this.host = host;
this.pathRequest = pathRequest;
this.pathAuthorize = pathAuthorize;
@@ -110,34 +106,23 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity {
this.https = https;
this.consumerKey = consumerKey;
this.consumerSecret = consumerSecret;
+ this.callback = callback;
}
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState, R.layout.authorization_activity);
+ super.onCreate(savedInstanceState, R.layout.authorization_activity, true);
setTitle(getAuthTitle());
- init();
- }
-
- private void init() {
- startButton = (Button) findViewById(R.id.start);
- pinEntry = (EditText) findViewById(R.id.pin);
- pinEntryButton = (Button) findViewById(R.id.pin_button);
-
- TextView auth = (TextView) findViewById(R.id.auth_1);
- auth.setText(getAboutAuth1());
- auth = (TextView) findViewById(R.id.auth_2);
- auth.setText(getAboutAuth2());
+ auth_1.setText(getAuthExplainShort());
+ auth_2.setText(getAuthExplainLong());
ImmutablePair<String, String> tempToken = getTempTokens();
OAtoken = tempToken.left;
OAtokenSecret = tempToken.right;
startButton.setText(getAuthAuthorize());
- pinEntryButton.setText(getAuthFinish());
-
startButton.setEnabled(true);
startButton.setOnClickListener(new StartListener());
@@ -147,24 +132,40 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity {
} else {
// already have temporary tokens, continue from pin
startButton.setText(getAuthAgain());
+ }
+ }
+
+ @Override
+ public void onNewIntent(final Intent intent) {
+ setIntent(intent);
+ }
- pinEntry.setHint(getAuthPinHint());
- pinEntry.setVisibility(View.VISIBLE);
- pinEntryButton.setVisibility(View.VISIBLE);
- pinEntryButton.setOnClickListener(new ConfirmPINListener());
+ @Override
+ public void onResume() {
+ super.onResume();
+ final Uri uri = getIntent().getData();
+ if (uri != null) {
+ final String verifier = uri.getQueryParameter("oauth_verifier");
+ if (StringUtils.isNotBlank(verifier)) {
+ exchangeTokens(verifier);
+ } else {
+ // We can shortcut the whole verification process if we do not have a token at all.
+ changeTokensHandler.sendEmptyMessage(NOT_AUTHENTICATED);
+ }
}
}
private void requestToken() {
- int status = 0;
final Parameters params = new Parameters();
- params.put("oauth_callback", "oob");
+ params.put("oauth_callback", callback);
final String method = "GET";
OAuth.signOAuth(host, pathRequest, method, https, params, null, null, consumerKey, consumerSecret);
final String line = Network.getResponseData(Network.getRequest(getUrlPrefix() + host + pathRequest, params));
+ int status = 0;
if (StringUtils.isNotBlank(line)) {
+ assert line != null;
final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line);
if (paramsMatcher1.find()) {
OAtoken = paramsMatcher1.group(1);
@@ -193,12 +194,12 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity {
requestTokenHandler.sendEmptyMessage(status);
}
- private void changeToken() {
+ private void changeToken(final String verifier) {
- int status = 0;
+ int status = NOT_AUTHENTICATED;
try {
- final Parameters params = new Parameters("oauth_verifier", pinEntry.getText().toString());
+ final Parameters params = new Parameters("oauth_verifier", verifier);
final String method = "POST";
OAuth.signOAuth(host, pathAccess, method, https, params, OAtoken, OAtokenSecret, consumerKey, consumerSecret);
@@ -222,7 +223,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity {
setTokens(null, null, false);
} else {
setTokens(OAtoken, OAtokenSecret, true);
- status = 1;
+ status = AUTHENTICATED;
}
} catch (Exception e) {
Log.e("OAuthAuthorizationActivity.changeToken", e);
@@ -260,68 +261,64 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity {
}
}
- private class ConfirmPINListener implements View.OnClickListener {
+ private void exchangeTokens(final String verifier) {
+ if (changeTokensDialog == null) {
+ changeTokensDialog = new ProgressDialog(this);
+ changeTokensDialog.setCancelable(false);
+ changeTokensDialog.setMessage(getAuthDialogWait());
+ }
+ changeTokensDialog.show();
- @Override
- public void onClick(View arg0) {
- if (StringUtils.isEmpty(((EditText) findViewById(R.id.pin)).getText().toString())) {
- helpDialog(getAuthDialogPinTitle(), getAuthDialogPinMessage());
- return;
- }
+ (new Thread() {
- if (changeTokensDialog == null) {
- changeTokensDialog = new ProgressDialog(OAuthAuthorizationActivity.this);
- changeTokensDialog.setCancelable(false);
- changeTokensDialog.setMessage(getAuthDialogWait());
+ @Override
+ public void run() {
+ changeToken(verifier);
}
- changeTokensDialog.show();
- pinEntryButton.setEnabled(false);
- pinEntryButton.setOnTouchListener(null);
- pinEntryButton.setOnClickListener(null);
-
- (new Thread() {
-
- @Override
- public void run() {
- changeToken();
- }
- }).start();
- }
+ }).start();
}
protected abstract ImmutablePair<String, String> getTempTokens();
- protected abstract void setTempTokens(String tokenPublic, String tokenSecret);
+ protected abstract void setTempTokens(@Nullable String tokenPublic, @Nullable String tokenSecret);
- protected abstract void setTokens(String tokenPublic, String tokenSecret, boolean enable);
+ protected abstract void setTokens(@Nullable String tokenPublic, @Nullable String tokenSecret, boolean enable);
// get resources from derived class
protected abstract String getAuthTitle();
- protected abstract String getAuthAgain();
+ protected String getAuthAgain() {
+ return getString(R.string.auth_again);
+ }
- protected abstract String getErrAuthInitialize();
+ protected String getErrAuthInitialize() {
+ return getString(R.string.err_auth_initialize);
+ }
- protected abstract String getAuthStart();
+ protected String getAuthStart() {
+ return getString(R.string.auth_start);
+ }
protected abstract String getAuthDialogCompleted();
- protected abstract String getErrAuthProcess();
-
- protected abstract String getAuthDialogWait();
-
- protected abstract String getAuthDialogPinTitle();
-
- protected abstract String getAuthDialogPinMessage();
-
- protected abstract String getAboutAuth1();
+ protected String getErrAuthProcess() {
+ return res.getString(R.string.err_auth_process);
+ }
- protected abstract String getAboutAuth2();
+ protected String getAuthDialogWait() {
+ return res.getString(R.string.auth_dialog_waiting, getAuthTitle());
+ }
- protected abstract String getAuthAuthorize();
+ protected String getAuthExplainShort() {
+ return res.getString(R.string.auth_explain_short, getAuthTitle());
+ }
- protected abstract String getAuthPinHint();
+ protected String getAuthExplainLong() {
+ return res.getString(R.string.auth_explain_long, getAuthTitle());
+ }
- protected abstract String getAuthFinish();
+ protected String getAuthAuthorize() {
+ return res.getString(R.string.auth_authorize, getAuthTitle());
+ }
}
diff --git a/main/src/cgeo/geocaching/network/Parameters.java b/main/src/cgeo/geocaching/network/Parameters.java
index f035c4a..9cb0da5 100644
--- a/main/src/cgeo/geocaching/network/Parameters.java
+++ b/main/src/cgeo/geocaching/network/Parameters.java
@@ -3,8 +3,9 @@ package cgeo.geocaching.network;
import ch.boye.httpclientandroidlib.NameValuePair;
import ch.boye.httpclientandroidlib.client.utils.URLEncodedUtils;
import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
-
import org.apache.commons.lang3.CharEncoding;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import java.security.InvalidParameterException;
import java.util.ArrayList;
@@ -81,7 +82,8 @@ public class Parameters extends ArrayList<NameValuePair> {
* if the number of key/values is unbalanced
* @return the object itself if it is non-null, a new one otherwise
*/
- public static Parameters extend(final Parameters params, final String... keyValues) {
+ @NonNull
+ public static Parameters extend(@Nullable final Parameters params, final String... keyValues) {
return params == null ? new Parameters(keyValues) : params.put(keyValues);
}
@@ -94,7 +96,8 @@ public class Parameters extends ArrayList<NameValuePair> {
* the object to merge from if non-null
* @return params with extra data if params was non-null, extra otherwise
*/
- public static Parameters merge(final Parameters params, final Parameters extra) {
+ @Nullable
+ public static Parameters merge(@Nullable final Parameters params, @Nullable final Parameters extra) {
if (params == null) {
return extra;
}
diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java
index ee9bc31..cb4c7f4 100644
--- a/main/src/cgeo/geocaching/network/StatusUpdater.java
+++ b/main/src/cgeo/geocaching/network/StatusUpdater.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.network;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.utils.MemorySubject;
import cgeo.geocaching.utils.PeriodicHandler;
import cgeo.geocaching.utils.PeriodicHandler.PeriodicHandlerListener;
@@ -42,8 +42,8 @@ public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implement
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()),
+ 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")));
diff --git a/main/src/cgeo/geocaching/settings/AuthorizeTwitterPreference.java b/main/src/cgeo/geocaching/settings/AuthorizeTwitterPreference.java
deleted file mode 100644
index 1fdd0de..0000000
--- a/main/src/cgeo/geocaching/settings/AuthorizeTwitterPreference.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package cgeo.geocaching.settings;
-
-import cgeo.geocaching.R;
-import cgeo.geocaching.twitter.TwitterAuthorizationActivity;
-
-import android.content.Context;
-import android.content.Intent;
-import android.preference.Preference;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-public class AuthorizeTwitterPreference extends Preference {
-
- public AuthorizeTwitterPreference(Context context) {
- super(context);
- }
-
- public AuthorizeTwitterPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public AuthorizeTwitterPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected View onCreateView(ViewGroup parent) {
- final SettingsActivity activity = (SettingsActivity) getContext();
-
- setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- Intent authIntent = new Intent(preference.getContext(),
- TwitterAuthorizationActivity.class);
- activity.startActivityForResult(authIntent,
- R.string.pref_fakekey_twitter_authorization);
-
- return false; // no shared preference has to be changed
- }
- });
-
- activity.setTwitterAuthTitle();
- return super.onCreateView(parent);
- }
-}
diff --git a/main/src/cgeo/geocaching/settings/LogSignaturePreference.java b/main/src/cgeo/geocaching/settings/LogSignaturePreference.java
deleted file mode 100644
index d0c9739..0000000
--- a/main/src/cgeo/geocaching/settings/LogSignaturePreference.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package cgeo.geocaching.settings;
-
-import cgeo.geocaching.R;
-
-import android.content.Context;
-import android.preference.DialogPreference;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.Button;
-import android.widget.EditText;
-
-public class LogSignaturePreference extends DialogPreference {
-
- private SettingsActivity settingsActivity;
- private EditText editText;
-
- public LogSignaturePreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public LogSignaturePreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- private void init() {
- setDialogLayoutResource(R.layout.log_signature_preference_dialog);
- }
-
- @Override
- protected void onBindDialogView(View view) {
- settingsActivity = (SettingsActivity) this.getContext();
-
- editText = (EditText) view.findViewById(R.id.signature_dialog_text);
- editText.setText(getPersistedString(""));
- settingsActivity.setSignatureTextView(editText);
-
- Button templates = (Button) view.findViewById(R.id.signature_templates);
- settingsActivity.registerForContextMenu(templates);
- templates.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View templates) {
- settingsActivity.openContextMenu(templates);
- }
- });
-
- super.onBindDialogView(view);
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- if (positiveResult) {
- String text = editText.getText().toString();
- persistString(text);
- callChangeListener(text);
- }
- super.onDialogClosed(positiveResult);
- }
-}
diff --git a/main/src/cgeo/geocaching/settings/AuthorizeOcPreference.java b/main/src/cgeo/geocaching/settings/OAuthPreference.java
index f5d6a57..3550947 100644
--- a/main/src/cgeo/geocaching/settings/AuthorizeOcPreference.java
+++ b/main/src/cgeo/geocaching/settings/OAuthPreference.java
@@ -1,9 +1,10 @@
package cgeo.geocaching.settings;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.oc.OCDEAuthorizationActivity;
import cgeo.geocaching.connector.oc.OCPLAuthorizationActivity;
+import cgeo.geocaching.twitter.TwitterAuthorizationActivity;
import android.content.Context;
import android.content.Intent;
@@ -12,49 +13,50 @@ import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
-public class AuthorizeOcPreference extends Preference {
+public class OAuthPreference extends Preference {
private static final int NO_KEY = -1;
- private enum OCAuthorizations {
+ private enum OAuthActivityMapping {
NONE(NO_KEY, null),
OCDE(R.string.pref_fakekey_ocde_authorization, OCDEAuthorizationActivity.class),
- OCPL(R.string.pref_fakekey_ocpl_authorization, OCPLAuthorizationActivity.class);
+ OCPL(R.string.pref_fakekey_ocpl_authorization, OCPLAuthorizationActivity.class),
+ TWITTER(R.string.pref_fakekey_twitter_authorization, TwitterAuthorizationActivity.class);
public int prefKeyId;
public Class<?> authActivity;
- OCAuthorizations(int prefKeyId, Class<?> clazz) {
+ OAuthActivityMapping(int prefKeyId, Class<?> clazz) {
this.prefKeyId = prefKeyId;
this.authActivity = clazz;
}
}
- private final OCAuthorizations ocAuth;
+ private final OAuthActivityMapping oAuthMapping;
- private OCAuthorizations getAuthorization() {
+ private OAuthActivityMapping getAuthorization() {
final String prefKey = getKey();
- for (OCAuthorizations auth : OCAuthorizations.values()) {
- if (auth.prefKeyId != NO_KEY && prefKey.equals(cgeoapplication.getInstance().getString(auth.prefKeyId))) {
+ for (OAuthActivityMapping auth : OAuthActivityMapping.values()) {
+ if (auth.prefKeyId != NO_KEY && prefKey.equals(CgeoApplication.getInstance().getString(auth.prefKeyId))) {
return auth;
}
}
- return OCAuthorizations.NONE;
+ return OAuthActivityMapping.NONE;
}
- public AuthorizeOcPreference(Context context) {
+ public OAuthPreference(Context context) {
super(context);
- this.ocAuth = getAuthorization();
+ this.oAuthMapping = getAuthorization();
}
- public AuthorizeOcPreference(Context context, AttributeSet attrs) {
+ public OAuthPreference(Context context, AttributeSet attrs) {
super(context, attrs);
- this.ocAuth = getAuthorization();
+ this.oAuthMapping = getAuthorization();
}
- public AuthorizeOcPreference(Context context, AttributeSet attrs, int defStyle) {
+ public OAuthPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- this.ocAuth = getAuthorization();
+ this.oAuthMapping = getAuthorization();
}
@Override
@@ -64,17 +66,17 @@ public class AuthorizeOcPreference extends Preference {
setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
- if (ocAuth.authActivity != null) {
- Intent authIntent = new Intent(preference.getContext(),
- ocAuth.authActivity);
- activity.startActivityForResult(authIntent,
- ocAuth.prefKeyId);
+ if (oAuthMapping.authActivity != null) {
+ Intent authIntent = new Intent(preference.getContext(),
+ oAuthMapping.authActivity);
+ activity.startActivityForResult(authIntent,
+ oAuthMapping.prefKeyId);
}
return false; // no shared preference has to be changed
}
});
- activity.setOcAuthTitle(ocAuth.prefKeyId);
+ activity.setOcAuthTitle(oAuthMapping.prefKeyId);
return super.onCreateView(parent);
}
}
diff --git a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
index a019c4a..fbf08fa 100644
--- a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
+++ b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
@@ -99,7 +99,7 @@ public class RegisterSend2CgeoPreference extends Preference {
if (response != null && response.getStatusLine().getStatusCode() == 200) {
//response was OK
- String[] strings = Network.getResponseData(response).split(",");
+ String[] strings = StringUtils.split(Network.getResponseData(response), ',');
try {
pin = Integer.parseInt(strings[1].trim());
} catch (Exception e) {
diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java
index 3597cd0..146182a 100644
--- a/main/src/cgeo/geocaching/settings/Settings.java
+++ b/main/src/cgeo/geocaching/settings/Settings.java
@@ -1,8 +1,7 @@
package cgeo.geocaching.settings;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.StoredList;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum;
import cgeo.geocaching.connector.gc.GCConstants;
import cgeo.geocaching.connector.gc.Login;
@@ -10,6 +9,7 @@ import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.maps.MapProviderFactory;
import cgeo.geocaching.maps.google.GoogleMapProvider;
import cgeo.geocaching.maps.interfaces.GeoPointImpl;
@@ -24,6 +24,7 @@ import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.Nullable;
import android.content.Context;
import android.content.SharedPreferences;
@@ -41,7 +42,7 @@ import java.util.Locale;
/**
* General c:geo preferences/settings set by the user
*/
-public final class Settings {
+public class Settings {
public static final int SHOW_WP_THRESHOLD_DEFAULT = 10;
public static final int SHOW_WP_THRESHOLD_MAX = 50;
@@ -69,7 +70,7 @@ public final class Settings {
}
private static final SharedPreferences sharedPrefs = PreferenceManager
- .getDefaultSharedPreferences(cgeoapplication.getInstance().getBaseContext());
+ .getDefaultSharedPreferences(CgeoApplication.getInstance().getBaseContext());
static {
migrateSettings();
Log.setDebug(sharedPrefs.getBoolean(getKey(R.string.pref_debug), false));
@@ -81,8 +82,8 @@ public final class Settings {
*/
private static MapSource mapSource;
- private Settings() {
- // this class is not to be instantiated;
+ protected Settings() {
+ throw new InstantiationError();
}
private static void migrateSettings() {
@@ -90,7 +91,7 @@ public final class Settings {
int oldVersion = getInt(R.string.pref_settingsversion, 0);
if (oldVersion < 1) {
final String oldPreferencesName = "cgeo.pref";
- final SharedPreferences old = cgeoapplication.getInstance().getSharedPreferences(oldPreferencesName, Context.MODE_PRIVATE);
+ final SharedPreferences old = CgeoApplication.getInstance().getSharedPreferences(oldPreferencesName, Context.MODE_PRIVATE);
final Editor e = sharedPrefs.edit();
e.putString(getKey(R.string.pref_temp_twitter_token_secret), old.getString(getKey(R.string.pref_temp_twitter_token_secret), null));
@@ -191,7 +192,7 @@ public final class Settings {
}
private static String getKey(final int prefKeyId) {
- return cgeoapplication.getInstance().getString(prefKeyId);
+ return CgeoApplication.getInstance().getString(prefKeyId);
}
static String getString(final int prefKeyId, final String defaultValue) {
@@ -214,13 +215,13 @@ public final class Settings {
return sharedPrefs.getFloat(getKey(prefKeyId), defaultValue);
}
- static boolean putString(final int prefKeyId, final String value) {
+ protected static boolean putString(final int prefKeyId, final String value) {
final SharedPreferences.Editor edit = sharedPrefs.edit();
edit.putString(getKey(prefKeyId), value);
return edit.commit();
}
- private static boolean putBoolean(final int prefKeyId, final boolean value) {
+ protected static boolean putBoolean(final int prefKeyId, final boolean value) {
final SharedPreferences.Editor edit = sharedPrefs.edit();
edit.putBoolean(getKey(prefKeyId), value);
return edit.commit();
@@ -257,7 +258,7 @@ public final class Settings {
public static void setLanguage(boolean useEnglish) {
final Configuration config = new Configuration();
config.locale = useEnglish ? Locale.ENGLISH : Locale.getDefault();
- final Resources resources = cgeoapplication.getInstance().getResources();
+ final Resources resources = CgeoApplication.getInstance().getResources();
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
@@ -295,11 +296,7 @@ public final class Settings {
public static boolean isPremiumMember() {
// Basic Member, Premium Member, ???
- String memberStatus = Settings.getMemberStatus();
- if (memberStatus == null) {
- return false;
- }
- return GCConstants.MEMBER_STATUS_PM.equalsIgnoreCase(memberStatus);
+ return GCConstants.MEMBER_STATUS_PM.equalsIgnoreCase(Settings.getMemberStatus());
}
public static String getMemberStatus() {
@@ -317,7 +314,7 @@ public final class Settings {
return new ImmutablePair<String, String>(getString(tokenPublicPrefKey, null), getString(tokenSecretPrefKey, null));
}
- public static void setTokens(final int tokenPublicPrefKey, final String tokenPublic, final int tokenSecretPrefKey, final String tokenSecret) {
+ public static void setTokens(final int tokenPublicPrefKey, @Nullable final String tokenPublic, final int tokenSecretPrefKey, @Nullable final String tokenSecret) {
if (tokenPublic == null) {
remove(tokenPublicPrefKey);
} else {
@@ -441,6 +438,10 @@ public final class Settings {
return MapsforgeMapProvider.isValidMapFile(mapFileIn);
}
+ public static boolean isScaleMapsforgeText() {
+ return getBoolean(R.string.pref_mapsforge_scale_text, true);
+ }
+
public static CoordInputFormatEnum getCoordInputFormat() {
return CoordInputFormatEnum.fromInt(getInt(R.string.pref_coordinputformat, 0));
}
@@ -449,10 +450,6 @@ public final class Settings {
putInt(R.string.pref_coordinputformat, format.ordinal());
}
- static void setLogOffline(final boolean offline) {
- putBoolean(R.string.pref_log_offline, offline);
- }
-
public static boolean getLogOffline() {
return getBoolean(R.string.pref_log_offline, false);
}
@@ -481,11 +478,6 @@ public final class Settings {
return getBoolean(R.string.pref_excludemine, false);
}
- public static void setUseEnglish(final boolean english) {
- putBoolean(R.string.pref_useenglish, english);
- setLanguage(english);
- }
-
public static boolean isUseEnglish() {
return getBoolean(R.string.pref_useenglish, false);
}
@@ -657,7 +649,7 @@ public final class Settings {
public static void setAnyCoordinates(final Geopoint coords) {
if (null != coords) {
putFloat(R.string.pref_anylatitude, (float) coords.getLatitude());
- putFloat(R.string.pref_anylatitude, (float) coords.getLongitude());
+ putFloat(R.string.pref_anylongitude, (float) coords.getLongitude());
} else {
remove(R.string.pref_anylatitude);
remove(R.string.pref_anylongitude);
@@ -747,8 +739,8 @@ public final class Settings {
&& StringUtils.isNotBlank(getTokenSecret());
}
- public static void setTwitterTokens(final String tokenPublic,
- final String tokenSecret, boolean enableTwitter) {
+ public static void setTwitterTokens(@Nullable final String tokenPublic,
+ @Nullable final String tokenSecret, boolean enableTwitter) {
putString(R.string.pref_twitter_token_public, tokenPublic);
putString(R.string.pref_twitter_token_secret, tokenSecret);
if (tokenPublic != null) {
@@ -758,8 +750,8 @@ public final class Settings {
setUseTwitter(enableTwitter);
}
- public static void setTwitterTempTokens(final String tokenPublic,
- final String tokenSecret) {
+ public static void setTwitterTempTokens(@Nullable final String tokenPublic,
+ @Nullable final String tokenSecret) {
putString(R.string.pref_temp_twitter_token_public, tokenPublic);
putString(R.string.pref_temp_twitter_token_secret, tokenSecret);
}
@@ -796,22 +788,12 @@ public final class Settings {
String.valueOf(NavigationAppsEnum.COMPASS.id)));
}
- public static void setDefaultNavigationTool(final int defaultNavigationTool) {
- putString(R.string.pref_defaultNavigationTool,
- String.valueOf(defaultNavigationTool));
- }
-
public static int getDefaultNavigationTool2() {
return Integer.parseInt(getString(
R.string.pref_defaultNavigationTool2,
String.valueOf(NavigationAppsEnum.INTERNAL_MAP.id)));
}
- public static void setDefaultNavigationTool2(final int defaultNavigationTool) {
- putString(R.string.pref_defaultNavigationTool2,
- String.valueOf(defaultNavigationTool));
- }
-
public static Strategy getLiveMapStrategy() {
return Strategy.getById(getInt(R.string.pref_livemapstrategy, Strategy.AUTO.id));
}
@@ -924,13 +906,11 @@ public final class Settings {
}
public static String getCacheTwitterMessage() {
- // TODO make customizable from UI
- return "I found [NAME] ([URL])";
+ return getString(R.string.pref_twitter_cache_message, "I found [NAME] ([URL]).");
}
public static String getTrackableTwitterMessage() {
- // TODO make customizable from UI
- return "I touched [NAME] ([URL])!";
+ return getString(R.string.pref_twitter_trackable_message, "I touched [NAME] ([URL]).");
}
public static int getLogImageScale() {
@@ -941,11 +921,6 @@ public final class Settings {
putInt(R.string.pref_logImageScale, scale);
}
- // Only for tests!
- static void setExcludeDisabledCaches(final boolean exclude) {
- putBoolean(R.string.pref_excludedisabled, exclude);
- }
-
public static void setExcludeMine(final boolean exclude) {
putBoolean(R.string.pref_excludemine, exclude);
}
@@ -964,28 +939,47 @@ public final class Settings {
return a && b;
}
- static void setStoreOfflineMaps(final boolean offlineMaps) {
- putBoolean(R.string.pref_offlinemaps, offlineMaps);
+ public static long getFieldnoteExportDate() {
+ return getLong(R.string.pref_fieldNoteExportDate, 0);
}
- static void setStoreOfflineWpMaps(final boolean offlineWpMaps) {
- putBoolean(R.string.pref_offlinewpmaps, offlineWpMaps);
+ /**
+ * remember date of last field note export
+ *
+ * @param date
+ */
+ public static void setFieldnoteExportDate(final long date) {
+ putLong(R.string.pref_fieldNoteExportDate, date);
}
- static void setUseImperialUnits(final boolean imperial) {
- putBoolean(R.string.pref_units, imperial);
+ public static boolean isUseNavigationApp(NavigationAppsEnum navApp) {
+ return getBoolean(navApp.preferenceKey, true);
}
- public static long getFieldnoteExportDate() {
- return getLong(R.string.pref_fieldnoteExportDate, 0);
+ /**
+ * remember the state of the "Upload" checkbox in the field notes export dialog
+ *
+ * @param upload
+ */
+ public static void setFieldNoteExportUpload(boolean upload) {
+ putBoolean(R.string.pref_fieldNoteExportUpload, upload);
}
- public static void setFieldnoteExportDate(final long date) {
- putLong(R.string.pref_fieldnoteExportDate, date);
+ public static boolean getFieldNoteExportUpload() {
+ return getBoolean(R.string.pref_fieldNoteExportUpload, true);
}
- public static boolean isUseNavigationApp(NavigationAppsEnum navApp) {
- return getBoolean(navApp.preferenceKey, true);
+ /**
+ * remember the state of the "Only new" checkbox in the field notes export dialog
+ *
+ * @param onlyNew
+ */
+ public static void setFieldNoteExportOnlyNew(boolean onlyNew) {
+ putBoolean(R.string.pref_fieldNoteExportOnlyNew, onlyNew);
+ }
+
+ public static boolean getFieldNoteExportOnlyNew() {
+ return getBoolean(R.string.pref_fieldNoteExportOnlyNew, false);
}
}
diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java
index 90b6145..7b3f7fa 100644
--- a/main/src/cgeo/geocaching/settings/SettingsActivity.java
+++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.settings;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Intents;
import cgeo.geocaching.R;
import cgeo.geocaching.SelectMapfileActivity;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum;
@@ -15,8 +15,6 @@ import cgeo.geocaching.maps.MapProviderFactory;
import cgeo.geocaching.maps.interfaces.MapSource;
import cgeo.geocaching.utils.DatabaseBackupUtils;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.LogTemplateProvider;
-import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate;
import org.apache.commons.lang3.StringUtils;
import org.openintents.intents.FileManagerIntents;
@@ -34,17 +32,10 @@ import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.MenuItem;
-import android.view.MenuItem.OnMenuItemClickListener;
-import android.view.View;
import android.widget.BaseAdapter;
-import android.widget.EditText;
import android.widget.ListAdapter;
import java.io.File;
-import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -64,8 +55,6 @@ public class SettingsActivity extends PreferenceActivity {
private static final String INTENT_GOTO = "GOTO";
private static final int INTENT_GOTO_SERVICES = 1;
- private EditText signatureText;
-
/**
* Enumeration for directory choosers. This is how we can retrieve information about the
* directory and preference key in onActivityResult() easily just by knowing
@@ -73,18 +62,20 @@ public class SettingsActivity extends PreferenceActivity {
*/
private enum DirChooserType {
GPX_IMPORT_DIR(1, R.string.pref_gpxImportDir,
- Environment.getExternalStorageDirectory().getPath() + "/gpx"),
+ Environment.getExternalStorageDirectory().getPath() + "/gpx", false),
GPX_EXPORT_DIR(2, R.string.pref_gpxExportDir,
- Environment.getExternalStorageDirectory().getPath() + "/gpx"),
- THEMES_DIR(3, R.string.pref_renderthemepath, "");
+ Environment.getExternalStorageDirectory().getPath() + "/gpx", true),
+ THEMES_DIR(3, R.string.pref_renderthemepath, "", false);
public final int requestCode;
public final int keyId;
public final String defaultValue;
+ public final boolean writeMode;
- DirChooserType(final int requestCode, final int keyId, final String defaultValue) {
+ DirChooserType(final int requestCode, final int keyId, final String defaultValue, final boolean writeMode) {
this.requestCode = requestCode;
this.keyId = keyId;
this.defaultValue = defaultValue;
+ this.writeMode = writeMode;
}
}
@@ -102,8 +93,10 @@ public class SettingsActivity extends PreferenceActivity {
if (gotoPage == INTENT_GOTO_SERVICES) {
// start with services screen
PreferenceScreen main = (PreferenceScreen) getPreference(R.string.pref_fakekey_main_screen);
- int index = getPreference(R.string.pref_fakekey_services_screen).getOrder();
- main.onItemClick(null, null, index, 0);
+ if (main != null) {
+ int index = getPreference(R.string.pref_fakekey_services_screen).getOrder();
+ main.onItemClick(null, null, index, 0);
+ }
}
}
@@ -131,7 +124,7 @@ public class SettingsActivity extends PreferenceActivity {
R.string.pref_gpxExportDir, R.string.pref_gpxImportDir,
R.string.pref_mapDirectory, R.string.pref_defaultNavigationTool,
R.string.pref_defaultNavigationTool2, R.string.pref_webDeviceName,
- R.string.pref_fakekey_preference_backup_info, }) {
+ R.string.pref_fakekey_preference_backup_info, R.string.pref_twitter_cache_message, R.string.pref_twitter_trackable_message }) {
bindSummaryToStringValue(k);
}
getPreference(R.string.pref_units).setDefaultValue(Settings.getImperialUnitsDefault());
@@ -171,51 +164,13 @@ public class SettingsActivity extends PreferenceActivity {
}
private static String getKey(final int prefKeyId) {
- return cgeoapplication.getInstance().getString(prefKeyId);
+ return CgeoApplication.getInstance().getString(prefKeyId);
}
private Preference getPreference(final int keyId) {
return SettingsActivity.findPreference(this, getKey(keyId));
}
- // workaround, because OnContextItemSelected nor onMenuItemSelected is never called
- OnMenuItemClickListener TEMPLATE_CLICK = new OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(final MenuItem item) {
- LogTemplate template = LogTemplateProvider.getTemplate(item.getItemId());
- if (template != null) {
- insertSignatureTemplate(template);
- return true;
- }
- return false;
- }
- };
-
- // workaround, because OnContextItemSelected and onMenuItemSelected are never called
- void setSignatureTextView(final EditText view) {
- this.signatureText = view;
- }
-
- @Override
- public void onCreateContextMenu(final ContextMenu menu, final View v,
- final ContextMenuInfo menuInfo) {
- // context menu for signature templates
- if (v.getId() == R.id.signature_templates) {
- menu.setHeaderTitle(R.string.init_signature_template_button);
- ArrayList<LogTemplate> templates = LogTemplateProvider.getTemplates();
- for (int i = 0; i < templates.size(); ++i) {
- menu.add(0, templates.get(i).getItemId(), 0, templates.get(i).getResourceId());
- menu.getItem(i).setOnMenuItemClickListener(TEMPLATE_CLICK);
- }
- }
- super.onCreateContextMenu(menu, v, menuInfo);
- }
-
- private void insertSignatureTemplate(final LogTemplate template) {
- String insertText = "[" + template.getTemplateString() + "]";
- ActivityMixin.insertAtPosition(signatureText, insertText, true);
- }
-
/**
* Fill the choice list for map sources.
*/
@@ -306,6 +261,7 @@ public class SettingsActivity extends PreferenceActivity {
// OI file manager not available
final Intent dirChooser = new Intent(this, SimpleDirChooser.class);
dirChooser.putExtra(Intents.EXTRA_START_DIR, startDirectory);
+ dirChooser.putExtra(SimpleDirChooser.EXTRA_CHOOSE_FOR_WRITING, dct.writeMode);
startActivityForResult(dirChooser, dct.requestCode);
}
}
@@ -354,7 +310,7 @@ public class SettingsActivity extends PreferenceActivity {
@Override
public boolean onPreferenceClick(final Preference preference) {
boolean oldValue = Settings.isDbOnSDCard();
- ((cgeoapplication) SettingsActivity.this.getApplication())
+ ((CgeoApplication) SettingsActivity.this.getApplication())
.moveDatabase(SettingsActivity.this);
return oldValue != Settings.isDbOnSDCard();
}
@@ -407,6 +363,9 @@ public class SettingsActivity extends PreferenceActivity {
case R.string.pref_fakekey_ocpl_authorization:
setOCPLAuthTitle();
break;
+ case R.string.pref_fakekey_twitter_authorization:
+ setTwitterAuthTitle();
+ break;
default:
Log.e(String.format(Locale.ENGLISH, "Invalid key %d in SettingsActivity.setTitle()", prefKeyId));
}
@@ -415,22 +374,22 @@ public class SettingsActivity extends PreferenceActivity {
void setOCDEAuthTitle() {
getPreference(R.string.pref_fakekey_ocde_authorization)
.setTitle(getString(Settings.hasOCAuthorization(R.string.pref_ocde_tokenpublic, R.string.pref_ocde_tokensecret)
- ? R.string.init_reregister_oc_de
- : R.string.init_register_oc_de));
+ ? R.string.settings_reauthorize
+ : R.string.settings_authorize));
}
void setOCPLAuthTitle() {
getPreference(R.string.pref_fakekey_ocpl_authorization)
.setTitle(getString(Settings.hasOCAuthorization(R.string.pref_ocpl_tokenpublic, R.string.pref_ocpl_tokensecret)
- ? R.string.init_reregister_oc_pl
- : R.string.init_register_oc_pl));
+ ? R.string.settings_reauthorize
+ : R.string.settings_authorize));
}
void setTwitterAuthTitle() {
getPreference(R.string.pref_fakekey_twitter_authorization)
.setTitle(getString(Settings.hasTwitterAuthorization()
- ? R.string.init_twitter_reauthorize
- : R.string.init_twitter_authorize));
+ ? R.string.settings_reauthorize
+ : R.string.settings_authorize));
}
public static void jumpToServicesPage(final Context fromActivity) {
@@ -457,14 +416,25 @@ public class SettingsActivity extends PreferenceActivity {
case R.string.pref_mapDirectory:
if (data.hasExtra(Intents.EXTRA_MAP_FILE)) {
final String mapFile = data.getStringExtra(Intents.EXTRA_MAP_FILE);
- Settings.setMapFile(mapFile);
- if (!Settings.isValidMapFile(Settings.getMapFile())) {
- ActivityMixin.showToast(this, R.string.warn_invalid_mapfile);
+ File file = new File(mapFile);
+ if (!file.isDirectory()) {
+ Settings.setMapFile(mapFile);
+ if (!Settings.isValidMapFile(Settings.getMapFile())) {
+ ActivityMixin.showToast(this, R.string.warn_invalid_mapfile);
+ } else {
+ // Ensure map source preference is updated accordingly.
+ // TODO: There should be a better way to find and select the map source for a map file
+ Integer mapSourceId = mapFile.hashCode();
+ ListPreference mapSource = (ListPreference) getPreference(R.string.pref_mapsource);
+ mapSource.setValue(mapSourceId.toString());
+ VALUE_CHANGE_LISTENER.onPreferenceChange(mapSource, mapSourceId);
+ }
+ } else {
+ Settings.setMapFileDirectory(mapFile);
}
}
initMapSourcePreference();
- getPreference(R.string.pref_mapDirectory).setSummary(
- Settings.getMapFileDirectory());
+ getPreference(R.string.pref_mapDirectory).setSummary(StringUtils.defaultString(Settings.getMapFileDirectory()));
break;
case R.string.pref_fakekey_ocde_authorization:
setOCDEAuthTitle();
@@ -523,7 +493,7 @@ public class SettingsActivity extends PreferenceActivity {
preference.setSummary(mapSource.getName());
} else if (isPreference(preference, R.string.pref_connectorOCActive) || isPreference(preference, R.string.pref_connectorOCPLActive) || isPreference(preference, R.string.pref_connectorGCActive)) {
// // reset log-in status if connector activation was changed
- cgeoapplication.getInstance().checkLogin = true;
+ CgeoApplication.getInstance().checkLogin = true;
} else if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
@@ -554,7 +524,7 @@ public class SettingsActivity extends PreferenceActivity {
if (Login.isActualLoginStatus()) {
Login.logout();
}
- cgeoapplication.getInstance().checkLogin = true;
+ CgeoApplication.getInstance().checkLogin = true;
}
return true;
}
diff --git a/main/src/cgeo/geocaching/settings/TemplateTextPreference.java b/main/src/cgeo/geocaching/settings/TemplateTextPreference.java
new file mode 100644
index 0000000..9eaaa67
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/TemplateTextPreference.java
@@ -0,0 +1,111 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.utils.LogTemplateProvider;
+import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.TypedArray;
+import android.preference.DialogPreference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+import java.util.ArrayList;
+
+public class TemplateTextPreference extends DialogPreference {
+
+ /**
+ * default value, if none is given in the preference XML.
+ */
+ private static final String DEFAULT_VALUE = StringUtils.EMPTY;
+ private SettingsActivity settingsActivity;
+ private EditText editText;
+ private String initialValue;
+
+ public TemplateTextPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public TemplateTextPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ setDialogLayoutResource(R.layout.template_preference_dialog);
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ settingsActivity = (SettingsActivity) this.getContext();
+
+ editText = (EditText) view.findViewById(R.id.signature_dialog_text);
+ editText.setText(getPersistedString(initialValue != null ? initialValue.toString() : StringUtils.EMPTY));
+
+ Button button = (Button) view.findViewById(R.id.signature_templates);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View button) {
+ AlertDialog.Builder alert = new AlertDialog.Builder(TemplateTextPreference.this.getContext());
+ alert.setTitle(R.string.init_signature_template_button);
+ final ArrayList<LogTemplate> templates = LogTemplateProvider.getTemplates();
+ String[] items = new String[templates.size()];
+ for (int i = 0; i < templates.size(); i++) {
+ items[i] = settingsActivity.getResources().getString(templates.get(i).getResourceId());
+ }
+ alert.setItems(items, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int position) {
+ dialog.dismiss();
+ final LogTemplate template = templates.get(position);
+ insertSignatureTemplate(template);
+ }
+ });
+ alert.create().show();
+ }
+ });
+
+ super.onBindDialogView(view);
+ }
+
+ private void insertSignatureTemplate(final LogTemplate template) {
+ String insertText = "[" + template.getTemplateString() + "]";
+ ActivityMixin.insertAtPosition(editText, insertText, true);
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ if (positiveResult) {
+ String text = editText.getText().toString();
+ persistString(text);
+ callChangeListener(text);
+ }
+ super.onDialogClosed(positiveResult);
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
+ if (restorePersistedValue) {
+ // Restore existing state
+ initialValue = this.getPersistedString(DEFAULT_VALUE);
+ } else {
+ // Set default state from the XML attribute
+ initialValue = defaultValue.toString();
+ persistString(initialValue);
+ }
+ }
+
+ @Override
+ protected Object onGetDefaultValue(TypedArray array, int index) {
+ return array.getString(index);
+ }
+}
diff --git a/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java b/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
index 3cdd393..99a535a 100644
--- a/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
+++ b/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
@@ -47,6 +47,7 @@ public class ComparatorUserInterface {
register(R.string.caches_sort_inventory, InventoryComparator.class);
register(R.string.caches_sort_name, NameComparator.class);
register(R.string.caches_sort_favorites, PopularityComparator.class);
+ register(R.string.caches_sort_favorites_ratio, PopularityRatioComparator.class);
register(R.string.caches_sort_rating, RatingComparator.class);
register(R.string.caches_sort_size, SizeComparator.class);
register(R.string.caches_sort_state, StateComparator.class);
diff --git a/main/src/cgeo/geocaching/sorting/DateComparator.java b/main/src/cgeo/geocaching/sorting/DateComparator.java
index 3464103..091f6a4 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.CgeoApplication;
import java.util.ArrayList;
import java.util.Date;
@@ -27,7 +27,7 @@ public class DateComparator extends AbstractCacheComparator {
final ArrayList<Geocache> list = new ArrayList<Geocache>();
list.add(cache1);
list.add(cache2);
- final DistanceComparator distanceComparator = new DistanceComparator(cgeoapplication.getInstance().currentGeo().getCoords(), list);
+ final DistanceComparator distanceComparator = new DistanceComparator(CgeoApplication.getInstance().currentGeo().getCoords(), list);
return distanceComparator.compare(cache1, cache2);
}
return dateDifference;
diff --git a/main/src/cgeo/geocaching/sorting/FindsComparator.java b/main/src/cgeo/geocaching/sorting/FindsComparator.java
index ba929b8..b147fad 100644
--- a/main/src/cgeo/geocaching/sorting/FindsComparator.java
+++ b/main/src/cgeo/geocaching/sorting/FindsComparator.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.sorting;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.enumerations.LogType;
public class FindsComparator extends AbstractCacheComparator {
@@ -20,7 +20,7 @@ public class FindsComparator extends AbstractCacheComparator {
private static int getFindsCount(Geocache cache) {
if (cache.getLogCounts().isEmpty()) {
- cache.setLogCounts(cgData.loadLogCounts(cache.getGeocode()));
+ cache.setLogCounts(DataStore.loadLogCounts(cache.getGeocode()));
}
Integer logged = cache.getLogCounts().get(LogType.FOUND_IT);
if (logged != null) {
diff --git a/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java b/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java
new file mode 100644
index 0000000..fab7bb1
--- /dev/null
+++ b/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java
@@ -0,0 +1,56 @@
+/**
+ *
+ */
+package cgeo.geocaching.sorting;
+
+import cgeo.geocaching.DataStore;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.enumerations.LogType;
+
+/**
+ * sorts caches by popularity ratio (favorites per find in %).
+ * only caches with 10 finds and more are counted to obtain meaningful statistics
+ */
+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;
+ float ratio2 = 0.0f;
+
+ int finds1 = getFindsCount(cache1);
+ int finds2 = getFindsCount(cache2);
+
+ if (finds1 != 0 && finds1 > 9) {
+ ratio1 = (((float) cache1.getFavoritePoints()) / ((float) finds1));
+ }
+ if (finds2 != 0 && finds2 > 9) {
+ ratio2 = (((float) cache2.getFavoritePoints()) / ((float) finds2));
+ }
+
+ if ((ratio2 - ratio1) > 0.0f) {
+ return 1;
+ } else if ((ratio2 - ratio1) < 0.0f) {
+ return -1;
+ }
+
+ return 0;
+ }
+
+ private static int getFindsCount(Geocache cache) {
+ if (cache.getLogCounts().isEmpty()) {
+ cache.setLogCounts(DataStore.loadLogCounts(cache.getGeocode()));
+ }
+ Integer logged = cache.getLogCounts().get(LogType.FOUND_IT);
+ if (logged != null) {
+ return logged;
+ }
+ return 0;
+ }
+}
diff --git a/main/src/cgeo/geocaching/speech/SpeechService.java b/main/src/cgeo/geocaching/speech/SpeechService.java
index 1907bfc..2a72bbf 100644
--- a/main/src/cgeo/geocaching/speech/SpeechService.java
+++ b/main/src/cgeo/geocaching/speech/SpeechService.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.speech;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.DirectionProvider;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.settings.Settings;
@@ -48,7 +48,7 @@ public class SpeechService extends Service implements OnInitListener {
GeoDirHandler geoHandler = new GeoDirHandler() {
@Override
protected void updateDirection(float newDirection) {
- if (cgeoapplication.getInstance().currentGeo().getSpeed() <= 5) {
+ if (CgeoApplication.getInstance().currentGeo().getSpeed() <= 5) {
direction = DirectionProvider.getDirectionNow(startingActivity, newDirection);
directionInitialized = true;
updateCompass();
@@ -177,7 +177,7 @@ public class SpeechService extends Service implements OnInitListener {
if (intent != null) {
target = intent.getParcelableExtra(EXTRA_TARGET_COORDS);
}
- return START_NOT_STICKY;
+ return START_NOT_STICKY; // service can be stopped by system, if under memory pressure
}
private void speak(final String text) {
diff --git a/main/src/cgeo/geocaching/speech/TextFactory.java b/main/src/cgeo/geocaching/speech/TextFactory.java
index 81a74fb..2a3b6d7 100644
--- a/main/src/cgeo/geocaching/speech/TextFactory.java
+++ b/main/src/cgeo/geocaching/speech/TextFactory.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.speech;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.IConversion;
import cgeo.geocaching.utils.AngleUtils;
@@ -12,6 +12,13 @@ import java.util.Locale;
/**
* Creates the output to be read by TTS.
*
+ * Note: some languages need to read "one hour" as "a hour" (indefinite article). Also, other languages
+ * use the <tt>quantity="1"</tt> plurals rule for other values than 1, such as Slovenian, so it is not
+ * possible to store the literal value to use for 1 in this rule. For this reason, we need to have one
+ * string for the unit quantity ("one meter") and a plurals rule for everything else.
+ *
+ * See http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html for rules
+ * on unit expressions.
*/
public class TextFactory {
public static String getText(Geopoint position, Geopoint target, float direction) {
@@ -78,11 +85,11 @@ public class TextFactory {
}
private static String getString(int resourceId, Object... formatArgs) {
- return cgeoapplication.getInstance().getString(resourceId, formatArgs);
+ return CgeoApplication.getInstance().getString(resourceId, formatArgs);
}
private static String getQuantityString(int resourceId, int quantity, Object... formatArgs) {
- return cgeoapplication.getInstance().getResources().getQuantityString(resourceId, quantity, formatArgs);
+ return CgeoApplication.getInstance().getResources().getQuantityString(resourceId, quantity, formatArgs);
}
private static String getDirection(Geopoint position, Geopoint target, float direction) {
diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java
index 7233764..7213789 100644
--- a/main/src/cgeo/geocaching/twitter/Twitter.java
+++ b/main/src/cgeo/geocaching/twitter/Twitter.java
@@ -1,9 +1,10 @@
package cgeo.geocaching.twitter;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.LogEntry;
import cgeo.geocaching.Trackable;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter.Format;
@@ -12,31 +13,42 @@ import cgeo.geocaching.network.OAuth;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
+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;
public final class Twitter {
private static final String HASH_PREFIX_WITH_BLANK = " #";
private static final int MAX_TWEET_SIZE = 140;
- public static void postTweetCache(String geocode) {
- final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
- postTweet(cgeoapplication.getInstance(), getStatusMessage(cache), null);
+ public static void postTweetCache(String geocode, final @Nullable LogEntry logEntry) {
+ final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ if (cache == null) {
+ return;
+ }
+ postTweet(CgeoApplication.getInstance(), getStatusMessage(cache, logEntry), null);
}
- public static void postTweetTrackable(String geocode) {
- final Trackable trackable = cgData.loadTrackable(geocode);
- postTweet(cgeoapplication.getInstance(), getStatusMessage(trackable), null);
+ public static void postTweetTrackable(String geocode, final @Nullable LogEntry logEntry) {
+ final Trackable trackable = DataStore.loadTrackable(geocode);
+ if (trackable == null) {
+ return;
+ }
+ postTweet(CgeoApplication.getInstance(), getStatusMessage(trackable, logEntry), null);
}
- private static void postTweet(final cgeoapplication app, final String status, final Geopoint coords) {
+ private static void postTweet(final CgeoApplication app, final String statusIn, final Geopoint coords) {
if (app == null || !Settings.isUseTwitter() || !Settings.isTwitterLoginValid()) {
return;
}
try {
+ final String status = shortenToMaxSize(statusIn);
Parameters parameters = new Parameters("status", status);
if (coords != null) {
parameters.put(
@@ -61,38 +73,33 @@ public final class Twitter {
}
}
+ private static String shortenToMaxSize(final String status) {
+ String result = StringUtils.trim(status);
+ if (StringUtils.length(result) > MAX_TWEET_SIZE) {
+ return StringUtils.substring(result, 0, MAX_TWEET_SIZE - 1) + 'โ€ฆ';
+ }
+ return result;
+ }
+
private static void appendHashTag(final StringBuilder status, final String tag) {
if (status.length() + HASH_PREFIX_WITH_BLANK.length() + tag.length() <= MAX_TWEET_SIZE) {
final String tagWithPrefix = HASH_PREFIX_WITH_BLANK + tag;
- if (status.indexOf(tagWithPrefix, 0) == -1) {
+ if (!StringUtils.contains(status, tagWithPrefix)) {
status.append(tagWithPrefix);
}
}
}
- static String getStatusMessage(Geocache cache) {
- String name = cache.getName();
- if (name.length() > 100) {
- name = name.substring(0, 100) + 'โ€ฆ';
- }
- final String url = StringUtils.defaultString(cache.getUrl());
- return fillTemplate(Settings.getCacheTwitterMessage(), name, url);
+ static String getStatusMessage(final @NonNull Geocache cache, final @Nullable LogEntry logEntry) {
+ return appendHashTags(LogTemplateProvider.applyTemplates(Settings.getCacheTwitterMessage(), new LogContext(cache, logEntry)));
}
- static String getStatusMessage(Trackable trackable) {
- String name = trackable.getName();
- if (name.length() > 82) {
- name = name.substring(0, 81) + 'โ€ฆ';
- }
- String url = StringUtils.defaultString(trackable.getUrl());
- String status = Settings.getTrackableTwitterMessage();
- return fillTemplate(status, name, url);
+ static String getStatusMessage(final @NonNull Trackable trackable, final @Nullable LogEntry logEntry) {
+ return appendHashTags(LogTemplateProvider.applyTemplates(Settings.getTrackableTwitterMessage(), new LogContext(trackable, logEntry)));
}
- private static String fillTemplate(String template, String name, final String url) {
- String result = StringUtils.replace(template, "[NAME]", name);
- result = StringUtils.replace(result, "[URL]", url);
- StringBuilder builder = new StringBuilder(result);
+ private static String appendHashTags(final String status) {
+ StringBuilder builder = new StringBuilder(status);
appendHashTag(builder, "cgeo");
appendHashTag(builder, "geocaching");
return builder.toString();
diff --git a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java
index 4d9a1f2..b813389 100644
--- a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java
@@ -1,10 +1,11 @@
package cgeo.geocaching.twitter;
import cgeo.geocaching.R;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.network.OAuthAuthorizationActivity;
+import cgeo.geocaching.settings.Settings;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.Nullable;
public class TwitterAuthorizationActivity extends OAuthAuthorizationActivity {
@@ -15,92 +16,33 @@ public class TwitterAuthorizationActivity extends OAuthAuthorizationActivity {
"/oauth/access_token",
true,
Settings.getKeyConsumerPublic(),
- Settings.getKeyConsumerSecret());
+ Settings.getKeyConsumerSecret(),
+ "callback://www.cgeo.org/twitter/");
}
@Override
- protected ImmutablePair<String, String> getTempTokens() {
+ protected final ImmutablePair<String, String> getTempTokens() {
return Settings.getTempToken();
}
@Override
- protected void setTempTokens(String tokenPublic, String tokenSecret) {
+ protected final void setTempTokens(@Nullable final String tokenPublic, @Nullable final String tokenSecret) {
Settings.setTwitterTempTokens(tokenPublic, tokenSecret);
}
@Override
- protected void setTokens(String tokenPublic, String tokenSecret, boolean enable) {
+ protected final void setTokens(@Nullable final String tokenPublic, @Nullable final String tokenSecret, final boolean enable) {
Settings.setTwitterTokens(tokenPublic, tokenSecret, enable);
}
@Override
- protected String getAuthTitle() {
+ protected final String getAuthTitle() {
return res.getString(R.string.auth_twitter);
}
@Override
- protected String getAuthAgain() {
- return res.getString(R.string.auth_again);
- }
-
- @Override
- protected String getErrAuthInitialize() {
- return res.getString(R.string.err_auth_initialize);
- }
-
- @Override
- protected String getAuthStart() {
- return res.getString(R.string.auth_start);
- }
-
- @Override
- protected String getAuthDialogCompleted() {
- return res.getString(R.string.auth_dialog_completed);
- }
-
- @Override
- protected String getErrAuthProcess() {
- return res.getString(R.string.err_auth_process);
- }
-
- @Override
- protected String getAuthDialogWait() {
- return res.getString(R.string.auth_dialog_wait);
- }
-
- @Override
- protected String getAuthDialogPinTitle() {
- return res.getString(R.string.auth_dialog_pin_title);
- }
-
- @Override
- protected String getAuthDialogPinMessage() {
- return res.getString(R.string.auth_dialog_pin_message);
- }
-
- @Override
- protected String getAboutAuth1() {
- return res.getString(R.string.about_auth_1);
- }
-
- @Override
- protected String getAboutAuth2() {
- return res.getString(R.string.about_auth_2);
- }
-
- @Override
- protected String getAuthAuthorize() {
- return res.getString(R.string.auth_authorize);
- }
-
- @Override
- protected String getAuthPinHint() {
- return res.getString(R.string.auth_pin_hint);
- }
-
- @Override
- protected String getAuthFinish() {
- return res.getString(R.string.auth_finish);
+ protected final String getAuthDialogCompleted() {
+ return res.getString(R.string.auth_dialog_completed_twitter);
}
}
diff --git a/main/src/cgeo/geocaching/ui/AbstractUIFactory.java b/main/src/cgeo/geocaching/ui/AbstractUIFactory.java
index 2351383..0d447f2 100644
--- a/main/src/cgeo/geocaching/ui/AbstractUIFactory.java
+++ b/main/src/cgeo/geocaching/ui/AbstractUIFactory.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.ui;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import android.content.res.Resources;
public class AbstractUIFactory {
- protected final static Resources res = cgeoapplication.getInstance().getResources();
+ protected final static Resources res = CgeoApplication.getInstance().getResources();
}
diff --git a/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java b/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java
index b717568..f8cfb8a 100644
--- a/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java
+++ b/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.ui;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeocaches;
+import cgeo.geocaching.CacheListActivity;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.network.Network;
@@ -53,10 +53,10 @@ abstract class AbstractUserClickListener implements View.OnClickListener {
public void onClick(DialogInterface dialog, int item) {
switch (item) {
case 0:
- cgeocaches.startActivityOwner(context, name.toString());
+ CacheListActivity.startActivityOwner(context, name.toString());
return;
case 1:
- cgeocaches.startActivityUserName(context, name.toString());
+ CacheListActivity.startActivityUserName(context, name.toString());
return;
case 2:
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(name.toString()))));
diff --git a/main/src/cgeo/geocaching/ui/AddressListAdapter.java b/main/src/cgeo/geocaching/ui/AddressListAdapter.java
index 736c036..0d5fba7 100644
--- a/main/src/cgeo/geocaching/ui/AddressListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/AddressListAdapter.java
@@ -2,9 +2,9 @@ package cgeo.geocaching.ui;
import butterknife.InjectView;
+import cgeo.geocaching.CacheListActivity;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
-import cgeo.geocaching.cgeocaches;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Units;
@@ -38,7 +38,7 @@ public class AddressListAdapter extends ArrayAdapter<Address> {
public AddressListAdapter(final Context context) {
super(context, 0);
inflater = ((Activity) context).getLayoutInflater();
- location = cgeoapplication.getInstance().currentGeo().getCoords();
+ location = CgeoApplication.getInstance().currentGeo().getCoords();
}
@Override
@@ -61,7 +61,7 @@ public class AddressListAdapter extends ArrayAdapter<Address> {
@Override
public void onClick(final View v) {
final Activity activity = (Activity) v.getContext();
- cgeocaches.startActivityAddress(activity, new Geopoint(address.getLatitude(), address.getLongitude()), StringUtils.defaultString(address.getAddressLine(0)));
+ CacheListActivity.startActivityAddress(activity, new Geopoint(address.getLatitude(), address.getLongitude()), StringUtils.defaultString(address.getAddressLine(0)));
activity.finish();
}
});
diff --git a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
index 9059a6b..5db562e 100644
--- a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
+++ b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
@@ -1,16 +1,18 @@
package cgeo.geocaching.ui;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Units;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import android.app.Activity;
import android.content.res.Resources;
+import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -134,7 +136,7 @@ public final class CacheDetailsCreator {
public void addDistance(final Geocache cache, final TextView cacheDistanceView) {
Float distance = null;
if (cache.getCoords() != null) {
- final Geopoint currentCoords = cgeoapplication.getInstance().currentGeo().getCoords();
+ final Geopoint currentCoords = CgeoApplication.getInstance().currentGeo().getCoords();
if (currentCoords != null) {
distance = currentCoords.distanceTo(cache);
}
@@ -159,7 +161,7 @@ public final class CacheDetailsCreator {
public void addDistance(final Waypoint wpt, final TextView waypointDistanceView) {
Float distance = null;
if (wpt.getCoords() != null) {
- final Geopoint currentCoords = cgeoapplication.getInstance().currentGeo().getCoords();
+ final Geopoint currentCoords = CgeoApplication.getInstance().currentGeo().getCoords();
if (currentCoords != null) {
distance = currentCoords.distanceTo(wpt);
}
@@ -175,4 +177,14 @@ public final class CacheDetailsCreator {
}
add(R.string.cache_distance, text);
}
+
+ public void addEventDate(@NonNull Geocache cache) {
+ if (cache.isEventCache() && cache.getHiddenDate() != null) {
+ final long time = cache.getHiddenDate().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);
+ }
+ }
+ }
}
diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
index c6aeaa6..56cc60a 100644
--- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
@@ -3,10 +3,10 @@ package cgeo.geocaching.ui;
import butterknife.InjectView;
import cgeo.geocaching.CacheDetailActivity;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheListType;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.filter.IFilter;
@@ -18,9 +18,10 @@ import cgeo.geocaching.sorting.EventDateComparator;
import cgeo.geocaching.sorting.InverseComparator;
import cgeo.geocaching.sorting.VisitComparator;
import cgeo.geocaching.utils.AngleUtils;
+import cgeo.geocaching.utils.DateUtils;
import cgeo.geocaching.utils.Log;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -112,7 +113,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
public CacheListAdapter(final Activity activity, final List<Geocache> list, CacheListType cacheListType) {
super(activity, 0, list);
- final IGeoData currentGeo = cgeoapplication.getInstance().currentGeo();
+ final IGeoData currentGeo = CgeoApplication.getInstance().currentGeo();
if (currentGeo != null) {
coords = currentGeo.getCoords();
}
@@ -328,7 +329,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
}
public void setActualHeading(final float direction) {
- if (Math.abs(AngleUtils.difference(azimuth, direction)) < 10) {
+ if (Math.abs(AngleUtils.difference(azimuth, direction)) < 5) {
return;
}
@@ -399,7 +400,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
}
Spannable spannable = null;
- if (cache.isDisabled() || cache.isArchived()) { // strike
+ if (cache.isDisabled() || cache.isArchived() || isPastEvent(cache)) { // strike
spannable = Spannable.Factory.getInstance().newSpannable(cache.getName());
spannable.setSpan(new StrikethroughSpan(), 0, spannable.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
@@ -488,6 +489,10 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
return v;
}
+ private static boolean isPastEvent(final Geocache cache) {
+ return cache.isEventCache() && DateUtils.daysSince(cache.getHiddenDate().getTime()) > 0;
+ }
+
private static Drawable getCacheIcon(Geocache cache) {
int hashCode = getIconHashCode(cache.getType(), cache.hasUserModifiedCoords() || cache.hasFinalDefined());
final Drawable drawable = gcIconDrawables.get(hashCode);
@@ -517,6 +522,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
@Override
public void onClick(View view) {
+ assert view instanceof CheckBox;
final boolean checkNow = ((CheckBox) view).isChecked();
cache.setStatusChecked(checkNow);
}
diff --git a/main/src/cgeo/geocaching/ui/CompassMiniView.java b/main/src/cgeo/geocaching/ui/CompassMiniView.java
index 92280dc..260c990 100644
--- a/main/src/cgeo/geocaching/ui/CompassMiniView.java
+++ b/main/src/cgeo/geocaching/ui/CompassMiniView.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.ui;
import cgeo.geocaching.R;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.AngleUtils;
import android.content.Context;
@@ -49,7 +49,6 @@ final public class CompassMiniView extends View {
*/
private static final int ARROW_BITMAP_SIZE = 21;
private static final PaintFlagsDrawFilter FILTER_SET = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG);
- private static final PaintFlagsDrawFilter FILTER_REMOVE = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0);
private static final float MINIMUM_ROTATION_DEGREES_FOR_REPAINT = 5;
public CompassMiniView(Context context) {
@@ -84,6 +83,7 @@ final public class CompassMiniView extends View {
@Override
public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
instances--;
if (instances == 0) {
if (compassArrow != null) {
@@ -144,19 +144,15 @@ final public class CompassMiniView extends View {
lastDrawingAzimuth = azimuthRelative;
// compass margins
- canvas.setDrawFilter(FILTER_SET);
-
final int canvasCenterX = getWidth() / 2;
final int canvasCenterY = getHeight() / 2;
final int marginLeft = (getWidth() - compassArrowWidth) / 2;
final int marginTop = (getHeight() - compassArrowHeight) / 2;
+ canvas.setDrawFilter(FILTER_SET);
canvas.rotate(-azimuthRelative, canvasCenterX, canvasCenterY);
canvas.drawBitmap(compassArrow, marginLeft, marginTop, null);
- canvas.rotate(azimuthRelative, canvasCenterX, canvasCenterY);
-
- canvas.setDrawFilter(FILTER_REMOVE);
}
private float calculateAzimuthRelative() {
diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java
index b73a2a9..3b4ed36 100644
--- a/main/src/cgeo/geocaching/ui/CompassView.java
+++ b/main/src/cgeo/geocaching/ui/CompassView.java
@@ -87,6 +87,7 @@ public class CompassView extends View implements PeriodicHandlerListener {
@Override
public void onDetachedFromWindow() {
redrawHandler.stop();
+ super.onDetachedFromWindow();
if (compassUnderlay != null) {
compassUnderlay.recycle();
diff --git a/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java b/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java
index afadb33..299256c 100644
--- a/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java
+++ b/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java
@@ -9,7 +9,7 @@ import android.widget.TextView;
/**
* view click listener to automatically switch different coordinate formats
- *
+ *
*/
public class CoordinatesFormatSwitcher implements OnClickListener {
@@ -29,6 +29,7 @@ public class CoordinatesFormatSwitcher implements OnClickListener {
@Override
public void onClick(View view) {
+ assert view instanceof TextView;
position = (position + 1) % availableFormats.length;
TextView textView = (TextView) view;
// rotate coordinate formats on click
diff --git a/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java b/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java
index 56c7f2f..e2e587e 100644
--- a/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java
+++ b/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java
@@ -2,34 +2,36 @@ package cgeo.geocaching.ui;
import cgeo.geocaching.utils.CryptUtils;
+import org.eclipse.jdt.annotation.NonNull;
+
import android.text.Spannable;
import android.view.View;
import android.widget.TextView;
public class DecryptTextClickListener implements View.OnClickListener {
- @Override
- public void onClick(View view) {
- if (view == null) {
- return;
- }
+ @NonNull private final TextView targetView;
- try {
- final TextView logView = (TextView) view;
+ public DecryptTextClickListener(@NonNull final TextView targetView) {
+ this.targetView = targetView;
+ }
+ @Override
+ public final void onClick(final View view) {
+ try {
// do not run the click listener if a link was clicked
- if (logView.getSelectionStart() != -1 || logView.getSelectionEnd() != -1) {
+ if (targetView.getSelectionStart() != -1 || targetView.getSelectionEnd() != -1) {
return;
}
- CharSequence text = logView.getText();
+ CharSequence text = targetView.getText();
if (text instanceof Spannable) {
Spannable span = (Spannable) text;
- logView.setText(CryptUtils.rot13(span));
+ targetView.setText(CryptUtils.rot13(span));
}
else {
String string = (String) text;
- logView.setText(CryptUtils.rot13(string));
+ targetView.setText(CryptUtils.rot13(string));
}
} catch (RuntimeException e) {
// nothing
diff --git a/main/src/cgeo/geocaching/ui/DirectionImage.java b/main/src/cgeo/geocaching/ui/DirectionImage.java
index 9de360c..cd7695e 100644
--- a/main/src/cgeo/geocaching/ui/DirectionImage.java
+++ b/main/src/cgeo/geocaching/ui/DirectionImage.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.ui;
-import cgeo.geocaching.StoredList;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.HtmlImage;
import org.apache.commons.lang3.StringUtils;
diff --git a/main/src/cgeo/geocaching/ui/Formatter.java b/main/src/cgeo/geocaching/ui/Formatter.java
index ecae9ea..49c7a50 100644
--- a/main/src/cgeo/geocaching/ui/Formatter.java
+++ b/main/src/cgeo/geocaching/ui/Formatter.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.ui;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheListType;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.WaypointType;
@@ -22,7 +22,7 @@ public abstract class Formatter {
/** Text separator used for formatting texts */
public static final String SEPARATOR = " ยท ";
- private static final Context context = cgeoapplication.getInstance().getBaseContext();
+ private static final Context context = CgeoApplication.getInstance().getBaseContext();
/**
* Generate a time string according to system-wide settings (locale, 12/24 hour)
@@ -87,9 +87,9 @@ public abstract class Formatter {
int diff = cgeo.geocaching.utils.DateUtils.daysSince(date);
switch (diff) {
case 0:
- return cgeoapplication.getInstance().getString(R.string.log_today);
+ return CgeoApplication.getInstance().getString(R.string.log_today);
case 1:
- return cgeoapplication.getInstance().getString(R.string.log_yesterday);
+ return CgeoApplication.getInstance().getString(R.string.log_yesterday);
default:
return formatShortDate(date);
}
@@ -107,6 +107,18 @@ public abstract class Formatter {
return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL);
}
+ /**
+ * Generate a numeric date and time string according to system-wide settings (locale,
+ * date format) such as "7 september at 12:35".
+ *
+ * @param date
+ * milliseconds since the epoch
+ * @return the formatted string
+ */
+ public static String formatDateTime(long date) {
+ return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME);
+ }
+
public static String formatCacheInfoLong(Geocache cache, CacheListType cacheListType) {
final ArrayList<String> infos = new ArrayList<String>();
if (StringUtils.isNotBlank(cache.getGeocode())) {
@@ -116,10 +128,10 @@ public abstract class Formatter {
addShortInfos(cache, infos);
if (cache.isPremiumMembersOnly()) {
- infos.add(cgeoapplication.getInstance().getString(R.string.cache_premium));
+ infos.add(CgeoApplication.getInstance().getString(R.string.cache_premium));
}
if (cacheListType != CacheListType.OFFLINE && cacheListType != CacheListType.HISTORY && cache.getListId() > 0) {
- infos.add(cgeoapplication.getInstance().getString(R.string.cache_offline));
+ infos.add(CgeoApplication.getInstance().getString(R.string.cache_offline));
}
return StringUtils.join(infos, Formatter.SEPARATOR);
}
@@ -161,7 +173,7 @@ public abstract class Formatter {
infos.add(waypointType.getL10n());
}
if (Waypoint.PREFIX_OWN.equalsIgnoreCase(waypoint.getPrefix())) {
- infos.add(cgeoapplication.getInstance().getString(R.string.waypoint_custom));
+ infos.add(CgeoApplication.getInstance().getString(R.string.waypoint_custom));
} else {
if (StringUtils.isNotBlank(waypoint.getPrefix())) {
infos.add(waypoint.getPrefix());
diff --git a/main/src/cgeo/geocaching/ui/ImagesList.java b/main/src/cgeo/geocaching/ui/ImagesList.java
index 0f860c4..4eaf06d 100644
--- a/main/src/cgeo/geocaching/ui/ImagesList.java
+++ b/main/src/cgeo/geocaching/ui/ImagesList.java
@@ -2,12 +2,12 @@ package cgeo.geocaching.ui;
import cgeo.geocaching.Image;
import cgeo.geocaching.R;
-import cgeo.geocaching.StoredList;
import cgeo.geocaching.files.LocalStorage;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.HtmlImage;
-import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.Log;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
@@ -156,6 +156,7 @@ public class ImagesList {
}
public void onCreateContextMenu(ContextMenu menu, View v) {
+ assert v instanceof ImageView;
activity.getMenuInflater().inflate(R.menu.images_list_context, menu);
final Resources res = activity.getResources();
menu.setHeaderTitle(res.getString(R.string.cache_image));
diff --git a/main/src/cgeo/geocaching/ui/LoggingUI.java b/main/src/cgeo/geocaching/ui/LoggingUI.java
index c2e2d24..30c719e 100644
--- a/main/src/cgeo/geocaching/ui/LoggingUI.java
+++ b/main/src/cgeo/geocaching/ui/LoggingUI.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.ui;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.settings.Settings;
@@ -74,7 +74,7 @@ public class LoggingUI extends AbstractUIFactory {
}
private static void showOfflineMenu(final Geocache cache, final Activity activity) {
- final LogEntry currentLog = cgData.loadLogOffline(cache.getGeocode());
+ final LogEntry currentLog = DataStore.loadLogOffline(cache.getGeocode());
final LogType currentLogType = currentLog == null ? null : currentLog.type;
final List<LogType> logTypes = cache.getPossibleLogTypes();
@@ -105,6 +105,8 @@ public class LoggingUI extends AbstractUIFactory {
case CLEAR_LOG:
cache.clearOfflineLog();
break;
+ default:
+ throw new IllegalStateException();
}
} else {
cache.logOffline(activity, logTypeEntry.logType);
diff --git a/main/src/cgeo/geocaching/ui/UserNameClickListener.java b/main/src/cgeo/geocaching/ui/UserNameClickListener.java
new file mode 100644
index 0000000..190dfde
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/UserNameClickListener.java
@@ -0,0 +1,18 @@
+package cgeo.geocaching.ui;
+
+import android.view.View;
+
+public class UserNameClickListener extends AbstractUserClickListener {
+
+ final private String name;
+
+ public UserNameClickListener(final String name) {
+ super(true);
+ this.name = name;
+ }
+
+ @Override
+ protected CharSequence getUserName(final View view) {
+ return name;
+ }
+}
diff --git a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
index 91ce7e3..00d4c1a 100644
--- a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
@@ -3,13 +3,13 @@ package cgeo.geocaching.ui.dialog;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.R;
-import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.settings.Settings.CoordInputFormatEnum;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.settings.Settings.CoordInputFormatEnum;
import org.apache.commons.lang3.StringUtils;
@@ -216,6 +216,8 @@ public class CoordinatesInputDialog extends NoTitleDialog {
eLonSec.setText(addZeros(gp.getLonSec(), 2));
eLonSub.setText(addZeros(gp.getLonSecFrac(), 3));
break;
+ default:
+ throw new IllegalStateException();
}
}
@@ -227,6 +229,7 @@ public class CoordinatesInputDialog extends NoTitleDialog {
@Override
public void onClick(View view) {
+ assert view instanceof Button;
final Button button = (Button) view;
final CharSequence text = button.getText();
if (StringUtils.isBlank(text)) {
diff --git a/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java b/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java
index 2c4f38d..6ad59ec 100644
--- a/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java
+++ b/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.ui.dialog;
import cgeo.geocaching.R;
import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import android.app.Activity;
import android.app.AlertDialog;
@@ -33,7 +33,7 @@ public class LiveMapInfoDialogBuilder {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
- cgeoapplication.getInstance().setLiveMapHintShown();
+ CgeoApplication.getInstance().setLiveMapHintShown();
if (checkBoxHide.getVisibility() == View.VISIBLE && checkBoxHide.isChecked()) {
Settings.setHideLiveHint(true);
}
diff --git a/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java
index 8da711e..8fe3866 100644
--- a/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java
+++ b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java
@@ -4,7 +4,7 @@ import cgeo.geocaching.CacheDetailActivity;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.ui.UserActionsClickListener;
@@ -23,7 +23,7 @@ import java.util.Map.Entry;
public class CacheLogsViewCreator extends LogsViewCreator {
private final boolean allLogs;
- private final Resources res = cgeoapplication.getInstance().getResources();
+ private final Resources res = CgeoApplication.getInstance().getResources();
public CacheLogsViewCreator(CacheDetailActivity cacheDetailActivity, boolean allLogs) {
super(cacheDetailActivity);
diff --git a/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java
index ee2713a..15634d3 100644
--- a/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java
+++ b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java
@@ -4,9 +4,9 @@ import cgeo.geocaching.Image;
import cgeo.geocaching.ImagesActivity;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
-import cgeo.geocaching.StoredList;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.Progress;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.ui.AbstractCachingPageViewCreator;
import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
@@ -129,7 +129,7 @@ public abstract class LogsViewCreator extends AbstractCachingPageViewCreator<Lis
if (null == convertView) {
holder.author.setOnClickListener(createUserActionsListener());
holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
- holder.text.setOnClickListener(new DecryptTextClickListener());
+ holder.text.setOnClickListener(new DecryptTextClickListener(holder.text));
activity.registerForContextMenu(holder.text);
}
}
diff --git a/main/src/cgeo/geocaching/utils/ApplicationSettings.java b/main/src/cgeo/geocaching/utils/ApplicationSettings.java
index 99d3142..78fa4f6 100644
--- a/main/src/cgeo/geocaching/utils/ApplicationSettings.java
+++ b/main/src/cgeo/geocaching/utils/ApplicationSettings.java
@@ -17,7 +17,7 @@ public class ApplicationSettings {
*/
public static String getPreferencesName() {
// There is currently no Android API to get the file name of the shared preferences. Let's hardcode
- // it without needing a cgeoapplication instance.
+ // it without needing a CgeoApplication instance.
return "cgeo.geocaching_preferences";
}
diff --git a/main/src/cgeo/geocaching/utils/CancellableHandler.java b/main/src/cgeo/geocaching/utils/CancellableHandler.java
index 8cf8f28..cb4b9db 100644
--- a/main/src/cgeo/geocaching/utils/CancellableHandler.java
+++ b/main/src/cgeo/geocaching/utils/CancellableHandler.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.utils;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import android.os.Handler;
import android.os.Message;
@@ -114,7 +114,7 @@ public abstract class CancellableHandler extends Handler {
public static void sendLoadProgressDetail(final Handler handler, final int resourceId) {
if (null != handler) {
- handler.obtainMessage(UPDATE_LOAD_PROGRESS_DETAIL, cgeoapplication.getInstance().getString(resourceId)).sendToTarget();
+ handler.obtainMessage(UPDATE_LOAD_PROGRESS_DETAIL, CgeoApplication.getInstance().getString(resourceId)).sendToTarget();
}
}
}
diff --git a/main/src/cgeo/geocaching/utils/ClipboardUtils.java b/main/src/cgeo/geocaching/utils/ClipboardUtils.java
index 67069b2..77250f3 100644
--- a/main/src/cgeo/geocaching/utils/ClipboardUtils.java
+++ b/main/src/cgeo/geocaching/utils/ClipboardUtils.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.utils;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import android.content.Context;
@@ -24,7 +24,7 @@ public final class ClipboardUtils {
*/
public static void copyToClipboard(final CharSequence text) {
// fully qualified name used here to avoid buggy deprecation warning (of javac) on the import statement
- final android.text.ClipboardManager clipboard = (android.text.ClipboardManager) cgeoapplication.getInstance().getSystemService(Context.CLIPBOARD_SERVICE);
+ final android.text.ClipboardManager clipboard = (android.text.ClipboardManager) CgeoApplication.getInstance().getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
}
diff --git a/main/src/cgeo/geocaching/utils/CryptUtils.java b/main/src/cgeo/geocaching/utils/CryptUtils.java
index d98585a..5273fa5 100644
--- a/main/src/cgeo/geocaching/utils/CryptUtils.java
+++ b/main/src/cgeo/geocaching/utils/CryptUtils.java
@@ -95,20 +95,6 @@ public final class CryptUtils {
return StringUtils.EMPTY;
}
- public static String sha1(String text) {
- try {
- final MessageDigest digest = MessageDigest.getInstance("SHA-1");
- digest.update(text.getBytes(CharEncoding.UTF_8), 0, text.length());
- return new BigInteger(1, digest.digest()).toString(16);
- } catch (NoSuchAlgorithmException e) {
- Log.e("CryptUtils.sha1", e);
- } catch (UnsupportedEncodingException e) {
- Log.e("CryptUtils.sha1", e);
- }
-
- return StringUtils.EMPTY;
- }
-
public static byte[] hashHmac(String text, String salt) {
byte[] macBytes = {};
diff --git a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java
index 8aa605f..b291a8a 100644
--- a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java
+++ b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.utils;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.MainActivity;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.ui.Formatter;
@@ -12,8 +12,6 @@ import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.res.Resources;
-import android.os.Handler;
-import android.os.Message;
import java.io.File;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -34,34 +32,31 @@ public class DatabaseBackupUtils {
final Resources res = activity.getResources();
final ProgressDialog dialog = ProgressDialog.show(activity, res.getString(R.string.init_backup_restore), res.getString(R.string.init_restore_running), true, false);
final AtomicBoolean restoreSuccessful = new AtomicBoolean(false);
- Thread restoreThread = new Thread() {
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- dialog.dismiss();
- boolean restored = restoreSuccessful.get();
- String message = restored ? res.getString(R.string.init_restore_success) : res.getString(R.string.init_restore_failed);
- ActivityMixin.helpDialog(activity, res.getString(R.string.init_backup_restore), message);
- if (activity instanceof MainActivity) {
- ((MainActivity) activity).updateCacheCounter();
- }
- }
- };
-
+ new Thread() {
@Override
public void run() {
- restoreSuccessful.set(cgData.restoreDatabaseInternal());
- handler.sendMessage(handler.obtainMessage());
+ restoreSuccessful.set(DataStore.restoreDatabaseInternal());
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ dialog.dismiss();
+ boolean restored = restoreSuccessful.get();
+ String message = restored ? res.getString(R.string.init_restore_success) : res.getString(R.string.init_restore_failed);
+ ActivityMixin.helpDialog(activity, res.getString(R.string.init_backup_restore), message);
+ if (activity instanceof MainActivity) {
+ ((MainActivity) activity).updateCacheCounter();
+ }
+ }
+ });
}
- };
- restoreThread.start();
+ }.start();
}
public static boolean createBackup(final Activity activity, final Runnable runAfterwards) {
final Context context = activity;
// avoid overwriting an existing backup with an empty database
// (can happen directly after reinstalling the app)
- if (cgData.getAllCachesCount() == 0) {
+ if (DataStore.getAllCachesCount() == 0) {
ActivityMixin.helpDialog(activity,
context.getString(R.string.init_backup),
context.getString(R.string.init_backup_unnecessary));
@@ -74,7 +69,7 @@ public class DatabaseBackupUtils {
new Thread() {
@Override
public void run() {
- final String backupFileName = cgData.backupDatabaseInternal();
+ final String backupFileName = DataStore.backupDatabaseInternal();
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
@@ -96,7 +91,7 @@ public class DatabaseBackupUtils {
}
public static File getRestoreFile() {
- final File fileSourceFile = cgData.getBackupFileInternal();
+ final File fileSourceFile = DataStore.getBackupFileInternal();
return fileSourceFile.exists() && fileSourceFile.length() > 0 ? fileSourceFile : null;
}
diff --git a/main/src/cgeo/geocaching/utils/GeoDirHandler.java b/main/src/cgeo/geocaching/utils/GeoDirHandler.java
index a143730..c85648b 100644
--- a/main/src/cgeo/geocaching/utils/GeoDirHandler.java
+++ b/main/src/cgeo/geocaching/utils/GeoDirHandler.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.utils;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.IGeoData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.settings.Settings;
import android.os.Handler;
@@ -29,7 +29,7 @@ public abstract class GeoDirHandler extends Handler implements IObserver<Object>
private static final int STOP_GEO = 1 << 4;
private static final int STOP_DIR = 1 << 5;
- private static final cgeoapplication app = cgeoapplication.getInstance();
+ private static final CgeoApplication app = CgeoApplication.getInstance();
@Override
final public void handleMessage(final Message message) {
diff --git a/main/src/cgeo/geocaching/utils/HtmlUtils.java b/main/src/cgeo/geocaching/utils/HtmlUtils.java
index 5717a37..37e20ec 100644
--- a/main/src/cgeo/geocaching/utils/HtmlUtils.java
+++ b/main/src/cgeo/geocaching/utils/HtmlUtils.java
@@ -3,6 +3,7 @@ package cgeo.geocaching.utils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
+import android.text.Html;
import android.text.Spanned;
import android.text.style.ImageSpan;
@@ -56,7 +57,7 @@ public final class HtmlUtils {
}
}
- // some line breaks are still in the text, source is unknown
- return StringUtils.replace(result, "<br />", "\n").trim();
+ // now that images are gone, do a normal html to text conversion
+ return Html.fromHtml(result).toString().trim();
}
}
diff --git a/main/src/cgeo/geocaching/utils/IOUtils.java b/main/src/cgeo/geocaching/utils/IOUtils.java
deleted file mode 100644
index df90da3..0000000
--- a/main/src/cgeo/geocaching/utils/IOUtils.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package cgeo.geocaching.utils;
-
-import java.io.Closeable;
-import java.io.IOException;
-
-final public class IOUtils {
-
- private IOUtils() {
- // utility class
- }
-
- public static void closeQuietly(final Closeable closeable) {
- if (closeable != null) {
- try {
- closeable.close();
- } catch (final IOException e) {
- Log.w("closeQuietly: unable to close " + closeable, e);
- }
- }
- }
-
-}
diff --git a/main/src/cgeo/geocaching/utils/ImageUtils.java b/main/src/cgeo/geocaching/utils/ImageUtils.java
index 34bfa1c..ea4498b 100644
--- a/main/src/cgeo/geocaching/utils/ImageUtils.java
+++ b/main/src/cgeo/geocaching/utils/ImageUtils.java
@@ -1,8 +1,11 @@
package cgeo.geocaching.utils;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.compatibility.Compatibility;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
@@ -46,7 +49,7 @@ public final class ImageUtils {
* @return BitmapDrawable The scaled image
*/
public static BitmapDrawable scaleBitmapTo(final Bitmap image, final int maxWidth, final int maxHeight) {
- final cgeoapplication app = cgeoapplication.getInstance();
+ final CgeoApplication app = CgeoApplication.getInstance();
Bitmap result = image;
int width = image.getWidth();
int height = image.getHeight();
@@ -94,9 +97,10 @@ public final class ImageUtils {
* Image to read
* @param maxXY
* boundings
- * @return String filename and path, NULL if something fails
+ * @return filename and path, <tt>null</tt> if something fails
*/
- public static String readScaleAndWriteImage(final String filePath, final int maxXY) {
+ @Nullable
+ public static String readScaleAndWriteImage(@NonNull final String filePath, final int maxXY) {
if (maxXY <= 0) {
return filePath;
}
@@ -117,12 +121,22 @@ public final class ImageUtils {
return null;
}
final BitmapDrawable scaledImage = scaleBitmapTo(image, maxXY, maxXY);
- final String uploadFilename = ImageUtils.getOutputImageFile().getPath();
+ final File tempImageFile = ImageUtils.getOutputImageFile();
+ if (tempImageFile == null) {
+ Log.e("ImageUtils.readScaleAndWriteImage: unable to write scaled image");
+ return null;
+ }
+ final String uploadFilename = tempImageFile.getPath();
storeBitmap(scaledImage.getBitmap(), Bitmap.CompressFormat.JPEG, 75, uploadFilename);
return uploadFilename;
}
- /** Create a File for saving an image or video */
+ /** Create a File for saving an image or video
+ *
+ * @return the temporary image file to use, or <tt>null</tt> if the media directory could
+ * not be created.
+ * */
+ @Nullable
public static File getOutputImageFile() {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
@@ -134,6 +148,7 @@ public final class ImageUtils {
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!FileUtils.mkdirs(mediaStorageDir)) {
+ Log.e("ImageUtils.getOutputImageFile: cannot create media storage directory");
return null;
}
}
@@ -143,6 +158,7 @@ public final class ImageUtils {
return new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
}
+ @Nullable
public static Uri getOutputImageFileUri() {
final File file = getOutputImageFile();
if (file == null) {
diff --git a/main/src/cgeo/geocaching/utils/Log.java b/main/src/cgeo/geocaching/utils/Log.java
index 1ade2f9..8f96f10 100644
--- a/main/src/cgeo/geocaching/utils/Log.java
+++ b/main/src/cgeo/geocaching/utils/Log.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.utils;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.CharEncoding;
import android.os.Environment;
diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
index 98201b5..76fa0f7 100644
--- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
+++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.utils;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
import cgeo.geocaching.Trackable;
import cgeo.geocaching.connector.ConnectorFactory;
@@ -35,22 +36,25 @@ public final class LogTemplateProvider {
private Geocache cache;
private Trackable trackable;
private boolean offline = false;
+ private LogEntry logEntry;
- public LogContext(final Geocache cache) {
- this(cache, false);
+ public LogContext(final Geocache cache, LogEntry logEntry) {
+ this(cache, logEntry, false);
}
- public LogContext(final Trackable trackable) {
+ public LogContext(final Trackable trackable, final LogEntry logEntry) {
this.trackable = trackable;
+ this.logEntry = logEntry;
}
public LogContext(final boolean offline) {
- this(null, offline);
+ this(null, null, offline);
}
- public LogContext(final Geocache cache, final boolean offline) {
+ public LogContext(final Geocache cache, LogEntry logEntry, final boolean offline) {
this.cache = cache;
this.offline = offline;
+ this.logEntry = logEntry;
}
public final Geocache getCache() {
@@ -64,6 +68,10 @@ public final class LogTemplateProvider {
public final boolean isOffline() {
return offline;
}
+
+ public final LogEntry getLogEntry() {
+ return logEntry;
+ }
}
public abstract static class LogTemplate {
@@ -178,6 +186,45 @@ public final class LogTemplateProvider {
return StringUtils.EMPTY;
}
});
+ templates.add(new LogTemplate("NAME", R.string.init_signature_template_name) {
+ @Override
+ public String getValue(LogContext context) {
+ Trackable trackable = context.getTrackable();
+ if (trackable != null) {
+ return trackable.getName();
+ }
+ Geocache cache = context.getCache();
+ if (cache != null) {
+ return cache.getName();
+ }
+ return StringUtils.EMPTY;
+ }
+ });
+ templates.add(new LogTemplate("URL", R.string.init_signature_template_url) {
+
+ @Override
+ public String getValue(LogContext context) {
+ Trackable trackable = context.getTrackable();
+ if (trackable != null) {
+ return trackable.getUrl();
+ }
+ Geocache cache = context.getCache();
+ if (cache != null) {
+ return cache.getUrl();
+ }
+ return StringUtils.EMPTY;
+ }
+ });
+ templates.add(new LogTemplate("LOG", R.string.init_signature_template_log) {
+ @Override
+ public String getValue(LogContext context) {
+ LogEntry logEntry = context.getLogEntry();
+ if (logEntry != null) {
+ return logEntry.getDisplayText();
+ }
+ return StringUtils.EMPTY;
+ }
+ });
return templates;
}
diff --git a/main/src/cgeo/geocaching/utils/ProcessUtils.java b/main/src/cgeo/geocaching/utils/ProcessUtils.java
index 3345ff1..d80674b 100644
--- a/main/src/cgeo/geocaching/utils/ProcessUtils.java
+++ b/main/src/cgeo/geocaching/utils/ProcessUtils.java
@@ -1,13 +1,14 @@
package cgeo.geocaching.utils;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.net.Uri;
import java.util.List;
@@ -43,7 +44,7 @@ public final class ProcessUtils {
* This will find installed applications even without launch intent (e.g. the streetview plugin).
*/
private static boolean hasPackageInstalled(final String packageName) {
- final List<PackageInfo> packs = cgeoapplication.getInstance().getPackageManager().getInstalledPackages(0);
+ final List<PackageInfo> packs = CgeoApplication.getInstance().getPackageManager().getInstalledPackages(0);
for (final PackageInfo packageInfo : packs) {
if (packageName.equals(packageInfo.packageName)) {
return true;
@@ -59,7 +60,7 @@ public final class ProcessUtils {
if (packageName == null) {
return null;
}
- final PackageManager packageManager = cgeoapplication.getInstance().getPackageManager();
+ final PackageManager packageManager = CgeoApplication.getInstance().getPackageManager();
try {
// This can throw an exception where the exception type is only defined on API Level > 3
// therefore surround with try-catch
@@ -70,10 +71,34 @@ public final class ProcessUtils {
}
public static boolean isIntentAvailable(final String intent) {
- final PackageManager packageManager = cgeoapplication.getInstance().getPackageManager();
- final List<ResolveInfo> list = packageManager.queryIntentActivities(
- new Intent(intent), PackageManager.MATCH_DEFAULT_ONLY);
+ return isIntentAvailable(intent, null);
+ }
+ /**
+ * Indicates whether the specified action can be used as an intent. This
+ * method queries the package manager for installed packages that can
+ * respond to an intent with the specified action. If no suitable package is
+ * found, this method returns false.
+ *
+ * @param action
+ * The Intent action to check for availability.
+ * @param uri
+ * The Intent URI to check for availability.
+ *
+ * @return True if an Intent with the specified action can be sent and
+ * responded to, false otherwise.
+ */
+ public static boolean isIntentAvailable(final String action, final Uri uri) {
+ final PackageManager packageManager = CgeoApplication.getInstance().getPackageManager();
+ final Intent intent;
+ if (uri == null) {
+ intent = new Intent(action);
+ } else {
+ intent = new Intent(action, uri);
+ }
+ final List<ResolveInfo> list = packageManager.queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
return CollectionUtils.isNotEmpty(list);
}
+
}
diff --git a/main/src/cgeo/geocaching/utils/SynchronizedDateFormat.java b/main/src/cgeo/geocaching/utils/SynchronizedDateFormat.java
new file mode 100644
index 0000000..2368469
--- /dev/null
+++ b/main/src/cgeo/geocaching/utils/SynchronizedDateFormat.java
@@ -0,0 +1,18 @@
+package cgeo.geocaching.utils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class SynchronizedDateFormat {
+ private final SimpleDateFormat format;
+
+ public SynchronizedDateFormat(final String pattern, final Locale locale) {
+ format = new SimpleDateFormat(pattern, locale);
+ }
+
+ public synchronized Date parse(final String input) throws ParseException {
+ return format.parse(input);
+ }
+}
diff --git a/main/src/cgeo/geocaching/utils/TextUtils.java b/main/src/cgeo/geocaching/utils/TextUtils.java
index c9d4958..302a65d 100644
--- a/main/src/cgeo/geocaching/utils/TextUtils.java
+++ b/main/src/cgeo/geocaching/utils/TextUtils.java
@@ -3,6 +3,8 @@
*/
package cgeo.geocaching.utils;
+import org.eclipse.jdt.annotation.Nullable;
+
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -34,7 +36,7 @@ public final class TextUtils {
* Find the last occurring value
* @return defaultValue or the n-th group if the pattern matches (trimmed if wanted)
*/
- public static String getMatch(final String data, final Pattern p, final boolean trim, final int group, final String defaultValue, final boolean last) {
+ public static String getMatch(@Nullable final String data, final Pattern p, final boolean trim, final int group, final String defaultValue, final boolean last) {
if (data != null) {
String result = null;
@@ -87,7 +89,7 @@ public final class TextUtils {
* Value to return if the pattern is not found
* @return defaultValue or the first group if the pattern matches (trimmed)
*/
- public static String getMatch(final String data, final Pattern p, final String defaultValue) {
+ public static String getMatch(@Nullable final String data, final Pattern p, final String defaultValue) {
return TextUtils.getMatch(data, p, true, 1, defaultValue, false);
}
diff --git a/main/src/cgeo/geocaching/utils/TranslationUtils.java b/main/src/cgeo/geocaching/utils/TranslationUtils.java
index 1224f7e..619db08 100644
--- a/main/src/cgeo/geocaching/utils/TranslationUtils.java
+++ b/main/src/cgeo/geocaching/utils/TranslationUtils.java
@@ -3,6 +3,8 @@ package cgeo.geocaching.utils;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.network.Network;
+import org.apache.commons.lang3.StringUtils;
+
import android.content.Intent;
import android.net.Uri;
@@ -11,12 +13,12 @@ import android.net.Uri;
*/
public final class TranslationUtils {
- private static final String translationWebsite = "http://translate.google.com/";
- private static final String translationForceClassicMode = "?vi=c";
- private static final String translationAutoSelect = "#auto";
- private static final String translationFieldSeparator = "|";
+ private static final String TRANSLATION_WEBSITE = "http://translate.google.com/";
+ private static final String TRANSLATION_FORCE_CLASSIC_MODE = "?vi=c";
+ private static final String TRANSLATION_AUTO_SELECT = "#auto";
+ private static final String TRANSLATION_FIELD_SEPARATOR = "|";
- public static final int translationTextLengthToWarn = 500;
+ public static final int TRANSLATION_TEXT_LENGTH_WARN = 500;
private static final String TRANSLATION_APP = "com.google.android.apps.translate";
private TranslationUtils() {
@@ -24,8 +26,8 @@ public final class TranslationUtils {
}
/**
- * Build a URI for Google Translate
- *
+ * Build a URI for Google Translate.
+ *
* @param toLang
* The two-letter lowercase ISO language codes as defined by ISO 639-1
* @param text
@@ -36,13 +38,13 @@ public final class TranslationUtils {
String content = Network.encode(text);
// the app works better without the "+", the website works better with "+", therefore assume using the app if installed
if (ProcessUtils.isLaunchable(TRANSLATION_APP)) {
- content = content.replace("+", "%20");
+ content = StringUtils.replace(content, "+", "%20");
}
- return translationWebsite + translationForceClassicMode + translationAutoSelect + translationFieldSeparator + toLang + translationFieldSeparator + content;
+ return TRANSLATION_WEBSITE + TRANSLATION_FORCE_CLASSIC_MODE + TRANSLATION_AUTO_SELECT + TRANSLATION_FIELD_SEPARATOR + toLang + TRANSLATION_FIELD_SEPARATOR + content;
}
/**
- * Send Intent for Google Translate. Can be caught by Google Translate App or browser
+ * Send Intent for Google Translate. Can be caught by Google Translate App or browser.
*
* @param toLang
* The two-letter lowercase ISO language codes as defined by ISO 639-1