aboutsummaryrefslogtreecommitdiffstats
path: root/main/src
diff options
context:
space:
mode:
Diffstat (limited to 'main/src')
-rw-r--r--main/src/cgeo/geocaching/AboutActivity.java7
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java4
-rw-r--r--main/src/cgeo/geocaching/Geocache.java181
-rw-r--r--main/src/cgeo/geocaching/ImageSelectActivity.java4
-rw-r--r--main/src/cgeo/geocaching/LogCacheActivity.java1
-rw-r--r--main/src/cgeo/geocaching/LogTrackableActivity.java7
-rw-r--r--main/src/cgeo/geocaching/MainActivity.java7
-rw-r--r--main/src/cgeo/geocaching/NavigateAnyPointActivity.java28
-rw-r--r--main/src/cgeo/geocaching/SearchActivity.java1
-rw-r--r--main/src/cgeo/geocaching/SelectMapfileActivity.java2
-rw-r--r--main/src/cgeo/geocaching/StaticMapsProvider.java10
-rw-r--r--main/src/cgeo/geocaching/StoredList.java10
-rw-r--r--main/src/cgeo/geocaching/TrackableActivity.java2
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractActivity.java8
-rw-r--r--main/src/cgeo/geocaching/apps/cache/GccApp.java21
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java82
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java3
-rw-r--r--main/src/cgeo/geocaching/cgData.java36
-rw-r--r--main/src/cgeo/geocaching/cgeoapplication.java39
-rw-r--r--main/src/cgeo/geocaching/cgeocaches.java26
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConstants.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java17
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java12
-rw-r--r--main/src/cgeo/geocaching/connector/gc/IconDecoder.java24
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Login.java24
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Tile.java16
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java4
-rw-r--r--main/src/cgeo/geocaching/export/FieldnoteExport.java7
-rw-r--r--main/src/cgeo/geocaching/export/GpxExport.java27
-rw-r--r--main/src/cgeo/geocaching/export/GpxSerializer.java3
-rw-r--r--main/src/cgeo/geocaching/files/AbstractFileListActivity.java84
-rw-r--r--main/src/cgeo/geocaching/files/LocalStorage.java74
-rw-r--r--main/src/cgeo/geocaching/maps/CGeoMap.java54
-rw-r--r--main/src/cgeo/geocaching/maps/PositionHistory.java63
-rw-r--r--main/src/cgeo/geocaching/maps/PositionOverlay.java82
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapView.java6
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleOverlay.java2
-rw-r--r--main/src/cgeo/geocaching/maps/interfaces/OverlayImpl.java2
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java6
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java2
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java6
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java2
-rw-r--r--main/src/cgeo/geocaching/network/HtmlImage.java11
-rw-r--r--main/src/cgeo/geocaching/settings/EditPasswordPreference.java1
-rw-r--r--main/src/cgeo/geocaching/settings/Settings.java73
-rw-r--r--main/src/cgeo/geocaching/settings/SettingsActivity.java84
-rw-r--r--main/src/cgeo/geocaching/speech/SpeechService.java19
-rw-r--r--main/src/cgeo/geocaching/ui/CacheListAdapter.java6
-rw-r--r--main/src/cgeo/geocaching/ui/EditNoteDialog.java7
-rw-r--r--main/src/cgeo/geocaching/ui/Formatter.java4
-rw-r--r--main/src/cgeo/geocaching/ui/GPXListAdapter.java3
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java14
-rw-r--r--main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java115
-rw-r--r--main/src/cgeo/geocaching/utils/FileUtils.java64
-rw-r--r--main/src/cgeo/geocaching/utils/Log.java18
-rw-r--r--main/src/cgeo/geocaching/utils/MatcherWrapper.java4
-rw-r--r--main/src/cgeo/geocaching/utils/SimpleCancellableHandler.java8
-rw-r--r--main/src/cgeo/geocaching/utils/UncertainProperty.java48
58 files changed, 903 insertions, 574 deletions
diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java
index ef59cee..14786ec 100644
--- a/main/src/cgeo/geocaching/AboutActivity.java
+++ b/main/src/cgeo/geocaching/AboutActivity.java
@@ -22,8 +22,8 @@ public class AboutActivity extends AbstractActivity {
@ViewById(R.id.about_version_string) protected TextView version;
@ViewById(R.id.contributors) protected TextView contributors;
@ViewById(R.id.changelog_master) protected TextView changeLogMaster;
- @ViewById(R.id.changelog_release) protected TextView changeLogRelease;
+ @ViewById(R.id.changelog_release) protected TextView changeLogRelease;
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO remove this after the theme has been fixed
@@ -80,4 +80,9 @@ public class AboutActivity extends AbstractActivity {
marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
startActivity(marketIntent);
}
+
+ @Click(R.id.license)
+ public void license() {
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.apache.org/licenses/LICENSE-2.0.html")));
+ }
}
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index 45a1dd2..f43de4e 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -243,7 +243,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return;
}
} else if (uriHost.contains("coord.info")) {
- if (uriPath != null && uriPath.startsWith("/gc")) {
+ if (StringUtils.startsWith(uriPath, "/gc")) {
geocode = uriPath.substring(1).toUpperCase(Locale.US);
} else {
showToast(res.getString(R.string.err_detail_open));
@@ -251,7 +251,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return;
}
} else if (uriHost.contains("opencaching.de")) {
- if (uriPath != null && uriPath.startsWith("/oc")) {
+ if (StringUtils.startsWith(uriPath, "/oc")) {
geocode = uriPath.substring(1).toUpperCase(Locale.US);
} else {
geocode = uri.getQueryParameter("wp");
diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java
index 3c69197..96fbc06 100644
--- a/main/src/cgeo/geocaching/Geocache.java
+++ b/main/src/cgeo/geocaching/Geocache.java
@@ -30,8 +30,10 @@ import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.LogTemplateProvider;
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.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
@@ -66,7 +68,7 @@ public class Geocache implements ICache, IWaypoint {
private String geocode = "";
private String cacheId = "";
private String guid = "";
- private CacheType cacheType = CacheType.UNKNOWN;
+ private UncertainProperty<CacheType> cacheType = new UncertainProperty<CacheType>(CacheType.UNKNOWN, Tile.ZOOMLEVEL_MIN - 1);
private String name = "";
private String ownerDisplayName = "";
private String ownerUserId = "";
@@ -84,7 +86,7 @@ public class Geocache implements ICache, IWaypoint {
* lazy initialized
*/
private String location = null;
- private Geopoint coords = null;
+ private UncertainProperty<Geopoint> coords = new UncertainProperty<Geopoint>(null);
private boolean reliableLatLon = false;
private String personalNote = null;
/**
@@ -95,17 +97,18 @@ public class Geocache implements ICache, IWaypoint {
* lazy initialized
*/
private String description = null;
- private boolean disabled = false;
- private boolean archived = false;
- private boolean premiumMembersOnly = false;
- private boolean found = false;
- private boolean favorite = false;
+ private Boolean disabled = null;
+ private Boolean archived = null;
+ private Boolean premiumMembersOnly = null;
+ private Boolean found = null;
+ private Boolean favorite = null;
+ private Boolean onWatchlist = null;
+ private Boolean logOffline = null;
private int favoritePoints = 0;
private float rating = 0; // valid ratings are larger than zero
private int votes = 0;
private float myVote = 0; // valid ratings are larger than zero
private int inventoryItems = 0;
- private boolean onWatchlist = false;
private final List<String> attributes = new LazyInitializedList<String>() {
@Override
public List<String> call() {
@@ -127,7 +130,6 @@ public class Geocache implements ICache, IWaypoint {
};
private List<Trackable> inventory = null;
private Map<LogType, Integer> logCounts = new HashMap<LogType, Integer>();
- private boolean logOffline = false;
private boolean userModifiedCoords = false;
// temporary values
private boolean statusChecked = false;
@@ -136,7 +138,7 @@ public class Geocache implements ICache, IWaypoint {
private final EnumSet<StorageLocation> storageLocation = EnumSet.of(StorageLocation.HEAP);
private boolean finalDefined = false;
private boolean logPasswordRequired = false;
- private int zoomlevel = Tile.ZOOMLEVEL_MAX + 1;
+ // private int zoomlevel = Tile.ZOOMLEVEL_MIN - 1;
private static final Pattern NUMBER_PATTERN = Pattern.compile("\\d+");
@@ -192,38 +194,35 @@ public class Geocache implements ICache, IWaypoint {
updated = System.currentTimeMillis();
// if parsed cache is not yet detailed and stored is, the information of
// the parsed cache will be overwritten
- if (!detailed && (other.detailed || zoomlevel < other.zoomlevel)) {
+ if (!detailed && other.detailed) {
detailed = other.detailed;
detailedUpdate = other.detailedUpdate;
- coords = other.coords;
- cacheType = other.cacheType;
- zoomlevel = other.zoomlevel;
// boolean values must be enumerated here. Other types are assigned outside this if-statement
- // TODO: check whether a search or a live map systematically returns those, in which case
- // we want to keep the most recent one instead of getting information from the previously
- // stored data. This is the case for "archived" for example which has been taken out of this
- // list.
- premiumMembersOnly = other.premiumMembersOnly;
reliableLatLon = other.reliableLatLon;
+ finalDefined = other.finalDefined;
+ }
+
+ if (premiumMembersOnly == null) {
+ premiumMembersOnly = other.premiumMembersOnly;
+ }
+ if (found == null) {
found = other.found;
+ }
+ if (disabled == null) {
disabled = other.disabled;
+ }
+ if (favorite == null) {
favorite = other.favorite;
+ }
+ if (archived == null) {
+ archived = other.archived;
+ }
+ if (onWatchlist == null) {
onWatchlist = other.onWatchlist;
+ }
+ if (logOffline == null) {
logOffline = other.logOffline;
- finalDefined = other.finalDefined;
- archived = other.archived;
}
-
- /*
- * No gathering for boolean members if other cache is not-detailed
- * and does not have information with higher reliability (denoted by zoomlevel)
- * - found
- * - own
- * - disabled
- * - favorite
- * - onWatchlist
- * - logOffline
- */
if (visitedDate == 0) {
visitedDate = other.visitedDate;
}
@@ -239,9 +238,7 @@ public class Geocache implements ICache, IWaypoint {
if (StringUtils.isBlank(guid)) {
guid = other.guid;
}
- if (null == cacheType || CacheType.UNKNOWN == cacheType) {
- cacheType = other.cacheType;
- }
+ cacheType = UncertainProperty.getMergedProperty(cacheType, other.cacheType);
if (StringUtils.isBlank(name)) {
name = other.name;
}
@@ -275,9 +272,7 @@ public class Geocache implements ICache, IWaypoint {
if (StringUtils.isBlank(getLocation())) {
location = other.getLocation();
}
- if (coords == null) {
- coords = other.coords;
- }
+ coords = UncertainProperty.getMergedProperty(coords, other.coords);
// don't use StringUtils.isBlank here. Otherwise we cannot recognize a note which was deleted on GC
if (personalNote == null) {
personalNote = other.personalNote;
@@ -354,9 +349,6 @@ public class Geocache implements ICache, IWaypoint {
if (!reliableLatLon) {
reliableLatLon = other.reliableLatLon;
}
- if (zoomlevel == -1) {
- zoomlevel = other.zoomlevel;
- }
return isEqualTo(other);
}
@@ -374,14 +366,14 @@ public class Geocache implements ICache, IWaypoint {
StringUtils.equalsIgnoreCase(name, other.name) &&
cacheType == other.cacheType &&
size == other.size &&
- found == other.found &&
- premiumMembersOnly == other.premiumMembersOnly &&
+ ObjectUtils.equals(found, other.found) &&
+ ObjectUtils.equals(premiumMembersOnly, other.premiumMembersOnly) &&
difficulty == other.difficulty &&
terrain == other.terrain &&
(coords != null ? coords.equals(other.coords) : null == other.coords) &&
reliableLatLon == other.reliableLatLon &&
- disabled == other.disabled &&
- archived == other.archived &&
+ ObjectUtils.equals(disabled, other.disabled) &&
+ ObjectUtils.equals(archived, other.archived) &&
listId == other.listId &&
StringUtils.equalsIgnoreCase(ownerDisplayName, other.ownerDisplayName) &&
StringUtils.equalsIgnoreCase(ownerUserId, other.ownerUserId) &&
@@ -389,9 +381,9 @@ public class Geocache implements ICache, IWaypoint {
StringUtils.equalsIgnoreCase(personalNote, other.personalNote) &&
StringUtils.equalsIgnoreCase(getShortDescription(), other.getShortDescription()) &&
StringUtils.equalsIgnoreCase(getLocation(), other.getLocation()) &&
- favorite == other.favorite &&
+ ObjectUtils.equals(favorite, other.favorite) &&
favoritePoints == other.favoritePoints &&
- onWatchlist == other.onWatchlist &&
+ ObjectUtils.equals(onWatchlist, other.onWatchlist) &&
(hidden != null ? hidden.equals(other.hidden) : null == other.hidden) &&
StringUtils.equalsIgnoreCase(guid, other.guid) &&
StringUtils.equalsIgnoreCase(getHint(), other.getHint()) &&
@@ -408,7 +400,7 @@ public class Geocache implements ICache, IWaypoint {
logs == other.logs &&
inventory == other.inventory &&
logCounts == other.logCounts &&
- logOffline == other.logOffline &&
+ ObjectUtils.equals(logOffline, other.logOffline) &&
finalDefined == other.finalDefined;
}
@@ -452,7 +444,7 @@ public class Geocache implements ICache, IWaypoint {
}
public boolean isEventCache() {
- return cacheType.isEvent();
+ return cacheType.getValue().isEvent();
}
public void logVisit(final IAbstractActivity fromActivity) {
@@ -483,7 +475,7 @@ public class Geocache implements ICache, IWaypoint {
if (status) {
ActivityMixin.showToast(fromActivity, res.getString(R.string.info_log_saved));
cgData.saveVisitDate(geocode);
- logOffline = true;
+ logOffline = Boolean.TRUE;
notifyChange();
} else {
@@ -504,7 +496,7 @@ public class Geocache implements ICache, IWaypoint {
if (isOwner()) {
logTypes.add(LogType.ANNOUNCEMENT);
}
- } else if (CacheType.WEBCAM == cacheType) {
+ } else if (CacheType.WEBCAM == cacheType.getValue()) {
logTypes.add(LogType.WEBCAM_PHOTO_TAKEN);
} else {
logTypes.add(LogType.FOUND_IT);
@@ -610,21 +602,21 @@ public class Geocache implements ICache, IWaypoint {
@Override
public boolean isArchived() {
- return archived;
+ return (archived != null && archived.booleanValue());
}
@Override
public boolean isDisabled() {
- return disabled;
+ return (disabled != null && disabled.booleanValue());
}
@Override
public boolean isPremiumMembersOnly() {
- return premiumMembersOnly;
+ return (premiumMembersOnly != null && premiumMembersOnly.booleanValue());
}
public void setPremiumMembersOnly(boolean members) {
- this.premiumMembersOnly = members;
+ this.premiumMembersOnly = Boolean.valueOf(members);
}
@Override
@@ -775,16 +767,16 @@ public class Geocache implements ICache, IWaypoint {
@Override
public boolean isFound() {
- return found;
+ return (found != null && found.booleanValue());
}
@Override
public boolean isFavorite() {
- return favorite;
+ return (favorite != null && favorite.booleanValue());
}
public void setFavorite(boolean favorite) {
- this.favorite = favorite;
+ this.favorite = Boolean.valueOf(favorite);
}
@Override
@@ -830,19 +822,22 @@ public class Geocache implements ICache, IWaypoint {
@Override
public String getNameForSorting() {
if (null == nameForSorting) {
- final MatcherWrapper matcher = new MatcherWrapper(NUMBER_PATTERN, name);
- if (matcher.find()) {
- nameForSorting = name.replace(matcher.group(), StringUtils.leftPad(matcher.group(), 6, '0'));
- }
- else {
- nameForSorting = name;
+ nameForSorting = name;
+ // pad each number part to a fixed size of 6 digits, so that numerical sorting becomes equivalent to string sorting
+ MatcherWrapper matcher = new MatcherWrapper(NUMBER_PATTERN, nameForSorting);
+ int start = 0;
+ while (matcher.find(start)) {
+ final String number = matcher.group();
+ nameForSorting = StringUtils.substring(nameForSorting, 0, matcher.start()) + StringUtils.leftPad(number, 6, '0') + StringUtils.substring(nameForSorting, matcher.start() + number.length());
+ start = matcher.start() + Math.max(6, number.length());
+ matcher = new MatcherWrapper(NUMBER_PATTERN, nameForSorting);
}
}
return nameForSorting;
}
public boolean isVirtual() {
- return cacheType.isVirtual();
+ return cacheType.getValue().isVirtual();
}
public boolean showSize() {
@@ -916,11 +911,30 @@ public class Geocache implements ICache, IWaypoint {
@Override
public Geopoint getCoords() {
- return coords;
+ return coords.getValue();
+ }
+
+ public int getCoordZoomLevel() {
+ return coords.getCertaintyLevel();
}
+ /**
+ * Set reliable coordinates
+ *
+ * @param coords
+ */
public void setCoords(Geopoint coords) {
- this.coords = coords;
+ this.coords = new UncertainProperty<Geopoint>(coords);
+ }
+
+ /**
+ * Set unreliable coordinates from a certain map zoom level
+ *
+ * @param coords
+ * @param zoomlevel
+ */
+ public void setCoords(Geopoint coords, int zoomlevel) {
+ this.coords = new UncertainProperty<Geopoint>(coords, zoomlevel);
}
/**
@@ -976,11 +990,11 @@ public class Geocache implements ICache, IWaypoint {
@Override
public boolean isOnWatchlist() {
- return onWatchlist;
+ return (onWatchlist != null && onWatchlist.booleanValue());
}
public void setOnWatchlist(boolean onWatchlist) {
- this.onWatchlist = onWatchlist;
+ this.onWatchlist = Boolean.valueOf(onWatchlist);
}
/**
@@ -1049,11 +1063,11 @@ public class Geocache implements ICache, IWaypoint {
}
public boolean isLogOffline() {
- return logOffline;
+ return (logOffline != null && logOffline.booleanValue());
}
public void setLogOffline(boolean logOffline) {
- this.logOffline = logOffline;
+ this.logOffline = Boolean.valueOf(logOffline);
}
public boolean isStatusChecked() {
@@ -1126,15 +1140,15 @@ public class Geocache implements ICache, IWaypoint {
}
public void setDisabled(boolean disabled) {
- this.disabled = disabled;
+ this.disabled = Boolean.valueOf(disabled);
}
public void setArchived(boolean archived) {
- this.archived = archived;
+ this.archived = Boolean.valueOf(archived);
}
public void setFound(boolean found) {
- this.found = found;
+ this.found = Boolean.valueOf(found);
}
public void setAttributes(List<String> attributes) {
@@ -1165,14 +1179,21 @@ public class Geocache implements ICache, IWaypoint {
*/
@Override
public CacheType getType() {
- return cacheType;
+ return cacheType.getValue();
}
public void setType(CacheType cacheType) {
if (cacheType == null || CacheType.ALL == cacheType) {
throw new IllegalArgumentException("Illegal cache type");
}
- this.cacheType = cacheType;
+ this.cacheType = new UncertainProperty<CacheType>(cacheType);
+ }
+
+ public void setType(CacheType cacheType, final int zoomlevel) {
+ if (cacheType == null || CacheType.ALL == cacheType) {
+ throw new IllegalArgumentException("Illegal cache type");
+ }
+ this.cacheType = new UncertainProperty<CacheType>(cacheType, zoomlevel);
}
public boolean hasDifficulty() {
@@ -1473,14 +1494,6 @@ public class Geocache implements ICache, IWaypoint {
storeCache(this, null, newListId, false, handler);
}
- public int getZoomLevel() {
- return this.zoomlevel;
- }
-
- public void setZoomlevel(int zoomlevel) {
- this.zoomlevel = zoomlevel;
- }
-
@Override
public int getId() {
return 0;
diff --git a/main/src/cgeo/geocaching/ImageSelectActivity.java b/main/src/cgeo/geocaching/ImageSelectActivity.java
index 52f9a7e..738b9a7 100644
--- a/main/src/cgeo/geocaching/ImageSelectActivity.java
+++ b/main/src/cgeo/geocaching/ImageSelectActivity.java
@@ -6,6 +6,7 @@ import butterknife.Views;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
@@ -328,8 +329,7 @@ public class ImageSelectActivity extends AbstractActivity {
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
- if (!mediaStorageDir.mkdirs()) {
- Log.w("Failed to create directory");
+ if (!FileUtils.mkdirs(mediaStorageDir)) {
return null;
}
}
diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java
index e11af0f..207dce5 100644
--- a/main/src/cgeo/geocaching/LogCacheActivity.java
+++ b/main/src/cgeo/geocaching/LogCacheActivity.java
@@ -545,6 +545,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
if (typeSelected == LogType.FOUND_IT || typeSelected == LogType.ATTENDED) {
cache.setFound(true);
+ cache.setVisitedDate(new Date().getTime());
}
cgData.saveChangedCache(cache);
diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java
index f0dd7f9..a45d584 100644
--- a/main/src/cgeo/geocaching/LogTrackableActivity.java
+++ b/main/src/cgeo/geocaching/LogTrackableActivity.java
@@ -183,7 +183,6 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
public void init() {
registerForContextMenu(typeButton);
- typeButton.setText(typeSelected.getL10n());
typeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -191,10 +190,11 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
}
});
+ setType(typeSelected);
dateButton.setOnClickListener(new DateListener());
setDate(date);
- tweetCheck.setChecked(true);
+ initTwitter();
if (CollectionUtils.isEmpty(possibleLogTypes)) {
possibleLogTypes = Trackable.getPossibleLogTypes();
@@ -223,7 +223,10 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
public void setType(LogType type) {
typeSelected = type;
typeButton.setText(typeSelected.getL10n());
+ }
+ private void initTwitter() {
+ tweetCheck.setChecked(true);
if (Settings.isUseTwitter() && Settings.isTwitterLoginValid()) {
tweetBox.setVisibility(View.VISIBLE);
} else {
diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java
index 2d488d6..a3daf97 100644
--- a/main/src/cgeo/geocaching/MainActivity.java
+++ b/main/src/cgeo/geocaching/MainActivity.java
@@ -14,6 +14,7 @@ import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.settings.SettingsActivity;
import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.utils.DatabaseBackupUtils;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.ProcessUtils;
@@ -462,12 +463,12 @@ public class MainActivity extends AbstractActivity {
builder.create().show();
}
- void updateCacheCounter() {
+ public void updateCacheCounter() {
(new CountBubbleUpdateThread()).start();
}
private void checkRestore() {
- if (!cgData.isNewlyCreatedDatebase() || null == cgData.getRestoreFile()) {
+ if (!cgData.isNewlyCreatedDatebase() || null == DatabaseBackupUtils.getRestoreFile()) {
return;
}
new AlertDialog.Builder(this)
@@ -479,7 +480,7 @@ public class MainActivity extends AbstractActivity {
public void onClick(final DialogInterface dialog, final int id) {
dialog.dismiss();
cgData.resetNewlyCreatedDatabase();
- app.restoreDatabase(MainActivity.this);
+ DatabaseBackupUtils.restoreDatabase(MainActivity.this);
}
})
.setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() {
diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
index be4ef05..741414b 100644
--- a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
+++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
@@ -100,13 +100,13 @@ public class NavigateAnyPointActivity extends AbstractActivity {
return rowView;
}
- private void fillViewHolder(ViewHolder viewHolder, Destination loc) {
+ private static void fillViewHolder(ViewHolder viewHolder, Destination loc) {
String lonString = loc.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE);
String latString = loc.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE);
viewHolder.longitude.setText(lonString);
viewHolder.latitude.setText(latString);
- viewHolder.date.setText(Formatter.formatShortDateTime(getContext(), loc.getDate()));
+ viewHolder.date.setText(Formatter.formatShortDateTime(loc.getDate()));
}
private LayoutInflater getInflater() {
@@ -490,6 +490,7 @@ public class NavigateAnyPointActivity extends AbstractActivity {
return null;
}
+ // get base coordinates
Geopoint coords;
if (StringUtils.isNotBlank(latText) && StringUtils.isNotBlank(lonText)) {
try {
@@ -507,8 +508,8 @@ public class NavigateAnyPointActivity extends AbstractActivity {
coords = app.currentGeo().getCoords();
}
- Geopoint result;
- if (StringUtils.isNotBlank(bearingText) && StringUtils.isNotBlank(distanceText)) {
+ // apply projection
+ if (coords != null && StringUtils.isNotBlank(bearingText) && StringUtils.isNotBlank(distanceText)) {
// bearing & distance
double bearing;
try {
@@ -527,23 +528,14 @@ public class NavigateAnyPointActivity extends AbstractActivity {
return null;
}
- final Geopoint coordsDst = coords.project(bearing, distance);
-
- if (coordsDst == null) {
- showToast(res.getString(R.string.err_point_location_error));
- return null;
- }
-
- result = coordsDst;
- } else if (coords != null) {
- result = coords;
- } else {
- return null;
+ coords = coords.project(bearing, distance);
}
- saveCoords(result);
+ if (coords != null) {
+ saveCoords(coords);
+ }
- return result;
+ return coords;
}
private void saveCoords(final Geopoint coords) {
diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java
index ccf3edf..57b391f 100644
--- a/main/src/cgeo/geocaching/SearchActivity.java
+++ b/main/src/cgeo/geocaching/SearchActivity.java
@@ -63,6 +63,7 @@ public class SearchActivity extends AbstractActivity {
// search query
final Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
+ hideKeyboard();
final String query = intent.getStringExtra(SearchManager.QUERY);
final boolean keywordSearch = intent.getBooleanExtra(Intents.EXTRA_KEYWORD_SEARCH, true);
diff --git a/main/src/cgeo/geocaching/SelectMapfileActivity.java b/main/src/cgeo/geocaching/SelectMapfileActivity.java
index 8f82288..8b50c1f 100644
--- a/main/src/cgeo/geocaching/SelectMapfileActivity.java
+++ b/main/src/cgeo/geocaching/SelectMapfileActivity.java
@@ -47,7 +47,7 @@ public class SelectMapfileActivity extends AbstractFileListActivity<FileSelectio
@Override
protected List<File> getBaseFolders() {
List<File> folders = new ArrayList<File>();
- for (File dir : getStorages()) {
+ for (File dir : LocalStorage.getStorages()) {
folders.add(new File(dir, "mfmaps"));
folders.add(new File(new File(dir, "Locus"), "mapsVector"));
folders.add(new File(dir, LocalStorage.cache));
diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java
index 2555b80..eb59bcb 100644
--- a/main/src/cgeo/geocaching/StaticMapsProvider.java
+++ b/main/src/cgeo/geocaching/StaticMapsProvider.java
@@ -7,6 +7,7 @@ import cgeo.geocaching.geopoint.GeopointFormatter.Format;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
@@ -82,7 +83,7 @@ public final class StaticMapsProvider {
// Delete image if it has no contents
final long fileSize = file.length();
if (fileSize < MIN_MAP_IMAGE_BYTES) {
- file.delete();
+ FileUtils.deleteIgnoringFailure(file);
}
}
}
@@ -229,10 +230,9 @@ public final class StaticMapsProvider {
int waypointId = waypoint.getId();
int waypointMapHash = waypoint.getStaticMapsHashcode();
for (int level = 1; level <= MAPS_LEVEL_MAX; level++) {
- try {
- StaticMapsProvider.getMapFile(geocode, WAYPOINT_PREFIX + waypointId + "_" + waypointMapHash + '_' + level, false).delete();
- } catch (Exception e) {
- Log.e("StaticMapsProvider.removeWpStaticMaps", e);
+ final File mapFile = StaticMapsProvider.getMapFile(geocode, WAYPOINT_PREFIX + waypointId + "_" + waypointMapHash + '_' + level, false);
+ if (!FileUtils.delete(mapFile)) {
+ Log.e("StaticMapsProvider.removeWpStaticMaps failed for " + mapFile.getAbsolutePath());
}
}
}
diff --git a/main/src/cgeo/geocaching/StoredList.java b/main/src/cgeo/geocaching/StoredList.java
index 55a155c..ec99d0a 100644
--- a/main/src/cgeo/geocaching/StoredList.java
+++ b/main/src/cgeo/geocaching/StoredList.java
@@ -72,6 +72,10 @@ public final class StoredList {
}
public void promptForListSelection(final int titleId, 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();
if (lists == null) {
@@ -106,7 +110,7 @@ public final class StoredList {
runAfterwards.run(StoredList.ALL_LIST_ID);
} else if (itemId >= lists.size()) {
// create new list on the fly
- promptForListCreation(runAfterwards);
+ promptForListCreation(runAfterwards, newListName);
}
else {
if (runAfterwards != null) {
@@ -131,8 +135,8 @@ public final class StoredList {
return lists;
}
- public void promptForListCreation(final RunnableWithArgument<Integer> runAfterwards) {
- handleListNameInput("", R.string.list_dialog_create_title, R.string.list_dialog_create, new RunnableWithArgument<String>() {
+ public void promptForListCreation(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) {
diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java
index d1f323c..35ffdc6 100644
--- a/main/src/cgeo/geocaching/TrackableActivity.java
+++ b/main/src/cgeo/geocaching/TrackableActivity.java
@@ -154,7 +154,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
} else if (uriHost.contains("coord.info")) {
final String uriPath = uri.getPath().toLowerCase(Locale.US);
- if (uriPath != null && uriPath.startsWith("/tb")) {
+ if (StringUtils.startsWith(uriPath, "/tb")) {
geocode = uriPath.substring(1).toUpperCase(Locale.US);
guid = null;
id = null;
diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java
index 9aca35e..28c0cdd 100644
--- a/main/src/cgeo/geocaching/activity/AbstractActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java
@@ -2,16 +2,18 @@ package cgeo.geocaching.activity;
import butterknife.Views;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.network.Cookies;
+import cgeo.geocaching.settings.Settings;
+import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
+import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
public abstract class AbstractActivity extends FragmentActivity implements IAbstractActivity {
@@ -113,4 +115,8 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
// initialize the action bar title with the activity title for single source
ActivityMixin.setTitle(this, getTitle());
}
+
+ protected void hideKeyboard() {
+ ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
+ }
}
diff --git a/main/src/cgeo/geocaching/apps/cache/GccApp.java b/main/src/cgeo/geocaching/apps/cache/GccApp.java
index b129b45..0bbc2dd 100644
--- a/main/src/cgeo/geocaching/apps/cache/GccApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/GccApp.java
@@ -1,9 +1,28 @@
package cgeo.geocaching.apps.cache;
import cgeo.geocaching.R;
+import cgeo.geocaching.utils.ProcessUtils;
+
+import android.content.Intent;
public class GccApp extends AbstractGeneralApp {
+ private static final String PACKAGE = "eisbehr.gcc";
+ private static final String PACKAGE_PRO = "eisbehr.gcc.pro";
+
public GccApp() {
- super(getString(R.string.cache_menu_gcc), "eisbehr.gcc");
+ super(getString(R.string.cache_menu_gcc), null);
+ }
+
+ @Override
+ public boolean isInstalled() {
+ return ProcessUtils.isLaunchable(PACKAGE) || ProcessUtils.isLaunchable(PACKAGE_PRO);
+ }
+
+ @Override
+ protected Intent getLaunchIntent() {
+ if (ProcessUtils.isLaunchable(PACKAGE_PRO)) {
+ return ProcessUtils.getLaunchIntent(PACKAGE_PRO);
+ }
+ return ProcessUtils.getLaunchIntent(PACKAGE);
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
index 4db889d..ec6b3e1 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
@@ -1,7 +1,6 @@
package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
import cgeo.geocaching.cgeoapplication;
@@ -15,6 +14,7 @@ import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationBikeA
import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationDrivingApp;
import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationWalkingApp;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.settings.Settings;
import android.app.Activity;
import android.app.AlertDialog;
@@ -30,51 +30,52 @@ public final class NavigationAppFactory extends AbstractAppFactory {
public enum NavigationAppsEnum {
/** The internal compass activity */
- COMPASS(new CompassApp(), 0),
+ COMPASS(new CompassApp(), 0, R.string.pref_navigation_menu_compass),
/** The external radar app */
- RADAR(new RadarApp(), 1),
+ RADAR(new RadarApp(), 1, R.string.pref_navigation_menu_radar),
/** The selected map */
- INTERNAL_MAP(new InternalMap(), 2),
- /** The internal static map activity */
- STATIC_MAP(new StaticMapApp(), 3),
- /** The external Locus app */
- DOWNLOAD_STATIC_MAPS(new DownloadStaticMapsApp(), 20),
+ INTERNAL_MAP(new InternalMap(), 2, R.string.pref_navigation_menu_internal_map),
+ /** The internal static map activity, when stored */
+ STATIC_MAP(new StaticMapApp(), 3, R.string.pref_navigation_menu_static_map),
+ /** The internal static map activity, when not yet stored */
+ DOWNLOAD_STATIC_MAPS(new DownloadStaticMapsApp(), 20, R.string.pref_navigation_menu_static_map_download),
/** The external Locus app */
- LOCUS(new LocusApp(), 4),
+ LOCUS(new LocusApp(), 4, R.string.pref_navigation_menu_locus),
/** The external RMaps app */
- RMAPS(new RMapsApp(), 5),
+ RMAPS(new RMapsApp(), 5, R.string.pref_navigation_menu_rmaps),
/** Google Maps */
- GOOGLE_MAPS(new GoogleMapsApp(), 6),
+ GOOGLE_MAPS(new GoogleMapsApp(), 6, R.string.pref_navigation_menu_google_maps),
/** Google Navigation */
- GOOGLE_NAVIGATION(new GoogleNavigationDrivingApp(), 7),
+ GOOGLE_NAVIGATION(new GoogleNavigationDrivingApp(), 7, R.string.pref_navigation_menu_google_navigation),
/** Google Streetview */
- GOOGLE_STREETVIEW(new StreetviewApp(), 8),
+ GOOGLE_STREETVIEW(new StreetviewApp(), 8, R.string.pref_navigation_menu_google_streetview),
/** The external OruxMaps app */
- ORUX_MAPS(new OruxMapsApp(), 9),
+ ORUX_MAPS(new OruxMapsApp(), 9, R.string.pref_navigation_menu_oruxmaps),
/** The external navigon app */
- NAVIGON(new NavigonApp(), 10),
+ NAVIGON(new NavigonApp(), 10, R.string.pref_navigation_menu_navigon),
/** The external Sygic app */
- SYGIC(new SygicNavigationApp(), 11),
+ SYGIC(new SygicNavigationApp(), 11, R.string.pref_navigation_menu_sygic),
/**
* Google Navigation in walking mode
*/
- GOOGLE_NAVIGATION_WALK(new GoogleNavigationWalkingApp(), 12),
+ GOOGLE_NAVIGATION_WALK(new GoogleNavigationWalkingApp(), 12, R.string.pref_navigation_menu_google_walk),
/**
* Google Navigation in walking mode
*/
- GOOGLE_NAVIGATION_BIKE(new GoogleNavigationBikeApp(), 21),
+ GOOGLE_NAVIGATION_BIKE(new GoogleNavigationBikeApp(), 21, R.string.pref_navigation_menu_google_bike),
/**
* Google Maps Directions
*/
- GOOGLE_MAPS_DIRECTIONS(new GoogleMapsDirectionApp(), 13),
+ GOOGLE_MAPS_DIRECTIONS(new GoogleMapsDirectionApp(), 13, R.string.pref_navigation_menu_google_maps_directions),
- CACHE_BEACON(new CacheBeaconApp(), 14),
- GCC(new GccApp(), 15),
- WHERE_YOU_GO(new WhereYouGoApp(), 16);
+ CACHE_BEACON(new CacheBeaconApp(), 14, R.string.pref_navigation_menu_cache_beacon),
+ GCC(new GccApp(), 15, R.string.pref_navigation_menu_gcc),
+ WHERE_YOU_GO(new WhereYouGoApp(), 16, R.string.pref_navigation_menu_where_you_go);
- NavigationAppsEnum(App app, int id) {
+ NavigationAppsEnum(final App app, final int id, final int preferenceKey) {
this.app = app;
this.id = id;
+ this.preferenceKey = preferenceKey;
}
/**
@@ -86,6 +87,11 @@ public final class NavigationAppFactory extends AbstractAppFactory {
*/
public final int id;
+ /**
+ * key of the related preference in the navigation menu preference screen, used for disabling the preference UI
+ */
+ public final int preferenceKey;
+
/*
* display app name in array adapter
*
@@ -142,18 +148,20 @@ public final class NavigationAppFactory extends AbstractAppFactory {
for (final NavigationAppsEnum navApp : getInstalledNavigationApps()) {
if ((showInternalMap || !(navApp.app instanceof InternalMap)) &&
(showDefaultNavigation || defaultNavigationTool != navApp.id)) {
- boolean add = false;
- if (cache != null && navApp.app instanceof CacheNavigationApp && navApp.app.isEnabled(cache)) {
- add = true;
- }
- if (waypoint != null && navApp.app instanceof WaypointNavigationApp && ((WaypointNavigationApp) navApp.app).isEnabled(waypoint)) {
- add = true;
- }
- if (destination != null && navApp.app instanceof GeopointNavigationApp) {
- add = true;
- }
- if (add) {
- items.add(navApp);
+ if (Settings.isUseNavigationApp(navApp)) {
+ boolean add = false;
+ if (cache != null && navApp.app instanceof CacheNavigationApp && navApp.app.isEnabled(cache)) {
+ add = true;
+ }
+ if (waypoint != null && navApp.app instanceof WaypointNavigationApp && ((WaypointNavigationApp) navApp.app).isEnabled(waypoint)) {
+ add = true;
+ }
+ if (destination != null && navApp.app instanceof GeopointNavigationApp) {
+ add = true;
+ }
+ if (add) {
+ items.add(navApp);
+ }
}
}
}
@@ -233,7 +241,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
for (final NavigationAppsEnum navApp : getInstalledNavigationApps()) {
if (navApp.app instanceof CacheNavigationApp) {
final CacheNavigationApp cacheApp = (CacheNavigationApp) navApp.app;
- if (cacheApp.isEnabled(cache)) {
+ if (cacheApp.isEnabled(cache) && Settings.isUseNavigationApp(navApp)) {
menu.add(0, MENU_ITEM_OFFSET + navApp.id, 0, navApp.app.getName());
}
}
@@ -244,7 +252,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
for (final NavigationAppsEnum navApp : getInstalledNavigationApps()) {
if (navApp.app instanceof WaypointNavigationApp) {
final WaypointNavigationApp waypointApp = (WaypointNavigationApp) navApp.app;
- if (waypointApp.isEnabled(waypoint)) {
+ if (waypointApp.isEnabled(waypoint) && Settings.isUseNavigationApp(navApp)) {
menu.add(0, MENU_ITEM_OFFSET + navApp.id, 0, navApp.app.getName());
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
index 7ea86fb..7966733 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.R;
import cgeo.geocaching.geopoint.Geopoint;
import android.app.Activity;
@@ -12,7 +13,7 @@ class NavigonApp extends AbstractPointNavigationApp {
private static final String INTENT_EXTRA_KEY_LONGITUDE = "longitude";
NavigonApp() {
- super("Navigon", INTENT);
+ super(getString(R.string.cache_menu_navigon), INTENT);
}
@Override
diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java
index 87710fb..9d636f9 100644
--- a/main/src/cgeo/geocaching/cgData.java
+++ b/main/src/cgeo/geocaching/cgData.java
@@ -14,6 +14,7 @@ import cgeo.geocaching.files.LocalStorage;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
import org.apache.commons.collections.CollectionUtils;
@@ -310,17 +311,17 @@ public class cgData {
database = null;
}
- private static File getBackupFile() {
+ public static File getBackupFileInternal() {
return new File(LocalStorage.getStorage(), "cgeo.sqlite");
}
- public static String backupDatabase() {
+ public static String backupDatabaseInternal() {
if (!LocalStorage.isExternalStorageAvailable()) {
Log.w("Database wasn't backed up: no external memory");
return null;
}
- final File target = getBackupFile();
+ final File target = getBackupFileInternal();
closeDb();
final boolean backupDone = LocalStorage.copy(databasePath(), target);
init();
@@ -351,7 +352,9 @@ public class cgData {
return false;
}
- source.delete();
+ if (!FileUtils.delete(source)) {
+ Log.e("Original database could not be deleted during move");
+ }
Settings.setDbOnSDCard(!Settings.isDbOnSDCard());
Log.i("Database was moved to " + target);
init();
@@ -370,18 +373,13 @@ public class cgData {
return databasePath(Settings.isDbOnSDCard());
}
- public static File getRestoreFile() {
- final File fileSourceFile = getBackupFile();
- return fileSourceFile.exists() ? fileSourceFile : null;
- }
-
- public static boolean restoreDatabase() {
+ public static boolean restoreDatabaseInternal() {
if (!LocalStorage.isExternalStorageAvailable()) {
Log.w("Database wasn't restored: no external memory");
return false;
}
- final File sourceFile = getBackupFile();
+ final File sourceFile = getBackupFileInternal();
closeDb();
final boolean restoreDone = LocalStorage.copy(sourceFile, databasePath());
init();
@@ -409,7 +407,7 @@ public class cgData {
public SQLiteDatabase openOrCreateDatabase(String name, int mode,
CursorFactory factory) {
final File file = new File(name);
- file.getParentFile().mkdirs();
+ FileUtils.mkdirs(file.getParentFile());
return SQLiteDatabase.openOrCreateDatabase(file, factory);
}
@@ -778,7 +776,7 @@ public class cgData {
final File[] wrongFiles = dir.listFiles(filter);
if (wrongFiles != null) {
for (final File wrongFile : wrongFiles) {
- wrongFile.delete();
+ FileUtils.deleteIgnoringFailure(wrongFile);
}
}
}
@@ -828,7 +826,7 @@ public class cgData {
for (final File file : LocalStorage.getStorageSec().listFiles()) {
if (file.isDirectory()) {
// This will silently fail if the directory is not empty.
- file.delete();
+ FileUtils.deleteIgnoringFailure(file);
}
}
}
@@ -2748,8 +2746,6 @@ public class cgData {
/**
* checks if this is a newly created database
- *
- * @return
*/
public static boolean isNewlyCreatedDatebase() {
return newlyCreatedDatabase;
@@ -2762,6 +2758,10 @@ public class cgData {
newlyCreatedDatabase = false;
}
+ /**
+ * Creates the WHERE clause for matching multiple geocodes. This automatically converts all given codes to
+ * UPPERCASE.
+ */
private static StringBuilder whereGeocodeIn(Set<String> geocodes) {
final StringBuilder where = new StringBuilder();
@@ -2771,7 +2771,7 @@ public class cgData {
if (all.length() > 0) {
all.append(',');
}
- all.append(DatabaseUtils.sqlEscapeString(geocode));
+ all.append(DatabaseUtils.sqlEscapeString(StringUtils.upperCase(geocode)));
}
where.append("geocode in (").append(all).append(')');
@@ -3000,7 +3000,7 @@ public class cgData {
for (String geocode : cachedGeocodes) {
if (connector.canHandle(geocode)) {
Geocache geocache = cacheCache.getCacheFromCache(geocode);
- if (geocache.getZoomLevel() <= maxZoom) {
+ if (geocache.getCoordZoomLevel() <= maxZoom) {
boolean found = false;
for (Tile tile : tiles) {
if (tile.containsPoint(geocache)) {
diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/cgeoapplication.java
index fd5f714..5a793f5 100644
--- a/main/src/cgeo/geocaching/cgeoapplication.java
+++ b/main/src/cgeo/geocaching/cgeoapplication.java
@@ -25,7 +25,11 @@ public class cgeoapplication extends Application {
private static cgeoapplication instance;
public cgeoapplication() {
- instance = this;
+ setInstance(this);
+ }
+
+ private static void setInstance(final cgeoapplication application) {
+ instance = application;
}
public static cgeoapplication getInstance() {
@@ -86,39 +90,6 @@ public class cgeoapplication extends Application {
}
/**
- * restore the database in a new thread, showing a progress window
- *
- * @param fromActivity
- * calling activity
- */
- public void restoreDatabase(final Activity fromActivity) {
- final Resources res = this.getResources();
- final ProgressDialog dialog = ProgressDialog.show(fromActivity, res.getString(R.string.init_backup_restore), res.getString(R.string.init_restore_running), true, false);
- final AtomicBoolean atomic = new AtomicBoolean(false);
- Thread restoreThread = new Thread() {
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- dialog.dismiss();
- boolean restored = atomic.get();
- String message = restored ? res.getString(R.string.init_restore_success) : res.getString(R.string.init_restore_failed);
- ActivityMixin.helpDialog(fromActivity, res.getString(R.string.init_backup_restore), message);
- if (fromActivity instanceof MainActivity) {
- ((MainActivity) fromActivity).updateCacheCounter();
- }
- }
- };
-
- @Override
- public void run() {
- atomic.set(cgData.restoreDatabase());
- handler.sendMessage(handler.obtainMessage());
- }
- };
- restoreThread.start();
- }
-
- /**
* Register an observer to receive GeoData information.
* <br/>
* If there is a chance that no observers are registered before this
diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java
index 5d7841d..304aabe 100644
--- a/main/src/cgeo/geocaching/cgeocaches.java
+++ b/main/src/cgeo/geocaching/cgeocaches.java
@@ -396,6 +396,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
};
private AbstractSearchLoader currentLoader;
+ private String newListName = StringUtils.EMPTY;
public cgeocaches() {
super(true);
@@ -503,7 +504,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);
- if (newSearch != null && newSearch.getTotal() != search.getTotal()) {
+ if (newSearch.getTotal() != search.getTotal()) {
refreshCurrentList();
}
}
@@ -717,7 +718,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
invalidateOptionsMenuCompatible();
return false;
case MENU_CREATE_LIST:
- new StoredList.UserInterface(this).promptForListCreation(null);
+ new StoredList.UserInterface(this).promptForListCreation(null, newListName);
invalidateOptionsMenuCompatible();
return false;
case MENU_DROP_LIST:
@@ -927,7 +928,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
adapter.setSelectMode(false);
refreshCurrentList();
}
- }, true, listId);
+ }, true, listId, newListName);
break;
case MENU_STORE_CACHE:
case MENU_REFRESH:
@@ -1082,7 +1083,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
public void run(final Integer selectedListId) {
refreshStored(caches, selectedListId);
}
- }, true, StoredList.TEMPORARY_LIST_ID);
+ }, true, StoredList.TEMPORARY_LIST_ID, newListName);
} else {
refreshStored(caches, this.listId);
}
@@ -1481,9 +1482,9 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
currentLoader.reset();
((OfflineGeocacheListLoader) currentLoader).setListId(listId);
((OfflineGeocacheListLoader) currentLoader).setSearchCenter(coords);
+ adapter.setComparator(null); // delete current sorting
currentLoader.startLoading();
-
invalidateOptionsMenuCompatible();
}
@@ -1719,13 +1720,13 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
break;
case KEYWORD:
final String keyword = extras.getString(Intents.EXTRA_KEYWORD);
- title = keyword;
+ rememberTerm(keyword);
loader = new KeywordGeocacheListLoader(app, keyword);
break;
case ADDRESS:
final String address = extras.getString(Intents.EXTRA_ADDRESS);
if (StringUtils.isNotBlank(address)) {
- title = address;
+ rememberTerm(address);
} else {
title = coords.toString();
}
@@ -1738,12 +1739,12 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
break;
case USERNAME:
final String username = extras.getString(Intents.EXTRA_USERNAME);
- title = username;
+ rememberTerm(username);
loader = new UsernameGeocacheListLoader(app, username);
break;
case OWNER:
final String ownerName = extras.getString(Intents.EXTRA_USERNAME);
- title = ownerName;
+ rememberTerm(ownerName);
loader = new OwnerGeocacheListLoader(app, ownerName);
break;
case MAP:
@@ -1771,6 +1772,13 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
return loader;
}
+ private void rememberTerm(String term) {
+ // set the title of the activity
+ title = term;
+ // and remember this term for potential use in list creation
+ newListName = term;
+ }
+
@Override
public void onLoadFinished(Loader<SearchResult> arg0, SearchResult searchIn) {
// The database search was moved into the UI call intentionally. If this is done before the runOnUIThread,
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
index c2aeffd..e93df14 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
@@ -127,7 +127,7 @@ public final class GCConstants {
public final static Pattern PATTERN_SEARCH_TOTALCOUNT = Pattern.compile("<span>Total Records\\D*(\\d+)<");
public final static Pattern PATTERN_SEARCH_RECAPTCHA = Pattern.compile("<script[^>]*src=\"[^\"]*/recaptcha/api/challenge\\?k=([^\"]+)\"[^>]*>");
public final static Pattern PATTERN_SEARCH_RECAPTCHACHALLENGE = Pattern.compile("challenge : '([^']+)'");
- public final static Pattern PATTERN_SEARCH_HIDDEN_DATE = Pattern.compile("<span class=\"small\">([\\d-/]{6,10})</span>");
+ public final static Pattern PATTERN_SEARCH_HIDDEN_DATE = Pattern.compile("<td valign=\"top\"[^<]+<span class=\"small\">([^<]+)</span>");
/**
* Patterns for waypoints
diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index d243306..4fdde56 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCMap.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -209,16 +209,15 @@ public class GCMap {
cache.setReliableLatLon(false);
cache.setGeocode(id);
cache.setName(nameCache.get(id));
- cache.setZoomlevel(tile.getZoomlevel());
- cache.setCoords(tile.getCoord(xy));
+ cache.setCoords(tile.getCoord(xy), tile.getZoomLevel());
if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && bitmap != null) {
for (UTFGridPosition singlePos : singlePositions.get(id)) {
- if (IconDecoder.parseMapPNG(cache, bitmap, singlePos, tile.getZoomlevel())) {
+ if (IconDecoder.parseMapPNG(cache, bitmap, singlePos, tile.getZoomLevel())) {
break; // cache parsed
}
}
} else {
- cache.setType(CacheType.UNKNOWN);
+ cache.setType(CacheType.UNKNOWN, tile.getZoomLevel());
}
boolean exclude = false;
@@ -296,7 +295,7 @@ public class GCMap {
final Set<Tile> tiles = Tile.getTilesForViewport(viewport);
if (Settings.isDebug()) {
- searchResult.setUrl(new StringBuilder().append(tiles.iterator().next().getZoomlevel()).append(Formatter.SEPARATOR).append(searchResult.getUrl()).toString());
+ searchResult.setUrl(new StringBuilder().append(tiles.iterator().next().getZoomLevel()).append(Formatter.SEPARATOR).append(searchResult.getUrl()).toString());
}
for (Tile tile : tiles) {
@@ -305,7 +304,7 @@ public class GCMap {
final Parameters params = new Parameters(
"x", String.valueOf(tile.getX()),
"y", String.valueOf(tile.getY()),
- "z", String.valueOf(tile.getZoomlevel()),
+ "z", String.valueOf(tile.getZoomLevel()),
"ep", "1",
"app", "cgeo");
if (tokens != null) {
@@ -321,7 +320,7 @@ public class GCMap {
} else if (Settings.getCacheType() == CacheType.MYSTERY) {
params.put("ect", "9,5,3,6,453,13,1304,137,11,4,2,1858");
}
- if (tile.getZoomlevel() != 14) {
+ if (tile.getZoomLevel() != 14) {
params.put("_", String.valueOf(System.currentTimeMillis()));
}
// TODO: other types t.b.d
@@ -341,7 +340,7 @@ public class GCMap {
Log.w("GCMap.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")");
} else {
final SearchResult search = GCMap.parseMapJSON(data, tile, bitmap, strategy);
- if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) {
+ if (CollectionUtils.isEmpty(search.getGeocodes())) {
Log.e("GCMap.searchByViewport: No cache parsed for viewport " + viewport);
}
else {
@@ -359,7 +358,7 @@ public class GCMap {
}
// Check for vanished found caches
- if (tiles.iterator().next().getZoomlevel() >= Tile.ZOOMLEVEL_MIN_PERSONALIZED) {
+ if (tiles.iterator().next().getZoomLevel() >= Tile.ZOOMLEVEL_MIN_PERSONALIZED) {
searchResult.addFilteredGeocodes(cgData.getCachedMissingFromSearch(searchResult, tiles, GCConnector.getInstance(), Tile.ZOOMLEVEL_MIN_PERSONALIZED - 1));
}
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index 7dc048a..0dc4242 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -529,9 +529,7 @@ public abstract class GCParser {
if (result != null) {
// replace linebreak and paragraph tags
final String hint = GCConstants.PATTERN_LINEBREAK.matcher(result).replaceAll("\n");
- if (hint != null) {
- cache.setHint(StringUtils.replace(hint, "</p>", "").trim());
- }
+ cache.setHint(StringUtils.replace(hint, "</p>", "").trim());
}
cache.checkFields();
@@ -766,7 +764,7 @@ public abstract class GCParser {
public static SearchResult searchByNextPage(final SearchResult search, boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) {
if (search == null) {
- return search;
+ return null;
}
final String[] viewstates = search.getViewstates();
@@ -1131,9 +1129,9 @@ public abstract class GCParser {
* @return status code to indicate success or failure
*/
public static ImmutablePair<StatusCode, String> uploadLogImage(final String logId, final String caption, final String description, final Uri imageUri) {
- final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/seek/upload.aspx").build().toString();
+ final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/seek/upload.aspx").encodedQuery("LID=" + logId).build().toString();
- final String page = Login.getRequestLogged(uri, new Parameters("LID=", logId));
+ final String page = Login.getRequestLogged(uri, null);
if (StringUtils.isBlank(page)) {
Log.e("GCParser.uploadLogImage: No data from server");
return new ImmutablePair<StatusCode, String>(StatusCode.UNKNOWN_ERROR, null);
@@ -1717,7 +1715,7 @@ public abstract class GCParser {
try {
final Integer ctl = Integer.valueOf(trackableMatcher.group(3));
final Integer id = Integer.valueOf(trackableMatcher.group(5));
- if (trackCode != null && name != null && ctl != null && id != null) {
+ if (trackCode != null && ctl != null && id != null) {
final TrackableLog entry = new TrackableLog(trackCode, name, id, ctl);
Log.i("Trackable in inventory (#" + entry.ctl + "/" + entry.id + "): " + entry.trackCode + " - " + entry.name);
diff --git a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java
index ed44392..c7b470a 100644
--- a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java
+++ b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.connector.gc;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.enumerations.CacheType;
+import cgeo.geocaching.settings.Settings;
import android.graphics.Bitmap;
@@ -87,19 +87,19 @@ public abstract class IconDecoder {
if (count > 1) { // 2 pixels need to detect same type and we say good to go
switch (type) {
case CT_TRADITIONAL:
- cache.setType(CacheType.TRADITIONAL);
+ cache.setType(CacheType.TRADITIONAL, zoomlevel);
return true;
case CT_MULTI:
- cache.setType(CacheType.MULTI);
+ cache.setType(CacheType.MULTI, zoomlevel);
return true;
case CT_MYSTERY:
- cache.setType(CacheType.MYSTERY);
+ cache.setType(CacheType.MYSTERY, zoomlevel);
return true;
case CT_EVENT:
- cache.setType(CacheType.EVENT);
+ cache.setType(CacheType.EVENT, zoomlevel);
return true;
case CT_EARTH:
- cache.setType(CacheType.EARTH);
+ cache.setType(CacheType.EARTH, zoomlevel);
return true;
case CT_FOUND:
cache.setFound(true);
@@ -108,22 +108,22 @@ public abstract class IconDecoder {
cache.setOwnerUserId(Settings.getUsername());
return true;
case CT_MEGAEVENT:
- cache.setType(CacheType.MEGA_EVENT);
+ cache.setType(CacheType.MEGA_EVENT, zoomlevel);
return true;
case CT_CITO:
- cache.setType(CacheType.CITO);
+ cache.setType(CacheType.CITO, zoomlevel);
return true;
case CT_WEBCAM:
- cache.setType(CacheType.WEBCAM);
+ cache.setType(CacheType.WEBCAM, zoomlevel);
return true;
case CT_WHERIGO:
- cache.setType(CacheType.WHERIGO);
+ cache.setType(CacheType.WHERIGO, zoomlevel);
return true;
case CT_VIRTUAL:
- cache.setType(CacheType.VIRTUAL);
+ cache.setType(CacheType.VIRTUAL, zoomlevel);
return true;
case CT_LETTERBOX:
- cache.setType(CacheType.LETTERBOX);
+ cache.setType(CacheType.LETTERBOX, zoomlevel);
return true;
}
}
diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java
index 2629339..0d8fb05 100644
--- a/main/src/cgeo/geocaching/connector/gc/Login.java
+++ b/main/src/cgeo/geocaching/connector/gc/Login.java
@@ -30,20 +30,22 @@ import java.util.Map;
public abstract class Login {
+ private static final String DEFAULT_CUSTOM_DATE_FORMAT = "MM/dd/yyyy";
+
private final static String ENGLISH = "<a href=\"#\">English&#9660;</a>";
// false = not logged in
private static boolean actualLoginStatus = false;
- private static String actualUserName = "";
+ private static String actualUserName = StringUtils.EMPTY;
private static int actualCachesFound = -1;
- private static String actualStatus = "";
+ private static String actualStatus = StringUtils.EMPTY;
- private final static Map<String, SimpleDateFormat> gcCustomDateFormats;
+ private final static Map<String, SimpleDateFormat> GC_CUSTOM_DATE_FORMATS;
public static final String LANGUAGE_CHANGE_URI = "http://www.geocaching.com/my/souvenirs.aspx";
static {
final String[] formats = new String[] {
- "MM/dd/yyyy",
+ DEFAULT_CUSTOM_DATE_FORMAT,
"yyyy-MM-dd",
"yyyy/MM/dd",
"dd/MMM/yyyy",
@@ -58,7 +60,7 @@ public abstract class Login {
map.put(format, new SimpleDateFormat(format, Locale.ENGLISH));
}
- gcCustomDateFormats = Collections.unmodifiableMap(map);
+ GC_CUSTOM_DATE_FORMATS = Collections.unmodifiableMap(map);
}
public static StatusCode login() {
@@ -321,14 +323,14 @@ public abstract class Login {
final String trimmed = input.trim();
- if (gcCustomDateFormats.containsKey(format)) {
+ if (GC_CUSTOM_DATE_FORMATS.containsKey(format)) {
try {
- return gcCustomDateFormats.get(format).parse(trimmed);
+ return GC_CUSTOM_DATE_FORMATS.get(format).parse(trimmed);
} catch (final ParseException e) {
}
}
- for (final SimpleDateFormat sdf : gcCustomDateFormats.values()) {
+ for (final SimpleDateFormat sdf : GC_CUSTOM_DATE_FORMATS.values()) {
try {
return sdf.parse(trimmed);
} catch (final ParseException e) {
@@ -344,11 +346,11 @@ public abstract class Login {
public static SimpleDateFormat getCustomGcDateFormat() {
final String format = Settings.getGcCustomDate();
- if (gcCustomDateFormats.containsKey(format)) {
- return gcCustomDateFormats.get(format);
+ if (GC_CUSTOM_DATE_FORMATS.containsKey(format)) {
+ return GC_CUSTOM_DATE_FORMATS.get(format);
}
- return gcCustomDateFormats.get("MM/dd/yyyy");
+ return GC_CUSTOM_DATE_FORMATS.get(DEFAULT_CUSTOM_DATE_FORMAT);
}
/**
diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java
index 3177f2c..4ed53c9 100644
--- a/main/src/cgeo/geocaching/connector/gc/Tile.java
+++ b/main/src/cgeo/geocaching/connector/gc/Tile.java
@@ -50,7 +50,7 @@ public class Tile {
private final int tileX;
private final int tileY;
- private final int zoomlevel;
+ private final int zoomLevel;
private final Viewport viewPort;
public Tile(Geopoint origin, int zoomlevel) {
@@ -59,7 +59,7 @@ public class Tile {
private Tile(int tileX, int tileY, int zoomlevel) {
- this.zoomlevel = clippedZoomlevel(zoomlevel);
+ this.zoomLevel = clippedZoomlevel(zoomlevel);
this.tileX = tileX;
this.tileY = tileY;
@@ -67,8 +67,8 @@ public class Tile {
viewPort = new Viewport(getCoord(new UTFGridPosition(0, 0)), getCoord(new UTFGridPosition(63, 63)));
}
- public int getZoomlevel() {
- return zoomlevel;
+ public int getZoomLevel() {
+ return zoomLevel;
}
private static int clippedZoomlevel(int zoomlevel) {
@@ -120,14 +120,14 @@ public class Tile {
double pixX = tileX * TILE_SIZE + pos.x * 4;
double pixY = tileY * TILE_SIZE + pos.y * 4;
- double lonDeg = ((360.0 * pixX) / NUMBER_OF_PIXELS[this.zoomlevel]) - 180.0;
- double latRad = Math.atan(Math.sinh(Math.PI * (1 - 2 * pixY / NUMBER_OF_PIXELS[this.zoomlevel])));
+ double lonDeg = ((360.0 * pixX) / NUMBER_OF_PIXELS[this.zoomLevel]) - 180.0;
+ double latRad = Math.atan(Math.sinh(Math.PI * (1 - 2 * pixY / NUMBER_OF_PIXELS[this.zoomLevel])));
return new Geopoint(Math.toDegrees(latRad), lonDeg);
}
@Override
public String toString() {
- return String.format(Locale.US, "(%d/%d), zoom=%d", tileX, tileY, zoomlevel);
+ return String.format(Locale.US, "(%d/%d), zoom=%d", tileX, tileY, zoomLevel);
}
/**
@@ -225,7 +225,7 @@ public class Tile {
}
return (this.tileX == ((Tile) o).tileX)
&& (this.tileY == ((Tile) o).tileY)
- && (this.zoomlevel == ((Tile) o).zoomlevel);
+ && (this.zoomLevel == ((Tile) o).zoomLevel);
}
@Override
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index be7b3a4..139a48e 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -247,9 +247,7 @@ final class OkapiClient {
while (keys.hasNext()) {
final String key = keys.next();
final Geocache cache = parseSmallCache(cachesResponse.getJSONObject(key));
- if (cache != null) {
- caches.add(cache);
- }
+ caches.add(cache);
}
return caches;
}
diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java
index 38cd43e..d0040a9 100644
--- a/main/src/cgeo/geocaching/export/FieldnoteExport.java
+++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java
@@ -12,6 +12,7 @@ import cgeo.geocaching.network.Parameters;
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;
@@ -82,7 +83,7 @@ class FieldnoteExport extends AbstractExport {
final CheckBox onlyNewOption = (CheckBox) layout.findViewById(R.id.onlynew);
if (Settings.getFieldnoteExportDate() > 0) {
- onlyNewOption.setText(getString(R.string.export_fieldnotes_onlynew) + "\n(" + Formatter.formatShortDateTime(activity, Settings.getFieldnoteExportDate()) + ')');
+ onlyNewOption.setText(getString(R.string.export_fieldnotes_onlynew) + "\n(" + Formatter.formatShortDateTime(Settings.getFieldnoteExportDate()) + ')');
}
builder.setPositiveButton(R.string.export, new DialogInterface.OnClickListener() {
@@ -134,7 +135,7 @@ class FieldnoteExport extends AbstractExport {
for (final Geocache cache : caches) {
if (cache.isLogOffline()) {
final LogEntry log = cgData.loadLogOffline(cache.getGeocode());
- if (!onlyNew || onlyNew && log.date > Settings.getFieldnoteExportDate()) {
+ if (!onlyNew || log.date > Settings.getFieldnoteExportDate()) {
appendFieldNote(fieldNoteBuffer, cache, log);
}
}
@@ -151,7 +152,7 @@ class FieldnoteExport extends AbstractExport {
return false;
}
- exportLocation.mkdirs();
+ FileUtils.mkdirs(exportLocation);
final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".txt");
diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java
index 61be3c5..821a3f6 100644
--- a/main/src/cgeo/geocaching/export/GpxExport.java
+++ b/main/src/cgeo/geocaching/export/GpxExport.java
@@ -1,13 +1,16 @@
package cgeo.geocaching.export;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.R;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.AsyncTaskWithProgress;
+import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
+import org.apache.commons.lang3.CharEncoding;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -22,8 +25,9 @@ import android.widget.TextView;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileWriter;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -106,6 +110,12 @@ class GpxExport extends AbstractExport {
this.activity = activity;
}
+ private File getExportFile() {
+ final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
+ final Date now = new Date();
+ return FileUtils.getUniqueNamedFile(Settings.getGpxExportDir() + File.separatorChar + "export_" + fileNameDateFormat.format(now) + ".gpx");
+ }
+
@Override
protected File doInBackgroundInternal(String[] geocodes) {
// quick check for being able to write the GPX file
@@ -117,18 +127,17 @@ class GpxExport extends AbstractExport {
setMessage(cgeoapplication.getInstance().getResources().getQuantityString(R.plurals.cache_counts, allGeocodes.size(), allGeocodes.size()));
- final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
- final File exportFile = new File(Settings.getGpxExportDir() + File.separatorChar + "export_" + fileNameDateFormat.format(new Date()) + ".gpx");
+ final File exportFile = getExportFile();
BufferedWriter writer = null;
try {
final File exportLocation = new File(Settings.getGpxExportDir());
- exportLocation.mkdirs();
+ FileUtils.mkdirs(exportLocation);
- writer = new BufferedWriter(new FileWriter(exportFile));
+ writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(exportFile), CharEncoding.UTF_8));
new GpxSerializer().writeGPX(allGeocodes, writer, new GpxSerializer.ProgressListener() {
@Override
- public void publishProgress(int countExported) {
+ public void publishProgress(final int countExported) {
ExportTask.this.publishProgress(countExported);
}
});
@@ -142,9 +151,9 @@ class GpxExport extends AbstractExport {
// Ignore double error
}
}
- // delete partial gpx file on error
+ // delete partial GPX file on error
if (exportFile.exists()) {
- exportFile.delete();
+ FileUtils.deleteIgnoringFailure(exportFile);
}
return null;
diff --git a/main/src/cgeo/geocaching/export/GpxSerializer.java b/main/src/cgeo/geocaching/export/GpxSerializer.java
index 2d25296..1e39be4 100644
--- a/main/src/cgeo/geocaching/export/GpxSerializer.java
+++ b/main/src/cgeo/geocaching/export/GpxSerializer.java
@@ -11,6 +11,7 @@ import cgeo.geocaching.utils.TextUtils;
import cgeo.geocaching.utils.XmlUtils;
import cgeo.org.kxml2.io.KXmlSerializer;
+import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
import org.xmlpull.v1.XmlSerializer;
@@ -56,7 +57,7 @@ public final class GpxSerializer {
this.progressListener = progressListener;
gpx.setOutput(writer);
- gpx.startDocument("UTF-8", true);
+ gpx.startDocument(CharEncoding.UTF_8, true);
gpx.setPrefix("", PREFIX_GPX);
gpx.setPrefix("xsi", PREFIX_XSI);
gpx.setPrefix("groundspeak", PREFIX_GROUNDSPEAK);
diff --git a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
index 8b02eeb..b0aba58 100644
--- a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
+++ b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
@@ -5,7 +5,6 @@ import cgeo.geocaching.R;
import cgeo.geocaching.StoredList;
import cgeo.geocaching.activity.AbstractListActivity;
import cgeo.geocaching.utils.FileUtils;
-import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.Log;
import org.apache.commons.collections.CollectionUtils;
@@ -19,10 +18,7 @@ import android.os.Handler;
import android.os.Message;
import android.widget.ArrayAdapter;
-import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -55,15 +51,11 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
}
private String getDefaultFolders() {
- StringBuilder sb = new StringBuilder();
- for (File f : getBaseFolders()) {
- String fName = f.getPath();
- if (sb.length() > 0) {
- sb.append('\n');
- }
- sb.append(fName);
+ final ArrayList<String> names = new ArrayList<String>();
+ for (File dir : getExistingBaseFolders()) {
+ names.add(dir.getPath());
}
- return sb.toString();
+ return StringUtils.join(names, '\n');
}
};
@@ -160,19 +152,16 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
try {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
boolean loaded = false;
- for (final File dir : getBaseFolders())
- {
- if (dir.exists() && dir.isDirectory()) {
- FileUtils.listDir(list, dir,selector,changeWaitDialogHandler);
- if (!list.isEmpty()) {
- loaded = true;
- break;
- }
+ for (final File dir : getExistingBaseFolders()) {
+ FileUtils.listDir(list, dir, selector, changeWaitDialogHandler);
+ if (!list.isEmpty()) {
+ loaded = true;
+ break;
}
}
if (!loaded) {
changeWaitDialogHandler.sendMessage(Message.obtain(changeWaitDialogHandler, MSG_SEARCH_WHOLE_SD_CARD, Environment.getExternalStorageDirectory().getName()));
- listDirs(list, getStorages(), selector, changeWaitDialogHandler);
+ listDirs(list, LocalStorage.getStorages(), selector, changeWaitDialogHandler);
}
} else {
Log.w("No external media mounted.");
@@ -202,49 +191,6 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
}
}
- /*
- * Get all storages available on the device.
- * Will include paths like /mnt/sdcard /mnt/usbdisk /mnt/ext_card /mnt/sdcard/ext_card
- */
- protected static List<File> getStorages() {
-
- String extStorage = Environment.getExternalStorageDirectory().getAbsolutePath();
- List<File> storages = new ArrayList<File>();
- storages.add(new File(extStorage));
- File file = new File("/system/etc/vold.fstab");
- if (file.canRead()) {
- FileReader fr = null;
- BufferedReader br = null;
- try {
- fr = new FileReader(file);
- br = new BufferedReader(fr);
- String s = br.readLine();
- while (s != null) {
- if (s.startsWith("dev_mount")) {
- String[] tokens = StringUtils.split(s);
- if (tokens.length >= 3) {
- String path = tokens[2]; // mountpoint
- if (!extStorage.equals(path)) {
- File directory = new File(path);
- if (directory.exists() && directory.isDirectory()) {
- storages.add(directory);
- }
- }
- }
- }
- s = br.readLine();
- }
- } catch (IOException e) {
- Log.e("Could not get additional mount points for user content. " +
- "Proceeding with external storage only (" + extStorage + ")");
- } finally {
- IOUtils.closeQuietly(fr);
- IOUtils.closeQuietly(br);
- }
- }
- return storages;
- }
-
/**
* Check if a filename belongs to the AbstractFileListActivity. This implementation checks for file extensions.
* Subclasses may override this method to filter out specific files.
@@ -261,6 +207,16 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
return false;
}
+ protected List<File> getExistingBaseFolders() {
+ ArrayList<File> result = new ArrayList<File>();
+ for (final File dir : getBaseFolders()) {
+ if (dir.exists() && dir.isDirectory()) {
+ result.add(dir);
+ }
+ }
+ return result;
+ }
+
protected AbstractFileListActivity(final String extension) {
setExtensions(new String[] { extension });
}
diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java
index ec09433..57f586e 100644
--- a/main/src/cgeo/geocaching/files/LocalStorage.java
+++ b/main/src/cgeo/geocaching/files/LocalStorage.java
@@ -2,6 +2,7 @@ package cgeo.geocaching.files;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.utils.CryptUtils;
+import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.Log;
@@ -14,6 +15,7 @@ import android.os.Environment;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -24,12 +26,14 @@ import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
/**
* Handle local storage issues on phone and SD card.
*
*/
-public class LocalStorage {
+public final class LocalStorage {
public static final String HEADER_LAST_MODIFIED = "last-modified";
public static final String HEADER_ETAG = "etag";
@@ -39,6 +43,10 @@ public class LocalStorage {
private static File internalStorageBase;
+ private LocalStorage() {
+ // utility class
+ }
+
/**
* Return the primary storage cache root (external media if mounted, phone otherwise).
*
@@ -159,7 +167,7 @@ public class LocalStorage {
private static File buildFile(final File base, final String fileName, final boolean isUrl, final boolean createDirs) {
if (createDirs) {
- base.mkdirs();
+ FileUtils.mkdirs(base);
}
return new File(base, isUrl ? CryptUtils.md5(fileName) + getExtension(fileName) : fileName);
}
@@ -194,7 +202,7 @@ public class LocalStorage {
final Header header = response != null ? response.getFirstHeader(name) : null;
final File file = filenameForHeader(baseFile, name);
if (header == null) {
- file.delete();
+ FileUtils.deleteIgnoringFailure(file);
} else {
saveToFile(new ByteArrayInputStream(header.getValue().getBytes()), file);
}
@@ -256,15 +264,15 @@ public class LocalStorage {
final boolean written = copy(inputStream, fos);
fos.close();
if (!written) {
- targetFile.delete();
+ FileUtils.deleteIgnoringFailure(targetFile);
}
return written;
} finally {
- inputStream.close();
+ IOUtils.closeQuietly(inputStream);
}
} catch (IOException e) {
Log.e("LocalStorage.saveToFile", e);
- targetFile.delete();
+ FileUtils.deleteIgnoringFailure(targetFile);
}
return false;
}
@@ -279,7 +287,7 @@ public class LocalStorage {
* @return true if the copy happened without error, false otherwise
*/
public static boolean copy(final File source, final File destination) {
- destination.getParentFile().mkdirs();
+ FileUtils.mkdirs(destination.getParentFile());
InputStream input = null;
OutputStream output = null;
@@ -288,9 +296,10 @@ public class LocalStorage {
output = new BufferedOutputStream(new FileOutputStream(destination));
} catch (FileNotFoundException e) {
Log.e("LocalStorage.copy: could not open file", e);
+ return false;
+ } finally {
IOUtils.closeQuietly(input);
IOUtils.closeQuietly(output);
- return false;
}
boolean copyDone = copy(input, output);
@@ -338,12 +347,12 @@ public class LocalStorage {
if (file.isDirectory()) {
deleteDirectory(file);
} else {
- file.delete();
+ FileUtils.delete(file);
}
}
}
- return path.delete();
+ return FileUtils.delete(path);
}
/**
@@ -361,7 +370,7 @@ public class LocalStorage {
}
for (final File file : filesToDelete) {
try {
- if (!file.delete()) {
+ if (!FileUtils.delete(file)) {
Log.w("LocalStorage.deleteFilesPrefix: Can't delete file " + file.getName());
}
} catch (Exception e) {
@@ -389,4 +398,47 @@ public class LocalStorage {
};
return LocalStorage.getStorageDir(geocode).listFiles(filter);
}
+
+ /**
+ * Get all storages available on the device.
+ * Will include paths like /mnt/sdcard /mnt/usbdisk /mnt/ext_card /mnt/sdcard/ext_card
+ */
+ public static List<File> getStorages() {
+
+ String extStorage = Environment.getExternalStorageDirectory().getAbsolutePath();
+ List<File> storages = new ArrayList<File>();
+ storages.add(new File(extStorage));
+ File file = new File("/system/etc/vold.fstab");
+ if (file.canRead()) {
+ FileReader fr = null;
+ BufferedReader br = null;
+ try {
+ fr = new FileReader(file);
+ br = new BufferedReader(fr);
+ String s = br.readLine();
+ while (s != null) {
+ if (s.startsWith("dev_mount")) {
+ String[] tokens = StringUtils.split(s);
+ if (tokens.length >= 3) {
+ String path = tokens[2]; // mountpoint
+ if (!extStorage.equals(path)) {
+ File directory = new File(path);
+ if (directory.exists() && directory.isDirectory()) {
+ storages.add(directory);
+ }
+ }
+ }
+ }
+ s = br.readLine();
+ }
+ } catch (IOException e) {
+ Log.e("Could not get additional mount points for user content. " +
+ "Proceeding with external storage only (" + extStorage + ")");
+ } finally {
+ IOUtils.closeQuietly(fr);
+ IOUtils.closeQuietly(br);
+ }
+ }
+ return storages;
+ }
}
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index f892622..0817170 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -156,12 +156,12 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private ScaleOverlay overlayScale = null;
private PositionOverlay overlayPosition = null;
// data for overlays
- private static final int[][] INSET_RELIABLE = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; // center, 33x40 / 45x51
- private static final int[][] INSET_TYPE = { { 5, 8, 6, 10 }, { 4, 4, 5, 11 } }; // center, 22x22 / 36x36
- private static final int[][] INSET_OWN = { { 21, 0, 0, 26 }, { 25, 0, 0, 35 } }; // top right, 12x12 / 16x16
- private static final int[][] INSET_FOUND = { { 0, 0, 21, 28 }, { 0, 0, 25, 35 } }; // top left, 12x12 / 16x16
- private static final int[][] INSET_USERMODIFIEDCOORDS = { { 21, 28, 0, 0 }, { 19, 25, 0, 0 } }; // bottom right, 12x12 / 26x26
- private static final int[][] INSET_PERSONALNOTE = { { 0, 28, 21, 0 }, { 0, 25, 19, 0 } }; // bottom left, 12x12 / 26x26
+ private static final int[][] INSET_RELIABLE = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; // center, 33x40 / 45x51 / 60x68
+ private static final int[][] INSET_TYPE = { { 5, 8, 6, 10 }, { 4, 4, 5, 11 }, { 4, 4, 5, 11 } }; // center, 22x22 / 36x36
+ private static final int[][] INSET_OWN = { { 21, 0, 0, 26 }, { 25, 0, 0, 35 }, { 40, 0, 0, 48 } }; // top right, 12x12 / 16x16 / 20x20
+ private static final int[][] INSET_FOUND = { { 0, 0, 21, 28 }, { 0, 0, 25, 35 }, { 0, 0, 40, 48 } }; // top left, 12x12 / 16x16 / 20x20
+ private static final int[][] INSET_USERMODIFIEDCOORDS = { { 21, 28, 0, 0 }, { 19, 25, 0, 0 }, { 25, 33, 0, 0 } }; // bottom right, 12x12 / 26x26 / 35x35
+ private static final int[][] INSET_PERSONALNOTE = { { 0, 28, 21, 0 }, { 0, 25, 19, 0 }, { 0, 33, 25, 0 } }; // bottom left, 12x12 / 26x26 / 35x35
private SparseArray<LayerDrawable> overlaysCache = new SparseArray<LayerDrawable>();
/** Count of caches currently visible */
@@ -1179,33 +1179,29 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens);
- if (searchResult != null) {
- downloaded = true;
- if (searchResult.getError() == StatusCode.NOT_LOGGED_IN && Settings.isGCConnectorActive()) {
- Login.login();
- tokens = null;
- } else {
- break;
- }
+ downloaded = true;
+ if (searchResult.getError() == StatusCode.NOT_LOGGED_IN && Settings.isGCConnectorActive()) {
+ Login.login();
+ tokens = null;
+ } else {
+ break;
}
count++;
} while (count < 2);
- if (searchResult != null) {
- Set<Geocache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
- CGeoMap.filter(result);
- // update the caches
- // 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));
- // new collection type needs to remove first to refresh
- caches.removeAll(result);
- caches.addAll(result);
- lastSearchResult = searchResult;
- }
+ Set<Geocache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
+ CGeoMap.filter(result);
+ // update the caches
+ // 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));
+ // new collection type needs to remove first to refresh
+ caches.removeAll(result);
+ caches.addAll(result);
+ lastSearchResult = searchResult;
//render
displayExecutor.execute(new DisplayRunnable(viewport));
@@ -1677,7 +1673,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
// background: disabled or not
final Drawable marker = getResources().getDrawable(cache.getMapMarkerId());
layers.add(marker);
- final int resolution = marker.getIntrinsicWidth() > 40 ? 1 : 0;
+ final int resolution = marker.getIntrinsicWidth() > 40 ? (marker.getIntrinsicWidth() > 50 ? 2 : 1) : 0;
// reliable or not
if (!cache.isReliableLatLon()) {
insets.add(INSET_RELIABLE[resolution]);
diff --git a/main/src/cgeo/geocaching/maps/PositionHistory.java b/main/src/cgeo/geocaching/maps/PositionHistory.java
new file mode 100644
index 0000000..9b090fc
--- /dev/null
+++ b/main/src/cgeo/geocaching/maps/PositionHistory.java
@@ -0,0 +1,63 @@
+package cgeo.geocaching.maps;
+
+import android.location.Location;
+
+import java.util.ArrayList;
+
+/**
+ * Map trail history
+ */
+public class PositionHistory {
+
+ /**
+ * minimum distance between two recorded points of the trail
+ */
+ private static final double MINIMUM_DISTANCE_METERS = 10.0;
+
+ /**
+ * maximum number of positions to remember
+ */
+ private static final int MAX_POSITIONS = 700;
+
+ private ArrayList<Location> history = new ArrayList<Location>();
+
+ /**
+ * Adds the current position to the trail history to be able to show the trail on the map.
+ */
+ void rememberTrailPosition(Location coordinates) {
+ if (coordinates.getAccuracy() >= 50f) {
+ return;
+ }
+ if (coordinates.getLatitude() == 0.0 && coordinates.getLatitude() == 0.0) {
+ return;
+ }
+ if (history.isEmpty()) {
+ history.add(coordinates);
+ return;
+ }
+
+ Location historyRecent = history.get(history.size() - 1);
+ if (historyRecent.distanceTo(coordinates) <= MINIMUM_DISTANCE_METERS) {
+ return;
+ }
+
+ history.add(coordinates);
+
+ // avoid running out of memory
+ final int itemsToRemove = getHistory().size() - MAX_POSITIONS;
+ if (itemsToRemove > 0) {
+ for (int i = 0; i < itemsToRemove; i++) {
+ getHistory().remove(0);
+ }
+ }
+ }
+
+ public ArrayList<Location> getHistory() {
+ return history;
+ }
+
+ public void setHistory(ArrayList<Location> history) {
+ this.history = history;
+ }
+
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/maps/PositionOverlay.java b/main/src/cgeo/geocaching/maps/PositionOverlay.java
index c3a0834..39f4987 100644
--- a/main/src/cgeo/geocaching/maps/PositionOverlay.java
+++ b/main/src/cgeo/geocaching/maps/PositionOverlay.java
@@ -1,7 +1,6 @@
package cgeo.geocaching.maps;
import cgeo.geocaching.R;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.maps.interfaces.GeneralOverlay;
import cgeo.geocaching.maps.interfaces.GeoPointImpl;
@@ -9,6 +8,7 @@ import cgeo.geocaching.maps.interfaces.MapItemFactory;
import cgeo.geocaching.maps.interfaces.MapProjectionImpl;
import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OverlayImpl;
+import cgeo.geocaching.settings.Settings;
import android.app.Activity;
import android.graphics.Bitmap;
@@ -37,10 +37,7 @@ public class PositionOverlay implements GeneralOverlay {
private int heightArrowHalf = 0;
private PaintFlagsDrawFilter setfil = null;
private PaintFlagsDrawFilter remfil = null;
- private Location historyRecent = null;
- private ArrayList<Location> history = new ArrayList<Location>();
- private Point historyPointN = new Point();
- private Point historyPointP = new Point();
+ private PositionHistory positionHistory = new PositionHistory();
private Activity activity;
private MapItemFactory mapItemFactory = null;
private OverlayImpl ovlImpl = null;
@@ -139,67 +136,40 @@ public class PositionOverlay implements GeneralOverlay {
accuracyCircle.setStyle(Style.FILL);
canvas.drawCircle(center.x, center.y, radius, accuracyCircle);
- if (coordinates.getAccuracy() < 50f && ((historyRecent != null && historyRecent.distanceTo(coordinates) > 5.0) || historyRecent == null)) {
- if (historyRecent != null) {
- history.add(historyRecent);
- }
- historyRecent = coordinates;
-
- int toRemove = history.size() - 700;
-
- if (toRemove > 0) {
- for (int cnt = 0; cnt < toRemove; cnt++) {
- history.remove(cnt);
- }
- }
- }
+ positionHistory.rememberTrailPosition(coordinates);
if (Settings.isMapTrail()) {
- int size = history.size();
+ int size = positionHistory.getHistory().size();
if (size > 1) {
int alphaCnt = size - 201;
if (alphaCnt < 1) {
alphaCnt = 1;
}
+ Point pointNow = new Point();
+ Point pointPrevious = new Point();
+ Location prev = positionHistory.getHistory().get(0);
+ projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(prev)), pointPrevious);
+
for (int cnt = 1; cnt < size; cnt++) {
- Location prev = history.get(cnt - 1);
- Location now = history.get(cnt);
-
- if (prev != null && now != null) {
- projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(prev)), historyPointP);
- projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(now)), historyPointN);
-
- int alpha;
- if ((alphaCnt - cnt) > 0) {
- alpha = 255 / (alphaCnt - cnt);
- }
- else {
- alpha = 255;
- }
-
- historyLineShadow.setAlpha(alpha);
- historyLine.setAlpha(alpha);
-
- canvas.drawLine(historyPointP.x, historyPointP.y, historyPointN.x, historyPointN.y, historyLineShadow);
- canvas.drawLine(historyPointP.x, historyPointP.y, historyPointN.x, historyPointN.y, historyLine);
- }
- }
- }
+ Location now = positionHistory.getHistory().get(cnt);
+ projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(now)), pointNow);
- if (size > 0) {
- Location prev = history.get(size - 1);
- Location now = coordinates;
+ int alpha;
+ if ((alphaCnt - cnt) > 0) {
+ alpha = 255 / (alphaCnt - cnt);
+ }
+ else {
+ alpha = 255;
+ }
- if (prev != null && now != null) {
- projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(prev)), historyPointP);
- projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(now)), historyPointN);
+ historyLineShadow.setAlpha(alpha);
+ historyLine.setAlpha(alpha);
- historyLineShadow.setAlpha(255);
- historyLine.setAlpha(255);
+ canvas.drawLine(pointPrevious.x, pointPrevious.y, pointNow.x, pointNow.y, historyLineShadow);
+ canvas.drawLine(pointPrevious.x, pointPrevious.y, pointNow.x, pointNow.y, historyLine);
- canvas.drawLine(historyPointP.x, historyPointP.y, historyPointN.x, historyPointN.y, historyLineShadow);
- canvas.drawLine(historyPointP.x, historyPointP.y, historyPointN.x, historyPointN.y, historyLine);
+ pointPrevious.set(pointNow.x, pointNow.y);
}
}
}
@@ -230,10 +200,10 @@ public class PositionOverlay implements GeneralOverlay {
}
public ArrayList<Location> getHistory() {
- return history;
+ return positionHistory.getHistory();
}
- public void setHistory(ArrayList<Location> inHistory) {
- history = inHistory;
+ public void setHistory(ArrayList<Location> history) {
+ positionHistory.setHistory(history);
}
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
index 6e5406e..3cf258e 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
@@ -14,7 +14,7 @@ import cgeo.geocaching.maps.interfaces.MapProjectionImpl;
import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OnMapDragListener;
import cgeo.geocaching.maps.interfaces.OverlayImpl;
-import cgeo.geocaching.maps.interfaces.OverlayImpl.overlayType;
+import cgeo.geocaching.maps.interfaces.OverlayImpl.OverlayType;
import cgeo.geocaching.utils.Log;
import com.google.android.maps.GeoPoint;
@@ -121,7 +121,7 @@ public class GoogleMapView extends MapView implements MapViewImpl {
@Override
public PositionOverlay createAddPositionOverlay(Activity activity) {
- GoogleOverlay ovl = new GoogleOverlay(activity, overlayType.PositionOverlay);
+ GoogleOverlay ovl = new GoogleOverlay(activity, OverlayType.PositionOverlay);
getOverlays().add(ovl);
return (PositionOverlay) ovl.getBase();
}
@@ -129,7 +129,7 @@ public class GoogleMapView extends MapView implements MapViewImpl {
@Override
public ScaleOverlay createAddScaleOverlay(Activity activity) {
- GoogleOverlay ovl = new GoogleOverlay(activity, overlayType.ScaleOverlay);
+ GoogleOverlay ovl = new GoogleOverlay(activity, OverlayType.ScaleOverlay);
getOverlays().add(ovl);
return (ScaleOverlay) ovl.getBase();
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java b/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java
index 773f9ff..bf4f606 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java
@@ -20,7 +20,7 @@ public class GoogleOverlay extends Overlay implements OverlayImpl {
private GeneralOverlay overlayBase = null;
private Lock lock = new ReentrantLock();
- public GoogleOverlay(Activity activityIn, overlayType ovlType) {
+ public GoogleOverlay(Activity activityIn, OverlayType ovlType) {
switch (ovlType) {
case PositionOverlay:
overlayBase = new PositionOverlay(activityIn, this);
diff --git a/main/src/cgeo/geocaching/maps/interfaces/OverlayImpl.java b/main/src/cgeo/geocaching/maps/interfaces/OverlayImpl.java
index 115b692..a17b5fb 100644
--- a/main/src/cgeo/geocaching/maps/interfaces/OverlayImpl.java
+++ b/main/src/cgeo/geocaching/maps/interfaces/OverlayImpl.java
@@ -6,7 +6,7 @@ package cgeo.geocaching.maps.interfaces;
*/
public interface OverlayImpl {
- public enum overlayType {
+ public enum OverlayType {
PositionOverlay,
ScaleOverlay
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
index 2b0c1f7..aa11405 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
@@ -14,7 +14,7 @@ import cgeo.geocaching.maps.interfaces.MapSource;
import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OnMapDragListener;
import cgeo.geocaching.maps.interfaces.OverlayImpl;
-import cgeo.geocaching.maps.interfaces.OverlayImpl.overlayType;
+import cgeo.geocaching.maps.interfaces.OverlayImpl.OverlayType;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
@@ -109,14 +109,14 @@ public class MapsforgeMapView extends MapView implements MapViewImpl {
@Override
public PositionOverlay createAddPositionOverlay(Activity activity) {
- MapsforgeOverlay ovl = new MapsforgeOverlay(activity, overlayType.PositionOverlay);
+ MapsforgeOverlay ovl = new MapsforgeOverlay(activity, OverlayType.PositionOverlay);
getOverlays().add(ovl);
return (PositionOverlay) ovl.getBase();
}
@Override
public ScaleOverlay createAddScaleOverlay(Activity activity) {
- MapsforgeOverlay ovl = new MapsforgeOverlay(activity, overlayType.ScaleOverlay);
+ MapsforgeOverlay ovl = new MapsforgeOverlay(activity, OverlayType.ScaleOverlay);
getOverlays().add(ovl);
return (ScaleOverlay) ovl.getBase();
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
index dd7fb75..a94b988 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
@@ -21,7 +21,7 @@ public class MapsforgeOverlay extends Overlay implements OverlayImpl {
private GeneralOverlay overlayBase = null;
private Lock lock = new ReentrantLock();
- public MapsforgeOverlay(Activity activityIn, OverlayImpl.overlayType ovlType) {
+ public MapsforgeOverlay(Activity activityIn, OverlayImpl.OverlayType ovlType) {
switch (ovlType) {
case PositionOverlay:
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
index 8e3a4d8..a074e70 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
@@ -13,7 +13,7 @@ import cgeo.geocaching.maps.interfaces.MapProjectionImpl;
import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OnMapDragListener;
import cgeo.geocaching.maps.interfaces.OverlayImpl;
-import cgeo.geocaching.maps.interfaces.OverlayImpl.overlayType;
+import cgeo.geocaching.maps.interfaces.OverlayImpl.OverlayType;
import cgeo.geocaching.utils.Log;
import org.mapsforge.android.mapsold.GeoPoint;
@@ -103,14 +103,14 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl {
@Override
public PositionOverlay createAddPositionOverlay(Activity activity) {
- MapsforgeOverlay ovl = new MapsforgeOverlay(activity, overlayType.PositionOverlay);
+ MapsforgeOverlay ovl = new MapsforgeOverlay(activity, OverlayType.PositionOverlay);
getOverlays().add(ovl);
return (PositionOverlay) ovl.getBase();
}
@Override
public ScaleOverlay createAddScaleOverlay(Activity activity) {
- MapsforgeOverlay ovl = new MapsforgeOverlay(activity, overlayType.ScaleOverlay);
+ MapsforgeOverlay ovl = new MapsforgeOverlay(activity, OverlayType.ScaleOverlay);
getOverlays().add(ovl);
return (ScaleOverlay) ovl.getBase();
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java
index d40b539..bdaac98 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java
@@ -21,7 +21,7 @@ public class MapsforgeOverlay extends Overlay implements OverlayImpl {
private GeneralOverlay overlayBase = null;
private Lock lock = new ReentrantLock();
- public MapsforgeOverlay(Activity activityIn, OverlayImpl.overlayType ovlType) {
+ public MapsforgeOverlay(Activity activityIn, OverlayImpl.OverlayType ovlType) {
switch (ovlType) {
case PositionOverlay:
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java
index 0649e12..797e67d 100644
--- a/main/src/cgeo/geocaching/network/HtmlImage.java
+++ b/main/src/cgeo/geocaching/network/HtmlImage.java
@@ -6,6 +6,7 @@ import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.files.LocalStorage;
+import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
@@ -146,9 +147,13 @@ public class HtmlImage implements Html.ImageGetter {
*/
private static void makeFreshCopy(final File file) {
final File tempFile = new File(file.getParentFile(), file.getName() + "-temp");
- file.renameTo(tempFile);
- LocalStorage.copy(tempFile, file);
- tempFile.delete();
+ if (file.renameTo(tempFile)) {
+ LocalStorage.copy(tempFile, file);
+ FileUtils.deleteIgnoringFailure(tempFile);
+ }
+ else {
+ Log.e("Could not reset timestamp of file " + file.getAbsolutePath());
+ }
}
private Bitmap getTransparent1x1Image() {
diff --git a/main/src/cgeo/geocaching/settings/EditPasswordPreference.java b/main/src/cgeo/geocaching/settings/EditPasswordPreference.java
index d89f128..20d0250 100644
--- a/main/src/cgeo/geocaching/settings/EditPasswordPreference.java
+++ b/main/src/cgeo/geocaching/settings/EditPasswordPreference.java
@@ -10,7 +10,6 @@ import android.util.AttributeSet;
* Use it exactly as an EditTextPreference
*
* @see SettingsActivity - search for EditPasswordPreference
- * @author koem
*/
public class EditPasswordPreference extends EditTextPreference {
diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java
index a4b2563..0e6158f 100644
--- a/main/src/cgeo/geocaching/settings/Settings.java
+++ b/main/src/cgeo/geocaching/settings/Settings.java
@@ -43,7 +43,7 @@ import java.util.Locale;
*/
public final class Settings {
- public static final int SHOW_WP_THRESHOLD_DEFAULT = 5;
+ public static final int SHOW_WP_THRESHOLD_DEFAULT = 10;
public static final int SHOW_WP_THRESHOLD_MAX = 50;
private static final int MAP_SOURCE_DEFAULT = GoogleMapProvider.GOOGLE_MAP_ID.hashCode();
@@ -53,14 +53,14 @@ public final class Settings {
private final static String keyConsumerPublic = CryptUtils.rot13("ESnsCvAv3kEupF1GCR3jGj");
private final static String keyConsumerSecret = CryptUtils.rot13("7vQWceACV9umEjJucmlpFe9FCMZSeqIqfkQ2BnhV9x");
- public enum coordInputFormatEnum {
+ public enum CoordInputFormatEnum {
Plain,
Deg,
Min,
Sec;
- public static coordInputFormatEnum fromInt(int id) {
- final coordInputFormatEnum[] values = coordInputFormatEnum.values();
+ public static CoordInputFormatEnum fromInt(int id) {
+ final CoordInputFormatEnum[] values = CoordInputFormatEnum.values();
if (id < 0 || id >= values.length) {
return Min;
}
@@ -75,8 +75,11 @@ public final class Settings {
Log.setDebug(sharedPrefs.getBoolean(getKey(R.string.pref_debug), false));
}
- // maps
- private static MapProvider mapProvider = null;
+ /**
+ * Cache the mapsource locally. If that is an offline map source, each request would potentially access the
+ * underlying map file, leading to delays.
+ */
+ private static MapSource mapSource;
private Settings() {
// this class is not to be instantiated;
@@ -132,10 +135,10 @@ public final class Settings {
e.putString(getKey(R.string.pref_memberstatus), old.getString(getKey(R.string.pref_memberstatus), ""));
e.putInt(getKey(R.string.pref_coordinputformat), old.getInt(getKey(R.string.pref_coordinputformat), 0));
e.putBoolean(getKey(R.string.pref_log_offline), old.getBoolean(getKey(R.string.pref_log_offline), false));
- e.putBoolean(getKey(R.string.pref_choose_list), old.getBoolean(getKey(R.string.pref_choose_list), false));
+ e.putBoolean(getKey(R.string.pref_choose_list), old.getBoolean(getKey(R.string.pref_choose_list), true));
e.putBoolean(getKey(R.string.pref_loaddirectionimg), old.getBoolean(getKey(R.string.pref_loaddirectionimg), true));
e.putString(getKey(R.string.pref_gccustomdate), old.getString(getKey(R.string.pref_gccustomdate), null));
- e.putInt(getKey(R.string.pref_gcshowwaypointsthreshold), old.getInt(getKey(R.string.pref_gcshowwaypointsthreshold), 0));
+ e.putInt(getKey(R.string.pref_showwaypointsthreshold), old.getInt(getKey(R.string.pref_showwaypointsthreshold), SHOW_WP_THRESHOLD_DEFAULT));
e.putString(getKey(R.string.pref_cookiestore), old.getString(getKey(R.string.pref_cookiestore), null));
e.putBoolean(getKey(R.string.pref_opendetailslastpage), old.getBoolean(getKey(R.string.pref_opendetailslastpage), false));
e.putInt(getKey(R.string.pref_lastdetailspage), old.getInt(getKey(R.string.pref_lastdetailspage), 1));
@@ -163,7 +166,7 @@ public final class Settings {
} else if (wpThreshold > SHOW_WP_THRESHOLD_MAX) {
wpThreshold = SHOW_WP_THRESHOLD_MAX;
}
- e.putInt(getKey(R.string.pref_gcshowwaypointsthreshold), wpThreshold);
+ e.putInt(getKey(R.string.pref_showwaypointsthreshold), wpThreshold);
// KEY_MAP_SOURCE must be string, because it is the key for a ListPreference now
int ms = sharedPrefs.getInt(getKey(R.string.pref_mapsource), MAP_SOURCE_DEFAULT);
@@ -397,10 +400,7 @@ public final class Settings {
}
public static MapProvider getMapProvider() {
- if (mapProvider == null) {
- mapProvider = getMapSource().getMapProvider();
- }
- return mapProvider;
+ return getMapSource().getMapProvider();
}
public static String getMapFile() {
@@ -441,11 +441,11 @@ public final class Settings {
return MapsforgeMapProvider.isValidMapFile(mapFileIn);
}
- public static coordInputFormatEnum getCoordInputFormat() {
- return coordInputFormatEnum.fromInt(getInt(R.string.pref_coordinputformat, 0));
+ public static CoordInputFormatEnum getCoordInputFormat() {
+ return CoordInputFormatEnum.fromInt(getInt(R.string.pref_coordinputformat, 0));
}
- public static void setCoordInputFormat(final coordInputFormatEnum format) {
+ public static void setCoordInputFormat(final CoordInputFormatEnum format) {
putInt(R.string.pref_coordinputformat, format.ordinal());
}
@@ -543,7 +543,21 @@ public final class Settings {
}
public static boolean isUseImperialUnits() {
- return getBoolean(R.string.pref_units, false);
+ return getBoolean(R.string.pref_units, getImperialUnitsDefault());
+ }
+
+ static boolean getImperialUnitsDefault() {
+ final String countryCode = Locale.getDefault().getCountry();
+ if ("US".equals(countryCode)) {
+ return true; // USA
+ }
+ if ("LR".equals(countryCode)) {
+ return true; // Liberia
+ }
+ if ("MM".equals(countryCode)) {
+ return true; // Burma
+ }
+ return false;
}
public static boolean isLiveMap() {
@@ -582,12 +596,15 @@ public final class Settings {
}
public static MapSource getMapSource() {
+ if (mapSource != null) {
+ return mapSource;
+ }
final int id = getConvertedMapId();
- final MapSource map = MapProviderFactory.getMapSource(id);
- if (map != null) {
+ mapSource = MapProviderFactory.getMapSource(id);
+ if (mapSource != null) {
// don't use offline maps if the map file is not valid
- if ((!(map instanceof OfflineMapSource)) || (isValidMapFile())) {
- return map;
+ if ((!(mapSource instanceof OfflineMapSource)) || (isValidMapFile())) {
+ return mapSource;
}
}
// fallback to first available map
@@ -636,13 +653,12 @@ public final class Settings {
}
public static void setMapSource(final MapSource newMapSource) {
- if (!MapProviderFactory.isSameActivity(getMapSource(), newMapSource)) {
- mapProvider = null;
- }
putString(R.string.pref_mapsource, String.valueOf(newMapSource.getNumericalId()));
if (newMapSource instanceof OfflineMapSource) {
setMapFile(((OfflineMapSource) newMapSource).getFileName());
}
+ // cache the value
+ mapSource = newMapSource;
}
public static void setAnyCoordinates(final Geopoint coords) {
@@ -704,11 +720,11 @@ public final class Settings {
* The Threshold for the showing of child waypoints
*/
public static int getWayPointsThreshold() {
- return getInt(R.string.pref_gcshowwaypointsthreshold, SHOW_WP_THRESHOLD_DEFAULT);
+ return getInt(R.string.pref_showwaypointsthreshold, SHOW_WP_THRESHOLD_DEFAULT);
}
public static void setShowWaypointsThreshold(final int threshold) {
- putInt(R.string.pref_gcshowwaypointsthreshold, threshold);
+ putInt(R.string.pref_showwaypointsthreshold, threshold);
}
public static boolean isUseTwitter() {
@@ -974,4 +990,9 @@ public final class Settings {
public static void setFieldnoteExportDate(final long date) {
putLong(R.string.pref_fieldnoteExportDate, date);
}
+
+ public static boolean isUseNavigationApp(NavigationAppsEnum navApp) {
+ return getBoolean(navApp.preferenceKey, true);
+ }
+
}
diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java
index daef9af..42f6074 100644
--- a/main/src/cgeo/geocaching/settings/SettingsActivity.java
+++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java
@@ -3,7 +3,6 @@ package cgeo.geocaching.settings;
import cgeo.geocaching.Intents;
import cgeo.geocaching.R;
import cgeo.geocaching.SelectMapfileActivity;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
@@ -13,7 +12,7 @@ import cgeo.geocaching.connector.gc.Login;
import cgeo.geocaching.files.SimpleDirChooser;
import cgeo.geocaching.maps.MapProviderFactory;
import cgeo.geocaching.maps.interfaces.MapSource;
-import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.utils.DatabaseBackupUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.LogTemplateProvider;
import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate;
@@ -21,7 +20,6 @@ import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate;
import org.apache.commons.lang3.StringUtils;
import org.openintents.intents.FileManagerIntents;
-import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -58,7 +56,6 @@ import java.util.Locale;
* guidelines and the <a href="http://developer.android.com/guide/topics/ui/settings.html">Settings API Guide</a> for
* more information on developing a Settings UI.
*
- * @author koem (initial author)
*/
public class SettingsActivity extends PreferenceActivity {
@@ -123,6 +120,7 @@ public class SettingsActivity extends PreferenceActivity {
initBasicMemberPreferences();
initSend2CgeoPreferences();
initServicePreferences();
+ initNavigationMenuPreferences();
for (int k : new int[] { R.string.pref_username, R.string.pref_password,
R.string.pref_pass_vote, R.string.pref_signature,
@@ -133,6 +131,18 @@ public class SettingsActivity extends PreferenceActivity {
R.string.pref_fakekey_preference_backup_info, }) {
bindSummaryToStringValue(k);
}
+ getPreference(R.string.pref_units).setDefaultValue(Settings.getImperialUnitsDefault());
+ }
+
+ private void initNavigationMenuPreferences() {
+ for (NavigationAppsEnum appEnum : NavigationAppsEnum.values()) {
+ if (appEnum.app.isInstalled()) {
+ getPreference(appEnum.preferenceKey).setEnabled(true);
+ }
+ }
+ getPreference(R.string.pref_fakekey_basicmembers_screen)
+ .setEnabled(!Settings.isPremiumMember());
+ redrawScreen(R.string.pref_fakekey_navigation_menu_screen);
}
private void initServicePreferences() {
@@ -298,39 +308,13 @@ public class SettingsActivity extends PreferenceActivity {
backup.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(final Preference preference) {
- final Context context = preference.getContext();
- // avoid overwriting an existing backup with an empty database
- // (can happen directly after reinstalling the app)
- if (cgData.getAllCachesCount() == 0) {
- ActivityMixin.helpDialog(SettingsActivity.this,
- context.getString(R.string.init_backup),
- context.getString(R.string.init_backup_unnecessary));
- return false;
- }
+ return DatabaseBackupUtils.createBackup(SettingsActivity.this, new Runnable() {
- final ProgressDialog dialog = ProgressDialog.show(context,
- context.getString(R.string.init_backup),
- context.getString(R.string.init_backup_running), true, false);
- new Thread() {
@Override
public void run() {
- final String backupFileName = cgData.backupDatabase();
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- dialog.dismiss();
- ActivityMixin.helpDialog(SettingsActivity.this,
- context.getString(R.string.init_backup_backup),
- backupFileName != null
- ? context.getString(R.string.init_backup_success)
- + "\n" + backupFileName
- : context.getString(R.string.init_backup_failed));
- VALUE_CHANGE_LISTENER.onPreferenceChange(SettingsActivity.this.getPreference(R.string.pref_fakekey_preference_backup_info), "");
- }
- });
+ VALUE_CHANGE_LISTENER.onPreferenceChange(SettingsActivity.this.getPreference(R.string.pref_fakekey_preference_backup_info), "");
}
- }.start();
- return true;
+ });
}
});
@@ -338,8 +322,7 @@ public class SettingsActivity extends PreferenceActivity {
restore.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(final Preference preference) {
- ((cgeoapplication) SettingsActivity.this.getApplication())
- .restoreDatabase(SettingsActivity.this);
+ DatabaseBackupUtils.restoreDatabase(SettingsActivity.this);
return true;
}
});
@@ -492,10 +475,19 @@ public class SettingsActivity extends PreferenceActivity {
if (preference instanceof EditPasswordPreference) {
if (StringUtils.isBlank((String) value)) {
- preference.setSummary("");
+ preference.setSummary(StringUtils.EMPTY);
} else {
- preference.setSummary("\u2022 \u2022 \u2022 \u2022 \u2022 \u2022 \u2022 \u2022 \u2022 \u2022");
+ preference.setSummary(StringUtils.repeat("\u2022 ", 10));
}
+ } else if (isPreference(preference, R.string.pref_mapsource)) {
+ // reset the cached map source
+ int mapSourceId = Integer.valueOf(stringValue);
+ final MapSource mapSource = MapProviderFactory.getMapSource(mapSourceId);
+ Settings.setMapSource(mapSource);
+ 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;
} else if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
@@ -507,13 +499,11 @@ public class SettingsActivity extends PreferenceActivity {
index >= 0
? listPreference.getEntries()[index]
: null);
- } else if (getKey(R.string.pref_fakekey_preference_backup_info).equals(preference.getKey())) {
- File lastBackupFile = cgData.getRestoreFile();
- String text;
- if (lastBackupFile != null) {
+ } else if (isPreference(preference, R.string.pref_fakekey_preference_backup_info)) {
+ final String text;
+ if (DatabaseBackupUtils.hasBackup()) {
text = preference.getContext().getString(R.string.init_backup_last) + " "
- + Formatter.formatTime(lastBackupFile.lastModified())
- + ", " + Formatter.formatDate(lastBackupFile.lastModified());
+ + DatabaseBackupUtils.getBackupDateTime();
} else {
text = preference.getContext().getString(R.string.init_backup_last_no);
}
@@ -523,17 +513,13 @@ public class SettingsActivity extends PreferenceActivity {
// simple string representation.
preference.setSummary(stringValue);
}
- // reset log-in if gc user or password is changed
- if (isPreference(preference, R.string.pref_username) || isPreference(preference, R.string.pref_password)) {
+ if ((isPreference(preference, R.string.pref_username) && !stringValue.equals(Settings.getUsername())) || (isPreference(preference, R.string.pref_password) && !stringValue.equals(Settings.getGcLogin().getRight()))) {
+ // reset log-in if gc user or password is changed
if (Login.isActualLoginStatus()) {
Login.logout();
}
cgeoapplication.getInstance().checkLogin = true;
}
- // reset log-in status if connector activation was changed
- if (isPreference(preference, R.string.pref_connectorOCActive) || isPreference(preference, R.string.pref_connectorOCPLActive) || isPreference(preference, R.string.pref_connectorGCActive)) {
- cgeoapplication.getInstance().checkLogin = true;
- }
return true;
}
};
diff --git a/main/src/cgeo/geocaching/speech/SpeechService.java b/main/src/cgeo/geocaching/speech/SpeechService.java
index 634f1c4..ae289ed 100644
--- a/main/src/cgeo/geocaching/speech/SpeechService.java
+++ b/main/src/cgeo/geocaching/speech/SpeechService.java
@@ -1,8 +1,9 @@
package cgeo.geocaching.speech;
import cgeo.geocaching.DirectionProvider;
-import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
@@ -44,16 +45,18 @@ public class SpeechService extends Service implements OnInitListener {
GeoDirHandler geoHandler = new GeoDirHandler() {
@Override
protected void updateDirection(float newDirection) {
- direction = DirectionProvider.getDirectionNow(startingActivity, newDirection);
- directionInitialized = true;
- updateCompass();
+ if (cgeoapplication.getInstance().currentGeo().getSpeed() <= 5) {
+ direction = DirectionProvider.getDirectionNow(startingActivity, newDirection);
+ directionInitialized = true;
+ updateCompass();
+ }
}
@Override
protected void updateGeoData(cgeo.geocaching.IGeoData newGeo) {
position = newGeo.getCoords();
positionInitialized = true;
- if (newGeo.getSpeed() > 5) {
+ if (!Settings.isUseCompass() || newGeo.getSpeed() > 5) {
direction = newGeo.getBearing();
directionInitialized = true;
}
@@ -151,7 +154,11 @@ public class SpeechService extends Service implements OnInitListener {
initialized = true;
- geoHandler.startGeoAndDir();
+ if (Settings.isUseCompass()) {
+ geoHandler.startGeoAndDir();
+ } else {
+ geoHandler.startGeo();
+ }
}
@Override
diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
index 3179857..c6aeaa6 100644
--- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
@@ -6,12 +6,12 @@ import cgeo.geocaching.CacheDetailActivity;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.R;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheListType;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.filter.IFilter;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.sorting.CacheComparator;
import cgeo.geocaching.sorting.DistanceComparator;
import cgeo.geocaching.sorting.EventDateComparator;
@@ -645,6 +645,10 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
}
public void setInitialComparator() {
+ // will be called repeatedly when coming back to the list, therefore check first for an already existing sorting
+ if (cacheComparator != null) {
+ return;
+ }
CacheComparator comparator = null; // a null comparator will automatically sort by distance
if (cacheListType == CacheListType.HISTORY) {
comparator = new VisitComparator();
diff --git a/main/src/cgeo/geocaching/ui/EditNoteDialog.java b/main/src/cgeo/geocaching/ui/EditNoteDialog.java
index 50cf57a..2af1cb8 100644
--- a/main/src/cgeo/geocaching/ui/EditNoteDialog.java
+++ b/main/src/cgeo/geocaching/ui/EditNoteDialog.java
@@ -7,7 +7,7 @@ import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
-import android.view.LayoutInflater;
+import android.view.ContextThemeWrapper;
import android.view.View;
import android.widget.EditText;
@@ -35,13 +35,12 @@ public class EditNoteDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View view = inflater.inflate(R.layout.fragment_edit_note, null);
+ View view = View.inflate(new ContextThemeWrapper(getActivity(), R.style.dark), R.layout.fragment_edit_note, null);
mEditText = (EditText) view.findViewById(R.id.note);
String initialNote = getArguments().getString(ARGUMENT_INITIAL_NOTE);
if (initialNote != null) {
mEditText.setText(initialNote);
- initialNote = null;
+ getArguments().remove(ARGUMENT_INITIAL_NOTE);
}
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
diff --git a/main/src/cgeo/geocaching/ui/Formatter.java b/main/src/cgeo/geocaching/ui/Formatter.java
index 92a0defc..ecae9ea 100644
--- a/main/src/cgeo/geocaching/ui/Formatter.java
+++ b/main/src/cgeo/geocaching/ui/Formatter.java
@@ -99,13 +99,11 @@ public abstract class Formatter {
* Generate a numeric date and time string according to system-wide settings (locale,
* date format) such as "7 sept. at 12:35".
*
- * @param context
- * a Context
* @param date
* milliseconds since the epoch
* @return the formatted string
*/
- public static String formatShortDateTime(Context context, long date) {
+ public static String formatShortDateTime(long date) {
return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL);
}
diff --git a/main/src/cgeo/geocaching/ui/GPXListAdapter.java b/main/src/cgeo/geocaching/ui/GPXListAdapter.java
index 7f3c33f..988bb81 100644
--- a/main/src/cgeo/geocaching/ui/GPXListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/GPXListAdapter.java
@@ -5,6 +5,7 @@ import butterknife.InjectView;
import cgeo.geocaching.GpxFileListActivity;
import cgeo.geocaching.R;
import cgeo.geocaching.files.GPXImporter;
+import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
import android.app.Activity;
@@ -80,7 +81,7 @@ public class GPXListAdapter extends ArrayAdapter<File> {
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
- file.delete();
+ FileUtils.deleteIgnoringFailure(file);
GPXListAdapter.this.remove(file);
}
})
diff --git a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
index 959cb14..91ce7e3 100644
--- a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
@@ -4,7 +4,7 @@ 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.settings.Settings.CoordInputFormatEnum;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.compatibility.Compatibility;
@@ -41,7 +41,7 @@ public class CoordinatesInputDialog extends NoTitleDialog {
private CoordinateUpdate cuListener;
- private coordInputFormatEnum currentFormat = null;
+ private CoordInputFormatEnum currentFormat = null;
public CoordinatesInputDialog(final AbstractActivity context, final Geocache cache, final Geopoint gp, final IGeoData geo) {
super(context, ActivityMixin.getDialogTheme());
@@ -272,7 +272,7 @@ public class CoordinatesInputDialog extends NoTitleDialog {
* formatSec 2/3 2 2 3
*/
- if (currentFormat == coordInputFormatEnum.Plain) {
+ if (currentFormat == CoordInputFormatEnum.Plain) {
return;
}
@@ -325,7 +325,7 @@ public class CoordinatesInputDialog extends NoTitleDialog {
}
private boolean calc(final boolean signalError) {
- if (currentFormat == coordInputFormatEnum.Plain) {
+ if (currentFormat == CoordInputFormatEnum.Plain) {
try {
gp = new Geopoint(eLat.getText().toString(), eLon.getText().toString());
} catch (final Geopoint.ParseException e) {
@@ -375,10 +375,10 @@ public class CoordinatesInputDialog extends NoTitleDialog {
if (editText == eLonDeg || editText == eLatSub || editText == eLonSub) {
return 3;
}
- if ((editText == eLatMin || editText == eLonMin) && currentFormat == coordInputFormatEnum.Deg) {
+ if ((editText == eLatMin || editText == eLonMin) && currentFormat == CoordInputFormatEnum.Deg) {
return 5;
}
- if ((editText == eLatSec || editText == eLonSec) && currentFormat == coordInputFormatEnum.Min) {
+ if ((editText == eLatSec || editText == eLonSec) && currentFormat == CoordInputFormatEnum.Min) {
return 3;
}
return 2;
@@ -402,7 +402,7 @@ public class CoordinatesInputDialog extends NoTitleDialog {
}
}
- currentFormat = coordInputFormatEnum.fromInt(pos);
+ currentFormat = CoordInputFormatEnum.fromInt(pos);
Settings.setCoordInputFormat(currentFormat);
updateGUI();
}
diff --git a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java
new file mode 100644
index 0000000..24f375d
--- /dev/null
+++ b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java
@@ -0,0 +1,115 @@
+package cgeo.geocaching.utils;
+
+import cgeo.geocaching.MainActivity;
+import cgeo.geocaching.R;
+import cgeo.geocaching.cgData;
+import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.ui.Formatter;
+
+import org.apache.commons.lang3.StringUtils;
+
+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;
+
+public class DatabaseBackupUtils {
+
+ private DatabaseBackupUtils() {
+ // utility class
+ }
+
+ /**
+ * restore the database in a new thread, showing a progress window
+ *
+ * @param activity
+ * calling activity
+ */
+ public static void restoreDatabase(final Activity activity) {
+ 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();
+ }
+ }
+ };
+
+ @Override
+ public void run() {
+ restoreSuccessful.set(cgData.restoreDatabaseInternal());
+ handler.sendMessage(handler.obtainMessage());
+ }
+ };
+ restoreThread.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) {
+ ActivityMixin.helpDialog(activity,
+ context.getString(R.string.init_backup),
+ context.getString(R.string.init_backup_unnecessary));
+ return false;
+ }
+
+ final ProgressDialog dialog = ProgressDialog.show(context,
+ context.getString(R.string.init_backup),
+ context.getString(R.string.init_backup_running), true, false);
+ new Thread() {
+ @Override
+ public void run() {
+ final String backupFileName = cgData.backupDatabaseInternal();
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ dialog.dismiss();
+ ActivityMixin.helpDialog(activity,
+ context.getString(R.string.init_backup_backup),
+ backupFileName != null
+ ? context.getString(R.string.init_backup_success)
+ + "\n" + backupFileName
+ : context.getString(R.string.init_backup_failed));
+ if (runAfterwards != null) {
+ runAfterwards.run();
+ }
+ }
+ });
+ }
+ }.start();
+ return true;
+ }
+
+ public static File getRestoreFile() {
+ final File fileSourceFile = cgData.getBackupFileInternal();
+ return fileSourceFile.exists() ? fileSourceFile : null;
+ }
+
+ public static boolean hasBackup() {
+ return getRestoreFile() != null;
+ }
+
+ public static String getBackupDateTime() {
+ final File restoreFile = getRestoreFile();
+ if (restoreFile == null) {
+ return StringUtils.EMPTY;
+ }
+ return Formatter.formatShortDateTime(restoreFile.lastModified());
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/utils/FileUtils.java b/main/src/cgeo/geocaching/utils/FileUtils.java
index 5ab8fcc..edb8102 100644
--- a/main/src/cgeo/geocaching/utils/FileUtils.java
+++ b/main/src/cgeo/geocaching/utils/FileUtils.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.utils;
import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
import android.os.Handler;
import android.os.Message;
@@ -11,8 +12,6 @@ import java.util.List;
/**
* Utility class for files
*
- * @author rsudev
- *
*/
public final class FileUtils {
@@ -65,4 +64,65 @@ public final class FileUtils {
public abstract boolean shouldEnd();
}
+
+ /**
+ * Create a unique non existing file named like the given file name. If a file with the given name already exists,
+ * add a number as suffix to the file name.<br>
+ * Example: For the file name "file.ext" this will return the first file of the list
+ * <ul>
+ * <li>file.ext</li>
+ * <li>file_2.ext</li>
+ * <li>file_3.ext</li>
+ * </ul>
+ * which does not yet exist.
+ */
+ public static File getUniqueNamedFile(final String baseNameAndPath) {
+ String extension = StringUtils.substringAfterLast(baseNameAndPath, ".");
+ String pathName = StringUtils.substringBeforeLast(baseNameAndPath, ".");
+ int number = 1;
+ while (new File(getNumberedFileName(pathName, extension, number)).exists()) {
+ number++;
+ }
+ return new File(getNumberedFileName(pathName, extension, number));
+ }
+
+ private static String getNumberedFileName(String pathName, String extension, int number) {
+ return pathName + (number > 1 ? "_" + Integer.toString(number) : "") + "." + extension;
+ }
+
+ /**
+ * This usage of this method indicates that the return value of File.delete() can safely be ignored.
+ */
+ public static void deleteIgnoringFailure(final File file) {
+ if (!file.delete()) {
+ Log.i("Could not delete " + file.getAbsolutePath());
+ }
+ }
+
+ /**
+ * Deletes a file and logs deletion failures.
+ *
+ * @return <code> true</code> if this file was deleted, <code>false</code> otherwise.
+ */
+ public static boolean delete(final File file) {
+ final boolean success = file.delete();
+ if (!success) {
+ Log.e("Could not delete " + file.getAbsolutePath());
+ }
+ return success;
+ }
+
+ /**
+ * Creates the directory named by the given file, creating any missing parent directories in the process.
+ *
+ * @return <code>true</code> if the directory was created, <code>false</code> on failure or if the directory already
+ * existed.
+ */
+ public static boolean mkdirs(File file) {
+ final boolean success = file.mkdirs();
+ if (!success) {
+ Log.e("Could not make directories " + file.getAbsolutePath());
+ }
+ return success;
+ }
}
diff --git a/main/src/cgeo/geocaching/utils/Log.java b/main/src/cgeo/geocaching/utils/Log.java
index f7f33d9..aa8dbd1 100644
--- a/main/src/cgeo/geocaching/utils/Log.java
+++ b/main/src/cgeo/geocaching/utils/Log.java
@@ -8,26 +8,30 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
-final public class Log {
+public final class Log {
private static final String TAG = "cgeo";
/**
- * the debug flag is cached here so that we don't need to access the settings every time we have to evaluate it
+ * The debug flag is cached here so that we don't need to access the settings every time we have to evaluate it.
*/
private static boolean isDebug = true;
private static boolean first = true;
+ private Log() {
+ // utility class
+ }
+
public static boolean isDebug() {
return isDebug;
}
/**
- * save a copy of the debug flag from the settings for performance reasons
- *
+ * Save a copy of the debug flag from the settings for performance reasons.
+ *
* @param isDebug
*/
- public static void setDebug(boolean isDebug) {
+ public static void setDebug(final boolean isDebug) {
Log.isDebug = isDebug;
}
@@ -95,11 +99,11 @@ final public class Log {
*
* @param msg the message to log, or to add to the log if other messages have been stored in the same run
*/
- public synchronized static void logToFile(final String msg) {
+ public static synchronized void logToFile(final String msg) {
final File file = new File(Environment.getExternalStorageDirectory(), "cgeo-debug.log");
if (first) {
first = false;
- file.delete();
+ FileUtils.delete(file);
}
Writer writer = null;
try {
diff --git a/main/src/cgeo/geocaching/utils/MatcherWrapper.java b/main/src/cgeo/geocaching/utils/MatcherWrapper.java
index c3c1663..78b1170 100644
--- a/main/src/cgeo/geocaching/utils/MatcherWrapper.java
+++ b/main/src/cgeo/geocaching/utils/MatcherWrapper.java
@@ -22,6 +22,10 @@ public class MatcherWrapper {
return matcher.find();
}
+ public boolean find(int start) {
+ return matcher.find(start);
+ }
+
/**
* see {@link Matcher#group(int)}
*/
diff --git a/main/src/cgeo/geocaching/utils/SimpleCancellableHandler.java b/main/src/cgeo/geocaching/utils/SimpleCancellableHandler.java
index 75c10ab..9207c74 100644
--- a/main/src/cgeo/geocaching/utils/SimpleCancellableHandler.java
+++ b/main/src/cgeo/geocaching/utils/SimpleCancellableHandler.java
@@ -20,7 +20,7 @@ public class SimpleCancellableHandler extends CancellableHandler {
}
@Override
- public void handleRegularMessage(final Message msg) {
+ protected void handleRegularMessage(final Message msg) {
AbstractActivity activity = activityRef.get();
if (activity != null && msg.getData() != null && msg.getData().getString(MESSAGE_TEXT) != null) {
activity.showToast(msg.getData().getString(MESSAGE_TEXT));
@@ -30,7 +30,7 @@ public class SimpleCancellableHandler extends CancellableHandler {
}
@Override
- public void handleCancel(final Object extra) {
+ protected void handleCancel(final Object extra) {
AbstractActivity activity = activityRef.get();
if (activity != null) {
activity.showToast((String) extra);
@@ -38,7 +38,7 @@ public class SimpleCancellableHandler extends CancellableHandler {
dismissProgress();
}
- public final void showToast(int resId) {
+ protected final void showToast(int resId) {
AbstractActivity activity = activityRef.get();
if (activity != null) {
Resources res = activity.getResources();
@@ -46,7 +46,7 @@ public class SimpleCancellableHandler extends CancellableHandler {
}
}
- public final void dismissProgress() {
+ protected final void dismissProgress() {
Progress progressDialog = progressDialogRef.get();
if (progressDialog != null) {
progressDialog.dismiss();
diff --git a/main/src/cgeo/geocaching/utils/UncertainProperty.java b/main/src/cgeo/geocaching/utils/UncertainProperty.java
new file mode 100644
index 0000000..5f86662
--- /dev/null
+++ b/main/src/cgeo/geocaching/utils/UncertainProperty.java
@@ -0,0 +1,48 @@
+package cgeo.geocaching.utils;
+
+import cgeo.geocaching.connector.gc.Tile;
+
+public class UncertainProperty<T> {
+
+ private final T value;
+ private final int certaintyLevel;
+
+ public UncertainProperty(T value) {
+ this(value, Tile.ZOOMLEVEL_MAX + 1);
+ }
+
+ public UncertainProperty(T value, int certaintyLevel) {
+ this.value = value;
+ this.certaintyLevel = certaintyLevel;
+ }
+
+ public T getValue() {
+ return value;
+ }
+
+ public int getCertaintyLevel() {
+ return certaintyLevel;
+ }
+
+ public UncertainProperty<T> getMergedProperty(final UncertainProperty<T> other) {
+ if (null == other || null == other.value) {
+ return this;
+ }
+ if (null == this.value) {
+ return other;
+ }
+ if (other.certaintyLevel > certaintyLevel) {
+ return other;
+ }
+
+ return this;
+ }
+
+ public static <T> UncertainProperty<T> getMergedProperty(UncertainProperty<T> property, UncertainProperty<T> otherProperty) {
+ if (null == property) {
+ return otherProperty;
+ }
+ return property.getMergedProperty(otherProperty);
+ }
+
+}