diff options
Diffstat (limited to 'main')
32 files changed, 220 insertions, 160 deletions
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); |
