diff options
43 files changed, 746 insertions, 232 deletions
@@ -103,3 +103,4 @@ c:geo is distributed under [Apache License, Version 2.0](http://www.apache.org/l - Google+: https://plus.google.com/105588163414303246956 - Google Play: https://play.google.com/store/apps/details?id=cgeo.geocaching - Live status: http://status.cgeo.org/ +- Developer chat: #cgeo on freenode.net (e.g. https://webchat.freenode.net/) diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml index 6217ad5..ca3026a 100644 --- a/main/AndroidManifest.xml +++ b/main/AndroidManifest.xml @@ -409,6 +409,7 @@ <!-- TravelBug URL via coord.info redirection --> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -420,6 +421,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -433,6 +435,7 @@ <!-- TravelBug URL tracking page --> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -444,6 +447,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -457,6 +461,7 @@ <!-- GeoKrety URLs --> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -468,6 +473,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> diff --git a/main/build.gradle b/main/build.gradle index 5ab860b..9034c74 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -28,7 +28,7 @@ gradle connectedCheck def AAVersion = '3.2' def RXJavaVersion = '1.0.4' -def RXAndroidVersion = '0.23.0' +def RXAndroidVersion = '0.24.0' def RXJavaAsyncUtilVersion = '0.21.0' def JacksonCoreVersion = '2.4.4' def JacksonDatabindVersion = '2.4.4' diff --git a/main/libs/rxandroid-0.23.0.jar b/main/libs/rxandroid-0.23.0.jar Binary files differdeleted file mode 100644 index 63c874d..0000000 --- a/main/libs/rxandroid-0.23.0.jar +++ /dev/null diff --git a/main/libs/rxandroid-0.23.0.jar.properties b/main/libs/rxandroid-0.23.0.jar.properties deleted file mode 100644 index f4b1b70..0000000 --- a/main/libs/rxandroid-0.23.0.jar.properties +++ /dev/null @@ -1,2 +0,0 @@ -src=src/rxandroid-0.23.0-sources.jar -doc=src/rxandroid-0.23.0-javadoc.jar diff --git a/main/libs/rxandroid-0.24.0.jar b/main/libs/rxandroid-0.24.0.jar Binary files differnew file mode 100644 index 0000000..35eb088 --- /dev/null +++ b/main/libs/rxandroid-0.24.0.jar diff --git a/main/libs/rxandroid-0.24.0.jar.properties b/main/libs/rxandroid-0.24.0.jar.properties new file mode 100644 index 0000000..d995320 --- /dev/null +++ b/main/libs/rxandroid-0.24.0.jar.properties @@ -0,0 +1,2 @@ +src=src/rxandroid-0.24.0-sources.jar +doc=src/rxandroid-0.24.0-javadoc.jar diff --git a/main/libs/src/rxandroid-0.23.0-javadoc.jar b/main/libs/src/rxandroid-0.23.0-javadoc.jar Binary files differdeleted file mode 100644 index 1c6a02f..0000000 --- a/main/libs/src/rxandroid-0.23.0-javadoc.jar +++ /dev/null diff --git a/main/libs/src/rxandroid-0.23.0-sources.jar b/main/libs/src/rxandroid-0.23.0-sources.jar Binary files differdeleted file mode 100644 index ab5d74e..0000000 --- a/main/libs/src/rxandroid-0.23.0-sources.jar +++ /dev/null diff --git a/main/libs/src/rxandroid-0.24.0-javadoc.jar b/main/libs/src/rxandroid-0.24.0-javadoc.jar Binary files differnew file mode 100644 index 0000000..ea887e5 --- /dev/null +++ b/main/libs/src/rxandroid-0.24.0-javadoc.jar diff --git a/main/libs/src/rxandroid-0.24.0-sources.jar b/main/libs/src/rxandroid-0.24.0-sources.jar Binary files differnew file mode 100644 index 0000000..8bffa81 --- /dev/null +++ b/main/libs/src/rxandroid-0.24.0-sources.jar diff --git a/main/project/libraries/update-libs.sh b/main/project/libraries/update-libs.sh index be3483c..b49dbef 100755 --- a/main/project/libraries/update-libs.sh +++ b/main/project/libraries/update-libs.sh @@ -2,7 +2,7 @@ # RXJAVA=1.0.4 -RXANDROID=0.23.0 +RXANDROID=0.24.0 RXJAVAASYNCUTIL=0.21.0 JACKSONCORE=2.4.4 JACKSONDATABIND=2.4.4 diff --git a/main/res/values/changelog_master.xml b/main/res/values/changelog_master.xml index 1e3c3d4..0576519 100644 --- a/main/res/values/changelog_master.xml +++ b/main/res/values/changelog_master.xml @@ -2,5 +2,8 @@ <resources> <!-- changelog for the master branch --> <string name="changelog_master" translatable="false"> + <b>Next feature release:</b>\n + ยท Put features there\n + \n </string> </resources> diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java index d7d60d2..ceafc31 100644 --- a/main/src/cgeo/geocaching/AboutActivity.java +++ b/main/src/cgeo/geocaching/AboutActivity.java @@ -266,7 +266,7 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> } body .append("\nLow power mode: ").append(Settings.useLowPowerMode() ? "active" : "inactive") - .append("\nMagnetic field sensor: ").append(presence(Sensors.getInstance().hasMagneticFieldSensor())) + .append("\nCompass capabilities: ").append(Sensors.getInstance().hasCompassCapabilities() ? "yes" : "no") .append("\nRotation sensor: ").append(presence(RotationProvider.hasRotationSensor(context))) .append("\nGeomagnetic rotation sensor: ").append(presence(RotationProvider.hasGeomagneticRotationSensor(context))) .append("\nOrientation sensor: ").append(presence(OrientationProvider.hasOrientationSensor(context))) diff --git a/main/src/cgeo/geocaching/AbstractDialogFragment.java b/main/src/cgeo/geocaching/AbstractDialogFragment.java index 0f0ea2f..d81dde5 100644 --- a/main/src/cgeo/geocaching/AbstractDialogFragment.java +++ b/main/src/cgeo/geocaching/AbstractDialogFragment.java @@ -19,7 +19,7 @@ import cgeo.geocaching.utils.RxUtils; import rx.Observable; import rx.Subscription; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; import rx.functions.Func0; import rx.subscriptions.Subscriptions; @@ -187,7 +187,7 @@ public abstract class AbstractDialogFragment extends DialogFragment implements C if (!cache.supportsGCVote()) { return; } - AndroidObservable.bindActivity(getActivity(), Observable.defer(new Func0<Observable<GCVoteRating>>() { + AppObservable.bindActivity(getActivity(), Observable.defer(new Func0<Observable<GCVoteRating>>() { @Override public Observable<GCVoteRating> call() { final GCVoteRating rating = GCVote.getRating(cache.getGuid(), geocode); diff --git a/main/src/cgeo/geocaching/AddressListActivity.java b/main/src/cgeo/geocaching/AddressListActivity.java index 4f81f8b..4ff48f6 100644 --- a/main/src/cgeo/geocaching/AddressListActivity.java +++ b/main/src/cgeo/geocaching/AddressListActivity.java @@ -7,7 +7,7 @@ import cgeo.geocaching.location.MapQuestGeocoder; import cgeo.geocaching.ui.AddressListAdapter; import rx.Observable; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; import android.app.ProgressDialog; @@ -22,7 +22,6 @@ public class AddressListActivity extends AbstractListActivity { public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.addresslist_activity); - final AddressListAdapter adapter = new AddressListAdapter(this); setListAdapter(adapter); @@ -37,7 +36,7 @@ public class AddressListActivity extends AbstractListActivity { final Observable<Address> geocoderObservable = new AndroidGeocoder(this).getFromLocationName(keyword) .onErrorResumeNext(MapQuestGeocoder.getFromLocationName(keyword)) .onErrorResumeNext(GCGeocoder.getFromLocationName(keyword)); - AndroidObservable.bindActivity(this, geocoderObservable.toList()).subscribe(new Action1<List<Address>>() { + AppObservable.bindActivity(this, geocoderObservable.toList()).subscribe(new Action1<List<Address>>() { @Override public void call(final List<Address> addresses) { waitDialog.dismiss(); diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 0866897..9406fd4 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -66,7 +66,7 @@ import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; import rx.Subscription; -import rx.android.observables.AndroidObservable; +import rx.android.view.ViewObservable; import rx.functions.Action0; import rx.functions.Action1; import rx.subscriptions.CompositeSubscription; @@ -807,7 +807,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc view = (ScrollView) getLayoutInflater().inflate(R.layout.cachedetail_details_page, parentView, false); // Start loading preview map - AndroidObservable.bindActivity(CacheDetailActivity.this, previewMap).subscribeOn(RxUtils.networkScheduler) + ViewObservable.bindView(view, previewMap).subscribeOn(RxUtils.networkScheduler) .subscribe(new Action1<BitmapDrawable>() { @Override public void call(final BitmapDrawable image) { diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java index 8b0fc73..27dbb4a 100644 --- a/main/src/cgeo/geocaching/CompassActivity.java +++ b/main/src/cgeo/geocaching/CompassActivity.java @@ -139,7 +139,7 @@ public class CompassActivity extends AbstractActionBarActivity { @Override public boolean onCreateOptionsMenu(final Menu menu) { getMenuInflater().inflate(R.menu.compass_activity_options, menu); - menu.findItem(R.id.menu_compass_sensor).setVisible(Sensors.getInstance().hasMagneticFieldSensor()); + menu.findItem(R.id.menu_compass_sensor).setVisible(Sensors.getInstance().hasCompassCapabilities()); if (cache != null) { LoggingUI.addMenuItems(this, menu, cache); } diff --git a/main/src/cgeo/geocaching/DataStore.java b/main/src/cgeo/geocaching/DataStore.java index 0f9f6bf..02f48a0 100644 --- a/main/src/cgeo/geocaching/DataStore.java +++ b/main/src/cgeo/geocaching/DataStore.java @@ -33,7 +33,7 @@ import org.eclipse.jdt.annotation.Nullable; import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action0; import rx.functions.Action1; import rx.functions.Func0; @@ -407,7 +407,7 @@ public class DataStore { */ public static void moveDatabase(final Activity fromActivity) { final ProgressDialog dialog = ProgressDialog.show(fromActivity, fromActivity.getString(R.string.init_dbmove_dbmove), fromActivity.getString(R.string.init_dbmove_running), true, false); - AndroidObservable.bindActivity(fromActivity, Async.fromCallable(new Func0<Boolean>() { + AppObservable.bindActivity(fromActivity, Async.fromCallable(new Func0<Boolean>() { @Override public Boolean call() { if (!LocalStorage.isExternalStorageAvailable()) { @@ -2946,7 +2946,7 @@ public class DataStore { } public static void saveChangedCache(final Geocache cache) { - DataStore.saveCache(cache, cache.getStorageLocation().contains(StorageLocation.DATABASE) ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.CACHE)); + DataStore.saveCache(cache, cache.inDatabase() ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.CACHE)); } private static enum PreparedStatement { @@ -3001,8 +3001,9 @@ public class DataStore { private static void clearPreparedStatements() { for (final PreparedStatement preparedStatement : statements) { - if (preparedStatement.statement != null) { - preparedStatement.statement.close(); + final SQLiteStatement statement = preparedStatement.statement; + if (statement != null) { + statement.close(); preparedStatement.statement = null; } } diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java index c842a7f..dda19c8 100644 --- a/main/src/cgeo/geocaching/Geocache.java +++ b/main/src/cgeo/geocaching/Geocache.java @@ -133,13 +133,13 @@ public class Geocache implements IWaypoint { private final LazyInitializedList<String> attributes = new LazyInitializedList<String>() { @Override public List<String> call() { - return DataStore.loadAttributes(geocode); + return inDatabase() ? DataStore.loadAttributes(geocode) : new LinkedList<String>(); } }; private final LazyInitializedList<Waypoint> waypoints = new LazyInitializedList<Waypoint>() { @Override public List<Waypoint> call() { - return DataStore.loadWaypoints(geocode); + return inDatabase() ? DataStore.loadWaypoints(geocode) : new LinkedList<Waypoint>(); } }; private List<Image> spoilers = null; @@ -629,18 +629,25 @@ public class Geocache implements IWaypoint { */ private void initializeCacheTexts() { if (description == null || shortdesc == null || hint == null || location == null) { - final Geocache partial = DataStore.loadCacheTexts(this.getGeocode()); - if (description == null) { - setDescription(partial.getDescription()); - } - if (shortdesc == null) { - setShortDescription(partial.getShortDescription()); - } - if (hint == null) { - setHint(partial.getHint()); - } - if (location == null) { - setLocation(partial.getLocation()); + if (inDatabase()) { + final Geocache partial = DataStore.loadCacheTexts(this.getGeocode()); + if (description == null) { + setDescription(partial.getDescription()); + } + if (shortdesc == null) { + setShortDescription(partial.getShortDescription()); + } + if (hint == null) { + setHint(partial.getHint()); + } + if (location == null) { + setLocation(partial.getLocation()); + } + } else { + description = StringUtils.defaultString(description); + shortdesc = StringUtils.defaultString(shortdesc); + hint = StringUtils.defaultString(hint); + location = StringUtils.defaultString(location); } } } @@ -1013,7 +1020,7 @@ public class Geocache implements IWaypoint { */ @NonNull public List<LogEntry> getLogs() { - return DataStore.loadLogs(geocode); + return inDatabase() ? DataStore.loadLogs(geocode) : Collections.<LogEntry>emptyList(); } /** @@ -1182,6 +1189,13 @@ public class Geocache implements IWaypoint { } /** + * Check if this cache instance comes from or has been stored into the database. + */ + public boolean inDatabase() { + return storageLocation.contains(StorageLocation.DATABASE); + } + + /** * @param waypoint * Waypoint to add to the cache * @param saveToDatabase @@ -1748,7 +1762,7 @@ public class Geocache implements IWaypoint { */ public int getFindsCount() { if (getLogCounts().isEmpty()) { - setLogCounts(DataStore.loadLogCounts(getGeocode())); + setLogCounts(inDatabase() ? DataStore.loadLogCounts(getGeocode()) : Collections.<LogType, Integer>emptyMap()); } final Integer logged = getLogCounts().get(LogType.FOUND_IT); if (logged != null) { diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java index 558c70a..399de83 100644 --- a/main/src/cgeo/geocaching/MainActivity.java +++ b/main/src/cgeo/geocaching/MainActivity.java @@ -11,7 +11,9 @@ import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.list.PseudoList; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.AndroidGeocoder; import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.MapQuestGeocoder; import cgeo.geocaching.location.Units; import cgeo.geocaching.maps.CGeoMap; import cgeo.geocaching.network.Network; @@ -37,12 +39,11 @@ import com.google.zxing.integration.android.IntentResult; import org.apache.commons.lang3.StringUtils; import rx.Observable; -import rx.Observable.OnSubscribe; -import rx.Subscriber; -import rx.android.observables.AndroidObservable; import rx.android.schedulers.AndroidSchedulers; +import rx.android.view.ViewObservable; import rx.functions.Action0; import rx.functions.Action1; +import rx.functions.Func1; import android.app.AlertDialog; import android.app.AlertDialog.Builder; @@ -54,7 +55,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.location.Address; -import android.location.Geocoder; import android.net.ConnectivityManager; import android.os.Bundle; import android.os.Handler; @@ -75,7 +75,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Locale; public class MainActivity extends AbstractActionBarActivity { @InjectView(R.id.nav_satellites) protected TextView navSatellites; @@ -501,7 +500,7 @@ public class MainActivity extends AbstractActionBarActivity { } public void updateCacheCounter() { - AndroidObservable.bindActivity(this, DataStore.getAllCachesCountObservable()).subscribe(new Action1<Integer>() { + ViewObservable.bindView(countBubble, DataStore.getAllCachesCountObservable()).subscribe(new Action1<Integer>() { @Override public void call(final Integer countBubbleCnt1) { if (countBubbleCnt1 == 0) { @@ -572,30 +571,21 @@ public class MainActivity extends AbstractActionBarActivity { navAccuracy.setText(null); } + final Geopoint currentCoords = geo.getCoords(); if (Settings.isShowAddress()) { if (addCoords == null) { navLocation.setText(R.string.loc_no_addr); } - if (addCoords == null || (geo.getCoords().distanceTo(addCoords) > 0.5)) { - final Observable<String> address = Observable.create(new OnSubscribe<String>() { + if (addCoords == null || (currentCoords.distanceTo(addCoords) > 0.5)) { + addCoords = currentCoords; + final Observable<String> address = (new AndroidGeocoder(MainActivity.this).getFromLocation(currentCoords) + .onErrorResumeNext(MapQuestGeocoder.getFromLocation(currentCoords))).map(new Func1<Address, String>() { @Override - public void call(final Subscriber<? super String> subscriber) { - try { - addCoords = geo.getCoords(); - final Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault()); - final List<Address> addresses = geocoder.getFromLocation(addCoords.getLatitude(), addCoords.getLongitude(), 1); - if (!addresses.isEmpty()) { - subscriber.onNext(formatAddress(addresses.get(0))); - } - subscriber.onCompleted(); - } catch (final Exception e) { - subscriber.onError(e); - } + public String call(final Address address) { + return formatAddress(address); } - }); - AndroidObservable.bindActivity(MainActivity.this, address.onErrorResumeNext(Observable.just(geo.getCoords().toString()))) - .subscribeOn(RxUtils.networkScheduler) - .subscribe(new Action1<String>() { + }).onErrorResumeNext(Observable.just(currentCoords.toString())); + ViewObservable.bindView(navLocation, address).subscribe(new Action1<String>() { @Override public void call(final String address) { navLocation.setText(address); @@ -603,7 +593,7 @@ public class MainActivity extends AbstractActionBarActivity { }); } } else { - navLocation.setText(geo.getCoords().toString()); + navLocation.setText(currentCoords.toString()); } } } diff --git a/main/src/cgeo/geocaching/PocketQueryList.java b/main/src/cgeo/geocaching/PocketQueryList.java index 21f306e..27edffd 100644 --- a/main/src/cgeo/geocaching/PocketQueryList.java +++ b/main/src/cgeo/geocaching/PocketQueryList.java @@ -2,14 +2,10 @@ package cgeo.geocaching; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.connector.gc.GCParser; -import cgeo.geocaching.utils.RxUtils; import org.apache.commons.collections4.CollectionUtils; -import rx.Observable; -import rx.Observable.OnSubscribe; -import rx.Subscriber; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; import android.app.Activity; @@ -47,13 +43,7 @@ public final class PocketQueryList { public static void promptForListSelection(final Activity activity, final Action1<PocketQueryList> runAfterwards) { final Dialog waitDialog = ProgressDialog.show(activity, activity.getString(R.string.search_pocket_title), activity.getString(R.string.search_pocket_loading), true, true); - AndroidObservable.bindActivity(activity, Observable.create(new OnSubscribe<List<PocketQueryList>>() { - @Override - public void call(final Subscriber<? super List<PocketQueryList>> subscriber) { - subscriber.onNext(GCParser.searchPocketQueryList()); - subscriber.onCompleted(); - } - })).subscribeOn(RxUtils.networkScheduler).subscribe(new Action1<List<PocketQueryList>>() { + AppObservable.bindActivity(activity, GCParser.searchPocketQueryListObservable).subscribe(new Action1<List<PocketQueryList>>() { @Override public void call(final List<PocketQueryList> pocketQueryLists) { waitDialog.dismiss(); @@ -61,6 +51,7 @@ public final class PocketQueryList { } }); } + private static void selectFromPocketQueries(final Activity activity, final List<PocketQueryList> pocketQueryList, final Action1<PocketQueryList> runAfterwards) { if (CollectionUtils.isEmpty(pocketQueryList)) { ActivityMixin.showToast(activity, activity.getString(R.string.warn_no_pocket_query_found)); diff --git a/main/src/cgeo/geocaching/StatusFragment.java b/main/src/cgeo/geocaching/StatusFragment.java index e8824ce..76e841d 100644 --- a/main/src/cgeo/geocaching/StatusFragment.java +++ b/main/src/cgeo/geocaching/StatusFragment.java @@ -8,7 +8,7 @@ import cgeo.geocaching.network.StatusUpdater.Status; import cgeo.geocaching.utils.Log; import rx.Subscription; -import rx.android.observables.AndroidObservable; +import rx.android.view.ViewObservable; import rx.functions.Action1; import rx.subscriptions.Subscriptions; @@ -36,7 +36,7 @@ public class StatusFragment extends Fragment { super.onCreateView(inflater, container, savedInstanceState); final ViewGroup statusGroup = (ViewGroup) inflater.inflate(R.layout.status, container, false); ButterKnife.inject(this, statusGroup); - statusSubscription = AndroidObservable.bindFragment(this, StatusUpdater.latestStatus) + statusSubscription = ViewObservable.bindView(statusGroup, StatusUpdater.latestStatus) .subscribe(new Action1<Status>() { @Override public void call(final Status status) { diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java index 45111f6..ff84dcb 100644 --- a/main/src/cgeo/geocaching/TrackableActivity.java +++ b/main/src/cgeo/geocaching/TrackableActivity.java @@ -26,14 +26,15 @@ import cgeo.geocaching.utils.RxUtils; import cgeo.geocaching.utils.UnknownTagsHandler; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.Charsets; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import rx.Observable; -import rx.android.events.OnClickEvent; -import rx.android.observables.AndroidObservable; -import rx.android.observables.ViewObservable; +import rx.android.app.AppObservable; +import rx.android.view.OnClickEvent; +import rx.android.view.ViewObservable; import rx.functions.Action1; import rx.functions.Func0; import rx.subscriptions.CompositeSubscription; @@ -42,6 +43,8 @@ import android.app.ProgressDialog; import android.content.Intent; import android.graphics.drawable.BitmapDrawable; import android.net.Uri; +import android.nfc.NdefMessage; +import android.nfc.NfcAdapter; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.view.ActionMode; @@ -102,14 +105,20 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi // get parameters final Bundle extras = getIntent().getExtras(); - final Uri uri = getIntent().getData(); - // try to get data from extras - if (extras != null) { + final Uri uri; + if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) { + final NdefMessage msg = (NdefMessage) extras.getParcelableArray(NfcAdapter.EXTRA_NDEF_MESSAGES)[0]; + uri = Uri.parse("http://" + new String(msg.getRecords()[0].getPayload(), Charsets.UTF_8)); + } else if (extras != null) { + // try to get data from extras geocode = extras.getString(Intents.EXTRA_GEOCODE); name = extras.getString(Intents.EXTRA_NAME); guid = extras.getString(Intents.EXTRA_GUID); id = extras.getString(Intents.EXTRA_ID); + uri = getIntent().getData(); + } else { + uri = null; } // try to get data from URI @@ -183,7 +192,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi }); waitDialog = ProgressDialog.show(this, message, res.getString(R.string.trackable_details_loading), true, true); createSubscriptions = new CompositeSubscription(); - createSubscriptions.add(AndroidObservable.bindActivity(this, loadTrackable(geocode, guid, id)).singleOrDefault(null).subscribe(new Action1<Trackable>() { + createSubscriptions.add(AppObservable.bindActivity(this, loadTrackable(geocode, guid, id)).singleOrDefault(null).subscribe(new Action1<Trackable>() { @Override public void call(final Trackable trackable) { TrackableActivity.this.trackable = trackable; @@ -294,7 +303,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi private void setupIcon(final ActionBar actionBar, final String url) { final HtmlImage imgGetter = new HtmlImage(HtmlImage.SHARED, false, 0, false); - AndroidObservable.bindActivity(this, imgGetter.fetchDrawable(url)).subscribe(new Action1<BitmapDrawable>() { + AppObservable.bindActivity(this, imgGetter.fetchDrawable(url)).subscribe(new Action1<BitmapDrawable>() { @Override public void call(final BitmapDrawable image) { if (actionBar != null) { @@ -525,7 +534,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } }); - AndroidObservable.bindActivity(TrackableActivity.this, new HtmlImage(geocode, true, 0, false).fetchDrawable(trackable.getImage())).subscribe(new Action1<BitmapDrawable>() { + ViewObservable.bindView(trackableImage, new HtmlImage(geocode, true, 0, false).fetchDrawable(trackable.getImage())).subscribe(new Action1<BitmapDrawable>() { @Override public void call(final BitmapDrawable bitmapDrawable) { trackableImage.setImageDrawable(bitmapDrawable); diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index ba11958..4cddfe6 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -231,7 +231,14 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs @Override public NdefMessage createNdefMessage(final NfcEvent event) { final String uri = sharingInterface.getAndroidBeamUri(); - return uri != null ? new NdefMessage(new NdefRecord[]{NdefRecord.createUri(uri)}) : null; + if (uri == null) { + return null; + } + final NdefRecord[] records = { + NdefRecord.createUri(uri), + NdefRecord.createApplicationRecord(CgeoApplication.getInstance().getPackageName()) + }; + return new NdefMessage(records); } }, this); diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index badbc67..5c03dd7 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -65,6 +65,7 @@ import android.text.Html; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; @@ -985,52 +986,58 @@ public abstract class GCParser { return trackable; } - public static List<PocketQueryList> searchPocketQueryList() { - - final Parameters params = new Parameters(); + /** + * Observable that fetches a list of pocket queries. Returns a single element (which may be an empty list). + * Executes on the network scheduler. + */ + public static final Observable<List<PocketQueryList>> searchPocketQueryListObservable = Async.fromCallable(new Func0<List<PocketQueryList>>() { + @Override + public List<PocketQueryList> call() { + final Parameters params = new Parameters(); - final String page = GCLogin.getInstance().getRequestLogged("http://www.geocaching.com/pocket/default.aspx", params); + final String page = GCLogin.getInstance().getRequestLogged("http://www.geocaching.com/pocket/default.aspx", params); - if (StringUtils.isBlank(page)) { - Log.e("GCParser.searchPocketQueryList: No data from server"); - return null; - } + if (StringUtils.isBlank(page)) { + Log.e("GCParser.searchPocketQueryList: No data from server"); + return Collections.emptyList(); + } - 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(); - } + 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(); + } - final List<PocketQueryList> list = new ArrayList<>(); + final List<PocketQueryList> list = new ArrayList<>(); - final MatcherWrapper matcherPocket = new MatcherWrapper(GCConstants.PATTERN_LIST_PQ, subPage); + final MatcherWrapper matcherPocket = new MatcherWrapper(GCConstants.PATTERN_LIST_PQ, subPage); - while (matcherPocket.find()) { - int maxCaches; - try { - maxCaches = Integer.parseInt(matcherPocket.group(1)); - } catch (final NumberFormatException e) { - maxCaches = 0; - Log.e("GCParser.searchPocketQueryList: Unable to parse max caches", e); + while (matcherPocket.find()) { + int maxCaches; + try { + maxCaches = Integer.parseInt(matcherPocket.group(1)); + } catch (final NumberFormatException e) { + maxCaches = 0; + Log.e("GCParser.searchPocketQueryList: Unable to parse max caches", e); + } + final String guid = Html.fromHtml(matcherPocket.group(2)).toString(); + final String name = Html.fromHtml(matcherPocket.group(3)).toString(); + final PocketQueryList pqList = new PocketQueryList(guid, name, maxCaches); + list.add(pqList); } - final String guid = Html.fromHtml(matcherPocket.group(2)).toString(); - final String name = Html.fromHtml(matcherPocket.group(3)).toString(); - final PocketQueryList pqList = new PocketQueryList(guid, name, maxCaches); - list.add(pqList); - } - // just in case, lets sort the resulting list - Collections.sort(list, new Comparator<PocketQueryList>() { + // just in case, lets sort the resulting list + Collections.sort(list, new Comparator<PocketQueryList>() { - @Override - public int compare(final PocketQueryList left, final PocketQueryList right) { - return String.CASE_INSENSITIVE_ORDER.compare(left.getName(), right.getName()); - } - }); + @Override + public int compare(final PocketQueryList left, final PocketQueryList right) { + return String.CASE_INSENSITIVE_ORDER.compare(left.getName(), right.getName()); + } + }); - return list; - } + return list; + } + }, RxUtils.networkScheduler); public static ImmutablePair<StatusCode, String> postLog(final String geocode, final String cacheid, final String[] viewstates, final LogType logType, final int year, final int month, final int day, @@ -1695,28 +1702,22 @@ public abstract class GCParser { Log.e("GCParser.loadLogsFromDetails: error " + statusCode + " when requesting log information"); return Observable.empty(); } - final String rawResponse = Network.getResponseData(response); - if (rawResponse == null) { + final InputStream responseStream = Network.getResponseStream(response); + if (responseStream == null) { Log.e("GCParser.loadLogsFromDetails: unable to read whole response"); return Observable.empty(); } - return parseLogs(logType != Logs.ALL, rawResponse); + return parseLogs(logType != Logs.ALL, responseStream); } }).subscribeOn(RxUtils.networkScheduler); } - private static Observable<LogEntry> parseLogs(final boolean markAsFriendsLog, final String rawResponse) { + private static Observable<LogEntry> parseLogs(final boolean markAsFriendsLog, final InputStream responseStream) { return Observable.create(new OnSubscribe<LogEntry>() { @Override public void call(final Subscriber<? super LogEntry> subscriber) { - // for non logged in users the log book is not shown - if (StringUtils.isBlank(rawResponse)) { - subscriber.onCompleted(); - return; - } - try { - final ObjectNode resp = (ObjectNode) JsonUtils.reader.readTree(rawResponse); + final ObjectNode resp = (ObjectNode) JsonUtils.reader.readTree(responseStream); if (!resp.path("status").asText().equals("success")) { Log.e("GCParser.loadLogsFromDetails: status is " + resp.path("status").asText("[absent]")); subscriber.onCompleted(); diff --git a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java index c392521..5fc3c2b 100644 --- a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java +++ b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java @@ -11,7 +11,7 @@ import cgeo.geocaching.utils.RxUtils; import org.apache.commons.io.IOUtils; import rx.Observable; -import rx.android.observables.AndroidObservable; +import rx.android.view.ViewObservable; import rx.functions.Action1; import rx.functions.Func0; @@ -64,7 +64,7 @@ public class RecaptchaHandler extends Handler { return Observable.empty(); } }); - AndroidObservable.bindActivity(activity, captcha).subscribeOn(RxUtils.networkScheduler).subscribe(new Action1<Bitmap>() { + ViewObservable.bindView(imageView, captcha).subscribeOn(RxUtils.networkScheduler).subscribe(new Action1<Bitmap>() { @Override public void call(final Bitmap bitmap) { imageView.setImageBitmap(bitmap); diff --git a/main/src/cgeo/geocaching/location/AndroidGeocoder.java b/main/src/cgeo/geocaching/location/AndroidGeocoder.java index 98ea285..d0d07e8 100644 --- a/main/src/cgeo/geocaching/location/AndroidGeocoder.java +++ b/main/src/cgeo/geocaching/location/AndroidGeocoder.java @@ -16,11 +16,6 @@ import android.location.Geocoder; import java.util.List; import java.util.Locale; -/** - * Encapsulation of the Android {@link Geocoder} with default error handling. All methods of this class - * are blocking and will do network lookups. - * - */ public class AndroidGeocoder { private final Geocoder geocoder; @@ -39,21 +34,49 @@ public class AndroidGeocoder { * @see Geocoder#getFromLocationName(String, int) */ public Observable<Address> getFromLocationName(@NonNull final String keyword) { + if (!Geocoder.isPresent()) { + return Observable.error(new RuntimeException("no Android geocoder")); + } return Observable.defer(new Func0<Observable<Address>>() { @Override public Observable<Address> call() { try { - final List<Address> addresses = geocoder.getFromLocationName(keyword, 20); - if (CollectionUtils.isEmpty(addresses)) { - return Observable.error(new RuntimeException("no result from Android geocoder")); - } - return Observable.from(addresses); + return addressesToObservable(geocoder.getFromLocationName(keyword, 20)); } catch (final Exception e) { - Log.i("Unable to use Android geocoder: " + e.getMessage()); + Log.i("Unable to use Android reverse geocoder: " + e.getMessage()); return Observable.error(e); } } }).subscribeOn(RxUtils.networkScheduler); } + /** + * Retrieve the physical address for coordinates. The work happens on the network scheduler. + * + * @param coords the coordinates + * @return an observable containing one location or an error + */ + public Observable<Address> getFromLocation(@NonNull final Geopoint coords) { + if (!Geocoder.isPresent()) { + return Observable.error(new RuntimeException("no Android reverse geocoder")); + } + return Observable.defer(new Func0<Observable<Address>>() { + @Override + public Observable<Address> call() { + try { + return addressesToObservable(geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 1)); + } catch (final Exception e) { + Log.i("Unable to use Android reverse geocoder: " + e.getMessage()); + return Observable.error(e); + } + } + }).subscribeOn(RxUtils.networkScheduler).first(); + } + + private static Observable<Address> addressesToObservable(final List<Address> addresses) { + return CollectionUtils.isEmpty(addresses) ? + Observable.<Address>error(new RuntimeException("no result from Android geocoder")) : + Observable.from(addresses); + } + } diff --git a/main/src/cgeo/geocaching/location/MapQuestGeocoder.java b/main/src/cgeo/geocaching/location/MapQuestGeocoder.java index 537ae40..cc4a6b5 100644 --- a/main/src/cgeo/geocaching/location/MapQuestGeocoder.java +++ b/main/src/cgeo/geocaching/location/MapQuestGeocoder.java @@ -39,11 +39,25 @@ public class MapQuestGeocoder { * @see android.location.Geocoder#getFromLocationName(String, int) */ public static Observable<Address> getFromLocationName(@NonNull final String address) { + return get("address", new Parameters("location", address, "maxResults", "20", "thumbMaps", "false")); + } + + /** + * Retrieve the physical address for coordinates. The work happens on the network scheduler. + * + * @param coords the coordinates + * @return an observable containing one location or an error + */ + public static Observable<Address> getFromLocation(@NonNull final Geopoint coords) { + return get("reverse", new Parameters("location", String.format(Locale.US, "%f,%f", coords.getLatitude(), coords.getLongitude()))).first(); + } + + private static Observable<Address> get(@NonNull final String method, @NonNull final Parameters parameters) { return Observable.defer(new Func0<Observable<Address>>() { @Override public Observable<Address> call() { - final ObjectNode response = Network.requestJSON("https://www.mapquestapi.com/geocoding/v1/address", - new Parameters("key", MAPQUEST_KEY, "location", address, "maxResults", "20", "thumbMaps", "false")); + final ObjectNode response = Network.requestJSON("https://www.mapquestapi.com/geocoding/v1/" + method, + parameters.put("key", MAPQUEST_KEY)); if (response == null) { Log.w("MapQuest decoder error: no response"); return Observable.error(new RuntimeException("no answer from MapQuest geocoder")); @@ -110,6 +124,10 @@ public class MapQuestGeocoder { break; case "Country": address.setCountryCode(content); + address.setCountryName(new Locale("", content).getDisplayCountry()); + break; + // Make checkers happy + default: break; } } diff --git a/main/src/cgeo/geocaching/sensors/Sensors.java b/main/src/cgeo/geocaching/sensors/Sensors.java index 498ec0e..80ed175 100644 --- a/main/src/cgeo/geocaching/sensors/Sensors.java +++ b/main/src/cgeo/geocaching/sensors/Sensors.java @@ -15,8 +15,6 @@ import rx.functions.Action1; import rx.functions.Func1; import android.content.Context; -import android.hardware.Sensor; -import android.hardware.SensorManager; import java.util.concurrent.atomic.AtomicBoolean; @@ -29,7 +27,7 @@ public class Sensors { @NonNull private volatile GeoData currentGeo = GeoData.DUMMY_LOCATION; private volatile float currentDirection = 0.0f; private volatile boolean hasValidLocation = false; - private final boolean hasMagneticFieldSensor; + private final boolean hasCompassCapabilities; private final CgeoApplication app = CgeoApplication.getInstance(); private static class InstanceHolder { @@ -53,8 +51,8 @@ public class Sensors { private Sensors() { gpsStatusObservable = GpsStatusProvider.create(app).replay(1).refCount(); - final SensorManager sensorManager = (SensorManager) app.getSystemService(Context.SENSOR_SERVICE); - hasMagneticFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null; + final Context context = CgeoApplication.getInstance().getApplicationContext(); + hasCompassCapabilities = RotationProvider.hasRotationSensor(context) || OrientationProvider.hasOrientationSensor(context); } public static final Sensors getInstance() { @@ -84,8 +82,8 @@ public class Sensors { public void setupDirectionObservable(final boolean useLowPower) { // If we have no magnetic sensor, there is no point in trying to setup any, we will always get the direction from the GPS. - if (!hasMagneticFieldSensor) { - Log.i("No magnetic field sensor, using only the GPS for the orientation"); + if (!hasCompassCapabilities) { + Log.i("No compass capabilities, using only the GPS for the orientation"); directionObservable = RxUtils.rememberLast(geoDataObservableLowPower.map(GPS_TO_DIRECTION).doOnNext(onNextrememberDirectionAction), 0f); return; } @@ -153,8 +151,8 @@ public class Sensors { return currentDirection; } - public boolean hasMagneticFieldSensor() { - return hasMagneticFieldSensor; + public boolean hasCompassCapabilities() { + return hasCompassCapabilities; } } diff --git a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java index 2f83028..ed09757 100644 --- a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java +++ b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java @@ -11,7 +11,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import rx.Observable; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; import rx.functions.Func0; import rx.util.async.Async; @@ -74,7 +74,7 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab loginDialog.setCancelable(false); Cookies.clearCookies(); - AndroidObservable.bindActivity(settingsActivity, Async.start(new Func0<ImmutablePair<StatusCode, Observable<Drawable>>>() { + AppObservable.bindActivity(settingsActivity, Async.start(new Func0<ImmutablePair<StatusCode, Observable<Drawable>>>() { @Override public ImmutablePair<StatusCode, Observable<Drawable>> call() { return login(); diff --git a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java index 1e8e00a..e016921 100644 --- a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java +++ b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java @@ -13,7 +13,7 @@ import ch.boye.httpclientandroidlib.HttpResponse; import org.apache.commons.lang3.StringUtils; import rx.Observable; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; import rx.functions.Func0; @@ -55,7 +55,7 @@ public class RegisterSend2CgeoPreference extends AbstractClickablePreference { activity.getString(R.string.init_sendToCgeo_registering), true); progressDialog.setCancelable(false); - AndroidObservable.bindActivity(activity, Observable.defer(new Func0<Observable<Integer>>() { + AppObservable.bindActivity(activity, Observable.defer(new Func0<Observable<Integer>>() { @Override public Observable<Integer> call() { final String nam = StringUtils.defaultString(deviceName); diff --git a/main/src/cgeo/geocaching/ui/ImagesList.java b/main/src/cgeo/geocaching/ui/ImagesList.java index aa81dd0..0126258 100644 --- a/main/src/cgeo/geocaching/ui/ImagesList.java +++ b/main/src/cgeo/geocaching/ui/ImagesList.java @@ -13,7 +13,7 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import rx.Subscription; -import rx.android.observables.AndroidObservable; +import rx.android.view.ViewObservable; import rx.functions.Action0; import rx.functions.Action1; import rx.subscriptions.CompositeSubscription; @@ -122,7 +122,7 @@ public class ImagesList { final ImageView imageView = (ImageView) inflater.inflate(R.layout.image_item, rowView, false); assert imageView != null; - subscriptions.add(AndroidObservable.bindActivity(activity, imgGetter.fetchDrawable(img.getUrl())).subscribe(new Action1<BitmapDrawable>() { + subscriptions.add(ViewObservable.bindView(imageView, imgGetter.fetchDrawable(img.getUrl())).subscribe(new Action1<BitmapDrawable>() { @Override public void call(final BitmapDrawable image) { display(imageView, image, img, rowView); diff --git a/play-services-base/lint.xml b/play-services-base/lint.xml new file mode 100644 index 0000000..715caf3 --- /dev/null +++ b/play-services-base/lint.xml @@ -0,0 +1,190 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lint> + <issue id="AaptCrash" severity="ignore" /> + <issue id="AccidentalOctal" severity="ignore" /> + <issue id="AdapterViewChildren" severity="ignore" /> + <issue id="AddJavascriptInterface" severity="ignore" /> + <issue id="AllowBackup" severity="ignore" /> + <issue id="AlwaysShowAction" severity="ignore" /> + <issue id="AndroidGradlePluginVersion" severity="ignore" /> + <issue id="AppCompatMethod" severity="ignore" /> + <issue id="AppCompatResource" severity="ignore" /> + <issue id="Assert" severity="ignore" /> + <issue id="ButtonCase" severity="ignore" /> + <issue id="ButtonOrder" severity="ignore" /> + <issue id="ButtonStyle" severity="ignore" /> + <issue id="ByteOrderMark" severity="ignore" /> + <issue id="ClickableViewAccessibility" severity="ignore" /> + <issue id="CommitPrefEdits" severity="ignore" /> + <issue id="CommitTransaction" severity="ignore" /> + <issue id="ContentDescription" severity="ignore" /> + <issue id="CustomViewStyleable" severity="ignore" /> + <issue id="CutPasteId" severity="ignore" /> + <issue id="DalvikOverride" severity="ignore" /> + <issue id="DefaultLocale" severity="ignore" /> + <issue id="Deprecated" severity="ignore" /> + <issue id="DeviceAdmin" severity="ignore" /> + <issue id="DisableBaselineAlignment" severity="ignore" /> + <issue id="DrawAllocation" severity="ignore" /> + <issue id="DuplicateActivity" severity="ignore" /> + <issue id="DuplicateDefinition" severity="ignore" /> + <issue id="DuplicateIds" severity="ignore" /> + <issue id="DuplicateIncludedIds" severity="ignore" /> + <issue id="DuplicateUsesFeature" severity="ignore" /> + <issue id="EnforceUTF8" severity="ignore" /> + <issue id="ExportedContentProvider" severity="ignore" /> + <issue id="ExportedPreferenceActivity" severity="ignore" /> + <issue id="ExportedReceiver" severity="ignore" /> + <issue id="ExportedService" severity="ignore" /> + <issue id="ExtraText" severity="ignore" /> + <issue id="ExtraTranslation" severity="ignore" /> + <issue id="FloatMath" severity="ignore" /> + <issue id="GetInstance" severity="ignore" /> + <issue id="GifUsage" severity="ignore" /> + <issue id="GradleCompatible" severity="ignore" /> + <issue id="GradleDependency" severity="ignore" /> + <issue id="GradleDeprecated" severity="ignore" /> + <issue id="GradleDynamicVersion" severity="ignore" /> + <issue id="GradleGetter" severity="ignore" /> + <issue id="GradleIdeError" severity="ignore" /> + <issue id="GradleOverrides" severity="ignore" /> + <issue id="GradlePath" severity="ignore" /> + <issue id="GrantAllUris" severity="ignore" /> + <issue id="GridLayout" severity="ignore" /> + <issue id="HandlerLeak" severity="ignore" /> + <issue id="HardcodedDebugMode" severity="ignore" /> + <issue id="HardcodedText" severity="ignore" /> + <issue id="IconColors" severity="ignore" /> + <issue id="IconDensities" severity="ignore" /> + <issue id="IconDipSize" severity="ignore" /> + <issue id="IconDuplicates" severity="ignore" /> + <issue id="IconDuplicatesConfig" severity="ignore" /> + <issue id="IconExtension" severity="ignore" /> + <issue id="IconLauncherShape" severity="ignore" /> + <issue id="IconLocation" severity="ignore" /> + <issue id="IconMissingDensityFolder" severity="ignore" /> + <issue id="IconMixedNinePatch" severity="ignore" /> + <issue id="IconNoDpi" severity="ignore" /> + <issue id="IconXmlAndPng" severity="ignore" /> + <issue id="IllegalResourceRef" severity="ignore" /> + <issue id="ImpliedQuantity" severity="ignore" /> + <issue id="InOrMmUsage" severity="ignore" /> + <issue id="IncludeLayoutParam" severity="ignore" /> + <issue id="InconsistentArrays" severity="ignore" /> + <issue id="InconsistentLayout" severity="ignore" /> + <issue id="InefficientWeight" severity="ignore" /> + <issue id="InflateParams" severity="ignore" /> + <issue id="InlinedApi" severity="ignore" /> + <issue id="InnerclassSeparator" severity="ignore" /> + <issue id="Instantiatable" severity="ignore" /> + <issue id="InvalidId" severity="ignore" /> + <issue id="InvalidPackage" severity="ignore" /> + <issue id="JavascriptInterface" severity="ignore" /> + <issue id="LabelFor" severity="ignore" /> + <issue id="LibraryCustomView" severity="ignore" /> + <issue id="LocalSuppress" severity="ignore" /> + <issue id="LocaleFolder" severity="ignore" /> + <issue id="MangledCRLF" severity="ignore" /> + <issue id="ManifestOrder" severity="ignore" /> + <issue id="ManifestTypo" severity="ignore" /> + <issue id="MenuTitle" severity="ignore" /> + <issue id="MergeRootFrame" severity="ignore" /> + <issue id="MissingApplicationIcon" severity="ignore" /> + <issue id="MissingId" severity="ignore" /> + <issue id="MissingPrefix" severity="ignore" /> + <issue id="MissingQuantity" severity="ignore" /> + <issue id="MissingRegistered" severity="ignore" /> + <issue id="MissingSuperCall" severity="ignore" /> + <issue id="MissingTranslation" severity="ignore" /> + <issue id="MissingVersion" severity="ignore" /> + <issue id="MockLocation" severity="ignore" /> + <issue id="MultipleUsesSdk" severity="ignore" /> + <issue id="NamespaceTypo" severity="ignore" /> + <issue id="NestedScrolling" severity="ignore" /> + <issue id="NestedWeights" severity="ignore" /> + <issue id="NewApi" severity="ignore" /> + <issue id="NfcTechWhitespace" severity="ignore" /> + <issue id="NotSibling" severity="ignore" /> + <issue id="ObsoleteLayoutParam" severity="ignore" /> + <issue id="OldTargetApi" severity="ignore" /> + <issue id="OnClick" severity="ignore" /> + <issue id="Orientation" severity="ignore" /> + <issue id="Overdraw" severity="ignore" /> + <issue id="Override" severity="ignore" /> + <issue id="PackagedPrivateKey" severity="ignore" /> + <issue id="ParcelCreator" severity="ignore" /> + <issue id="PrivateResource" severity="ignore" /> + <issue id="Proguard" severity="ignore" /> + <issue id="ProguardSplit" severity="ignore" /> + <issue id="PropertyEscape" severity="ignore" /> + <issue id="ProtectedPermissions" severity="ignore" /> + <issue id="PxUsage" severity="ignore" /> + <issue id="Recycle" severity="ignore" /> + <issue id="ReferenceType" severity="ignore" /> + <issue id="Registered" severity="ignore" /> + <issue id="RequiredSize" severity="ignore" /> + <issue id="ResAuto" severity="ignore" /> + <issue id="ResourceAsColor" severity="ignore" /> + <issue id="ResourceCycle" severity="ignore" /> + <issue id="ResourceName" severity="ignore" /> + <issue id="RtlCompat" severity="ignore" /> + <issue id="RtlEnabled" severity="ignore" /> + <issue id="RtlHardcoded" severity="ignore" /> + <issue id="RtlSymmetry" severity="ignore" /> + <issue id="ScrollViewCount" severity="ignore" /> + <issue id="ScrollViewSize" severity="ignore" /> + <issue id="SdCardPath" severity="ignore" /> + <issue id="SecureRandom" severity="ignore" /> + <issue id="ServiceCast" severity="ignore" /> + <issue id="SetJavaScriptEnabled" severity="ignore" /> + <issue id="ShowToast" severity="ignore" /> + <issue id="SignatureOrSystemPermissions" severity="ignore" /> + <issue id="SimpleDateFormat" severity="ignore" /> + <issue id="SmallSp" severity="ignore" /> + <issue id="SpUsage" severity="ignore" /> + <issue id="StateListReachable" severity="ignore" /> + <issue id="StringFormatCount" severity="ignore" /> + <issue id="StringFormatInvalid" severity="ignore" /> + <issue id="StringFormatMatches" severity="ignore" /> + <issue id="StringShouldBeInt" severity="ignore" /> + <issue id="Suspicious0dp" severity="ignore" /> + <issue id="SuspiciousImport" severity="ignore" /> + <issue id="TextFields" severity="ignore" /> + <issue id="TextViewEdits" severity="ignore" /> + <issue id="TooDeepLayout" severity="ignore" /> + <issue id="TooManyViews" severity="ignore" /> + <issue id="TrulyRandom" severity="ignore" /> + <issue id="TypographyDashes" severity="ignore" /> + <issue id="TypographyEllipsis" severity="ignore" /> + <issue id="TypographyFractions" severity="ignore" /> + <issue id="TypographyOther" severity="ignore" /> + <issue id="Typos" severity="ignore" /> + <issue id="UniquePermission" severity="ignore" /> + <issue id="UnknownId" severity="ignore" /> + <issue id="UnknownIdInLayout" severity="ignore" /> + <issue id="UnlocalizedSms" severity="ignore" /> + <issue id="UnusedAttribute" severity="ignore" /> + <issue id="UnusedNamespace" severity="ignore" /> + <issue id="UnusedQuantity" severity="ignore" /> + <issue id="UnusedResources" severity="ignore" /> + <issue id="UseCheckPermission" severity="ignore" /> + <issue id="UseCompoundDrawables" severity="ignore" /> + <issue id="UseSparseArrays" severity="ignore" /> + <issue id="UseValueOf" severity="ignore" /> + <issue id="UselessLeaf" severity="ignore" /> + <issue id="UselessParent" severity="ignore" /> + <issue id="UsesMinSdkAttributes" severity="ignore" /> + <issue id="ValidFragment" severity="ignore" /> + <issue id="ViewConstructor" severity="ignore" /> + <issue id="ViewHolder" severity="ignore" /> + <issue id="ViewTag" severity="ignore" /> + <issue id="Wakelock" severity="ignore" /> + <issue id="WebViewLayout" severity="ignore" /> + <issue id="WorldReadableFiles" severity="ignore" /> + <issue id="WorldWriteableFiles" severity="ignore" /> + <issue id="WrongCall" severity="ignore" /> + <issue id="WrongCase" severity="ignore" /> + <issue id="WrongFolder" severity="ignore" /> + <issue id="WrongManifestParent" severity="ignore" /> + <issue id="WrongViewCast" severity="ignore" /> +</lint>
\ No newline at end of file diff --git a/play-services-location/lint.xml b/play-services-location/lint.xml new file mode 100644 index 0000000..715caf3 --- /dev/null +++ b/play-services-location/lint.xml @@ -0,0 +1,190 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lint> + <issue id="AaptCrash" severity="ignore" /> + <issue id="AccidentalOctal" severity="ignore" /> + <issue id="AdapterViewChildren" severity="ignore" /> + <issue id="AddJavascriptInterface" severity="ignore" /> + <issue id="AllowBackup" severity="ignore" /> + <issue id="AlwaysShowAction" severity="ignore" /> + <issue id="AndroidGradlePluginVersion" severity="ignore" /> + <issue id="AppCompatMethod" severity="ignore" /> + <issue id="AppCompatResource" severity="ignore" /> + <issue id="Assert" severity="ignore" /> + <issue id="ButtonCase" severity="ignore" /> + <issue id="ButtonOrder" severity="ignore" /> + <issue id="ButtonStyle" severity="ignore" /> + <issue id="ByteOrderMark" severity="ignore" /> + <issue id="ClickableViewAccessibility" severity="ignore" /> + <issue id="CommitPrefEdits" severity="ignore" /> + <issue id="CommitTransaction" severity="ignore" /> + <issue id="ContentDescription" severity="ignore" /> + <issue id="CustomViewStyleable" severity="ignore" /> + <issue id="CutPasteId" severity="ignore" /> + <issue id="DalvikOverride" severity="ignore" /> + <issue id="DefaultLocale" severity="ignore" /> + <issue id="Deprecated" severity="ignore" /> + <issue id="DeviceAdmin" severity="ignore" /> + <issue id="DisableBaselineAlignment" severity="ignore" /> + <issue id="DrawAllocation" severity="ignore" /> + <issue id="DuplicateActivity" severity="ignore" /> + <issue id="DuplicateDefinition" severity="ignore" /> + <issue id="DuplicateIds" severity="ignore" /> + <issue id="DuplicateIncludedIds" severity="ignore" /> + <issue id="DuplicateUsesFeature" severity="ignore" /> + <issue id="EnforceUTF8" severity="ignore" /> + <issue id="ExportedContentProvider" severity="ignore" /> + <issue id="ExportedPreferenceActivity" severity="ignore" /> + <issue id="ExportedReceiver" severity="ignore" /> + <issue id="ExportedService" severity="ignore" /> + <issue id="ExtraText" severity="ignore" /> + <issue id="ExtraTranslation" severity="ignore" /> + <issue id="FloatMath" severity="ignore" /> + <issue id="GetInstance" severity="ignore" /> + <issue id="GifUsage" severity="ignore" /> + <issue id="GradleCompatible" severity="ignore" /> + <issue id="GradleDependency" severity="ignore" /> + <issue id="GradleDeprecated" severity="ignore" /> + <issue id="GradleDynamicVersion" severity="ignore" /> + <issue id="GradleGetter" severity="ignore" /> + <issue id="GradleIdeError" severity="ignore" /> + <issue id="GradleOverrides" severity="ignore" /> + <issue id="GradlePath" severity="ignore" /> + <issue id="GrantAllUris" severity="ignore" /> + <issue id="GridLayout" severity="ignore" /> + <issue id="HandlerLeak" severity="ignore" /> + <issue id="HardcodedDebugMode" severity="ignore" /> + <issue id="HardcodedText" severity="ignore" /> + <issue id="IconColors" severity="ignore" /> + <issue id="IconDensities" severity="ignore" /> + <issue id="IconDipSize" severity="ignore" /> + <issue id="IconDuplicates" severity="ignore" /> + <issue id="IconDuplicatesConfig" severity="ignore" /> + <issue id="IconExtension" severity="ignore" /> + <issue id="IconLauncherShape" severity="ignore" /> + <issue id="IconLocation" severity="ignore" /> + <issue id="IconMissingDensityFolder" severity="ignore" /> + <issue id="IconMixedNinePatch" severity="ignore" /> + <issue id="IconNoDpi" severity="ignore" /> + <issue id="IconXmlAndPng" severity="ignore" /> + <issue id="IllegalResourceRef" severity="ignore" /> + <issue id="ImpliedQuantity" severity="ignore" /> + <issue id="InOrMmUsage" severity="ignore" /> + <issue id="IncludeLayoutParam" severity="ignore" /> + <issue id="InconsistentArrays" severity="ignore" /> + <issue id="InconsistentLayout" severity="ignore" /> + <issue id="InefficientWeight" severity="ignore" /> + <issue id="InflateParams" severity="ignore" /> + <issue id="InlinedApi" severity="ignore" /> + <issue id="InnerclassSeparator" severity="ignore" /> + <issue id="Instantiatable" severity="ignore" /> + <issue id="InvalidId" severity="ignore" /> + <issue id="InvalidPackage" severity="ignore" /> + <issue id="JavascriptInterface" severity="ignore" /> + <issue id="LabelFor" severity="ignore" /> + <issue id="LibraryCustomView" severity="ignore" /> + <issue id="LocalSuppress" severity="ignore" /> + <issue id="LocaleFolder" severity="ignore" /> + <issue id="MangledCRLF" severity="ignore" /> + <issue id="ManifestOrder" severity="ignore" /> + <issue id="ManifestTypo" severity="ignore" /> + <issue id="MenuTitle" severity="ignore" /> + <issue id="MergeRootFrame" severity="ignore" /> + <issue id="MissingApplicationIcon" severity="ignore" /> + <issue id="MissingId" severity="ignore" /> + <issue id="MissingPrefix" severity="ignore" /> + <issue id="MissingQuantity" severity="ignore" /> + <issue id="MissingRegistered" severity="ignore" /> + <issue id="MissingSuperCall" severity="ignore" /> + <issue id="MissingTranslation" severity="ignore" /> + <issue id="MissingVersion" severity="ignore" /> + <issue id="MockLocation" severity="ignore" /> + <issue id="MultipleUsesSdk" severity="ignore" /> + <issue id="NamespaceTypo" severity="ignore" /> + <issue id="NestedScrolling" severity="ignore" /> + <issue id="NestedWeights" severity="ignore" /> + <issue id="NewApi" severity="ignore" /> + <issue id="NfcTechWhitespace" severity="ignore" /> + <issue id="NotSibling" severity="ignore" /> + <issue id="ObsoleteLayoutParam" severity="ignore" /> + <issue id="OldTargetApi" severity="ignore" /> + <issue id="OnClick" severity="ignore" /> + <issue id="Orientation" severity="ignore" /> + <issue id="Overdraw" severity="ignore" /> + <issue id="Override" severity="ignore" /> + <issue id="PackagedPrivateKey" severity="ignore" /> + <issue id="ParcelCreator" severity="ignore" /> + <issue id="PrivateResource" severity="ignore" /> + <issue id="Proguard" severity="ignore" /> + <issue id="ProguardSplit" severity="ignore" /> + <issue id="PropertyEscape" severity="ignore" /> + <issue id="ProtectedPermissions" severity="ignore" /> + <issue id="PxUsage" severity="ignore" /> + <issue id="Recycle" severity="ignore" /> + <issue id="ReferenceType" severity="ignore" /> + <issue id="Registered" severity="ignore" /> + <issue id="RequiredSize" severity="ignore" /> + <issue id="ResAuto" severity="ignore" /> + <issue id="ResourceAsColor" severity="ignore" /> + <issue id="ResourceCycle" severity="ignore" /> + <issue id="ResourceName" severity="ignore" /> + <issue id="RtlCompat" severity="ignore" /> + <issue id="RtlEnabled" severity="ignore" /> + <issue id="RtlHardcoded" severity="ignore" /> + <issue id="RtlSymmetry" severity="ignore" /> + <issue id="ScrollViewCount" severity="ignore" /> + <issue id="ScrollViewSize" severity="ignore" /> + <issue id="SdCardPath" severity="ignore" /> + <issue id="SecureRandom" severity="ignore" /> + <issue id="ServiceCast" severity="ignore" /> + <issue id="SetJavaScriptEnabled" severity="ignore" /> + <issue id="ShowToast" severity="ignore" /> + <issue id="SignatureOrSystemPermissions" severity="ignore" /> + <issue id="SimpleDateFormat" severity="ignore" /> + <issue id="SmallSp" severity="ignore" /> + <issue id="SpUsage" severity="ignore" /> + <issue id="StateListReachable" severity="ignore" /> + <issue id="StringFormatCount" severity="ignore" /> + <issue id="StringFormatInvalid" severity="ignore" /> + <issue id="StringFormatMatches" severity="ignore" /> + <issue id="StringShouldBeInt" severity="ignore" /> + <issue id="Suspicious0dp" severity="ignore" /> + <issue id="SuspiciousImport" severity="ignore" /> + <issue id="TextFields" severity="ignore" /> + <issue id="TextViewEdits" severity="ignore" /> + <issue id="TooDeepLayout" severity="ignore" /> + <issue id="TooManyViews" severity="ignore" /> + <issue id="TrulyRandom" severity="ignore" /> + <issue id="TypographyDashes" severity="ignore" /> + <issue id="TypographyEllipsis" severity="ignore" /> + <issue id="TypographyFractions" severity="ignore" /> + <issue id="TypographyOther" severity="ignore" /> + <issue id="Typos" severity="ignore" /> + <issue id="UniquePermission" severity="ignore" /> + <issue id="UnknownId" severity="ignore" /> + <issue id="UnknownIdInLayout" severity="ignore" /> + <issue id="UnlocalizedSms" severity="ignore" /> + <issue id="UnusedAttribute" severity="ignore" /> + <issue id="UnusedNamespace" severity="ignore" /> + <issue id="UnusedQuantity" severity="ignore" /> + <issue id="UnusedResources" severity="ignore" /> + <issue id="UseCheckPermission" severity="ignore" /> + <issue id="UseCompoundDrawables" severity="ignore" /> + <issue id="UseSparseArrays" severity="ignore" /> + <issue id="UseValueOf" severity="ignore" /> + <issue id="UselessLeaf" severity="ignore" /> + <issue id="UselessParent" severity="ignore" /> + <issue id="UsesMinSdkAttributes" severity="ignore" /> + <issue id="ValidFragment" severity="ignore" /> + <issue id="ViewConstructor" severity="ignore" /> + <issue id="ViewHolder" severity="ignore" /> + <issue id="ViewTag" severity="ignore" /> + <issue id="Wakelock" severity="ignore" /> + <issue id="WebViewLayout" severity="ignore" /> + <issue id="WorldReadableFiles" severity="ignore" /> + <issue id="WorldWriteableFiles" severity="ignore" /> + <issue id="WrongCall" severity="ignore" /> + <issue id="WrongCase" severity="ignore" /> + <issue id="WrongFolder" severity="ignore" /> + <issue id="WrongManifestParent" severity="ignore" /> + <issue id="WrongViewCast" severity="ignore" /> +</lint>
\ No newline at end of file diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml index 814b6de..3ffded7 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -5,8 +5,8 @@ android:versionName="1.0" > <uses-sdk - android:minSdkVersion="8" - android:targetSdkVersion="13" /> + android:minSdkVersion="9" + android:targetSdkVersion="19" /> <uses-feature android:name="android.hardware.screen.portrait" @@ -31,4 +31,4 @@ </activity> </application> -</manifest>
\ No newline at end of file +</manifest> diff --git a/tests/src/cgeo/CGeoTestCase.java b/tests/src/cgeo/CGeoTestCase.java index 5759bc7..7fc1e8d 100644 --- a/tests/src/cgeo/CGeoTestCase.java +++ b/tests/src/cgeo/CGeoTestCase.java @@ -2,6 +2,7 @@ package cgeo; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.DataStore; +import cgeo.geocaching.Geocache; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; import cgeo.geocaching.settings.Settings; @@ -44,6 +45,17 @@ public abstract class CGeoTestCase extends ApplicationTestCase<CgeoApplication> } /** + * Remove completely the previous instance of a cache, then save this object into the database + * and the cache cache. + * + * @param cache the fresh cache to save + */ + protected static void saveFreshCacheToDB(final Geocache cache) { + removeCacheCompletely(cache.getGeocode()); + DataStore.saveCache(cache, LoadFlags.SAVE_ALL); + } + + /** * must be called once before setting the flags * can be called again after restoring the flags */ diff --git a/tests/src/cgeo/geocaching/GeocacheTest.java b/tests/src/cgeo/geocaching/GeocacheTest.java index 954b492..37b6883 100644 --- a/tests/src/cgeo/geocaching/GeocacheTest.java +++ b/tests/src/cgeo/geocaching/GeocacheTest.java @@ -12,6 +12,7 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.List; @@ -66,13 +67,12 @@ public class GeocacheTest extends CGeoTestCase { } private void assertWaypointsParsed(final String note, final int expectedWaypoints) { - recordMapStoreFlags(); try { setMapStoreFlags(false, false); - Geocache cache = new Geocache(); + final Geocache cache = new Geocache(); final String geocode = "Test" + System.nanoTime(); cache.setGeocode(geocode); cache.setWaypoints(new ArrayList<Waypoint>(), false); @@ -94,52 +94,106 @@ public class GeocacheTest extends CGeoTestCase { } } - public static void testMergeDownloadedStored() { + public static void testMergeDownloaded() { + final Geocache previous = new Geocache(); + previous.setGeocode("GC12345"); + previous.setDetailed(true); + previous.setDisabled(true); + previous.setType(CacheType.TRADITIONAL); + previous.setCoords(new Geopoint(40.0, 8.0)); + previous.setDescription("Test1"); + previous.setAttributes(Collections.singletonList("TestAttribute")); + previous.setShortDescription("Short"); + previous.setHint("Hint"); + removeCacheCompletely(previous.getGeocode()); + + final Geocache download = new Geocache(); + download.setGeocode("GC12345"); + download.setDetailed(true); + download.setDisabled(false); + download.setType(CacheType.MULTI); + download.setCoords(new Geopoint(41.0, 9.0)); + download.setDescription("Test2"); - Geocache stored = new Geocache(); + download.gatherMissingFrom(previous); + + assertThat(download.isDetailed()).as("merged detailed").isTrue(); + assertThat(download.isDisabled()).as("merged disabled").isFalse(); + assertThat(download.getType()).as("merged download").isEqualTo(CacheType.MULTI); + assertThat(download.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(41.0, 9.0)); + assertThat(download.getDescription()).as("merged description").isEqualTo("Test2"); + assertThat(download.getShortDescription()).as("merged short description").isEmpty(); + assertThat(download.getAttributes()).as("merged attributes").isEmpty(); + assertThat(download.getHint()).as("merged hint").isEmpty(); + } + + public static void testMergeDownloadedStored() { + final Geocache stored = new Geocache(); stored.setGeocode("GC12345"); stored.setDetailed(true); stored.setDisabled(true); stored.setType(CacheType.TRADITIONAL); stored.setCoords(new Geopoint(40.0, 8.0)); stored.setDescription("Test1"); - ArrayList<String> attributes = new ArrayList<String>(1); - attributes.add("TestAttribute"); - stored.setAttributes(attributes); + stored.setAttributes(Collections.singletonList("TestAttribute")); stored.setShortDescription("Short"); stored.setHint("Hint"); + saveFreshCacheToDB(stored); - Geocache download = new Geocache(); + final Geocache download = new Geocache(); download.setGeocode("GC12345"); download.setDetailed(true); download.setDisabled(false); download.setType(CacheType.MULTI); download.setCoords(new Geopoint(41.0, 9.0)); download.setDescription("Test2"); + download.setAttributes(Collections.<String>emptyList()); download.gatherMissingFrom(stored); assertThat(download.isDetailed()).as("merged detailed").isTrue(); assertThat(download.isDisabled()).as("merged disabled").isFalse(); - assertEquals("Type not merged correctly", CacheType.MULTI, download.getType()); - assertEquals("Longitude not merged correctly", 9.0, download.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 41.0, download.getCoords().getLatitude(), 0.1); - assertEquals("Description not merged correctly", "Test2", download.getDescription()); - assertEquals("ShortDescription not merged correctly", "", download.getShortDescription()); - assertEquals("Attributes not merged correctly", new ArrayList<String>(0), download.getAttributes()); - assertEquals("Hint not merged correctly", "", download.getHint()); + assertThat(download.getType()).as("merged download").isEqualTo(CacheType.MULTI); + assertThat(download.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(41.0, 9.0)); + assertThat(download.getDescription()).as("merged description").isEqualTo("Test2"); + assertThat(download.getShortDescription()).as("merged short description").isEmpty(); + assertThat(download.getAttributes()).as("merged attributes").isEmpty(); + assertThat(download.getHint()).as("merged hint").isEmpty(); } - public static void testMergeLivemapStored() { + public static void testMergeLivemap() { + final Geocache previous = new Geocache(); + previous.setGeocode("GC12345"); + previous.setDetailed(true); + previous.setDisabled(true); + previous.setType(CacheType.TRADITIONAL); + previous.setCoords(new Geopoint(40.0, 8.0)); + removeCacheCompletely(previous.getGeocode()); + + final Geocache livemap = new Geocache(); + livemap.setGeocode("GC12345"); + livemap.setType(CacheType.MULTI, 12); + livemap.setCoords(new Geopoint(41.0, 9.0), 12); + + livemap.gatherMissingFrom(previous); + + assertThat(livemap.isDetailed()).as("merged detailed").isTrue(); + assertThat(livemap.isDisabled()).as("merged disabled").isTrue(); + assertThat(livemap.getType()).as("merged type").isEqualTo(CacheType.TRADITIONAL); + assertThat(livemap.getCoords()).as("merged coordinates").isEqualToComparingFieldByField(new Geopoint(40.0, 8.0)); + assertThat(livemap.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(previous.getCoordZoomLevel()); + } - Geocache stored = new Geocache(); + public static void testMergeLivemapStored() { + final Geocache stored = new Geocache(); stored.setGeocode("GC12345"); stored.setDetailed(true); stored.setDisabled(true); stored.setType(CacheType.TRADITIONAL); stored.setCoords(new Geopoint(40.0, 8.0)); + saveFreshCacheToDB(stored); - Geocache livemap = new Geocache(); + final Geocache livemap = new Geocache(); livemap.setGeocode("GC12345"); livemap.setType(CacheType.MULTI, 12); livemap.setCoords(new Geopoint(41.0, 9.0), 12); @@ -148,90 +202,81 @@ public class GeocacheTest extends CGeoTestCase { assertThat(livemap.isDetailed()).as("merged detailed").isTrue(); assertThat(livemap.isDisabled()).as("merged disabled").isTrue(); - assertEquals("Type not merged correctly", CacheType.TRADITIONAL, livemap.getType()); - assertEquals("Longitude not merged correctly", 8.0, livemap.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 40.0, livemap.getCoords().getLatitude(), 0.1); - assertEquals("Zoomlevel not merged correctly", stored.getCoordZoomLevel(), livemap.getCoordZoomLevel()); + assertThat(livemap.getType()).as("merged type").isEqualTo(CacheType.TRADITIONAL); + assertThat(livemap.getCoords()).as("merged coordinates").isEqualToComparingFieldByField(new Geopoint(40.0, 8.0)); + assertThat(livemap.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(stored.getCoordZoomLevel()); } public static void testMergeLivemapZoomin() { - - Geocache livemapFirst = new Geocache(); + final Geocache livemapFirst = new Geocache(); livemapFirst.setGeocode("GC12345"); livemapFirst.setType(CacheType.TRADITIONAL); livemapFirst.setCoords(new Geopoint(40.0, 8.0), 11); - Geocache livemapSecond = new Geocache(); + final Geocache livemapSecond = new Geocache(); livemapSecond.setGeocode("GC12345"); livemapSecond.setType(CacheType.MULTI); livemapSecond.setCoords(new Geopoint(41.0, 9.0), 12); livemapSecond.gatherMissingFrom(livemapFirst); - assertEquals("Type not merged correctly", CacheType.MULTI, livemapSecond.getType()); - assertEquals("Longitude not merged correctly", 9.0, livemapSecond.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 41.0, livemapSecond.getCoords().getLatitude(), 0.1); - assertEquals("Zoomlevel not merged correctly", 12, livemapSecond.getCoordZoomLevel()); + assertThat(livemapSecond.getType()).as("merged type").isEqualTo(CacheType.MULTI); + assertThat(livemapSecond.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(41.0, 9.0)); + assertThat(livemapSecond.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(12); } public static void testMergeLivemapZoomout() { - - Geocache livemapFirst = new Geocache(); + final Geocache livemapFirst = new Geocache(); livemapFirst.setGeocode("GC12345"); livemapFirst.setType(CacheType.TRADITIONAL, 12); livemapFirst.setCoords(new Geopoint(40.0, 8.0), 12); - Geocache livemapSecond = new Geocache(); + final Geocache livemapSecond = new Geocache(); livemapSecond.setGeocode("GC12345"); livemapSecond.setType(CacheType.MULTI, 11); livemapSecond.setCoords(new Geopoint(41.0, 9.0), 11); livemapSecond.gatherMissingFrom(livemapFirst); - assertEquals("Type not merged correctly", CacheType.TRADITIONAL, livemapSecond.getType()); - assertEquals("Longitude not merged correctly", 8.0, livemapSecond.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 40.0, livemapSecond.getCoords().getLatitude(), 0.1); - assertEquals("Zoomlevel not merged correctly", 12, livemapSecond.getCoordZoomLevel()); + assertThat(livemapSecond.getType()).as("merged type").isEqualTo(CacheType.TRADITIONAL); + assertThat(livemapSecond.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(40.0, 8.0)); + assertThat(livemapSecond.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(12); } public static void testMergePopupLivemap() { - - Geocache livemap = new Geocache(); + final Geocache livemap = new Geocache(); livemap.setGeocode("GC12345"); livemap.setCoords(new Geopoint(40.0, 8.0), 12); livemap.setFound(true); - Geocache popup = new Geocache(); + final Geocache popup = new Geocache(); popup.setGeocode("GC12345"); popup.setType(CacheType.MULTI); popup.gatherMissingFrom(livemap); - assertEquals("Type not merged correctly", CacheType.MULTI, popup.getType()); - assertEquals("Longitude not merged correctly", 8.0, popup.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 40.0, popup.getCoords().getLatitude(), 0.1); - assertThat(popup.isFound()).overridingErrorMessage("Found not merged correctly").isTrue(); - assertEquals("Zoomlevel not merged correctly", 12, popup.getCoordZoomLevel()); + assertThat(popup.getType()).as("merged type").isEqualTo(CacheType.MULTI); + assertThat(popup.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(40.0, 8.0)); + assertThat(popup.isFound()).overridingErrorMessage("merged found").isTrue(); + assertThat(popup.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(12); } public static void testMergeLivemapBMSearched() { - - Geocache bmsearched = new Geocache(); + final Geocache bmsearched = new Geocache(); bmsearched.setGeocode("GC12345"); - Geocache livemap = new Geocache(); + final Geocache livemap = new Geocache(); livemap.setGeocode("GC12345"); livemap.setCoords(new Geopoint(40.0, 8.0), 12); livemap.gatherMissingFrom(bmsearched); - assertEquals("Longitude not merged correctly", 8.0, livemap.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 40.0, livemap.getCoords().getLatitude(), 0.1); - assertEquals("Zoomlevel not merged correctly", 12, livemap.getCoordZoomLevel()); + assertThat(livemap.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(40.0, 8.0)); + assertThat(livemap.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(12); } public static void testNameForSorting() { - Geocache cache = new Geocache(); + final Geocache cache = new Geocache(); cache.setName("GR8 01-01"); assertThat(cache.getNameForSorting()).isEqualTo("GR000008 000001-000001"); } @@ -253,7 +298,7 @@ public class GeocacheTest extends CGeoTestCase { } public static void testGuessEventTimeShortDescription() { - Geocache cache = new Geocache(); + final Geocache cache = new Geocache(); cache.setType(CacheType.EVENT); cache.setDescription(StringUtils.EMPTY); cache.setShortDescription("text 14:20 text"); @@ -276,13 +321,13 @@ public class GeocacheTest extends CGeoTestCase { } public static void testGetPossibleLogTypes() throws Exception { - Geocache gcCache = new Geocache(); + final Geocache gcCache = new Geocache(); gcCache.setGeocode("GC123"); gcCache.setType(CacheType.WEBCAM); assertThat(gcCache.getPossibleLogTypes()).as("possible GC cache log types").contains(LogType.WEBCAM_PHOTO_TAKEN); assertThat(gcCache.getPossibleLogTypes()).as("possible GC cache log types").contains(LogType.NEEDS_MAINTENANCE); - Geocache ocCache = new Geocache(); + final Geocache ocCache = new Geocache(); ocCache.setGeocode("OC1234"); ocCache.setType(CacheType.TRADITIONAL); assertThat(ocCache.getPossibleLogTypes()).as("traditional cache possible log types").doesNotContain(LogType.WEBCAM_PHOTO_TAKEN); @@ -290,24 +335,24 @@ public class GeocacheTest extends CGeoTestCase { } public static void testLogTypeEventPast() throws Exception { - Calendar today = Calendar.getInstance(); + final Calendar today = Calendar.getInstance(); today.add(Calendar.DAY_OF_MONTH, -1); assertThat(createEventCache(today).getDefaultLogType()).isEqualTo(LogType.ATTENDED); } public static void testLogTypeEventToday() throws Exception { - Calendar today = Calendar.getInstance(); + final Calendar today = Calendar.getInstance(); assertThat(createEventCache(today).getDefaultLogType()).isEqualTo(LogType.ATTENDED); } public static void testLogTypeEventFuture() throws Exception { - Calendar today = Calendar.getInstance(); + final Calendar today = Calendar.getInstance(); today.add(Calendar.DAY_OF_MONTH, 1); assertThat(createEventCache(today).getDefaultLogType()).isEqualTo(LogType.WILL_ATTEND); } - private static Geocache createEventCache(Calendar calendar) { - Geocache cache = new Geocache(); + private static Geocache createEventCache(final Calendar calendar) { + final Geocache cache = new Geocache(); cache.setType(CacheType.EVENT); cache.setHidden(calendar.getTime()); return cache; diff --git a/tests/src/cgeo/geocaching/location/GeocoderTest.java b/tests/src/cgeo/geocaching/location/GeocoderTest.java index f53c074..0cc1a79 100644 --- a/tests/src/cgeo/geocaching/location/GeocoderTest.java +++ b/tests/src/cgeo/geocaching/location/GeocoderTest.java @@ -4,45 +4,57 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.CGeoTestCase; import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; import org.assertj.core.data.Offset; import rx.Observable; -import android.annotation.TargetApi; import android.location.Address; import android.location.Geocoder; -import android.os.Build; public class GeocoderTest extends CGeoTestCase { private static final String TEST_ADDRESS = "46 rue Barrault, Paris, France"; private static final double TEST_LATITUDE = 48.82677; private static final double TEST_LONGITUDE = 2.34644; + private static final Geopoint TEST_COORDS = new Geopoint(TEST_LATITUDE, TEST_LONGITUDE); private static final Offset<Double> TEST_OFFSET = Offset.offset(0.00050); - @TargetApi(Build.VERSION_CODES.GINGERBREAD) public static void testAndroidGeocoder() { // Some emulators don't have access to Google Android geocoder if (Geocoder.isPresent()) { - testGeocoder(new AndroidGeocoder(CgeoApplication.getInstance()).getFromLocationName(TEST_ADDRESS), "Android"); + final AndroidGeocoder geocoder = new AndroidGeocoder(CgeoApplication.getInstance()); + testGeocoder(geocoder.getFromLocationName(TEST_ADDRESS), "Android", true); + testGeocoder(geocoder.getFromLocation(TEST_COORDS), "Android reverse", true); + } else { + Log.i("not testing absent Android geocoder"); } } public static void testGCGeocoder() { - testGeocoder(GCGeocoder.getFromLocationName(TEST_ADDRESS), "GC"); + testGeocoder(GCGeocoder.getFromLocationName(TEST_ADDRESS), "GC", false); } public static void testMapQuestGeocoder() { - testGeocoder(MapQuestGeocoder.getFromLocationName(TEST_ADDRESS), "MapQuest"); + testGeocoder(MapQuestGeocoder.getFromLocationName(TEST_ADDRESS), "MapQuest", true); + testGeocoder(MapQuestGeocoder.getFromLocation(TEST_COORDS), "MapQuest reverse", true); } - public static void testGeocoder(final Observable<Address> addressObservable, final String geocoder) { + public static void testGeocoder(final Observable<Address> addressObservable, final String geocoder, final boolean withAddress) { final Address address = addressObservable.toBlocking().first(); - assertThat(address.getLatitude()).as("latitude for " + geocoder + " geocoder").isCloseTo(TEST_LATITUDE, TEST_OFFSET); - assertThat(address.getLongitude()).as("longitude for " + geocoder + " geocoder").isCloseTo(TEST_LONGITUDE, TEST_OFFSET); - assertThat(StringUtils.lowerCase(address.getAddressLine(0))).as("street address for " + geocoder + " geocoder").startsWith("46 rue barrault"); + assertThat(address.getLatitude()).as(describe("latitude", geocoder)).isCloseTo(TEST_LATITUDE, TEST_OFFSET); + assertThat(address.getLongitude()).as(describe("longitude", geocoder)).isCloseTo(TEST_LONGITUDE, TEST_OFFSET); + if (withAddress) { + assertThat(StringUtils.lowerCase(address.getAddressLine(0))).as(describe("street address", geocoder)).startsWith("46 rue barrault"); + assertThat(address.getLocality()).as(describe("locality", geocoder)).isEqualTo("Paris"); + assertThat(address.getCountryName()).as(describe("country name", geocoder)).isEqualTo("France"); + } + } + + private static String describe(final String field, final String geocoder) { + return new StringBuilder(field).append(" for ").append(geocoder).append(" .geocoder").toString(); } } diff --git a/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.java b/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.java index 9580be8..4d74792 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.java +++ b/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.java @@ -97,6 +97,7 @@ public class GC1ZXX2 extends MockedCache { return null; } + @NonNull @Override public List<String> getAttributes() { final String[] attributes = new String[] { diff --git a/tests/src/cgeo/geocaching/test/mock/GC2CJPF.java b/tests/src/cgeo/geocaching/test/mock/GC2CJPF.java index 5c65f37..7404e23 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC2CJPF.java +++ b/tests/src/cgeo/geocaching/test/mock/GC2CJPF.java @@ -132,6 +132,7 @@ public class GC2CJPF extends MockedCache { return null; } + @NonNull @Override public List<String> getAttributes() { final String[] attributes = new String[] { diff --git a/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java b/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java index 2525514..77f078b 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java +++ b/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java @@ -100,6 +100,7 @@ public class GC2JVEH extends MockedCache { return null; } + @NonNull @Override public List<String> getAttributes() { final String[] attributes = new String[] { diff --git a/tests/src/cgeo/geocaching/test/mock/GC3XX5J.java b/tests/src/cgeo/geocaching/test/mock/GC3XX5J.java index 36e2358..c526d72 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC3XX5J.java +++ b/tests/src/cgeo/geocaching/test/mock/GC3XX5J.java @@ -98,6 +98,7 @@ public class GC3XX5J extends MockedCache { return null; } + @NonNull @Override public List<String> getAttributes() { final String[] attributes = new String[] { |
