diff options
Diffstat (limited to 'main/src/cgeo')
25 files changed, 499 insertions, 523 deletions
diff --git a/main/src/cgeo/geocaching/CacheCache.java b/main/src/cgeo/geocaching/CacheCache.java index 1ada88c..bea8274 100644 --- a/main/src/cgeo/geocaching/CacheCache.java +++ b/main/src/cgeo/geocaching/CacheCache.java @@ -1,7 +1,7 @@ package cgeo.geocaching; import cgeo.geocaching.cgData.StorageLocation; -import cgeo.geocaching.connector.gc.GCBase; +import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.utils.LeastRecentlyUsedMap; @@ -108,7 +108,7 @@ public class CacheCache { @Override public void onRemove(cgCache removed) { - GCBase.removeFromTileCache(removed); + Tile.Cache.removeFromTileCache(removed); } } diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 885a6b5..7b9c147 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -7,7 +7,7 @@ import cgeo.geocaching.apps.cache.GeneralAppsFactory; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; -import cgeo.geocaching.connector.gc.GCParser; +import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.enumerations.CacheAttribute; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; @@ -505,7 +505,7 @@ public class CacheDetailActivity extends AbstractActivity { case CONTEXT_MENU_WAYPOINT_CACHES_AROUND: { final cgWaypoint waypoint = cache.getWaypoint(index); if (waypoint != null) { - cgeocaches.startActivityCachesAround(this, waypoint.getCoords()); + cgeocaches.startActivityCoordinates(this, waypoint.getCoords()); } } break; @@ -561,7 +561,7 @@ public class CacheDetailActivity extends AbstractActivity { cache.openInBrowser(this); return true; case MENU_CACHES_AROUND: - cgeocaches.startActivityCachesAround(this, cache.getCoords()); + cgeocaches.startActivityCoordinates(this, cache.getCoords()); return true; case MENU_CALENDAR: addToCalendarWithIntent(); @@ -1714,7 +1714,7 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - handler.sendEmptyMessage(GCParser.addToWatchlist(cache)); + handler.sendEmptyMessage(GCConnector.addToWatchlist(cache)); } } @@ -1728,7 +1728,7 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - handler.sendEmptyMessage(GCParser.removeFromWatchlist(cache)); + handler.sendEmptyMessage(GCConnector.removeFromWatchlist(cache)); } } diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java index 2e56c7c..d48f98c 100644 --- a/main/src/cgeo/geocaching/SearchResult.java +++ b/main/src/cgeo/geocaching/SearchResult.java @@ -14,6 +14,7 @@ import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashSet; @@ -81,6 +82,18 @@ public class SearchResult implements Parcelable { setTotal(in.readInt()); } + public SearchResult(cgCache cache) { + this(); + addCache(cache); + } + + public SearchResult(Collection<cgCache> caches) { + this(); + for (cgCache cache : caches) { + addCache(cache); + } + } + @Override public void writeToParcel(final Parcel out, final int flags) { out.writeStringArray(geocodes.toArray(new String[geocodes.size()])); diff --git a/main/src/cgeo/geocaching/cgCache.java b/main/src/cgeo/geocaching/cgCache.java index bb6dffa..6373749 100644 --- a/main/src/cgeo/geocaching/cgCache.java +++ b/main/src/cgeo/geocaching/cgCache.java @@ -4,8 +4,10 @@ import cgeo.geocaching.cgData.StorageLocation; import cgeo.geocaching.activity.IAbstractActivity; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; -import cgeo.geocaching.connector.gc.GCBase; +import cgeo.geocaching.connector.capability.ISearchByCenter; +import cgeo.geocaching.connector.capability.ISearchByGeocode; import cgeo.geocaching.connector.gc.GCConnector; +import cgeo.geocaching.connector.gc.GCConstants; import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; @@ -480,7 +482,7 @@ public class cgCache implements ICache, IWaypoint { } public boolean supportsRefresh() { - return getConnector().supportsRefreshCache(this); + return getConnector() instanceof ISearchByGeocode; } public boolean supportsWatchList() { @@ -574,7 +576,7 @@ public class cgCache implements ICache, IWaypoint { @Override public String getCacheId() { if (StringUtils.isBlank(cacheId) && getConnector().equals(GCConnector.getInstance())) { - return String.valueOf(GCBase.gccodeToGCId(geocode)); + return String.valueOf(GCConstants.gccodeToGCId(geocode)); } return cacheId; @@ -605,7 +607,7 @@ public class cgCache implements ICache, IWaypoint { } public boolean supportsCachesAround() { - return getConnector().supportsCachesAround(); + return getConnector() instanceof ISearchByCenter; } public void shareCache(Activity fromActivity, Resources res) { @@ -1521,7 +1523,7 @@ public class cgCache implements ICache, IWaypoint { return null; } - cgeoapplication app = cgeoapplication.getInstance(); + final cgeoapplication app = cgeoapplication.getInstance(); if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (app.isOffline(geocode, guid) || app.isThere(geocode, guid, true, true))) { final SearchResult search = new SearchResult(); final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : app.getGeocode(guid); @@ -1531,10 +1533,14 @@ public class cgCache implements ICache, IWaypoint { // if we have no geocode, we can't dynamically select the handler, but must explicitly use GC if (geocode == null && guid != null) { - return GCConnector.getInstance().searchByGeocode(null, guid, app, handler); + return GCConnector.getInstance().searchByGeocode(null, guid, handler); } - return ConnectorFactory.getConnector(geocode).searchByGeocode(geocode, guid, app, handler); + final IConnector connector = ConnectorFactory.getConnector(geocode); + if (connector instanceof ISearchByGeocode) { + return ((ISearchByGeocode) connector).searchByGeocode(geocode, guid, handler); + } + return null; } } diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 695af42..5231bf7 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -7,6 +7,8 @@ import cgeo.geocaching.activity.Progress; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cachelist.CacheListAppFactory; import cgeo.geocaching.connector.gc.GCParser; +import cgeo.geocaching.connector.gc.SearchHandler; +import cgeo.geocaching.connector.gc.AbstractSearchThread; import cgeo.geocaching.enumerations.CacheListType; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; @@ -438,7 +440,7 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object } // reload history list - (new LoadByHistoryThread(loadCachesHandler)).start(); + (new LoadByHistoryThread()).start(); progress.dismiss(); } @@ -500,7 +502,7 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object } Thread threadPure; - cgSearchThread thread; + AbstractSearchThread thread; switch (type) { case OFFLINE: @@ -519,7 +521,7 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object showProgress(true); setLoadingCaches(); - threadPure = new LoadByOfflineThread(loadCachesHandler, coords, listId); + threadPure = new LoadByOfflineThread(coords, listId); threadPure.start(); break; @@ -529,7 +531,7 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object showProgress(true); setLoadingCaches(); - threadPure = new LoadByHistoryThread(loadCachesHandler); + threadPure = new LoadByHistoryThread(); threadPure.start(); break; case NEAREST: @@ -539,8 +541,8 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object showProgress(true); setLoadingCaches(); - thread = new LoadByCoordsThread(loadCachesHandler, coords); - thread.setRecaptchaHandler(new cgSearchHandler(this, res, thread)); + thread = new LoadByCoordsThread(coords); + thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); thread.start(); break; case COORDINATE: @@ -550,8 +552,8 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object showProgress(true); setLoadingCaches(); - thread = new LoadByCoordsThread(loadCachesHandler, coords); - thread.setRecaptchaHandler(new cgSearchHandler(this, res, thread)); + thread = new LoadByCoordsThread(coords); + thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); thread.start(); break; case KEYWORD: @@ -560,8 +562,8 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object showProgress(true); setLoadingCaches(); - thread = new LoadByKeywordThread(loadCachesHandler, keyword); - thread.setRecaptchaHandler(new cgSearchHandler(this, res, thread)); + thread = new LoadByKeywordThread(keyword); + thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); thread.start(); break; case ADDRESS: @@ -578,8 +580,8 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object setLoadingCaches(); } - thread = new LoadByCoordsThread(loadCachesHandler, coords); - thread.setRecaptchaHandler(new cgSearchHandler(this, res, thread)); + thread = new LoadByCoordsThread(coords); + thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); thread.start(); break; case USERNAME: @@ -588,8 +590,8 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object showProgress(true); setLoadingCaches(); - thread = new LoadByUserNameThread(loadCachesHandler, username); - thread.setRecaptchaHandler(new cgSearchHandler(this, res, thread)); + thread = new LoadByUserNameThread(username); + thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); thread.start(); break; case OWNER: @@ -598,8 +600,8 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object showProgress(true); setLoadingCaches(); - thread = new LoadByOwnerThread(loadCachesHandler, username); - thread.setRecaptchaHandler(new cgSearchHandler(this, res, thread)); + thread = new LoadByOwnerThread(username); + thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); thread.start(); break; case MAP: @@ -1443,13 +1445,10 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object } private class LoadByOfflineThread extends Thread { - - final private Handler handler; final private Geopoint coords; final private int listId; - public LoadByOfflineThread(final Handler handlerIn, final Geopoint coordsIn, int listIdIn) { - handler = handlerIn; + public LoadByOfflineThread(final Geopoint coordsIn, int listIdIn) { coords = coordsIn; listId = listIdIn; } @@ -1457,50 +1456,34 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object @Override public void run() { search = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, Settings.getCacheType(), listId); - handler.sendMessage(Message.obtain()); + loadCachesHandler.sendMessage(Message.obtain()); } } private class LoadByHistoryThread extends Thread { - - final private Handler handler; - - public LoadByHistoryThread(Handler handlerIn) { - handler = handlerIn; - } - @Override public void run() { search = cgeoapplication.getInstance().getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL); - handler.sendMessage(Message.obtain()); + loadCachesHandler.sendMessage(Message.obtain()); } } - private class LoadNextPageThread extends cgSearchThread { - - private final Handler handler; - - public LoadNextPageThread(Handler handlerIn) { - handler = handlerIn; + private class LoadNextPageThread extends AbstractSearchThread { + public LoadNextPageThread() { + super(loadNextPageHandler); } @Override - public void run() { - search = GCParser.searchByNextPage(this, search, Settings.isShowCaptcha()); - - handler.sendMessage(Message.obtain()); + public void runSearch() { + search = GCParser.searchByNextPage(search, Settings.isShowCaptcha()); } } - private class LoadByCoordsThread extends cgSearchThread { - - final private Handler handler; + private class LoadByCoordsThread extends AbstractSearchThread { final private Geopoint coords; - public LoadByCoordsThread(final Handler handler, final Geopoint coords) { - setPriority(Thread.MIN_PRIORITY); - - this.handler = handler; + public LoadByCoordsThread(final Geopoint coords) { + super(loadCachesHandler); this.coords = coords; if (coords == null) { @@ -1511,22 +1494,16 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object } @Override - public void run() { - search = GCParser.searchByCoords(this, coords, cacheType, Settings.isShowCaptcha()); - - handler.sendMessage(Message.obtain()); + public void runSearch() { + search = GCParser.searchByCoords(coords, cacheType, Settings.isShowCaptcha()); } } - private class LoadByKeywordThread extends cgSearchThread { - - final private Handler handler; + private class LoadByKeywordThread extends AbstractSearchThread { final private String keyword; - public LoadByKeywordThread(final Handler handler, final String keyword) { - setPriority(Thread.MIN_PRIORITY); - - this.handler = handler; + public LoadByKeywordThread(final String keyword) { + super(loadCachesHandler); this.keyword = keyword; if (keyword == null) { @@ -1537,21 +1514,16 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object } @Override - public void run() { - search = GCParser.searchByKeyword(this, keyword, cacheType, Settings.isShowCaptcha()); - handler.sendMessage(Message.obtain()); + public void runSearch() { + search = GCParser.searchByKeyword(keyword, cacheType, Settings.isShowCaptcha()); } } - private class LoadByUserNameThread extends cgSearchThread { - - final private Handler handler; + private class LoadByUserNameThread extends AbstractSearchThread { final private String username; - public LoadByUserNameThread(final Handler handler, final String username) { - setPriority(Thread.MIN_PRIORITY); - - this.handler = handler; + public LoadByUserNameThread(final String username) { + super(loadCachesHandler); this.username = username; if (StringUtils.isBlank(username)) { @@ -1562,21 +1534,16 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object } @Override - public void run() { - search = GCParser.searchByUsername(this, username, cacheType, Settings.isShowCaptcha()); - handler.sendMessage(Message.obtain()); + public void runSearch() { + search = GCParser.searchByUsername(username, cacheType, Settings.isShowCaptcha()); } } - private class LoadByOwnerThread extends cgSearchThread { - - final private Handler handler; + private class LoadByOwnerThread extends AbstractSearchThread { final private String username; - public LoadByOwnerThread(final Handler handler, final String username) { - setPriority(Thread.MIN_PRIORITY); - - this.handler = handler; + public LoadByOwnerThread(final String username) { + super(loadCachesHandler); this.username = username; if (StringUtils.isBlank(username)) { @@ -1587,9 +1554,8 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object } @Override - public void run() { - search = GCParser.searchByOwner(this, username, cacheType, Settings.isShowCaptcha()); - handler.sendMessage(Message.obtain()); + public void runSearch() { + search = GCParser.searchByOwner(username, cacheType, Settings.isShowCaptcha()); } } @@ -1645,7 +1611,6 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object } Log.i("Waiting for next cache " + delay + " ms"); - sleep(delay); } catch (Exception e) { Log.e("cgeocaches.LoadDetailsThread.sleep: " + e.toString()); } @@ -1849,9 +1814,8 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object setLoadingCaches(); listFooter.setOnClickListener(null); - LoadNextPageThread thread; - thread = new LoadNextPageThread(loadNextPageHandler); - thread.setRecaptchaHandler(new cgSearchHandler(cgeocaches.this, res, thread)); + final LoadNextPageThread thread = new LoadNextPageThread(); + thread.setRecaptchaHandler(new SearchHandler(cgeocaches.this, res, thread)); thread.start(); } } @@ -1908,7 +1872,7 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object private class MoveHandler extends Handler { @Override public void handleMessage(Message msg) { - Thread threadPure = new LoadByOfflineThread(loadCachesHandler, coords, msg.what); + Thread threadPure = new LoadByOfflineThread(coords, msg.what); threadPure.start(); } } @@ -2038,16 +2002,6 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object context.startActivity(cachesIntent); } - public static void startActivityCachesAround(final AbstractActivity context, final Geopoint coords) { - cgeocaches cachesActivity = new cgeocaches(); - - Intent cachesIntent = new Intent(context, cachesActivity.getClass()); - cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.COORDINATE); - cachesIntent.putExtra(EXTRAS_COORDS, coords); - - context.startActivity(cachesIntent); - } - public static void startActivityOwner(final AbstractActivity context, final String userName) { final Intent cachesIntent = new Intent(context, cgeocaches.class); @@ -2121,7 +2075,7 @@ public class cgeocaches extends AbstractListActivity implements IObserver<Object } public static void startActivityAddress(final Context context, final Geopoint coords, final String address) { - Intent addressIntent = new Intent(context, cgeocaches.class); + final Intent addressIntent = new Intent(context, cgeocaches.class); addressIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.ADDRESS); addressIntent.putExtra(EXTRAS_COORDS, coords); addressIntent.putExtra("address", address); diff --git a/main/src/cgeo/geocaching/cgeopopup.java b/main/src/cgeo/geocaching/cgeopopup.java index dd9be5b..05383f1 100644 --- a/main/src/cgeo/geocaching/cgeopopup.java +++ b/main/src/cgeo/geocaching/cgeopopup.java @@ -2,7 +2,7 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; -import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.gc.GCMap; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; @@ -236,7 +236,7 @@ public class cgeopopup extends AbstractActivity { if ( CacheType.UNKNOWN == cache.getType() ) { Set<String> geocodes = new HashSet<String>(); geocodes.add(geocode); - SearchResult search = ConnectorFactory.searchByGeocodes(geocodes); + SearchResult search = GCMap.searchByGeocodes(geocodes); cache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_ONLY); } @@ -515,7 +515,7 @@ public class cgeopopup extends AbstractActivity { return; } - cgeocaches.startActivityCachesAround(this, cache.getCoords()); + cgeocaches.startActivityCoordinates(this, cache.getCoords()); finish(); } diff --git a/main/src/cgeo/geocaching/cgeowaypoint.java b/main/src/cgeo/geocaching/cgeowaypoint.java index ca3182d..61f44b9 100644 --- a/main/src/cgeo/geocaching/cgeowaypoint.java +++ b/main/src/cgeo/geocaching/cgeowaypoint.java @@ -240,7 +240,7 @@ public class cgeowaypoint extends AbstractActivity implements IObserver<IGeoData showToast(res.getString(R.string.err_location_unknown)); } - cgeocaches.startActivityCachesAround(this, waypoint.getCoords()); + cgeocaches.startActivityCoordinates(this, waypoint.getCoords()); finish(); } 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/cgSearchThread.java b/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java index ff73a66..33c8a92 100644 --- a/main/src/cgeo/geocaching/cgSearchThread.java +++ b/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java @@ -1,13 +1,20 @@ -package cgeo.geocaching; +package cgeo.geocaching.connector.gc; import cgeo.geocaching.utils.Log; import android.os.Handler; +import android.os.Message; -abstract public class cgSearchThread extends Thread { +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; @@ -44,4 +51,18 @@ abstract public class cgSearchThread extends Thread { 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/cgSearchHandler.java b/main/src/cgeo/geocaching/connector/gc/SearchHandler.java index 6d38ea1..45efff2 100644 --- a/main/src/cgeo/geocaching/cgSearchHandler.java +++ b/main/src/cgeo/geocaching/connector/gc/SearchHandler.java @@ -1,5 +1,6 @@ -package cgeo.geocaching; +package cgeo.geocaching.connector.gc; +import cgeo.geocaching.R; import cgeo.geocaching.utils.Log; import android.app.Activity; @@ -20,10 +21,10 @@ import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; -public class cgSearchHandler extends Handler { +public class SearchHandler extends Handler { private Activity activity = null; private Resources res = null; - private cgSearchThread recaptchaThread = null; + private AbstractSearchThread recaptchaThread = null; private ImageView imageView = null; private Bitmap img = null; @@ -40,7 +41,7 @@ public class cgSearchHandler extends Handler { } }; - public cgSearchHandler(Activity activityIn, Resources resIn, cgSearchThread recaptchaThreadIn) { + public SearchHandler(Activity activityIn, Resources resIn, AbstractSearchThread recaptchaThreadIn) { activity = activityIn; res = resIn; recaptchaThread = recaptchaThreadIn; 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); } + } diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index 6b24ec9..03c8284 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -15,7 +15,6 @@ import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.cgeocaches; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.connector.ConnectorFactory; -import cgeo.geocaching.connector.gc.GCBase; import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; @@ -1133,7 +1132,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto do { if (tokens == null) { - tokens = GCBase.getTokens(); + tokens = Login.getMapTokens(); if (noMapTokenHandler != null && tokens == null) { noMapTokenHandler.sendEmptyMessage(0); } |