aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/connector
diff options
context:
space:
mode:
authorBananeweizen <bananeweizen@gmx.de>2012-05-05 10:31:30 +0200
committerBananeweizen <bananeweizen@gmx.de>2012-05-05 10:31:30 +0200
commit057f24b4f57dadeeba92a04c83e3bcd790e983b1 (patch)
tree23464d3fd6a16c6ede3206bc39ed4b2e16d0419c /main/src/cgeo/geocaching/connector
parent84c6bd6cc358b2cde2926a62990e4c151c47d6d1 (diff)
downloadcgeo-057f24b4f57dadeeba92a04c83e3bcd790e983b1.zip
cgeo-057f24b4f57dadeeba92a04c83e3bcd790e983b1.tar.gz
cgeo-057f24b4f57dadeeba92a04c83e3bcd790e983b1.tar.bz2
refactoring: more cleanup in connector interfaces
* switch from method overrides to interface detection for connector features * remove GCBase and put code into other classes * reduce GC specific code being used in general activities
Diffstat (limited to 'main/src/cgeo/geocaching/connector')
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractConnector.java30
-rw-r--r--main/src/cgeo/geocaching/connector/ConnectorFactory.java17
-rw-r--r--main/src/cgeo/geocaching/connector/IConnector.java26
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java13
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java12
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java8
-rw-r--r--main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java68
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java49
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConstants.java30
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java (renamed from main/src/cgeo/geocaching/connector/gc/GCBase.java)414
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java46
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Login.java8
-rw-r--r--main/src/cgeo/geocaching/connector/gc/SearchHandler.java107
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Tile.java50
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiConnector.java14
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OXConnector.java22
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java45
17 files changed, 558 insertions, 401 deletions
diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java
index 248ca23..f1d00fa 100644
--- a/main/src/cgeo/geocaching/connector/AbstractConnector.java
+++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java
@@ -2,12 +2,7 @@ package cgeo.geocaching.connector;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
-import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
-import cgeo.geocaching.utils.CancellableHandler;
-
-import java.util.Set;
public abstract class AbstractConnector implements IConnector {
@@ -17,11 +12,6 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
- public boolean supportsRefreshCache(cgCache cache) {
- return false;
- }
-
- @Override
public boolean supportsWatchList() {
return false;
}
@@ -41,26 +31,6 @@ public abstract class AbstractConnector implements IConnector {
return false;
}
- @Override
- public boolean supportsCachesAround() {
- return false;
- }
-
- @Override
- public SearchResult searchByCoordinate(Geopoint center) {
- return null;
- }
-
- @Override
- public SearchResult searchByGeocode(String geocode, String guid, cgeoapplication app, CancellableHandler handler) {
- return null;
- }
-
- @Override
- public SearchResult searchByGeocodes(Set<String> geocodes) {
- return null;
- }
-
public SearchResult searchByViewport(Viewport viewport, String tokens[]) {
return null;
}
diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
index fc8ef45..784a54e 100644
--- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java
+++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
@@ -6,13 +6,10 @@ import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.connector.oc.OCApiConnector;
import cgeo.geocaching.connector.oc.OCConnector;
import cgeo.geocaching.connector.ox.OXConnector;
-import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
import org.apache.commons.lang3.StringUtils;
-import java.util.Set;
-
public final class ConnectorFactory {
private static final UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector();
private static final IConnector[] connectors = new IConnector[] {
@@ -70,13 +67,6 @@ public final class ConnectorFactory {
return StringUtils.isBlank(geocode) || !Character.isLetterOrDigit(geocode.charAt(0));
}
- /** @see IConnector#searchByCoordinate */
- public static SearchResult searchByCoordinate(final Geopoint center) {
- // We have only connector capable of doing a 'searchByCoordinate()'
- // If there is a second connector the information has to be collected from all collectors
- return GCConnector.getInstance().searchByCoordinate(center);
- }
-
/** @see IConnector#searchByViewport */
public static SearchResult searchByViewport(final Viewport viewport, final String[] tokens) {
// We have only connector capable of doing a 'searchByViewport()'
@@ -84,11 +74,4 @@ public final class ConnectorFactory {
return GCConnector.getInstance().searchByViewport(viewport, tokens);
}
- /** @see IConnector#searchByGeocodes */
- public static SearchResult searchByGeocodes(final Set<String> geocodes) {
- // We have only connector capable of doing a 'searchByViewport()'
- // If there is a second connector the information has to be collected from all collectors
- return GCConnector.getInstance().searchByGeocodes(geocodes);
- }
-
}
diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java
index 28c21c8..4bc63fc 100644
--- a/main/src/cgeo/geocaching/connector/IConnector.java
+++ b/main/src/cgeo/geocaching/connector/IConnector.java
@@ -2,12 +2,7 @@ package cgeo.geocaching.connector;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
-import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
-import cgeo.geocaching.utils.CancellableHandler;
-
-import java.util.Set;
public interface IConnector {
/**
@@ -25,8 +20,6 @@ public interface IConnector {
*/
public boolean canHandle(final String geocode);
- public boolean supportsRefreshCache(final cgCache cache);
-
/**
* get browser URL for the given cache
*
@@ -72,25 +65,6 @@ public interface IConnector {
public boolean supportsUserActions();
/**
- * enable/disable "caches around" action in cache details
- *
- * @return
- */
- public boolean supportsCachesAround();
-
- public SearchResult searchByGeocode(final String geocode, final String guid, final cgeoapplication app, final CancellableHandler handler);
-
- public SearchResult searchByGeocodes(final Set<String> geocodes);
-
- /**
- * search caches by coordinate. must be implemented if {@link supportsCachesAround} returns <code>true</true>
- *
- * @param center
- * @return
- */
- public SearchResult searchByCoordinate(final Geopoint center);
-
- /**
* Search caches by viewport.
*
* @param viewport
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
new file mode 100644
index 0000000..62645c2
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
@@ -0,0 +1,13 @@
+package cgeo.geocaching.connector.capability;
+
+import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.geopoint.Geopoint;
+
+/**
+ * connector capability for online searching caches around a center coordinate, sorted by distance
+ *
+ */
+public interface ISearchByCenter {
+ public SearchResult searchByCenter(final Geopoint center);
+
+}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java b/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java
new file mode 100644
index 0000000..c3d6bba
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java
@@ -0,0 +1,12 @@
+package cgeo.geocaching.connector.capability;
+
+import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.utils.CancellableHandler;
+
+/**
+ * connector capability of searching online for a cache by geocode
+ *
+ */
+public interface ISearchByGeocode {
+ public SearchResult searchByGeocode(final String geocode, final String guid, final CancellableHandler handler);
+}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
new file mode 100644
index 0000000..316cf00
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
@@ -0,0 +1,8 @@
+package cgeo.geocaching.connector.capability;
+
+import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.geopoint.Viewport;
+
+public interface ISearchByViewPort {
+ public SearchResult searchByViewport(final Viewport viewport, final String[] tokens);
+}
diff --git a/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java b/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java
new file mode 100644
index 0000000..33c8a92
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java
@@ -0,0 +1,68 @@
+package cgeo.geocaching.connector.gc;
+
+import cgeo.geocaching.utils.Log;
+
+import android.os.Handler;
+import android.os.Message;
+
+abstract public class AbstractSearchThread extends Thread {
+ private Handler recaptchaHandler = null;
+ private String recaptchaChallenge = null;
+ private String recaptchaText = null;
+ private final Handler handler;
+ private static AbstractSearchThread currentInstance;
+
+ public AbstractSearchThread(final Handler handler) {
+ this.handler = handler;
+ }
+
+ public void setRecaptchaHandler(Handler recaptchaHandlerIn) {
+ recaptchaHandler = recaptchaHandlerIn;
+ }
+
+ public void notifyNeed() {
+ if (recaptchaHandler != null) {
+ recaptchaHandler.sendEmptyMessage(1);
+ }
+ }
+
+ public synchronized void waitForUser() {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ Log.w("searchThread is not waiting for user...");
+ }
+ }
+
+ public void setChallenge(String challenge) {
+ recaptchaChallenge = challenge;
+ }
+
+ public String getChallenge() {
+ return recaptchaChallenge;
+ }
+
+ public synchronized void setText(String text) {
+ recaptchaText = text;
+
+ notify();
+ }
+
+ public synchronized String getText() {
+ return recaptchaText;
+ }
+
+ @Override
+ final public void run() {
+ super.run();
+ currentInstance = this;
+ runSearch();
+ handler.sendMessage(Message.obtain());
+ }
+
+ protected abstract void runSearch();
+
+ public static AbstractSearchThread getCurrentInstance() {
+ return currentInstance;
+ }
+}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index b461cc2..fbda5cd 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -6,7 +6,10 @@ import cgeo.geocaching.Settings;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.AbstractConnector;
+import cgeo.geocaching.connector.capability.ISearchByCenter;
+import cgeo.geocaching.connector.capability.ISearchByGeocode;
import cgeo.geocaching.enumerations.StatusCode;
+import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.CancellableHandler;
@@ -15,10 +18,9 @@ import cgeo.geocaching.utils.Log;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import java.util.Set;
import java.util.regex.Pattern;
-public class GCConnector extends AbstractConnector {
+public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter {
private static GCConnector instance;
private static final Pattern gpxZipFilePattern = Pattern.compile("\\d{7,}(_.+)?\\.zip", Pattern.CASE_INSENSITIVE);
@@ -43,11 +45,6 @@ public class GCConnector extends AbstractConnector {
}
@Override
- public boolean supportsRefreshCache(cgCache cache) {
- return true;
- }
-
- @Override
public String getCacheUrl(cgCache cache) {
// it would also be possible to use "http://www.geocaching.com/seek/cache_details.aspx?wp=" + cache.getGeocode();
return "http://coord.info/" + cache.getGeocode();
@@ -79,18 +76,7 @@ public class GCConnector extends AbstractConnector {
}
@Override
- public boolean supportsCachesAround() {
- return true;
- }
-
- @Override
- public SearchResult searchByGeocode(final String geocode, final String guid, final cgeoapplication app, final CancellableHandler handler) {
-
- if (app == null) {
- Log.e("cgeoBase.searchByGeocode: No application found");
- return null;
- }
-
+ public SearchResult searchByGeocode(final String geocode, final String guid, final CancellableHandler handler) {
final Parameters params = new Parameters("decrypt", "y");
if (StringUtils.isNotBlank(geocode)) {
params.put("wp", geocode);
@@ -106,11 +92,11 @@ public class GCConnector extends AbstractConnector {
if (StringUtils.isEmpty(page)) {
final SearchResult search = new SearchResult();
- if (app.isThere(geocode, guid, true, false)) {
+ if (cgeoapplication.getInstance().isThere(geocode, guid, true, false)) {
if (StringUtils.isBlank(geocode) && StringUtils.isNotBlank(guid)) {
Log.i("Loading old cache from cache.");
- search.addGeocode(app.getGeocode(guid));
+ search.addGeocode(cgeoapplication.getInstance().getGeocode(guid));
} else {
search.addGeocode(geocode);
}
@@ -134,13 +120,8 @@ public class GCConnector extends AbstractConnector {
}
@Override
- public SearchResult searchByGeocodes(Set<String> geocodes) {
- return GCBase.searchByGeocodes(geocodes);
- }
-
- @Override
public SearchResult searchByViewport(Viewport viewport, String[] tokens) {
- return GCBase.searchByViewport(viewport, tokens);
+ return GCMap.searchByViewport(viewport, tokens);
}
@Override
@@ -153,8 +134,18 @@ public class GCConnector extends AbstractConnector {
return cacheHasReliableLatLon;
}
+ public static int addToWatchlist(cgCache cache) {
+ return GCParser.addToWatchlist(cache);
+ }
+
+ public static int removeFromWatchlist(cgCache cache) {
+ return GCParser.removeFromWatchlist(cache);
+ }
+
@Override
- public String[] getTokens() {
- return GCBase.getTokens();
+ public SearchResult searchByCenter(Geopoint center) {
+ // TODO make search by coordinate use this method. currently it is just a marker that this connector supports search by center
+ return null;
}
+
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
index 083626d..21dde03 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
@@ -158,7 +158,37 @@ public final class GCConstants {
/** Number of logs to retrieve from GC.com */
public final static int NUMBER_OF_LOGS = 35;
+ private final static String SEQUENCE_GCID = "0123456789ABCDEFGHJKMNPQRTVWXYZ";
+ private final static long GC_BASE31 = 31;
+ private final static long GC_BASE16 = 16;
+
+ /**
+ * Convert GCCode (geocode) to (old) GCIds
+ *
+ * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40
+ * see http://support.groundspeak.com/index.php?pg=kb.printer.friendly&id=1#p221
+ */
+ public static long gccodeToGCId(final String gccode) {
+ long gcid = 0;
+ long base = GC_BASE31;
+ String geocodeWO = gccode.substring(2).toUpperCase();
+
+ if ((geocodeWO.length() < 4) || (geocodeWO.length() == 4 && SEQUENCE_GCID.indexOf(geocodeWO.charAt(0)) < 16)) {
+ base = GC_BASE16;
+ }
+
+ for (int p = 0; p < geocodeWO.length(); p++) {
+ gcid = base * gcid + SEQUENCE_GCID.indexOf(geocodeWO.charAt(p));
+ }
+
+ if (base == GC_BASE31) {
+ gcid += Math.pow(16, 4) - 16 * Math.pow(31, 3);
+ }
+ return gcid;
+ }
+
private GCConstants() {
// this class shall not have instances
}
+
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCBase.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index 64e5875..c7cb40f 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCBase.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -1,6 +1,5 @@
package cgeo.geocaching.connector.gc;
-import cgeo.geocaching.ICoordinates;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
import cgeo.geocaching.cgCache;
@@ -13,16 +12,13 @@ import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.IConversion;
import cgeo.geocaching.geopoint.Viewport;
-import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.ui.Formatter;
-import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.LeastRecentlyUsedMap;
import cgeo.geocaching.utils.Log;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import org.apache.http.HttpResponse;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -31,172 +27,80 @@ import android.graphics.Bitmap;
import java.text.ParseException;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-/**
- * GC.com/Groundspeak (GS) specific stuff
- *
- * @author blafoo
- *
- */
-public class GCBase {
-
- protected final static String SEQUENCE_GCID = "0123456789ABCDEFGHJKMNPQRTVWXYZ";
- protected final static long GC_BASE31 = 31;
- protected final static long GC_BASE16 = 16;
-
- private final static LeastRecentlyUsedMap<Integer, Tile> tileCache = new LeastRecentlyUsedMap.LruCache<Integer, Tile>(64);
+public class GCMap {
private static Viewport lastSearchViewport = null;
- /**
- * Searches the view port on the live map with Strategy.AUTO
- *
- * @param viewport
- * Area to search
- * @param tokens
- * Live map tokens
- * @return
- */
- public static SearchResult searchByViewport(final Viewport viewport, final String[] tokens) {
- Strategy strategy = Settings.getLiveMapStrategy();
- if (strategy == Strategy.AUTO) {
- float speedNow = cgeoapplication.getInstance().currentGeo().getSpeed();
- strategy = speedNow >= 8 ? Strategy.FAST : Strategy.DETAILED; // 8 m/s = 30 km/h
- }
- // return searchByViewport(viewport, tokens, strategy);
-
- // testing purpose
- {
- SearchResult result = searchByViewport(viewport, tokens, strategy);
- String text = Formatter.SEPARATOR + strategy.getL10n() + Formatter.SEPARATOR;
- int speed = (int) cgeoapplication.getInstance().currentGeo().getSpeed();
- if (Settings.isUseMetricUnits()) {
- text += speed + " km/h";
- } else {
- text += speed / IConversion.MILES_TO_KILOMETER + " mph";
- }
- result.setUrl(result.getUrl() + text);
- return result;
- }
- }
-
- public static void removeFromTileCache(final ICoordinates point) {
- if (point != null) {
- Collection<Tile> tiles = new ArrayList<Tile>(tileCache.values());
- for (Tile tile : tiles) {
- if (tile.containsPoint(point)) {
- tileCache.remove(tile.hashCode());
- }
- }
- }
- }
-
- /**
- * Searches the view port on the live map for caches.
- * The strategy dictates if only live map information is used or if an additional
- * searchByCoordinates query is issued.
- *
- * @param viewport
- * Area to search
- * @param tokens
- * Live map tokens
- * @param strategy
- * Strategy for data retrieval and parsing, @see Strategy
- * @return
- */
- private static SearchResult searchByViewport(final Viewport viewport, final String[] tokens, Strategy strategy) {
- Log.d("GCBase.searchByViewport" + viewport.toString());
-
- String referer = GCConstants.URL_LIVE_MAP;
-
- final SearchResult searchResult = new SearchResult();
- searchResult.setUrl(referer + "?ll=" + viewport.getCenter().getLatitude() + "," + viewport.getCenter().getLongitude());
+ public static SearchResult searchByGeocodes(Set<String> geocodes) {
+ final SearchResult result = new SearchResult();
- if (strategy.flags.contains(StrategyFlag.LOAD_TILES)) {
- final Set<Tile> tiles = getTilesForViewport(viewport);
+ final String geocodeList = StringUtils.join(geocodes.toArray(), "|");
+ final String referer = GCConstants.URL_LIVE_MAP_DETAILS;
- for (Tile tile : tiles) {
+ try {
+ final Parameters params = new Parameters("i", geocodeList, "_", String.valueOf(System.currentTimeMillis()));
+ final String data = StringUtils.defaultString(Tile.requestMapInfo(referer, params, referer));
- if (!tileCache.containsKey(tile.hashCode())) {
- final Parameters params = new Parameters(
- "x", String.valueOf(tile.getX()),
- "y", String.valueOf(tile.getY()),
- "z", String.valueOf(tile.getZoomlevel()),
- "ep", "1");
- if (tokens != null) {
- params.put("k", tokens[0], "st", tokens[1]);
- }
- if (Settings.isExcludeMyCaches()) {
- params.put("hf", "1", "hh", "1"); // hide found, hide hidden
- }
- if (Settings.getCacheType() == CacheType.TRADITIONAL) {
- params.put("ect", "9,5,3,6,453,13,1304,137,11,4,8,1858"); // 2 = tradi 3 = multi 8 = mystery
- } else if (Settings.getCacheType() == CacheType.MULTI) {
- params.put("ect", "9,5,2,6,453,13,1304,137,11,4,8,1858");
- } else if (Settings.getCacheType() == CacheType.MYSTERY) {
- params.put("ect", "9,5,3,6,453,13,1304,137,11,4,2,1858");
- }
- if (tile.getZoomlevel() != 14) {
- params.put("_", String.valueOf(System.currentTimeMillis()));
- }
- // TODO: other types t.b.d
+ // Example JSON information
+ // {"status":"success",
+ // "data":[{"name":"Mission: Impossible","gc":"GC1234","g":"34c2e609-5246-4f91-9029-d6c02b0f2a82","available":true,"archived":false,"subrOnly":false,"li":false,"fp":"5","difficulty":{"text":3.5,"value":"3_5"},"terrain":{"text":1.0,"value":"1"},"hidden":"7/23/2001","container":{"text":"Regular","value":"regular.gif"},"type":{"text":"Unknown Cache","value":8},"owner":{"text":"Ca$h_Cacher","value":"2db18e69-6877-402a-848d-6362621424f6"}},
+ // {"name":"HP: Hannover - Sahlkamp","gc":"GC2Q97X","g":"a09149ca-00e0-4aa2-b332-db2b4dfb18d2","available":true,"archived":false,"subrOnly":false,"li":false,"fp":"0","difficulty":{"text":1.0,"value":"1"},"terrain":{"text":1.5,"value":"1_5"},"hidden":"5/29/2011","container":{"text":"Small","value":"small.gif"},"type":{"text":"Traditional Cache","value":2},"owner":{"text":"GeoM@n","value":"1deaa69e-6bcc-421d-95a1-7d32b468cb82"}}]
+ // }
- // The PNG must be requested first, otherwise the following request would always return with 204 - No Content
- Bitmap bitmap = Tile.requestMapTile(GCConstants.URL_MAP_TILE, params, referer);
+ final JSONObject json = new JSONObject(data);
+ final String status = json.getString("status");
+ if (StringUtils.isBlank(status)) {
- // Check bitmap size
- if (bitmap != null && (bitmap.getWidth() != Tile.TILE_SIZE ||
- bitmap.getHeight() != Tile.TILE_SIZE)) {
- bitmap.recycle();
- bitmap = null;
- }
+ throw new JSONException("No status inside JSON");
+ }
+ if ("success".compareTo(status) != 0) {
+ throw new JSONException("Wrong status inside JSON");
+ }
+ final JSONArray dataArray = json.getJSONArray("data");
+ if (dataArray == null) {
+ throw new JSONException("No data inside JSON");
+ }
- String data = Tile.requestMapInfo(GCConstants.URL_MAP_INFO, params, referer);
- if (StringUtils.isEmpty(data)) {
- Log.e("GCBase.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")");
- } else {
- final SearchResult search = parseMapJSON(data, tile, bitmap, strategy);
- if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) {
- Log.e("GCBase.searchByViewport: No cache parsed for viewport " + viewport);
- }
- else {
- searchResult.addGeocodes(search.getGeocodes());
- }
- tileCache.put(tile.hashCode(), tile);
- }
+ for (int j = 0; j < dataArray.length(); j++) {
+ final cgCache cache = new cgCache();
- // release native bitmap memory
- if (bitmap != null) {
- bitmap.recycle();
- }
+ JSONObject dataObject = dataArray.getJSONObject(j);
+ cache.setName(dataObject.getString("name"));
+ cache.setGeocode(dataObject.getString("gc"));
+ cache.setGuid(dataObject.getString("g")); // 34c2e609-5246-4f91-9029-d6c02b0f2a82"
+ cache.setDisabled(!dataObject.getBoolean("available"));
+ cache.setArchived(dataObject.getBoolean("archived"));
+ cache.setPremiumMembersOnly(dataObject.getBoolean("subrOnly"));
+ // "li" seems to be "false" always
+ cache.setFavoritePoints(Integer.parseInt(dataObject.getString("fp")));
+ JSONObject difficultyObj = dataObject.getJSONObject("difficulty");
+ cache.setDifficulty(Float.parseFloat(difficultyObj.getString("text"))); // 3.5
+ JSONObject terrainObj = dataObject.getJSONObject("terrain");
+ cache.setTerrain(Float.parseFloat(terrainObj.getString("text"))); // 1.5
+ cache.setHidden(Login.parseGcCustomDate(dataObject.getString("hidden"), "MM/dd/yyyy")); // 7/23/2001
+ JSONObject containerObj = dataObject.getJSONObject("container");
+ cache.setSize(CacheSize.getById(containerObj.getString("text"))); // Regular
+ JSONObject typeObj = dataObject.getJSONObject("type");
+ cache.setType(CacheType.getByPattern(typeObj.getString("text"))); // Traditional Cache
+ JSONObject ownerObj = dataObject.getJSONObject("owner");
+ cache.setOwner(ownerObj.getString("text"));
- }
- }
- }
+ result.addCache(cache);
- if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY)) {
- final Geopoint center = viewport.getCenter();
- if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) {
- SearchResult search = GCParser.searchByCoords(null, center, Settings.getCacheType(), false);
- if (search != null && !search.isEmpty()) {
- final Set<String> geocodes = search.getGeocodes();
- if (Settings.isPremiumMember()) {
- lastSearchViewport = cgeoapplication.getInstance().getBounds(geocodes);
- } else {
- lastSearchViewport = new Viewport(center, 0.01, 0.01);
- }
- searchResult.addGeocodes(geocodes);
- }
}
+ } catch (JSONException e) {
+ result.setError(StatusCode.UNKNOWN_ERROR);
+ } catch (ParseException e) {
+ result.setError(StatusCode.UNKNOWN_ERROR);
+ } catch (NumberFormatException e) {
+ result.setError(StatusCode.UNKNOWN_ERROR);
}
-
- return searchResult;
+ return result;
}
/**
@@ -313,125 +217,135 @@ public class GCBase {
return searchResult;
}
-
/**
- * Calculate needed tiles for the given viewport
- *
+ * Searches the view port on the live map with Strategy.AUTO
+ *
* @param viewport
+ * Area to search
+ * @param tokens
+ * Live map tokens
* @return
*/
- protected static Set<Tile> getTilesForViewport(final Viewport viewport) {
- Set<Tile> tiles = new HashSet<Tile>();
- int zoom = Math.min(Tile.calcZoomLon(viewport.bottomLeft, viewport.topRight),
- Tile.calcZoomLat(viewport.bottomLeft, viewport.topRight));
- tiles.add(new Tile(viewport.bottomLeft, zoom));
- tiles.add(new Tile(new Geopoint(viewport.getLatitudeMin(), viewport.getLongitudeMax()), zoom));
- tiles.add(new Tile(new Geopoint(viewport.getLatitudeMax(), viewport.getLongitudeMin()), zoom));
- tiles.add(new Tile(viewport.topRight, zoom));
- return tiles;
- }
-
- /**
- * Convert GCCode (geocode) to (old) GCIds
- *
- * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40
- * see http://support.groundspeak.com/index.php?pg=kb.printer.friendly&id=1#p221
- */
- public static long gccodeToGCId(final String gccode) {
- long gcid = 0;
- long base = GC_BASE31;
- String geocodeWO = gccode.substring(2).toUpperCase();
-
- if ((geocodeWO.length() < 4) || (geocodeWO.length() == 4 && SEQUENCE_GCID.indexOf(geocodeWO.charAt(0)) < 16)) {
- base = GC_BASE16;
- }
-
- for (int p = 0; p < geocodeWO.length(); p++) {
- gcid = base * gcid + SEQUENCE_GCID.indexOf(geocodeWO.charAt(p));
+ public static SearchResult searchByViewport(final Viewport viewport, final String[] tokens) {
+ Strategy strategy = Settings.getLiveMapStrategy();
+ if (strategy == Strategy.AUTO) {
+ float speedNow = cgeoapplication.getInstance().currentGeo().getSpeed();
+ strategy = speedNow >= 8 ? Strategy.FAST : Strategy.DETAILED; // 8 m/s = 30 km/h
}
+ // return searchByViewport(viewport, tokens, strategy);
- if (base == GC_BASE31) {
- gcid += Math.pow(16, 4) - 16 * Math.pow(31, 3);
+ // testing purpose
+ {
+ SearchResult result = searchByViewport(viewport, tokens, strategy);
+ String text = Formatter.SEPARATOR + strategy.getL10n() + Formatter.SEPARATOR;
+ int speed = (int) cgeoapplication.getInstance().currentGeo().getSpeed();
+ if (Settings.isUseMetricUnits()) {
+ text += speed + " km/h";
+ } else {
+ text += speed / IConversion.MILES_TO_KILOMETER + " mph";
+ }
+ result.setUrl(result.getUrl() + text);
+ return result;
}
- return gcid;
- }
-
- /** Get user session & session token from the Live Map. Needed for following requests */
- public static String[] getTokens() {
- final HttpResponse response = Network.getRequest(GCConstants.URL_LIVE_MAP);
- final String data = Network.getResponseData(response);
- String userSession = BaseUtils.getMatch(data, GCConstants.PATTERN_USERSESSION, "");
- String sessionToken = BaseUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, "");
- return new String[] { userSession, sessionToken };
}
- public static SearchResult searchByGeocodes(final Set<String> geocodes) {
-
- final SearchResult result = new SearchResult();
+ /**
+ * Searches the view port on the live map for caches.
+ * The strategy dictates if only live map information is used or if an additional
+ * searchByCoordinates query is issued.
+ *
+ * @param viewport
+ * Area to search
+ * @param tokens
+ * Live map tokens
+ * @param strategy
+ * Strategy for data retrieval and parsing, @see Strategy
+ * @return
+ */
+ private static SearchResult searchByViewport(final Viewport viewport, final String[] tokens, Strategy strategy) {
+ Log.d("GCBase.searchByViewport" + viewport.toString());
- final String geocodeList = StringUtils.join(geocodes.toArray(), "|");
- final String referer = GCConstants.URL_LIVE_MAP_DETAILS;
+ final SearchResult searchResult = new SearchResult();
+ searchResult.setUrl(GCConstants.URL_LIVE_MAP + "?ll=" + viewport.getCenter().getLatitude() + "," + viewport.getCenter().getLongitude());
- try {
- final Parameters params = new Parameters("i", geocodeList, "_", String.valueOf(System.currentTimeMillis()));
- final String data = StringUtils.defaultString(Tile.requestMapInfo(referer, params, referer));
+ if (strategy.flags.contains(StrategyFlag.LOAD_TILES)) {
+ final Set<Tile> tiles = Tile.getTilesForViewport(viewport);
- // Example JSON information
- // {"status":"success",
- // "data":[{"name":"Mission: Impossible","gc":"GC1234","g":"34c2e609-5246-4f91-9029-d6c02b0f2a82","available":true,"archived":false,"subrOnly":false,"li":false,"fp":"5","difficulty":{"text":3.5,"value":"3_5"},"terrain":{"text":1.0,"value":"1"},"hidden":"7/23/2001","container":{"text":"Regular","value":"regular.gif"},"type":{"text":"Unknown Cache","value":8},"owner":{"text":"Ca$h_Cacher","value":"2db18e69-6877-402a-848d-6362621424f6"}},
- // {"name":"HP: Hannover - Sahlkamp","gc":"GC2Q97X","g":"a09149ca-00e0-4aa2-b332-db2b4dfb18d2","available":true,"archived":false,"subrOnly":false,"li":false,"fp":"0","difficulty":{"text":1.0,"value":"1"},"terrain":{"text":1.5,"value":"1_5"},"hidden":"5/29/2011","container":{"text":"Small","value":"small.gif"},"type":{"text":"Traditional Cache","value":2},"owner":{"text":"GeoM@n","value":"1deaa69e-6bcc-421d-95a1-7d32b468cb82"}}]
- // }
+ for (Tile tile : tiles) {
- final JSONObject json = new JSONObject(data);
- final String status = json.getString("status");
- if (StringUtils.isBlank(status)) {
+ if (!Tile.Cache.contains(tile)) {
+ final Parameters params = new Parameters(
+ "x", String.valueOf(tile.getX()),
+ "y", String.valueOf(tile.getY()),
+ "z", String.valueOf(tile.getZoomlevel()),
+ "ep", "1");
+ if (tokens != null) {
+ params.put("k", tokens[0], "st", tokens[1]);
+ }
+ if (Settings.isExcludeMyCaches()) {
+ params.put("hf", "1", "hh", "1"); // hide found, hide hidden
+ }
+ if (Settings.getCacheType() == CacheType.TRADITIONAL) {
+ params.put("ect", "9,5,3,6,453,13,1304,137,11,4,8,1858"); // 2 = tradi 3 = multi 8 = mystery
+ } else if (Settings.getCacheType() == CacheType.MULTI) {
+ params.put("ect", "9,5,2,6,453,13,1304,137,11,4,8,1858");
+ } else if (Settings.getCacheType() == CacheType.MYSTERY) {
+ params.put("ect", "9,5,3,6,453,13,1304,137,11,4,2,1858");
+ }
+ if (tile.getZoomlevel() != 14) {
+ params.put("_", String.valueOf(System.currentTimeMillis()));
+ }
+ // TODO: other types t.b.d
- throw new JSONException("No status inside JSON");
- }
- if ("success".compareTo(status) != 0) {
- throw new JSONException("Wrong status inside JSON");
- }
- final JSONArray dataArray = json.getJSONArray("data");
- if (dataArray == null) {
- throw new JSONException("No data inside JSON");
- }
+ // The PNG must be requested first, otherwise the following request would always return with 204 - No Content
+ Bitmap bitmap = Tile.requestMapTile(params);
- for (int j = 0; j < dataArray.length(); j++) {
+ // Check bitmap size
+ if (bitmap != null && (bitmap.getWidth() != Tile.TILE_SIZE ||
+ bitmap.getHeight() != Tile.TILE_SIZE)) {
+ bitmap.recycle();
+ bitmap = null;
+ }
- cgCache cache = new cgCache();
+ String data = Tile.requestMapInfo(GCConstants.URL_MAP_INFO, params, GCConstants.URL_LIVE_MAP);
+ if (StringUtils.isEmpty(data)) {
+ Log.e("GCBase.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())) {
+ Log.e("GCBase.searchByViewport: No cache parsed for viewport " + viewport);
+ }
+ else {
+ searchResult.addGeocodes(search.getGeocodes());
+ }
+ Tile.Cache.add(tile);
+ }
- JSONObject dataObject = dataArray.getJSONObject(j);
- cache.setName(dataObject.getString("name"));
- cache.setGeocode(dataObject.getString("gc"));
- cache.setGuid(dataObject.getString("g")); // 34c2e609-5246-4f91-9029-d6c02b0f2a82"
- cache.setDisabled(!dataObject.getBoolean("available"));
- cache.setArchived(dataObject.getBoolean("archived"));
- cache.setPremiumMembersOnly(dataObject.getBoolean("subrOnly"));
- // "li" seems to be "false" always
- cache.setFavoritePoints(Integer.parseInt(dataObject.getString("fp")));
- JSONObject difficultyObj = dataObject.getJSONObject("difficulty");
- cache.setDifficulty(Float.parseFloat(difficultyObj.getString("text"))); // 3.5
- JSONObject terrainObj = dataObject.getJSONObject("terrain");
- cache.setTerrain(Float.parseFloat(terrainObj.getString("text"))); // 1.5
- cache.setHidden(Login.parseGcCustomDate(dataObject.getString("hidden"), "MM/dd/yyyy")); // 7/23/2001
- JSONObject containerObj = dataObject.getJSONObject("container");
- cache.setSize(CacheSize.getById(containerObj.getString("text"))); // Regular
- JSONObject typeObj = dataObject.getJSONObject("type");
- cache.setType(CacheType.getByPattern(typeObj.getString("text"))); // Traditional Cache
- JSONObject ownerObj = dataObject.getJSONObject("owner");
- cache.setOwner(ownerObj.getString("text"));
+ // release native bitmap memory
+ if (bitmap != null) {
+ bitmap.recycle();
+ }
- result.addCache(cache);
+ }
+ }
+ }
+ if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY)) {
+ final Geopoint center = viewport.getCenter();
+ if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) {
+ SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false);
+ if (search != null && !search.isEmpty()) {
+ final Set<String> geocodes = search.getGeocodes();
+ if (Settings.isPremiumMember()) {
+ lastSearchViewport = cgeoapplication.getInstance().getBounds(geocodes);
+ } else {
+ lastSearchViewport = new Viewport(center, 0.01, 0.01);
+ }
+ searchResult.addGeocodes(geocodes);
+ }
}
- } catch (JSONException e) {
- result.setError(StatusCode.UNKNOWN_ERROR);
- } catch (ParseException e) {
- result.setError(StatusCode.UNKNOWN_ERROR);
- } catch (NumberFormatException e) {
- result.setError(StatusCode.UNKNOWN_ERROR);
}
- return result;
- }
+ return searchResult;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index 9b397c9..3d2e994 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -7,7 +7,6 @@ import cgeo.geocaching.Settings;
import cgeo.geocaching.TrackableLog;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgImage;
-import cgeo.geocaching.cgSearchThread;
import cgeo.geocaching.cgTrackable;
import cgeo.geocaching.cgWaypoint;
import cgeo.geocaching.cgeoapplication;
@@ -61,7 +60,7 @@ public abstract class GCParser {
private final static SimpleDateFormat dateTbIn1 = new SimpleDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009
private final static SimpleDateFormat dateTbIn2 = new SimpleDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009
- private static SearchResult parseSearch(final cgSearchThread thread, final String url, final String pageContent, final boolean showCaptcha) {
+ private static SearchResult parseSearch(final String url, final String pageContent, final boolean showCaptcha) {
if (StringUtils.isBlank(pageContent)) {
Log.e("cgeoBase.parseSearch: No page given");
return null;
@@ -77,6 +76,7 @@ public abstract class GCParser {
searchResult.viewstates = Login.getViewstates(page);
// recaptcha
+ AbstractSearchThread thread = AbstractSearchThread.getCurrentInstance();
if (showCaptcha) {
String recaptchaJsParam = BaseUtils.getMatch(page, GCConstants.PATTERN_SEARCH_RECAPTCHA, false, null);
@@ -305,7 +305,7 @@ public abstract class GCParser {
return searchResult;
}
- public static SearchResult parseCache(final String page, final CancellableHandler handler) {
+ static SearchResult parseCache(final String page, final CancellableHandler handler) {
final SearchResult searchResult = parseCacheFromText(page, handler);
if (searchResult != null && !searchResult.getGeocodes().isEmpty()) {
final cgCache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
@@ -710,7 +710,7 @@ public abstract class GCParser {
return searchResult;
}
- public static SearchResult searchByNextPage(cgSearchThread thread, final SearchResult search, boolean showCaptcha) {
+ public static SearchResult searchByNextPage(final SearchResult search, boolean showCaptcha) {
if (search == null) {
return search;
}
@@ -747,7 +747,7 @@ public abstract class GCParser {
return search;
}
- final SearchResult searchResult = parseSearch(thread, url, page, showCaptcha);
+ final SearchResult searchResult = parseSearch(url, page, showCaptcha);
if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) {
Log.e("cgeoBase.searchByNextPage: No cache parsed");
return search;
@@ -771,7 +771,7 @@ public abstract class GCParser {
* @param addF
* @return the original params if not null, maybe augmented with f=1, or a new Parameters with f=1 or null otherwise
*/
- public static Parameters addFToParams(final Parameters params, final boolean my, final boolean addF) {
+ private static Parameters addFToParams(final Parameters params, final boolean my, final boolean addF) {
if (!my && Settings.isExcludeMyCaches() && addF) {
if (params == null) {
return new Parameters("f", "1");
@@ -784,8 +784,6 @@ public abstract class GCParser {
}
/**
- * @param thread
- * thread to run the captcha if needed
* @param cacheType
* @param listId
* @param showCaptcha
@@ -793,7 +791,7 @@ public abstract class GCParser {
* the parameters to add to the request URI
* @return
*/
- private static SearchResult searchByAny(final cgSearchThread thread, final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params) {
+ private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params) {
insertCacheType(params, cacheType);
final String uri = "http://www.geocaching.com/seek/nearest.aspx";
@@ -805,7 +803,7 @@ public abstract class GCParser {
return null;
}
- final SearchResult searchResult = parseSearch(thread, fullUri, page, showCaptcha);
+ final SearchResult searchResult = parseSearch(fullUri, page, showCaptcha);
if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) {
Log.e("cgeoBase.searchByAny: No cache parsed");
return searchResult;
@@ -818,22 +816,22 @@ public abstract class GCParser {
return search;
}
- public static SearchResult searchByCoords(final cgSearchThread thread, final Geopoint coords, final CacheType cacheType, final boolean showCaptcha) {
+ public static SearchResult searchByCoords(final Geopoint coords, final CacheType cacheType, final boolean showCaptcha) {
final Parameters params = new Parameters("lat", Double.toString(coords.getLatitude()), "lng", Double.toString(coords.getLongitude()));
- return searchByAny(thread, cacheType, false, showCaptcha, params);
+ return searchByAny(cacheType, false, showCaptcha, params);
}
- public static SearchResult searchByKeyword(final cgSearchThread thread, final String keyword, final CacheType cacheType, final boolean showCaptcha) {
+ public static SearchResult searchByKeyword(final String keyword, final CacheType cacheType, final boolean showCaptcha) {
if (StringUtils.isBlank(keyword)) {
Log.e("cgeoBase.searchByKeyword: No keyword given");
return null;
}
final Parameters params = new Parameters("key", keyword);
- return searchByAny(thread, cacheType, false, showCaptcha, params);
+ return searchByAny(cacheType, false, showCaptcha, params);
}
- public static SearchResult searchByUsername(final cgSearchThread thread, final String userName, final CacheType cacheType, final boolean showCaptcha) {
+ public static SearchResult searchByUsername(final String userName, final CacheType cacheType, final boolean showCaptcha) {
if (StringUtils.isBlank(userName)) {
Log.e("cgeoBase.searchByUsername: No user name given");
return null;
@@ -847,17 +845,17 @@ public abstract class GCParser {
Log.i("cgBase.searchByUsername: Overriding users choice, downloading all caches.");
}
- return searchByAny(thread, cacheType, my, showCaptcha, params);
+ return searchByAny(cacheType, my, showCaptcha, params);
}
- public static SearchResult searchByOwner(final cgSearchThread thread, final String userName, final CacheType cacheType, final boolean showCaptcha) {
+ public static SearchResult searchByOwner(final String userName, final CacheType cacheType, final boolean showCaptcha) {
if (StringUtils.isBlank(userName)) {
Log.e("cgeoBase.searchByOwner: No user name given");
return null;
}
final Parameters params = new Parameters("u", userName);
- return searchByAny(thread, cacheType, false, showCaptcha, params);
+ return searchByAny(cacheType, false, showCaptcha, params);
}
public static cgTrackable searchTrackable(final String geocode, final String guid, final String id) {
@@ -885,7 +883,7 @@ public abstract class GCParser {
return trackable;
}
- trackable = parseTrackable(page, cgeoapplication.getInstance(), geocode);
+ trackable = parseTrackable(page, geocode);
if (trackable == null) {
Log.e("cgeoBase.searchTrackable: No trackable parsed");
return null;
@@ -1108,7 +1106,7 @@ public abstract class GCParser {
* the cache to add
* @return -1: error occured
*/
- public static int addToWatchlist(final cgCache cache) {
+ static int addToWatchlist(final cgCache cache) {
final String uri = "http://www.geocaching.com/my/watchlist.aspx?w=" + cache.getCacheId();
String page = Login.postRequestLogged(uri, null);
@@ -1134,7 +1132,7 @@ public abstract class GCParser {
* the cache to remove
* @return -1: error occured
*/
- public static int removeFromWatchlist(final cgCache cache) {
+ static int removeFromWatchlist(final cgCache cache) {
final String uri = "http://www.geocaching.com/my/watchlist.aspx?ds=1&action=rem&id=" + cache.getCacheId();
String page = Login.postRequestLogged(uri, null);
@@ -1170,7 +1168,7 @@ public abstract class GCParser {
* if not null, the application to use to save the trackable
* @return the parsed trackable, or null if none could be parsed
*/
- public static cgTrackable parseTrackable(final String page, final cgeoapplication app, final String possibleTrackingcode) {
+ static cgTrackable parseTrackable(final String page, final String possibleTrackingcode) {
if (StringUtils.isBlank(page)) {
Log.e("cgeoBase.parseTrackable: No page given");
return null;
@@ -1332,8 +1330,8 @@ public abstract class GCParser {
trackable.setTrackingcode(possibleTrackingcode);
}
- if (app != null) {
- app.saveTrackable(trackable);
+ if (cgeoapplication.getInstance() != null) {
+ cgeoapplication.getInstance().saveTrackable(trackable);
}
return trackable;
diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java
index c39fcef..113f581 100644
--- a/main/src/cgeo/geocaching/connector/gc/Login.java
+++ b/main/src/cgeo/geocaching/connector/gc/Login.java
@@ -433,4 +433,12 @@ public abstract class Login {
return data;
}
+ /** Get user session & session token from the Live Map. Needed for following requests */
+ public static String[] getMapTokens() {
+ final HttpResponse response = Network.getRequest(GCConstants.URL_LIVE_MAP);
+ final String data = Network.getResponseData(response);
+ final String userSession = BaseUtils.getMatch(data, GCConstants.PATTERN_USERSESSION, "");
+ final String sessionToken = BaseUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, "");
+ return new String[] { userSession, sessionToken };
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/gc/SearchHandler.java b/main/src/cgeo/geocaching/connector/gc/SearchHandler.java
new file mode 100644
index 0000000..45efff2
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/gc/SearchHandler.java
@@ -0,0 +1,107 @@
+package cgeo.geocaching.connector.gc;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.utils.Log;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Handler;
+import android.os.Message;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.ImageView;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public class SearchHandler extends Handler {
+ private Activity activity = null;
+ private Resources res = null;
+ private AbstractSearchThread recaptchaThread = null;
+ private ImageView imageView = null;
+ private Bitmap img = null;
+
+ private Handler imgHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ if (img != null && imageView != null) {
+ imageView.setImageBitmap(img);
+ }
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+ };
+
+ public SearchHandler(Activity activityIn, Resources resIn, AbstractSearchThread recaptchaThreadIn) {
+ activity = activityIn;
+ res = resIn;
+ recaptchaThread = recaptchaThreadIn;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ if (msg.what == 1) {
+ final AlertDialog.Builder dlg = new AlertDialog.Builder(activity);
+ final LayoutInflater inflater = activity.getLayoutInflater();
+ final View view = inflater.inflate(R.layout.recaptcha_dialog, null);
+
+ imageView = (ImageView) view.findViewById(R.id.image);
+
+ (new getCaptcha(new URL("http://www.google.com/recaptcha/api/image?c=" + recaptchaThread.getChallenge()))).start();
+
+ dlg.setTitle(res.getString(R.string.caches_recaptcha_title));
+ dlg.setView(view);
+ dlg.setNeutralButton(res.getString(R.string.caches_recaptcha_continue), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ final String text = ((EditText) view.findViewById(R.id.text)).getText().toString();
+
+ recaptchaThread.setText(text);
+
+ dialog.cancel();
+ }
+ });
+
+ dlg.create().show();
+ }
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+
+ private class getCaptcha extends Thread {
+ private URL uri = null;
+
+ public getCaptcha(URL uriIn) {
+ uri = uriIn;
+ }
+
+ @Override
+ public void run() {
+ try {
+ HttpURLConnection connection = (HttpURLConnection) uri.openConnection();
+ connection.setDoInput(true);
+ connection.connect();
+
+ InputStream is = connection.getInputStream();
+
+ img = BitmapFactory.decodeStream(is);
+
+ is.close();
+
+ imgHandler.sendEmptyMessage(0);
+ } catch (IOException e) {
+ Log.e("Failed to download reCAPTCHA image");
+ }
+ }
+ }
+}
diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java
index 692f28b..4747912 100644
--- a/main/src/cgeo/geocaching/connector/gc/Tile.java
+++ b/main/src/cgeo/geocaching/connector/gc/Tile.java
@@ -5,6 +5,7 @@ import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.utils.LeastRecentlyUsedMap;
import cgeo.geocaching.utils.Log;
import org.apache.http.HttpResponse;
@@ -13,6 +14,10 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
/**
* All about tiles.
@@ -213,8 +218,8 @@ public class Tile {
}
/** Request .png image for a tile. */
- public static Bitmap requestMapTile(final String url, final Parameters params, final String referer) {
- final HttpResponse response = Network.getRequest(url, params, new Parameters("Referer", referer));
+ public static Bitmap requestMapTile(final Parameters params) {
+ final HttpResponse response = Network.getRequest(GCConstants.URL_MAP_TILE, params, new Parameters("Referer", GCConstants.URL_LIVE_MAP));
try {
return response != null ? BitmapFactory.decodeStream(response.getEntity().getContent()) : null;
} catch (IOException e) {
@@ -226,4 +231,45 @@ public class Tile {
public boolean containsPoint(final ICoordinates point) {
return viewPort.contains(point);
}
+
+ /**
+ * Calculate needed tiles for the given viewport
+ *
+ * @param viewport
+ * @return
+ */
+ protected static Set<Tile> getTilesForViewport(final Viewport viewport) {
+ Set<Tile> tiles = new HashSet<Tile>();
+ int zoom = Math.min(Tile.calcZoomLon(viewport.bottomLeft, viewport.topRight),
+ Tile.calcZoomLat(viewport.bottomLeft, viewport.topRight));
+ tiles.add(new Tile(viewport.bottomLeft, zoom));
+ tiles.add(new Tile(new Geopoint(viewport.getLatitudeMin(), viewport.getLongitudeMax()), zoom));
+ tiles.add(new Tile(new Geopoint(viewport.getLatitudeMax(), viewport.getLongitudeMin()), zoom));
+ tiles.add(new Tile(viewport.topRight, zoom));
+ return tiles;
+ }
+
+ public static class Cache {
+ private final static LeastRecentlyUsedMap<Integer, Tile> tileCache = new LeastRecentlyUsedMap.LruCache<Integer, Tile>(64);
+
+ public static void removeFromTileCache(final ICoordinates point) {
+ if (point != null) {
+ Collection<Tile> tiles = new ArrayList<Tile>(tileCache.values());
+ for (Tile tile : tiles) {
+ if (tile.containsPoint(point)) {
+ tileCache.remove(tile.hashCode());
+ }
+ }
+ }
+ }
+
+ public static boolean contains(final Tile tile) {
+ return tileCache.containsKey(tile.hashCode());
+ }
+
+ public static void add(final Tile tile) {
+ tileCache.put(tile.hashCode(), tile);
+ }
+ }
+
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
index f291065..508aab4 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
@@ -3,12 +3,12 @@ package cgeo.geocaching.connector.oc;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.connector.capability.ISearchByGeocode;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.CryptUtils;
-public class OCApiConnector extends OCConnector {
+public class OCApiConnector extends OCConnector implements ISearchByGeocode {
private final String cK;
@@ -28,18 +28,12 @@ public class OCApiConnector extends OCConnector {
}
@Override
- public boolean supportsRefreshCache(cgCache cache) {
- return true;
- }
-
- @Override
- public SearchResult searchByGeocode(final String geocode, final String guid, final cgeoapplication app, final CancellableHandler handler) {
+ public SearchResult searchByGeocode(final String geocode, final String guid, final CancellableHandler handler) {
final cgCache cache = OkapiClient.getCache(geocode);
if (cache == null) {
return null;
}
- final SearchResult searchResult = new SearchResult();
- searchResult.addCache(cache);
+ final SearchResult searchResult = new SearchResult(cache);
return searchResult.filterSearchResults(false, false, Settings.getCacheType());
}
}
diff --git a/main/src/cgeo/geocaching/connector/ox/OXConnector.java b/main/src/cgeo/geocaching/connector/ox/OXConnector.java
index c81011f..4c53361 100644
--- a/main/src/cgeo/geocaching/connector/ox/OXConnector.java
+++ b/main/src/cgeo/geocaching/connector/ox/OXConnector.java
@@ -3,17 +3,20 @@ package cgeo.geocaching.connector.ox;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.AbstractConnector;
+import cgeo.geocaching.connector.capability.ISearchByCenter;
+import cgeo.geocaching.connector.capability.ISearchByGeocode;
+import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.utils.CancellableHandler;
+import java.util.Collection;
import java.util.regex.Pattern;
/**
* connector for OpenCaching.com
*
*/
-public class OXConnector extends AbstractConnector {
+public class OXConnector extends AbstractConnector implements ISearchByCenter, ISearchByGeocode {
private static final Pattern PATTERN_GEOCODE = Pattern.compile("OX[A-Z0-9]+", Pattern.CASE_INSENSITIVE);
@@ -44,13 +47,22 @@ public class OXConnector extends AbstractConnector {
}
@Override
- public SearchResult searchByGeocode(String geocode, String guid, cgeoapplication app, CancellableHandler handler) {
+ public SearchResult searchByGeocode(String geocode, String guid, CancellableHandler handler) {
final cgCache cache = OpenCachingApi.searchByGeoCode(geocode);
if (cache == null) {
return null;
}
- final SearchResult searchResult = new SearchResult();
- searchResult.addCache(cache);
+ final SearchResult searchResult = new SearchResult(cache);
+ return searchResult.filterSearchResults(false, false, Settings.getCacheType());
+ }
+
+ @Override
+ public SearchResult searchByCenter(Geopoint center) {
+ Collection<cgCache> caches = OpenCachingApi.searchByCenter(center);
+ if (caches == null) {
+ return null;
+ }
+ final SearchResult searchResult = new SearchResult(caches);
return searchResult.filterSearchResults(false, false, Settings.getCacheType());
}
}
diff --git a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
index 304429f..f06230e 100644
--- a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
+++ b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
@@ -5,6 +5,8 @@ import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.files.GPX10Parser;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.CryptUtils;
@@ -14,6 +16,7 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.http.HttpResponse;
import java.util.Collection;
+import java.util.Collections;
import java.util.EnumSet;
public class OpenCachingApi {
@@ -21,28 +24,54 @@ public class OpenCachingApi {
private static final String DEV_KEY = CryptUtils.rot13("PtqQnHo9RUTht3Np");
public static cgCache searchByGeoCode(final String geocode) {
- final HttpResponse response = Network.getRequest("http://www.opencaching.com/api/geocache/" + geocode + ".gpx", new Parameters("Authorization", DEV_KEY));
+ final HttpResponse response = Network.getRequest("http://www.opencaching.com/api/geocache/" + geocode + ".gpx",
+ new Parameters(
+ "Authorization", DEV_KEY,
+ "log_limit", "30",
+ "hint", "true",
+ "description", "html"));
+ final Collection<cgCache> caches = importCachesFromResponse(response, true);
+ if (CollectionUtils.isNotEmpty(caches)) {
+ return caches.iterator().next();
+ }
+ return null;
+ }
+
+ private static Collection<cgCache> importCachesFromResponse(final HttpResponse response, final boolean isDetailed) {
if (response == null) {
- return null;
+ return Collections.emptyList();
}
Collection<cgCache> caches = null;
try {
caches = new GPX10Parser(StoredList.STANDARD_LIST_ID).parse(response.getEntity().getContent(), null);
} catch (Exception e) {
Log.e("Error importing from OpenCaching.com", e);
+ return Collections.emptyList();
}
- if (caches != null && CollectionUtils.isNotEmpty(caches)) {
- final cgCache cache = caches.iterator().next();
+ for (cgCache cache : caches) {
cache.setUpdated(System.currentTimeMillis());
- cache.setDetailedUpdate(cache.getUpdated());
- cache.setDetailed(true);
+ if (isDetailed) {
+ cache.setDetailedUpdate(cache.getUpdated());
+ cache.setDetailed(true);
+ }
// save full detailed caches
cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
- return cache;
}
+ return caches;
+ }
- return null;
+ public static Collection<cgCache> searchByCenter(final Geopoint center) {
+ final HttpResponse response = Network.getRequest("http://www.opencaching.com/api/geocache/.gpx",
+ new Parameters(
+ "Authorization", DEV_KEY,
+ "log_limit", "0",
+ "hint", "false",
+ "description", "none",
+ "limit", "10",
+ "center", center.format(GeopointFormatter.Format.LAT_LON_DECDEGREE_COMMA)));
+ return importCachesFromResponse(response, false);
}
+
}