From 30194eb7d4dfd083ae7e456342203cc6d9d9cf81 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 16:39:46 +0200 Subject: Move functions to count visible points in viewport class --- main/src/cgeo/geocaching/geopoint/Viewport.java | 16 ++++++++++++++++ main/src/cgeo/geocaching/maps/CGeoMap.java | 16 +--------------- 2 files changed, 17 insertions(+), 15 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/geopoint/Viewport.java b/main/src/cgeo/geocaching/geopoint/Viewport.java index ba0e040..171000e 100644 --- a/main/src/cgeo/geocaching/geopoint/Viewport.java +++ b/main/src/cgeo/geocaching/geopoint/Viewport.java @@ -79,6 +79,22 @@ public final class Viewport { && coords.getLatitudeE6() <= topRight.getLatitudeE6(); } + /** + * Count the number of points present in the viewport. + * + * @param points a collection of (possibly null) points + * @return the number of non-null points in the viewport + */ + public int count(final @NonNull Collection points) { + int total = 0; + for (ICoordinates point: points) { + if (point != null && contains(point)) { + total = total + 1; + } + } + return total; + } + @Override public String toString() { return "(" + bottomLeft.toString() + "," + topRight.toString() + ")"; diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index 2ca0cfd..e96c246 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -373,21 +373,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } protected void countVisibleCaches() { - final List protectedCaches = caches.getAsList(); - - int count = 0; - if (!protectedCaches.isEmpty()) { - final Viewport viewport = mapView.getViewport(); - - for (final Geocache cache : protectedCaches) { - if (cache != null && cache.getCoords() != null) { - if (viewport.contains(cache)) { - count++; - } - } - } - } - cachesCnt = count; + cachesCnt = mapView.getViewport().count(caches.getAsList()); } @Override -- cgit v1.1 From 836fc36b272f5865e5c46e1f08e67eeeb49b3eae Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 16:44:16 +0200 Subject: Inline method used only once --- main/src/cgeo/geocaching/maps/CGeoMap.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index e96c246..cccc15c 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -1014,7 +1014,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { displayPoint(coordsIntent); loadTimer = Subscriptions.empty(); } else { - loadTimer = startLoadTimer(); + loadTimer = Schedulers.newThread().createWorker().schedulePeriodically(new LoadTimerAction(this), 0, 250, TimeUnit.MILLISECONDS); } return loadTimer; } @@ -1071,13 +1071,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } /** - * loading timer Triggers every 250ms and checks for viewport change and starts a {@link LoadRunnable}. - */ - private Subscription startLoadTimer() { - return Schedulers.newThread().createWorker().schedulePeriodically(new LoadTimerAction(this), 0, 250, TimeUnit.MILLISECONDS); - } - - /** * get if map is loading something * * @return -- cgit v1.1 From c687d8b70878935ed2fef931b1818c3a3c08d018 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 16:47:53 +0200 Subject: Do not catch ThreadDeath exception There is no reason to catch ThreadDeath exception here. --- main/src/cgeo/geocaching/maps/CGeoMap.java | 7 ------- 1 file changed, 7 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index cccc15c..db71c84 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -204,7 +204,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { private static BlockingQueue downloadQueue = new ArrayBlockingQueue<>(1); private static ThreadPoolExecutor downloadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, downloadQueue, new ThreadPoolExecutor.DiscardOldestPolicy()); private static BlockingQueue loadQueue = new ArrayBlockingQueue<>(1); - private static ThreadPoolExecutor loadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, loadQueue, new ThreadPoolExecutor.DiscardOldestPolicy()); // handlers /** Updates the titles */ @@ -1218,9 +1217,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { //render displayExecutor.execute(new DisplayRunnable(this)); - } catch (final ThreadDeath e) { - Log.d("DownloadThread stopped"); - displayHandler.sendEmptyMessage(UPDATE_TITLE); } finally { showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress } @@ -1280,9 +1276,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } displayHandler.sendEmptyMessage(UPDATE_TITLE); - } catch (final ThreadDeath e) { - Log.d("DisplayThread stopped"); - displayHandler.sendEmptyMessage(UPDATE_TITLE); } finally { showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); } -- cgit v1.1 From 4c08563f0ba5d84cfbe37707b35f2e22d2c6bd23 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 17:02:23 +0200 Subject: Remove special handling of pseudo location --- main/src/cgeo/geocaching/maps/CGeoMap.java | 19 ++++--------------- main/src/cgeo/geocaching/sensors/GeoData.java | 9 +-------- main/src/cgeo/geocaching/sensors/GeoDataProvider.java | 10 +++------- main/src/cgeo/geocaching/sensors/IGeoData.java | 2 -- 4 files changed, 8 insertions(+), 32 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index db71c84..59ac4d7 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -891,7 +891,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { // Set center of map to my location if appropriate. private void myLocationInMiddle(final IGeoData geo) { - if (followMyLocation && !geo.isPseudoLocation()) { + if (followMyLocation) { centerMap(geo.getCoords()); } } @@ -908,7 +908,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { private static final float MIN_LOCATION_DELTA = 0.01f; Location currentLocation = new Location(""); - boolean locationValid = false; float currentHeading; private long timeLastPositionOverlayCalculation = 0; @@ -923,15 +922,9 @@ public class CGeoMap extends AbstractMap implements ViewFactory { @Override public void updateGeoDir(final IGeoData geo, final float dir) { - if (geo.isPseudoLocation()) { - locationValid = false; - } else { - locationValid = true; - - currentLocation = geo.getLocation(); - currentHeading = DirectionProvider.getDirectionNow(dir); - repaintPositionOverlay(); - } + currentLocation = geo.getLocation(); + currentHeading = DirectionProvider.getDirectionNow(dir); + repaintPositionOverlay(); } /** @@ -975,10 +968,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } boolean needsRepaintForDistance() { - if (!locationValid) { - return false; - } - final CGeoMap map = mapRef.get(); if (map == null) { return false; diff --git a/main/src/cgeo/geocaching/sensors/GeoData.java b/main/src/cgeo/geocaching/sensors/GeoData.java index c0b3974..c0f57b5 100644 --- a/main/src/cgeo/geocaching/sensors/GeoData.java +++ b/main/src/cgeo/geocaching/sensors/GeoData.java @@ -10,14 +10,12 @@ class GeoData extends Location implements IGeoData { private final boolean gpsEnabled; private final int satellitesVisible; private final int satellitesFixed; - private final boolean pseudoLocation; - GeoData(final Location location, final boolean gpsEnabled, final int satellitesVisible, final int satellitesFixed, final boolean pseudoLocation) { + GeoData(final Location location, final boolean gpsEnabled, final int satellitesVisible, final int satellitesFixed) { super(location); this.gpsEnabled = gpsEnabled; this.satellitesVisible = satellitesVisible; this.satellitesFixed = satellitesFixed; - this.pseudoLocation = pseudoLocation; } @Override @@ -59,9 +57,4 @@ class GeoData extends Location implements IGeoData { public int getSatellitesFixed() { return satellitesFixed; } - - @Override - public boolean isPseudoLocation() { - return pseudoLocation; - } } diff --git a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java index a4799cb..50d42db 100644 --- a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java +++ b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java @@ -3,8 +3,6 @@ package cgeo.geocaching.sensors; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.StartableHandlerThread; -import org.apache.commons.lang3.StringUtils; - import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; @@ -29,7 +27,6 @@ import java.util.concurrent.TimeUnit; public class GeoDataProvider implements OnSubscribe { - private static final String LAST_LOCATION_PSEUDO_PROVIDER = "last"; private final LocationManager geoManager; private final LocationData gpsLocation = new LocationData(); private final LocationData netLocation = new LocationData(); @@ -140,7 +137,7 @@ public class GeoDataProvider implements OnSubscribe { }; private IGeoData findInitialLocation() { - final Location initialLocation = new Location(LAST_LOCATION_PSEUDO_PROVIDER); + final Location initialLocation = new Location("initial"); try { // Try to find a sensible initial location from the last locations known to Android. final Location lastGpsLocation = geoManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); @@ -167,7 +164,7 @@ public class GeoDataProvider implements OnSubscribe { } // Start with an historical GeoData just in case someone queries it before we get // a chance to get any information. - return new GeoData(initialLocation, false, 0, 0, true); + return new GeoData(initialLocation, false, 0, 0); } private static void copyCoords(final Location target, final Location source) { @@ -275,8 +272,7 @@ public class GeoDataProvider implements OnSubscribe { // We do not necessarily get signalled when satellites go to 0/0. final int visible = gpsLocation.isRecent() ? satellitesVisible : 0; - final boolean pseudoLocation = StringUtils.equals(locationData.location.getProvider(), LAST_LOCATION_PSEUDO_PROVIDER); - final IGeoData current = new GeoData(locationData.location, gpsEnabled, visible, satellitesFixed, pseudoLocation); + final IGeoData current = new GeoData(locationData.location, gpsEnabled, visible, satellitesFixed); subject.onNext(current); } diff --git a/main/src/cgeo/geocaching/sensors/IGeoData.java b/main/src/cgeo/geocaching/sensors/IGeoData.java index 5b4f046..3b58d79 100644 --- a/main/src/cgeo/geocaching/sensors/IGeoData.java +++ b/main/src/cgeo/geocaching/sensors/IGeoData.java @@ -10,8 +10,6 @@ public interface IGeoData { public Location getLocation(); public LocationProviderType getLocationProvider(); - public boolean isPseudoLocation(); - public Geopoint getCoords(); public float getBearing(); public float getSpeed(); -- cgit v1.1 From d3b01e7764f16de845001627ddf39bf3f1e0de35 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 17:21:31 +0200 Subject: Create a separate GPS Status provider --- .../cgeo/geocaching/sensors/GpsStatusProvider.java | 146 +++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 main/src/cgeo/geocaching/sensors/GpsStatusProvider.java (limited to 'main') diff --git a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java new file mode 100644 index 0000000..56b2ca9 --- /dev/null +++ b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java @@ -0,0 +1,146 @@ +package cgeo.geocaching.sensors; + +import cgeo.geocaching.sensors.GpsStatusProvider.Status; +import cgeo.geocaching.utils.StartableHandlerThread; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; + +import rx.Observable; +import rx.Observable.OnSubscribe; +import rx.Subscriber; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action0; +import rx.functions.Action1; +import rx.observables.ConnectableObservable; +import rx.subjects.BehaviorSubject; +import rx.subscriptions.CompositeSubscription; +import rx.subscriptions.Subscriptions; + +import android.content.Context; +import android.location.GpsSatellite; +import android.location.GpsStatus; +import android.location.LocationManager; + +import java.util.concurrent.atomic.AtomicInteger; + +public class GpsStatusProvider implements OnSubscribe { + + public static class Status { + final public boolean gpsEnabled; + final public int satellitesVisible; + final public int satellitesFixed; + + public Status(final boolean gpsEnabled, final int satellitesVisible, final int satellitesFixed) { + this.gpsEnabled = gpsEnabled; + this.satellitesVisible = satellitesVisible; + this.satellitesFixed = satellitesFixed; + } + } + + private final LocationManager geoManager; + private final BehaviorSubject subject; + private static final StartableHandlerThread handlerThread = + new StartableHandlerThread("GpsStatusProvider thread", android.os.Process.THREAD_PRIORITY_BACKGROUND); + static { + handlerThread.start(); + } + + private Status latest = new Status(false, 0, 0); + + /** + * Build a new gps status provider object. + *

+ * There is no need to instantiate more than one such object in an application, as observers can be added + * at will. + * + * @param context the context used to retrieve the system services + */ + protected GpsStatusProvider(final Context context) { + geoManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + subject = BehaviorSubject.create(latest); + } + + public static Observable create(final Context context) { + final GpsStatusProvider provider = new GpsStatusProvider(context); + return provider.worker.refCount(); + } + + @Override + public void call(final Subscriber subscriber) { + subject.subscribe(subscriber); + } + + final ConnectableObservable worker = new ConnectableObservable(this) { + private final AtomicInteger count = new AtomicInteger(0); + + final private GpsStatus.Listener gpsStatusListener = new GpsStatusListener(); + + @Override + public void connect(Action1 connection) { + final CompositeSubscription subscription = new CompositeSubscription(); + AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() { + @Override + public void call() { + if (count.getAndIncrement() == 0) { + Log.d("GpsStatusProvider: starting the GPS status listener"); + geoManager.addGpsStatusListener(gpsStatusListener); + } + + subscription.add(Subscriptions.create(new Action0() { + @Override + public void call() { + AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() { + @Override + public void call() { + if (count.decrementAndGet() == 0) { + Log.d("GpsStatusProvider: stopping the GPS status listener"); + geoManager.removeGpsStatusListener(gpsStatusListener); + } + } + }); + } + })); + } + }); + connection.call(subscription); + } + }; + + private final class GpsStatusListener implements GpsStatus.Listener { + + @Override + public void onGpsStatusChanged(final int event) { + switch (event) { + case GpsStatus.GPS_EVENT_FIRST_FIX: + case GpsStatus.GPS_EVENT_SATELLITE_STATUS: { + final GpsStatus status = geoManager.getGpsStatus(null); + int visible = 0; + int fixed = 0; + for (final GpsSatellite satellite : status.getSatellites()) { + if (satellite.usedInFix()) { + fixed++; + } + visible++; + } + if (visible == latest.satellitesVisible && fixed == latest.satellitesFixed) { + return; + } + latest = new Status(latest.gpsEnabled, visible, fixed); + break; + } + case GpsStatus.GPS_EVENT_STARTED: + latest = new Status(true, latest.satellitesVisible, latest.satellitesFixed); + break; + case GpsStatus.GPS_EVENT_STOPPED: + latest = new Status(false, 0, 0); + break; + default: + throw new IllegalStateException(); + } + + subject.onNext(latest); + } + } + +} -- cgit v1.1 From bb356a34c816c15902a16b7c92907d1e5c25b824 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 17:41:13 +0200 Subject: Remove GPS status from location information --- main/src/cgeo/geocaching/CgeoApplication.java | 11 +++ main/src/cgeo/geocaching/CompassActivity.java | 23 ++++-- main/src/cgeo/geocaching/MainActivity.java | 38 +++------ .../cgeo/geocaching/activity/AbstractActivity.java | 4 +- main/src/cgeo/geocaching/sensors/GeoData.java | 23 +----- .../cgeo/geocaching/sensors/GeoDataProvider.java | 94 ++++------------------ main/src/cgeo/geocaching/sensors/IGeoData.java | 3 - 7 files changed, 56 insertions(+), 140 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java index 863dcdd..6d07b7f 100644 --- a/main/src/cgeo/geocaching/CgeoApplication.java +++ b/main/src/cgeo/geocaching/CgeoApplication.java @@ -2,6 +2,8 @@ package cgeo.geocaching; import cgeo.geocaching.sensors.DirectionProvider; import cgeo.geocaching.sensors.GeoDataProvider; +import cgeo.geocaching.sensors.GpsStatusProvider; +import cgeo.geocaching.sensors.GpsStatusProvider.Status; import cgeo.geocaching.sensors.IGeoData; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.OOMDumpingUncaughtExceptionHandler; @@ -23,6 +25,7 @@ public class CgeoApplication extends Application { private static CgeoApplication instance; private Observable geoDataObservable; private Observable directionObservable; + private Observable gpsStatusObservable; private volatile IGeoData currentGeo = null; private volatile float currentDirection = 0.0f; @@ -104,6 +107,14 @@ public class CgeoApplication extends Application { return directionObservable; } + public synchronized Observable gpsStatusObservable() { + if (gpsStatusObservable == null) { + final ConnectableObservable onDemand = GpsStatusProvider.create(this).replay(1); + gpsStatusObservable = onDemand.refCount(); + } + return gpsStatusObservable; + } + public IGeoData currentGeo() { return currentGeo != null ? currentGeo : geoDataObservable().toBlocking().first(); } diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java index 025d938..7b5ae35 100644 --- a/main/src/cgeo/geocaching/CompassActivity.java +++ b/main/src/cgeo/geocaching/CompassActivity.java @@ -10,6 +10,7 @@ import cgeo.geocaching.geopoint.Units; import cgeo.geocaching.maps.CGeoMap; import cgeo.geocaching.sensors.DirectionProvider; import cgeo.geocaching.sensors.GeoDirHandler; +import cgeo.geocaching.sensors.GpsStatusProvider.Status; import cgeo.geocaching.sensors.IGeoData; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.speech.SpeechService; @@ -21,6 +22,9 @@ import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.Nullable; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; + import android.content.Context; import android.content.Intent; import android.content.res.Configuration; @@ -118,7 +122,8 @@ public class CompassActivity extends AbstractActionBarActivity { @Override public void onResume() { - super.onResume(geoDirHandler.start(GeoDirHandler.UPDATE_GEODIR)); + super.onResume(geoDirHandler.start(GeoDirHandler.UPDATE_GEODIR), + app.gpsStatusObservable().observeOn(AndroidSchedulers.mainThread()).subscribe(gpsStatusHandler)); } @Override @@ -259,16 +264,22 @@ public class CompassActivity extends AbstractActionBarActivity { headingView.setText(Math.round(cacheHeading) + "°"); } + private final Action1 gpsStatusHandler = new Action1() { + @Override + public void call(final Status gpsStatus) { + if (gpsStatus.satellitesVisible >= 0) { + navSatellites.setText(res.getString(R.string.loc_sat) + ": " + gpsStatus.satellitesFixed + "/" + gpsStatus.satellitesVisible); + } else { + navSatellites.setText(""); + } + } + }; + private final GeoDirHandler geoDirHandler = new GeoDirHandler() { @Override public void updateGeoDir(final IGeoData geo, final float dir) { try { if (geo.getCoords() != null) { - if (geo.getSatellitesVisible() >= 0) { - navSatellites.setText(res.getString(R.string.loc_sat) + ": " + geo.getSatellitesFixed() + "/" + geo.getSatellitesVisible()); - } else { - navSatellites.setText(""); - } navType.setText(res.getString(geo.getLocationProvider().resourceId)); if (geo.getAccuracy() >= 0) { diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java index 2d6e9f0..ad081a0 100644 --- a/main/src/cgeo/geocaching/MainActivity.java +++ b/main/src/cgeo/geocaching/MainActivity.java @@ -16,6 +16,8 @@ import cgeo.geocaching.list.PseudoList; import cgeo.geocaching.list.StoredList; import cgeo.geocaching.maps.CGeoMap; import cgeo.geocaching.sensors.GeoDirHandler; +import cgeo.geocaching.sensors.GpsStatusProvider; +import cgeo.geocaching.sensors.GpsStatusProvider.Status; import cgeo.geocaching.sensors.IGeoData; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.SettingsActivity; @@ -36,8 +38,8 @@ import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; import rx.android.observables.AndroidObservable; +import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; -import rx.subscriptions.Subscriptions; import android.app.AlertDialog; import android.app.AlertDialog.Builder; @@ -145,37 +147,16 @@ public class MainActivity extends AbstractActionBarActivity { return StringUtils.join(addressParts, ", "); } - private class SatellitesHandler extends GeoDirHandler { - - private boolean gpsEnabled = false; - private int satellitesFixed = 0; - private int satellitesVisible = 0; - + private final Action1 satellitesHandler = new Action1() { @Override - public void updateGeoData(final IGeoData data) { - if (data.getGpsEnabled() == gpsEnabled && - data.getSatellitesFixed() == satellitesFixed && - data.getSatellitesVisible() == satellitesVisible) { - return; - } - gpsEnabled = data.getGpsEnabled(); - satellitesFixed = data.getSatellitesFixed(); - satellitesVisible = data.getSatellitesVisible(); - - if (gpsEnabled) { - if (satellitesFixed > 0) { - navSatellites.setText(res.getString(R.string.loc_sat) + ": " + satellitesFixed + '/' + satellitesVisible); - } else if (satellitesVisible >= 0) { - navSatellites.setText(res.getString(R.string.loc_sat) + ": 0/" + satellitesVisible); - } + public void call(final Status gpsStatus) { + if (gpsStatus.gpsEnabled) { + navSatellites.setText(res.getString(R.string.loc_sat) + ": " + gpsStatus.satellitesFixed + '/' + gpsStatus.satellitesVisible); } else { navSatellites.setText(res.getString(R.string.loc_gps_disabled)); } } - - } - - private final SatellitesHandler satellitesHandler = new SatellitesHandler(); + }; private final Handler firstLoginHandler = new Handler() { @@ -229,7 +210,8 @@ public class MainActivity extends AbstractActionBarActivity { @Override public void onResume() { - super.onResume(Subscriptions.from(locationUpdater.start(GeoDirHandler.UPDATE_GEODATA), satellitesHandler.start(GeoDirHandler.UPDATE_GEODATA))); + super.onResume(locationUpdater.start(GeoDirHandler.UPDATE_GEODATA), + app.gpsStatusObservable().observeOn(AndroidSchedulers.mainThread()).subscribe(satellitesHandler)); updateUserInfoHandler.sendEmptyMessage(-1); startBackgroundLogin(); init(); diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index e3df1f7..a28fcfa 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -86,9 +86,9 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs return super.onOptionsItemSelected(item); } - public void onResume(final Subscription resumeSubscription) { + public void onResume(final Subscription... resumeSubscriptions) { super.onResume(); - this.resumeSubscription = resumeSubscription; + this.resumeSubscription = Subscriptions.from(resumeSubscriptions); } @Override diff --git a/main/src/cgeo/geocaching/sensors/GeoData.java b/main/src/cgeo/geocaching/sensors/GeoData.java index c0f57b5..2061b6b 100644 --- a/main/src/cgeo/geocaching/sensors/GeoData.java +++ b/main/src/cgeo/geocaching/sensors/GeoData.java @@ -7,15 +7,9 @@ import android.location.Location; import android.location.LocationManager; class GeoData extends Location implements IGeoData { - private final boolean gpsEnabled; - private final int satellitesVisible; - private final int satellitesFixed; - GeoData(final Location location, final boolean gpsEnabled, final int satellitesVisible, final int satellitesFixed) { + GeoData(final Location location) { super(location); - this.gpsEnabled = gpsEnabled; - this.satellitesVisible = satellitesVisible; - this.satellitesFixed = satellitesFixed; } @Override @@ -42,19 +36,4 @@ class GeoData extends Location implements IGeoData { public Geopoint getCoords() { return new Geopoint(this); } - - @Override - public boolean getGpsEnabled() { - return gpsEnabled; - } - - @Override - public int getSatellitesVisible() { - return satellitesVisible; - } - - @Override - public int getSatellitesFixed() { - return satellitesFixed; - } } diff --git a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java index 50d42db..3154363 100644 --- a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java +++ b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java @@ -16,14 +16,13 @@ import rx.subscriptions.CompositeSubscription; import rx.subscriptions.Subscriptions; import android.content.Context; -import android.location.GpsSatellite; -import android.location.GpsStatus; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; public class GeoDataProvider implements OnSubscribe { @@ -37,10 +36,6 @@ public class GeoDataProvider implements OnSubscribe { handlerThread.start(); } - public boolean gpsEnabled = false; - public int satellitesVisible = 0; - public int satellitesFixed = 0; - private static class LocationData { public Location location; public long timestamp = 0; @@ -83,12 +78,8 @@ public class GeoDataProvider implements OnSubscribe { } final ConnectableObservable worker = new ConnectableObservable(this) { - private int debugSessionCounter = 0; - - private final Object lock = new Object(); - private int count = 0; + private final AtomicInteger count = new AtomicInteger(0); - final private GpsStatus.Listener gpsStatusListener = new GpsStatusListener(); final private Listener networkListener = new Listener(LocationManager.NETWORK_PROVIDER, netLocation); final private Listener gpsListener = new Listener(LocationManager.GPS_PROVIDER, gpsLocation); @@ -98,16 +89,13 @@ public class GeoDataProvider implements OnSubscribe { AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() { @Override public void call() { - synchronized(lock) { - if (count++ == 0) { - Log.d("GeoDataProvider: starting the GPS and network listeners" + " (" + ++debugSessionCounter + ")"); - geoManager.addGpsStatusListener(gpsStatusListener); - for (final Listener listener : new Listener[] { networkListener, gpsListener }) { - try { - geoManager.requestLocationUpdates(listener.locationProvider, 0, 0, listener); - } catch (final Exception e) { - Log.w("There is no location provider " + listener.locationProvider); - } + if (count.getAndIncrement() == 0) { + Log.d("GeoDataProvider: starting the GPS and network listeners"); + for (final Listener listener : new Listener[]{networkListener, gpsListener}) { + try { + geoManager.requestLocationUpdates(listener.locationProvider, 0, 0, listener); + } catch (final Exception e) { + Log.w("There is no location provider " + listener.locationProvider); } } } @@ -118,13 +106,10 @@ public class GeoDataProvider implements OnSubscribe { AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() { @Override public void call() { - synchronized (lock) { - if (--count == 0) { - Log.d("GeoDataProvider: stopping the GPS and network listeners" + " (" + debugSessionCounter + ")"); - geoManager.removeUpdates(networkListener); - geoManager.removeUpdates(gpsListener); - geoManager.removeGpsStatusListener(gpsStatusListener); - } + if (count.decrementAndGet() == 0) { + Log.d("GeoDataProvider: stopping the GPS and network listeners"); + geoManager.removeUpdates(networkListener); + geoManager.removeUpdates(gpsListener); } } }, 2500, TimeUnit.MILLISECONDS); @@ -164,7 +149,7 @@ public class GeoDataProvider implements OnSubscribe { } // Start with an historical GeoData just in case someone queries it before we get // a chance to get any information. - return new GeoData(initialLocation, false, 0, 0); + return new GeoData(initialLocation); } private static void copyCoords(final Location target, final Location source) { @@ -203,54 +188,6 @@ public class GeoDataProvider implements OnSubscribe { } } - private final class GpsStatusListener implements GpsStatus.Listener { - - @Override - public void onGpsStatusChanged(final int event) { - boolean changed = false; - switch (event) { - case GpsStatus.GPS_EVENT_FIRST_FIX: - case GpsStatus.GPS_EVENT_SATELLITE_STATUS: { - final GpsStatus status = geoManager.getGpsStatus(null); - int visible = 0; - int fixed = 0; - for (final GpsSatellite satellite : status.getSatellites()) { - if (satellite.usedInFix()) { - fixed++; - } - visible++; - } - if (visible != satellitesVisible || fixed != satellitesFixed) { - satellitesVisible = visible; - satellitesFixed = fixed; - changed = true; - } - break; - } - case GpsStatus.GPS_EVENT_STARTED: - if (!gpsEnabled) { - gpsEnabled = true; - changed = true; - } - break; - case GpsStatus.GPS_EVENT_STOPPED: - if (gpsEnabled) { - gpsEnabled = false; - satellitesFixed = 0; - satellitesVisible = 0; - changed = true; - } - break; - default: - throw new IllegalStateException(); - } - - if (changed) { - selectBest(); - } - } - } - private LocationData best() { if (gpsLocation.isRecent() || !netLocation.isValid()) { return gpsLocation.isValid() ? gpsLocation : null; @@ -271,8 +208,7 @@ public class GeoDataProvider implements OnSubscribe { } // We do not necessarily get signalled when satellites go to 0/0. - final int visible = gpsLocation.isRecent() ? satellitesVisible : 0; - final IGeoData current = new GeoData(locationData.location, gpsEnabled, visible, satellitesFixed); + final IGeoData current = new GeoData(locationData.location); subject.onNext(current); } diff --git a/main/src/cgeo/geocaching/sensors/IGeoData.java b/main/src/cgeo/geocaching/sensors/IGeoData.java index 3b58d79..b78b805 100644 --- a/main/src/cgeo/geocaching/sensors/IGeoData.java +++ b/main/src/cgeo/geocaching/sensors/IGeoData.java @@ -14,7 +14,4 @@ public interface IGeoData { public float getBearing(); public float getSpeed(); public float getAccuracy(); - public boolean getGpsEnabled(); - public int getSatellitesVisible(); - public int getSatellitesFixed(); } -- cgit v1.1 From 0f0db2ab42a9bf292f58e992f4eebd7ae6e3016c Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 17:46:40 +0200 Subject: Use the same handler thread for GpsStatus and GeoData --- main/src/cgeo/geocaching/sensors/GeoDataProvider.java | 12 +++--------- main/src/cgeo/geocaching/sensors/GpsStatusProvider.java | 11 ++--------- main/src/cgeo/geocaching/utils/RxUtils.java | 11 +++++++++++ 3 files changed, 16 insertions(+), 18 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java index 3154363..347c5a1 100644 --- a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java +++ b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java @@ -1,13 +1,12 @@ package cgeo.geocaching.sensors; import cgeo.geocaching.utils.Log; -import cgeo.geocaching.utils.StartableHandlerThread; +import cgeo.geocaching.utils.RxUtils; import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action0; import rx.functions.Action1; import rx.observables.ConnectableObservable; @@ -30,11 +29,6 @@ public class GeoDataProvider implements OnSubscribe { private final LocationData gpsLocation = new LocationData(); private final LocationData netLocation = new LocationData(); private final BehaviorSubject subject; - private static final StartableHandlerThread handlerThread = - new StartableHandlerThread("GeoDataProvider thread", android.os.Process.THREAD_PRIORITY_BACKGROUND); - static { - handlerThread.start(); - } private static class LocationData { public Location location; @@ -86,7 +80,7 @@ public class GeoDataProvider implements OnSubscribe { @Override public void connect(Action1 connection) { final CompositeSubscription subscription = new CompositeSubscription(); - AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() { + RxUtils.looperCallbacksWorker.schedule(new Action0() { @Override public void call() { if (count.getAndIncrement() == 0) { @@ -103,7 +97,7 @@ public class GeoDataProvider implements OnSubscribe { subscription.add(Subscriptions.create(new Action0() { @Override public void call() { - AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() { + RxUtils.looperCallbacksWorker.schedule(new Action0() { @Override public void call() { if (count.decrementAndGet() == 0) { diff --git a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java index 56b2ca9..2c1e724 100644 --- a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java +++ b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java @@ -1,7 +1,6 @@ package cgeo.geocaching.sensors; import cgeo.geocaching.sensors.GpsStatusProvider.Status; -import cgeo.geocaching.utils.StartableHandlerThread; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.RxUtils; @@ -9,7 +8,6 @@ import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action0; import rx.functions.Action1; import rx.observables.ConnectableObservable; @@ -40,11 +38,6 @@ public class GpsStatusProvider implements OnSubscribe { private final LocationManager geoManager; private final BehaviorSubject subject; - private static final StartableHandlerThread handlerThread = - new StartableHandlerThread("GpsStatusProvider thread", android.os.Process.THREAD_PRIORITY_BACKGROUND); - static { - handlerThread.start(); - } private Status latest = new Status(false, 0, 0); @@ -79,7 +72,7 @@ public class GpsStatusProvider implements OnSubscribe { @Override public void connect(Action1 connection) { final CompositeSubscription subscription = new CompositeSubscription(); - AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() { + RxUtils.looperCallbacksWorker.schedule(new Action0() { @Override public void call() { if (count.getAndIncrement() == 0) { @@ -90,7 +83,7 @@ public class GpsStatusProvider implements OnSubscribe { subscription.add(Subscriptions.create(new Action0() { @Override public void call() { - AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() { + RxUtils.looperCallbacksWorker.schedule(new Action0() { @Override public void call() { if (count.decrementAndGet() == 0) { diff --git a/main/src/cgeo/geocaching/utils/RxUtils.java b/main/src/cgeo/geocaching/utils/RxUtils.java index 241ba78..e3208fb 100644 --- a/main/src/cgeo/geocaching/utils/RxUtils.java +++ b/main/src/cgeo/geocaching/utils/RxUtils.java @@ -2,6 +2,8 @@ package cgeo.geocaching.utils; import rx.Observable; import rx.Scheduler; +import rx.Scheduler.Worker; +import rx.android.schedulers.AndroidSchedulers; import rx.observables.BlockingObservable; import rx.schedulers.Schedulers; @@ -14,6 +16,15 @@ public class RxUtils { // Utility class, not to be instanciated private RxUtils() {} + private static final StartableHandlerThread looperCallbacksThread = + new StartableHandlerThread("GpsStatusProvider thread", android.os.Process.THREAD_PRIORITY_BACKGROUND); + + static { + looperCallbacksThread.start(); + } + + public static final Worker looperCallbacksWorker = AndroidSchedulers.handlerThread(looperCallbacksThread.getHandler()).createWorker(); + public final static Scheduler computationScheduler = Schedulers.computation(); public static final Scheduler networkScheduler = Schedulers.from(new ThreadPoolExecutor(10, 10, 5, TimeUnit.SECONDS, new LinkedBlockingQueue())); -- cgit v1.1 From 0d019b16706b6a7cf3808478f2156f63062972bd Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 19:04:36 +0200 Subject: Factor out looper thread activity scheduling --- .../cgeo/geocaching/sensors/GeoDataProvider.java | 51 +++++++----------- .../cgeo/geocaching/sensors/GpsStatusProvider.java | 38 +++++--------- main/src/cgeo/geocaching/utils/RxUtils.java | 60 +++++++++++++++++++++- 3 files changed, 88 insertions(+), 61 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java index 347c5a1..01b966c 100644 --- a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java +++ b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java @@ -11,8 +11,6 @@ import rx.functions.Action0; import rx.functions.Action1; import rx.observables.ConnectableObservable; import rx.subjects.BehaviorSubject; -import rx.subscriptions.CompositeSubscription; -import rx.subscriptions.Subscriptions; import android.content.Context; import android.location.Location; @@ -73,45 +71,32 @@ public class GeoDataProvider implements OnSubscribe { final ConnectableObservable worker = new ConnectableObservable(this) { private final AtomicInteger count = new AtomicInteger(0); - - final private Listener networkListener = new Listener(LocationManager.NETWORK_PROVIDER, netLocation); - final private Listener gpsListener = new Listener(LocationManager.GPS_PROVIDER, gpsLocation); + private final Listener networkListener = new Listener(LocationManager.NETWORK_PROVIDER, netLocation); + private final Listener gpsListener = new Listener(LocationManager.GPS_PROVIDER, gpsLocation); @Override public void connect(Action1 connection) { - final CompositeSubscription subscription = new CompositeSubscription(); - RxUtils.looperCallbacksWorker.schedule(new Action0() { - @Override - public void call() { - if (count.getAndIncrement() == 0) { - Log.d("GeoDataProvider: starting the GPS and network listeners"); - for (final Listener listener : new Listener[]{networkListener, gpsListener}) { - try { - geoManager.requestLocationUpdates(listener.locationProvider, 0, 0, listener); - } catch (final Exception e) { - Log.w("There is no location provider " + listener.locationProvider); + connection.call(RxUtils.looperCallbacksSchedule(count, + new Action0() { + @Override + public void call() { + Log.d("GeoDataProvider: starting the GPS and network listeners"); + for (final Listener listener : new Listener[]{networkListener, gpsListener}) { + try { + geoManager.requestLocationUpdates(listener.locationProvider, 0, 0, listener); + } catch (final Exception e) { + Log.w("There is no location provider " + listener.locationProvider); + } } } - } - - subscription.add(Subscriptions.create(new Action0() { + }, new Action0() { @Override public void call() { - RxUtils.looperCallbacksWorker.schedule(new Action0() { - @Override - public void call() { - if (count.decrementAndGet() == 0) { - Log.d("GeoDataProvider: stopping the GPS and network listeners"); - geoManager.removeUpdates(networkListener); - geoManager.removeUpdates(gpsListener); - } - } - }, 2500, TimeUnit.MILLISECONDS); + Log.d("GeoDataProvider: stopping the GPS and network listeners"); + geoManager.removeUpdates(networkListener); + geoManager.removeUpdates(gpsListener); } - })); - } - }); - connection.call(subscription); + }, 2500, TimeUnit.MILLISECONDS)); } }; diff --git a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java index 2c1e724..8094a39 100644 --- a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java +++ b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java @@ -12,8 +12,6 @@ import rx.functions.Action0; import rx.functions.Action1; import rx.observables.ConnectableObservable; import rx.subjects.BehaviorSubject; -import rx.subscriptions.CompositeSubscription; -import rx.subscriptions.Subscriptions; import android.content.Context; import android.location.GpsSatellite; @@ -66,37 +64,25 @@ public class GpsStatusProvider implements OnSubscribe { final ConnectableObservable worker = new ConnectableObservable(this) { private final AtomicInteger count = new AtomicInteger(0); - - final private GpsStatus.Listener gpsStatusListener = new GpsStatusListener(); + private final GpsStatus.Listener gpsStatusListener = new GpsStatusListener(); @Override public void connect(Action1 connection) { - final CompositeSubscription subscription = new CompositeSubscription(); - RxUtils.looperCallbacksWorker.schedule(new Action0() { - @Override - public void call() { - if (count.getAndIncrement() == 0) { - Log.d("GpsStatusProvider: starting the GPS status listener"); - geoManager.addGpsStatusListener(gpsStatusListener); - } - - subscription.add(Subscriptions.create(new Action0() { + connection.call(RxUtils.looperCallbacksSchedule(count, + new Action0() { @Override public void call() { - RxUtils.looperCallbacksWorker.schedule(new Action0() { - @Override - public void call() { - if (count.decrementAndGet() == 0) { - Log.d("GpsStatusProvider: stopping the GPS status listener"); - geoManager.removeGpsStatusListener(gpsStatusListener); - } - } - }); + Log.d("GpsStatusProvider: starting the GPS status listener"); + geoManager.addGpsStatusListener(gpsStatusListener); + } + }, + new Action0() { + @Override + public void call() { + Log.d("GpsStatusProvider: stopping the GPS status listener"); + geoManager.removeGpsStatusListener(gpsStatusListener); } })); - } - }); - connection.call(subscription); } }; diff --git a/main/src/cgeo/geocaching/utils/RxUtils.java b/main/src/cgeo/geocaching/utils/RxUtils.java index e3208fb..c1a8f2c 100644 --- a/main/src/cgeo/geocaching/utils/RxUtils.java +++ b/main/src/cgeo/geocaching/utils/RxUtils.java @@ -3,13 +3,18 @@ package cgeo.geocaching.utils; import rx.Observable; import rx.Scheduler; import rx.Scheduler.Worker; +import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action0; import rx.observables.BlockingObservable; import rx.schedulers.Schedulers; +import rx.subscriptions.CompositeSubscription; +import rx.subscriptions.Subscriptions; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; public class RxUtils { @@ -17,13 +22,13 @@ public class RxUtils { private RxUtils() {} private static final StartableHandlerThread looperCallbacksThread = - new StartableHandlerThread("GpsStatusProvider thread", android.os.Process.THREAD_PRIORITY_BACKGROUND); + new StartableHandlerThread("Looper callbacks thread", android.os.Process.THREAD_PRIORITY_BACKGROUND); static { looperCallbacksThread.start(); } - public static final Worker looperCallbacksWorker = AndroidSchedulers.handlerThread(looperCallbacksThread.getHandler()).createWorker(); + private static final Worker looperCallbacksWorker = AndroidSchedulers.handlerThread(looperCallbacksThread.getHandler()).createWorker(); public final static Scheduler computationScheduler = Schedulers.computation(); @@ -36,4 +41,55 @@ public class RxUtils { public static void waitForCompletion(final Observable... observables) { waitForCompletion(Observable.merge(observables).toBlocking()); } + + /** + * Start a job (typically one that register handlers) on a looper thread if the counter goes above 0, + * and stop it if it comes back to 0 after the job is unsubscribed from. + * + * @param counter the counter to use + * @param onStart the job to launch if the counter goes above 0 + * @param onStop the job to launch when unsubscribing if the counter goes back at 0 + * @param stopDelay the delay before which the unsubscription should take place + * @param stopDelayUnit the unit of the delay before which the unsubscription should take place + * @return the subscription allowing to unsubscribe + */ + public static Subscription looperCallbacksSchedule(final AtomicInteger counter, final Action0 onStart, final Action0 onStop, + final long stopDelay, final TimeUnit stopDelayUnit) { + final CompositeSubscription subscription = new CompositeSubscription(); + looperCallbacksWorker.schedule(new Action0() { + @Override + public void call() { + if (counter.getAndIncrement() == 0) { + onStart.call(); + } + subscription.add(Subscriptions.create(new Action0() { + @Override + public void call() { + looperCallbacksWorker.schedule(new Action0() { + @Override + public void call() { + if (counter.decrementAndGet() == 0) { + onStop.call(); + } + } + }, stopDelay, stopDelayUnit); + } + })); + } + }); + return subscription; + } + + /** + * Start a job (typically one that register handlers) on a looper thread if the counter goes above 0, + * and stop it if it comes back to 0 after the job is unsubscribed from. + * + * @param counter the counter to use + * @param onStart the job to launch if the counter goes above 0 + * @param onStop the job to launch when unsubscribing if the counter goes back at 0 + * @return the subscription allowing to unsubscribe + */ + public static Subscription looperCallbacksSchedule(final AtomicInteger counter, final Action0 onStart, final Action0 onStop) { + return looperCallbacksSchedule(counter, onStart, onStop, 0, TimeUnit.SECONDS); + } } -- cgit v1.1 From 4a50e96b504053675197d329bd4c9bdf40edfae6 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 19:17:05 +0200 Subject: If the GPS is started already, we won't receive GPS_EVENT_STARTED --- main/src/cgeo/geocaching/sensors/GpsStatusProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java index 8094a39..684841f 100644 --- a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java +++ b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java @@ -105,11 +105,11 @@ public class GpsStatusProvider implements OnSubscribe { if (visible == latest.satellitesVisible && fixed == latest.satellitesFixed) { return; } - latest = new Status(latest.gpsEnabled, visible, fixed); + latest = new Status(true, visible, fixed); break; } case GpsStatus.GPS_EVENT_STARTED: - latest = new Status(true, latest.satellitesVisible, latest.satellitesFixed); + latest = new Status(true, 0, 0); break; case GpsStatus.GPS_EVENT_STOPPED: latest = new Status(false, 0, 0); -- cgit v1.1 From ba922a39e0aadcb9afc5bbeedbfcda40276adcad Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 19:39:08 +0200 Subject: Further factoring of ConnectableObservable behaviour --- .../cgeo/geocaching/sensors/GeoDataProvider.java | 47 ++++----- .../cgeo/geocaching/sensors/GpsStatusProvider.java | 35 +++---- main/src/cgeo/geocaching/utils/RxUtils.java | 106 ++++++++++----------- 3 files changed, 82 insertions(+), 106 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java index 01b966c..7645d7f 100644 --- a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java +++ b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java @@ -1,14 +1,11 @@ package cgeo.geocaching.sensors; import cgeo.geocaching.utils.Log; -import cgeo.geocaching.utils.RxUtils; +import cgeo.geocaching.utils.RxUtils.ConnectableLooperCallbacks; import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; -import rx.Subscription; -import rx.functions.Action0; -import rx.functions.Action1; import rx.observables.ConnectableObservable; import rx.subjects.BehaviorSubject; @@ -19,7 +16,6 @@ import android.location.LocationManager; import android.os.Bundle; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; public class GeoDataProvider implements OnSubscribe { @@ -69,34 +65,27 @@ public class GeoDataProvider implements OnSubscribe { subject.subscribe(subscriber); } - final ConnectableObservable worker = new ConnectableObservable(this) { - private final AtomicInteger count = new AtomicInteger(0); + final ConnectableObservable worker = new ConnectableLooperCallbacks(this, 2500, TimeUnit.MILLISECONDS) { private final Listener networkListener = new Listener(LocationManager.NETWORK_PROVIDER, netLocation); private final Listener gpsListener = new Listener(LocationManager.GPS_PROVIDER, gpsLocation); @Override - public void connect(Action1 connection) { - connection.call(RxUtils.looperCallbacksSchedule(count, - new Action0() { - @Override - public void call() { - Log.d("GeoDataProvider: starting the GPS and network listeners"); - for (final Listener listener : new Listener[]{networkListener, gpsListener}) { - try { - geoManager.requestLocationUpdates(listener.locationProvider, 0, 0, listener); - } catch (final Exception e) { - Log.w("There is no location provider " + listener.locationProvider); - } - } - } - }, new Action0() { - @Override - public void call() { - Log.d("GeoDataProvider: stopping the GPS and network listeners"); - geoManager.removeUpdates(networkListener); - geoManager.removeUpdates(gpsListener); - } - }, 2500, TimeUnit.MILLISECONDS)); + protected void onStart() { + Log.d("GeoDataProvider: starting the GPS and network listeners"); + for (final Listener listener : new Listener[]{networkListener, gpsListener}) { + try { + geoManager.requestLocationUpdates(listener.locationProvider, 0, 0, listener); + } catch (final Exception e) { + Log.w("There is no location provider " + listener.locationProvider); + } + } + } + + @Override + protected void onStop() { + Log.d("GeoDataProvider: stopping the GPS and network listeners"); + geoManager.removeUpdates(networkListener); + geoManager.removeUpdates(gpsListener); } }; diff --git a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java index 684841f..61243c3 100644 --- a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java +++ b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java @@ -2,14 +2,11 @@ package cgeo.geocaching.sensors; import cgeo.geocaching.sensors.GpsStatusProvider.Status; import cgeo.geocaching.utils.Log; -import cgeo.geocaching.utils.RxUtils; +import cgeo.geocaching.utils.RxUtils.ConnectableLooperCallbacks; import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; -import rx.Subscription; -import rx.functions.Action0; -import rx.functions.Action1; import rx.observables.ConnectableObservable; import rx.subjects.BehaviorSubject; @@ -18,8 +15,6 @@ import android.location.GpsSatellite; import android.location.GpsStatus; import android.location.LocationManager; -import java.util.concurrent.atomic.AtomicInteger; - public class GpsStatusProvider implements OnSubscribe { public static class Status { @@ -62,27 +57,19 @@ public class GpsStatusProvider implements OnSubscribe { subject.subscribe(subscriber); } - final ConnectableObservable worker = new ConnectableObservable(this) { - private final AtomicInteger count = new AtomicInteger(0); + final ConnectableObservable worker = new ConnectableLooperCallbacks(this) { private final GpsStatus.Listener gpsStatusListener = new GpsStatusListener(); @Override - public void connect(Action1 connection) { - connection.call(RxUtils.looperCallbacksSchedule(count, - new Action0() { - @Override - public void call() { - Log.d("GpsStatusProvider: starting the GPS status listener"); - geoManager.addGpsStatusListener(gpsStatusListener); - } - }, - new Action0() { - @Override - public void call() { - Log.d("GpsStatusProvider: stopping the GPS status listener"); - geoManager.removeGpsStatusListener(gpsStatusListener); - } - })); + protected void onStart() { + Log.d("GpsStatusProvider: starting the GPS status listener"); + geoManager.addGpsStatusListener(gpsStatusListener); + } + + @Override + protected void onStop() { + Log.d("GpsStatusProvider: stopping the GPS status listener"); + geoManager.removeGpsStatusListener(gpsStatusListener); } }; diff --git a/main/src/cgeo/geocaching/utils/RxUtils.java b/main/src/cgeo/geocaching/utils/RxUtils.java index c1a8f2c..f58348d 100644 --- a/main/src/cgeo/geocaching/utils/RxUtils.java +++ b/main/src/cgeo/geocaching/utils/RxUtils.java @@ -6,7 +6,9 @@ import rx.Scheduler.Worker; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action0; +import rx.functions.Action1; import rx.observables.BlockingObservable; +import rx.observables.ConnectableObservable; import rx.schedulers.Schedulers; import rx.subscriptions.CompositeSubscription; import rx.subscriptions.Subscriptions; @@ -21,15 +23,6 @@ public class RxUtils { // Utility class, not to be instanciated private RxUtils() {} - private static final StartableHandlerThread looperCallbacksThread = - new StartableHandlerThread("Looper callbacks thread", android.os.Process.THREAD_PRIORITY_BACKGROUND); - - static { - looperCallbacksThread.start(); - } - - private static final Worker looperCallbacksWorker = AndroidSchedulers.handlerThread(looperCallbacksThread.getHandler()).createWorker(); - public final static Scheduler computationScheduler = Schedulers.computation(); public static final Scheduler networkScheduler = Schedulers.from(new ThreadPoolExecutor(10, 10, 5, TimeUnit.SECONDS, new LinkedBlockingQueue())); @@ -43,53 +36,60 @@ public class RxUtils { } /** - * Start a job (typically one that register handlers) on a looper thread if the counter goes above 0, - * and stop it if it comes back to 0 after the job is unsubscribed from. + * ConnectableObservable whose subscription and unsubscription take place on a looper thread. * - * @param counter the counter to use - * @param onStart the job to launch if the counter goes above 0 - * @param onStop the job to launch when unsubscribing if the counter goes back at 0 - * @param stopDelay the delay before which the unsubscription should take place - * @param stopDelayUnit the unit of the delay before which the unsubscription should take place - * @return the subscription allowing to unsubscribe + * @param the type of the observable */ - public static Subscription looperCallbacksSchedule(final AtomicInteger counter, final Action0 onStart, final Action0 onStop, - final long stopDelay, final TimeUnit stopDelayUnit) { - final CompositeSubscription subscription = new CompositeSubscription(); - looperCallbacksWorker.schedule(new Action0() { - @Override - public void call() { - if (counter.getAndIncrement() == 0) { - onStart.call(); - } - subscription.add(Subscriptions.create(new Action0() { - @Override - public void call() { - looperCallbacksWorker.schedule(new Action0() { - @Override - public void call() { - if (counter.decrementAndGet() == 0) { - onStop.call(); - } - } - }, stopDelay, stopDelayUnit); + public static abstract class ConnectableLooperCallbacks extends ConnectableObservable { + private static final StartableHandlerThread looperCallbacksThread = + new StartableHandlerThread("Looper callbacks thread", android.os.Process.THREAD_PRIORITY_BACKGROUND); + static { + looperCallbacksThread.start(); + } + private static final Worker looperCallbacksWorker = AndroidSchedulers.handlerThread(looperCallbacksThread.getHandler()).createWorker(); + + final AtomicInteger counter = new AtomicInteger(0); + final long stopDelay; + final TimeUnit stopDelayUnit; + + public ConnectableLooperCallbacks(final OnSubscribe onSubscribe, final long stopDelay, final TimeUnit stopDelayUnit) { + super(onSubscribe); + this.stopDelay = stopDelay; + this.stopDelayUnit = stopDelayUnit; + } + + public ConnectableLooperCallbacks(final OnSubscribe onSubscribe) { + this(onSubscribe, 0, TimeUnit.SECONDS); + } + + @Override + final public void connect(final Action1 action1) { + final CompositeSubscription subscription = new CompositeSubscription(); + looperCallbacksWorker.schedule(new Action0() { + @Override + public void call() { + if (counter.getAndIncrement() == 0) { + onStart(); } - })); - } - }); - return subscription; - } + subscription.add(Subscriptions.create(new Action0() { + @Override + public void call() { + looperCallbacksWorker.schedule(new Action0() { + @Override + public void call() { + if (counter.decrementAndGet() == 0) { + onStop(); + } + } + }, stopDelay, stopDelayUnit); + } + })); + } + }); + action1.call(subscription); + } - /** - * Start a job (typically one that register handlers) on a looper thread if the counter goes above 0, - * and stop it if it comes back to 0 after the job is unsubscribed from. - * - * @param counter the counter to use - * @param onStart the job to launch if the counter goes above 0 - * @param onStop the job to launch when unsubscribing if the counter goes back at 0 - * @return the subscription allowing to unsubscribe - */ - public static Subscription looperCallbacksSchedule(final AtomicInteger counter, final Action0 onStart, final Action0 onStop) { - return looperCallbacksSchedule(counter, onStart, onStop, 0, TimeUnit.SECONDS); + abstract protected void onStart(); + abstract protected void onStop(); } } -- cgit v1.1 From c7c3375597b7895645610925b362c759048c53d5 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 3 Aug 2014 20:59:40 +0200 Subject: prevent accidental use of undefined OKAPI keys --- main/src/cgeo/geocaching/connector/oc/OCApiConnector.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java index 284234e..9e9ec7f 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java @@ -31,7 +31,7 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode { private final ApiSupport apiSupport; private final String licenseString; - public OCApiConnector(String name, String host, String prefix, String cK, String licenseString, ApiSupport apiSupport) { + public OCApiConnector(final String name, final String host, final String prefix, final String cK, final String licenseString, final ApiSupport apiSupport) { super(name, host, prefix); this.cK = cK; this.apiSupport = apiSupport; @@ -39,7 +39,12 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode { } public void addAuthentication(final Parameters params) { - params.put(CryptUtils.rot13("pbafhzre_xrl"), CryptUtils.rot13(cK)); + final String rotCK = CryptUtils.rot13(cK); + // check that developers are not using the Ant defined properties without any values + if (StringUtils.startsWith(rotCK, "${")) { + throw new IllegalStateException("invalid OKAPI OAuth token " + rotCK); + } + params.put(CryptUtils.rot13("pbafhzre_xrl"), rotCK); } @Override @@ -93,13 +98,13 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode { /** * Checks if a search based on a user name targets the current user - * + * * @param username * Name of the user the query is searching after * @return True - search target and current is same, False - current user not known or not the same as username */ @SuppressWarnings("static-method") - public boolean isSearchForMyCaches(String username) { + public boolean isSearchForMyCaches(final String username) { return false; } } -- cgit v1.1 From ae2564fcd90417a3e161358d42998a814d22900f Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 3 Aug 2014 21:01:09 +0200 Subject: use dedicated class for OAuth tokens --- .../cgeo/geocaching/connector/oc/OkapiClient.java | 25 +++++++++--- main/src/cgeo/geocaching/network/OAuth.java | 10 ++--- .../network/OAuthAuthorizationActivity.java | 46 +++++++++++----------- main/src/cgeo/geocaching/network/OAuthTokens.java | 38 ++++++++++++++++++ main/src/cgeo/geocaching/twitter/Twitter.java | 16 ++++---- 5 files changed, 94 insertions(+), 41 deletions(-) create mode 100644 main/src/cgeo/geocaching/network/OAuthTokens.java (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java index 3df62aa..f664d93 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java @@ -27,6 +27,7 @@ import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.OAuth; +import cgeo.geocaching.network.OAuthTokens; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; @@ -35,7 +36,6 @@ import cgeo.geocaching.utils.SynchronizedDateFormat; import ch.boye.httpclientandroidlib.HttpResponse; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.json.JSONArray; @@ -734,19 +734,22 @@ final class OkapiClient { @NonNull private static JSONResult request(final OCApiConnector connector, final OkapiService service, final Parameters params) { if (connector == null) { - return new JSONResult(null); + return new JSONResult("unknown OKAPI connector"); } final String host = connector.getHost(); if (StringUtils.isBlank(host)) { - return new JSONResult(null); + return new JSONResult("unknown OKAPI connector host"); } params.add("langpref", getPreferredLanguage()); if (connector.getSupportedAuthLevel() == OAuthLevel.Level3) { - final ImmutablePair tokens = Settings.getTokenPair(connector.getTokenPublicPrefKeyId(), connector.getTokenSecretPrefKeyId()); - OAuth.signOAuth(host, service.methodName, "GET", false, params, tokens.left, tokens.right, connector.getCK(), connector.getCS()); + final OAuthTokens tokens = new OAuthTokens(connector); + if (!tokens.isValid()) { + return new JSONResult("invalid oauth tokens"); + } + OAuth.signOAuth(host, service.methodName, "GET", false, params, tokens, connector.getCK(), connector.getCS()); } else { connector.addAuthentication(params); } @@ -902,5 +905,17 @@ final class OkapiClient { this.data = data; this.isSuccess = isSuccess && data != null; } + + public JSONResult(final @NonNull String errorMessage) { + isSuccess = false; + data = new JSONObject(); + final JSONObject error = new JSONObject(); + try { + error.put("developer_message", errorMessage); + data.put("error", error); + } catch (final JSONException e) { + Log.e("error creating JSON result error message", e); + } + } } } diff --git a/main/src/cgeo/geocaching/network/OAuth.java b/main/src/cgeo/geocaching/network/OAuth.java index cfc62fc..c23ffbf 100644 --- a/main/src/cgeo/geocaching/network/OAuth.java +++ b/main/src/cgeo/geocaching/network/OAuth.java @@ -6,7 +6,6 @@ import ch.boye.httpclientandroidlib.NameValuePair; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; import java.util.ArrayList; import java.util.Date; @@ -18,8 +17,7 @@ public class OAuth { final String method, final boolean https, final Parameters params, - @Nullable final String token, - @Nullable final String tokenSecret, + final OAuthTokens tokens, final String consumerKey, final String consumerSecret) { params.put( @@ -27,7 +25,7 @@ public class OAuth { "oauth_nonce", CryptUtils.md5(Long.toString(System.currentTimeMillis())), "oauth_signature_method", "HMAC-SHA1", "oauth_timestamp", Long.toString(new Date().getTime() / 1000), - "oauth_token", StringUtils.defaultString(token), + "oauth_token", StringUtils.defaultString(tokens.getTokenPublic()), "oauth_version", "1.0"); params.sort(); @@ -36,7 +34,7 @@ public class OAuth { paramsEncoded.add(nameValue.getName() + "=" + OAuth.percentEncode(nameValue.getValue())); } - final String keysPacked = consumerSecret + "&" + StringUtils.defaultString(tokenSecret); // both even if empty some of them! + final String keysPacked = consumerSecret + "&" + StringUtils.defaultString(tokens.getTokenSecret()); // both even if empty some of them! final @NonNull String joinedParams = StringUtils.join(paramsEncoded.toArray(), '&'); final String requestPacked = method + "&" + OAuth.percentEncode((https ? "https" : "http") + "://" + host + path) + "&" + OAuth.percentEncode(joinedParams); params.put("oauth_signature", CryptUtils.base64Encode(CryptUtils.hashHmac(requestPacked, keysPacked))); @@ -48,7 +46,7 @@ public class OAuth { * @param url * @return */ - static String percentEncode(@NonNull String url) { + static String percentEncode(@NonNull final String url) { return StringUtils.replace(Network.rfc3986URLEncode(url), "*", "%2A"); } } diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java index eb56f0b..6ebd070 100644 --- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java @@ -59,10 +59,10 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { private ProgressDialog requestTokenDialog = null; private ProgressDialog changeTokensDialog = null; - private Handler requestTokenHandler = new Handler() { + private final Handler requestTokenHandler = new Handler() { @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { if (requestTokenDialog != null && requestTokenDialog.isShowing()) { requestTokenDialog.dismiss(); } @@ -85,10 +85,10 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { }; - private Handler changeTokensHandler = new Handler() { + private final Handler changeTokensHandler = new Handler() { @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { if (changeTokensDialog != null && changeTokensDialog.isShowing()) { changeTokensDialog.dismiss(); } @@ -105,10 +105,10 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { }; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.authorization_activity); - Bundle extras = getIntent().getExtras(); + final Bundle extras = getIntent().getExtras(); if (extras != null) { host = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_HOST, host); pathRequest = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_PATH_REQUEST, pathRequest); @@ -125,7 +125,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { auth_1.setText(getAuthExplainShort()); auth_2.setText(getAuthExplainLong()); - ImmutablePair tempToken = getTempTokens(); + final ImmutablePair tempToken = getTempTokens(); OAtoken = tempToken.left; OAtokenSecret = tempToken.right; @@ -167,7 +167,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { final Parameters params = new Parameters(); params.put("oauth_callback", callback); final String method = "GET"; - OAuth.signOAuth(host, pathRequest, method, https, params, null, null, consumerKey, consumerSecret); + OAuth.signOAuth(host, pathRequest, method, https, params, new OAuthTokens(null, null), consumerKey, consumerSecret); final HttpResponse response = Network.getRequest(getUrlPrefix() + host + pathRequest, params); if (Network.isSuccess(response)) { @@ -193,9 +193,9 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { final String encodedParams = EntityUtils.toString(new UrlEncodedFormEntity(paramsBrowser)); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getUrlPrefix() + host + pathAuthorize + "?" + encodedParams))); status = STATUS_SUCCESS; - } catch (ParseException e) { + } catch (final ParseException e) { Log.e("OAuthAuthorizationActivity.requestToken", e); - } catch (IOException e) { + } catch (final IOException e) { Log.e("OAuthAuthorizationActivity.requestToken", e); } } @@ -221,7 +221,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { final Parameters params = new Parameters("oauth_verifier", verifier); final String method = "POST"; - OAuth.signOAuth(host, pathAccess, method, https, params, OAtoken, OAtokenSecret, consumerKey, consumerSecret); + OAuth.signOAuth(host, pathAccess, method, https, params, new OAuthTokens(OAtoken, OAtokenSecret), consumerKey, consumerSecret); final String line = StringUtils.defaultString(Network.getResponseData(Network.postRequest(getUrlPrefix() + host + pathAccess, params))); OAtoken = ""; @@ -244,7 +244,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { setTokens(OAtoken, OAtokenSecret, true); status = AUTHENTICATED; } - } catch (Exception e) { + } catch (final Exception e) { Log.e("OAuthAuthorizationActivity.changeToken", e); } @@ -258,7 +258,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { private class StartListener implements View.OnClickListener { @Override - public void onClick(View arg0) { + public void onClick(final View arg0) { if (requestTokenDialog == null) { requestTokenDialog = new ProgressDialog(OAuthAuthorizationActivity.this); requestTokenDialog.setCancelable(false); @@ -333,7 +333,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { * @return String with a more detailed error message (user-facing, localized), can be empty */ @SuppressWarnings("static-method") - protected String getExtendedErrorMsg(HttpResponse response) { + protected String getExtendedErrorMsg(final HttpResponse response) { return StringUtils.EMPTY; } @@ -363,14 +363,14 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { @NonNull public final String consumerSecret; @NonNull public final String callback; - public OAuthParameters(@NonNull String host, - @NonNull String pathRequest, - @NonNull String pathAuthorize, - @NonNull String pathAccess, - boolean https, - @NonNull String consumerKey, - @NonNull String consumerSecret, - @NonNull String callback) { + public OAuthParameters(@NonNull final String host, + @NonNull final String pathRequest, + @NonNull final String pathAuthorize, + @NonNull final String pathAccess, + final boolean https, + @NonNull final String consumerKey, + @NonNull final String consumerSecret, + @NonNull final String callback) { this.host = host; this.pathRequest = pathRequest; this.pathAuthorize = pathAuthorize; @@ -381,7 +381,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { this.callback = callback; } - public void setOAuthExtras(Intent intent) { + public void setOAuthExtras(final Intent intent) { if (intent != null) { intent.putExtra(Intents.EXTRA_OAUTH_HOST, host); intent.putExtra(Intents.EXTRA_OAUTH_PATH_REQUEST, pathRequest); diff --git a/main/src/cgeo/geocaching/network/OAuthTokens.java b/main/src/cgeo/geocaching/network/OAuthTokens.java new file mode 100644 index 0000000..9f45e7f --- /dev/null +++ b/main/src/cgeo/geocaching/network/OAuthTokens.java @@ -0,0 +1,38 @@ +package cgeo.geocaching.network; + +import cgeo.geocaching.connector.oc.OCApiConnector; +import cgeo.geocaching.settings.Settings; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.eclipse.jdt.annotation.NonNull; + +import android.util.Pair; + +public class OAuthTokens extends Pair { + + public OAuthTokens(@NonNull final OCApiConnector connector) { + this(Settings.getTokenPair(connector.getTokenPublicPrefKeyId(), connector.getTokenSecretPrefKeyId())); + } + + public OAuthTokens(final ImmutablePair tokenPair) { + this(tokenPair.left, tokenPair.right); + } + + public OAuthTokens(final String pub, final String secret) { + super(pub, secret); + } + + public boolean isValid() { + return StringUtils.isNotBlank(getTokenPublic()) && StringUtils.isNotBlank(getTokenSecret()); + } + + public String getTokenPublic() { + return first; + } + + public String getTokenSecret() { + return second; + } + +} diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java index c89c0b6..253d91f 100644 --- a/main/src/cgeo/geocaching/twitter/Twitter.java +++ b/main/src/cgeo/geocaching/twitter/Twitter.java @@ -10,6 +10,7 @@ import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter.Format; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.OAuth; +import cgeo.geocaching.network.OAuthTokens; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; @@ -17,6 +18,7 @@ import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogContext; import ch.boye.httpclientandroidlib.HttpResponse; + import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -25,7 +27,7 @@ public final class Twitter { private static final String HASH_PREFIX_WITH_BLANK = " #"; private static final int MAX_TWEET_SIZE = 140; - public static void postTweetCache(String geocode, final @Nullable LogEntry logEntry) { + public static void postTweetCache(final String geocode, final @Nullable LogEntry logEntry) { final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); if (cache == null) { return; @@ -33,7 +35,7 @@ public final class Twitter { postTweet(CgeoApplication.getInstance(), getStatusMessage(cache, logEntry), null); } - public static void postTweetTrackable(String geocode, final @Nullable LogEntry logEntry) { + public static void postTweetTrackable(final String geocode, final @Nullable LogEntry logEntry) { final Trackable trackable = DataStore.loadTrackable(geocode); if (trackable == null) { return; @@ -48,7 +50,7 @@ public final class Twitter { try { final String status = shortenToMaxSize(statusIn); - Parameters parameters = new Parameters("status", status); + final Parameters parameters = new Parameters("status", status); if (coords != null) { parameters.put( "lat", coords.format(Format.LAT_DECDEGREE_RAW), @@ -56,7 +58,7 @@ public final class Twitter { "display_coordinates", "true"); } - OAuth.signOAuth("api.twitter.com", "/1.1/statuses/update.json", "POST", true, parameters, Settings.getTokenPublic(), Settings.getTokenSecret(), Settings.getKeyConsumerPublic(), Settings.getKeyConsumerSecret()); + OAuth.signOAuth("api.twitter.com", "/1.1/statuses/update.json", "POST", true, parameters, new OAuthTokens(Settings.getTokenPublic(), Settings.getTokenSecret()), Settings.getKeyConsumerPublic(), Settings.getKeyConsumerSecret()); final HttpResponse httpResponse = Network.postRequest("https://api.twitter.com/1.1/statuses/update.json", parameters); if (httpResponse != null) { if (httpResponse.getStatusLine().getStatusCode() == 200) { @@ -67,13 +69,13 @@ public final class Twitter { } else { Log.e("Tweet could not be posted. Reason: httpResponse Object is null"); } - } catch (Exception e) { + } catch (final Exception e) { Log.e("Twitter.postTweet", e); } } private static String shortenToMaxSize(final String status) { - String result = StringUtils.trim(status); + final String result = StringUtils.trim(status); if (StringUtils.length(result) > MAX_TWEET_SIZE) { return StringUtils.substring(result, 0, MAX_TWEET_SIZE - 1) + '…'; } @@ -98,7 +100,7 @@ public final class Twitter { } private static String appendHashTags(final String status) { - StringBuilder builder = new StringBuilder(status); + final StringBuilder builder = new StringBuilder(status); appendHashTag(builder, "cgeo"); appendHashTag(builder, "geocaching"); return builder.toString(); -- cgit v1.1 From 8227161f177d185ebf8226b42bc4508f61b2adca Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 3 Aug 2014 21:52:28 +0200 Subject: typos --- .../src/cgeo/geocaching/connector/gc/GCParser.java | 60 +++++++++++----------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index 60d7856..1430e80 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -211,11 +211,11 @@ public abstract class GCParser { final String dateHidden = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_HIDDEN_DATE, false, 1, null, false); if (StringUtils.isNotBlank(dateHidden)) { try { - Date date = GCLogin.parseGcCustomDate(dateHidden); + final Date date = GCLogin.parseGcCustomDate(dateHidden); if (date != null) { cache.setHidden(date); } - } catch (ParseException e) { + } catch (final ParseException e) { Log.e("Error parsing event date from search"); } } @@ -380,10 +380,12 @@ public abstract class GCParser { * Parse cache from text and return either an error code or a cache object in a pair. Note that inline logs are * not parsed nor saved, while the cache itself is. * - * @param pageIn the page text to parse - * @param handler the handler to send the progress notifications to - * @return a pair, with a {@link StatusCode} on the left, and a non-nulll cache objet on the right - * iff the status code is {@link StatusCode.NO_ERROR}. + * @param pageIn + * the page text to parse + * @param handler + * the handler to send the progress notifications to + * @return a pair, with a {@link StatusCode} on the left, and a non-null cache object on the right + * iff the status code is {@link StatusCode.NO_ERROR}. */ static private ImmutablePair parseCacheFromText(final String pageIn, @Nullable final CancellableHandler handler) { CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_details); @@ -408,7 +410,7 @@ public abstract class GCParser { // first handle the content with line breaks, then trim everything for easier matching and reduced memory consumption in parsed fields String personalNoteWithLineBreaks = ""; - MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_PERSONALNOTE, pageIn); + final MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_PERSONALNOTE, pageIn); if (matcher.find()) { personalNoteWithLineBreaks = matcher.group(1).trim(); } @@ -762,7 +764,7 @@ public abstract class GCParser { return StringUtils.replaceChars(numberWithPunctuation, ".,", ""); } - public static SearchResult searchByNextPage(final SearchResult search, boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByNextPage(final SearchResult search, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (search == null) { return null; } @@ -845,7 +847,7 @@ public abstract class GCParser { * @return */ @Nullable - private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, RecaptchaReceiver recaptchaReceiver) { + private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, final RecaptchaReceiver recaptchaReceiver) { insertCacheType(params, cacheType); final String uri = "http://www.geocaching.com/seek/nearest.aspx"; @@ -871,12 +873,12 @@ public abstract class GCParser { return search; } - public static SearchResult searchByCoords(final @NonNull Geopoint coords, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByCoords(final @NonNull Geopoint coords, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { final Parameters params = new Parameters("lat", Double.toString(coords.getLatitude()), "lng", Double.toString(coords.getLongitude())); return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByKeyword(final @NonNull String keyword, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByKeyword(final @NonNull String keyword, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(keyword)) { Log.e("GCParser.searchByKeyword: No keyword given"); return null; @@ -894,7 +896,7 @@ public abstract class GCParser { return false; } - public static SearchResult searchByUsername(final String userName, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByUsername(final String userName, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(userName)) { Log.e("GCParser.searchByUsername: No user name given"); return null; @@ -905,7 +907,7 @@ public abstract class GCParser { return searchByAny(cacheType, isSearchForMyCaches(userName), showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByPocketQuery(final String pocketGuid, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByPocketQuery(final String pocketGuid, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(pocketGuid)) { Log.e("GCParser.searchByPocket: No guid name given"); return null; @@ -916,7 +918,7 @@ public abstract class GCParser { return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByOwner(final String userName, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByOwner(final String userName, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(userName)) { Log.e("GCParser.searchByOwner: No user name given"); return null; @@ -926,7 +928,7 @@ public abstract class GCParser { return searchByAny(cacheType, isSearchForMyCaches(userName), showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByAddress(final String address, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByAddress(final String address, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(address)) { Log.e("GCParser.searchByAddress: No address given"); return null; @@ -1001,13 +1003,13 @@ public abstract class GCParser { return null; } - String subPage = StringUtils.substringAfter(page, "class=\"PocketQueryListTable"); + final String subPage = StringUtils.substringAfter(page, "class=\"PocketQueryListTable"); if (StringUtils.isEmpty(subPage)) { Log.e("GCParser.searchPocketQueryList: class \"PocketQueryListTable\" not found on page"); return Collections.emptyList(); } - List list = new ArrayList<>(); + final List list = new ArrayList<>(); final MatcherWrapper matcherPocket = new MatcherWrapper(GCConstants.PATTERN_LIST_PQ, subPage); @@ -1015,7 +1017,7 @@ public abstract class GCParser { int maxCaches; try { maxCaches = Integer.parseInt(matcherPocket.group(1)); - } catch (NumberFormatException e) { + } catch (final NumberFormatException e) { maxCaches = 0; Log.e("GCParser.searchPocketQueryList: Unable to parse max caches", e); } @@ -1029,7 +1031,7 @@ public abstract class GCParser { Collections.sort(list, new Comparator() { @Override - public int compare(PocketQueryList left, PocketQueryList right) { + public int compare(final PocketQueryList left, final PocketQueryList right) { return String.CASE_INSENSITIVE_ORDER.compare(left.getName(), right.getName()); } }); @@ -1522,11 +1524,11 @@ public abstract class GCParser { if (releaseString != null) { try { trackable.setReleased(dateTbIn1.parse(releaseString)); - } catch (ParseException e) { + } catch (final ParseException e) { if (trackable.getReleased() == null) { try { trackable.setReleased(dateTbIn2.parse(releaseString)); - } catch (ParseException e1) { + } catch (final ParseException e1) { Log.e("Could not parse trackable release " + releaseString); } } @@ -1630,7 +1632,7 @@ public abstract class GCParser { return trackable; } - private static String convertLinks(String input) { + private static String convertLinks(final String input) { if (input == null) { return null; } @@ -1657,7 +1659,7 @@ public abstract class GCParser { final String paramName; - SpecialLogs(String paramName) { + SpecialLogs(final String paramName) { this.paramName = paramName; } @@ -1702,7 +1704,7 @@ public abstract class GCParser { Log.e("GCParser.loadLogsFromDetails: error " + statusCode + " when requesting log information"); return Observable.empty(); } - String rawResponse = Network.getResponseData(response); + final String rawResponse = Network.getResponseData(response); if (rawResponse == null) { Log.e("GCParser.loadLogsFromDetails: unable to read whole response"); return Observable.empty(); @@ -1781,7 +1783,7 @@ public abstract class GCParser { } @NonNull - public static List parseTypes(String page) { + public static List parseTypes(final String page) { if (StringUtils.isEmpty(page)) { return Collections.emptyList(); } @@ -1934,15 +1936,15 @@ public abstract class GCParser { } } - public static boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) { + public static boolean uploadModifiedCoordinates(final Geocache cache, final Geopoint wpt) { return editModifiedCoordinates(cache, wpt); } - public static boolean deleteModifiedCoordinates(Geocache cache) { + public static boolean deleteModifiedCoordinates(final Geocache cache) { return editModifiedCoordinates(cache, null); } - public static boolean editModifiedCoordinates(Geocache cache, Geopoint wpt) { + public static boolean editModifiedCoordinates(final Geocache cache, final Geopoint wpt) { final String userToken = getUserToken(cache); if (StringUtils.isEmpty(userToken)) { return false; @@ -1977,7 +1979,7 @@ public abstract class GCParser { return false; } - public static boolean uploadPersonalNote(Geocache cache) { + public static boolean uploadPersonalNote(final Geocache cache) { final String userToken = getUserToken(cache); if (StringUtils.isEmpty(userToken)) { return false; -- cgit v1.1 From 30dddca902eb9cffc6390ebd935d325519ffc2a1 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 3 Aug 2014 21:52:58 +0200 Subject: logcat shows wrong error for initial reset of OOM handler --- .../cgeo/geocaching/utils/OOMDumpingUncaughtExceptionHandler.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/utils/OOMDumpingUncaughtExceptionHandler.java b/main/src/cgeo/geocaching/utils/OOMDumpingUncaughtExceptionHandler.java index 1401542..0c6365c 100644 --- a/main/src/cgeo/geocaching/utils/OOMDumpingUncaughtExceptionHandler.java +++ b/main/src/cgeo/geocaching/utils/OOMDumpingUncaughtExceptionHandler.java @@ -11,14 +11,12 @@ public class OOMDumpingUncaughtExceptionHandler implements UncaughtExceptionHand private boolean defaultReplaced = false; public static boolean activateHandler() { - final OOMDumpingUncaughtExceptionHandler handler = new OOMDumpingUncaughtExceptionHandler(); return handler.activate(); } private boolean activate() { - defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); // replace default handler if that has not been done already @@ -34,10 +32,8 @@ public class OOMDumpingUncaughtExceptionHandler implements UncaughtExceptionHand } public static boolean resetToDefault() { - - boolean defaultResetted = false; - final UncaughtExceptionHandler unspecificHandler = Thread.getDefaultUncaughtExceptionHandler(); + boolean defaultResetted = unspecificHandler != null; if (unspecificHandler instanceof OOMDumpingUncaughtExceptionHandler) { final OOMDumpingUncaughtExceptionHandler handler = (OOMDumpingUncaughtExceptionHandler) unspecificHandler; @@ -48,7 +44,6 @@ public class OOMDumpingUncaughtExceptionHandler implements UncaughtExceptionHand } private boolean reset() { - final boolean resetted = defaultReplaced; if (defaultReplaced) { -- cgit v1.1 From e31103eda917df73b20152b65d23caee5588b5ec Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 21:57:56 +0200 Subject: Use multicatch --- main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java index 6ebd070..6e6b4d2 100644 --- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java @@ -193,9 +193,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { final String encodedParams = EntityUtils.toString(new UrlEncodedFormEntity(paramsBrowser)); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getUrlPrefix() + host + pathAuthorize + "?" + encodedParams))); status = STATUS_SUCCESS; - } catch (final ParseException e) { - Log.e("OAuthAuthorizationActivity.requestToken", e); - } catch (final IOException e) { + } catch (ParseException | IOException e) { Log.e("OAuthAuthorizationActivity.requestToken", e); } } -- cgit v1.1 From 455c229b01643235188d3afbac284669ea37d4c3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 22:04:49 +0200 Subject: Use simpler regular expressions --- main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java index 6e6b4d2..76a1927 100644 --- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java @@ -51,8 +51,8 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { @NonNull private String callback = StringUtils.EMPTY; private String OAtoken = null; private String OAtokenSecret = null; - private final Pattern paramsPattern1 = Pattern.compile("oauth_token=([a-zA-Z0-9\\-\\_.]+)"); - private final Pattern paramsPattern2 = Pattern.compile("oauth_token_secret=([a-zA-Z0-9\\-\\_.]+)"); + private final Pattern paramsPattern1 = Pattern.compile("oauth_token=([\\w_.-]+)"); + private final Pattern paramsPattern2 = Pattern.compile("oauth_token_secret=([\\w_.-]+)"); @InjectView(R.id.start) protected Button startButton; @InjectView(R.id.auth_1) protected TextView auth_1; @InjectView(R.id.auth_2) protected TextView auth_2; -- cgit v1.1 From 5ec513941d9a6456748d650da312cfd2450f8dbd Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 22:07:56 +0200 Subject: Make patterns more preeminently constant --- .../cgeo/geocaching/network/OAuthAuthorizationActivity.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java index 76a1927..5efea02 100644 --- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java @@ -40,6 +40,8 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { private static final int STATUS_ERROR = 0; private static final int STATUS_SUCCESS = 1; private static final int STATUS_ERROR_EXT_MSG = 2; + private static final Pattern PARAMS_PATTERN_1 = Pattern.compile("oauth_token=([\\w_.-]+)"); + private static final Pattern PARAMS_PATTERN_2 = Pattern.compile("oauth_token_secret=([\\w_.-]+)"); @NonNull private String host = StringUtils.EMPTY; @NonNull private String pathRequest = StringUtils.EMPTY; @@ -51,8 +53,6 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { @NonNull private String callback = StringUtils.EMPTY; private String OAtoken = null; private String OAtokenSecret = null; - private final Pattern paramsPattern1 = Pattern.compile("oauth_token=([\\w_.-]+)"); - private final Pattern paramsPattern2 = Pattern.compile("oauth_token_secret=([\\w_.-]+)"); @InjectView(R.id.start) protected Button startButton; @InjectView(R.id.auth_1) protected TextView auth_1; @InjectView(R.id.auth_2) protected TextView auth_2; @@ -176,11 +176,11 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { int status = STATUS_ERROR; if (StringUtils.isNotBlank(line)) { assert line != null; - final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line); + final MatcherWrapper paramsMatcher1 = new MatcherWrapper(PARAMS_PATTERN_1, line); if (paramsMatcher1.find()) { OAtoken = paramsMatcher1.group(1); } - final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line); + final MatcherWrapper paramsMatcher2 = new MatcherWrapper(PARAMS_PATTERN_2, line); if (paramsMatcher2.find()) { OAtokenSecret = paramsMatcher2.group(1); } @@ -225,11 +225,11 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { OAtoken = ""; OAtokenSecret = ""; - final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line); + final MatcherWrapper paramsMatcher1 = new MatcherWrapper(PARAMS_PATTERN_1, line); if (paramsMatcher1.find()) { OAtoken = paramsMatcher1.group(1); } - final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line); + final MatcherWrapper paramsMatcher2 = new MatcherWrapper(PARAMS_PATTERN_2, line); if (paramsMatcher2.find() && paramsMatcher2.groupCount() > 0) { OAtokenSecret = paramsMatcher2.group(1); } -- cgit v1.1 From 3684ad6841c44841acc7c4ff9e85d6b48d6465a6 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 22:49:25 +0200 Subject: Use incrementation operator --- main/src/cgeo/geocaching/geopoint/Viewport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/geopoint/Viewport.java b/main/src/cgeo/geocaching/geopoint/Viewport.java index 171000e..a48b0a1 100644 --- a/main/src/cgeo/geocaching/geopoint/Viewport.java +++ b/main/src/cgeo/geocaching/geopoint/Viewport.java @@ -89,7 +89,7 @@ public final class Viewport { int total = 0; for (ICoordinates point: points) { if (point != null && contains(point)) { - total = total + 1; + total += 1; } } return total; -- cgit v1.1 From 44c69ebc309b5e648f062b86f1484831ad1957f9 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 22:50:21 +0200 Subject: Suppression warnings for external KXmlSerializer --- main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java | 1 + 1 file changed, 1 insertion(+) (limited to 'main') diff --git a/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java b/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java index 027ff53..01a1872 100644 --- a/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java +++ b/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java @@ -32,6 +32,7 @@ import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Locale; +@SuppressWarnings("ALL") public class KXmlSerializer implements XmlSerializer { // static final String UNDEFINED = ":"; -- cgit v1.1 From c617503fabe25adb954f24e9724ae51d6b3d7b1d Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 22:51:46 +0200 Subject: Remove redundant else constructs --- main/src/cgeo/geocaching/files/GPXImporter.java | 5 +++-- main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java index 52f68e1..85d12f7 100644 --- a/main/src/cgeo/geocaching/files/GPXImporter.java +++ b/main/src/cgeo/geocaching/files/GPXImporter.java @@ -139,10 +139,11 @@ public class GPXImporter { final String mimeType) { if (GPX_MIME_TYPES.contains(mimeType)) { return FileType.GPX; - } else if (ZIP_MIME_TYPES.contains(mimeType)) { + } + if (ZIP_MIME_TYPES.contains(mimeType)) { return FileType.ZIP; } - return FileType.UNKNOWN; + return FileType.UNKNOWN; } private ImportThread getImporterFromFileType(Uri uri, diff --git a/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java b/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java index 57a69ee..a2da6ee 100644 --- a/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java +++ b/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java @@ -26,7 +26,8 @@ public class PopularityRatioComparator extends AbstractCacheComparator { if ((ratio2 - ratio1) > 0.0f) { return 1; - } else if ((ratio2 - ratio1) < 0.0f) { + } + if ((ratio2 - ratio1) < 0.0f) { return -1; } -- cgit v1.1 From d5d5e63ebc5c844a42eddbfdc2da8b093fd810f3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 22:56:18 +0200 Subject: Remove unused fields --- main/src/cgeo/geocaching/AbstractDialogFragment.java | 2 -- main/src/cgeo/geocaching/list/StoredList.java | 1 - 2 files changed, 3 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/AbstractDialogFragment.java b/main/src/cgeo/geocaching/AbstractDialogFragment.java index 4025347..6f64146 100644 --- a/main/src/cgeo/geocaching/AbstractDialogFragment.java +++ b/main/src/cgeo/geocaching/AbstractDialogFragment.java @@ -42,7 +42,6 @@ import android.widget.ImageView; import android.widget.TextView; public abstract class AbstractDialogFragment extends DialogFragment implements CacheMenuHandler.ActivityInterface, PopupMenu.OnMenuItemClickListener, MenuItem.OnMenuItemClickListener { - protected CgeoApplication app = null; protected Resources res = null; protected String geocode; protected CacheDetailsCreator details; @@ -61,7 +60,6 @@ public abstract class AbstractDialogFragment extends DialogFragment implements C public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); res = getResources(); - app = (CgeoApplication) getActivity().getApplication(); setHasOptionsMenu(true); } diff --git a/main/src/cgeo/geocaching/list/StoredList.java b/main/src/cgeo/geocaching/list/StoredList.java index 53632a0..013898e 100644 --- a/main/src/cgeo/geocaching/list/StoredList.java +++ b/main/src/cgeo/geocaching/list/StoredList.java @@ -25,7 +25,6 @@ import java.util.List; public final class StoredList extends AbstractList { public static final int TEMPORARY_LIST_ID = 0; - public static final StoredList TEMPORARY_LIST = new StoredList(TEMPORARY_LIST_ID, "", 0); // Never displayed public static final int STANDARD_LIST_ID = 1; private final int count; // this value is only valid as long as the list is not changed by other database operations -- cgit v1.1 From a9e56aafe5b66bed5381fb52456d9e9d909dc3b3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 23:00:44 +0200 Subject: Remove unused package cgeo.geocaching.concurrent --- .../geocaching/concurrent/BlockingThreadPool.java | 57 ---------------------- .../concurrent/PriorityThreadFactory.java | 25 ---------- 2 files changed, 82 deletions(-) delete mode 100644 main/src/cgeo/geocaching/concurrent/BlockingThreadPool.java delete mode 100644 main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java (limited to 'main') diff --git a/main/src/cgeo/geocaching/concurrent/BlockingThreadPool.java b/main/src/cgeo/geocaching/concurrent/BlockingThreadPool.java deleted file mode 100644 index a6d7e9b..0000000 --- a/main/src/cgeo/geocaching/concurrent/BlockingThreadPool.java +++ /dev/null @@ -1,57 +0,0 @@ -package cgeo.geocaching.concurrent; - - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * BlockingThreadPool restricts the amount of parallel threads executing Runnables. - */ -public class BlockingThreadPool { - /** The queue holding the Runnable. **/ - private BlockingQueue queue = null; - /** The Executor. **/ - private ThreadPoolExecutor executor; - - /** - * Creates a ThreadPool with a given maximum of parallel threads running. - * Idle threads will be stopped until new threads are added. - * - * @param poolSize - * Maximum amout of parallel Threads - * @param priority - * The Thread priority e.g. Thread.MIN_PRIORITY - */ - public BlockingThreadPool(int poolSize, int priority) { - ThreadFactory threadFactory = new PriorityThreadFactory(priority); - this.queue = new ArrayBlockingQueue<>(poolSize, true); - this.executor = new ThreadPoolExecutor(0, poolSize, 5, TimeUnit.SECONDS, this.queue); - this.executor.setThreadFactory(threadFactory); - } - - /** - * Add a runnable to the pool. This will start the core threads in the underlying - * executor and try to add the Runnable to the pool. This method waits until timeout - * if no free thread is available. - * - * @param task - * The Runnable to add to the pool - * @param timeout - * The timeout to wait for a free thread - * @param unit - * The timeout unit - * @return true/false successful added - * @throws InterruptedException - * Operation was interrupted - */ - public boolean add(Runnable task, int timeout, TimeUnit unit) throws InterruptedException { - this.executor.setCorePoolSize(this.executor.getMaximumPoolSize()); - this.executor.prestartAllCoreThreads(); - boolean successfull = this.queue.offer(task, timeout, unit); - this.executor.setCorePoolSize(0); - return successfull; - } -} diff --git a/main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java b/main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java deleted file mode 100644 index 0da198b..0000000 --- a/main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package cgeo.geocaching.concurrent; - -import org.eclipse.jdt.annotation.NonNull; - -import java.util.concurrent.ThreadFactory; - -/** - * Helper class for setting Thread priority in ThreadPool. - */ -public class PriorityThreadFactory implements ThreadFactory { - private int priority; - - public PriorityThreadFactory(int priority) { - this.priority = priority; - } - - @NonNull - @Override - public Thread newThread(Runnable r) { - Thread result = new Thread(r); - result.setPriority(this.priority); - return result; - } - -} -- cgit v1.1 From 836eab0ce727bbecb25d626afc6d5170f685a98c Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 23:03:55 +0200 Subject: Remove unused methods --- main/src/cgeo/geocaching/CacheDetailActivity.java | 7 ------- main/src/cgeo/geocaching/DataStore.java | 21 --------------------- main/src/cgeo/geocaching/list/StoredList.java | 4 ---- 3 files changed, 32 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index bb1f154..363d1db 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -617,13 +617,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity runAfterwards) { - promptForListSelection(titleId, runAfterwards, false, -1); - } - public void promptForListSelection(final int titleId, @NonNull final Action1 runAfterwards, final boolean onlyConcreteLists, final int exceptListId) { promptForListSelection(titleId, runAfterwards, onlyConcreteLists, exceptListId, StringUtils.EMPTY); } -- cgit v1.1 From 68b79ef34f9457a225acde7b9fc4d7ff3fa383b3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 21:57:56 +0200 Subject: Use multicatch --- main/src/cgeo/geocaching/CgeoApplication.java | 7 +------ main/src/cgeo/geocaching/connector/gc/GCMap.java | 10 ++-------- main/src/cgeo/geocaching/files/FileTypeDetector.java | 3 --- main/src/cgeo/geocaching/sorting/SortActionProvider.java | 4 +--- main/src/cgeo/geocaching/utils/CryptUtils.java | 8 ++------ 5 files changed, 6 insertions(+), 26 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java index 6d07b7f..269c1b6 100644 --- a/main/src/cgeo/geocaching/CgeoApplication.java +++ b/main/src/cgeo/geocaching/CgeoApplication.java @@ -62,12 +62,7 @@ public class CgeoApplication extends Application { final Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey"); menuKeyField.setAccessible(true); menuKeyField.setBoolean(config, false); - } catch (final IllegalArgumentException e) { - // ignore - } catch (final NoSuchFieldException e) { - // ignore - } catch (final IllegalAccessException e) { - // ignore + } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException ignore) { } // ensure initialization of lists DataStore.getLists(); diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java index 27ce06e..c7318ce 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCMap.java +++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java @@ -102,11 +102,7 @@ public class GCMap { caches.add(cache); } result.addAndPutInCache(caches); - } catch (JSONException e) { - result.setError(StatusCode.UNKNOWN_ERROR); - } catch (ParseException e) { - result.setError(StatusCode.UNKNOWN_ERROR); - } catch (NumberFormatException e) { + } catch (JSONException | ParseException | NumberFormatException e) { result.setError(StatusCode.UNKNOWN_ERROR); } return result; @@ -220,9 +216,7 @@ public class GCMap { searchResult.addAndPutInCache(caches); Log.d("Retrieved " + searchResult.getCount() + " caches for tile " + tile.toString()); - } catch (RuntimeException e) { - Log.e("GCMap.parseMapJSON", e); - } catch (JSONException e) { + } catch (RuntimeException | JSONException e) { Log.e("GCMap.parseMapJSON", e); } diff --git a/main/src/cgeo/geocaching/files/FileTypeDetector.java b/main/src/cgeo/geocaching/files/FileTypeDetector.java index 389b83a..ab0f032 100644 --- a/main/src/cgeo/geocaching/files/FileTypeDetector.java +++ b/main/src/cgeo/geocaching/files/FileTypeDetector.java @@ -10,7 +10,6 @@ import android.content.ContentResolver; import android.net.Uri; import java.io.BufferedReader; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -37,8 +36,6 @@ public class FileTypeDetector { reader = new BufferedReader(new InputStreamReader(is)); type = detectHeader(reader); reader.close(); - } catch (FileNotFoundException e) { - Log.e("FileTypeDetector", e); } catch (IOException e) { Log.e("FileTypeDetector", e); } finally { diff --git a/main/src/cgeo/geocaching/sorting/SortActionProvider.java b/main/src/cgeo/geocaching/sorting/SortActionProvider.java index e9e65a0..61b2ffb 100644 --- a/main/src/cgeo/geocaching/sorting/SortActionProvider.java +++ b/main/src/cgeo/geocaching/sorting/SortActionProvider.java @@ -136,9 +136,7 @@ public class SortActionProvider extends ActionProvider implements OnMenuItemClic final CacheComparator comparator = cacheComparator.newInstance(); onClickListener.call(comparator); } - } catch (final InstantiationException e) { - Log.e("selectComparator", e); - } catch (final IllegalAccessException e) { + } catch (final InstantiationException | IllegalAccessException e) { Log.e("selectComparator", e); } } diff --git a/main/src/cgeo/geocaching/utils/CryptUtils.java b/main/src/cgeo/geocaching/utils/CryptUtils.java index 815c2f4..908add8 100644 --- a/main/src/cgeo/geocaching/utils/CryptUtils.java +++ b/main/src/cgeo/geocaching/utils/CryptUtils.java @@ -88,9 +88,7 @@ public final class CryptUtils { final MessageDigest digest = MessageDigest.getInstance("MD5"); digest.update(text.getBytes(CharEncoding.UTF_8), 0, text.length()); return new BigInteger(1, digest.digest()).toString(16); - } catch (NoSuchAlgorithmException e) { - Log.e("CryptUtils.md5", e); - } catch (UnsupportedEncodingException e) { + } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { Log.e("CryptUtils.md5", e); } @@ -105,9 +103,7 @@ public final class CryptUtils { final Mac mac = Mac.getInstance("HmacSHA1"); mac.init(secretKeySpec); macBytes = mac.doFinal(text.getBytes(CharEncoding.UTF_8)); - } catch (GeneralSecurityException e) { - Log.e("CryptUtils.hashHmac", e); - } catch (UnsupportedEncodingException e) { + } catch (GeneralSecurityException | UnsupportedEncodingException e) { Log.e("CryptUtils.hashHmac", e); } -- cgit v1.1 From 5bde7d6172b5e7fc32f1c8d8fbcce75a975aa738 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 3 Aug 2014 23:29:52 +0200 Subject: Make constants constant --- main/src/cgeo/geocaching/Geocache.java | 2 +- main/src/cgeo/geocaching/SelectMapfileActivity.java | 2 +- main/src/cgeo/geocaching/connector/ec/ECLogin.java | 2 +- main/src/cgeo/geocaching/files/SimpleDirChooser.java | 2 +- main/src/cgeo/geocaching/list/AbstractList.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java index e0daae1..1a814b0 100644 --- a/main/src/cgeo/geocaching/Geocache.java +++ b/main/src/cgeo/geocaching/Geocache.java @@ -165,7 +165,7 @@ public class Geocache implements ICache, IWaypoint { // Images whose URL contains one of those patterns will not be available on the Images tab // for opening into an external application. - private final String[] NO_EXTERNAL = new String[]{"geocheck.org"}; + private final static String[] NO_EXTERNAL = new String[]{"geocheck.org"}; /** * Create a new cache. To be used everywhere except for the GPX parser diff --git a/main/src/cgeo/geocaching/SelectMapfileActivity.java b/main/src/cgeo/geocaching/SelectMapfileActivity.java index dc898d7..970783c 100644 --- a/main/src/cgeo/geocaching/SelectMapfileActivity.java +++ b/main/src/cgeo/geocaching/SelectMapfileActivity.java @@ -33,7 +33,7 @@ public class SelectMapfileActivity extends AbstractFileListActivity NAME_COMPARATOR = new Comparator() { + private final static Comparator

Logged on: ([^<]+?)<"); public final static Pattern PATTERN_OWNER_DISPLAYNAME = Pattern.compile("
[^<]+([^<]+)"); public final static Pattern PATTERN_TYPE = Pattern.compile("\\W*Hidden[\\s:]*([^<]+?)
"); diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java index 8de3edc..d42bb34 100644 --- a/main/src/cgeo/geocaching/gcvote/GCVote.java +++ b/main/src/cgeo/geocaching/gcvote/GCVote.java @@ -20,7 +20,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.regex.Pattern; @@ -275,10 +274,6 @@ public final class GCVote { return rating >= MIN_RATING && rating <= MAX_RATING; } - public static String getRatingText(final float rating) { - return String.format(Locale.getDefault(), "%.1f", rating); - } - public static boolean isVotingPossible(final Geocache cache) { return Settings.isGCvoteLogin() && StringUtils.isNotBlank(cache.getGuid()) && cache.supportsGCVote(); } -- cgit v1.1 From 69993a499674c90ebb2cf16e2ce7411c533721f9 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 4 Aug 2014 19:14:20 +0200 Subject: Remove now unused HideLiveMapHint setting This is part of fix for #3470. --- main/res/values/preference_keys.xml | 1 - main/src/cgeo/geocaching/maps/CGeoMap.java | 2 +- main/src/cgeo/geocaching/settings/Settings.java | 9 --------- 3 files changed, 1 insertion(+), 11 deletions(-) (limited to 'main') diff --git a/main/res/values/preference_keys.xml b/main/res/values/preference_keys.xml index 72d7c61..5189cc5 100644 --- a/main/res/values/preference_keys.xml +++ b/main/res/values/preference_keys.xml @@ -108,7 +108,6 @@ cookiestore lastdetailspage livemapstrategy - hidelivemaphint livemaphintshowcount settingsversion trackableaction diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index 5b1461b..c373d3f 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -491,7 +491,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } prepareFilterBar(); - if (!app.isLiveMapHintShownInThisSession() && !Settings.getHideLiveMapHint() && Settings.getLiveMapHintShowCount() <= 3) { + if (!app.isLiveMapHintShownInThisSession() && Settings.getLiveMapHintShowCount() <= 3) { LiveMapInfoDialogBuilder.create(activity).show(); } } diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java index b0fc962..b1c5c31 100644 --- a/main/src/cgeo/geocaching/settings/Settings.java +++ b/main/src/cgeo/geocaching/settings/Settings.java @@ -154,7 +154,6 @@ public class Settings { e.putInt(getKey(R.string.pref_defaultNavigationTool2), old.getInt(getKey(R.string.pref_defaultNavigationTool2), NavigationAppsEnum.INTERNAL_MAP.id)); e.putInt(getKey(R.string.pref_livemapstrategy), old.getInt(getKey(R.string.pref_livemapstrategy), Strategy.AUTO.id)); e.putBoolean(getKey(R.string.pref_debug), old.getBoolean(getKey(R.string.pref_debug), false)); - e.putBoolean(getKey(R.string.pref_hidelivemaphint), old.getInt(getKey(R.string.pref_hidelivemaphint), 0) != 0); e.putInt(getKey(R.string.pref_livemaphintshowcount), old.getInt(getKey(R.string.pref_livemaphintshowcount), 0)); e.putInt(getKey(R.string.pref_settingsversion), 1); // mark migrated @@ -835,14 +834,6 @@ public class Settings { return Log.isDebug(); } - public static boolean getHideLiveMapHint() { - return getBoolean(R.string.pref_hidelivemaphint, false); - } - - public static void setHideLiveHint(final boolean hide) { - putBoolean(R.string.pref_hidelivemaphint, hide); - } - public static int getLiveMapHintShowCount() { return getInt(R.string.pref_livemaphintshowcount, 0); } -- cgit v1.1 From 899d7a357cbe38e4d71352fb0215c0674eb9b0c3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 4 Aug 2014 19:20:02 +0200 Subject: Use foreach loops when possible --- main/src/cgeo/geocaching/filter/PopularityFilter.java | 3 +-- main/src/cgeo/geocaching/filter/PopularityRatioFilter.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/filter/PopularityFilter.java b/main/src/cgeo/geocaching/filter/PopularityFilter.java index a0244b9..0fc807d 100644 --- a/main/src/cgeo/geocaching/filter/PopularityFilter.java +++ b/main/src/cgeo/geocaching/filter/PopularityFilter.java @@ -29,8 +29,7 @@ class PopularityFilter extends AbstractFilter { @Override public List getFilters() { final List filters = new ArrayList<>(FAVORITES.length); - for (int i = 0; i < FAVORITES.length; i++) { - final int minRange = FAVORITES[i]; + for (final int minRange : FAVORITES) { final int maxRange = Integer.MAX_VALUE; final String range = "> " + minRange; final String name = CgeoApplication.getInstance().getResources().getQuantityString(R.plurals.favorite_points, minRange, range); diff --git a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java index a04f219..ed8c074 100644 --- a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java +++ b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java @@ -53,8 +53,7 @@ class PopularityRatioFilter extends AbstractFilter { @Override public List getFilters() { final List filters = new ArrayList<>(RATIOS.length); - for (int i = 0; i < RATIOS.length; i++) { - final int minRange = RATIOS[i]; + for (final int minRange : RATIOS) { final int maxRange = Integer.MAX_VALUE; final String name = "> " + minRange + " " + CgeoApplication.getInstance().getResources().getString(R.string.percent_favorite_points); filters.add(new PopularityRatioFilter(name, minRange, maxRange)); -- cgit v1.1 From 81d4147076f4009ac913d681ca3c2c585554c5a0 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 4 Aug 2014 19:22:43 +0200 Subject: Do not repeatedly create empty byte arrays Empty byte arrays are immutable, so one can serve for everything. Also, use uppercase to represent constants after the class initialization is over. --- main/src/cgeo/geocaching/utils/CryptUtils.java | 36 ++++++++++++-------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/utils/CryptUtils.java b/main/src/cgeo/geocaching/utils/CryptUtils.java index 908add8..f2ff0c2 100644 --- a/main/src/cgeo/geocaching/utils/CryptUtils.java +++ b/main/src/cgeo/geocaching/utils/CryptUtils.java @@ -1,6 +1,5 @@ package cgeo.geocaching.utils; - import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; @@ -23,28 +22,29 @@ public final class CryptUtils { // utility class } - private static char[] base64map1 = new char[64]; - private static byte[] base64map2 = new byte[128]; + private static final byte[] EMPTY = {}; + private static char[] BASE64MAP1 = new char[64]; + private static byte[] BASE64MAP2 = new byte[128]; static { int i = 0; for (char c = 'A'; c <= 'Z'; c++) { - base64map1[i++] = c; + BASE64MAP1[i++] = c; } for (char c = 'a'; c <= 'z'; c++) { - base64map1[i++] = c; + BASE64MAP1[i++] = c; } for (char c = '0'; c <= '9'; c++) { - base64map1[i++] = c; + BASE64MAP1[i++] = c; } - base64map1[i++] = '+'; - base64map1[i++] = '/'; + BASE64MAP1[i++] = '+'; + BASE64MAP1[i++] = '/'; - for (i = 0; i < base64map2.length; i++) { - base64map2[i] = -1; + for (i = 0; i < BASE64MAP2.length; i++) { + BASE64MAP2[i] = -1; } for (i = 0; i < 64; i++) { - base64map2[base64map1[i]] = (byte) i; + BASE64MAP2[BASE64MAP1[i]] = (byte) i; } } @@ -96,18 +96,16 @@ public final class CryptUtils { } public static byte[] hashHmac(String text, String salt) { - byte[] macBytes = {}; try { final SecretKeySpec secretKeySpec = new SecretKeySpec(salt.getBytes(CharEncoding.UTF_8), "HmacSHA1"); final Mac mac = Mac.getInstance("HmacSHA1"); mac.init(secretKeySpec); - macBytes = mac.doFinal(text.getBytes(CharEncoding.UTF_8)); + return mac.doFinal(text.getBytes(CharEncoding.UTF_8)); } catch (GeneralSecurityException | UnsupportedEncodingException e) { Log.e("CryptUtils.hashHmac", e); + return EMPTY; } - - return macBytes; } public static CharSequence rot13(final Spannable span) { @@ -141,11 +139,11 @@ public final class CryptUtils { int o1 = ((i0 & 3) << 4) | (i1 >>> 4); int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); int o3 = i2 & 0x3F; - out[op++] = base64map1[o0]; - out[op++] = base64map1[o1]; - out[op] = op < oDataLen ? base64map1[o2] : '='; + out[op++] = BASE64MAP1[o0]; + out[op++] = BASE64MAP1[o1]; + out[op] = op < oDataLen ? BASE64MAP1[o2] : '='; op++; - out[op] = op < oDataLen ? base64map1[o3] : '='; + out[op] = op < oDataLen ? BASE64MAP1[o3] : '='; op++; } -- cgit v1.1 From 0ca6fd5d478eab76b20d813638c6bec3539b7f1d Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 4 Aug 2014 19:29:21 +0200 Subject: Do not use regular expressions to remove . and , --- main/src/cgeo/geocaching/connector/gc/GCLogin.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/gc/GCLogin.java b/main/src/cgeo/geocaching/connector/gc/GCLogin.java index e84851e..e99cdf6 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCLogin.java +++ b/main/src/cgeo/geocaching/connector/gc/GCLogin.java @@ -177,6 +177,9 @@ public class GCLogin extends AbstractLogin { return StatusCode.NO_ERROR; } + private static String removeDotAndComma(final String str) { + return StringUtils.replaceChars(str, ".,", null); + } /** * Check if the user has been logged in when he retrieved the data. @@ -203,7 +206,7 @@ public class GCLogin extends AbstractLogin { setActualUserName(TextUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???")); int cachesCount = 0; try { - cachesCount = Integer.parseInt(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", "")); + cachesCount = Integer.parseInt(removeDotAndComma(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0"))); } catch (final NumberFormatException e) { Log.e("getLoginStatus: bad cache count", e); } @@ -268,7 +271,7 @@ public class GCLogin extends AbstractLogin { Settings.setGCMemberStatus(GCConstants.MEMBER_STATUS_PM); } - setActualCachesFound(Integer.parseInt(TextUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", ""))); + setActualCachesFound(Integer.parseInt(removeDotAndComma(TextUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1")))); final String avatarURL = TextUtils.getMatch(profile, GCConstants.PATTERN_AVATAR_IMAGE_PROFILE_PAGE, false, null); if (null != avatarURL) { -- cgit v1.1 From b56c2a5a1c1f793d4953d35c9def32ceb768a880 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 4 Aug 2014 19:44:13 +0200 Subject: fix #4114: replace strings with patterns in parsers Some strings are really meant to be used as regular strings and not as regular expressions. --- main/src/cgeo/geocaching/connector/gc/GCParser.java | 8 ++++---- main/src/cgeo/geocaching/connector/oc/OkapiClient.java | 5 ++++- main/src/cgeo/geocaching/files/GPXParser.java | 2 +- main/src/cgeo/geocaching/files/LocParser.java | 2 +- main/src/cgeo/geocaching/network/Network.java | 6 ++++-- 5 files changed, 14 insertions(+), 9 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index 1430e80..f704da6 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -125,7 +125,7 @@ public abstract class GCParser { page = page.substring(startPos + 1, endPos - startPos + 1); // cut between and
- final String[] rows = page.split(" j) { - wp = wpItems[j].split(" 0) { type = content[0].toLowerCase(Locale.US).trim(); } diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java index 2871d77..13f8cca 100644 --- a/main/src/cgeo/geocaching/files/LocParser.java +++ b/main/src/cgeo/geocaching/files/LocParser.java @@ -88,7 +88,7 @@ public final class LocParser extends FileParser { } // >> premium only - final String[] points = fileContent.split(""); + final String[] points = StringUtils.splitByWholeSeparator(fileContent, ""); // parse coordinates for (String pointString : points) { diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java index ec6ec4f..57e6698 100644 --- a/main/src/cgeo/geocaching/network/Network.java +++ b/main/src/cgeo/geocaching/network/Network.java @@ -26,6 +26,7 @@ import ch.boye.httpclientandroidlib.params.CoreConnectionPNames; import ch.boye.httpclientandroidlib.params.CoreProtocolPNames; import ch.boye.httpclientandroidlib.params.HttpParams; import ch.boye.httpclientandroidlib.util.EntityUtils; + import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.Nullable; @@ -43,6 +44,7 @@ import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; +import java.util.regex.Pattern; public abstract class Network { @@ -51,7 +53,7 @@ public abstract class Network { /** Native user agent, taken from a Android 2.2 Nexus **/ private final static String NATIVE_USER_AGENT = "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"; - private static final String PATTERN_PASSWORD = "(?<=[\\?&])[Pp]ass(w(or)?d)?=[^&#$]+"; + private static final Pattern PATTERN_PASSWORD = Pattern.compile("(?<=[\\?&])[Pp]ass(w(or)?d)?=[^&#$]+"); private final static HttpParams clientParams = new BasicHttpParams(); @@ -63,7 +65,7 @@ public abstract class Network { } private static String hidePassword(final String message) { - return message.replaceAll(PATTERN_PASSWORD, "password=***"); + return PATTERN_PASSWORD.matcher(message).replaceAll("password=***"); } private static HttpClient getHttpClient() { -- cgit v1.1 From c22b10a72aa85f0c4a3b2bf8f8cea07cf5ef3fe3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 4 Aug 2014 19:52:40 +0200 Subject: Log exception when it happens --- main/src/cgeo/geocaching/network/Network.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java index 57e6698..5309923 100644 --- a/main/src/cgeo/geocaching/network/Network.java +++ b/main/src/cgeo/geocaching/network/Network.java @@ -116,7 +116,7 @@ public abstract class Network { try { request.setEntity(new StringEntity(json.toString(), CharEncoding.UTF_8)); } catch (UnsupportedEncodingException e) { - Log.e("postJsonRequest:JSON Entity: UnsupportedEncodingException"); + Log.e("postJsonRequest:JSON Entity: UnsupportedEncodingException", e); return null; } } -- cgit v1.1 From 322415479d79c0c2c91d3a83fca90655441ede01 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Mon, 4 Aug 2014 20:59:37 +0200 Subject: #4111: scale smileys --- main/src/cgeo/geocaching/network/HtmlImage.java | 17 ++++++----- main/src/cgeo/geocaching/network/SmileyImage.java | 34 ++++++++++++++++++++++ .../cgeo/geocaching/ui/logs/LogsViewCreator.java | 5 ++-- 3 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 main/src/cgeo/geocaching/network/SmileyImage.java (limited to 'main') diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index 31edc9f..d531303 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -89,7 +89,7 @@ public class HtmlImage implements Html.ImageGetter { final private int maxWidth; final private int maxHeight; final private Resources resources; - final private TextView view; + protected final TextView view; // Background loading final private PublishSubject> loading = PublishSubject.create(); @@ -208,12 +208,7 @@ public class HtmlImage implements Html.ImageGetter { private Pair loadFromDisk() { final Pair loadResult = loadImageFromStorage(url, pseudoGeocode, shared); - final Bitmap bitmap = loadResult.getLeft(); - return new ImmutablePair<>(bitmap != null ? - ImageUtils.scaleBitmapToFitDisplay(bitmap) : - null, - loadResult.getRight() - ); + return scaleImage(loadResult); } private void downloadAndSave(final Subscriber subscriber) { @@ -254,6 +249,14 @@ public class HtmlImage implements Html.ImageGetter { }); } + protected Pair scaleImage(final Pair loadResult) { + final Bitmap bitmap = loadResult.getLeft(); + return new ImmutablePair<>(bitmap != null ? + ImageUtils.scaleBitmapToFitDisplay(bitmap) : + null, + loadResult.getRight()); + } + public Observable waitForEndObservable(@Nullable final CancellableHandler handler) { if (handler != null) { handler.unsubscribeIfCancelled(subscription); diff --git a/main/src/cgeo/geocaching/network/SmileyImage.java b/main/src/cgeo/geocaching/network/SmileyImage.java new file mode 100644 index 0000000..ebac2bb --- /dev/null +++ b/main/src/cgeo/geocaching/network/SmileyImage.java @@ -0,0 +1,34 @@ +package cgeo.geocaching.network; + +import cgeo.geocaching.list.StoredList; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.widget.TextView; + +public class SmileyImage extends HtmlImage { + + public SmileyImage(final String geocode, final TextView view) { + super(geocode, false, StoredList.STANDARD_LIST_ID, false, view); + } + + @Override + protected Pair scaleImage(final Pair loadResult) { + final Bitmap bitmap = loadResult.getLeft(); + BitmapDrawable drawable; + if (bitmap != null) { + final int lineHeight = (int) (view.getLineHeight() * 0.8); + drawable = new BitmapDrawable(view.getResources(), bitmap); + final int width = drawable.getIntrinsicWidth() * lineHeight / drawable.getIntrinsicHeight(); + drawable.setBounds(0, 0, width, lineHeight); + } + else { + drawable = null; + } + return new ImmutablePair<>(drawable, loadResult.getRight()); + } + +} diff --git a/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java index 9532946..e7b830e 100644 --- a/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java +++ b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java @@ -4,8 +4,7 @@ import cgeo.geocaching.ImagesActivity; import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.activity.AbstractActivity; -import cgeo.geocaching.list.StoredList; -import cgeo.geocaching.network.HtmlImage; +import cgeo.geocaching.network.SmileyImage; import cgeo.geocaching.ui.AbstractCachingListViewPageViewCreator; import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; import cgeo.geocaching.ui.DecryptTextClickListener; @@ -85,7 +84,7 @@ public abstract class LogsViewCreator extends AbstractCachingListViewPageViewCre if (TextUtils.containsHtml(logText)) { logText = log.getDisplayText(); final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler(); - holder.text.setText(Html.fromHtml(logText, new HtmlImage(getGeocode(), false, StoredList.STANDARD_LIST_ID, false, holder.text), + holder.text.setText(Html.fromHtml(logText, new SmileyImage(getGeocode(), holder.text), unknownTagsHandler), TextView.BufferType.SPANNABLE); } else { holder.text.setText(logText, TextView.BufferType.SPANNABLE); -- cgit v1.1 From f725bbe2ec07600b81b723a30782bc341fde984d Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 4 Aug 2014 20:37:52 +0200 Subject: Import Jackson libraries --- main/build.gradle | 9 ++++++++- main/libs/jackson-annotations-2.4.1.jar | Bin 0 -> 38604 bytes main/libs/jackson-annotations-2.4.1.jar.properties | 2 ++ main/libs/jackson-core-2.4.1.1.jar | Bin 0 -> 225356 bytes main/libs/jackson-core-2.4.1.1.jar.properties | 2 ++ main/libs/jackson-databind-2.4.1.3.jar | Bin 0 -> 1074135 bytes main/libs/jackson-databind-2.4.1.3.jar.properties | 2 ++ main/libs/src/jackson-annotations-2.4.1-javadoc.jar | Bin 0 -> 268648 bytes main/libs/src/jackson-annotations-2.4.1-sources.jar | Bin 0 -> 42638 bytes main/libs/src/jackson-core-2.4.1.1-javadoc.jar | Bin 0 -> 800071 bytes main/libs/src/jackson-core-2.4.1.1-sources.jar | Bin 0 -> 235209 bytes main/libs/src/jackson-databind-2.4.1.3-javadoc.jar | Bin 0 -> 4055002 bytes main/libs/src/jackson-databind-2.4.1.3-sources.jar | Bin 0 -> 770115 bytes main/proguard-project.txt | 3 +++ main/project/libraries/update-libs.sh | 10 ++++++++++ 15 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 main/libs/jackson-annotations-2.4.1.jar create mode 100644 main/libs/jackson-annotations-2.4.1.jar.properties create mode 100644 main/libs/jackson-core-2.4.1.1.jar create mode 100644 main/libs/jackson-core-2.4.1.1.jar.properties create mode 100644 main/libs/jackson-databind-2.4.1.3.jar create mode 100644 main/libs/jackson-databind-2.4.1.3.jar.properties create mode 100644 main/libs/src/jackson-annotations-2.4.1-javadoc.jar create mode 100644 main/libs/src/jackson-annotations-2.4.1-sources.jar create mode 100644 main/libs/src/jackson-core-2.4.1.1-javadoc.jar create mode 100644 main/libs/src/jackson-core-2.4.1.1-sources.jar create mode 100644 main/libs/src/jackson-databind-2.4.1.3-javadoc.jar create mode 100644 main/libs/src/jackson-databind-2.4.1.3-sources.jar (limited to 'main') diff --git a/main/build.gradle b/main/build.gradle index e4f60fe..325af71 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -28,6 +28,9 @@ gradle connectedCheck def AAVersion = '3.0.1' def RXVersion = '0.19.6' +def JacksonCoreVersion = '2.4.1.1' +def JacksonDatabindVersion = '2.4.1.3' +def JacksonAnnotationsVersion = '2.4.1' group = 'cgeo.geocaching' version = '0.0.1' @@ -162,6 +165,10 @@ dependencies { compile "com.netflix.rxjava:rxjava-android:$RXVersion" compile "com.netflix.rxjava:rxjava-async-util:$RXVersion" + compile "com.fasterxml.jackson.core:jackson-core:$JacksonCoreVersion" + compile "com.fasterxml.jackson.core:jackson-databind:$JacksonDatabindVersion" + compile "com.fasterxml.jackson.core:jackson-annotations:$JacksonAnnotationsVersion" + //TEST //compile files('compile-libs/androidannotations-3.0.1.jar') //compile files('compile-libs/findbugs-ant.jar') @@ -357,4 +364,4 @@ task addTest { // always do the addtest on prebuild gradle.projectsEvaluated { preBuild.dependsOn(addTest) -}*/ \ No newline at end of file +}*/ diff --git a/main/libs/jackson-annotations-2.4.1.jar b/main/libs/jackson-annotations-2.4.1.jar new file mode 100644 index 0000000..decd2d1 Binary files /dev/null and b/main/libs/jackson-annotations-2.4.1.jar differ diff --git a/main/libs/jackson-annotations-2.4.1.jar.properties b/main/libs/jackson-annotations-2.4.1.jar.properties new file mode 100644 index 0000000..710f903 --- /dev/null +++ b/main/libs/jackson-annotations-2.4.1.jar.properties @@ -0,0 +1,2 @@ +src=src/jackson-annotations-2.4.1-sources.jar +doc=src/jackson-annotations-2.4.1-javadoc.jar diff --git a/main/libs/jackson-core-2.4.1.1.jar b/main/libs/jackson-core-2.4.1.1.jar new file mode 100644 index 0000000..5fe10ae Binary files /dev/null and b/main/libs/jackson-core-2.4.1.1.jar differ diff --git a/main/libs/jackson-core-2.4.1.1.jar.properties b/main/libs/jackson-core-2.4.1.1.jar.properties new file mode 100644 index 0000000..0a3222e --- /dev/null +++ b/main/libs/jackson-core-2.4.1.1.jar.properties @@ -0,0 +1,2 @@ +src=src/jackson-core-2.4.1.1-sources.jar +doc=src/jackson-core-2.4.1.1-javadoc.jar diff --git a/main/libs/jackson-databind-2.4.1.3.jar b/main/libs/jackson-databind-2.4.1.3.jar new file mode 100644 index 0000000..231bd1f Binary files /dev/null and b/main/libs/jackson-databind-2.4.1.3.jar differ diff --git a/main/libs/jackson-databind-2.4.1.3.jar.properties b/main/libs/jackson-databind-2.4.1.3.jar.properties new file mode 100644 index 0000000..f4cc029 --- /dev/null +++ b/main/libs/jackson-databind-2.4.1.3.jar.properties @@ -0,0 +1,2 @@ +src=src/jackson-databind-2.4.1.3-sources.jar +doc=src/jackson-databind-2.4.1.3-javadoc.jar diff --git a/main/libs/src/jackson-annotations-2.4.1-javadoc.jar b/main/libs/src/jackson-annotations-2.4.1-javadoc.jar new file mode 100644 index 0000000..40bb9d2 Binary files /dev/null and b/main/libs/src/jackson-annotations-2.4.1-javadoc.jar differ diff --git a/main/libs/src/jackson-annotations-2.4.1-sources.jar b/main/libs/src/jackson-annotations-2.4.1-sources.jar new file mode 100644 index 0000000..f9e50a4 Binary files /dev/null and b/main/libs/src/jackson-annotations-2.4.1-sources.jar differ diff --git a/main/libs/src/jackson-core-2.4.1.1-javadoc.jar b/main/libs/src/jackson-core-2.4.1.1-javadoc.jar new file mode 100644 index 0000000..cfae85e Binary files /dev/null and b/main/libs/src/jackson-core-2.4.1.1-javadoc.jar differ diff --git a/main/libs/src/jackson-core-2.4.1.1-sources.jar b/main/libs/src/jackson-core-2.4.1.1-sources.jar new file mode 100644 index 0000000..0647e10 Binary files /dev/null and b/main/libs/src/jackson-core-2.4.1.1-sources.jar differ diff --git a/main/libs/src/jackson-databind-2.4.1.3-javadoc.jar b/main/libs/src/jackson-databind-2.4.1.3-javadoc.jar new file mode 100644 index 0000000..5bab5af Binary files /dev/null and b/main/libs/src/jackson-databind-2.4.1.3-javadoc.jar differ diff --git a/main/libs/src/jackson-databind-2.4.1.3-sources.jar b/main/libs/src/jackson-databind-2.4.1.3-sources.jar new file mode 100644 index 0000000..1bab3a5 Binary files /dev/null and b/main/libs/src/jackson-databind-2.4.1.3-sources.jar differ diff --git a/main/proguard-project.txt b/main/proguard-project.txt index 74b8aa2..c6e67fd 100644 --- a/main/proguard-project.txt +++ b/main/proguard-project.txt @@ -21,6 +21,9 @@ # rxjava internal references sun.misc.Unsafe -dontwarn sun.misc.Unsafe +# jackson internal references +-dontwarn org.w3c.dom.bootstrap.DOMImplementationRegistry + #-dontnote org.apache.commons.logging.** -keep public class cgeo.geocaching.* diff --git a/main/project/libraries/update-libs.sh b/main/project/libraries/update-libs.sh index f2e9ced..bdf25c4 100755 --- a/main/project/libraries/update-libs.sh +++ b/main/project/libraries/update-libs.sh @@ -2,6 +2,9 @@ # RXJAVA=0.19.6 +JACKSONCORE=2.4.1.1 +JACKSONDATABIND=2.4.1.3 +JACKSONANNOTATIONS=2.4.1 cd $(git rev-parse --show-toplevel)/main/libs @@ -31,3 +34,10 @@ updatelib com/netflix/rxjava rxjava-core $RXJAVA updatelib com/netflix/rxjava rxjava-android $RXJAVA updatelib com/netflix/rxjava rxjava-async-util $RXJAVA fixgradle RXVersion $RXJAVA + +updatelib com/fasterxml/jackson/core jackson-core $JACKSONCORE +fixgradle JacksonCoreVersion $JACKSONCORE +updatelib com/fasterxml/jackson/core jackson-databind $JACKSONDATABIND +fixgradle JacksonDatabindVersion $JACKSONDATABIND +updatelib com/fasterxml/jackson/core jackson-annotations $JACKSONANNOTATIONS +fixgradle JacksonAnnotationsVersion $JACKSONANNOTATIONS -- cgit v1.1 From 5fb26a1e173fd2c0fa461968dae38e8b4cdfc0c2 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 4 Aug 2014 21:17:35 +0200 Subject: Use Jackson for geocaching.com data parsing --- main/src/cgeo/geocaching/connector/gc/GCMap.java | 97 ++++++----- .../src/cgeo/geocaching/connector/gc/GCParser.java | 183 +++++++++------------ main/src/cgeo/geocaching/network/Network.java | 15 +- .../src/cgeo/geocaching/network/StatusUpdater.java | 23 +-- main/src/cgeo/geocaching/utils/JsonUtils.java | 20 +++ 5 files changed, 163 insertions(+), 175 deletions(-) create mode 100644 main/src/cgeo/geocaching/utils/JsonUtils.java (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java index c7318ce..bacaddb 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCMap.java +++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java @@ -9,6 +9,7 @@ import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; import cgeo.geocaching.enumerations.LiveMapStrategy.StrategyFlag; import cgeo.geocaching.enumerations.StatusCode; +import cgeo.geocaching.files.ParserException; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter.Format; import cgeo.geocaching.geopoint.Units; @@ -16,20 +17,23 @@ import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Formatter; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.LeastRecentlyUsedMap; import cgeo.geocaching.utils.Log; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; import rx.Observable; import rx.functions.Func2; import android.graphics.Bitmap; +import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; @@ -60,49 +64,41 @@ public class GCMap { // {"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"}}] // } - final JSONObject json = new JSONObject(data); - final String status = json.getString("status"); + final ObjectNode json = (ObjectNode) JsonUtils.reader.readTree(data); + final String status = json.path("status").asText(); if (StringUtils.isBlank(status)) { - - throw new JSONException("No status inside JSON"); + throw new ParserException("No status inside JSON"); } if ("success".compareTo(status) != 0) { - throw new JSONException("Wrong status inside JSON"); + throw new ParserException("Wrong status inside JSON"); } - final JSONArray dataArray = json.getJSONArray("data"); + final ArrayNode dataArray = (ArrayNode) json.get("data"); if (dataArray == null) { - throw new JSONException("No data inside JSON"); + throw new ParserException("No data inside JSON"); } final ArrayList caches = new ArrayList<>(); - for (int j = 0; j < dataArray.length(); j++) { + for (final JsonNode dataObject: dataArray) { final Geocache cache = new Geocache(); - - 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")); + cache.setName(dataObject.path("name").asText()); + cache.setGeocode(dataObject.path("gc").asText()); + cache.setGuid(dataObject.path("g").asText()); // 34c2e609-5246-4f91-9029-d6c02b0f2a82" + cache.setDisabled(!dataObject.path("available").asBoolean()); + cache.setArchived(dataObject.path("archived").asBoolean()); + cache.setPremiumMembersOnly(dataObject.path("subrOnly").asBoolean()); // "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(GCLogin.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.setOwnerDisplayName(ownerObj.getString("text")); + cache.setFavoritePoints(Integer.parseInt(dataObject.path("fp").asText())); + cache.setDifficulty(Float.parseFloat(dataObject.path("difficulty").path("text").asText())); // 3.5 + cache.setTerrain(Float.parseFloat(dataObject.path("terrain").path("text").asText())); // 1.5 + cache.setHidden(GCLogin.parseGcCustomDate(dataObject.path("hidden").asText(), "MM/dd/yyyy")); // 7/23/2001 + cache.setSize(CacheSize.getById(dataObject.path("container").path("text").asText())); // Regular + cache.setType(CacheType.getByPattern(dataObject.path("type").path("text").asText())); // Traditional Cache + cache.setOwnerDisplayName(dataObject.path("owner").path("text").asText()); caches.add(cache); } result.addAndPutInCache(caches); - } catch (JSONException | ParseException | NumberFormatException e) { + } catch (ParserException | ParseException | IOException | NumberFormatException ignore) { result.setError(StatusCode.UNKNOWN_ERROR); } return result; @@ -121,7 +117,7 @@ public class GCMap { final LeastRecentlyUsedMap nameCache = new LeastRecentlyUsedMap.LruCache<>(2000); // JSON id, cache name if (StringUtils.isEmpty(data)) { - throw new JSONException("No page given"); + throw new ParserException("No page given"); } // Example JSON information @@ -130,34 +126,33 @@ public class GCMap { // "data":{"55_55":[{"i":"gEaR","n":"Spiel & Sport"}],"55_54":[{"i":"gEaR","n":"Spiel & Sport"}],"17_25":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"55_53":[{"i":"gEaR","n":"Spiel & Sport"}],"17_27":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"17_26":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"57_53":[{"i":"gEaR","n":"Spiel & Sport"}],"57_55":[{"i":"gEaR","n":"Spiel & Sport"}],"3_62":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"3_61":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"57_54":[{"i":"gEaR","n":"Spiel & Sport"}],"3_60":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"15_27":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"15_26":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"15_25":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"4_60":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"4_61":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"4_62":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"16_25":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"16_26":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"16_27":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"2_62":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"2_60":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"2_61":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"56_53":[{"i":"gEaR","n":"Spiel & Sport"}],"56_54":[{"i":"gEaR","n":"Spiel & Sport"}],"56_55":[{"i":"gEaR","n":"Spiel & Sport"}]} // } - final JSONObject json = new JSONObject(data); + final ObjectNode json = (ObjectNode) JsonUtils.reader.readTree(data); - final JSONArray grid = json.getJSONArray("grid"); - if (grid == null || grid.length() != (UTFGrid.GRID_MAXY + 1)) { - throw new JSONException("No grid inside JSON"); + final ArrayNode grid = (ArrayNode) json.get("grid"); + if (grid == null || grid.size() != (UTFGrid.GRID_MAXY + 1)) { + throw new ParserException("No grid inside JSON"); } - final JSONArray keys = json.getJSONArray("keys"); + final ArrayNode keys = (ArrayNode) json.get("keys"); if (keys == null) { - throw new JSONException("No keys inside JSON"); + throw new ParserException("No keys inside JSON"); } - final JSONObject dataObject = json.getJSONObject("data"); + final ObjectNode dataObject = (ObjectNode) json.get("data"); if (dataObject == null) { - throw new JSONException("No data inside JSON"); + throw new ParserException("No data inside JSON"); } // iterate over the data and construct all caches in this tile Map> positions = new HashMap<>(); // JSON id as key Map> singlePositions = new HashMap<>(); // JSON id as key - for (int i = 1; i < keys.length(); i++) { // index 0 is empty - String key = keys.getString(i); - if (StringUtils.isNotBlank(key)) { + for (final JsonNode rawKey: keys) { + final String key = rawKey.asText(); + if (StringUtils.isNotBlank(key)) { // index 0 is empty UTFGridPosition pos = UTFGridPosition.fromString(key); - JSONArray dataForKey = dataObject.getJSONArray(key); - for (int j = 0; j < dataForKey.length(); j++) { - JSONObject cacheInfo = dataForKey.getJSONObject(j); - String id = cacheInfo.getString("i"); - nameCache.put(id, cacheInfo.getString("n")); + final ArrayNode dataForKey = (ArrayNode) dataObject.get(key); + for (final JsonNode cacheInfo: dataForKey) { + final String id = cacheInfo.get("i").asText(); + nameCache.put(id, cacheInfo.get("n").asText()); List listOfPositions = positions.get(id); List singleListOfPositions = singlePositions.get(id); @@ -170,7 +165,7 @@ public class GCMap { } listOfPositions.add(pos); - if (dataForKey.length() == 1) { + if (dataForKey.size() == 1) { singleListOfPositions.add(pos); } @@ -216,7 +211,7 @@ public class GCMap { searchResult.addAndPutInCache(caches); Log.d("Retrieved " + searchResult.getCount() + " caches for tile " + tile.toString()); - } catch (RuntimeException | JSONException e) { + } catch (RuntimeException | ParserException | IOException e) { Log.e("GCMap.parseMapJSON", e); } diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index f704da6..2b3aa11 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -30,6 +30,7 @@ import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.DirectionImage; import cgeo.geocaching.utils.CancellableHandler; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MatcherWrapper; import cgeo.geocaching.utils.RxUtils; @@ -38,15 +39,16 @@ import cgeo.geocaching.utils.TextUtils; import ch.boye.httpclientandroidlib.HttpResponse; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; import rx.Observable; import rx.Observable.OnSubscribe; @@ -59,6 +61,7 @@ import android.net.Uri; import android.text.Html; import java.io.File; +import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; @@ -126,11 +129,11 @@ public abstract class GCParser { page = page.substring(startPos + 1, endPos - startPos + 1); // cut between and
final String[] rows = StringUtils.splitByWholeSeparator(page, ""); @@ -933,27 +936,23 @@ public abstract class GCParser { Log.e("GCParser.searchByAddress: No address given"); return null; } - try { - final JSONObject response = Network.requestJSON("http://www.geocaching.com/api/geocode", new Parameters("q", address)); - if (response == null) { - return null; - } - if (!StringUtils.equalsIgnoreCase(response.getString("status"), "success")) { - return null; - } - if (!response.has("data")) { - return null; - } - final JSONObject data = response.getJSONObject("data"); - if (data == null) { - return null; - } - return searchByCoords(new Geopoint(data.getDouble("lat"), data.getDouble("lng")), cacheType, showCaptcha, recaptchaReceiver); - } catch (final JSONException e) { - Log.w("GCParser.searchByAddress", e); + + final ObjectNode response = Network.requestJSON("http://www.geocaching.com/api/geocode", new Parameters("q", address)); + if (response == null) { + return null; } - return null; + if (!StringUtils.equalsIgnoreCase(response.path("status").asText(), "success")) { + return null; + } + + final JsonNode data = response.path("data"); + final JsonNode latNode = data.get("lat"); + final JsonNode lngNode = data.get("lng"); + if (latNode == null || lngNode == null) { + return null; + } + return searchByCoords(new Geopoint(latNode.asDouble(), lngNode.asDouble()), cacheType, showCaptcha, recaptchaReceiver); } @Nullable @@ -1485,7 +1484,7 @@ public abstract class GCParser { } } catch (final RuntimeException e) { // failed to parse trackable owner name - Log.w("GCParser.parseTrackable: Failed to parse trackable owner name"); + Log.w("GCParser.parseTrackable: Failed to parse trackable owner name", e); } // trackable origin @@ -1516,7 +1515,7 @@ public abstract class GCParser { } } catch (final RuntimeException e) { // failed to parse trackable last known place - Log.w("GCParser.parseTrackable: Failed to parse trackable last known place"); + Log.w("GCParser.parseTrackable: Failed to parse trackable last known place", e); } // released date - can be missing on the page @@ -1524,12 +1523,12 @@ public abstract class GCParser { if (releaseString != null) { try { trackable.setReleased(dateTbIn1.parse(releaseString)); - } catch (final ParseException e) { + } catch (final ParseException ignore) { if (trackable.getReleased() == null) { try { trackable.setReleased(dateTbIn2.parse(releaseString)); - } catch (final ParseException e1) { - Log.e("Could not parse trackable release " + releaseString); + } catch (final ParseException e) { + Log.e("Could not parse trackable release " + releaseString, e); } } } @@ -1565,7 +1564,7 @@ public abstract class GCParser { } } catch (final RuntimeException e) { // failed to parse trackable details & image - Log.w("GCParser.parseTrackable: Failed to parse trackable details & image"); + Log.w("GCParser.parseTrackable: Failed to parse trackable details & image", e); } if (StringUtils.isEmpty(trackable.getDetails()) && page.contains(GCConstants.ERROR_TB_NOT_ACTIVATED)) { trackable.setDetails(CgeoApplication.getInstance().getString(R.string.trackable_not_activated)); @@ -1587,7 +1586,7 @@ public abstract class GCParser { long date = 0; try { date = GCLogin.parseGcCustomDate(matcherLogs.group(2)).getTime(); - } catch (final ParseException e) { + } catch (final ParseException ignore) { } final LogEntry logDone = new LogEntry( @@ -1725,56 +1724,51 @@ public abstract class GCParser { } try { - final JSONObject resp = new JSONObject(rawResponse); - if (!resp.getString("status").equals("success")) { - Log.e("GCParser.loadLogsFromDetails: status is " + resp.getString("status")); + final ObjectNode resp = (ObjectNode) JsonUtils.reader.readTree(rawResponse); + if (!resp.path("status").asText().equals("success")) { + Log.e("GCParser.loadLogsFromDetails: status is " + resp.path("status").asText("[absent]")); subscriber.onCompleted(); return; } - final JSONArray data = resp.getJSONArray("data"); - - for (int index = 0; index < data.length(); index++) { - final JSONObject entry = data.getJSONObject(index); - + final ArrayNode data = (ArrayNode) resp.get("data"); + for (final JsonNode entry: data) { // FIXME: use the "LogType" field instead of the "LogTypeImage" one. - final String logIconNameExt = entry.optString("LogTypeImage", ".gif"); + final String logIconNameExt = entry.path("LogTypeImage").asText(".gif"); final String logIconName = logIconNameExt.substring(0, logIconNameExt.length() - 4); long date = 0; try { - date = GCLogin.parseGcCustomDate(entry.getString("Visited")).getTime(); - } catch (final ParseException e) { - Log.e("GCParser.loadLogsFromDetails: failed to parse log date."); + date = GCLogin.parseGcCustomDate(entry.get("Visited").asText()).getTime(); + } catch (ParseException | NullPointerException e) { + Log.e("GCParser.loadLogsFromDetails: failed to parse log date", e); } // TODO: we should update our log data structure to be able to record // proper coordinates, and make them clickable. In the meantime, it is // better to integrate those coordinates into the text rather than not // display them at all. - final String latLon = entry.getString("LatLonString"); - final String logText = (StringUtils.isEmpty(latLon) ? "" : (latLon + "

")) + TextUtils.removeControlCharacters(entry.getString("LogText")); + final String latLon = entry.path("LatLonString").asText(); + final String logText = (StringUtils.isEmpty(latLon) ? "" : (latLon + "

")) + TextUtils.removeControlCharacters(entry.path("LogText").asText()); final LogEntry logDone = new LogEntry( - TextUtils.removeControlCharacters(entry.getString("UserName")), + TextUtils.removeControlCharacters(entry.path("UserName").asText()), date, LogType.getByIconName(logIconName), logText); - logDone.found = entry.getInt("GeocacheFindCount"); + logDone.found = entry.path("GeocacheFindCount").asInt(); logDone.friend = markAsFriendsLog; - final JSONArray images = entry.getJSONArray("Images"); - for (int i = 0; i < images.length(); i++) { - final JSONObject image = images.getJSONObject(i); - final String url = "http://imgcdn.geocaching.com/cache/log/large/" + image.getString("FileName"); - final String title = TextUtils.removeControlCharacters(image.getString("Name")); + final ArrayNode images = (ArrayNode) entry.get("Images"); + for (final JsonNode image: images) { + final String url = "http://imgcdn.geocaching.com/cache/log/large/" + image.path("FileName").asText(); + final String title = TextUtils.removeControlCharacters(image.path("Name").asText()); final Image logImage = new Image(url, title); logDone.addLogImage(logImage); } subscriber.onNext(logDone); } - } catch (final JSONException e) { - // failed to parse logs + } catch (final IOException e) { Log.w("GCParser.loadLogsFromDetails: Failed to parse cache logs", e); } subscriber.onCompleted(); @@ -1950,31 +1944,23 @@ public abstract class GCParser { return false; } - try { - JSONObject jo; - if (wpt != null) { - jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken) - .put("data", new JSONObject() - .put("lat", wpt.getLatitudeE6() / 1E6) - .put("lng", wpt.getLongitudeE6() / 1E6)))); - } else { - jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken))); - } - - final String uriSuffix = wpt != null ? "SetUserCoordinate" : "ResetUserCoordinate"; + final ObjectNode jo = new ObjectNode(JsonUtils.factory); + final ObjectNode dto = jo.putObject("dto").put("ut", userToken); + if (wpt != null) { + dto.putObject("data").put("lat", wpt.getLatitudeE6() / 1E6).put("lng", wpt.getLongitudeE6() / 1E6); + } - final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/"; - final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo); - Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString()); + final String uriSuffix = wpt != null ? "SetUserCoordinate" : "ResetUserCoordinate"; - if (response != null && response.getStatusLine().getStatusCode() == 200) { - Log.i("GCParser.editModifiedCoordinates - edited on GC.com"); - return true; - } + final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/"; + final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo); + Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString()); - } catch (final JSONException e) { - Log.e("Unknown exception with json wrap code", e); + if (response != null && response.getStatusLine().getStatusCode() == 200) { + Log.i("GCParser.editModifiedCoordinates - edited on GC.com"); + return true; } + Log.e("GCParser.deleteModifiedCoordinates - cannot delete modified coords"); return false; } @@ -1985,26 +1971,21 @@ public abstract class GCParser { return false; } - try { - final JSONObject jo = new JSONObject() - .put("dto", (new JSONObject() - .put("et", cache.getPersonalNote()) - .put("ut", userToken))); + final ObjectNode jo = new ObjectNode(JsonUtils.factory).putObject("dto") + .put("et", cache.getPersonalNote()) + .put("ut", userToken); - final String uriSuffix = "SetUserCacheNote"; + final String uriSuffix = "SetUserCacheNote"; - final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/"; - final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo); - Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString()); + final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/"; + final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo); + Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString()); - if (response != null && response.getStatusLine().getStatusCode() == 200) { - Log.i("GCParser.uploadPersonalNote - uploaded to GC.com"); - return true; - } - - } catch (final JSONException e) { - Log.e("Unknown exception with json wrap code", e); + if (response != null && response.getStatusLine().getStatusCode() == 200) { + Log.i("GCParser.uploadPersonalNote - uploaded to GC.com"); + return true; } + Log.e("GCParser.uploadPersonalNote - cannot upload personal note"); return false; } diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java index 5309923..40f7f7e 100644 --- a/main/src/cgeo/geocaching/network/Network.java +++ b/main/src/cgeo/geocaching/network/Network.java @@ -2,6 +2,7 @@ package cgeo.geocaching.network; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.TextUtils; @@ -27,11 +28,11 @@ import ch.boye.httpclientandroidlib.params.CoreProtocolPNames; import ch.boye.httpclientandroidlib.params.HttpParams; import ch.boye.httpclientandroidlib.util.EntityUtils; +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONException; -import org.json.JSONObject; import android.content.Context; import android.net.ConnectivityManager; @@ -109,7 +110,7 @@ public abstract class Network { * @return the HTTP response, or null in case of an encoding error params */ @Nullable - public static HttpResponse postJsonRequest(final String uri, final JSONObject json) { + public static HttpResponse postJsonRequest(final String uri, final ObjectNode json) { HttpPost request = new HttpPost(uri); request.addHeader("Content-Type", "application/json; charset=utf-8"); if (json != null) { @@ -346,14 +347,14 @@ public abstract class Network { * @return a JSON object if the request was successful and the body could be decoded, null otherwise */ @Nullable - public static JSONObject requestJSON(final String uri, @Nullable final Parameters params) { + public static ObjectNode requestJSON(final String uri, @Nullable final Parameters params) { final HttpResponse response = request("GET", uri, params, new Parameters("Accept", "application/json, text/javascript, */*; q=0.01"), null); final String responseData = getResponseData(response, false); if (responseData != null) { try { - return new JSONObject(responseData); - } catch (final JSONException e) { - Log.w("Network.requestJSON", e); + return (ObjectNode) JsonUtils.reader.readTree(responseData); + } catch (final IOException e) { + Log.w("requestJSON", e); } } diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java index 82650d1..bc4a5db 100644 --- a/main/src/cgeo/geocaching/network/StatusUpdater.java +++ b/main/src/cgeo/geocaching/network/StatusUpdater.java @@ -4,8 +4,7 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.utils.RxUtils; import cgeo.geocaching.utils.Version; -import org.json.JSONException; -import org.json.JSONObject; +import com.fasterxml.jackson.databind.node.ObjectNode; import rx.functions.Action0; import rx.subjects.BehaviorSubject; @@ -31,11 +30,11 @@ public class StatusUpdater { this.url = url; } - Status(final JSONObject response) { - message = get(response, "message"); - messageId = get(response, "message_id"); - icon = get(response, "icon"); - url = get(response, "url"); + Status(final ObjectNode response) { + message = response.path("message").asText(null); + messageId = response.path("message_id").asText(null); + icon = response.path("icon").asText(null); + url = response.path("url").asText(null); } final static public Status closeoutStatus = @@ -55,7 +54,7 @@ public class StatusUpdater { RxUtils.networkScheduler.createWorker().schedulePeriodically(new Action0() { @Override public void call() { - final JSONObject response = + final ObjectNode response = Network.requestJSON("http://status.cgeo.org/api/status.json", new Parameters("version_code", String.valueOf(Version.getVersionCode(CgeoApplication.getInstance())), "version_name", Version.getVersionName(CgeoApplication.getInstance()), @@ -67,12 +66,4 @@ public class StatusUpdater { }, 0, 1800, TimeUnit.SECONDS); } - private static String get(final JSONObject json, final String key) { - try { - return json.getString(key); - } catch (final JSONException e) { - return null; - } - } - } diff --git a/main/src/cgeo/geocaching/utils/JsonUtils.java b/main/src/cgeo/geocaching/utils/JsonUtils.java new file mode 100644 index 0000000..492e137 --- /dev/null +++ b/main/src/cgeo/geocaching/utils/JsonUtils.java @@ -0,0 +1,20 @@ +package cgeo.geocaching.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; + +public class JsonUtils { + + private static final ObjectMapper mapper = new ObjectMapper(); + public static final ObjectReader reader = mapper.reader(); + public static final ObjectWriter writer = mapper.writer(); + + public static final JsonNodeFactory factory = new JsonNodeFactory(true); + + private JsonUtils() { + // Do not instantiate + } + +} -- cgit v1.1 From 269a24bb8d0bb8e85fbf15526854b32175c84f1b Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 4 Aug 2014 23:49:25 +0200 Subject: Use Jackson for EC connector --- main/src/cgeo/geocaching/connector/ec/ECApi.java | 49 +++++++++++----------- main/src/cgeo/geocaching/connector/ec/ECLogin.java | 18 ++++---- 2 files changed, 36 insertions(+), 31 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/ec/ECApi.java b/main/src/cgeo/geocaching/connector/ec/ECApi.java index a0da825..ae266fa 100644 --- a/main/src/cgeo/geocaching/connector/ec/ECApi.java +++ b/main/src/cgeo/geocaching/connector/ec/ECApi.java @@ -14,22 +14,24 @@ import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.list.StoredList; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.SynchronizedDateFormat; import ch.boye.httpclientandroidlib.HttpResponse; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import java.util.ArrayList; +import java.io.IOException; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; +import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.TimeZone; @@ -175,42 +177,41 @@ public class ECApi { if (StringUtils.isBlank(data) || StringUtils.equals(data, "[]")) { return Collections.emptyList(); } - final JSONArray json = new JSONArray(data); - final int len = json.length(); - final List caches = new ArrayList<>(len); - for (int i = 0; i < len; i++) { - final Geocache cache = parseCache(json.getJSONObject(i)); + final ArrayNode json = (ArrayNode) JsonUtils.reader.readTree(data); + final List caches = new LinkedList<>(); + for (final JsonNode node: json) { + final Geocache cache = parseCache(node); if (cache != null) { caches.add(cache); } } return caches; - } catch (final JSONException e) { - Log.w("JSONResult", e); + } catch (IOException | ClassCastException e) { + Log.w("importCachesFromJSON", e); } } return Collections.emptyList(); } - private static Geocache parseCache(final JSONObject response) { - final Geocache cache = new Geocache(); - cache.setReliableLatLon(true); + private static Geocache parseCache(final JsonNode response) { try { - cache.setGeocode("EC" + response.getString("cache_id")); - cache.setName(response.getString("title")); - cache.setCoords(new Geopoint(response.getString("lat"), response.getString("lon"))); - cache.setType(getCacheType(response.getString("type"))); - cache.setDifficulty((float) response.getDouble("difficulty")); - cache.setTerrain((float) response.getDouble("terrain")); - cache.setSize(CacheSize.getById(response.getString("size"))); - cache.setFound(response.getInt("found") == 1); + final Geocache cache = new Geocache(); + cache.setReliableLatLon(true); + cache.setGeocode("EC" + response.get("cache_id").asText()); + cache.setName(response.get("title").asText()); + cache.setCoords(new Geopoint(response.get("lat").asText(), response.get("lon").asText())); + cache.setType(getCacheType(response.get("type").asText())); + cache.setDifficulty((float) response.get("difficulty").asDouble()); + cache.setTerrain((float) response.get("terrain").asDouble()); + cache.setSize(CacheSize.getById(response.get("size").asText())); + cache.setFound(response.get("found").asInt() == 1); DataStore.saveCache(cache, EnumSet.of(SaveFlag.CACHE)); - } catch (final JSONException e) { + return cache; + } catch (final NullPointerException e) { Log.e("ECApi.parseCache", e); return null; } - return cache; } private static CacheType getCacheType(final String cacheType) { diff --git a/main/src/cgeo/geocaching/connector/ec/ECLogin.java b/main/src/cgeo/geocaching/connector/ec/ECLogin.java index 67ca28f..35c2db4 100644 --- a/main/src/cgeo/geocaching/connector/ec/ECLogin.java +++ b/main/src/cgeo/geocaching/connector/ec/ECLogin.java @@ -7,14 +7,18 @@ import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import ch.boye.httpclientandroidlib.HttpResponse; + +import com.fasterxml.jackson.databind.JsonNode; + import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONException; -import org.json.JSONObject; + +import java.io.IOException; public class ECLogin extends AbstractLogin { @@ -93,18 +97,18 @@ public class ECLogin extends AbstractLogin { setActualStatus(app.getString(R.string.init_login_popup_ok)); try { - final JSONObject json = new JSONObject(data); + final JsonNode json = JsonUtils.reader.readTree(data); - final String sid = json.getString("sid"); + final String sid = json.get("sid").asText(); if (!StringUtils.isBlank(sid)) { sessionId = sid; setActualLoginStatus(true); - setActualUserName(json.getString("username")); - setActualCachesFound(json.getInt("found")); + setActualUserName(json.get("username").asText()); + setActualCachesFound(json.get("found").asInt()); return true; } resetLoginStatus(); - } catch (final JSONException e) { + } catch (IOException | NullPointerException e) { Log.e("ECLogin.getLoginStatus", e); } -- cgit v1.1 From 1ca3c38f4dc62115feb54b9fcb66dd0de44af8fd Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 5 Aug 2014 00:39:36 +0200 Subject: Use Jackson for Okapi connector --- .../cgeo/geocaching/connector/oc/OkapiClient.java | 276 +++++++++------------ .../cgeo/geocaching/connector/oc/OkapiError.java | 14 +- 2 files changed, 126 insertions(+), 164 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java index dde2bbb..300112a 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java @@ -30,20 +30,24 @@ import cgeo.geocaching.network.OAuth; import cgeo.geocaching.network.OAuthTokens; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.SynchronizedDateFormat; import ch.boye.httpclientandroidlib.HttpResponse; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; import android.net.Uri; +import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; @@ -211,10 +215,15 @@ final class OkapiClient { } addFilterParams(valueMap, connector, my); - params.add("search_params", new JSONObject(valueMap).toString()); + try { + params.add("search_params", JsonUtils.writer.writeValueAsString(params)); + } catch (final JsonProcessingException e) { + Log.e("requestCaches", e); + return Collections.emptyList(); + } addRetrieveParams(params, connector); - final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params).data; + final ObjectNode data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params).data; if (data == null) { return Collections.emptyList(); @@ -247,7 +256,7 @@ final class OkapiClient { final Parameters params = new Parameters("cache_code", cache.getGeocode()); params.add("watched", watched ? "true" : "false"); - final JSONObject data = request(connector, OkapiService.SERVICE_MARK_CACHE, params).data; + final ObjectNode data = request(connector, OkapiService.SERVICE_MARK_CACHE, params).data; if (data == null) { return false; @@ -271,68 +280,62 @@ final class OkapiClient { params.add("password", logPassword); } - final JSONObject data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params).data; + final ObjectNode data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params).data; if (data == null) { return new LogResult(StatusCode.LOG_POST_ERROR, ""); } try { - if (data.getBoolean("success")) { - return new LogResult(StatusCode.NO_ERROR, data.getString("log_uuid")); + if (data.get("success").asBoolean()) { + return new LogResult(StatusCode.NO_ERROR, data.get("log_uuid").asText()); } return new LogResult(StatusCode.LOG_POST_ERROR, ""); - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.postLog", e); } return new LogResult(StatusCode.LOG_POST_ERROR, ""); } - private static List parseCaches(final JSONObject response) { + private static List parseCaches(final ObjectNode response) { try { // Check for empty result - final String result = response.getString("results"); + final String result = response.get("results").asText(); if (StringUtils.isBlank(result) || StringUtils.equals(result, "[]")) { return Collections.emptyList(); } // Get and iterate result list - final JSONObject cachesResponse = response.getJSONObject("results"); + final ObjectNode cachesResponse = (ObjectNode) response.get("results"); if (cachesResponse != null) { - final List caches = new ArrayList<>(cachesResponse.length()); - final Iterator keys = cachesResponse.keys(); - while (keys.hasNext()) { - final Object next = keys.next(); - if (next instanceof String) { - final String key = (String) next; - final Geocache cache = parseSmallCache(cachesResponse.getJSONObject(key)); - caches.add(cache); - } + final List caches = new ArrayList<>(cachesResponse.size()); + final Iterator it = cachesResponse.elements(); + while (it.hasNext()) { + caches.add(parseSmallCache((ObjectNode) it.next())); } return caches; } - } catch (final JSONException e) { + } catch (ClassCastException | NullPointerException e) { Log.e("OkapiClient.parseCachesResult", e); } return Collections.emptyList(); } - private static Geocache parseSmallCache(final JSONObject response) { + private static Geocache parseSmallCache(final ObjectNode response) { final Geocache cache = new Geocache(); cache.setReliableLatLon(true); try { - parseCoreCache(response, cache); - DataStore.saveCache(cache, EnumSet.of(SaveFlag.CACHE)); - } catch (final JSONException e) { + } catch (final NullPointerException e) { + // FIXME: here we may return a partially filled cache Log.e("OkapiClient.parseSmallCache", e); } return cache; } - private static Geocache parseCache(final JSONObject response) { + private static Geocache parseCache(final ObjectNode response) { final Geocache cache = new Geocache(); cache.setReliableLatLon(true); try { @@ -340,28 +343,27 @@ final class OkapiClient { parseCoreCache(response, cache); // not used: url - final JSONObject ownerObject = response.getJSONObject(CACHE_OWNER); - final String owner = parseUser(ownerObject); + final String owner = parseUser(response.get(CACHE_OWNER)); cache.setOwnerDisplayName(owner); // OpenCaching has no distinction between user id and user display name. Set the ID anyway to simplify c:geo workflows. cache.setOwnerUserId(owner); - cache.getLogCounts().put(LogType.FOUND_IT, response.getInt(CACHE_FOUNDS)); - cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.getInt(CACHE_NOTFOUNDS)); + cache.getLogCounts().put(LogType.FOUND_IT, response.get(CACHE_FOUNDS).asInt()); + cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.get(CACHE_NOTFOUNDS).asInt()); // only current Api - cache.getLogCounts().put(LogType.WILL_ATTEND, response.optInt(CACHE_WILLATTENDS)); + cache.getLogCounts().put(LogType.WILL_ATTEND, response.path(CACHE_WILLATTENDS).asInt()); - if (!response.isNull(CACHE_RATING)) { - cache.setRating((float) response.getDouble(CACHE_RATING)); + if (response.has(CACHE_RATING)) { + cache.setRating((float) response.get(CACHE_RATING).asDouble()); } - cache.setVotes(response.getInt(CACHE_VOTES)); + cache.setVotes(response.get(CACHE_VOTES).asInt()); - cache.setFavoritePoints(response.getInt(CACHE_RECOMMENDATIONS)); + cache.setFavoritePoints(response.get(CACHE_RECOMMENDATIONS).asInt()); // not used: req_password // Prepend gc-link to description if available final StringBuilder description = new StringBuilder(500); - if (!response.isNull("gc_code")) { - final String gccode = response.getString("gc_code"); + if (response.has("gc_code")) { + final String gccode = response.get("gc_code").asText(); description.append(CgeoApplication.getInstance().getResources() .getString(R.string.cache_listed_on, GCConnector.getInstance().getName())) .append(":


"); } - description.append(response.getString(CACHE_DESCRIPTION)); + description.append(response.get(CACHE_DESCRIPTION).asText()); cache.setDescription(description.toString()); // currently the hint is delivered as HTML (contrary to OKAPI documentation), so we can store it directly - cache.setHint(response.getString(CACHE_HINT)); + cache.setHint(response.get(CACHE_HINT).asText()); // not used: hints - final JSONArray images = response.getJSONArray(CACHE_IMAGES); + final ArrayNode images = (ArrayNode) response.get(CACHE_IMAGES); if (images != null) { - for (int i = 0; i < images.length(); i++) { - final JSONObject imageResponse = images.getJSONObject(i); - final String title = imageResponse.getString(CACHE_IMAGE_CAPTION); - final String url = absoluteUrl(imageResponse.getString(CACHE_IMAGE_URL), cache.getGeocode()); + for (final JsonNode imageResponse: images) { + final String title = imageResponse.get(CACHE_IMAGE_CAPTION).asText(); + final String url = absoluteUrl(imageResponse.get(CACHE_IMAGE_URL).asText(), cache.getGeocode()); // all images are added as spoiler images, although OKAPI has spoiler and non spoiler images cache.addSpoiler(new Image(url, title)); } } - cache.setAttributes(parseAttributes(response.getJSONArray(CACHE_ATTRNAMES), response.optJSONArray(CACHE_ATTR_ACODES))); + cache.setAttributes(parseAttributes((ArrayNode) response.path(CACHE_ATTRNAMES), (ArrayNode) response.get(CACHE_ATTR_ACODES))); //TODO: Store license per cache //cache.setLicense(response.getString("attribution_note")); - cache.setWaypoints(parseWaypoints(response.getJSONArray(CACHE_WPTS)), false); + cache.setWaypoints(parseWaypoints((ArrayNode) response.path(CACHE_WPTS)), false); - cache.setInventory(parseTrackables(response.getJSONArray(CACHE_TRACKABLES))); + cache.setInventory(parseTrackables((ArrayNode) response.path(CACHE_TRACKABLES))); - if (!response.isNull(CACHE_IS_WATCHED)) { - cache.setOnWatchlist(response.getBoolean(CACHE_IS_WATCHED)); + if (response.has(CACHE_IS_WATCHED)) { + cache.setOnWatchlist(response.get(CACHE_IS_WATCHED).asBoolean()); } - if (!response.isNull(CACHE_MY_NOTES)) { - cache.setPersonalNote(response.getString(CACHE_MY_NOTES)); + if (response.has(CACHE_MY_NOTES)) { + cache.setPersonalNote(response.get(CACHE_MY_NOTES).asText()); cache.parseWaypointsFromNote(); } - cache.setLogPasswordRequired(response.getBoolean(CACHE_REQ_PASSWORD)); + cache.setLogPasswordRequired(response.get(CACHE_REQ_PASSWORD).asBoolean()); cache.setDetailedUpdatedNow(); // save full detailed caches DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); - DataStore.saveLogsWithoutTransaction(cache.getGeocode(), parseLogs(response.getJSONArray(CACHE_LATEST_LOGS))); - } catch (final JSONException e) { + DataStore.saveLogsWithoutTransaction(cache.getGeocode(), parseLogs((ArrayNode) response.path(CACHE_LATEST_LOGS))); + } catch (ClassCastException | NullPointerException e) { Log.e("OkapiClient.parseCache", e); } return cache; } - private static void parseCoreCache(final JSONObject response, final Geocache cache) throws JSONException { - cache.setGeocode(response.getString(CACHE_CODE)); - cache.setName(response.getString(CACHE_NAME)); + private static void parseCoreCache(final ObjectNode response, final Geocache cache) { + cache.setGeocode(response.get(CACHE_CODE).asText()); + cache.setName(response.get(CACHE_NAME).asText()); // not used: names - setLocation(cache, response.getString(CACHE_LOCATION)); - cache.setType(getCacheType(response.getString(CACHE_TYPE))); + setLocation(cache, response.get(CACHE_LOCATION).asText()); + cache.setType(getCacheType(response.get(CACHE_TYPE).asText())); - final String status = response.getString(CACHE_STATUS); + final String status = response.get(CACHE_STATUS).asText(); cache.setDisabled(status.equalsIgnoreCase(CACHE_STATUS_DISABLED)); cache.setArchived(status.equalsIgnoreCase(CACHE_STATUS_ARCHIVED)); cache.setSize(getCacheSize(response)); - cache.setDifficulty((float) response.getDouble(CACHE_DIFFICULTY)); - cache.setTerrain((float) response.getDouble(CACHE_TERRAIN)); + cache.setDifficulty((float) response.get(CACHE_DIFFICULTY).asDouble()); + cache.setTerrain((float) response.get(CACHE_TERRAIN).asDouble()); - cache.setInventoryItems(response.getInt(CACHE_TRACKABLES_COUNT)); + cache.setInventoryItems(response.get(CACHE_TRACKABLES_COUNT).asInt()); - if (!response.isNull(CACHE_IS_FOUND)) { - cache.setFound(response.getBoolean(CACHE_IS_FOUND)); + if (response.has(CACHE_IS_FOUND)) { + cache.setFound(response.get(CACHE_IS_FOUND).asBoolean()); } - cache.setHidden(parseDate(response.getString(CACHE_HIDDEN))); + cache.setHidden(parseDate(response.get(CACHE_HIDDEN).asText())); } private static String absoluteUrl(final String url, final String geocode) { @@ -450,41 +451,39 @@ final class OkapiClient { return url; } - private static String parseUser(final JSONObject user) throws JSONException { - return user.getString(USER_USERNAME); + private static String parseUser(final JsonNode user) { + return user.get(USER_USERNAME).asText(); } - private static List parseLogs(final JSONArray logsJSON) { + private static List parseLogs(final ArrayNode logsJSON) { List result = null; - for (int i = 0; i < logsJSON.length(); i++) { + for (final JsonNode logResponse: logsJSON) { try { - final JSONObject logResponse = logsJSON.getJSONObject(i); final LogEntry log = new LogEntry( - parseUser(logResponse.getJSONObject(LOG_USER)), - parseDate(logResponse.getString(LOG_DATE)).getTime(), - parseLogType(logResponse.getString(LOG_TYPE)), - logResponse.getString(LOG_COMMENT).trim()); + parseUser(logResponse.get(LOG_USER)), + parseDate(logResponse.get(LOG_DATE).asText()).getTime(), + parseLogType(logResponse.get(LOG_TYPE).asText()), + logResponse.get(LOG_COMMENT).asText().trim()); if (result == null) { result = new ArrayList<>(); } result.add(log); - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.parseLogs", e); } } return result; } - private static List parseWaypoints(final JSONArray wptsJson) { + private static List parseWaypoints(final ArrayNode wptsJson) { List result = null; - for (int i = 0; i < wptsJson.length(); i++) { + for (final JsonNode wptResponse: wptsJson) { try { - final JSONObject wptResponse = wptsJson.getJSONObject(i); - final Waypoint wpt = new Waypoint(wptResponse.getString(WPT_NAME), - parseWptType(wptResponse.getString(WPT_TYPE)), + final Waypoint wpt = new Waypoint(wptResponse.get(WPT_NAME).asText(), + parseWptType(wptResponse.get(WPT_TYPE).asText()), false); - wpt.setNote(wptResponse.getString(WPT_DESCRIPTION)); - final Geopoint pt = parseCoords(wptResponse.getString(WPT_LOCATION)); + wpt.setNote(wptResponse.get(WPT_DESCRIPTION).asText()); + final Geopoint pt = parseCoords(wptResponse.get(WPT_LOCATION).asText()); if (pt != null) { wpt.setCoords(pt); } @@ -493,26 +492,25 @@ final class OkapiClient { } wpt.setPrefix(wpt.getName()); result.add(wpt); - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.parseWaypoints", e); } } return result; } - private static List parseTrackables(final JSONArray trackablesJson) { - if (trackablesJson.length() == 0) { + private static List parseTrackables(final ArrayNode trackablesJson) { + if (trackablesJson.size() == 0) { return Collections.emptyList(); } final List result = new ArrayList<>(); - for (int i = 0; i < trackablesJson.length(); i++) { + for (final JsonNode trackableResponse: trackablesJson) { try { - final JSONObject trackableResponse = trackablesJson.getJSONObject(i); final Trackable trk = new Trackable(); - trk.setGeocode(trackableResponse.getString(TRK_GEOCODE)); - trk.setName(trackableResponse.getString(TRK_NAME)); + trk.setGeocode(trackableResponse.get(TRK_GEOCODE).asText()); + trk.setName(trackableResponse.get(TRK_NAME).asText()); result.add(trk); - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.parseWaypoints", e); // Don't overwrite internal state with possibly partial result return null; @@ -600,14 +598,14 @@ final class OkapiClient { return null; } - private static List parseAttributes(final JSONArray nameList, final JSONArray acodeList) { + private static List parseAttributes(final ArrayNode nameList, final ArrayNode acodeList) { final List result = new ArrayList<>(); - for (int i = 0; i < nameList.length(); i++) { + for (int i = 0; i < nameList.size(); i++) { try { - final String name = nameList.getString(i); - final int acode = acodeList != null ? Integer.parseInt(acodeList.getString(i).substring(1)) : CacheAttribute.NO_ID; + final String name = nameList.get(i).asText(); + final int acode = acodeList != null ? Integer.parseInt(acodeList.get(i).asText().substring(1)) : CacheAttribute.NO_ID; final CacheAttribute attr = CacheAttribute.getByOcACode(acode); if (attr != null) { @@ -615,7 +613,7 @@ final class OkapiClient { } else { result.add(name); } - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.parseAttributes", e); } } @@ -629,27 +627,27 @@ final class OkapiClient { cache.setCoords(new Geopoint(latitude, longitude)); } - private static CacheSize getCacheSize(final JSONObject response) { - if (response.isNull(CACHE_SIZE2)) { + private static CacheSize getCacheSize(final ObjectNode response) { + if (!response.has(CACHE_SIZE2)) { return getCacheSizeDeprecated(response); } try { - final String size = response.getString(CACHE_SIZE2); + final String size = response.get(CACHE_SIZE2).asText(); return CacheSize.getById(size); - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.getCacheSize", e); return getCacheSizeDeprecated(response); } } - private static CacheSize getCacheSizeDeprecated(final JSONObject response) { - if (response.isNull(CACHE_SIZE_DEPRECATED)) { + private static CacheSize getCacheSizeDeprecated(final ObjectNode response) { + if (!response.has(CACHE_SIZE_DEPRECATED)) { return CacheSize.NOT_CHOSEN; } double size = 0; try { - size = response.getDouble(CACHE_SIZE_DEPRECATED); - } catch (final JSONException e) { + size = response.get(CACHE_SIZE_DEPRECATED).asDouble(); + } catch (final NullPointerException e) { Log.e("OkapiClient.getCacheSize", e); } switch ((int) Math.round(size)) { @@ -818,16 +816,7 @@ final class OkapiClient { return null; } - final JSONObject data = result.data; - if (!data.isNull(USER_UUID)) { - try { - return data.getString(USER_UUID); - } catch (final JSONException e) { - Log.e("OkapiClient.getUserUUID - uuid", e); - } - } - - return null; + return result.data.path(USER_UUID).asText(null); } public static UserInfo getUserInfo(final OCApiLiveConnector connector) { @@ -841,31 +830,11 @@ final class OkapiClient { return new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.getFromOkapiError(error.getResult())); } - final JSONObject data = result.data; - - String name = StringUtils.EMPTY; - boolean successUserName = false; - - if (!data.isNull(USER_USERNAME)) { - try { - name = data.getString(USER_USERNAME); - successUserName = true; - } catch (final JSONException e) { - Log.e("OkapiClient.getUserInfo - name", e); - } - } - - int finds = 0; - boolean successFinds = false; - - if (!data.isNull(USER_CACHES_FOUND)) { - try { - finds = data.getInt(USER_CACHES_FOUND); - successFinds = true; - } catch (final JSONException e) { - Log.e("OkapiClient.getUserInfo - finds", e); - } - } + final ObjectNode data = result.data; + final boolean successUserName = data.has(USER_USERNAME); + final String name = data.path(USER_USERNAME).asText(); + final boolean successFinds = data.has(USER_CACHES_FOUND); + final int finds = data.path(USER_CACHES_FOUND).asInt(); return new UserInfo(name, finds, successUserName && successFinds ? UserInfoStatus.SUCCESSFUL : UserInfoStatus.FAILED); } @@ -882,7 +851,7 @@ final class OkapiClient { if (!result.isSuccess) { return new OkapiError(result.data); } - return new OkapiError(new JSONObject()); + return new OkapiError(new ObjectNode(JsonUtils.factory)); } /** @@ -892,33 +861,26 @@ final class OkapiClient { private static class JSONResult { public final boolean isSuccess; - public final JSONObject data; + public final ObjectNode data; public JSONResult(final @Nullable HttpResponse response) { - final boolean isSuccess = Network.isSuccess(response); + final boolean isRequestSuccessful = Network.isSuccess(response); final String responseData = Network.getResponseDataAlways(response); - JSONObject data = null; + ObjectNode tempData = null; if (responseData != null) { try { - data = new JSONObject(responseData); - } catch (final JSONException e) { + tempData = (ObjectNode) JsonUtils.reader.readTree(responseData); + } catch (IOException | ClassCastException e) { Log.w("JSONResult", e); } } - this.data = data; - this.isSuccess = isSuccess && data != null; + data = tempData; + isSuccess = isRequestSuccessful && tempData != null; } public JSONResult(final @NonNull String errorMessage) { isSuccess = false; - data = new JSONObject(); - final JSONObject error = new JSONObject(); - try { - error.put("developer_message", errorMessage); - data.put("error", error); - } catch (final JSONException e) { - Log.e("error creating JSON result error message", e); - } + data = new ObjectNode(JsonUtils.factory).putObject("error").put("developer_message", errorMessage); } } } diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiError.java b/main/src/cgeo/geocaching/connector/oc/OkapiError.java index 7faf2c7..b847207 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiError.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiError.java @@ -2,11 +2,11 @@ package cgeo.geocaching.connector.oc; import cgeo.geocaching.utils.Log; +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONException; -import org.json.JSONObject; /** * Handles the JSON error response from OKAPI @@ -26,7 +26,7 @@ public class OkapiError { @NonNull private final OkapiErrors state; @NonNull private final String message; - public OkapiError(@Nullable JSONObject data) { + public OkapiError(@Nullable ObjectNode data) { // A null-response is by definition an error (some exception occurred somewhere in the flow) if (data == null) { @@ -39,10 +39,10 @@ public class OkapiError { String localmessage = null; OkapiErrors localstate = OkapiErrors.UNSPECIFIED; try { - JSONObject error = data.getJSONObject("error"); + final ObjectNode error = (ObjectNode) data.get("error"); // Check reason_stack element to look for the specific oauth problems we want to report back if (error.has("reason_stack")) { - String reason = error.getString("reason_stack"); + final String reason = error.get("reason_stack").asText(); if (StringUtils.contains(reason, "invalid_oauth_request")) { if (StringUtils.contains(reason, "invalid_timestamp")) { localstate = OkapiErrors.INVALID_TIMESTAMP; @@ -53,10 +53,10 @@ public class OkapiError { } // Check if we can extract a message as well if (error.has("developer_message")) { - localmessage = error.getString("developer_message"); + localmessage = error.get("developer_message").asText(); assert localmessage != null; // by virtue of defaultString } - } catch (JSONException ex) { + } catch (ClassCastException | NullPointerException ex) { Log.d("OkapiError: Failed to parse JSON", ex); localstate = OkapiErrors.UNSPECIFIED; } -- cgit v1.1 From 71734c4b0734d4db83e324cf1ec09319cb09019d Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Tue, 5 Aug 2014 08:17:12 +0200 Subject: avoid false optimization hint in eclipse --- main/src/cgeo/geocaching/network/HtmlImage.java | 1 + 1 file changed, 1 insertion(+) (limited to 'main') diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index d531303..4a5c506 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -249,6 +249,7 @@ public class HtmlImage implements Html.ImageGetter { }); } + @SuppressWarnings("static-method") protected Pair scaleImage(final Pair loadResult) { final Bitmap bitmap = loadResult.getLeft(); return new ImmutablePair<>(bitmap != null ? -- cgit v1.1 From 8fcc2adc388892729d326a465a06e0ba348e9c0b Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 5 Aug 2014 12:11:28 +0200 Subject: Redraw circle around user location at every accuracy change --- main/src/cgeo/geocaching/maps/CGeoMap.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index c373d3f..4b3132f 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -938,16 +938,16 @@ public class CGeoMap extends AbstractMap implements ViewFactory { try { final CGeoMap map = mapRef.get(); if (map != null) { - final boolean needsRepaintForDistance = needsRepaintForDistance(); + final boolean needsRepaintForDistanceOrAccuracy = needsRepaintForDistanceOrAccuracy(); final boolean needsRepaintForHeading = needsRepaintForHeading(); - if (needsRepaintForDistance) { + if (needsRepaintForDistanceOrAccuracy) { if (map.followMyLocation) { map.centerMap(new Geopoint(currentLocation)); } } - if (needsRepaintForDistance || needsRepaintForHeading) { + if (needsRepaintForDistanceOrAccuracy || needsRepaintForHeading) { map.overlayPositionAndScale.setCoordinates(currentLocation); map.overlayPositionAndScale.setHeading(currentHeading); map.mapView.repaintRequired(map.overlayPositionAndScale); @@ -967,7 +967,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { return Math.abs(AngleUtils.difference(currentHeading, map.overlayPositionAndScale.getHeading())) > MIN_HEADING_DELTA; } - boolean needsRepaintForDistance() { + boolean needsRepaintForDistanceOrAccuracy() { final CGeoMap map = mapRef.get(); if (map == null) { return false; @@ -976,6 +976,9 @@ public class CGeoMap extends AbstractMap implements ViewFactory { float dist = Float.MAX_VALUE; if (lastLocation != null) { + if (lastLocation.getAccuracy() != currentLocation.getAccuracy()) { + return true; + } dist = currentLocation.distanceTo(lastLocation); } -- cgit v1.1 From 2fb959cf7be2c44a0bbbe27c1b39b395567479de Mon Sep 17 00:00:00 2001 From: rsudev Date: Tue, 5 Aug 2014 22:29:50 +0200 Subject: Fixes #4133, Empty personal note on OC leads to 'null' as text - gc_code was affected as well, using now 'hasNonNull' instead of 'has' in the relevant places --- main/src/cgeo/geocaching/connector/oc/OkapiClient.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java index 300112a..be347d2 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java @@ -362,7 +362,7 @@ final class OkapiClient { // not used: req_password // Prepend gc-link to description if available final StringBuilder description = new StringBuilder(500); - if (response.has("gc_code")) { + if (response.hasNonNull("gc_code")) { final String gccode = response.get("gc_code").asText(); description.append(CgeoApplication.getInstance().getResources() .getString(R.string.cache_listed_on, GCConnector.getInstance().getName())) @@ -399,7 +399,7 @@ final class OkapiClient { if (response.has(CACHE_IS_WATCHED)) { cache.setOnWatchlist(response.get(CACHE_IS_WATCHED).asBoolean()); } - if (response.has(CACHE_MY_NOTES)) { + if (response.hasNonNull(CACHE_MY_NOTES)) { cache.setPersonalNote(response.get(CACHE_MY_NOTES).asText()); cache.parseWaypointsFromNote(); } -- cgit v1.1 From dca4963b93906cf138748d204f5707e9e6b4c756 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 30 Jul 2014 15:03:32 +0200 Subject: Import Google Play Services --- main/AndroidManifest.xml | 5 ++++- main/build.gradle | 1 + main/cgeo.iml | 3 ++- main/project.properties | 5 +++-- 4 files changed, 10 insertions(+), 4 deletions(-) (limited to 'main') diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml index de91a06..1f06bc9 100644 --- a/main/AndroidManifest.xml +++ b/main/AndroidManifest.xml @@ -50,6 +50,9 @@ + - \ No newline at end of file + diff --git a/main/build.gradle b/main/build.gradle index 325af71..ffd22af 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -154,6 +154,7 @@ dependencies { compile files('libs/mapsforge-map-0.3.0-jar-with-dependencies.jar') compile 'com.android.support:appcompat-v7:19.1.0' + compile 'com.google.android.gms:play-services:5.0.77' compile 'com.jakewharton:butterknife:5.1.1' compile 'org.apache.commons:commons-collections4:4.0' diff --git a/main/cgeo.iml b/main/cgeo.iml index c662ceb..1b98d6a 100644 --- a/main/cgeo.iml +++ b/main/cgeo.iml @@ -44,7 +44,7 @@ - + @@ -56,6 +56,7 @@ + diff --git a/main/project.properties b/main/project.properties index f0fa845..5530267 100644 --- a/main/project.properties +++ b/main/project.properties @@ -8,11 +8,12 @@ # project structure. # # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt +proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt:../google-play-services_lib/proguard.txt # Project target. target=Google Inc.:Google APIs:19 android.library.reference.1=../mapswithme-api android.library.reference.2=../android-support-v7-appcompat +android.library.reference.3=../google-play-services_lib java.source=1.7 -java.target=1.7 \ No newline at end of file +java.target=1.7 -- cgit v1.1 From 8dfc859f5418c93a2cd8799d251170ac7b2df8f3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 30 Jul 2014 15:31:43 +0200 Subject: Initialize Google Play Services --- main/src/cgeo/geocaching/CgeoApplication.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'main') diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java index 269c1b6..1b3cb05 100644 --- a/main/src/cgeo/geocaching/CgeoApplication.java +++ b/main/src/cgeo/geocaching/CgeoApplication.java @@ -8,6 +8,9 @@ import cgeo.geocaching.sensors.IGeoData; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.OOMDumpingUncaughtExceptionHandler; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GooglePlayServicesUtil; + import rx.Observable; import rx.functions.Action1; import rx.observables.ConnectableObservable; @@ -28,6 +31,7 @@ public class CgeoApplication extends Application { private Observable gpsStatusObservable; private volatile IGeoData currentGeo = null; private volatile float currentDirection = 0.0f; + private boolean isGooglePlayServicesAvailable = false; public static void dumpOnOutOfMemory(final boolean enable) { @@ -66,6 +70,11 @@ public class CgeoApplication extends Application { } // ensure initialization of lists DataStore.getLists(); + // Check if Google Play services is available + if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) { + isGooglePlayServicesAvailable = true; + } + Log.i("Google Play services are " + (isGooglePlayServicesAvailable ? "" : "not ") + "available"); } @Override @@ -144,4 +153,8 @@ public class CgeoApplication extends Application { forceRelog = true; } + public boolean isGooglePlayServicesAvailable() { + return isGooglePlayServicesAvailable; + } + } -- cgit v1.1 From 878ed6668113a29eb8695cb556ff83fb75626061 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 5 Aug 2014 11:24:34 +0200 Subject: Use the Google Play fused location service when available --- main/res/values/strings.xml | 1 + main/src/cgeo/geocaching/CgeoApplication.java | 4 +- .../enumerations/LocationProviderType.java | 1 + .../geocaching/playservices/LocationProvider.java | 99 ++++++++++++++++++++++ main/src/cgeo/geocaching/sensors/GeoData.java | 7 +- 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 main/src/cgeo/geocaching/playservices/LocationProvider.java (limited to 'main') diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index ade4bf6..a2d1b8f 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -228,6 +228,7 @@ Last known Network + Fused GPS Sat Trying to Locate diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java index 1b3cb05..c8a68f4 100644 --- a/main/src/cgeo/geocaching/CgeoApplication.java +++ b/main/src/cgeo/geocaching/CgeoApplication.java @@ -1,5 +1,6 @@ package cgeo.geocaching; +import cgeo.geocaching.playservices.LocationProvider; import cgeo.geocaching.sensors.DirectionProvider; import cgeo.geocaching.sensors.GeoDataProvider; import cgeo.geocaching.sensors.GpsStatusProvider; @@ -85,7 +86,8 @@ public class CgeoApplication extends Application { public synchronized Observable geoDataObservable() { if (geoDataObservable == null) { - final ConnectableObservable onDemand = GeoDataProvider.create(this).replay(1); + final Observable rawObservable = isGooglePlayServicesAvailable() ? LocationProvider.create(this) : GeoDataProvider.create(this); + final ConnectableObservable onDemand = rawObservable.replay(1); onDemand.subscribe(new Action1() { @Override public void call(final IGeoData geoData) { diff --git a/main/src/cgeo/geocaching/enumerations/LocationProviderType.java b/main/src/cgeo/geocaching/enumerations/LocationProviderType.java index f2c79fe..e6024aa 100644 --- a/main/src/cgeo/geocaching/enumerations/LocationProviderType.java +++ b/main/src/cgeo/geocaching/enumerations/LocationProviderType.java @@ -5,6 +5,7 @@ import cgeo.geocaching.R; public enum LocationProviderType { GPS(R.string.loc_gps), NETWORK(R.string.loc_net), + FUSED(R.string.loc_fused), LAST(R.string.loc_last); public final int resourceId; diff --git a/main/src/cgeo/geocaching/playservices/LocationProvider.java b/main/src/cgeo/geocaching/playservices/LocationProvider.java new file mode 100644 index 0000000..714eaeb --- /dev/null +++ b/main/src/cgeo/geocaching/playservices/LocationProvider.java @@ -0,0 +1,99 @@ +package cgeo.geocaching.playservices; + +import cgeo.geocaching.sensors.GeoData; +import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils.ConnectableLooperCallbacks; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks; +import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener; +import com.google.android.gms.location.LocationClient; +import com.google.android.gms.location.LocationListener; +import com.google.android.gms.location.LocationRequest; + +import rx.Observable; +import rx.Observable.OnSubscribe; +import rx.Subscriber; +import rx.observables.ConnectableObservable; +import rx.subjects.BehaviorSubject; + +import android.content.Context; +import android.location.Location; +import android.os.Bundle; + +import java.util.concurrent.TimeUnit; + +public class LocationProvider implements OnSubscribe, ConnectionCallbacks, OnConnectionFailedListener, LocationListener { + + private final BehaviorSubject subject; + private final LocationClient locationClient; + private static final LocationRequest LOCATION_REQUEST = + LocationRequest.create().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(2000).setInterval(1000); + private static boolean firstLocation = true; + + /** + * Build a new geo data provider object. + *

+ * There is no need to instantiate more than one such object in an application, as observers can be added + * at will. + * + * @param context the context used to retrieve the system services + */ + protected LocationProvider(final Context context) { + locationClient = new LocationClient(context, this, this); + subject = BehaviorSubject.create(); + } + + public static Observable create(final Context context) { + final LocationProvider provider = new LocationProvider(context); + return provider.worker.refCount(); + } + + @Override + public void call(final Subscriber subscriber) { + subject.subscribe(subscriber); + } + + final ConnectableObservable worker = new ConnectableLooperCallbacks(this, 2500, TimeUnit.MILLISECONDS) { + @Override + protected void onStart() { + Log.d("LocationProvider: starting the location listener"); + locationClient.connect(); + } + + @Override + protected void onStop() { + Log.d("LocationProvider: stopping the location listener"); + locationClient.removeLocationUpdates(LocationProvider.this); + locationClient.disconnect(); + } + }; + + @Override + public void onConnected(final Bundle bundle) { + if (firstLocation) { + final Location initialLocation = locationClient.getLastLocation(); + if (initialLocation != null) { + subject.onNext(new GeoData(initialLocation)); + } + firstLocation = false; + } + locationClient.requestLocationUpdates(LOCATION_REQUEST, this); + } + + @Override + public void onDisconnected() { + } + + @Override + public void onConnectionFailed(final ConnectionResult connectionResult) { + Log.e("cannot connect to Google Play location service: " + connectionResult); + subject.onError(new RuntimeException("Connection failed: " + connectionResult)); + } + + @Override + public void onLocationChanged(final Location location) { + subject.onNext(new GeoData(location)); + } +} diff --git a/main/src/cgeo/geocaching/sensors/GeoData.java b/main/src/cgeo/geocaching/sensors/GeoData.java index 2061b6b..ea6c241 100644 --- a/main/src/cgeo/geocaching/sensors/GeoData.java +++ b/main/src/cgeo/geocaching/sensors/GeoData.java @@ -6,9 +6,9 @@ import cgeo.geocaching.geopoint.Geopoint; import android.location.Location; import android.location.LocationManager; -class GeoData extends Location implements IGeoData { +public class GeoData extends Location implements IGeoData { - GeoData(final Location location) { + public GeoData(final Location location) { super(location); } @@ -24,6 +24,9 @@ class GeoData extends Location implements IGeoData { if (provider.equals(LocationManager.NETWORK_PROVIDER)) { return LocationProviderType.NETWORK; } + if (provider.equals("fused")) { + return LocationProviderType.FUSED; + } return LocationProviderType.LAST; } -- cgit v1.1 From 16164a1f99e1cce98d7e84b6532c0f5355acab34 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 6 Aug 2014 11:07:52 +0200 Subject: Update Google Play services --- main/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/build.gradle b/main/build.gradle index ffd22af..bb9b9ca 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -154,7 +154,7 @@ dependencies { compile files('libs/mapsforge-map-0.3.0-jar-with-dependencies.jar') compile 'com.android.support:appcompat-v7:19.1.0' - compile 'com.google.android.gms:play-services:5.0.77' + compile 'com.google.android.gms:play-services:5.0.89' compile 'com.jakewharton:butterknife:5.1.1' compile 'org.apache.commons:commons-collections4:4.0' -- cgit v1.1 From f3d487eab86a3382a3c9d1b4c7f42c960534daea Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 6 Aug 2014 11:41:50 +0200 Subject: Update build tools for Gradle to version 20 --- main/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/build.gradle b/main/build.gradle index bb9b9ca..85a80fe 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -37,7 +37,7 @@ version = '0.0.1' android { compileSdkVersion "Google Inc.:Google APIs:19" //compileSdkVersion 19 - buildToolsVersion "19.1.0" + buildToolsVersion "20" compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 -- cgit v1.1 From 1e171478d8765bcf8a14ec3fbbf1c56d5b5ae8fc Mon Sep 17 00:00:00 2001 From: rsudev Date: Fri, 8 Aug 2014 22:32:20 +0200 Subject: Fixes #4142, Error 400 and NPE to all OC-sites - corrected small glitch from transition to Jackson --- main/src/cgeo/geocaching/connector/oc/OkapiClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java index be347d2..9a91abd 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java @@ -216,7 +216,7 @@ final class OkapiClient { addFilterParams(valueMap, connector, my); try { - params.add("search_params", JsonUtils.writer.writeValueAsString(params)); + params.add("search_params", JsonUtils.writer.writeValueAsString(valueMap)); } catch (final JsonProcessingException e) { Log.e("requestCaches", e); return Collections.emptyList(); -- cgit v1.1 From ffe3d2b7e57f9f5f917e9f492bc878b7575697e7 Mon Sep 17 00:00:00 2001 From: rsudev Date: Fri, 8 Aug 2014 23:16:53 +0200 Subject: Temporary workaround for #4143 --- main/src/cgeo/geocaching/MainActivity.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java index de3968f..9d9b48c 100644 --- a/main/src/cgeo/geocaching/MainActivity.java +++ b/main/src/cgeo/geocaching/MainActivity.java @@ -713,12 +713,18 @@ public class MainActivity extends AbstractActionBarActivity { } private void checkShowChangelog() { - final long lastChecksum = Settings.getLastChangelogChecksum(); - final long checksum = TextUtils.checksum(getString(R.string.changelog_master) + getString(R.string.changelog_release)); - Settings.setLastChangelogChecksum(checksum); - // don't show change log after new install... - if (lastChecksum > 0 && lastChecksum != checksum) { - AboutActivity.showChangeLog(this); + // temporary workaround for #4143 + //TODO: understand and avoid if possible + try { + final long lastChecksum = Settings.getLastChangelogChecksum(); + final long checksum = TextUtils.checksum(getString(R.string.changelog_master) + getString(R.string.changelog_release)); + Settings.setLastChangelogChecksum(checksum); + // don't show change log after new install... + if (lastChecksum > 0 && lastChecksum != checksum) { + AboutActivity.showChangeLog(this); + } + } catch (final Exception ex) { + Log.e("Error checking/showing changelog!", ex); } } -- cgit v1.1 From 179140318944cef5744d4f7f27441b1edc9ad6d4 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 9 Aug 2014 08:22:17 +0200 Subject: #4140 use ProGuard on debug builds --- main/build.xml | 275 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 148 insertions(+), 127 deletions(-) (limited to 'main') diff --git a/main/build.xml b/main/build.xml index 43c37b2..2b2467f 100644 --- a/main/build.xml +++ b/main/build.xml @@ -1,12 +1,12 @@ - - + - - + - - - - - + - - + - - - - - - - - - + + + + + + + - - + + - + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + Proguard.config is enabled + + + + + Proguard.config is disabled + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - + + + + + + + + + - - - - - - - - - Instrumenting classes from ${out.absolute.dir}/classes... - - - + + + + + + + + Instrumenting classes from ${out.absolute.dir}/classes... + + + - - + - - - + + - - - - - - - - - - - - Creating library output jar file... - - - - - - - Custom jar packaging exclusion: ${android.package.excludes} - - - - - - - + + + + + + + + + + + Creating library output jar file... + + + + + + + Custom jar packaging exclusion: ${android.package.excludes} + + + + + + + - - - - + + + + - - - - - - + + + - - - + + -- cgit v1.1 From c9f0d913e3ae0f64751e76aa7386fe72a3a44865 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 9 Aug 2014 08:31:25 +0200 Subject: #4140: keep EMMA classes in ProGuard --- main/proguard-project.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'main') diff --git a/main/proguard-project.txt b/main/proguard-project.txt index c6e67fd..cb62aef 100644 --- a/main/proguard-project.txt +++ b/main/proguard-project.txt @@ -64,3 +64,6 @@ # the sort action provider is only referenced from XML -keep public class cgeo.geocaching.sorting.SortActionProvider { *; } + +# keep Emma code coverage during debug builds +-keep class com.vladium.** { *; } -- cgit v1.1 From 5955b13490267c58a71c26037a7dc993c35e0b99 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 9 Aug 2014 09:38:14 +0200 Subject: #4140 keep all cgeo code in proguard --- main/proguard-project.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/proguard-project.txt b/main/proguard-project.txt index cb62aef..318e969 100644 --- a/main/proguard-project.txt +++ b/main/proguard-project.txt @@ -26,7 +26,7 @@ #-dontnote org.apache.commons.logging.** --keep public class cgeo.geocaching.* +-keep class cgeo.geocaching.** { *; } -keep class android.support.v4.os.** { *; } -keep class ch.boye.httpclientandroidlib.conn.scheme.Scheme { *; } -- cgit v1.1 From 1f7d1118248a51e18bbb18144511d843a53ff151 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 9 Aug 2014 10:16:54 +0200 Subject: #4140 disable play services due to blocking geodata call --- main/src/cgeo/geocaching/CgeoApplication.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java index c8a68f4..1b3cb05 100644 --- a/main/src/cgeo/geocaching/CgeoApplication.java +++ b/main/src/cgeo/geocaching/CgeoApplication.java @@ -1,6 +1,5 @@ package cgeo.geocaching; -import cgeo.geocaching.playservices.LocationProvider; import cgeo.geocaching.sensors.DirectionProvider; import cgeo.geocaching.sensors.GeoDataProvider; import cgeo.geocaching.sensors.GpsStatusProvider; @@ -86,8 +85,7 @@ public class CgeoApplication extends Application { public synchronized Observable geoDataObservable() { if (geoDataObservable == null) { - final Observable rawObservable = isGooglePlayServicesAvailable() ? LocationProvider.create(this) : GeoDataProvider.create(this); - final ConnectableObservable onDemand = rawObservable.replay(1); + final ConnectableObservable onDemand = GeoDataProvider.create(this).replay(1); onDemand.subscribe(new Action1() { @Override public void call(final IGeoData geoData) { -- cgit v1.1 From dc2947b54d6e7faa3313b3cc42850ca1c01d3658 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 9 Aug 2014 10:17:50 +0200 Subject: #4140: keep some test only classes in proguard These classes should not be whitelisted in our general ProGuard configuration. But for the time being lets include them to have a running test again. --- main/proguard-project.txt | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'main') diff --git a/main/proguard-project.txt b/main/proguard-project.txt index 318e969..bcdfa22 100644 --- a/main/proguard-project.txt +++ b/main/proguard-project.txt @@ -67,3 +67,8 @@ # keep Emma code coverage during debug builds -keep class com.vladium.** { *; } + +# keep some test only utils classes +-keep class org.apache.commons.lang3.StringUtils { *; } +-keep class org.apache.commons.io.IOUtils { *; } +-keep class org.apache.commons.io.FileUtils { *; } \ No newline at end of file -- cgit v1.1 From e040706f9c53d02047c7415ae0380f49477fce57 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 9 Aug 2014 10:26:26 +0200 Subject: enable proguard in gradle build Someone using IDEA or AS please verify this change. --- main/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/build.gradle b/main/build.gradle index 85a80fe..f2e4ae6 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -84,8 +84,8 @@ android { //packageNameSuffix ".debug" //zipAlign = true debuggable true - runProguard false - proguardFiles getDefaultProguardFile('proguard-android.txt'), '../tests/proguard.cfg' + runProguard true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt', '../tests/proguard.cfg' versionNameSuffix " Debug " + versionProps['betaNumber'] } release { -- cgit v1.1 From bb6267da4e1d9dcdb4935c04fce27adf79f11b67 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 9 Aug 2014 12:15:08 +0200 Subject: #4140: completely ignore EMMA in proguard --- main/proguard-project.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'main') diff --git a/main/proguard-project.txt b/main/proguard-project.txt index bcdfa22..2bc66da 100644 --- a/main/proguard-project.txt +++ b/main/proguard-project.txt @@ -65,8 +65,9 @@ # the sort action provider is only referenced from XML -keep public class cgeo.geocaching.sorting.SortActionProvider { *; } -# keep Emma code coverage during debug builds +# keep Emma code coverage during debug builds, and ignore related warnings -keep class com.vladium.** { *; } +-dontwarn com.vladium.** # keep some test only utils classes -keep class org.apache.commons.lang3.StringUtils { *; } -- cgit v1.1 From c28f9d024e513aec304bd144ae0d77e0e8173c66 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 10 Aug 2014 13:31:53 +0200 Subject: have shared moreunit settings for eclipse --- main/.settings/org.moreunit.prefs | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 main/.settings/org.moreunit.prefs (limited to 'main') diff --git a/main/.settings/org.moreunit.prefs b/main/.settings/org.moreunit.prefs new file mode 100644 index 0000000..17ff166 --- /dev/null +++ b/main/.settings/org.moreunit.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.moreunit.preferences.version=2 +org.moreunit.unitsourcefolder=cgeo\:src\:cgeo-test\:src\#cgeo\:src\:cgeo-test\:gen +org.moreunit.useprojectsettings=true -- cgit v1.1 From 1e24584929b62c304c7d36a7e1fa652e7e94a23a Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 10 Aug 2014 13:32:53 +0200 Subject: more strict checking of Maps API key --- main/src/cgeo/geocaching/maps/MapProviderFactory.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/maps/MapProviderFactory.java b/main/src/cgeo/geocaching/maps/MapProviderFactory.java index dd4ff0f..212188d 100644 --- a/main/src/cgeo/geocaching/maps/MapProviderFactory.java +++ b/main/src/cgeo/geocaching/maps/MapProviderFactory.java @@ -33,7 +33,8 @@ public class MapProviderFactory { public static boolean isGoogleMapsInstalled() { // Check if API key is available - if (StringUtils.isBlank(CgeoApplication.getInstance().getString(R.string.maps_api_key))) { + final String mapsKey = CgeoApplication.getInstance().getString(R.string.maps_api_key); + if (StringUtils.length(mapsKey) < 30 || StringUtils.contains(mapsKey, "key")) { Log.w("No Google API key available."); return false; } @@ -41,7 +42,7 @@ public class MapProviderFactory { // Check if API is available try { Class.forName("com.google.android.maps.MapActivity"); - } catch (ClassNotFoundException e) { + } catch (final ClassNotFoundException e) { return false; } @@ -59,7 +60,7 @@ public class MapProviderFactory { return provider1 == provider2 && provider1.isSameActivity(source1, source2); } - public static void addMapviewMenuItems(Menu menu) { + public static void addMapviewMenuItems(final Menu menu) { final SubMenu parentMenu = menu.findItem(R.id.menu_select_mapview).getSubMenu(); final int currentSource = Settings.getMapSource().getNumericalId(); @@ -78,8 +79,8 @@ public class MapProviderFactory { * @return the map source, or null if id does not correspond to a registered map source */ @Nullable - public static MapSource getMapSource(int id) { - for (MapSource mapSource : mapSources) { + public static MapSource getMapSource(final int id) { + for (final MapSource mapSource : mapSources) { if (mapSource.getNumericalId() == id) { return mapSource; } @@ -109,7 +110,7 @@ public class MapProviderFactory { */ public static void deleteOfflineMapSources() { final ArrayList deletion = new ArrayList<>(); - for (MapSource mapSource : mapSources) { + for (final MapSource mapSource : mapSources) { if (mapSource instanceof MapsforgeMapProvider.OfflineMapSource) { deletion.add(mapSource); } -- cgit v1.1 From d28fb223c6e4308a6e40db08e779c954252aff26 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 10 Aug 2014 13:33:37 +0200 Subject: typo --- main/templates/keys.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/templates/keys.xml b/main/templates/keys.xml index d40c0e3..b624b86 100644 --- a/main/templates/keys.xml +++ b/main/templates/keys.xml @@ -23,7 +23,7 @@ @ocro.okapi.consumer.key@ @ocro.okapi.consumer.secret@ - + @ocuk.okapi.consumer.key@ @ocuk.okapi.consumer.secret@ -- cgit v1.1 From af06e72c033bfd6791ffa567f622708efb7b54e7 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Mon, 11 Aug 2014 08:48:40 +0200 Subject: explicitly set context for layout editor --- main/res/layout/about_changes_page.xml | 4 +++- main/res/layout/about_contributors_page.xml | 4 +++- main/res/layout/about_help_page.xml | 4 +++- main/res/layout/about_license_page.xml | 3 ++- main/res/layout/about_version_page.xml | 4 +++- main/res/layout/addresslist_activity.xml | 3 ++- main/res/layout/addresslist_item.xml | 4 +++- main/res/layout/attribute_image.xml | 4 +++- main/res/layout/authorization_activity.xml | 4 +++- main/res/layout/cachedetail_activity.xml | 4 +++- main/res/layout/cachedetail_description_page.xml | 5 ++++- main/res/layout/cachedetail_details_page.xml | 4 +++- main/res/layout/cachedetail_images_page.xml | 4 +++- main/res/layout/cachedetail_inventory_page.xml | 4 +++- main/res/layout/cachedetail_waypoints_footer.xml | 7 ++++--- main/res/layout/cachedetail_waypoints_page.xml | 4 +++- main/res/layout/cachelist_spinneritem.xml | 11 +++++------ main/res/layout/cacheslist_activity.xml | 4 +++- main/res/layout/cacheslist_footer.xml | 4 +++- main/res/layout/cacheslist_item.xml | 3 ++- main/res/layout/compass_activity.xml | 4 +++- main/res/layout/coordinatesinput_dialog.xml | 3 ++- main/res/layout/editwaypoint_activity.xml | 4 +++- main/res/layout/fieldnote_export_dialog.xml | 4 +++- main/res/layout/fragment_edit_note.xml | 4 +++- main/res/layout/gpx.xml | 4 +++- main/res/layout/gpx_export_dialog.xml | 4 +++- main/res/layout/gpx_item.xml | 4 +++- main/res/layout/image_item.xml | 4 +++- main/res/layout/images_activity.xml | 4 +++- main/res/layout/imageselect_activity.xml | 4 +++- main/res/layout/internal_browser.xml | 16 +++++++++------- main/res/layout/livemapinfo.xml | 5 +++-- main/res/layout/logcache_activity.xml | 4 +++- main/res/layout/logcache_trackable_item.xml | 4 +++- main/res/layout/logs_item.xml | 4 +++- main/res/layout/logs_page.xml | 1 + main/res/layout/logtrackable_activity.xml | 4 +++- main/res/layout/main_activity.xml | 3 ++- main/res/layout/main_activity_connectorstatus.xml | 4 +++- main/res/layout/map_google.xml | 6 +++--- main/res/layout/map_mapsforge.xml | 4 +++- main/res/layout/map_mapsforge_old.xml | 4 +++- main/res/layout/mapfile_item.xml | 4 +++- main/res/layout/navigateanypoint_activity.xml | 4 +++- main/res/layout/navigateanypoint_header.xml | 4 +++- main/res/layout/popup.xml | 2 +- main/res/layout/preference_info_icon.xml | 6 ++++-- main/res/layout/recaptcha_dialog.xml | 5 +++-- main/res/layout/search_activity.xml | 3 ++- main/res/layout/simple_dir_chooser.xml | 3 ++- main/res/layout/simple_dir_item.xml | 4 +++- main/res/layout/simple_way_point.xml | 4 +++- main/res/layout/star_image.xml | 4 +++- main/res/layout/staticmaps_activity.xml | 4 +++- main/res/layout/staticmaps_activity_item.xml | 4 +++- main/res/layout/status.xml | 4 +++- main/res/layout/template_preference_dialog.xml | 4 +++- main/res/layout/trackable_details_view.xml | 4 +++- main/res/layout/trackable_image.xml | 4 +++- main/res/layout/usefulapps_activity.xml | 3 ++- main/res/layout/usefulapps_item.xml | 4 +++- main/res/layout/waypoint_item.xml | 4 +++- main/res/layout/waypoint_popup.xml | 6 ++++-- 64 files changed, 192 insertions(+), 82 deletions(-) (limited to 'main') diff --git a/main/res/layout/about_changes_page.xml b/main/res/layout/about_changes_page.xml index 544d338..355ce90 100644 --- a/main/res/layout/about_changes_page.xml +++ b/main/res/layout/about_changes_page.xml @@ -1,9 +1,11 @@ + android:padding="4dip" + tools:context=".AboutActivity$ChangeLogViewCreator" > + android:padding="4dip" + tools:context=".AboutActivity$ContributorsViewCreator" > + android:padding="4dip" + tools:context=".AboutActivity$HelpViewCreator" > + android:padding="4dip" + tools:context=".AboutActivity$LicenseViewCreator" > + android:padding="4dip" + tools:context=".AboutActivity$VersionViewCreator" > + android:orientation="vertical" + tools:context=".AddressListActivity" > + android:paddingTop="7dip" + tools:context=".ui.AddressListAdapter" > + android:layout_height="wrap_content" + tools:context=".CacheDetailActivity$AttributeViewBuilder" > + android:padding="4dip" + tools:context=".network.OAuthAuthorizationActivity" > + android:orientation="vertical" + tools:context=".CacheDetailActivity" > + android:layout_height="fill_parent" + tools:context=".CacheDetailActivity$DescriptionViewCreator" > +