aboutsummaryrefslogtreecommitdiffstats
path: root/main/src
diff options
context:
space:
mode:
Diffstat (limited to 'main/src')
-rw-r--r--main/src/cgeo/geocaching/AbstractPopupActivity.java17
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java74
-rw-r--r--main/src/cgeo/geocaching/CacheListActivity.java2
-rw-r--r--main/src/cgeo/geocaching/CompassActivity.java5
-rw-r--r--main/src/cgeo/geocaching/DataStore.java132
-rw-r--r--main/src/cgeo/geocaching/EditWaypointActivity.java8
-rw-r--r--main/src/cgeo/geocaching/Geocache.java98
-rw-r--r--main/src/cgeo/geocaching/Image.java26
-rw-r--r--main/src/cgeo/geocaching/LogCacheActivity.java40
-rw-r--r--main/src/cgeo/geocaching/LogEntry.java5
-rw-r--r--main/src/cgeo/geocaching/MainActivity.java27
-rw-r--r--main/src/cgeo/geocaching/NavigateAnyPointActivity.java7
-rw-r--r--main/src/cgeo/geocaching/PocketQueryList.java9
-rw-r--r--main/src/cgeo/geocaching/StatusFragment.java85
-rw-r--r--main/src/cgeo/geocaching/TrackableActivity.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/MapsWithMeApp.java43
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java3
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java3
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java67
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java17
-rw-r--r--main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java7
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java2
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheType.java5
-rw-r--r--main/src/cgeo/geocaching/export/GpxSerializer.java58
-rw-r--r--main/src/cgeo/geocaching/files/AbstractFileListActivity.java1
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java8
-rw-r--r--main/src/cgeo/geocaching/filter/AttributeFilter.java9
-rw-r--r--main/src/cgeo/geocaching/list/StoredList.java2
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java4
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java2
-rw-r--r--main/src/cgeo/geocaching/network/HtmlImage.java13
-rw-r--r--main/src/cgeo/geocaching/sensors/DirectionProvider.java38
-rw-r--r--main/src/cgeo/geocaching/sensors/GeoDirHandler.java7
-rw-r--r--main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java9
-rw-r--r--main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java9
-rw-r--r--main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java5
-rw-r--r--main/src/cgeo/geocaching/ui/CacheListAdapter.java4
-rw-r--r--main/src/cgeo/geocaching/ui/ImagesList.java6
-rw-r--r--main/src/cgeo/geocaching/utils/FileUtils.java30
-rw-r--r--main/src/cgeo/geocaching/utils/ImageUtils.java8
-rw-r--r--main/src/cgeo/geocaching/utils/MiscUtils.java40
-rw-r--r--main/src/cgeo/geocaching/utils/RxUtils.java33
42 files changed, 593 insertions, 379 deletions
diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java
index 683579f..88cad01 100644
--- a/main/src/cgeo/geocaching/AbstractPopupActivity.java
+++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java
@@ -14,12 +14,14 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.ui.LoggingUI;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RxUtils;
import org.apache.commons.lang3.StringUtils;
+
import rx.Observable;
+import rx.android.observables.AndroidObservable;
import rx.functions.Action1;
import rx.functions.Func0;
+import rx.schedulers.Schedulers;
import android.graphics.Rect;
import android.os.Bundle;
@@ -79,13 +81,13 @@ public abstract class AbstractPopupActivity extends AbstractActivity implements
if (!cache.supportsGCVote()) {
return;
}
- RxUtils.subscribeOnIOThenUI(Observable.defer(new Func0<Observable<GCVoteRating>>() {
+ AndroidObservable.bindActivity(this, Observable.defer(new Func0<Observable<GCVoteRating>>() {
@Override
public Observable<GCVoteRating> call() {
final GCVoteRating rating = GCVote.getRating(cache.getGuid(), geocode);
return rating != null ? Observable.just(rating) : Observable.<GCVoteRating>empty();
}
- }), new Action1<GCVoteRating>() {
+ })).subscribe(new Action1<GCVoteRating>() {
@Override
public void call(final GCVoteRating rating) {
cache.setRating(rating.getRating());
@@ -93,7 +95,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity implements
DataStore.saveChangedCache(cache);
details.addRating(cache);
}
- });
+ }, Schedulers.io());
}
protected void init() {
@@ -160,11 +162,6 @@ public abstract class AbstractPopupActivity extends AbstractActivity implements
}
@Override
- public void onPause() {
- super.onPause();
- }
-
- @Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
@@ -255,7 +252,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity implements
* @param view
* unused here but needed since this method is referenced from XML layout
*/
- public final void goDefaultNavigation(@SuppressWarnings("unused") View view) {
+ public final void goDefaultNavigation(View view) {
navigateTo();
finish();
}
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index a8fa8ee..a66d181 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -8,6 +8,7 @@ import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.AbstractViewPagerActivity;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
+import cgeo.geocaching.apps.cachelist.MapsWithMeCacheListApp;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
@@ -45,7 +46,6 @@ import cgeo.geocaching.utils.CryptUtils;
import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
-import cgeo.geocaching.utils.RxUtils;
import cgeo.geocaching.utils.SimpleCancellableHandler;
import cgeo.geocaching.utils.SimpleHandler;
import cgeo.geocaching.utils.TextUtils;
@@ -56,14 +56,16 @@ import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
+
import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Observer;
import rx.Scheduler.Inner;
import rx.Subscriber;
-import rx.Subscription;
+import rx.android.observables.AndroidObservable;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
+import rx.subscriptions.CompositeSubscription;
import android.R.color;
import android.app.AlertDialog;
@@ -143,19 +145,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private SearchResult search;
- private final GeoDirHandler locationUpdater = new GeoDirHandler() {
- @Override
- public void updateGeoData(final IGeoData geo) {
- if (cacheDistanceView == null) {
- return;
- }
-
- if (geo.getCoords() != null && cache != null && cache.getCoords() != null) {
- cacheDistanceView.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(cache.getCoords())));
- cacheDistanceView.bringToFront();
- }
- }
- };
+ private GeoDirHandler locationUpdater;
private CharSequence clickedItemText = null;
@@ -168,7 +158,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private TextView cacheDistanceView;
protected ImagesList imagesList;
- private Subscription imagesSubscription;
+ private CompositeSubscription createSubscriptions;
/**
* waypoint selected in context menu. This variable will be gone when the waypoint context menu is a fragment.
*/
@@ -178,6 +168,8 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.cachedetail_activity);
+ createSubscriptions = new CompositeSubscription();
+
// set title in code, as the activity needs a hard coded title due to the intent filters
setTitle(res.getString(R.string.cache));
@@ -195,6 +187,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
guid = extras.getString(Intents.EXTRA_GUID);
}
+ // When clicking a cache in MapsWithMe, we get back a PendingIntent
+ if (StringUtils.isEmpty(geocode)) {
+ geocode = MapsWithMeCacheListApp.getCacheFromMapsWithMe(this, getIntent());
+ }
+
// try to get data from URI
if (geocode == null && guid == null && uri != null) {
final String uriHost = uri.getHost().toLowerCase(Locale.US);
@@ -310,6 +307,8 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
loadCacheHandler.sendMessage(Message.obtain());
}
});
+
+ locationUpdater = new CacheDetailsGeoDirHandler(this);
}
@Override
@@ -330,9 +329,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
@Override
public void onDestroy() {
- if (imagesList != null) {
- imagesSubscription.unsubscribe();
- }
+ createSubscriptions.unsubscribe();
super.onDestroy();
}
@@ -345,11 +342,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
@Override
- public void onPause() {
- super.onPause();
- }
-
- @Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) {
super.onCreateContextMenu(menu, view, info);
final int viewId = view.getId();
@@ -521,6 +513,30 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return true;
}
+ private static final class CacheDetailsGeoDirHandler extends GeoDirHandler {
+ private final WeakReference<CacheDetailActivity> activityRef;
+
+ public CacheDetailsGeoDirHandler(final CacheDetailActivity activity) {
+ this.activityRef = new WeakReference<CacheDetailActivity>(activity);
+ }
+
+ @Override
+ public void updateGeoData(final IGeoData geo) {
+ final CacheDetailActivity activity = activityRef.get();
+ if (activity == null) {
+ return;
+ }
+ if (activity.cacheDistanceView == null) {
+ return;
+ }
+
+ if (geo.getCoords() != null && activity.cache != null && activity.cache.getCoords() != null) {
+ activity.cacheDistanceView.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(activity.cache.getCoords())));
+ activity.cacheDistanceView.bringToFront();
+ }
+ }
+ }
+
private final static class LoadCacheHandler extends SimpleCancellableHandler {
public LoadCacheHandler(CacheDetailActivity activity, Progress progress) {
@@ -649,7 +665,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return;
}
imagesList = new ImagesList(this, cache.getGeocode());
- imagesSubscription = imagesList.loadImages(imageView, cache.getImages(), false);
+ createSubscriptions.add(imagesList.loadImages(imageView, cache.getImages(), false));
}
public static void startActivity(final Context context, final String geocode) {
@@ -878,7 +894,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
view = (ScrollView) getLayoutInflater().inflate(R.layout.cachedetail_details_page, null);
// Start loading preview map
- RxUtils.subscribeOnIOThenUI(previewMap, new Action1<BitmapDrawable>() {
+ AndroidObservable.bindActivity(CacheDetailActivity.this, previewMap).subscribe(new Action1<BitmapDrawable>() {
@Override
public void call(final BitmapDrawable image) {
final Bitmap bitmap = image.getBitmap();
@@ -888,7 +904,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
view.findViewById(R.id.map_preview_box).setVisibility(View.VISIBLE);
}
}
- });
+ }, Schedulers.io());
detailsList = (LinearLayout) view.findViewById(R.id.details_list);
final CacheDetailsCreator details = new CacheDetailsCreator(CacheDetailActivity.this, detailsList);
@@ -1605,7 +1621,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
});
- RxUtils.subscribeOnIOThenUI(producer, new Observer<Spanned>() {
+ AndroidObservable.bindActivity(this, producer).subscribe(new Observer<Spanned>() {
@Override
public void onCompleted() {
if (null != loadingIndicatorView) {
@@ -1668,7 +1684,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
descriptionView.setBackgroundResource(backcolor);
}
- });
+ }, Schedulers.io());
}
private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ListView> {
diff --git a/main/src/cgeo/geocaching/CacheListActivity.java b/main/src/cgeo/geocaching/CacheListActivity.java
index b2404d9..0aec119 100644
--- a/main/src/cgeo/geocaching/CacheListActivity.java
+++ b/main/src/cgeo/geocaching/CacheListActivity.java
@@ -1384,7 +1384,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
* @param view
* unused here but needed since this method is referenced from XML layout
*/
- public void goMap(@SuppressWarnings("unused") View view) {
+ public void goMap(View view) {
if (!cacheToShow()) {
return;
}
diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java
index ff7a025..36dcf27 100644
--- a/main/src/cgeo/geocaching/CompassActivity.java
+++ b/main/src/cgeo/geocaching/CompassActivity.java
@@ -122,11 +122,6 @@ public class CompassActivity extends AbstractActivity {
}
@Override
- public void onPause() {
- super.onPause();
- }
-
- @Override
public void onDestroy() {
compassView.destroyDrawingCache();
SpeechService.stopService(this);
diff --git a/main/src/cgeo/geocaching/DataStore.java b/main/src/cgeo/geocaching/DataStore.java
index eb4c32e..32a4b64 100644
--- a/main/src/cgeo/geocaching/DataStore.java
+++ b/main/src/cgeo/geocaching/DataStore.java
@@ -20,8 +20,6 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.Dialogs;
import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.MiscUtils;
-import cgeo.geocaching.utils.RxUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
@@ -29,9 +27,11 @@ import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
+import rx.android.observables.AndroidObservable;
import rx.functions.Action1;
import rx.functions.Func0;
import rx.functions.Func1;
+import rx.schedulers.Schedulers;
import rx.util.async.Async;
import android.app.Activity;
@@ -395,7 +395,7 @@ public class DataStore {
*/
public static void moveDatabase(final Activity fromActivity) {
final ProgressDialog dialog = ProgressDialog.show(fromActivity, fromActivity.getString(R.string.init_dbmove_dbmove), fromActivity.getString(R.string.init_dbmove_running), true, false);
- RxUtils.subscribeOnIOThenUI(Async.fromCallable(new Func0<Boolean>() {
+ AndroidObservable.bindActivity(fromActivity, Async.fromCallable(new Func0<Boolean>() {
@Override
public Boolean call() {
if (!LocalStorage.isExternalStorageAvailable()) {
@@ -420,14 +420,14 @@ public class DataStore {
init();
return true;
}
- }), new Action1<Boolean>() {
+ })).subscribe(new Action1<Boolean>() {
@Override
public void call(final Boolean success) {
dialog.dismiss();
final String message = success ? fromActivity.getString(R.string.init_dbmove_success) : fromActivity.getString(R.string.init_dbmove_failed);
Dialogs.message(fromActivity, R.string.init_dbmove_dbmove, message);
}
- });
+ }, Schedulers.io());
}
private static File databasePath(final boolean internal) {
@@ -1197,7 +1197,6 @@ public class DataStore {
saveAttributesWithoutTransaction(cache);
saveWaypointsWithoutTransaction(cache);
saveSpoilersWithoutTransaction(cache);
- saveLogsWithoutTransaction(cache.getGeocode(), cache.getLogs());
saveLogCountsWithoutTransaction(cache);
saveInventoryWithoutTransaction(cache.getGeocode(), cache.getInventory());
@@ -1322,7 +1321,7 @@ public class DataStore {
*/
private static void removeOutdatedWaypointsOfCache(final @NonNull Geocache cache, final @NonNull Collection<String> remainingWaypointIds) {
final String idList = StringUtils.join(remainingWaypointIds, ',');
- database.delete(dbTableWaypoints, "geocode = ? AND _id NOT in (" + idList + ")", new String[]{cache.getGeocode()});
+ database.delete(dbTableWaypoints, "geocode = ? AND _id NOT in (" + idList + ")", new String[] { cache.getGeocode() });
}
/**
@@ -1430,7 +1429,7 @@ public class DataStore {
}
}
- private static void saveLogsWithoutTransaction(final String geocode, final List<LogEntry> logs) {
+ public static void saveLogsWithoutTransaction(final String geocode, final List<LogEntry> logs) {
// TODO delete logimages referring these logs
database.delete(dbTableLogs, "geocode = ?", new String[]{geocode});
@@ -1567,8 +1566,8 @@ public class DataStore {
return new HashSet<Geocache>();
}
- final Set<Geocache> result = new HashSet<Geocache>();
- final List<String> remaining = new LinkedList<String>(geocodes);
+ Set<Geocache> result = new HashSet<Geocache>();
+ Set<String> remaining = new HashSet<String>(geocodes);
if (loadFlags.contains(LoadFlag.LOAD_CACHE_BEFORE)) {
for (String geocode : new HashSet<String>(remaining)) {
@@ -1588,7 +1587,7 @@ public class DataStore {
loadFlags.contains(LoadFlag.LOAD_INVENTORY) ||
loadFlags.contains(LoadFlag.LOAD_OFFLINE_LOG)) {
- final Collection<Geocache> cachesFromDB = loadCachesFromGeocodes(remaining, loadFlags);
+ final Set<Geocache> cachesFromDB = loadCachesFromGeocodes(remaining, loadFlags);
result.addAll(cachesFromDB);
for (final Geocache cache : cachesFromDB) {
remaining.remove(cache.getGeocode());
@@ -1614,11 +1613,15 @@ public class DataStore {
/**
* Load caches.
*
- * @param allGeocodes
+ * @param geocodes
* @param loadFlags
* @return Set of loaded caches. Never null.
*/
- private static Collection<Geocache> loadCachesFromGeocodes(final List<String> allGeocodes, final EnumSet<LoadFlag> loadFlags) {
+ private static Set<Geocache> loadCachesFromGeocodes(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) {
+ if (CollectionUtils.isEmpty(geocodes)) {
+ return Collections.emptySet();
+ }
+
// do not log the entire collection of geo codes to the debug log. This can be more than 100 KB of text for large lists!
init();
@@ -1633,73 +1636,67 @@ public class DataStore {
}
query.append(" WHERE ").append(dbTableCaches).append('.');
+ query.append(DataStore.whereGeocodeIn(geocodes));
- final String queryBegin = query.toString();
- final List<Geocache> result = new ArrayList<Geocache>(allGeocodes.size());
-
- for (List<String> geocodes: MiscUtils.buffer(allGeocodes, 50)) {
- final Cursor cursor = database.rawQuery(queryBegin + DataStore.whereGeocodeIn(geocodes), null);
- try {
- final Set<Geocache> caches = new HashSet<Geocache>();
- int logIndex = -1;
+ Cursor cursor = database.rawQuery(query.toString(), null);
+ try {
+ final Set<Geocache> caches = new HashSet<Geocache>();
+ int logIndex = -1;
- while (cursor.moveToNext()) {
- final Geocache cache = DataStore.createCacheFromDatabaseContent(cursor);
+ while (cursor.moveToNext()) {
+ Geocache cache = DataStore.createCacheFromDatabaseContent(cursor);
- if (loadFlags.contains(LoadFlag.LOAD_ATTRIBUTES)) {
- cache.setAttributes(loadAttributes(cache.getGeocode()));
- }
+ if (loadFlags.contains(LoadFlag.LOAD_ATTRIBUTES)) {
+ cache.setAttributes(loadAttributes(cache.getGeocode()));
+ }
- if (loadFlags.contains(LoadFlag.LOAD_WAYPOINTS)) {
- final List<Waypoint> waypoints = loadWaypoints(cache.getGeocode());
- if (CollectionUtils.isNotEmpty(waypoints)) {
- cache.setWaypoints(waypoints, false);
- }
+ if (loadFlags.contains(LoadFlag.LOAD_WAYPOINTS)) {
+ final List<Waypoint> waypoints = loadWaypoints(cache.getGeocode());
+ if (CollectionUtils.isNotEmpty(waypoints)) {
+ cache.setWaypoints(waypoints, false);
}
+ }
- if (loadFlags.contains(LoadFlag.LOAD_SPOILERS)) {
- final List<Image> spoilers = loadSpoilers(cache.getGeocode());
- cache.setSpoilers(spoilers);
- }
+ if (loadFlags.contains(LoadFlag.LOAD_SPOILERS)) {
+ final List<Image> spoilers = loadSpoilers(cache.getGeocode());
+ cache.setSpoilers(spoilers);
+ }
- if (loadFlags.contains(LoadFlag.LOAD_LOGS)) {
- cache.setLogs(loadLogs(cache.getGeocode()));
- final Map<LogType, Integer> logCounts = loadLogCounts(cache.getGeocode());
- if (MapUtils.isNotEmpty(logCounts)) {
- cache.getLogCounts().clear();
- cache.getLogCounts().putAll(logCounts);
- }
+ if (loadFlags.contains(LoadFlag.LOAD_LOGS)) {
+ final Map<LogType, Integer> logCounts = loadLogCounts(cache.getGeocode());
+ if (MapUtils.isNotEmpty(logCounts)) {
+ cache.getLogCounts().clear();
+ cache.getLogCounts().putAll(logCounts);
}
+ }
- if (loadFlags.contains(LoadFlag.LOAD_INVENTORY)) {
- final List<Trackable> inventory = loadInventory(cache.getGeocode());
- if (CollectionUtils.isNotEmpty(inventory)) {
- if (cache.getInventory() == null) {
- cache.setInventory(new ArrayList<Trackable>());
- } else {
- cache.getInventory().clear();
- }
- cache.getInventory().addAll(inventory);
+ if (loadFlags.contains(LoadFlag.LOAD_INVENTORY)) {
+ final List<Trackable> inventory = loadInventory(cache.getGeocode());
+ if (CollectionUtils.isNotEmpty(inventory)) {
+ if (cache.getInventory() == null) {
+ cache.setInventory(new ArrayList<Trackable>());
+ } else {
+ cache.getInventory().clear();
}
+ cache.getInventory().addAll(inventory);
}
+ }
- if (loadFlags.contains(LoadFlag.LOAD_OFFLINE_LOG)) {
- if (logIndex < 0) {
- logIndex = cursor.getColumnIndex("log");
- }
- cache.setLogOffline(!cursor.isNull(logIndex));
+ if (loadFlags.contains(LoadFlag.LOAD_OFFLINE_LOG)) {
+ if (logIndex < 0) {
+ logIndex = cursor.getColumnIndex("log");
}
- cache.addStorageLocation(StorageLocation.DATABASE);
- cacheCache.putCacheInCache(cache);
-
- caches.add(cache);
+ cache.setLogOffline(!cursor.isNull(logIndex));
}
- result.addAll(caches);
- } finally {
- cursor.close();
+ cache.addStorageLocation(StorageLocation.DATABASE);
+ cacheCache.putCacheInCache(cache);
+
+ caches.add(cache);
}
+ return caches;
+ } finally {
+ cursor.close();
}
- return result;
}
@@ -1927,6 +1924,11 @@ public class DataStore {
return false;
}
+ /**
+ * @param geocode
+ * @return an immutable, non null list of logs
+ */
+ @NonNull
public static List<LogEntry> loadLogs(String geocode) {
List<LogEntry> logs = new ArrayList<LogEntry>();
@@ -1962,7 +1964,7 @@ public class DataStore {
cursor.close();
- return logs;
+ return Collections.unmodifiableList(logs);
}
public static Map<LogType, Integer> loadLogCounts(String geocode) {
diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java
index 45775a7..55de0a6 100644
--- a/main/src/cgeo/geocaching/EditWaypointActivity.java
+++ b/main/src/cgeo/geocaching/EditWaypointActivity.java
@@ -10,11 +10,11 @@ import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.DistanceParser;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.sensors.GeoDirHandler;
import cgeo.geocaching.sensors.IGeoData;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
import cgeo.geocaching.ui.dialog.Dialogs;
-import cgeo.geocaching.sensors.GeoDirHandler;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.TextUtils;
@@ -22,7 +22,6 @@ import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Extra;
import org.androidannotations.annotations.InstanceState;
import org.androidannotations.annotations.ViewById;
-
import org.apache.commons.lang3.StringUtils;
import android.app.ProgressDialog;
@@ -205,11 +204,6 @@ public class EditWaypointActivity extends AbstractActivity {
super.onResume(geoDirHandler.start(GeoDirHandler.UPDATE_GEODATA));
}
- @Override
- public void onPause() {
- super.onPause();
- }
-
private void initializeWaypointTypeSelector() {
ArrayAdapter<WaypointType> wpAdapter = new ArrayAdapter<WaypointType>(this, android.R.layout.simple_spinner_item, POSSIBLE_WAYPOINT_TYPES.toArray(new WaypointType[POSSIBLE_WAYPOINT_TYPES.size()]));
wpAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java
index a224e4e..19c15fd 100644
--- a/main/src/cgeo/geocaching/Geocache.java
+++ b/main/src/cgeo/geocaching/Geocache.java
@@ -25,6 +25,7 @@ import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.CancellableHandler;
+import cgeo.geocaching.utils.DateUtils;
import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.LazyInitializedList;
import cgeo.geocaching.utils.Log;
@@ -34,12 +35,16 @@ import cgeo.geocaching.utils.MatcherWrapper;
import cgeo.geocaching.utils.UncertainProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+
import rx.Scheduler;
import rx.Scheduler.Inner;
import rx.Subscription;
@@ -50,11 +55,13 @@ import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.Html;
import android.text.Html.ImageGetter;
+import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
@@ -73,6 +80,10 @@ import java.util.regex.Pattern;
/**
* Internal c:geo representation of a "cache"
*/
+/**
+ * @author kep9fe
+ *
+ */
public class Geocache implements ICache, IWaypoint {
private static final int OWN_WP_PREFIX_OFFSET = 17;
@@ -138,12 +149,7 @@ public class Geocache implements ICache, IWaypoint {
}
};
private List<Image> spoilers = null;
- private final LazyInitializedList<LogEntry> logs = new LazyInitializedList<LogEntry>() {
- @Override
- public List<LogEntry> call() {
- return DataStore.loadLogs(geocode);
- }
- };
+
private List<Trackable> inventory = null;
private Map<LogType, Integer> logCounts = new HashMap<LogType, Integer>();
private boolean userModifiedCoords = false;
@@ -177,11 +183,10 @@ public class Geocache implements ICache, IWaypoint {
*
* @param gpxParser
*/
- public Geocache(@SuppressWarnings("unused") GPXParser gpxParser) {
+ public Geocache(GPXParser gpxParser) {
setReliableLatLon(true);
setAttributes(Collections.<String> emptyList());
setWaypoints(Collections.<Waypoint> emptyList(), false);
- setLogs(Collections.<LogEntry> emptyList());
}
public void setChangeNotificationHandler(Handler newNotificationHandler) {
@@ -349,12 +354,6 @@ public class Geocache implements ICache, IWaypoint {
inventory = other.inventory;
inventoryItems = other.inventoryItems;
}
- if (logs.isEmpty()) { // keep last known logs if none
- logs.clear();
- if (other.logs != null) {
- logs.addAll(other.logs);
- }
- }
if (logCounts.isEmpty()) {
logCounts = other.logCounts;
}
@@ -421,7 +420,6 @@ public class Geocache implements ICache, IWaypoint {
attributes == other.attributes &&
waypoints == other.waypoints &&
spoilers == other.spoilers &&
- logs == other.logs &&
inventory == other.inventory &&
logCounts == other.logCounts &&
ObjectUtils.equals(logOffline, other.logOffline) &&
@@ -776,10 +774,7 @@ public class Geocache implements ICache, IWaypoint {
@Override
public List<Image> getSpoilers() {
- if (spoilers == null) {
- return Collections.emptyList();
- }
- return Collections.unmodifiableList(spoilers);
+ return ListUtils.unmodifiableList(ListUtils.emptyIfNull(spoilers));
}
@Override
@@ -1005,21 +1000,24 @@ public class Geocache implements ICache, IWaypoint {
}
/**
- * @return never <code>null</code>
+ * The list of logs is immutable, because it is directly fetched from the database on demand, and not stored at this
+ * object. If you want to modify logs, you have to load all logs of the cache, create a new list from the existing
+ * list and store that new list in the database.
+ *
+ * @return immutable list of logs
*/
+ @NonNull
public List<LogEntry> getLogs() {
- // It is important to return the underlying list here and not the lazily initialized one,
- // because database manipulation may erase the existing logs before methods are called
- // on the previous logs, when updating the saved logs for example.
- return logs.getUnderlyingList();
+ return DataStore.loadLogs(geocode);
}
/**
- * @return only the logs of friends, never <code>null</code>
+ * @return only the logs of friends
*/
+ @NonNull
public List<LogEntry> getFriendsLogs() {
final ArrayList<LogEntry> friendLogs = new ArrayList<LogEntry>();
- for (final LogEntry log : logs) {
+ for (final LogEntry log : getLogs()) {
if (log.friend) {
friendLogs.add(log);
}
@@ -1027,17 +1025,6 @@ public class Geocache implements ICache, IWaypoint {
return Collections.unmodifiableList(friendLogs);
}
- /**
- * @param logs
- * the log entries
- */
- public void setLogs(List<LogEntry> logs) {
- this.logs.clear();
- if (logs != null) {
- this.logs.addAll(logs);
- }
- }
-
public boolean isLogOffline() {
return BooleanUtils.isTrue(logOffline);
}
@@ -1735,6 +1722,7 @@ public class Geocache implements ICache, IWaypoint {
public Collection<Image> getImages() {
final LinkedList<Image> result = new LinkedList<Image>();
result.addAll(getSpoilers());
+ addLocalSpoilersTo(result);
for (final LogEntry log : getLogs()) {
result.addAll(log.getLogImages());
}
@@ -1746,6 +1734,23 @@ public class Geocache implements ICache, IWaypoint {
return result;
}
+ // Add spoilers stored locally in /sdcard/GeocachePhotos
+ private void addLocalSpoilersTo(final List<Image> spoilers) {
+ if (StringUtils.length(geocode) >= 2) {
+ final String suffix = StringUtils.right(geocode, 2);
+ final File baseDir = new File(Environment.getExternalStorageDirectory().toString(), "GeocachePhotos");
+ final File lastCharDir = new File(baseDir, suffix.substring(1));
+ final File secondToLastCharDir = new File(lastCharDir, suffix.substring(0, 1));
+ final File finalDir = new File(secondToLastCharDir, getGeocode());
+ final File[] files = finalDir.listFiles();
+ if (files != null) {
+ for (final File image : files) {
+ spoilers.add(new Image("file://" + image.getAbsolutePath(), image.getName()));
+ }
+ }
+ }
+ }
+
public void setDetailedUpdatedNow() {
final long now = System.currentTimeMillis();
setUpdated(now);
@@ -1806,4 +1811,23 @@ public class Geocache implements ICache, IWaypoint {
return (getType().applyDistanceRule() || hasUserModifiedCoords()) && getConnector() == GCConnector.getInstance();
}
+ public LogType getDefaultLogType() {
+ if (isEventCache()) {
+ final Date eventDate = getHiddenDate();
+ boolean expired = DateUtils.isPastEvent(this);
+
+ if (hasOwnLog(LogType.WILL_ATTEND) || expired || (eventDate != null && DateUtils.daysSince(eventDate.getTime()) == 0)) {
+ return hasOwnLog(LogType.ATTENDED) ? LogType.NOTE : LogType.ATTENDED;
+ }
+ return LogType.WILL_ATTEND;
+ }
+ if (isFound()) {
+ return LogType.NOTE;
+ }
+ if (getType() == CacheType.WEBCAM) {
+ return LogType.WEBCAM_PHOTO_TAKEN;
+ }
+ return LogType.FOUND_IT;
+ }
+
}
diff --git a/main/src/cgeo/geocaching/Image.java b/main/src/cgeo/geocaching/Image.java
index 22c76aa..50ea80e 100644
--- a/main/src/cgeo/geocaching/Image.java
+++ b/main/src/cgeo/geocaching/Image.java
@@ -1,5 +1,7 @@
package cgeo.geocaching;
+import cgeo.geocaching.utils.FileUtils;
+
import org.apache.commons.lang3.StringUtils;
import android.content.Context;
@@ -8,6 +10,8 @@ import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import java.io.File;
+
public class Image implements Parcelable {
private final String url;
private final String title;
@@ -23,6 +27,10 @@ public class Image implements Parcelable {
this(url, title, null);
}
+ public Image(final File file) {
+ this("file://" + file.getAbsolutePath(), file.getName(), null);
+ }
+
public Image(final Parcel in) {
url = in.readString();
title = in.readString();
@@ -85,4 +93,22 @@ public class Image implements Parcelable {
return "???";
}
+
+ /**
+ * Check if the URL represents a file on the local file system.
+ *
+ * @return <tt>true</tt> if the URL scheme is <tt>file</tt>, <tt>false</tt> otherwise
+ */
+ public boolean isLocalFile() {
+ return FileUtils.isFileUrl(url);
+ }
+
+ /**
+ * Local file name when {@link #isLocalFile()} is <tt>true</tt>.
+ *
+ * @return the local file
+ */
+ public File localFile() {
+ return FileUtils.urlToFile(url);
+ }
}
diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java
index 0f65a1d..2b05263 100644
--- a/main/src/cgeo/geocaching/LogCacheActivity.java
+++ b/main/src/cgeo/geocaching/LogCacheActivity.java
@@ -3,7 +3,6 @@ package cgeo.geocaching;
import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.ImageResult;
import cgeo.geocaching.connector.LogResult;
-import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.LogTypeTrackable;
@@ -341,25 +340,10 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
private void setDefaultValues() {
date = Calendar.getInstance();
rating = GCVote.NO_RATING;
- if (cache.isEventCache()) {
- final Date eventDate = cache.getHiddenDate();
- boolean expired = DateUtils.isPastEvent(cache);
-
- if (cache.hasOwnLog(LogType.WILL_ATTEND) || expired) {
- typeSelected = cache.hasOwnLog(LogType.ATTENDED) ? LogType.NOTE : LogType.ATTENDED;
- } else {
- typeSelected = LogType.WILL_ATTEND;
- }
- // it this is an attended event log, use the event date by default instead of the current date
- if (expired && typeSelected == LogType.ATTENDED) {
- date.setTime(eventDate);
- }
- } else {
- if (cache.isFound()) {
- typeSelected = LogType.NOTE;
- } else {
- typeSelected = cache.getType() == CacheType.WEBCAM ? LogType.WEBCAM_PHOTO_TAKEN : LogType.FOUND_IT;
- }
+ typeSelected = cache.getDefaultLogType();
+ // it this is an attended event log, use the event date by default instead of the current date
+ if (cache.isEventCache() && DateUtils.isPastEvent(cache) && typeSelected == LogType.ATTENDED) {
+ date.setTime(cache.getHiddenDate());
}
text = null;
imageCaption = StringUtils.EMPTY;
@@ -531,16 +515,20 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
final LogResult logResult = loggingManager.postLog(cache, typeSelected, date, log, logPwd, trackables);
if (logResult.getPostLogResult() == StatusCode.NO_ERROR) {
- final LogEntry logNow = new LogEntry(date.getTimeInMillis(), typeSelected, log);
-
- cache.getLogs().add(0, logNow);
-
+ // update geocache in DB
if (typeSelected == LogType.FOUND_IT || typeSelected == LogType.ATTENDED) {
cache.setFound(true);
cache.setVisitedDate(new Date().getTime());
}
-
DataStore.saveChangedCache(cache);
+
+ // update logs in DB
+ ArrayList<LogEntry> newLogs = new ArrayList<LogEntry>(cache.getLogs());
+ final LogEntry logNow = new LogEntry(date.getTimeInMillis(), typeSelected, log);
+ newLogs.add(0, logNow);
+ DataStore.saveLogsWithoutTransaction(cache.getGeocode(), newLogs);
+
+ // update offline log in DB
cache.clearOfflineLog();
if (typeSelected == LogType.FOUND_IT) {
@@ -557,7 +545,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
final String uploadedImageUrl = imageResult.getImageUri();
if (StringUtils.isNotEmpty(uploadedImageUrl)) {
logNow.addLogImage(new Image(uploadedImageUrl, imageCaption, imageDescription));
- DataStore.saveChangedCache(cache);
+ DataStore.saveLogsWithoutTransaction(cache.getGeocode(), newLogs);
}
return imageResult.getPostResult();
}
diff --git a/main/src/cgeo/geocaching/LogEntry.java b/main/src/cgeo/geocaching/LogEntry.java
index fde0564..ca4a3d1 100644
--- a/main/src/cgeo/geocaching/LogEntry.java
+++ b/main/src/cgeo/geocaching/LogEntry.java
@@ -14,6 +14,11 @@ import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
+/**
+ * Entry in a log book. This object should not be referenced directly from a Geocache object to reduce the memory usage
+ * of the Geocache objects.
+ *
+ */
public final class LogEntry {
private static final Pattern PATTERN_REMOVE_COLORS = Pattern.compile("</?font.*?>", Pattern.CASE_INSENSITIVE);
diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java
index b82614b..42dd58d 100644
--- a/main/src/cgeo/geocaching/MainActivity.java
+++ b/main/src/cgeo/geocaching/MainActivity.java
@@ -21,7 +21,6 @@ import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.ui.dialog.Dialogs;
import cgeo.geocaching.utils.DatabaseBackupUtils;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RxUtils;
import cgeo.geocaching.utils.Version;
import com.google.zxing.integration.android.IntentIntegrator;
@@ -30,7 +29,9 @@ import org.apache.commons.lang3.StringUtils;
import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Subscriber;
+import rx.android.observables.AndroidObservable;
import rx.functions.Action1;
+import rx.schedulers.Schedulers;
import rx.subscriptions.Subscriptions;
import android.app.AlertDialog;
@@ -551,13 +552,13 @@ public class MainActivity extends AbstractActivity {
}
}
});
- RxUtils.subscribeOnIOThenUI(address.onErrorResumeNext(Observable.from(geo.getCoords().toString())),
- new Action1<String>() {
+ AndroidObservable.bindActivity(MainActivity.this, address.onErrorResumeNext(Observable.from(geo.getCoords().toString())))
+ .subscribe(new Action1<String>() {
@Override
public void call(final String address) {
navLocation.setText(address);
}
- });
+ }, Schedulers.io());
}
} else {
navLocation.setText(geo.getCoords().toString());
@@ -569,7 +570,7 @@ public class MainActivity extends AbstractActivity {
* @param v
* unused here but needed since this method is referenced from XML layout
*/
- public void cgeoFindOnMap(@SuppressWarnings("unused") final View v) {
+ public void cgeoFindOnMap(final View v) {
findOnMap.setPressed(true);
CGeoMap.startActivityLiveMap(this);
}
@@ -578,7 +579,7 @@ public class MainActivity extends AbstractActivity {
* @param v
* unused here but needed since this method is referenced from XML layout
*/
- public void cgeoFindNearest(@SuppressWarnings("unused") final View v) {
+ public void cgeoFindNearest(final View v) {
if (app.currentGeo().getCoords() == null) {
return;
}
@@ -591,7 +592,7 @@ public class MainActivity extends AbstractActivity {
* @param v
* unused here but needed since this method is referenced from XML layout
*/
- public void cgeoFindByOffline(@SuppressWarnings("unused") final View v) {
+ public void cgeoFindByOffline(final View v) {
findByOffline.setPressed(true);
CacheListActivity.startActivityOffline(this);
}
@@ -600,7 +601,7 @@ public class MainActivity extends AbstractActivity {
* @param v
* unused here but needed since this method is referenced from XML layout
*/
- public void cgeoSearch(@SuppressWarnings("unused") final View v) {
+ public void cgeoSearch(final View v) {
advanced.setPressed(true);
startActivity(new Intent(this, SearchActivity.class));
}
@@ -609,7 +610,7 @@ public class MainActivity extends AbstractActivity {
* @param v
* unused here but needed since this method is referenced from XML layout
*/
- public void cgeoPoint(@SuppressWarnings("unused") final View v) {
+ public void cgeoPoint(final View v) {
any.setPressed(true);
startActivity(new Intent(this, NavigateAnyPointActivity.class));
}
@@ -618,7 +619,7 @@ public class MainActivity extends AbstractActivity {
* @param v
* unused here but needed since this method is referenced from XML layout
*/
- public void cgeoFilter(@SuppressWarnings("unused") final View v) {
+ public void cgeoFilter(final View v) {
filter.setPressed(true);
filter.performClick();
}
@@ -627,7 +628,7 @@ public class MainActivity extends AbstractActivity {
* @param v
* unused here but needed since this method is referenced from XML layout
*/
- public void cgeoNavSettings(@SuppressWarnings("unused") final View v) {
+ public void cgeoNavSettings(final View v) {
startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
@@ -708,7 +709,7 @@ public class MainActivity extends AbstractActivity {
* @param view
* unused here but needed since this method is referenced from XML layout
*/
- public void showAbout(@SuppressWarnings("unused") final View view) {
+ public void showAbout(final View view) {
startActivity(new Intent(this, AboutActivity.class));
}
@@ -716,7 +717,7 @@ public class MainActivity extends AbstractActivity {
* @param view
* unused here but needed since this method is referenced from XML layout
*/
- public void goSearch(@SuppressWarnings("unused") final View view) {
+ public void goSearch(final View view) {
onSearchRequested();
}
diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
index d577eb5..0a750e0 100644
--- a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
+++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
@@ -9,13 +9,13 @@ import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.geopoint.DistanceParser;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.sensors.GeoDirHandler;
import cgeo.geocaching.sensors.IGeoData;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.AbstractViewHolder;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
import cgeo.geocaching.ui.dialog.Dialogs;
-import cgeo.geocaching.sensors.GeoDirHandler;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
@@ -238,11 +238,6 @@ public class NavigateAnyPointActivity extends AbstractActivity {
init();
}
- @Override
- public void onPause() {
- super.onPause();
- }
-
private void init() {
latButton.setOnClickListener(new CoordDialogListener());
lonButton.setOnClickListener(new CoordDialogListener());
diff --git a/main/src/cgeo/geocaching/PocketQueryList.java b/main/src/cgeo/geocaching/PocketQueryList.java
index e748b29..2ac137f 100644
--- a/main/src/cgeo/geocaching/PocketQueryList.java
+++ b/main/src/cgeo/geocaching/PocketQueryList.java
@@ -2,13 +2,14 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.connector.gc.GCParser;
-import cgeo.geocaching.utils.RxUtils;
import org.apache.commons.collections4.CollectionUtils;
import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Subscriber;
+import rx.android.observables.AndroidObservable;
import rx.functions.Action1;
+import rx.schedulers.Schedulers;
import android.app.Activity;
import android.app.AlertDialog;
@@ -45,19 +46,19 @@ public final class PocketQueryList {
public static void promptForListSelection(final Activity activity, final Action1<PocketQueryList> runAfterwards) {
final Dialog waitDialog = ProgressDialog.show(activity, activity.getString(R.string.search_pocket_title), activity.getString(R.string.search_pocket_loading), true, true);
- RxUtils.subscribeOnIOThenUI(Observable.create(new OnSubscribe<List<PocketQueryList>>() {
+ AndroidObservable.bindActivity(activity, Observable.create(new OnSubscribe<List<PocketQueryList>>() {
@Override
public void call(final Subscriber<? super List<PocketQueryList>> subscriber) {
subscriber.onNext(GCParser.searchPocketQueryList());
subscriber.onCompleted();
}
- }), new Action1<List<PocketQueryList>>() {
+ })).subscribe(new Action1<List<PocketQueryList>>() {
@Override
public void call(final List<PocketQueryList> pocketQueryLists) {
waitDialog.dismiss();
selectFromPocketQueries(activity, pocketQueryLists, runAfterwards);
}
- });
+ }, Schedulers.io());
}
private static void selectFromPocketQueries(final Activity activity, final List<PocketQueryList> pocketQueryList, final Action1<PocketQueryList> runAfterwards) {
if (CollectionUtils.isEmpty(pocketQueryList)) {
diff --git a/main/src/cgeo/geocaching/StatusFragment.java b/main/src/cgeo/geocaching/StatusFragment.java
index a59316f..f8552d7 100644
--- a/main/src/cgeo/geocaching/StatusFragment.java
+++ b/main/src/cgeo/geocaching/StatusFragment.java
@@ -3,10 +3,11 @@ package cgeo.geocaching;
import cgeo.geocaching.network.StatusUpdater;
import cgeo.geocaching.network.StatusUpdater.Status;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RxUtils;
import rx.Subscription;
+import rx.android.observables.AndroidObservable;
import rx.functions.Action1;
+import rx.schedulers.Schedulers;
import android.content.Intent;
import android.content.res.Resources;
@@ -30,53 +31,53 @@ public class StatusFragment extends Fragment {
final ViewGroup statusGroup = (ViewGroup) inflater.inflate(R.layout.status, container, false);
final ImageView statusIcon = (ImageView) statusGroup.findViewById(R.id.status_icon);
final TextView statusMessage = (TextView) statusGroup.findViewById(R.id.status_message);
- statusSubscription = RxUtils.subscribeOnIOThenUI(StatusUpdater.latestStatus, new Action1<Status>() {
- @Override
- public void call(final Status status) {
- if (status == null) {
- statusGroup.setVisibility(View.INVISIBLE);
- return;
- }
+ statusSubscription = AndroidObservable.bindFragment(this, StatusUpdater.latestStatus).subscribe(new Action1<Status>() {
+ @Override
+ public void call(final Status status) {
+ if (status == null) {
+ statusGroup.setVisibility(View.INVISIBLE);
+ return;
+ }
- final Resources res = getResources();
- final String packageName = getActivity().getPackageName();
+ final Resources res = getResources();
+ final String packageName = getActivity().getPackageName();
- if (status.icon != null) {
- final int iconId = res.getIdentifier(status.icon, "drawable", packageName);
- if (iconId != 0) {
- statusIcon.setImageResource(iconId);
- statusIcon.setVisibility(View.VISIBLE);
- } else {
- Log.w("StatusHandler: could not find icon corresponding to @drawable/" + status.icon);
- statusIcon.setVisibility(View.GONE);
- }
- } else {
- statusIcon.setVisibility(View.GONE);
- }
+ if (status.icon != null) {
+ final int iconId = res.getIdentifier(status.icon, "drawable", packageName);
+ if (iconId != 0) {
+ statusIcon.setImageResource(iconId);
+ statusIcon.setVisibility(View.VISIBLE);
+ } else {
+ Log.w("StatusHandler: could not find icon corresponding to @drawable/" + status.icon);
+ statusIcon.setVisibility(View.GONE);
+ }
+ } else {
+ statusIcon.setVisibility(View.GONE);
+ }
- String message = status.message;
- if (status.messageId != null) {
- final int messageId = res.getIdentifier(status.messageId, "string", packageName);
- if (messageId != 0) {
- message = res.getString(messageId);
- }
- }
+ String message = status.message;
+ if (status.messageId != null) {
+ final int messageId = res.getIdentifier(status.messageId, "string", packageName);
+ if (messageId != 0) {
+ message = res.getString(messageId);
+ }
+ }
- statusMessage.setText(message);
- statusGroup.setVisibility(View.VISIBLE);
+ statusMessage.setText(message);
+ statusGroup.setVisibility(View.VISIBLE);
- if (status.url != null) {
- statusGroup.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(final View v) {
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(status.url)));
+ if (status.url != null) {
+ statusGroup.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(status.url)));
+ }
+ });
+ } else {
+ statusGroup.setClickable(false);
}
- });
- } else {
- statusGroup.setClickable(false);
- }
- }
- });
+ }
+ }, Schedulers.io());
return statusGroup;
}
diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java
index a14a397..81d23c9 100644
--- a/main/src/cgeo/geocaching/TrackableActivity.java
+++ b/main/src/cgeo/geocaching/TrackableActivity.java
@@ -20,12 +20,12 @@ import cgeo.geocaching.ui.UserNameClickListener;
import cgeo.geocaching.ui.logs.TrackableLogsViewCreator;
import cgeo.geocaching.utils.HtmlUtils;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RxUtils;
import cgeo.geocaching.utils.UnknownTagsHandler;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
+import rx.android.observables.AndroidObservable;
import rx.android.observables.ViewObservable;
import rx.functions.Action1;
@@ -524,7 +524,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
});
- RxUtils.subscribeThenUI(new HtmlImage(geocode, true, 0, false).fetchDrawable(trackable.getImage()), new Action1<BitmapDrawable>() {
+ AndroidObservable.bindActivity(TrackableActivity.this, new HtmlImage(geocode, true, 0, false).fetchDrawable(trackable.getImage())).subscribe(new Action1<BitmapDrawable>() {
@Override
public void call(final BitmapDrawable bitmapDrawable) {
trackableImage.setImageDrawable(bitmapDrawable);
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/MapsWithMeApp.java b/main/src/cgeo/geocaching/apps/cache/navi/MapsWithMeApp.java
new file mode 100644
index 0000000..ea5aebb
--- /dev/null
+++ b/main/src/cgeo/geocaching/apps/cache/navi/MapsWithMeApp.java
@@ -0,0 +1,43 @@
+package cgeo.geocaching.apps.cache.navi;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
+import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.geopoint.Geopoint;
+
+import com.mapswithme.maps.api.MapsWithMeApi;
+
+import android.app.Activity;
+
+public class MapsWithMeApp extends AbstractPointNavigationApp {
+
+ protected MapsWithMeApp() {
+ super(getString(R.string.cache_menu_mapswithme), R.id.cache_app_mapswithme, null);
+ }
+
+ @Override
+ public void navigate(Activity activity, Geopoint coords) {
+ navigate(activity, coords, getString(R.string.unknown));
+ }
+
+ @Override
+ public void navigate(Activity activity, Geocache cache) {
+ navigate(activity, cache.getCoords(), cache.getName());
+ }
+
+ private static void navigate(Activity activity, Geopoint coords, String label) {
+ MapsWithMeApi.showPointOnMap(activity, coords.getLatitude(), coords.getLongitude(), label);
+ }
+
+ @Override
+ public void navigate(Activity activity, Waypoint waypoint) {
+ navigate(activity, waypoint.getCoords(), waypoint.getName());
+ }
+
+ @Override
+ public boolean isInstalled() {
+ // the library can handle the app not being installed
+ return true;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
index bf0e776..3177a29 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
@@ -72,7 +72,8 @@ public final class NavigationAppFactory extends AbstractAppFactory {
CACHE_BEACON(new CacheBeaconApp(), 14, R.string.pref_navigation_menu_cache_beacon),
GCC(new GccApp(), 15, R.string.pref_navigation_menu_gcc),
WHERE_YOU_GO(new WhereYouGoApp(), 16, R.string.pref_navigation_menu_where_you_go),
- PEBBLE(new PebbleApp(), 17, R.string.pref_navigation_menu_pebble);
+ PEBBLE(new PebbleApp(), 17, R.string.pref_navigation_menu_pebble),
+ MAPSWITHME(new MapsWithMeApp(), 22, R.string.pref_navigation_menu_mapswithme);
NavigationAppsEnum(final App app, final int id, final int preferenceKey) {
this.app = app;
diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java
index 4df9d26..8212111 100644
--- a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java
@@ -21,7 +21,8 @@ public final class CacheListAppFactory extends AbstractAppFactory {
public static final CacheListApp[] apps = {
new InternalCacheListMap(),
new LocusShowCacheListApp(),
- new LocusExportCacheListApp()
+ new LocusExportCacheListApp(),
+ new MapsWithMeCacheListApp()
};
}
diff --git a/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java
new file mode 100644
index 0000000..ba177f0
--- /dev/null
+++ b/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java
@@ -0,0 +1,67 @@
+package cgeo.geocaching.apps.cachelist;
+
+import cgeo.geocaching.CacheDetailActivity;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
+import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.apps.AbstractApp;
+
+import com.mapswithme.maps.api.MWMPoint;
+import com.mapswithme.maps.api.MWMResponse;
+import com.mapswithme.maps.api.MapsWithMeApi;
+
+import org.eclipse.jdt.annotation.Nullable;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+
+import java.util.List;
+
+public class MapsWithMeCacheListApp extends AbstractApp implements CacheListApp {
+
+ protected MapsWithMeCacheListApp() {
+ super(getString(R.string.caches_map_mapswithme), R.id.cache_app_mapswithme, Intent.ACTION_VIEW);
+ }
+
+ @Override
+ public boolean invoke(List<Geocache> caches, Activity activity, SearchResult search) {
+ final MWMPoint[] points = new MWMPoint[caches.size()];
+ for (int i = 0; i < points.length; i++) {
+ Geocache geocache = caches.get(i);
+ points[i] = new MWMPoint(geocache.getCoords().getLatitude(), geocache.getCoords().getLongitude(), geocache.getName(), geocache.getGeocode());
+ }
+ MapsWithMeApi.showPointsOnMap(activity, null, getPendingIntent(activity), points);
+ return true;
+ }
+
+ @Override
+ public boolean isInstalled() {
+ // API can handle installing on the fly
+ return true;
+ }
+
+ /**
+ * get cache code from a PendingIntent after an invocation of MapsWithMe
+ *
+ * @return
+ */
+ @Nullable
+ public static String getCacheFromMapsWithMe(final Context context, final Intent intent) {
+ final MWMResponse mwmResponse = MWMResponse.extractFromIntent(context, intent);
+ if (mwmResponse != null) {
+ final MWMPoint point = mwmResponse.getPoint();
+ if (point != null) {
+ return point.getId();
+ }
+ }
+ return null;
+ }
+
+ private static PendingIntent getPendingIntent(Context context) {
+ final Intent intent = new Intent(context, CacheDetailActivity.class);
+ return PendingIntent.getActivity(context, 0, intent, 0);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index 56d434d..0549b3f 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -36,6 +36,7 @@ import cgeo.geocaching.utils.SynchronizedDateFormat;
import cgeo.geocaching.utils.TextUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
+
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
@@ -723,9 +724,6 @@ public abstract class GCParser {
cache.parseWaypointsFromNote();
- // logs
- cache.setLogs(getLogsFromDetails(page, false));
-
// last check for necessary cache conditions
if (StringUtils.isBlank(cache.getGeocode())) {
searchResult.setError(StatusCode.UNKNOWN_ERROR);
@@ -734,6 +732,7 @@ public abstract class GCParser {
cache.setDetailedUpdatedNow();
searchResult.addAndPutInCache(Collections.singletonList(cache));
+ DataStore.saveLogsWithoutTransaction(cache.getGeocode(), getLogsFromDetails(page, false));
return searchResult;
}
@@ -1831,16 +1830,18 @@ public abstract class GCParser {
//cache.setLogs(loadLogsFromDetails(page, cache, false));
if (Settings.isFriendLogsWanted()) {
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs);
- final List<LogEntry> allLogs = cache.getLogs();
final List<LogEntry> friendLogs = getLogsFromDetails(page, true);
- if (friendLogs != null) {
+ if (friendLogs != null && !friendLogs.isEmpty()) {
+ // create new list, as the existing log list is immutable
+ ArrayList<LogEntry> mergedLogs = new ArrayList<LogEntry>(cache.getLogs());
for (final LogEntry log : friendLogs) {
- if (allLogs.contains(log)) {
- allLogs.get(allLogs.indexOf(log)).friend = true;
+ if (mergedLogs.contains(log)) {
+ mergedLogs.get(mergedLogs.indexOf(log)).friend = true;
} else {
- cache.getLogs().add(log);
+ mergedLogs.add(log);
}
}
+ DataStore.saveLogsWithoutTransaction(cache.getGeocode(), mergedLogs);
}
}
diff --git a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java
index 280069f..7cced74 100644
--- a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java
+++ b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java
@@ -4,12 +4,13 @@ import cgeo.geocaching.R;
import cgeo.geocaching.loaders.RecaptchaReceiver;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RxUtils;
import org.apache.commons.io.IOUtils;
import rx.Observable;
+import rx.android.observables.AndroidObservable;
import rx.functions.Action1;
import rx.functions.Func0;
+import rx.schedulers.Schedulers;
import android.app.Activity;
import android.app.AlertDialog;
@@ -56,7 +57,7 @@ public class RecaptchaHandler extends Handler {
return Observable.empty();
}
});
- RxUtils.subscribeOnIOThenUI(captcha, new Action1<Bitmap>() {
+ AndroidObservable.bindActivity(activity, captcha).subscribe(new Action1<Bitmap>() {
@Override
public void call(final Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
@@ -66,7 +67,7 @@ public class RecaptchaHandler extends Handler {
public void call(final Throwable throwable) {
// Do nothing
}
- });
+ }, Schedulers.io());
reloadButton.setEnabled(true);
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 712bb26..3c93488 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -372,7 +372,6 @@ final class OkapiClient {
}
cache.setAttributes(parseAttributes(response.getJSONArray(CACHE_ATTRNAMES), response.optJSONArray(CACHE_ATTR_ACODES)));
- cache.setLogs(parseLogs(response.getJSONArray(CACHE_LATEST_LOGS)));
//TODO: Store license per cache
//cache.setLicense(response.getString("attribution_note"));
cache.setWaypoints(parseWaypoints(response.getJSONArray(CACHE_WPTS)), false);
@@ -388,6 +387,7 @@ final class OkapiClient {
cache.setDetailedUpdatedNow();
// save full detailed caches
DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveLogsWithoutTransaction(cache.getGeocode(), parseLogs(response.getJSONArray(CACHE_LATEST_LOGS)));
} catch (final JSONException e) {
Log.e("OkapiClient.parseCache", e);
}
diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java
index 35fe7a1..506c791 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheType.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheType.java
@@ -19,7 +19,8 @@ public enum CacheType {
MYSTERY("mystery", "Unknown Cache", "40861821-1835-4e11-b666-8d41064d03fe", R.string.mystery, R.drawable.type_mystery),
LETTERBOX("letterbox", "Letterbox hybrid", "4bdd8fb2-d7bc-453f-a9c5-968563b15d24", R.string.letterbox, R.drawable.type_letterbox),
EVENT("event", "Event Cache", "69eb8534-b718-4b35-ae3c-a856a55b0874", R.string.event, R.drawable.type_event),
- MEGA_EVENT("mega", "Mega-event Cache", "69eb8535-b718-4b35-ae3c-a856a55b0874", R.string.mega, R.drawable.type_mega),
+ MEGA_EVENT("mega", "Mega-Event Cache", "69eb8535-b718-4b35-ae3c-a856a55b0874", R.string.mega, R.drawable.type_mega),
+ GIGA_EVENT("giga", "Giga-Event Cache", "51420629-5739-4945-8bdd-ccfd434c0ead", R.string.giga, R.drawable.type_giga),
EARTH("earth", "Earthcache", "c66f5cf3-9523-4549-b8dd-759cd2f18db8", R.string.earth, R.drawable.type_earth),
CITO("cito", "Cache in Trash out Event", "57150806-bc1a-42d6-9cf0-538d171a2d22", R.string.cito, R.drawable.type_cito),
WEBCAM("webcam", "Webcam Cache", "31d2ae3c-c358-4b5f-8dcd-2185bf472d3d", R.string.webcam, R.drawable.type_webcam),
@@ -89,7 +90,7 @@ public enum CacheType {
}
public boolean isEvent() {
- return EVENT == this || MEGA_EVENT == this || CITO == this || LOSTANDFOUND == this || BLOCK_PARTY == this || GPS_EXHIBIT == this;
+ return EVENT == this || MEGA_EVENT == this || CITO == this || GIGA_EVENT == this || LOSTANDFOUND == this || BLOCK_PARTY == this || GPS_EXHIBIT == this;
}
@Override
diff --git a/main/src/cgeo/geocaching/export/GpxSerializer.java b/main/src/cgeo/geocaching/export/GpxSerializer.java
index fef91cf..b2587aa 100644
--- a/main/src/cgeo/geocaching/export/GpxSerializer.java
+++ b/main/src/cgeo/geocaching/export/GpxSerializer.java
@@ -34,7 +34,7 @@ public final class GpxSerializer {
public static final String PREFIX_XSI = "http://www.w3.org/2001/XMLSchema-instance";
public static final String PREFIX_GPX = "http://www.topografix.com/GPX/1/0";
public static final String PREFIX_GROUNDSPEAK = "http://www.groundspeak.com/cache/1/0";
- public static final String PREFIX_GSAK = "http://www.gsak.net/xmlv1/4";
+ public static final String PREFIX_GSAK = "http://www.gsak.net/xmlv1/6";
public static final String PREFIX_CGEO = "http://www.cgeo.org/wptext/1/0";
/**
@@ -74,7 +74,7 @@ public final class GpxSerializer {
gpx.attribute(PREFIX_XSI, "schemaLocation",
PREFIX_GPX + " http://www.topografix.com/GPX/1/0/gpx.xsd " +
PREFIX_GROUNDSPEAK + " http://www.groundspeak.com/cache/1/0/1/cache.xsd " +
- PREFIX_GSAK + " http://www.gsak.net/xmlv1/4/gsak.xsd");
+ PREFIX_GSAK + " http://www.gsak.net/xmlv1/6/gsak.xsd");
// Split the overall set of geocodes into small chunks. That is a compromise between memory efficiency (because
// we don't load all caches fully into memory) and speed (because we don't query each cache separately).
@@ -129,8 +129,8 @@ public final class GpxSerializer {
"container", cache.getSize().id,
"difficulty", Float.toString(cache.getDifficulty()),
"terrain", Float.toString(cache.getTerrain()),
- "country", cache.getLocation(),
- "state", "",
+ "country", getCountry(cache),
+ "state", getState(cache),
"encoded_hints", cache.getHint());
writeAttributes(cache);
@@ -149,6 +149,9 @@ public final class GpxSerializer {
writeTravelBugs(cache);
gpx.endTag(PREFIX_GROUNDSPEAK, "cache");
+
+ writeGSAK(cache);
+
gpx.endTag(PREFIX_GPX, "wpt");
writeWaypoints(cache);
@@ -160,6 +163,25 @@ public final class GpxSerializer {
}
}
+ private void writeGSAK(final Geocache cache) throws IOException {
+ gpx.startTag(PREFIX_GSAK, "wptExtension");
+ XmlUtils.multipleTexts(gpx, PREFIX_GSAK,
+ "IsPremium", gpxBoolean(cache.isPremiumMembersOnly()),
+ "FavPoints", Integer.toString(cache.getFavoritePoints()),
+ "Watch", gpxBoolean(cache.isOnWatchlist()),
+ "GcNote", StringUtils.trimToEmpty(cache.getPersonalNote()));
+ gpx.endTag(PREFIX_GSAK, "wptExtension");
+ }
+
+ /**
+ * @param boolFlag
+ * @return XML schema compliant boolean representation of the boolean flag. This must be either true, false, 0 or 1,
+ * but no other value (also not upper case True/False).
+ */
+ private static String gpxBoolean(boolean boolFlag) {
+ return boolFlag ? "true" : "false";
+ }
+
private void writeWaypoints(final Geocache cache) throws IOException {
final List<Waypoint> waypoints = cache.getWaypoints();
final List<Waypoint> ownWaypoints = new ArrayList<Waypoint>(waypoints.size());
@@ -239,12 +261,13 @@ public final class GpxSerializer {
}
private void writeLogs(final Geocache cache) throws IOException {
- if (cache.getLogs().isEmpty()) {
+ List<LogEntry> logs = cache.getLogs();
+ if (logs.isEmpty()) {
return;
}
gpx.startTag(PREFIX_GROUNDSPEAK, "logs");
- for (final LogEntry log : cache.getLogs()) {
+ for (final LogEntry log : logs) {
gpx.startTag(PREFIX_GROUNDSPEAK, "log");
gpx.attribute("", "id", Integer.toString(log.id));
@@ -317,4 +340,27 @@ public final class GpxSerializer {
gpx.endTag(PREFIX_GROUNDSPEAK, "attributes");
}
+ public static String getState(final Geocache cache) {
+ return getLocationPart(cache, 0);
+ }
+
+ private static String getLocationPart(final Geocache cache, int partIndex) {
+ final String location = cache.getLocation();
+ if (StringUtils.contains(location, ", ")) {
+ final String[] parts = StringUtils.split(location, ',');
+ if (parts.length == 2) {
+ return StringUtils.trim(parts[partIndex]);
+ }
+ }
+ return StringUtils.EMPTY;
+ }
+
+ public static String getCountry(final Geocache cache) {
+ String country = getLocationPart(cache, 1);
+ if (StringUtils.isNotEmpty(country)) {
+ return country;
+ }
+ // fall back to returning everything, but only for the country
+ return cache.getLocation();
+ }
}
diff --git a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
index 35e6265..07b4fb4 100644
--- a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
+++ b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
@@ -121,6 +121,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
}
+ @SuppressWarnings("static-method")
protected boolean requireFiles() {
return true;
}
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
index f5380be..8d328e4 100644
--- a/main/src/cgeo/geocaching/files/GPXParser.java
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -42,6 +42,7 @@ import java.util.Collection;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashSet;
+import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;
@@ -99,6 +100,7 @@ public abstract class GPXParser extends FileParser {
private String parentCacheCode = null;
private boolean wptVisited = false;
private boolean wptUserDefined = false;
+ private List<LogEntry> logs = new ArrayList<LogEntry>();
/**
* Parser result. Maps geocode to cache.
@@ -334,6 +336,7 @@ public abstract class GPXParser extends FileParser {
// finally store the cache in the database
result.add(geocode);
DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveLogsWithoutTransaction(cache.getGeocode(), logs);
// avoid the cachecache using lots of memory for caches which the user did not actually look at
DataStore.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
@@ -757,7 +760,7 @@ public abstract class GPXParser extends FileParser {
@Override
public void end() {
if (log.type != LogType.UNKNOWN) {
- cache.getLogs().add(log);
+ logs.add(log);
}
}
});
@@ -876,7 +879,7 @@ public abstract class GPXParser extends FileParser {
/**
* Add listeners for c:geo extensions
- *
+ *
* @param cacheParent
*/
private void registerCgeoExtensions(final Element cacheParent) {
@@ -985,6 +988,7 @@ public abstract class GPXParser extends FileParser {
parentCacheCode = null;
wptVisited = false;
wptUserDefined = false;
+ logs = new ArrayList<LogEntry>();
cache = new Geocache(this);
diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java
index 6f0d5da..552a48c 100644
--- a/main/src/cgeo/geocaching/filter/AttributeFilter.java
+++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java
@@ -1,14 +1,11 @@
package cgeo.geocaching.filter;
import cgeo.geocaching.CgeoApplication;
-import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.enumerations.LoadFlags.LoadFlag;
import android.content.res.Resources;
-import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
@@ -29,11 +26,7 @@ class AttributeFilter extends AbstractFilter {
@Override
public boolean accepts(final Geocache cache) {
- Geocache fullCache = DataStore.loadCache(cache.getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES));
- if (fullCache == null) {
- fullCache = cache;
- }
- return fullCache.getAttributes().contains(attribute);
+ return cache.getAttributes().contains(attribute);
}
public static class Factory implements IFilterFactory {
diff --git a/main/src/cgeo/geocaching/list/StoredList.java b/main/src/cgeo/geocaching/list/StoredList.java
index 7e2a83c..e557fc8 100644
--- a/main/src/cgeo/geocaching/list/StoredList.java
+++ b/main/src/cgeo/geocaching/list/StoredList.java
@@ -147,6 +147,8 @@ public final class StoredList extends AbstractList {
public void promptForListCreation(@NonNull final Action1<Integer> runAfterwards, String newListName) {
handleListNameInput(newListName, R.string.list_dialog_create_title, R.string.list_dialog_create, new Action1<String>() {
+ // We need to update the list cache by creating a new StoredList object here.
+ @SuppressWarnings("unused")
@Override
public void call(final String listName) {
final int newId = DataStore.createList(listName);
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
index e993548..7a5aab2 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
@@ -15,6 +15,7 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import org.mapsforge.android.maps.MapView;
import org.mapsforge.android.maps.Projection;
import org.mapsforge.android.maps.mapgenerator.MapGenerator;
@@ -49,7 +50,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl {
}
@Override
- public void draw(Canvas canvas) {
+ public void draw(@NonNull Canvas canvas) {
try {
// Google Maps and OSM Maps use different zoom levels for the same view.
// Here we don't want the Google Maps compatible zoom level, but the actual one.
@@ -74,6 +75,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl {
}
@Override
+ @NonNull
public GeoPointImpl getMapViewCenter() {
GeoPoint point = getMapPosition().getMapCenter();
return new MapsforgeGeoPoint(point.latitudeE6, point.longitudeE6);
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
index 30caed5..4fa4e02 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
@@ -41,7 +41,7 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl {
}
@Override
- public void draw(Canvas canvas) {
+ public void draw(@NonNull Canvas canvas) {
try {
// Google Maps and OSM Maps use different zoom levels for the same view.
// Here we don't want the Google Maps compatible zoom level, but the actual one.
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java
index 8ee2ba7..9c55fe9 100644
--- a/main/src/cgeo/geocaching/network/HtmlImage.java
+++ b/main/src/cgeo/geocaching/network/HtmlImage.java
@@ -25,6 +25,7 @@ import rx.Scheduler;
import rx.Scheduler.Inner;
import rx.Subscriber;
import rx.functions.Action1;
+import rx.functions.Func0;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject;
@@ -132,6 +133,18 @@ public class HtmlImage implements Html.ImageGetter {
return Observable.from(getTransparent1x1Image(resources));
}
+ // Explicit local file URLs are loaded from the filesystem regardless of their age. The IO part is short
+ // enough to make the whole operation on the computation scheduler.
+ if (FileUtils.isFileUrl(url)) {
+ return Observable.defer(new Func0<Observable<? extends BitmapDrawable>>() {
+ @Override
+ public Observable<? extends BitmapDrawable> call() {
+ final Bitmap bitmap = loadCachedImage(FileUtils.urlToFile(url), true).getLeft();
+ return bitmap != null ? Observable.from(ImageUtils.scaleBitmapToFitDisplay(bitmap)) : Observable.<BitmapDrawable>empty();
+ }
+ }).subscribeOn(RxUtils.computationScheduler);
+ }
+
final boolean shared = url.contains("/images/icons/icon_");
final String pseudoGeocode = shared ? SHARED : geocode;
diff --git a/main/src/cgeo/geocaching/sensors/DirectionProvider.java b/main/src/cgeo/geocaching/sensors/DirectionProvider.java
index 788d5bd..ff4a439 100644
--- a/main/src/cgeo/geocaching/sensors/DirectionProvider.java
+++ b/main/src/cgeo/geocaching/sensors/DirectionProvider.java
@@ -30,6 +30,7 @@ public class DirectionProvider {
private int count = 0;
private SensorManager sensorManager;
+
@Override
public void onSensorChanged(final SensorEvent event) {
subject.onNext(event.values[0]);
@@ -50,23 +51,52 @@ public class DirectionProvider {
//Log.i(Settings.tag, "Compass' accuracy is low (" + accuracy + ")");
}
- // This will be removed when using a new location service. Until then, it is okay to be used.
- @SuppressWarnings("deprecation")
@Override
public void start(final Context context, final Handler handler) {
+ if (!hasSensor(context)) {
+ return;
+ }
if (++count == 1) {
- sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
- sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL, handler);
+ Sensor orientationSensor = getOrientationSensor(context);
+ sensorManager.registerListener(this, orientationSensor, SensorManager.SENSOR_DELAY_NORMAL, handler);
}
}
@Override
public void stop() {
+ if (!hasSensor) {
+ return;
+ }
if (--count == 0) {
sensorManager.unregisterListener(this);
}
}
+ /**
+ * Assume that there is an orientation sensor, unless we have really checked that
+ */
+ private boolean hasSensor = true;
+
+ /**
+ * Flag for one time check if there is a sensor.
+ */
+ private boolean hasSensorChecked = false;
+
+ public boolean hasSensor(Context context) {
+ if (hasSensorChecked == false) {
+ hasSensor = getOrientationSensor(context) != null;
+ hasSensorChecked = true;
+ }
+ return hasSensor;
+ }
+
+ // This will be removed when using a new location service. Until then, it is okay to be used.
+ @SuppressWarnings("deprecation")
+ private Sensor getOrientationSensor(final Context context) {
+ sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+ return sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
+ }
+
}
private static final StartableHandlerThread handlerThread =
diff --git a/main/src/cgeo/geocaching/sensors/GeoDirHandler.java b/main/src/cgeo/geocaching/sensors/GeoDirHandler.java
index c10cb48..0f30142 100644
--- a/main/src/cgeo/geocaching/sensors/GeoDirHandler.java
+++ b/main/src/cgeo/geocaching/sensors/GeoDirHandler.java
@@ -4,6 +4,7 @@ import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.settings.Settings;
import org.apache.commons.lang3.tuple.ImmutablePair;
+
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
@@ -37,7 +38,7 @@ public abstract class GeoDirHandler {
*
* @param geoData the new geographical data
*/
- public void updateGeoData(@SuppressWarnings("unused") final IGeoData geoData) {
+ public void updateGeoData(final IGeoData geoData) {
}
/**
@@ -46,7 +47,7 @@ public abstract class GeoDirHandler {
*
* @param direction the new direction
*/
- public void updateDirection(@SuppressWarnings("unused") final float direction) {
+ public void updateDirection(final float direction) {
}
/**
@@ -59,7 +60,7 @@ public abstract class GeoDirHandler {
* If the device goes fast enough, or if the compass use is not enabled in the settings,
* the GPS direction information will be used instead of the compass one.
*/
- public void updateGeoDir(@SuppressWarnings("unused") final IGeoData geoData, @SuppressWarnings("unused") final float direction) {
+ public void updateGeoDir(final IGeoData geoData, final float direction) {
}
private static Observable<Float> fixedDirection() {
diff --git a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java
index 298270b..917c9c4 100644
--- a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java
+++ b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java
@@ -5,12 +5,13 @@ import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.network.Cookies;
import cgeo.geocaching.ui.dialog.Dialogs;
-import cgeo.geocaching.utils.RxUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import rx.android.observables.AndroidObservable;
import rx.functions.Action1;
import rx.functions.Func0;
+import rx.schedulers.Schedulers;
import rx.util.async.Async;
import android.app.ProgressDialog;
@@ -64,12 +65,12 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab
loginDialog.setCancelable(false);
Cookies.clearCookies();
- RxUtils.subscribeOnIOThenUI(Async.start(new Func0<ImmutablePair<StatusCode, ? extends Drawable>>() {
+ AndroidObservable.bindActivity(activity, Async.start(new Func0<ImmutablePair<StatusCode, ? extends Drawable>>() {
@Override
public ImmutablePair<StatusCode, ? extends Drawable> call() {
return login();
}
- }), new Action1<ImmutablePair<StatusCode, ? extends Drawable>>() {
+ })).subscribe(new Action1<ImmutablePair<StatusCode, ? extends Drawable>>() {
@Override
public void call(final ImmutablePair<StatusCode, ? extends Drawable> loginInfo) {
loginDialog.dismiss();
@@ -85,7 +86,7 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab
}
activity.initBasicMemberPreferences();
}
- });
+ }, Schedulers.io());
return false; // no shared preference has to be changed
}
diff --git a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
index 1b18438..cc2de9f 100644
--- a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
+++ b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
@@ -6,13 +6,14 @@ import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.ui.dialog.Dialogs;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RxUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
import org.apache.commons.lang3.StringUtils;
import rx.Observable;
+import rx.android.observables.AndroidObservable;
import rx.functions.Action1;
import rx.functions.Func0;
+import rx.schedulers.Schedulers;
import android.app.ProgressDialog;
import android.content.Context;
@@ -52,7 +53,7 @@ public class RegisterSend2CgeoPreference extends AbstractClickablePreference {
activity.getString(R.string.init_sendToCgeo_registering), true);
progressDialog.setCancelable(false);
- RxUtils.subscribeOnIOThenUI(Observable.defer(new Func0<Observable<Integer>>() {
+ AndroidObservable.bindActivity(activity, Observable.defer(new Func0<Observable<Integer>>() {
@Override
public Observable<Integer> call() {
final String nam = StringUtils.defaultString(deviceName);
@@ -74,7 +75,7 @@ public class RegisterSend2CgeoPreference extends AbstractClickablePreference {
return Observable.empty();
}
- }).firstOrDefault(0), new Action1<Integer>() {
+ }).firstOrDefault(0)).subscribe(new Action1<Integer>() {
@Override
public void call(final Integer pin) {
progressDialog.dismiss();
@@ -86,7 +87,7 @@ public class RegisterSend2CgeoPreference extends AbstractClickablePreference {
Dialogs.message(activity, R.string.init_sendToCgeo, R.string.init_sendToCgeo_register_fail);
}
}
- });
+ }, Schedulers.io());
return true;
}
diff --git a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java
index 2b171b4..968dce5 100644
--- a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java
+++ b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java
@@ -34,12 +34,13 @@ public abstract class AbstractCacheComparator implements CacheComparator {
/**
* Check necessary preconditions (like missing fields) before running the comparison itself.
* Caches not filling the conditions will be placed last, sorted by Geocode.
- *
+ *
* The default returns <code>true</code> and can be overridden if needed in child classes.
- *
+ *
* @param cache
* @return <code>true</code> if the cache holds the necessary data to be compared meaningfully
*/
+ @SuppressWarnings("static-method")
protected boolean canCompare(final Geocache cache) {
return true;
}
diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
index d827e3e..0d90d9f 100644
--- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
@@ -377,7 +377,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
final boolean lightSkin = Settings.isLightSkin();
- final TouchListener touchListener = new TouchListener(cache, v);
+ final TouchListener touchListener = new TouchListener(cache);
v.setOnClickListener(touchListener);
v.setOnLongClickListener(touchListener);
v.setOnTouchListener(touchListener);
@@ -541,7 +541,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
private final Geocache cache;
private final GestureDetector gestureDetector;
- public TouchListener(final Geocache cache, final View view) {
+ public TouchListener(final Geocache cache) {
this.cache = cache;
gestureDetector = new GestureDetector(getContext(), new FlingGesture(cache));
}
diff --git a/main/src/cgeo/geocaching/ui/ImagesList.java b/main/src/cgeo/geocaching/ui/ImagesList.java
index d1b2a64..5727971 100644
--- a/main/src/cgeo/geocaching/ui/ImagesList.java
+++ b/main/src/cgeo/geocaching/ui/ImagesList.java
@@ -6,11 +6,11 @@ import cgeo.geocaching.files.LocalStorage;
import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.RxUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import rx.Subscription;
+import rx.android.observables.AndroidObservable;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.subscriptions.CompositeSubscription;
@@ -118,7 +118,7 @@ public class ImagesList {
final ImageView imageView = (ImageView) inflater.inflate(R.layout.image_item, null);
assert(imageView != null);
- subscriptions.add(RxUtils.subscribeThenUI(imgGetter.fetchDrawable(img.getUrl()), new Action1<BitmapDrawable>() {
+ subscriptions.add(AndroidObservable.bindActivity(activity, imgGetter.fetchDrawable(img.getUrl())).subscribe(new Action1<BitmapDrawable>() {
@Override
public void call(final BitmapDrawable image) {
display(imageView, image, img, rowView);
@@ -214,7 +214,7 @@ public class ImagesList {
private void viewImageInStandardApp(final Image img, final BitmapDrawable image) {
try {
final Intent intent = new Intent().setAction(android.content.Intent.ACTION_VIEW);
- final File file = LocalStorage.getStorageFile(geocode, img.getUrl(), true, true);
+ final File file = img.isLocalFile() ? img.localFile() : LocalStorage.getStorageFile(geocode, img.getUrl(), true, true);
if (file.exists()) {
intent.setDataAndType(Uri.fromFile(file), mimeTypeForUrl(img.getUrl()));
} else {
diff --git a/main/src/cgeo/geocaching/utils/FileUtils.java b/main/src/cgeo/geocaching/utils/FileUtils.java
index 4a349a8..979820c 100644
--- a/main/src/cgeo/geocaching/utils/FileUtils.java
+++ b/main/src/cgeo/geocaching/utils/FileUtils.java
@@ -23,6 +23,8 @@ import java.util.List;
*/
public final class FileUtils {
+ private static final String FILE_PROTOCOL = "file://";
+
private FileUtils() {
// utility class
}
@@ -153,4 +155,32 @@ public final class FileUtils {
}
return true;
}
+
+ /**
+ * Check if the URL represents a file on the local file system.
+ *
+ * @return <tt>true</tt> if the URL scheme is <tt>file</tt>, <tt>false</tt> otherwise
+ */
+ public static boolean isFileUrl(final String url) {
+ return StringUtils.startsWith(url, FILE_PROTOCOL);
+ }
+
+ /**
+ * Build an URL from a file name.
+ *
+ * @param file a local file name
+ * @return an URL with the <tt>file</tt> scheme
+ */
+ public static String fileToUrl(final File file) {
+ return FILE_PROTOCOL + file.getAbsolutePath();
+ }
+
+ /**
+ * Local file name when {@link #isFileUrl(String)} is <tt>true</tt>.
+ *
+ * @return the local file
+ */
+ public static File urlToFile(final String url) {
+ return new File(StringUtils.substring(url, FILE_PROTOCOL.length()));
+ }
}
diff --git a/main/src/cgeo/geocaching/utils/ImageUtils.java b/main/src/cgeo/geocaching/utils/ImageUtils.java
index e226703..ffb7bf3 100644
--- a/main/src/cgeo/geocaching/utils/ImageUtils.java
+++ b/main/src/cgeo/geocaching/utils/ImageUtils.java
@@ -273,9 +273,11 @@ public final class ImageUtils {
/**
* Decode a base64-encoded string and save the result into a stream.
- *
- * @param inString the encoded string
- * @param outFile the file to save the decoded result into
+ *
+ * @param inString
+ * the encoded string
+ * @param out
+ * the stream to save the decoded result into
*/
public static void decodeBase64ToStream(final String inString, final OutputStream out) throws IOException {
Base64InputStream in = null;
diff --git a/main/src/cgeo/geocaching/utils/MiscUtils.java b/main/src/cgeo/geocaching/utils/MiscUtils.java
deleted file mode 100644
index 122c4eb..0000000
--- a/main/src/cgeo/geocaching/utils/MiscUtils.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package cgeo.geocaching.utils;
-
-import org.apache.commons.collections4.iterators.IteratorIterable;
-import org.apache.commons.lang3.NotImplementedException;
-
-import java.util.Iterator;
-import java.util.List;
-
-final public class MiscUtils {
-
- private MiscUtils() {} // Do not instantiate
-
- public static <T> Iterable<List<T>> buffer(final List<T> original, final int n) {
- if (n <= 0) {
- throw new IllegalArgumentException("buffer size must be positive");
- }
- return new IteratorIterable<List<T>>(new Iterator<List<T>>() {
- final int size = original.size();
- int next = 0;
-
- @Override
- public boolean hasNext() {
- return next < size;
- }
-
- @Override
- public List<T> next() {
- final List<T> result = original.subList(next, Math.min(next + n, size));
- next += n;
- return result;
- }
-
- @Override
- public void remove() {
- throw new NotImplementedException("remove");
- }
- });
- }
-
-}
diff --git a/main/src/cgeo/geocaching/utils/RxUtils.java b/main/src/cgeo/geocaching/utils/RxUtils.java
index 9926bab..8e7864c 100644
--- a/main/src/cgeo/geocaching/utils/RxUtils.java
+++ b/main/src/cgeo/geocaching/utils/RxUtils.java
@@ -1,11 +1,6 @@
package cgeo.geocaching.utils;
-import rx.Observable;
-import rx.Observer;
import rx.Scheduler;
-import rx.Subscription;
-import rx.android.schedulers.AndroidSchedulers;
-import rx.functions.Action1;
import rx.schedulers.Schedulers;
import java.util.concurrent.LinkedBlockingQueue;
@@ -20,32 +15,4 @@ public class RxUtils {
final static private int cores = Runtime.getRuntime().availableProcessors();
public final static Scheduler computationScheduler = Schedulers.executor(new ThreadPoolExecutor(1, cores, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()));
- public static <T> Subscription subscribeThenUI(final Observable<T> observable, final Observer<T> observer) {
- return observable.observeOn(AndroidSchedulers.mainThread()).subscribe(observer);
- }
-
- public static <T> Subscription subscribeThenUI(final Observable<T> observable, final Action1<T> action) {
- return observable.observeOn(AndroidSchedulers.mainThread()).subscribe(action);
- }
-
- public static <T> Subscription subscribeThenUI(final Observable<T> observable, final Action1<T> action, final Action1<Throwable> onError) {
- return observable.observeOn(AndroidSchedulers.mainThread()).subscribe(action, onError);
- }
-
- public static <T> Observable<T> onIO(final Observable<T> observable) {
- return observable.subscribeOn(Schedulers.io());
- }
-
- public static <T> Subscription subscribeOnIOThenUI(final Observable<T> observable, final Observer<T> observer) {
- return subscribeThenUI(onIO(observable), observer);
- }
-
- public static <T> Subscription subscribeOnIOThenUI(final Observable<T> observable, final Action1<T> action) {
- return subscribeThenUI(onIO(observable), action);
- }
-
- public static <T> Subscription subscribeOnIOThenUI(final Observable<T> observable, final Action1<T> action, final Action1<Throwable> onError) {
- return subscribeThenUI(onIO(observable), action, onError);
- }
-
}