aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo')
-rw-r--r--main/src/cgeo/calendar/CalendarAddon.java5
-rw-r--r--main/src/cgeo/contacts/ContactsAddon.java5
-rw-r--r--main/src/cgeo/geocaching/AboutActivity.java19
-rw-r--r--main/src/cgeo/geocaching/AbstractDialogFragment.java358
-rw-r--r--main/src/cgeo/geocaching/AbstractLoggingActivity.java25
-rw-r--r--main/src/cgeo/geocaching/AbstractPopupActivity.java260
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java580
-rw-r--r--main/src/cgeo/geocaching/CacheListActivity.java432
-rw-r--r--main/src/cgeo/geocaching/CacheListSpinnerAdapter.java68
-rw-r--r--main/src/cgeo/geocaching/CacheMenuHandler.java47
-rw-r--r--main/src/cgeo/geocaching/CachePopup.java206
-rw-r--r--main/src/cgeo/geocaching/CachePopupFragment.java229
-rw-r--r--main/src/cgeo/geocaching/CgeoApplication.java48
-rw-r--r--main/src/cgeo/geocaching/CompassActivity.java52
-rw-r--r--main/src/cgeo/geocaching/CreateShortcutActivity.java6
-rw-r--r--main/src/cgeo/geocaching/DataStore.java355
-rw-r--r--main/src/cgeo/geocaching/EditWaypointActivity.java25
-rw-r--r--main/src/cgeo/geocaching/Geocache.java204
-rw-r--r--main/src/cgeo/geocaching/ImageSelectActivity.java4
-rw-r--r--main/src/cgeo/geocaching/ImagesActivity.java4
-rw-r--r--main/src/cgeo/geocaching/LogCacheActivity.java262
-rw-r--r--main/src/cgeo/geocaching/LogTrackableActivity.java5
-rw-r--r--main/src/cgeo/geocaching/MainActivity.java96
-rw-r--r--main/src/cgeo/geocaching/NavigateAnyPointActivity.java28
-rw-r--r--main/src/cgeo/geocaching/PocketQueryList.java4
-rw-r--r--main/src/cgeo/geocaching/SearchActivity.java45
-rw-r--r--main/src/cgeo/geocaching/SearchResult.java15
-rw-r--r--main/src/cgeo/geocaching/SelectMapfileActivity.java3
-rw-r--r--main/src/cgeo/geocaching/StaticMapsActivity.java18
-rw-r--r--main/src/cgeo/geocaching/StaticMapsProvider.java157
-rw-r--r--main/src/cgeo/geocaching/StatusFragment.java5
-rw-r--r--main/src/cgeo/geocaching/TrackableActivity.java188
-rw-r--r--main/src/cgeo/geocaching/UsefulAppsActivity.java4
-rw-r--r--main/src/cgeo/geocaching/Waypoint.java38
-rw-r--r--main/src/cgeo/geocaching/WaypointPopup.java136
-rw-r--r--main/src/cgeo/geocaching/WaypointPopupFragment.java147
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractActionBarActivity.java34
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractActivity.java93
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractListActivity.java26
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java2
-rw-r--r--main/src/cgeo/geocaching/activity/ActionBarListActivity.java34
-rw-r--r--main/src/cgeo/geocaching/activity/ActivityMixin.java72
-rw-r--r--main/src/cgeo/geocaching/activity/IAbstractActivity.java3
-rw-r--r--main/src/cgeo/geocaching/activity/SimpleWebviewActivity.java32
-rw-r--r--main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java18
-rw-r--r--main/src/cgeo/geocaching/apps/cache/GccApp.java28
-rw-r--r--main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java22
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java8
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java10
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java24
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java10
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel11.java17
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java15
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java8
-rw-r--r--main/src/cgeo/geocaching/compatibility/Compatibility.java24
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java6
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java24
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java362
-rw-r--r--main/src/cgeo/geocaching/connector/gc/IconDecoder.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java4
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Tile.java5
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java6
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java60
-rw-r--r--main/src/cgeo/geocaching/export/ExportFactory.java67
-rw-r--r--main/src/cgeo/geocaching/export/FieldnoteExport.java8
-rw-r--r--main/src/cgeo/geocaching/export/GpxExport.java19
-rw-r--r--main/src/cgeo/geocaching/files/FileParser.java8
-rw-r--r--main/src/cgeo/geocaching/files/FileType.java8
-rw-r--r--main/src/cgeo/geocaching/files/FileTypeDetector.java77
-rw-r--r--main/src/cgeo/geocaching/files/GPXImporter.java103
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java4
-rw-r--r--main/src/cgeo/geocaching/files/LocParser.java11
-rw-r--r--main/src/cgeo/geocaching/filter/PopularityRatioFilter.java17
-rw-r--r--main/src/cgeo/geocaching/filter/StateFilter.java14
-rw-r--r--main/src/cgeo/geocaching/gcvote/GCVote.java33
-rw-r--r--main/src/cgeo/geocaching/geopoint/Geopoint.java11
-rw-r--r--main/src/cgeo/geocaching/geopoint/Units.java11
-rw-r--r--main/src/cgeo/geocaching/list/AbstractList.java4
-rw-r--r--main/src/cgeo/geocaching/list/PseudoList.java31
-rw-r--r--main/src/cgeo/geocaching/list/StoredList.java73
-rw-r--r--main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java22
-rw-r--r--main/src/cgeo/geocaching/maps/AbstractMap.java9
-rw-r--r--main/src/cgeo/geocaching/maps/CGeoMap.java754
-rw-r--r--main/src/cgeo/geocaching/maps/CachesOverlay.java2
-rw-r--r--main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java7
-rw-r--r--main/src/cgeo/geocaching/maps/PositionDrawer.java8
-rw-r--r--main/src/cgeo/geocaching/maps/ScaleDrawer.java9
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java12
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapView.java16
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleOverlay.java5
-rw-r--r--main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java3
-rw-r--r--main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java3
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java6
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java12
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java5
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java6
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java12
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java5
-rw-r--r--main/src/cgeo/geocaching/network/HtmlImage.java34
-rw-r--r--main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java2
-rw-r--r--main/src/cgeo/geocaching/network/StatusUpdater.java7
-rw-r--r--main/src/cgeo/geocaching/search/AutoCompleteAdapter.java17
-rw-r--r--main/src/cgeo/geocaching/search/SearchSuggestionCursor.java46
-rw-r--r--main/src/cgeo/geocaching/search/SuggestionProvider.java16
-rw-r--r--main/src/cgeo/geocaching/sensors/DirectionProvider.java42
-rw-r--r--main/src/cgeo/geocaching/sensors/GeoDataProvider.java18
-rw-r--r--main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java4
-rw-r--r--main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java4
-rw-r--r--main/src/cgeo/geocaching/settings/Settings.java74
-rw-r--r--main/src/cgeo/geocaching/settings/SettingsActivity.java104
-rw-r--r--main/src/cgeo/geocaching/settings/TemplateTextPreference.java2
-rw-r--r--main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java122
-rw-r--r--main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/SortActionProvider.java153
-rw-r--r--main/src/cgeo/geocaching/ui/AbstractCachingListViewPageViewCreator.java1
-rw-r--r--main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java1
-rw-r--r--main/src/cgeo/geocaching/ui/CacheListAdapter.java39
-rw-r--r--main/src/cgeo/geocaching/ui/CompassView.java48
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java159
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/DateDialog.java42
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/Dialogs.java14
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/NoTitleDialog.java32
-rw-r--r--main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java12
-rw-r--r--main/src/cgeo/geocaching/utils/DebugUtils.java37
-rw-r--r--main/src/cgeo/geocaching/utils/LogTemplateProvider.java62
-rw-r--r--main/src/cgeo/geocaching/utils/RxUtils.java17
-rw-r--r--main/src/cgeo/geocaching/utils/ShareUtils.java27
-rw-r--r--main/src/cgeo/geocaching/utils/TextUtils.java20
-rw-r--r--main/src/cgeo/geocaching/utils/TranslationUtils.java4
130 files changed, 4488 insertions, 3109 deletions
diff --git a/main/src/cgeo/calendar/CalendarAddon.java b/main/src/cgeo/calendar/CalendarAddon.java
index 117fb9a..4a672fa 100644
--- a/main/src/cgeo/calendar/CalendarAddon.java
+++ b/main/src/cgeo/calendar/CalendarAddon.java
@@ -18,6 +18,11 @@ import android.net.Uri;
import java.util.Date;
public class CalendarAddon {
+
+ private CalendarAddon() {
+ // utility class
+ }
+
public static boolean isAvailable() {
return ProcessUtils.isIntentAvailable(ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST));
}
diff --git a/main/src/cgeo/contacts/ContactsAddon.java b/main/src/cgeo/contacts/ContactsAddon.java
index f2498ea..7165a77 100644
--- a/main/src/cgeo/contacts/ContactsAddon.java
+++ b/main/src/cgeo/contacts/ContactsAddon.java
@@ -8,6 +8,11 @@ import android.content.Intent;
import android.net.Uri;
public class ContactsAddon {
+
+ private ContactsAddon() {
+ // utility class
+ }
+
public static void openContactCard(Activity context, String userName) {
final Parameters params = new Parameters(
IContacts.PARAM_NAME, userName
diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java
index 6cda723..5bf0f06 100644
--- a/main/src/cgeo/geocaching/AboutActivity.java
+++ b/main/src/cgeo/geocaching/AboutActivity.java
@@ -14,6 +14,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
+import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -28,6 +29,8 @@ import java.util.Scanner;
public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> {
+ private static final String EXTRA_ABOUT_STARTPAGE = "cgeo.geocaching.extra.about.startpage";
+
class LicenseViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
@InjectView(R.id.license) protected TextView licenseLink;
@@ -84,7 +87,6 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page>
@InjectView(R.id.website) protected TextView website;
@InjectView(R.id.facebook) protected TextView facebook;
@InjectView(R.id.twitter) protected TextView twitter;
- @InjectView(R.id.nutshellmanual) protected TextView nutshellmanual;
@InjectView(R.id.market) protected TextView market;
@InjectView(R.id.faq) protected TextView faq;
@@ -96,7 +98,6 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page>
setClickListener(website, "http://www.cgeo.org/");
setClickListener(facebook, "http://www.facebook.com/pages/cgeo/297269860090");
setClickListener(twitter, "http://twitter.com/android_gc");
- setClickListener(nutshellmanual, "http://manual.cgeo.org/");
setClickListener(faq, "http://faq.cgeo.org/");
market.setOnClickListener(new View.OnClickListener() {
@@ -142,7 +143,13 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page>
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.viewpager_activity);
- createViewPager(0, null);
+
+ int startPage = Page.VERSION.ordinal();
+ Bundle extras = getIntent().getExtras();
+ if (extras != null) {
+ startPage = extras.getInt(EXTRA_ABOUT_STARTPAGE, startPage);
+ }
+ createViewPager(startPage, null);
reinitializeViewPager();
}
@@ -210,4 +217,10 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page>
return result;
}
+ public static void showChangeLog(Context fromActivity) {
+ final Intent intent = new Intent(fromActivity, AboutActivity.class);
+ intent.putExtra(EXTRA_ABOUT_STARTPAGE, Page.CHANGELOG.ordinal());
+ fromActivity.startActivity(intent);
+ }
+
}
diff --git a/main/src/cgeo/geocaching/AbstractDialogFragment.java b/main/src/cgeo/geocaching/AbstractDialogFragment.java
new file mode 100644
index 0000000..6de8fec
--- /dev/null
+++ b/main/src/cgeo/geocaching/AbstractDialogFragment.java
@@ -0,0 +1,358 @@
+package cgeo.geocaching;
+
+import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.enumerations.CacheSize;
+import cgeo.geocaching.enumerations.LoadFlags;
+import cgeo.geocaching.gcvote.GCVote;
+import cgeo.geocaching.gcvote.GCVoteRating;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.geopoint.Units;
+import cgeo.geocaching.sensors.GeoDirHandler;
+import cgeo.geocaching.sensors.IGeoData;
+import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.ui.CacheDetailsCreator;
+import cgeo.geocaching.ui.LoggingUI;
+import cgeo.geocaching.utils.Log;
+
+import rx.Observable;
+import rx.Subscription;
+import rx.android.observables.AndroidObservable;
+import rx.functions.Action1;
+import rx.functions.Func0;
+import rx.schedulers.Schedulers;
+import rx.subscriptions.Subscriptions;
+
+import android.annotation.TargetApi;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.support.v7.widget.PopupMenu;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public abstract class AbstractDialogFragment extends DialogFragment implements CacheMenuHandler.ActivityInterface, PopupMenu.OnMenuItemClickListener, MenuItem.OnMenuItemClickListener {
+ protected CgeoApplication app = null;
+ protected Resources res = null;
+ protected String geocode;
+ protected CacheDetailsCreator details;
+
+ private Subscription resumeSubscription = Subscriptions.empty();
+ private TextView cacheDistance = null;
+
+
+ protected static final String GEOCODE_ARG= "GEOCODE";
+ protected static final String WAYPOINT_ARG= "WAYPOINT";
+
+ protected Geocache cache;
+
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ res = getResources();
+ app = (CgeoApplication) getActivity().getApplication();
+ setHasOptionsMenu(true);
+ }
+
+ protected void initCustomActionBar(View v)
+ {
+ final ImageView defaultNavigationImageView = (ImageView) v.findViewById(R.id.defaultNavigation);
+ defaultNavigationImageView.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ startDefaultNavigation2();
+ return true;
+ }
+ });
+ defaultNavigationImageView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ navigateTo();
+ }
+ });
+
+ final View overflowActionBar = v.findViewById(R.id.overflowActionBar);
+ overflowActionBar.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showPopup(v);
+ }
+ });
+ /* Use a context menu instead popup where the popup menu is not working */
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
+ registerForContextMenu(overflowActionBar);
+ }
+
+ }
+
+ final public void setTitle(final CharSequence title) {
+ final TextView titleview = (TextView) getView().findViewById(R.id.actionbar_title);
+ if (titleview != null) {
+ titleview.setText(title);
+
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ geocode = getArguments().getString(GEOCODE_ARG);
+ }
+
+
+ protected void showPopup(View view)
+ {
+ // For reason I totally not understand the PopupMenu from Appcompat is broken beyond
+ // repair. Chicken out here and show the old menu on Gingerbread.
+ // The "correct" way of implementing this is stil in
+ // showPopupCompat(view)
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
+ view.showContextMenu();
+ } else {
+ showPopupHoneycomb(view);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void showPopupHoneycomb(View view) {
+ android.widget.PopupMenu popupMenu = new android.widget.PopupMenu(getActivity(), view);
+ CacheMenuHandler.addMenuItems(new MenuInflater(getActivity()), popupMenu.getMenu(), cache);
+ popupMenu.setOnMenuItemClickListener(
+ new android.widget.PopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ return AbstractDialogFragment.this.onMenuItemClick(item);
+ }
+ }
+ );
+ popupMenu.show();
+ }
+
+ protected void showPopupCompat(View view)
+ {
+ PopupMenu popupMenu = new PopupMenu(getActivity(), view);
+
+ // Directly instantiate SupportMenuInflater instead of getActivity().getMenuinflator
+ // getMenuinflator will throw a NPE since it tries to get the not displayed ActionBar
+ // menuinflator = getActivity().getMenuInflater();
+ // MenuInflater menuinflator = new SupportMenuInflater(getActivity());
+ CacheMenuHandler.addMenuItems(popupMenu.getMenuInflater(), popupMenu.getMenu(), cache);
+ popupMenu.setOnMenuItemClickListener(this);
+ popupMenu.show();
+ }
+
+
+ protected void init()
+ {
+ cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+
+ if (cache == null) {
+ ((AbstractActivity) getActivity()).showToast(res.getString(R.string.err_detail_cache_find));
+
+ getActivity().finish();
+ return;
+ }
+
+ geocode = cache.getGeocode();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ this.resumeSubscription = geoUpdate.start(GeoDirHandler.UPDATE_GEODATA);
+ init();
+ }
+
+
+ @Override
+ public void onPause() {
+ resumeSubscription.unsubscribe();
+ super.onPause();
+ }
+
+
+ private void aquireGCVote() {
+ if (!Settings.isRatingWanted()) {
+ return;
+ }
+ if (!cache.supportsGCVote()) {
+ return;
+ }
+ AndroidObservable.bindActivity(getActivity(), Observable.defer(new Func0<Observable<GCVoteRating>>() {
+ @Override
+ public Observable<GCVoteRating> call() {
+ final GCVoteRating rating = GCVote.getRating(cache.getGuid(), geocode);
+ return rating != null ? Observable.just(rating) : Observable.<GCVoteRating>empty();
+ }
+ })).subscribeOn(Schedulers.io()).subscribe(new Action1<GCVoteRating>() {
+ @Override
+ public void call(final GCVoteRating rating) {
+ cache.setRating(rating.getRating());
+ cache.setVotes(rating.getVotes());
+ DataStore.saveChangedCache(cache);
+ details.addRating(cache);
+ }
+ });
+ }
+
+ protected final void addCacheDetails() {
+ assert cache != null;
+ // cache type
+ final String cacheType = cache.getType().getL10n();
+ final String cacheSize = cache.getSize() != CacheSize.UNKNOWN ? " (" + cache.getSize().getL10n() + ")" : "";
+ details.add(R.string.cache_type, cacheType + cacheSize);
+
+ details.add(R.string.cache_geocode, cache.getGeocode());
+ details.addCacheState(cache);
+
+ details.addDistance(cache, cacheDistance);
+ cacheDistance = details.getValueView();
+
+ details.addDifficulty(cache);
+ details.addTerrain(cache);
+ details.addEventDate(cache);
+
+ // rating
+ if (cache.getRating() > 0) {
+ details.addRating(cache);
+ } else {
+ aquireGCVote();
+ }
+
+ // favorite count
+ details.add(R.string.cache_favorite, cache.getFavoritePoints() + "×");
+
+ // more details
+ final Button buttonMore = (Button) getView().findViewById(R.id.more_details);
+
+ buttonMore.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View arg0) {
+ CacheDetailActivity.startActivity(getActivity(), geocode);
+ getActivity().finish();
+ }
+ });
+
+ /* Only working combination as it seems */
+ registerForContextMenu(buttonMore);
+ }
+
+ public final void showToast(String text) {
+ ActivityMixin.showToast(getActivity(), text);
+ }
+
+ private final GeoDirHandler geoUpdate = new GeoDirHandler() {
+
+ @Override
+ public void updateGeoData(final IGeoData geo) {
+ try {
+ if (geo.getCoords() != null && cache != null && cache.getCoords() != null) {
+ cacheDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(cache.getCoords())));
+ cacheDistance.bringToFront();
+ }
+ onUpdateGeoData(geo);
+ } catch (final RuntimeException e) {
+ Log.w("Failed to UpdateLocation location.");
+ }
+ }
+ };
+
+ /**
+ * @param geo
+ * location
+ */
+ protected void onUpdateGeoData(final IGeoData geo) {
+ // do nothing by default
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ CacheMenuHandler.addMenuItems(inflater, menu, cache);
+
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ CacheMenuHandler.addMenuItems(new MenuInflater(getActivity()), menu, cache);
+ for (int i=0;i<menu.size();i++) {
+ MenuItem m = menu.getItem(i);
+ m.setOnMenuItemClickListener(this);
+ }
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ return onOptionsItemSelected(item);
+ }
+
+
+ @Override
+ public boolean onMenuItemClick(MenuItem menuItem) {
+ return onOptionsItemSelected(menuItem);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (CacheMenuHandler.onMenuItemSelected(item, this, cache)) {
+ return true;
+ }
+ if (LoggingUI.onMenuItemSelected(item, getActivity(), cache)) {
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+
+ try {
+ CacheMenuHandler.onPrepareOptionsMenu(menu, cache);
+ LoggingUI.onPrepareOptionsMenu(menu, cache);
+ } catch (final RuntimeException e) {
+ // nothing
+ }
+ }
+
+
+ protected abstract Geopoint getCoordinates();
+
+ protected abstract void startDefaultNavigation2();
+
+
+ @Override
+ public void cachesAround() {
+ final Geopoint coords = getCoordinates();
+ if (coords == null) {
+ showToast(res.getString(R.string.err_location_unknown));
+ return;
+ }
+ CacheListActivity.startActivityCoordinates((AbstractActivity) getActivity(), coords);
+ getActivity().finish();
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ getActivity().finish();
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ }
+}
diff --git a/main/src/cgeo/geocaching/AbstractLoggingActivity.java b/main/src/cgeo/geocaching/AbstractLoggingActivity.java
index c3ba7d2..bca5db1 100644
--- a/main/src/cgeo/geocaching/AbstractLoggingActivity.java
+++ b/main/src/cgeo/geocaching/AbstractLoggingActivity.java
@@ -1,32 +1,29 @@
package cgeo.geocaching;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.connector.gc.GCSmiliesProvider;
import cgeo.geocaching.connector.gc.GCSmiliesProvider.Smiley;
import cgeo.geocaching.connector.trackable.TravelBugConnector;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.LogTemplateProvider;
import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate;
-import org.apache.commons.lang3.StringUtils;
-
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.widget.EditText;
-public abstract class AbstractLoggingActivity extends AbstractActivity {
+public abstract class AbstractLoggingActivity extends AbstractActionBarActivity {
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.abstract_logging_activity, menu);
final SubMenu menuLog = menu.findItem(R.id.menu_templates).getSubMenu();
- for (final LogTemplate template : LogTemplateProvider.getTemplates()) {
+ for (final LogTemplate template : LogTemplateProvider.getTemplatesWithSignature()) {
menuLog.add(0, template.getItemId(), 0, template.getResourceId());
}
@@ -39,10 +36,7 @@ public abstract class AbstractLoggingActivity extends AbstractActivity {
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- final boolean signatureAvailable = StringUtils.isNotBlank(Settings.getSignature());
- menu.findItem(R.id.menu_signature).setVisible(signatureAvailable);
-
+ public boolean onPrepareOptionsMenu(final Menu menu) {
boolean smileyVisible = false;
final Geocache cache = getLogContext().getCache();
if (cache != null && ConnectorFactory.getConnector(cache).equals(GCConnector.getInstance())) {
@@ -59,14 +53,9 @@ public abstract class AbstractLoggingActivity extends AbstractActivity {
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public boolean onOptionsItemSelected(final MenuItem item) {
final int id = item.getItemId();
- if (id == R.id.menu_signature) {
- insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), getLogContext()), true);
- return true;
- }
-
final LogTemplate template = LogTemplateProvider.getTemplate(id);
if (template != null) {
insertIntoLog(template.getValue(getLogContext()), true);
@@ -79,12 +68,12 @@ public abstract class AbstractLoggingActivity extends AbstractActivity {
return true;
}
- return false;
+ return super.onOptionsItemSelected(item);
}
protected abstract LogContext getLogContext();
- protected void insertIntoLog(String newText, final boolean moveCursor) {
+ protected void insertIntoLog(final String newText, final boolean moveCursor) {
final EditText log = (EditText) findViewById(R.id.log);
ActivityMixin.insertAtPosition(log, newText, moveCursor);
}
diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java
deleted file mode 100644
index 88cad01..0000000
--- a/main/src/cgeo/geocaching/AbstractPopupActivity.java
+++ /dev/null
@@ -1,260 +0,0 @@
-package cgeo.geocaching;
-
-import cgeo.geocaching.activity.AbstractActivity;
-import cgeo.geocaching.activity.ActivityMixin;
-import cgeo.geocaching.enumerations.CacheSize;
-import cgeo.geocaching.enumerations.LoadFlags;
-import cgeo.geocaching.gcvote.GCVote;
-import cgeo.geocaching.gcvote.GCVoteRating;
-import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.Units;
-import cgeo.geocaching.sensors.GeoDirHandler;
-import cgeo.geocaching.sensors.IGeoData;
-import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.ui.CacheDetailsCreator;
-import cgeo.geocaching.ui.LoggingUI;
-import cgeo.geocaching.utils.Log;
-
-import org.apache.commons.lang3.StringUtils;
-
-import rx.Observable;
-import rx.android.observables.AndroidObservable;
-import rx.functions.Action1;
-import rx.functions.Func0;
-import rx.schedulers.Schedulers;
-
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-public abstract class AbstractPopupActivity extends AbstractActivity implements CacheMenuHandler.ActivityInterface {
-
- protected Geocache cache = null;
- protected String geocode = null;
- protected CacheDetailsCreator details;
-
- private TextView cacheDistance = null;
- private final int layout;
-
- private final GeoDirHandler geoUpdate = new GeoDirHandler() {
-
- @Override
- public void updateGeoData(final IGeoData geo) {
- try {
- if (geo.getCoords() != null && cache != null && cache.getCoords() != null) {
- cacheDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(cache.getCoords())));
- cacheDistance.bringToFront();
- }
- onUpdateGeoData(geo);
- } catch (final RuntimeException e) {
- Log.w("Failed to UpdateLocation location.");
- }
- }
- };
-
- /**
- * Callback to run when new location information is available.
- * This may be overridden by deriving classes. The default implementation does nothing.
- *
- * @param geo
- * the new data
- */
- public void onUpdateGeoData(final IGeoData geo) {
- }
-
- protected AbstractPopupActivity(int layout) {
- this.layout = layout;
- }
-
- private void aquireGCVote() {
- if (!Settings.isRatingWanted()) {
- return;
- }
- if (!cache.supportsGCVote()) {
- return;
- }
- AndroidObservable.bindActivity(this, Observable.defer(new Func0<Observable<GCVoteRating>>() {
- @Override
- public Observable<GCVoteRating> call() {
- final GCVoteRating rating = GCVote.getRating(cache.getGuid(), geocode);
- return rating != null ? Observable.just(rating) : Observable.<GCVoteRating>empty();
- }
- })).subscribe(new Action1<GCVoteRating>() {
- @Override
- public void call(final GCVoteRating rating) {
- cache.setRating(rating.getRating());
- cache.setVotes(rating.getVotes());
- DataStore.saveChangedCache(cache);
- details.addRating(cache);
- }
- }, Schedulers.io());
- }
-
- protected void init() {
- cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
-
- if (cache == null) {
- showToast(res.getString(R.string.err_detail_cache_find));
-
- finish();
- return;
- }
-
- geocode = cache.getGeocode();
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // set theme
- this.setTheme(ActivityMixin.getDialogTheme());
- // set layout
- setContentView(layout);
-
- // get parameters
- final Bundle extras = getIntent().getExtras();
- if (extras != null) {
- geocode = extras.getString(Intents.EXTRA_GEOCODE);
- }
-
- if (StringUtils.isBlank(geocode)) {
- showToast(res.getString(R.string.err_detail_cache_find));
-
- finish();
- return;
- }
-
- final ImageView defaultNavigationImageView = (ImageView) findViewById(R.id.defaultNavigation);
- defaultNavigationImageView.setOnLongClickListener(new OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- startDefaultNavigation2();
- return true;
- }
- });
-
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- CacheMenuHandler.addMenuItems(this, menu, cache);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (CacheMenuHandler.onMenuItemSelected(item, this, cache)) {
- return true;
- }
- if (LoggingUI.onMenuItemSelected(item, this, cache)) {
- return true;
- }
-
- return true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
-
- try {
- CacheMenuHandler.onPrepareOptionsMenu(menu, cache);
- LoggingUI.onPrepareOptionsMenu(menu, cache);
- } catch (final RuntimeException e) {
- // nothing
- }
-
- return true;
- }
-
- protected abstract Geopoint getCoordinates();
-
- @Override
- public void onResume() {
- super.onResume(geoUpdate.start(GeoDirHandler.UPDATE_GEODATA));
- init();
- }
-
- @Override
- public boolean onTouchEvent(final MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_UP) {
- final Rect r = new Rect(0, 0, 0, 0);
- getWindow().getDecorView().getHitRect(r);
- if (!r.contains((int) event.getX(), (int) event.getY())) {
- finish();
- return true;
- }
- }
- return super.onTouchEvent(event);
- }
-
- protected abstract void startDefaultNavigation2();
-
- protected final void addCacheDetails() {
- assert cache != null;
- // cache type
- final String cacheType = cache.getType().getL10n();
- final String cacheSize = cache.getSize() != CacheSize.UNKNOWN ? " (" + cache.getSize().getL10n() + ")" : "";
- details.add(R.string.cache_type, cacheType + cacheSize);
-
- details.add(R.string.cache_geocode, cache.getGeocode());
- details.addCacheState(cache);
-
- details.addDistance(cache, cacheDistance);
- cacheDistance = details.getValueView();
-
- details.addDifficulty(cache);
- details.addTerrain(cache);
- details.addEventDate(cache);
-
- // rating
- if (cache.getRating() > 0) {
- details.addRating(cache);
- } else {
- aquireGCVote();
- }
-
- // favorite count
- details.add(R.string.cache_favorite, cache.getFavoritePoints() + "×");
-
- // more details
- final Button buttonMore = (Button) findViewById(R.id.more_details);
- buttonMore.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View arg0) {
- CacheDetailActivity.startActivity(AbstractPopupActivity.this, geocode);
- finish();
- }
- });
- }
-
- @Override
- public void cachesAround() {
- final Geopoint coords = getCoordinates();
- if (coords == null) {
- showToast(res.getString(R.string.err_location_unknown));
- return;
- }
- CacheListActivity.startActivityCoordinates(this, coords);
- finish();
- }
-
- /**
- * @param view
- * unused here but needed since this method is referenced from XML layout
- */
- public final void goDefaultNavigation(View view) {
- navigateTo();
- finish();
- }
-
-}
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index a66d181..e1c0541 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -46,6 +46,7 @@ import cgeo.geocaching.utils.CryptUtils;
import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
+import cgeo.geocaching.utils.RxUtils;
import cgeo.geocaching.utils.SimpleCancellableHandler;
import cgeo.geocaching.utils.SimpleHandler;
import cgeo.geocaching.utils.TextUtils;
@@ -60,9 +61,9 @@ import org.apache.commons.lang3.tuple.Pair;
import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Observer;
-import rx.Scheduler.Inner;
import rx.Subscriber;
import rx.android.observables.AndroidObservable;
+import rx.functions.Action0;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
import rx.subscriptions.CompositeSubscription;
@@ -84,6 +85,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.FragmentManager;
+import android.support.v7.view.ActionMode;
import android.text.Editable;
import android.text.Html;
import android.text.Spannable;
@@ -165,7 +167,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private Waypoint selectedWaypoint;
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.cachedetail_activity);
createSubscriptions = new CompositeSubscription();
@@ -272,22 +274,13 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// nothing, we lost the window
}
- final ImageView defaultNavigationImageView = (ImageView) findViewById(R.id.defaultNavigation);
- defaultNavigationImageView.setOnLongClickListener(new OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- startDefaultNavigation2();
- return true;
- }
- });
-
final int pageToOpen = savedInstanceState != null ?
savedInstanceState.getInt(STATE_PAGE_INDEX, 0) :
Settings.isOpenLastDetailsPage() ? Settings.getLastDetailsPage() : 1;
createViewPager(pageToOpen, new OnPageSelectedListener() {
@Override
- public void onPageSelected(int position) {
+ public void onPageSelected(final int position) {
if (Settings.isOpenLastDetailsPage()) {
Settings.setLastDetailsPage(position);
}
@@ -300,9 +293,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final String realGeocode = geocode;
final String realGuid = guid;
- Schedulers.io().schedule(new Action1<Inner>() {
+ Schedulers.io().createWorker().schedule(new Action0() {
@Override
- public void call(final Inner inner) {
+ public void call() {
search = Geocache.searchByGeocode(realGeocode, StringUtils.isBlank(realGeocode) ? realGuid : null, 0, false, loadCacheHandler);
loadCacheHandler.sendMessage(Message.obtain());
}
@@ -342,53 +335,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
@Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) {
+ public void onCreateContextMenu(final ContextMenu menu, final View view, final ContextMenu.ContextMenuInfo info) {
super.onCreateContextMenu(menu, view, info);
final int viewId = view.getId();
switch (viewId) {
- case R.id.value: // coordinates, gc-code, name
- assert view instanceof TextView;
- clickedItemText = ((TextView) view).getText();
- final CharSequence itemTitle = ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText();
- buildDetailsContextMenu(menu, clickedItemText, itemTitle, true);
- break;
- case R.id.shortdesc:
- assert view instanceof TextView;
- clickedItemText = ((TextView) view).getText();
- buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_description), false);
- break;
- case R.id.longdesc:
- assert view instanceof TextView;
- // combine short and long description
- final String shortDesc = cache.getShortDescription();
- if (StringUtils.isBlank(shortDesc)) {
- clickedItemText = ((TextView) view).getText();
- } else {
- clickedItemText = shortDesc + "\n\n" + ((TextView) view).getText();
- }
- buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_description), false);
- break;
- case R.id.personalnote:
- assert view instanceof TextView;
- clickedItemText = ((TextView) view).getText();
- buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_personal_note), true);
- break;
- case R.id.hint:
- assert view instanceof TextView;
- clickedItemText = ((TextView) view).getText();
- buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_hint), false);
- break;
- case R.id.log:
- assert view instanceof TextView;
- clickedItemText = ((TextView) view).getText();
- buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_logs), false);
- break;
- case R.id.date: // event date
- assert view instanceof TextView;
- clickedItemText = ((TextView) view).getText();
- buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_event), true);
- menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar());
- break;
case R.id.waypoint:
menu.setHeaderTitle(selectedWaypoint.getName() + " (" + res.getString(R.string.waypoint) + ")");
getMenuInflater().inflate(R.menu.waypoint_options, menu);
@@ -414,25 +364,25 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
@Override
- public boolean onContextItemSelected(MenuItem item) {
- if (onClipboardItemSelected(item, clickedItemText)) {
- return true;
- }
+ public boolean onContextItemSelected(final MenuItem item) {
switch (item.getItemId()) {
// waypoints
case R.id.menu_waypoint_edit:
if (selectedWaypoint != null) {
+ ensureSaved();
EditWaypointActivity.startActivityEditWaypoint(this, cache, selectedWaypoint.getId());
refreshOnResume = true;
}
return true;
case R.id.menu_waypoint_duplicate:
+ ensureSaved();
if (cache.duplicateWaypoint(selectedWaypoint)) {
DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
notifyDataSetChanged();
}
return true;
case R.id.menu_waypoint_delete:
+ ensureSaved();
if (cache.deleteWaypoint(selectedWaypoint)) {
DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
notifyDataSetChanged();
@@ -454,10 +404,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
return true;
case R.id.menu_waypoint_reset_cache_coords:
+ ensureSaved();
if (ConnectorFactory.getConnector(cache).supportsOwnCoordinates()) {
createResetCacheCoordinatesDialog(cache, selectedWaypoint).show();
- }
- else {
+ } else {
final ProgressDialog progressDialog = ProgressDialog.show(this, getString(R.string.cache), getString(R.string.waypoint_reset), true);
final HandlerResetCoordinates handler = new HandlerResetCoordinates(this, progressDialog, false);
new ResetCoordsThread(cache, handler, selectedWaypoint, true, false, progressDialog).start();
@@ -476,20 +426,23 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ public boolean onCreateOptionsMenu(final Menu menu) {
CacheMenuHandler.addMenuItems(this, menu, cache);
return true;
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
+ public boolean onPrepareOptionsMenu(final Menu menu) {
CacheMenuHandler.onPrepareOptionsMenu(menu, cache);
LoggingUI.onPrepareOptionsMenu(menu, cache);
+ menu.findItem(R.id.menu_store).setVisible(cache != null && !cache.isOffline());
+ menu.findItem(R.id.menu_delete).setVisible(cache != null && cache.isOffline());
+ menu.findItem(R.id.menu_refresh).setVisible(cache != null && cache.isOffline());
return super.onPrepareOptionsMenu(menu);
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public boolean onOptionsItemSelected(final MenuItem item) {
if (CacheMenuHandler.onMenuItemSelected(item, this, cache)) {
return true;
}
@@ -497,9 +450,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final int menuItem = item.getItemId();
switch (menuItem) {
- case 0:
- // no menu selected, but a new sub menu shown
- return false;
+ case R.id.menu_delete:
+ dropCache();
+ return true;
+ case R.id.menu_store:
+ storeCache();
+ return true;
+ case R.id.menu_refresh:
+ refreshCache();
+ return true;
default:
if (NavigationAppFactory.onMenuItemSelected(item, this, cache)) {
return true;
@@ -510,7 +469,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- return true;
+ return super.onOptionsItemSelected(item);
}
private static final class CacheDetailsGeoDirHandler extends GeoDirHandler {
@@ -539,7 +498,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private final static class LoadCacheHandler extends SimpleCancellableHandler {
- public LoadCacheHandler(CacheDetailActivity activity, Progress progress) {
+ public LoadCacheHandler(final CacheDetailActivity activity, final Progress progress) {
super(activity, progress);
}
@@ -574,7 +533,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
private void updateStatusMsg(final String msg) {
- CacheDetailActivity activity = ((CacheDetailActivity) activityRef.get());
+ final CacheDetailActivity activity = ((CacheDetailActivity) activityRef.get());
if (activity == null) {
return;
}
@@ -591,6 +550,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
private void notifyDataSetChanged() {
+ // This might get called asynchronically when the activity is shut down
+ if (isFinishing()) {
+ return;
+ }
+
if (search == null) {
return;
}
@@ -613,7 +577,18 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
} else {
setTitle(cache.getGeocode());
}
- ((TextView) findViewById(R.id.actionbar_title)).setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(cache.getType().markerId), null, null, null);
+
+ getSupportActionBar().setIcon(getResources().getDrawable(cache.getType().markerId));
+
+ // if we have a newer Android device setup Android Beam for easy cache sharing
+ initializeAndroidBeam(
+ new ActivitySharingInterface() {
+ @Override
+ public String getUri() {
+ return cache.getCgeoUrl();
+ }
+ }
+ );
// reset imagesList so Images view page will be redrawn
imagesList = null;
@@ -622,8 +597,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// rendering done! remove progress popup if any there
invalidateOptionsMenuCompatible();
progress.dismiss();
+
+ Settings.addCacheToHistory(cache.getGeocode());
}
+
/**
* Tries to navigate to the {@link Geocache} of this activity.
*/
@@ -632,23 +610,16 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
/**
- * Tries to navigate to the {@link Geocache} of this activity.
- */
- private void startDefaultNavigation2() {
- NavigationAppFactory.startDefaultNavigationApplication(2, this, cache);
- }
-
- /**
* Wrapper for the referenced method in the xml-layout.
*/
- public void goDefaultNavigation(@SuppressWarnings("unused") View view) {
+ public void goDefaultNavigation(@SuppressWarnings("unused") final View view) {
startDefaultNavigation();
}
/**
* referenced from XML view
*/
- public void showNavigationMenu(@SuppressWarnings("unused") View view) {
+ public void showNavigationMenu(@SuppressWarnings("unused") final View view) {
NavigationAppFactory.showNavigationMenu(this, cache, null, null, true, true);
}
@@ -681,7 +652,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
DETAILS(R.string.detail),
DESCRIPTION(R.string.cache_description),
LOGS(R.string.cache_logs),
- LOGSFRIENDS(R.string.cache_logsfriends),
+ LOGSFRIENDS(R.string.cache_logs_friends_and_own),
WAYPOINTS(R.string.cache_waypoints),
INVENTORY(R.string.cache_inventory),
IMAGES(R.string.cache_images);
@@ -723,7 +694,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
attributeBox.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View v) {
+ public void onClick(final View v) {
// toggle between attribute icons and descriptions
toggleAttributeDisplay(attributeBox, attributeBoxMaxWidth);
}
@@ -748,7 +719,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
* lazy-creates the layout holding the icons of the caches attributes
* and makes it visible
*/
- private void showAttributeIcons(LinearLayout attribBox, int parentWidth) {
+ private void showAttributeIcons(final LinearLayout attribBox, final int parentWidth) {
if (attributeIconsLayout == null) {
attributeIconsLayout = createAttributeIconsLayout(parentWidth);
// no matching icons found? show text
@@ -766,7 +737,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
* lazy-creates the layout holding the descriptions of the caches attributes
* and makes it visible
*/
- private void showAttributeDescriptions(LinearLayout attribBox) {
+ private void showAttributeDescriptions(final LinearLayout attribBox) {
if (attributeDescriptionsLayout == null) {
attributeDescriptionsLayout = createAttributeDescriptionsLayout();
}
@@ -778,7 +749,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
/**
* toggle attribute descriptions and icons
*/
- private void toggleAttributeDisplay(LinearLayout attribBox, int parentWidth) {
+ private void toggleAttributeDisplay(final LinearLayout attribBox, final int parentWidth) {
// Don't toggle when there are no icons to show.
if (noAttributeIconsFound) {
return;
@@ -792,7 +763,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- private ViewGroup createAttributeIconsLayout(int parentWidth) {
+ private ViewGroup createAttributeIconsLayout(final int parentWidth) {
final LinearLayout rows = new LinearLayout(CacheDetailActivity.this);
rows.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
rows.setOrientation(LinearLayout.VERTICAL);
@@ -857,7 +828,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
for (String attributeName : cache.getAttributes()) {
final boolean enabled = CacheAttribute.isEnabled(attributeName);
// search for a translation of the attribute
- CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName));
+ final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName));
if (attrib != null) {
attributeName = attrib.getL10n(enabled);
}
@@ -873,6 +844,54 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
+ private void refreshCache() {
+ if (progress.isShowing()) {
+ showToast(res.getString(R.string.err_detail_still_working));
+ return;
+ }
+
+ if (!Network.isNetworkConnected(getApplicationContext())) {
+ showToast(getString(R.string.err_server));
+ return;
+ }
+
+ final RefreshCacheHandler refreshCacheHandler = new RefreshCacheHandler(CacheDetailActivity.this, progress);
+
+ progress.show(CacheDetailActivity.this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage());
+
+ cache.refresh(refreshCacheHandler, Schedulers.io());
+ }
+
+ private void dropCache() {
+ if (progress.isShowing()) {
+ showToast(res.getString(R.string.err_detail_still_working));
+ return;
+ }
+
+ progress.show(CacheDetailActivity.this, res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true, null);
+ cache.drop(new ChangeNotificationHandler(CacheDetailActivity.this, progress), Schedulers.io());
+ }
+
+ private void storeCache() {
+ if (progress.isShowing()) {
+ showToast(res.getString(R.string.err_detail_still_working));
+ return;
+ }
+
+ if (Settings.getChooseList()) {
+ // let user select list to store cache in
+ new StoredList.UserInterface(CacheDetailActivity.this).promptForListSelection(R.string.list_title,
+ new Action1<Integer>() {
+ @Override
+ public void call(final Integer selectedListId) {
+ storeCache(selectedListId, new StoreCacheHandler(CacheDetailActivity.this, progress));
+ }
+ }, true, StoredList.TEMPORARY_LIST_ID);
+ } else {
+ storeCache(StoredList.TEMPORARY_LIST_ID, new StoreCacheHandler(CacheDetailActivity.this, progress));
+ }
+ }
+
/**
* Creator for details-view.
*/
@@ -894,17 +913,18 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
view = (ScrollView) getLayoutInflater().inflate(R.layout.cachedetail_details_page, null);
// Start loading preview map
- AndroidObservable.bindActivity(CacheDetailActivity.this, previewMap).subscribe(new Action1<BitmapDrawable>() {
- @Override
- public void call(final BitmapDrawable image) {
- final Bitmap bitmap = image.getBitmap();
- if (bitmap != null && bitmap.getWidth() > 10) {
- final ImageView imageView = (ImageView) view.findViewById(R.id.map_preview);
- imageView.setImageDrawable(image);
- view.findViewById(R.id.map_preview_box).setVisibility(View.VISIBLE);
- }
- }
- }, Schedulers.io());
+ AndroidObservable.bindActivity(CacheDetailActivity.this, previewMap).subscribeOn(Schedulers.io())
+ .subscribe(new Action1<BitmapDrawable>() {
+ @Override
+ public void call(final BitmapDrawable image) {
+ final Bitmap bitmap = image.getBitmap();
+ if (bitmap != null && bitmap.getWidth() > 10) {
+ final ImageView imageView = (ImageView) view.findViewById(R.id.map_preview);
+ imageView.setImageDrawable(image);
+ view.findViewById(R.id.map_preview_box).setVisibility(View.VISIBLE);
+ }
+ }
+ });
detailsList = (LinearLayout) view.findViewById(R.id.details_list);
final CacheDetailsCreator details = new CacheDetailsCreator(CacheDetailActivity.this, detailsList);
@@ -918,10 +938,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
span.setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, span.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
- registerForContextMenu(details.add(R.string.cache_name, span));
+ addContextMenu(details.add(R.string.cache_name, span));
details.add(R.string.cache_type, cache.getType().getL10n());
details.addSize(cache);
- registerForContextMenu(details.add(R.string.cache_geocode, cache.getGeocode()));
+ addContextMenu(details.add(R.string.cache_geocode, cache.getGeocode()));
details.addCacheState(cache);
details.addDistance(cache, cacheDistanceView);
@@ -955,7 +975,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// hidden or event date
final TextView hiddenView = details.addHiddenDate(cache);
if (hiddenView != null) {
- registerForContextMenu(hiddenView);
+ addContextMenu(hiddenView);
}
// cache location
@@ -967,7 +987,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (cache.getCoords() != null) {
final TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString());
valueView.setOnClickListener(new CoordinatesFormatSwitcher(cache.getCoords()));
- registerForContextMenu(valueView);
+ addContextMenu(valueView);
}
// cache attributes
@@ -1015,59 +1035,23 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private class StoreCacheClickListener implements View.OnClickListener {
@Override
- public void onClick(View arg0) {
- if (progress.isShowing()) {
- showToast(res.getString(R.string.err_detail_still_working));
- return;
- }
-
- if (Settings.getChooseList()) {
- // let user select list to store cache in
- new StoredList.UserInterface(CacheDetailActivity.this).promptForListSelection(R.string.list_title,
- new Action1<Integer>() {
- @Override
- public void call(final Integer selectedListId) {
- storeCache(selectedListId, new StoreCacheHandler(CacheDetailActivity.this, progress));
- }
- }, true, StoredList.TEMPORARY_LIST_ID);
- } else {
- storeCache(StoredList.TEMPORARY_LIST_ID, new StoreCacheHandler(CacheDetailActivity.this, progress));
- }
+ public void onClick(final View arg0) {
+ storeCache();
}
}
private class RefreshCacheClickListener implements View.OnClickListener {
@Override
- public void onClick(View arg0) {
- if (progress.isShowing()) {
- showToast(res.getString(R.string.err_detail_still_working));
- return;
- }
-
- if (!Network.isNetworkConnected(getApplicationContext())) {
- showToast(getString(R.string.err_server));
- return;
- }
-
- final RefreshCacheHandler refreshCacheHandler = new RefreshCacheHandler(CacheDetailActivity.this, progress);
-
- progress.show(CacheDetailActivity.this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage());
-
- cache.refresh(cache.getListId(), refreshCacheHandler, Schedulers.io());
+ public void onClick(final View arg0) {
+ refreshCache();
}
}
private class DropCacheClickListener implements View.OnClickListener {
@Override
- public void onClick(View arg0) {
- if (progress.isShowing()) {
- showToast(res.getString(R.string.err_detail_still_working));
- return;
- }
-
- progress.show(CacheDetailActivity.this, res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true, null);
- cache.drop(new ChangeNotificationHandler(CacheDetailActivity.this, progress), Schedulers.io());
+ public void onClick(final View arg0) {
+ dropCache();
}
}
@@ -1075,7 +1059,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
* Abstract Listener for add / remove buttons for watchlist
*/
private abstract class AbstractWatchlistClickListener implements View.OnClickListener {
- public void doExecute(int titleId, int messageId, Thread thread) {
+ public void doExecute(final int titleId, final int messageId, final Thread thread) {
if (progress.isShowing()) {
showToast(res.getString(R.string.err_watchlist_still_managing));
return;
@@ -1096,7 +1080,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
*/
private class AddToWatchlistClickListener extends AbstractWatchlistClickListener {
@Override
- public void onClick(View arg0) {
+ public void onClick(final View arg0) {
doExecute(R.string.cache_dialog_watchlist_add_title,
R.string.cache_dialog_watchlist_add_message,
new WatchlistAddThread(new SimpleUpdateHandler(CacheDetailActivity.this, progress)));
@@ -1108,7 +1092,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
*/
private class RemoveFromWatchlistClickListener extends AbstractWatchlistClickListener {
@Override
- public void onClick(View arg0) {
+ public void onClick(final View arg0) {
doExecute(R.string.cache_dialog_watchlist_remove_title,
R.string.cache_dialog_watchlist_remove_message,
new WatchlistRemoveThread(new SimpleUpdateHandler(CacheDetailActivity.this, progress)));
@@ -1119,7 +1103,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private class WatchlistAddThread extends Thread {
private final Handler handler;
- public WatchlistAddThread(Handler handler) {
+ public WatchlistAddThread(final Handler handler) {
this.handler = handler;
}
@@ -1131,7 +1115,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
msg = Message.obtain(handler, MESSAGE_SUCCEEDED);
} else {
msg = Message.obtain(handler, MESSAGE_FAILED);
- Bundle bundle = new Bundle();
+ final Bundle bundle = new Bundle();
bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, res.getString(R.string.err_watchlist_failed));
msg.setData(bundle);
}
@@ -1143,7 +1127,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private class WatchlistRemoveThread extends Thread {
private final Handler handler;
- public WatchlistRemoveThread(Handler handler) {
+ public WatchlistRemoveThread(final Handler handler) {
this.handler = handler;
}
@@ -1155,7 +1139,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
msg = Message.obtain(handler, MESSAGE_SUCCEEDED);
} else {
msg = Message.obtain(handler, MESSAGE_FAILED);
- Bundle bundle = new Bundle();
+ final Bundle bundle = new Bundle();
bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, res.getString(R.string.err_watchlist_failed));
msg.setData(bundle);
}
@@ -1167,7 +1151,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private class FavoriteAddThread extends Thread {
private final Handler handler;
- public FavoriteAddThread(Handler handler) {
+ public FavoriteAddThread(final Handler handler) {
this.handler = handler;
}
@@ -1179,7 +1163,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
msg = Message.obtain(handler, MESSAGE_SUCCEEDED);
} else {
msg = Message.obtain(handler, MESSAGE_FAILED);
- Bundle bundle = new Bundle();
+ final Bundle bundle = new Bundle();
bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, res.getString(R.string.err_favorite_failed));
msg.setData(bundle);
}
@@ -1191,7 +1175,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private class FavoriteRemoveThread extends Thread {
private final Handler handler;
- public FavoriteRemoveThread(Handler handler) {
+ public FavoriteRemoveThread(final Handler handler) {
this.handler = handler;
}
@@ -1203,7 +1187,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
msg = Message.obtain(handler, MESSAGE_SUCCEEDED);
} else {
msg = Message.obtain(handler, MESSAGE_FAILED);
- Bundle bundle = new Bundle();
+ final Bundle bundle = new Bundle();
bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, res.getString(R.string.err_favorite_failed));
msg.setData(bundle);
}
@@ -1216,7 +1200,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
*/
private class FavoriteAddClickListener extends AbstractWatchlistClickListener {
@Override
- public void onClick(View arg0) {
+ public void onClick(final View arg0) {
doExecute(R.string.cache_dialog_favorite_add_title,
R.string.cache_dialog_favorite_add_message,
new FavoriteAddThread(new SimpleUpdateHandler(CacheDetailActivity.this, progress)));
@@ -1228,7 +1212,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
*/
private class FavoriteRemoveClickListener extends AbstractWatchlistClickListener {
@Override
- public void onClick(View arg0) {
+ public void onClick(final View arg0) {
doExecute(R.string.cache_dialog_favorite_remove_title,
R.string.cache_dialog_favorite_remove_message,
new FavoriteRemoveThread(new SimpleUpdateHandler(CacheDetailActivity.this, progress)));
@@ -1240,7 +1224,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
*/
private class ChangeListClickListener implements View.OnClickListener {
@Override
- public void onClick(View view) {
+ public void onClick(final View view) {
new StoredList.UserInterface(CacheDetailActivity.this).promptForListSelection(R.string.list_title,
new Action1<Integer>() {
@Override
@@ -1257,7 +1241,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
* @param listId
* the ID of the list
*/
- public void switchListById(int listId) {
+ public void switchListById(final int listId) {
if (listId < 0) {
return;
}
@@ -1360,7 +1344,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- private Observable<BitmapDrawable> previewMap = Observable.create(new OnSubscribe<BitmapDrawable>() {
+ private final Observable<BitmapDrawable> previewMap = Observable.create(new OnSubscribe<BitmapDrawable>() {
@Override
public void call(final Subscriber<? super BitmapDrawable> subscriber) {
try {
@@ -1369,7 +1353,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (image == null) {
if (Settings.isStoreOfflineMaps() && cache.getCoords() != null) {
- StaticMapsProvider.storeCachePreviewMap(cache);
+ RxUtils.waitForCompletion(StaticMapsProvider.storeCachePreviewMap(cache));
image = StaticMapsProvider.getPreviewMap(cache);
}
}
@@ -1417,7 +1401,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
showDesc.setVisibility(View.VISIBLE);
showDesc.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View arg0) {
+ public void onClick(final View arg0) {
loadLongDescription();
}
});
@@ -1427,16 +1411,13 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// cache personal note
setPersonalNote(personalNoteView, cache.getPersonalNote());
personalNoteView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
- registerForContextMenu(personalNoteView);
+ addContextMenu(personalNoteView);
final Button personalNoteEdit = (Button) view.findViewById(R.id.edit_personalnote);
personalNoteEdit.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View v) {
- if (cache.isOffline()) {
- editPersonalNote(cache, CacheDetailActivity.this);
- } else {
- warnPersonalNoteNeedsStoring();
- }
+ public void onClick(final View v) {
+ ensureSaved();
+ editPersonalNote(cache, CacheDetailActivity.this);
}
});
final Button personalNoteUpload = (Button) view.findViewById(R.id.upload_personalnote);
@@ -1444,7 +1425,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
personalNoteUpload.setVisibility(View.VISIBLE);
personalNoteUpload.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View v) {
+ public void onClick(final View v) {
if (StringUtils.length(cache.getPersonalNote()) > GCConstants.PERSONAL_NOTE_MAX_CHARS) {
warnPersonalNoteExceedsLimit();
} else {
@@ -1478,7 +1459,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
hintView.setOnClickListener(new DecryptTextClickListener(hintView));
hintBoxView.setOnClickListener(new DecryptTextClickListener(hintView));
hintBoxView.setClickable(true);
- registerForContextMenu(hintView);
+ addContextMenu(hintView);
} else {
hintView.setVisibility(View.GONE);
hintView.setClickable(false);
@@ -1493,7 +1474,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
spoilerlinkView.setClickable(true);
spoilerlinkView.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View arg0) {
+ public void onClick(final View arg0) {
if (cache == null || CollectionUtils.isEmpty(cache.getSpoilers())) {
showToast(res.getString(R.string.err_detail_no_spoiler));
return;
@@ -1516,7 +1497,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private void uploadPersonalNote() {
final SimpleCancellableHandler myHandler = new SimpleCancellableHandler(CacheDetailActivity.this, progress);
- Message cancelMessage = myHandler.cancelMessage(res.getString(R.string.cache_personal_note_upload_cancelled));
+ final Message cancelMessage = myHandler.cancelMessage(res.getString(R.string.cache_personal_note_upload_cancelled));
progress.show(CacheDetailActivity.this, res.getString(R.string.cache_personal_note_uploading), res.getString(R.string.cache_personal_note_uploading), true, cancelMessage);
if (currentThread != null) {
@@ -1533,30 +1514,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final String longDescription = cache.getDescription();
loadDescription(longDescription, longDescView, loadingView);
-
- // Hide the short description, if it is contained somewhere at the start of the long description.
- if (shortDescView != null) {
- final String shortDescription = cache.getShortDescription();
- if (StringUtils.isNotBlank(shortDescription)) {
- final int index = longDescription.indexOf(shortDescription);
- if (index >= 0 && index < 200) {
- shortDescView.setVisibility(View.GONE);
- }
- }
- }
- }
-
- private void warnPersonalNoteNeedsStoring() {
- Dialogs.confirm(CacheDetailActivity.this, R.string.cache_personal_note_unstored, R.string.cache_personal_note_store,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- storeCache(StoredList.STANDARD_LIST_ID, new StoreCachePersonalNoteHandler(CacheDetailActivity.this, progress));
- }
-
- });
}
private void warnPersonalNoteExceedsLimit() {
@@ -1564,7 +1521,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int which) {
+ public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
uploadPersonalNote();
}
@@ -1621,7 +1578,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
});
- AndroidObservable.bindActivity(this, producer).subscribe(new Observer<Spanned>() {
+ AndroidObservable.bindActivity(this, producer).subscribeOn(Schedulers.io()).subscribe(new Observer<Spanned>() {
@Override
public void onCompleted() {
if (null != loadingIndicatorView) {
@@ -1648,7 +1605,8 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
fixTextColor(descriptionString);
descriptionView.setVisibility(View.VISIBLE);
- registerForContextMenu(descriptionView);
+ addContextMenu(descriptionView);
+ potentiallyHideShortDescription();
}
}
@@ -1684,7 +1642,36 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
descriptionView.setBackgroundResource(backcolor);
}
- }, Schedulers.io());
+ });
+ }
+
+ /**
+ * Hide the short description, if it is contained somewhere at the start of the long description.
+ */
+ public void potentiallyHideShortDescription() {
+ final View shortView = ButterKnife.findById(this, R.id.shortdesc);
+ if (shortView == null) {
+ return;
+ }
+ if (shortView.getVisibility() == View.GONE) {
+ return;
+ }
+ final String shortDescription = cache.getShortDescription();
+ if (StringUtils.isNotBlank(shortDescription)) {
+ final int index = StringUtils.indexOf(cache.getDescription(), shortDescription);
+ // allow up to 200 characters of HTML formatting
+ if (index >= 0 && index < 200) {
+ shortView.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ private void ensureSaved() {
+ if (!cache.isOffline()) {
+ showToast(getString(R.string.info_cache_saved));
+ cache.setListId(StoredList.STANDARD_LIST_ID);
+ DataStore.saveCache(cache, LoadFlags.SAVE_ALL);
+ }
}
private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ListView> {
@@ -1703,12 +1690,13 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
view = (ListView) getLayoutInflater().inflate(R.layout.cachedetail_waypoints_page, null);
view.setClickable(true);
- View addWaypointButton = getLayoutInflater().inflate(R.layout.cachedetail_waypoints_footer, null);
+ final View addWaypointButton = getLayoutInflater().inflate(R.layout.cachedetail_waypoints_footer, null);
view.addFooterView(addWaypointButton);
addWaypointButton.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View v) {
+ public void onClick(final View v) {
+ ensureSaved();
EditWaypointActivity.startActivityAddWaypoint(CacheDetailActivity.this, cache);
refreshOnResume = true;
}
@@ -1716,12 +1704,13 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
view.setAdapter(new ArrayAdapter<Waypoint>(CacheDetailActivity.this, R.layout.waypoint_item, sortedWaypoints) {
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
+ public View getView(final int position, final View convertView, final ViewGroup parent) {
View rowView = convertView;
if (null == rowView) {
rowView = getLayoutInflater().inflate(R.layout.waypoint_item, null);
rowView.setClickable(true);
rowView.setLongClickable(true);
+ registerForContextMenu(rowView);
}
WaypointViewHolder holder = (WaypointViewHolder) rowView.getTag();
if (null == holder) {
@@ -1737,7 +1726,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return view;
}
- protected void fillViewHolder(View rowView, final WaypointViewHolder holder, final Waypoint wpt) {
+ protected void fillViewHolder(final View rowView, final WaypointViewHolder holder, final Waypoint wpt) {
// coordinates
final TextView coordinatesView = holder.coordinatesView;
if (null != wpt.getCoords()) {
@@ -1800,33 +1789,34 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final View wpNavView = holder.wpNavView;
wpNavView.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View v) {
+ public void onClick(final View v) {
NavigationAppFactory.startDefaultNavigationApplication(1, CacheDetailActivity.this, wpt);
}
});
wpNavView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
- public boolean onLongClick(View v) {
+ public boolean onLongClick(final View v) {
NavigationAppFactory.startDefaultNavigationApplication(2, CacheDetailActivity.this, wpt);
return true;
}
});
- registerForContextMenu(rowView);
+ addContextMenu(rowView);
rowView.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View v) {
+ public void onClick(final View v) {
selectedWaypoint = wpt;
- openContextMenu(v);
+ ensureSaved();
+ EditWaypointActivity.startActivityEditWaypoint(CacheDetailActivity.this, cache, wpt.getId());
+ refreshOnResume = true;
}
});
rowView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
- public boolean onLongClick(View v) {
+ public boolean onLongClick(final View v) {
selectedWaypoint = wpt;
- EditWaypointActivity.startActivityEditWaypoint(CacheDetailActivity.this, cache, wpt.getId());
- refreshOnResume = true;
+ openContextMenu(v);
return true;
}
});
@@ -1836,7 +1826,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final WaypointType waypointType = wpt.getWaypointType();
final Drawable icon;
if (wpt.isVisited()) {
- LayerDrawable ld = new LayerDrawable(new Drawable[] {
+ final LayerDrawable ld = new LayerDrawable(new Drawable[] {
res.getDrawable(waypointType.markerId),
res.getDrawable(R.drawable.tick) });
ld.setLayerInset(0, 0, 0, VISITED_INSET, VISITED_INSET);
@@ -1865,7 +1855,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
view.setAdapter(new ArrayAdapter<Trackable>(CacheDetailActivity.this, R.layout.simple_list_item_1, cache.getInventory()));
view.setOnItemClickListener(new OnItemClickListener() {
@Override
- public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
+ public void onItemClick(final AdapterView<?> arg0, final View arg1, final int arg2, final long arg3) {
final Object selection = arg0.getItemAtPosition(arg2);
if (selection instanceof Trackable) {
final Trackable trackable = (Trackable) selection;
@@ -1901,6 +1891,86 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
context.startActivity(cachesIntent);
}
+ public void addContextMenu(final View view) {
+ view.setOnLongClickListener(new OnLongClickListener() {
+
+ @Override
+ public boolean onLongClick(final View v) {
+ startSupportActionMode(new ActionMode.Callback() {
+
+ @Override
+ public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) {
+ switch (view.getId()) {
+ case R.id.value: // coordinates, gc-code, name
+ assert view instanceof TextView;
+ clickedItemText = ((TextView) view).getText();
+ final CharSequence itemTitle = ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText();
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, itemTitle, true);
+ return true;
+ case R.id.shortdesc:
+ assert view instanceof TextView;
+ clickedItemText = ((TextView) view).getText();
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_description), false);
+ return true;
+ case R.id.longdesc:
+ assert view instanceof TextView;
+ // combine short and long description
+ final String shortDesc = cache.getShortDescription();
+ if (StringUtils.isBlank(shortDesc)) {
+ clickedItemText = ((TextView) view).getText();
+ } else {
+ clickedItemText = shortDesc + "\n\n" + ((TextView) view).getText();
+ }
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_description), false);
+ return true;
+ case R.id.personalnote:
+ assert view instanceof TextView;
+ clickedItemText = ((TextView) view).getText();
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_personal_note), true);
+ return true;
+ case R.id.hint:
+ assert view instanceof TextView;
+ clickedItemText = ((TextView) view).getText();
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_hint), false);
+ return true;
+ case R.id.log:
+ assert view instanceof TextView;
+ clickedItemText = ((TextView) view).getText();
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_logs), false);
+ return true;
+ case R.id.date: // event date
+ assert view instanceof TextView;
+ clickedItemText = ((TextView) view).getText();
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_event), true);
+ menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onDestroyActionMode(final ActionMode actionMode) {
+ // do nothing
+ }
+
+ @Override
+ public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) {
+ actionMode.getMenuInflater().inflate(R.menu.details_context, menu);
+
+ // Return true so that the action mode is shown
+ return true;
+ }
+
+ @Override
+ public boolean onActionItemClicked(final ActionMode actionMode, final MenuItem menuItem) {
+ return onClipboardItemSelected(actionMode, menuItem, clickedItemText);
+ }
+ });
+ return false;
+ }
+ });
+ }
+
public static void startActivityGuid(final Context context, final String guid, final String cacheName) {
final Intent cacheIntent = new Intent(context, CacheDetailActivity.class);
cacheIntent.putExtra(Intents.EXTRA_GUID, guid);
@@ -1920,7 +1990,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
builder.setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, final int which) {
+ public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
final ProgressDialog progressDialog = ProgressDialog.show(CacheDetailActivity.this, getString(R.string.cache), getString(R.string.waypoint_reset), true);
final HandlerResetCoordinates handler = new HandlerResetCoordinates(CacheDetailActivity.this, progressDialog, which == 1);
@@ -1936,14 +2006,14 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private final ProgressDialog progressDialog;
private final boolean resetRemote;
- protected HandlerResetCoordinates(CacheDetailActivity activity, ProgressDialog progressDialog, boolean resetRemote) {
+ protected HandlerResetCoordinates(final CacheDetailActivity activity, final ProgressDialog progressDialog, final boolean resetRemote) {
super(activity);
this.progressDialog = progressDialog;
this.resetRemote = resetRemote;
}
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
if (msg.what == ResetCoordsThread.LOCAL) {
localFinished = true;
} else {
@@ -1972,7 +2042,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
public static final int LOCAL = 0;
public static final int ON_WEBSITE = 1;
- public ResetCoordsThread(Geocache cache, Handler handler, final Waypoint wpt, boolean local, boolean remote, final ProgressDialog progress) {
+ public ResetCoordsThread(final Geocache cache, final Handler handler, final Waypoint wpt, final boolean local, final boolean remote, final ProgressDialog progress) {
this.cache = cache;
this.handler = handler;
this.local = local;
@@ -2032,19 +2102,19 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private Geocache cache = null;
private CancellableHandler handler = null;
- public UploadPersonalNoteThread(Geocache cache, CancellableHandler handler) {
+ public UploadPersonalNoteThread(final Geocache cache, final CancellableHandler handler) {
this.cache = cache;
this.handler = handler;
}
@Override
public void run() {
- IConnector con = ConnectorFactory.getConnector(cache);
+ final IConnector con = ConnectorFactory.getConnector(cache);
if (con.supportsPersonalNote()) {
con.uploadPersonalNote(cache);
}
- Message msg = Message.obtain();
- Bundle bundle = new Bundle();
+ final Message msg = Message.obtain();
+ final Bundle bundle = new Bundle();
bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, res.getString(R.string.cache_personal_note_upload_done));
msg.setData(bundle);
handler.sendMessage(msg);
@@ -2052,7 +2122,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
@Override
- protected String getTitle(Page page) {
+ protected String getTitle(final Page page) {
// show number of waypoints directly in waypoint title
if (page == Page.WAYPOINTS) {
final int waypointCount = cache.getWaypoints().size();
@@ -2084,7 +2154,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
@Override
- protected AbstractViewPagerActivity.PageViewCreator createViewCreator(Page page) {
+ protected AbstractViewPagerActivity.PageViewCreator createViewCreator(final Page page) {
switch (page) {
case DETAILS:
return new DetailsViewCreator();
@@ -2112,9 +2182,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
static void updateOfflineBox(final View view, final Geocache cache, final Resources res,
- final OnClickListener refreshCacheClickListener,
- final OnClickListener dropCacheClickListener,
- final OnClickListener storeCacheClickListener) {
+ final OnClickListener refreshCacheClickListener,
+ final OnClickListener dropCacheClickListener,
+ final OnClickListener storeCacheClickListener) {
// offline use
final TextView offlineText = (TextView) view.findViewById(R.id.offline_text);
final Button offlineRefresh = (Button) view.findViewById(R.id.offline_refresh);
@@ -2160,12 +2230,12 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private static class StoreCacheHandler extends SimpleCancellableHandler {
- public StoreCacheHandler(CacheDetailActivity activity, Progress progress) {
+ public StoreCacheHandler(final CacheDetailActivity activity, final Progress progress) {
super(activity, progress);
}
@Override
- public void handleRegularMessage(Message msg) {
+ public void handleRegularMessage(final Message msg) {
if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) {
updateStatusMsg(R.string.cache_dialog_offline_save_message, (String) msg.obj);
} else {
@@ -2176,12 +2246,12 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private static final class RefreshCacheHandler extends SimpleCancellableHandler {
- public RefreshCacheHandler(CacheDetailActivity activity, Progress progress) {
+ public RefreshCacheHandler(final CacheDetailActivity activity, final Progress progress) {
super(activity, progress);
}
@Override
- public void handleRegularMessage(Message msg) {
+ public void handleRegularMessage(final Message msg) {
if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) {
updateStatusMsg(R.string.cache_dialog_refresh_message, (String) msg.obj);
} else {
@@ -2192,24 +2262,24 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private static final class ChangeNotificationHandler extends SimpleHandler {
- public ChangeNotificationHandler(CacheDetailActivity activity, Progress progress) {
+ public ChangeNotificationHandler(final CacheDetailActivity activity, final Progress progress) {
super(activity, progress);
}
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
notifyDatasetChanged(activityRef);
}
}
private static final class SimpleUpdateHandler extends SimpleHandler {
- public SimpleUpdateHandler(CacheDetailActivity activity, Progress progress) {
+ public SimpleUpdateHandler(final CacheDetailActivity activity, final Progress progress) {
super(activity, progress);
}
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
if (msg.what == MESSAGE_FAILED) {
super.handleMessage(msg);
} else {
@@ -2218,8 +2288,8 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- private static void notifyDatasetChanged(WeakReference<AbstractActivity> activityRef) {
- CacheDetailActivity activity = ((CacheDetailActivity) activityRef.get());
+ private static void notifyDatasetChanged(final WeakReference<AbstractActivity> activityRef) {
+ final CacheDetailActivity activity = ((CacheDetailActivity) activityRef.get());
if (activity != null) {
activity.notifyDataSetChanged();
}
@@ -2227,42 +2297,22 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
protected void storeCache(final int listId, final StoreCacheHandler storeCacheHandler) {
progress.show(this, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.cancelMessage());
- Schedulers.io().schedule(new Action1<Inner>() {
+ Schedulers.io().createWorker().schedule(new Action0() {
@Override
- public void call(final Inner inner) {
+ public void call() {
cache.store(listId, storeCacheHandler);
}
});
}
- private static final class StoreCachePersonalNoteHandler extends StoreCacheHandler {
-
- public StoreCachePersonalNoteHandler(CacheDetailActivity activity, Progress progress) {
- super(activity, progress);
- }
-
- @Override
- public void handleRegularMessage(Message msg) {
- if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) {
- updateStatusMsg(R.string.cache_dialog_offline_save_message, (String) msg.obj);
- } else {
- dismissProgress();
- CacheDetailActivity activity = (CacheDetailActivity) activityRef.get();
- if (activity != null) {
- editPersonalNote(activity.getCache(), activity);
- }
- }
- }
- }
-
public static void editPersonalNote(final Geocache cache, final CacheDetailActivity activity) {
if (cache.isOffline()) {
- EditNoteDialogListener editNoteDialogListener = new EditNoteDialogListener() {
+ final EditNoteDialogListener editNoteDialogListener = new EditNoteDialogListener() {
@Override
public void onFinishEditNoteDialog(final String note) {
cache.setPersonalNote(note);
cache.parseWaypointsFromNote();
- TextView personalNoteView = (TextView) activity.findViewById(R.id.personalnote);
+ final TextView personalNoteView = (TextView) activity.findViewById(R.id.personalnote);
setPersonalNote(personalNoteView, note);
DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
activity.notifyDataSetChanged();
diff --git a/main/src/cgeo/geocaching/CacheListActivity.java b/main/src/cgeo/geocaching/CacheListActivity.java
index 053798e..598171f 100644
--- a/main/src/cgeo/geocaching/CacheListActivity.java
+++ b/main/src/cgeo/geocaching/CacheListActivity.java
@@ -13,11 +13,13 @@ import cgeo.geocaching.enumerations.CacheListType;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.StatusCode;
-import cgeo.geocaching.export.ExportFactory;
+import cgeo.geocaching.export.FieldnoteExport;
+import cgeo.geocaching.export.GpxExport;
import cgeo.geocaching.files.GPXImporter;
import cgeo.geocaching.filter.FilterUserInterface;
import cgeo.geocaching.filter.IFilter;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.list.AbstractList;
import cgeo.geocaching.list.PseudoList;
import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.loaders.AbstractSearchLoader;
@@ -40,8 +42,9 @@ import cgeo.geocaching.sensors.DirectionProvider;
import cgeo.geocaching.sensors.GeoDirHandler;
import cgeo.geocaching.sensors.IGeoData;
import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.settings.SettingsActivity;
import cgeo.geocaching.sorting.CacheComparator;
-import cgeo.geocaching.sorting.ComparatorUserInterface;
+import cgeo.geocaching.sorting.SortActionProvider;
import cgeo.geocaching.ui.CacheListAdapter;
import cgeo.geocaching.ui.LoggingUI;
import cgeo.geocaching.ui.WeakReferenceHandler;
@@ -57,6 +60,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import rx.Subscription;
import rx.functions.Action1;
@@ -67,8 +71,10 @@ import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
@@ -77,6 +83,8 @@ import android.os.Message;
import android.provider.OpenableColumns;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.app.ActionBar;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
@@ -160,7 +168,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
dialog.setNegativeButton(res.getString(R.string.license_dismiss), new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int id) {
+ public void onClick(final DialogInterface dialog, final int id) {
Cookies.clearCookies();
dialog.cancel();
}
@@ -168,7 +176,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
dialog.setPositiveButton(res.getString(R.string.license_show), new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int id) {
+ public void onClick(final DialogInterface dialog, final int id) {
Cookies.clearCookies();
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/software/agreement.aspx?ID=0")));
}
@@ -212,12 +220,12 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private static class LoadCachesHandler extends WeakReferenceHandler<CacheListActivity> {
- protected LoadCachesHandler(CacheListActivity activity) {
+ protected LoadCachesHandler(final CacheListActivity activity) {
super(activity);
}
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
final CacheListActivity activity = getActivity();
if (activity == null) {
return;
@@ -252,26 +260,20 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
}
+ private String getCacheNumberString(final Resources res, final int count) {
+ return res.getQuantityString(R.plurals.cache_counts, count, count);
+ }
+
protected void updateTitle() {
- final ArrayList<Integer> numbers = new ArrayList<Integer>();
- if (adapter.isFiltered()) {
- numbers.add(adapter.getCount());
- }
- if (search != null) {
- numbers.add(search.getCount());
- }
- if (numbers.isEmpty()) {
- setTitle(title);
- }
- else {
- setTitle(title + " [" + StringUtils.join(numbers, '/') + ']');
- }
+ setTitle(title);
+ getSupportActionBar().setSubtitle(getCurrentSubtitle());
+ refreshSpinnerAdapter();
}
private final CancellableHandler loadDetailsHandler = new CancellableHandler() {
@Override
- public void handleRegularMessage(Message msg) {
+ public void handleRegularMessage(final Message msg) {
updateAdapter();
if (msg.what > -1) {
@@ -310,7 +312,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
*/
private class DownloadFromWebHandler extends CancellableHandler {
@Override
- public void handleRegularMessage(Message msg) {
+ public void handleRegularMessage(final Message msg) {
updateAdapter();
adapter.notifyDataSetChanged();
@@ -348,7 +350,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private final CancellableHandler clearOfflineLogsHandler = new CancellableHandler() {
@Override
- public void handleRegularMessage(Message msg) {
+ public void handleRegularMessage(final Message msg) {
adapter.setSelectMode(false);
refreshCurrentList();
@@ -361,7 +363,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private final Handler importGpxAttachementFinishedHandler = new Handler() {
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
refreshCurrentList();
}
};
@@ -373,10 +375,12 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
setTheme();
+
setContentView(R.layout.cacheslist_activity);
// get parameters
@@ -396,22 +400,16 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
}
- // Add the list selection in code. This way we can leave the XML layout of the action bar the same as for other activities.
- final View titleBar = findViewById(R.id.actionbar_title);
- titleBar.setClickable(true);
- titleBar.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- selectList();
- }
- });
-
setTitle(title);
+
initAdapter();
prepareFilterBar();
+ if (type.canSwitch) {
+ initActionBarSpinner();
+ }
+
currentLoader = (AbstractSearchLoader) getSupportLoaderManager().initLoader(type.getLoaderId(), extras, this);
// init
@@ -427,11 +425,57 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
if (isInvokedFromAttachment()) {
importGpxAttachement();
}
+
+
+
+ }
+
+ /**
+ * Action bar spinner adapter. {@code null} for list types that don't allow switching (search results, ...).
+ */
+ CacheListSpinnerAdapter mCacheListSpinnerAdapter;
+
+ /**
+ * remember current filter when switching between lists, so it can be re-applied afterwards
+ */
+ private IFilter currentFilter = null;
+
+ private SortActionProvider sortProvider;
+
+ private void initActionBarSpinner() {
+ mCacheListSpinnerAdapter = new CacheListSpinnerAdapter(this, R.layout.support_simple_spinner_dropdown_item);
+ getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
+ getSupportActionBar().setDisplayShowTitleEnabled(false);
+ getSupportActionBar().setListNavigationCallbacks(mCacheListSpinnerAdapter, new ActionBar.OnNavigationListener() {
+ @Override
+ public boolean onNavigationItemSelected(final int i, final long l) {
+ final int newListId = mCacheListSpinnerAdapter.getItem(i).id;
+ if (newListId != listId) {
+ switchListById(newListId);
+ }
+ return true;
+ }
+ });
}
+ private void refreshSpinnerAdapter() {
+ /* If the activity does not use the Spinner this will be null */
+ if (mCacheListSpinnerAdapter==null) {
+ return;
+ }
+ mCacheListSpinnerAdapter.clear();
+
+ final AbstractList list = AbstractList.getListById(listId);
+
+ for (final AbstractList l: StoredList.UserInterface.getMenuLists(false, PseudoList.NEW_LIST.id)) {
+ mCacheListSpinnerAdapter.add(l);
+ }
+
+ getSupportActionBar().setSelectedNavigationItem(mCacheListSpinnerAdapter.getPosition(list));
+ }
@Override
- public void onConfigurationChanged(Configuration newConfig) {
+ public void onConfigurationChanged(final Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (currentLoader != null && currentLoader.isLoading()) {
showFooterLoadingCaches();
@@ -452,7 +496,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
new StoredList.UserInterface(this).promptForListSelection(R.string.gpx_import_select_list_title, new Action1<Integer>() {
@Override
- public void call(Integer listId) {
+ public void call(final Integer listId) {
new GPXImporter(CacheListActivity.this, listId, importGpxAttachementFinishedHandler).importGPX();
switchListById(listId);
}
@@ -499,11 +543,29 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.cache_list_options, menu);
CacheListAppFactory.addMenuItems(menu, this, res);
+ sortProvider = (SortActionProvider) MenuItemCompat.getActionProvider(menu.findItem(R.id.menu_sort));
+ sortProvider.setSelection(adapter.getCacheComparator());
+ sortProvider.setClickListener(new Action1<CacheComparator>() {
+ @Override
+ public void call(final CacheComparator selectedComparator) {
+ final CacheComparator oldComparator = adapter.getCacheComparator();
+ // selecting the same sorting twice will toggle the order
+ if (selectedComparator != null && oldComparator != null && selectedComparator.getClass().equals(oldComparator.getClass())) {
+ adapter.toggleInverseSort();
+ }
+ else {
+ // always reset the inversion for a new sorting criteria
+ adapter.resetInverseSort();
+ }
+ setComparator(selectedComparator);
+ sortProvider.setSelection(selectedComparator);
+ }
+ });
return true;
}
@@ -512,7 +574,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
+ public boolean onPrepareOptionsMenu(final Menu menu) {
super.onPrepareOptionsMenu(menu);
final boolean isHistory = type == CacheListType.HISTORY;
@@ -532,18 +594,17 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
setVisible(menu, R.id.menu_switch_select_mode, !isEmpty);
setVisible(menu, R.id.submenu_manage, (isHistory && !isEmpty) || isOffline);
- setVisible(menu, R.id.submenu_manage_lists, isOffline);
+
+ setVisible(menu, R.id.menu_create_list, isOffline);
setVisible(menu, R.id.menu_sort, !isEmpty && !isHistory);
setVisible(menu, R.id.menu_refresh_stored, !isEmpty && (isConcrete || type != CacheListType.OFFLINE));
setVisible(menu, R.id.menu_drop_caches, !isEmpty && isOffline);
- setVisible(menu, R.id.menu_drop_caches_and_list, isConcrete && !isEmpty && isOffline);
- setVisible(menu, R.id.menu_delete_events, isConcrete && !isEmpty && containsEvents());
+ setVisible(menu, R.id.menu_delete_events, isConcrete && !isEmpty && containsPastEvents());
setVisible(menu, R.id.menu_move_to_list, isOffline && !isEmpty);
- setVisible(menu, R.id.menu_export, !isEmpty && (isHistory || isOffline));
setVisible(menu, R.id.menu_remove_from_history, !isEmpty && isHistory);
setVisible(menu, R.id.menu_clear_offline_logs, !isEmpty && containsOfflineLogs() && (isHistory || isOffline));
- setVisible(menu, R.id.menu_import_web, isOffline && Settings.getWebDeviceCode() != null);
+ setVisible(menu, R.id.menu_import_web, isOffline);
setVisible(menu, R.id.menu_import_gpx, isOffline);
setVisible(menu, R.id.menu_refresh_stored_top, !isOffline && !isEmpty);
@@ -551,30 +612,23 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
menu.findItem(R.id.menu_refresh_stored_top).setTitle(R.string.caches_store_offline);
}
- final boolean hasSelection = adapter != null && adapter.getCheckedCount() > 0;
final boolean isNonDefaultList = isConcrete && listId != StoredList.STANDARD_LIST_ID;
if (isOffline || type == CacheListType.HISTORY) { // only offline list
- setMenuItemLabel(menu, R.id.menu_drop_caches, R.string.caches_drop_selected, R.string.caches_drop_all);
+ setMenuItemLabel(menu, R.id.menu_drop_caches, R.string.caches_remove_selected, R.string.caches_remove_all);
setMenuItemLabel(menu, R.id.menu_refresh_stored, R.string.caches_refresh_selected, R.string.caches_refresh_all);
setMenuItemLabel(menu, R.id.menu_move_to_list, R.string.caches_move_selected, R.string.caches_move_all);
} else { // search and global list (all other than offline and history)
setMenuItemLabel(menu, R.id.menu_refresh_stored, R.string.caches_store_selected, R.string.caches_store_offline);
}
- // make combined list deletion only possible when there are no filters, as that leads to confusion for the hidden caches
- menu.findItem(R.id.menu_drop_caches_and_list).setVisible(isOffline && !hasSelection && isNonDefaultList && !adapter.isFiltered() && Settings.getCacheType() == CacheType.ALL);
-
menu.findItem(R.id.menu_drop_list).setVisible(isNonDefaultList);
menu.findItem(R.id.menu_rename_list).setVisible(isNonDefaultList);
- final boolean multipleLists = DataStore.getLists().size() >= 2;
- menu.findItem(R.id.menu_switch_list).setVisible(multipleLists);
menu.findItem(R.id.menu_move_to_list).setVisible(!isEmpty);
setMenuItemLabel(menu, R.id.menu_remove_from_history, R.string.cache_remove_from_history, R.string.cache_clear_history);
- setMenuItemLabel(menu, R.id.menu_export, R.string.export, R.string.export);
- menu.findItem(R.id.menu_import_android).setVisible(Compatibility.isStorageAccessFrameworkAvailable());
+ menu.findItem(R.id.menu_import_android).setVisible(Compatibility.isStorageAccessFrameworkAvailable() && isOffline);
} catch (final RuntimeException e) {
Log.e("CacheListActivity.onPrepareOptionsMenu", e);
}
@@ -582,9 +636,9 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
return true;
}
- private boolean containsEvents() {
+ private boolean containsPastEvents() {
for (final Geocache cache : adapter.getCheckedOrAllCaches()) {
- if (cache.isEventCache()) {
+ if (DateUtils.isPastEvent(cache)) {
return true;
}
}
@@ -614,8 +668,14 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (super.onOptionsItemSelected(item)) {
+ return true;
+ }
switch (item.getItemId()) {
+ case R.id.menu_show_on_map:
+ goMap();
+ return true;
case R.id.menu_switch_select_mode:
adapter.switchSelectMode();
invalidateOptionsMenuCompatible();
@@ -626,11 +686,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
invalidateOptionsMenuCompatible();
return true;
case R.id.menu_drop_caches:
- dropStored(false);
- invalidateOptionsMenuCompatible();
- return false;
- case R.id.menu_drop_caches_and_list:
- dropStored(true);
+ dropStored();
invalidateOptionsMenuCompatible();
return true;
case R.id.menu_import_gpx:
@@ -643,10 +699,11 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
return false;
case R.id.menu_create_list:
new StoredList.UserInterface(this).promptForListCreation(getListSwitchingRunnable(), newListName);
+ refreshSpinnerAdapter();
invalidateOptionsMenuCompatible();
return false;
case R.id.menu_drop_list:
- removeList(true);
+ removeList(false);
invalidateOptionsMenuCompatible();
return false;
case R.id.menu_rename_list:
@@ -656,36 +713,18 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
adapter.invertSelection();
invalidateOptionsMenuCompatible();
return false;
- case R.id.menu_switch_list:
- selectList();
- invalidateOptionsMenuCompatible();
- return false;
case R.id.menu_filter:
showFilterMenu(null);
return true;
- case R.id.menu_sort:
- final CacheComparator oldComparator = adapter.getCacheComparator();
- new ComparatorUserInterface(this).selectComparator(oldComparator, new Action1<CacheComparator>() {
- @Override
- public void call(CacheComparator selectedComparator) {
- // selecting the same sorting twice will toggle the order
- if (selectedComparator != null && oldComparator != null && selectedComparator.getClass().equals(oldComparator.getClass())) {
- adapter.toggleInverseSort();
- }
- else {
- // always reset the inversion for a new sorting criteria
- adapter.resetInverseSort();
- }
- setComparator(selectedComparator);
- }
- });
- return true;
case R.id.menu_import_web:
importWeb();
- return false;
- case R.id.menu_export:
- ExportFactory.showExportMenu(adapter.getCheckedOrAllCaches(), this);
- return false;
+ return true;
+ case R.id.menu_export_gpx:
+ new GpxExport().export(adapter.getCheckedOrAllCaches(), this);
+ return true;
+ case R.id.menu_export_fieldnotes:
+ new FieldnoteExport().export(adapter.getCheckedOrAllCaches(), this);
+ return true;
case R.id.menu_remove_from_history:
removeFromHistoryCheck();
invalidateOptionsMenuCompatible();
@@ -735,7 +774,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
deletion.add(cache);
}
}
- new DropDetailsTask(false).execute(deletion.toArray(new Geocache[deletion.size()]));
+ new DropDetailsTask().execute(deletion.toArray(new Geocache[deletion.size()]));
}
public void clearOfflineLogs() {
@@ -750,13 +789,8 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
public void showFilterMenu(final View view) {
new FilterUserInterface(this).selectFilter(new Action1<IFilter>() {
@Override
- public void call(IFilter selectedFilter) {
- if (selectedFilter != null) {
- setFilter(selectedFilter);
- } else {
- // clear filter
- setFilter(null);
- }
+ public void call(@Nullable final IFilter selectedFilter) {
+ setFilter(selectedFilter);
}
});
}
@@ -795,7 +829,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
final boolean isOffline = cache.isOffline();
menu.findItem(R.id.menu_drop_cache).setVisible(isOffline);
menu.findItem(R.id.menu_move_to_list).setVisible(isOffline);
- menu.findItem(R.id.menu_export).setVisible(isOffline);
menu.findItem(R.id.menu_refresh).setVisible(isOffline);
menu.findItem(R.id.menu_store_cache).setVisible(!isOffline);
@@ -806,7 +839,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
new StoredList.UserInterface(this).promptForListSelection(R.string.cache_menu_move_list, new Action1<Integer>() {
@Override
- public void call(Integer newListId) {
+ public void call(final Integer newListId) {
DataStore.moveToList(adapter.getCheckedOrAllCaches(), newListId);
adapter.setSelectMode(false);
@@ -816,7 +849,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
@Override
- public boolean onContextItemSelected(MenuItem item) {
+ public boolean onContextItemSelected(final MenuItem item) {
ContextMenu.ContextMenuInfo info = item.getMenuInfo();
// restore menu info for sub menu items, see
@@ -853,7 +886,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
case R.id.menu_drop_cache:
cache.drop(new Handler() {
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
adapter.notifyDataSetChanged();
refreshCurrentList();
}
@@ -863,7 +896,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
new StoredList.UserInterface(this).promptForListSelection(R.string.cache_menu_move_list, new Action1<Integer>() {
@Override
- public void call(Integer newListId) {
+ public void call(final Integer newListId) {
DataStore.moveToList(Collections.singletonList(cache), newListId);
adapter.setSelectMode(false);
refreshCurrentList();
@@ -874,9 +907,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
case R.id.menu_refresh:
refreshStored(Collections.singletonList(cache));
break;
- case R.id.menu_export:
- ExportFactory.showExportMenu(Collections.singletonList(cache), this);
- return false;
default:
// we must remember the menu info for the sub menu, there is a bug
// in Android:
@@ -904,7 +934,8 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
return adapter.findCacheByGeocode(contextMenuGeocode);
}
- private boolean setFilter(IFilter filter) {
+ private boolean setFilter(final IFilter filter) {
+ currentFilter = filter;
adapter.setFilter(filter);
prepareFilterBar();
updateTitle();
@@ -913,7 +944,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
@Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
+ public boolean onKeyDown(final int keyCode, final KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (adapter.isSelectMode()) {
adapter.setSelectMode(false);
@@ -927,12 +958,15 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
final ListView list = getListView();
registerForContextMenu(list);
adapter = new CacheListAdapter(this, cacheList, type);
+ adapter.setFilter(currentFilter);
- listFooter = getLayoutInflater().inflate(R.layout.cacheslist_footer, null);
- listFooter.setClickable(true);
- listFooter.setOnClickListener(new MoreCachesListener());
- listFooterText = (TextView) listFooter.findViewById(R.id.more_caches);
- list.addFooterView(listFooter);
+ if (listFooter == null) {
+ listFooter = getLayoutInflater().inflate(R.layout.cacheslist_footer, null);
+ listFooter.setClickable(true);
+ listFooter.setOnClickListener(new MoreCachesListener());
+ listFooterText = (TextView) listFooter.findViewById(R.id.more_caches);
+ list.addFooterView(listFooter);
+ }
setListAdapter(adapter);
adapter.forceSort();
}
@@ -975,7 +1009,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_IMPORT_GPX && resultCode == Activity.RESULT_OK) {
@@ -991,7 +1025,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
refreshCurrentList();
}
- private String getDisplayName(Uri uri) {
+ private String getDisplayName(final Uri uri) {
Cursor cursor = null;
try {
cursor = getContentResolver().query(uri, new String[] { OpenableColumns.DISPLAY_NAME }, null, null, null);
@@ -1017,25 +1051,32 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
return;
}
- if (Settings.getChooseList() && type != CacheListType.OFFLINE) {
+ if (Settings.getChooseList() && (type != CacheListType.OFFLINE && type != CacheListType.HISTORY)) {
// let user select list to store cache in
new StoredList.UserInterface(this).promptForListSelection(R.string.list_title,
new Action1<Integer>() {
@Override
public void call(final Integer selectedListId) {
- refreshStored(caches, selectedListId);
+ // in case of online lists, set the list id to a concrete list now
+ for (final Geocache geocache : caches) {
+ geocache.setListId(selectedListId);
+ }
+ refreshStoredInternal(caches);
}
}, true, StoredList.TEMPORARY_LIST_ID, newListName);
} else {
if (type != CacheListType.OFFLINE) {
- refreshStored(caches, StoredList.STANDARD_LIST_ID);
- } else {
- refreshStored(caches, this.listId);
+ for (final Geocache geocache : caches) {
+ if (geocache.getListId() == StoredList.TEMPORARY_LIST_ID) {
+ geocache.setListId(StoredList.STANDARD_LIST_ID);
+ }
+ }
}
+ refreshStoredInternal(caches);
}
}
- private void refreshStored(final List<Geocache> caches, final int storeListId) {
+ private void refreshStoredInternal(final List<Geocache> caches) {
detailProgress = 0;
showProgress(false);
@@ -1053,16 +1094,16 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
detailProgressTime = System.currentTimeMillis();
- final LoadDetailsThread threadDetails = new LoadDetailsThread(loadDetailsHandler, caches, storeListId);
+ final LoadDetailsThread threadDetails = new LoadDetailsThread(loadDetailsHandler, caches);
threadDetails.start();
}
public void removeFromHistoryCheck() {
- int message = (adapter != null && adapter.getCheckedCount() > 0) ? R.string.cache_remove_from_history
+ final int message = (adapter != null && adapter.getCheckedCount() > 0) ? R.string.cache_remove_from_history
: R.string.cache_clear_history;
Dialogs.confirmYesNo(this, R.string.caches_removing_from_history, message, new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int id) {
+ public void onClick(final DialogInterface dialog, final int id) {
removeFromHistory();
dialog.cancel();
}
@@ -1081,8 +1122,19 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
public void importWeb() {
- detailProgress = 0;
+ // menu is also shown with no device connected
+ if (Settings.getWebDeviceCode() == null) {
+ Dialogs.confirm(this, R.string.web_import_title, R.string.init_sendToCgeo_description, new OnClickListener() {
+
+ @Override
+ public void onClick(final DialogInterface dialog, final int which) {
+ SettingsActivity.openForScreen(R.string.preference_screen_sendtocgeo, CacheListActivity.this);
+ }
+ });
+ return;
+ }
+ detailProgress = 0;
showProgress(false);
final DownloadFromWebHandler downloadFromWebHandler = new DownloadFromWebHandler();
progress.show(this, null, res.getString(R.string.web_import_waiting), true, downloadFromWebHandler.cancelMessage());
@@ -1091,23 +1143,21 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
threadWeb.start();
}
- public void dropStored(final boolean removeListAfterwards) {
- int message = (adapter.getCheckedCount() > 0) ? R.string.caches_drop_selected_ask : R.string.caches_drop_all_ask;
- Dialogs.confirmYesNo(this, R.string.caches_drop_stored, message, new DialogInterface.OnClickListener() {
+ public void dropStored() {
+ final int titleId = (adapter.getCheckedCount() > 0) ? R.string.caches_remove_selected : R.string.caches_remove_all;
+ final int messageId = (adapter.getCheckedCount() > 0) ? R.string.caches_remove_selected_confirm : R.string.caches_remove_all_confirm;
+ final String message = getString(messageId, adapter.getCheckedOrAllCount());
+ Dialogs.confirmYesNo(this, titleId, message, new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int id) {
- dropSelected(removeListAfterwards);
+ public void onClick(final DialogInterface dialog, final int id) {
+ final List<Geocache> selected = adapter.getCheckedOrAllCaches();
+ new DropDetailsTask().execute(selected.toArray(new Geocache[selected.size()]));
dialog.cancel();
}
});
}
- public void dropSelected(boolean removeListAfterwards) {
- final List<Geocache> selected = adapter.getCheckedOrAllCaches();
- new DropDetailsTask(removeListAfterwards).execute(selected.toArray(new Geocache[selected.size()]));
- }
-
/**
* Thread to refresh the cache details.
*/
@@ -1115,15 +1165,11 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private class LoadDetailsThread extends Thread {
final private CancellableHandler handler;
- final private int listIdLD;
final private List<Geocache> caches;
- public LoadDetailsThread(CancellableHandler handler, List<Geocache> caches, int listId) {
+ public LoadDetailsThread(final CancellableHandler handler, final List<Geocache> caches) {
this.handler = handler;
this.caches = caches;
-
- // in case of online lists, set the list id to the standard list
- this.listIdLD = Math.max(listId, StoredList.STANDARD_LIST_ID);
}
@Override
@@ -1152,13 +1198,13 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
* @return
* <code>false</code> if the storing was interrupted, <code>true</code> otherwise
*/
- private boolean refreshCache(Geocache cache) {
+ private boolean refreshCache(final Geocache cache) {
try {
if (handler.isCancelled()) {
throw new InterruptedException("Stopped storing process.");
}
detailProgress++;
- cache.refreshSynchronous(listIdLD, null);
+ cache.refreshSynchronous(null);
handler.sendEmptyMessage(cacheList.indexOf(cache));
} catch (final InterruptedException e) {
Log.i(e.getMessage());
@@ -1176,7 +1222,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
final private CancellableHandler handler;
final private int listIdLFW;
- public LoadFromWebThread(CancellableHandler handler, int listId) {
+ public LoadFromWebThread(final CancellableHandler handler, final int listId) {
this.handler = handler;
listIdLFW = StoredList.getConcreteList(listId);
}
@@ -1226,26 +1272,18 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private class DropDetailsTask extends AsyncTaskWithProgress<Geocache, Void> {
- private final boolean removeListAfterwards;
-
- public DropDetailsTask(boolean removeListAfterwards) {
- super(CacheListActivity.this, null, res.getString(R.string.caches_drop_progress), true);
- this.removeListAfterwards = removeListAfterwards;
+ public DropDetailsTask() {
+ super(CacheListActivity.this, null, res.getString(R.string.caches_remove_progress), true);
}
@Override
- protected Void doInBackgroundInternal(Geocache[] caches) {
+ protected Void doInBackgroundInternal(final Geocache[] caches) {
DataStore.markDropped(Arrays.asList(caches));
return null;
}
@Override
- protected void onPostExecuteInternal(Void result) {
- // remove list in UI because of toast
- if (removeListAfterwards) {
- removeList(false);
- }
-
+ protected void onPostExecuteInternal(final Void result) {
adapter.setSelectMode(false);
refreshCurrentList();
replaceCacheListFromSearch();
@@ -1258,7 +1296,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
final private Handler handler;
final private List<Geocache> selected;
- public ClearOfflineLogsThread(Handler handlerIn) {
+ public ClearOfflineLogsThread(final Handler handlerIn) {
handler = handlerIn;
selected = adapter.getCheckedOrAllCaches();
}
@@ -1273,7 +1311,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private class MoreCachesListener implements View.OnClickListener {
@Override
- public void onClick(View arg0) {
+ public void onClick(final View arg0) {
showProgress(true);
showFooterLoadingCaches();
listFooter.setOnClickListener(null);
@@ -1291,13 +1329,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
}
- public void selectList() {
- if (!type.canSwitch) {
- return;
- }
- new StoredList.UserInterface(this).promptForListSelection(R.string.list_title, getListSwitchingRunnable());
- }
-
@NonNull
private Action1<Integer> getListSwitchingRunnable() {
return new Action1<Integer>() {
@@ -1309,7 +1340,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
};
}
- public void switchListById(int id) {
+ public void switchListById(final int id) {
if (id < 0) {
return;
}
@@ -1327,18 +1358,17 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
listId = list.id;
title = list.title;
+ type = CacheListType.OFFLINE;
Settings.saveLastList(listId);
+ initAdapter();
+
showProgress(true);
showFooterLoadingCaches();
DataStore.moveToList(adapter.getCheckedCaches(), listId);
- currentLoader = (OfflineGeocacheListLoader) getSupportLoaderManager().initLoader(CacheListType.OFFLINE.getLoaderId(), new Bundle(), this);
- currentLoader.reset();
- ((OfflineGeocacheListLoader) currentLoader).setListId(listId);
- ((OfflineGeocacheListLoader) currentLoader).setSearchCenter(coords);
- currentLoader.startLoading();
+ currentLoader = (OfflineGeocacheListLoader) getSupportLoaderManager().restartLoader(CacheListType.OFFLINE.getLoaderId(), OfflineGeocacheListLoader.getBundleForList(listId), this);
invalidateOptionsMenuCompatible();
}
@@ -1356,6 +1386,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private void removeListInternal() {
if (DataStore.removeList(listId)) {
showToast(res.getString(R.string.list_dialog_remove_ok));
+ refreshSpinnerAdapter();
switchListById(StoredList.STANDARD_LIST_ID);
} else {
showToast(res.getString(R.string.list_dialog_remove_err));
@@ -1365,12 +1396,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
private void removeList(final boolean askForConfirmation) {
// if there are no caches on this list, don't bother the user with questions.
// there is no harm in deleting the list, he could recreate it easily
- if (CollectionUtils.isEmpty(cacheList)) {
- removeListInternal();
- return;
- }
-
- if (!askForConfirmation) {
+ if (!askForConfirmation && CollectionUtils.isEmpty(cacheList)) {
removeListInternal();
return;
}
@@ -1378,17 +1404,13 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
// ask him, if there are caches on the list
Dialogs.confirm(this, R.string.list_dialog_remove_title, R.string.list_dialog_remove_description, R.string.list_dialog_remove, new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int whichButton) {
+ public void onClick(final DialogInterface dialog, final int whichButton) {
removeListInternal();
}
});
}
- /**
- * @param view
- * unused here but needed since this method is referenced from XML layout
- */
- public void goMap(View view) {
+ public void goMap() {
if (!cacheToShow()) {
return;
}
@@ -1404,6 +1426,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
private void refreshCurrentList() {
+ refreshSpinnerAdapter();
switchListById(listId);
}
@@ -1467,7 +1490,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
context.startActivity(cachesIntent);
}
- public static void startActivityHistory(Context context) {
+ public static void startActivityHistory(final Context context) {
final Intent cachesIntent = new Intent(context, CacheListActivity.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.HISTORY);
context.startActivity(cachesIntent);
@@ -1491,7 +1514,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
context.startActivity(cachesIntent);
}
- private static boolean isValidCoords(AbstractActivity context, Geopoint coords) {
+ private static boolean isValidCoords(final AbstractActivity context, final Geopoint coords) {
if (coords == null) {
context.showToast(CgeoApplication.getInstance().getString(R.string.warn_no_coordinates));
return false;
@@ -1533,7 +1556,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
// Loaders
@Override
- public Loader<SearchResult> onCreateLoader(int type, Bundle extras) {
+ public Loader<SearchResult> onCreateLoader(final int type, final Bundle extras) {
if (type >= CacheListLoaderType.values().length) {
throw new IllegalArgumentException("invalid loader type " + type);
}
@@ -1566,6 +1589,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
break;
case HISTORY:
title = res.getString(R.string.caches_history);
+ listId = PseudoList.HISTORY_LIST.id;
loader = new HistoryGeocacheListLoader(app, coords);
break;
case NEAREST:
@@ -1625,7 +1649,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
loader = new PocketGeocacheListLoader(app, guid);
break;
}
- setTitle(title);
+ updateTitle();
showProgress(true);
showFooterLoadingCaches();
@@ -1635,7 +1659,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
return loader;
}
- private void rememberTerm(String term) {
+ private void rememberTerm(final String term) {
// set the title of the activity
title = term;
// and remember this term for potential use in list creation
@@ -1643,7 +1667,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
@Override
- public void onLoadFinished(Loader<SearchResult> arg0, SearchResult searchIn) {
+ public void onLoadFinished(final Loader<SearchResult> arg0, final SearchResult searchIn) {
// The database search was moved into the UI call intentionally. If this is done before the runOnUIThread,
// then we have 2 sets of caches in memory. This can lead to OOM for huge cache lists.
if (searchIn != null) {
@@ -1660,10 +1684,46 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
showProgress(false);
hideLoading();
+ invalidateOptionsMenuCompatible();
}
@Override
- public void onLoaderReset(Loader<SearchResult> arg0) {
+ public void onLoaderReset(final Loader<SearchResult> arg0) {
//Not interesting
}
+
+ /**
+ * Allow the title bar spinner to show the same subtitle like the activity itself would show.
+ *
+ * @param list
+ * @return
+ */
+ public CharSequence getCacheListSubtitle(@NonNull final AbstractList list) {
+ // if this is the current list, be aware of filtering
+ if (list.id == listId) {
+ return getCurrentSubtitle();
+ }
+ // otherwise return the overall number
+ final int numberOfCaches = list.getNumberOfCaches();
+ if (numberOfCaches < 0) {
+ return StringUtils.EMPTY;
+ }
+ return getCacheNumberString(getResources(), numberOfCaches);
+ }
+
+ /**
+ * Calculate the subtitle of the current list depending on (optional) filters.
+ *
+ * @return
+ */
+ private CharSequence getCurrentSubtitle() {
+ final ArrayList<String> numbers = new ArrayList<String>();
+ if (adapter.isFiltered()) {
+ numbers.add(getCacheNumberString(getResources(), adapter.getCount()));
+ }
+ if (search != null) {
+ numbers.add(getCacheNumberString(getResources(), search.getCount()));
+ }
+ return numbers.isEmpty() ? null : StringUtils.join(numbers, '/');
+ }
}
diff --git a/main/src/cgeo/geocaching/CacheListSpinnerAdapter.java b/main/src/cgeo/geocaching/CacheListSpinnerAdapter.java
new file mode 100644
index 0000000..6311e47
--- /dev/null
+++ b/main/src/cgeo/geocaching/CacheListSpinnerAdapter.java
@@ -0,0 +1,68 @@
+package cgeo.geocaching;
+
+import cgeo.geocaching.list.AbstractList;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+class CacheListSpinnerAdapter extends ArrayAdapter<AbstractList> {
+
+ static class ViewHolder {
+ TextView title;
+ TextView subtitle;
+ }
+
+ private final CacheListActivity cacheListActivity;
+
+ public CacheListSpinnerAdapter(final CacheListActivity context, final int resource) {
+ super(context, resource);
+ cacheListActivity = context;
+ }
+
+
+ @Override
+ public View getView(final int position, final View convertView, final ViewGroup parent) {
+ return getCustomView(position, convertView, parent);
+ }
+
+
+ @Override
+ public View getDropDownView(final int position, final View convertView, final ViewGroup parent) {
+ return getCustomView(position, convertView, parent);
+ }
+
+ public View getCustomView(final int position, final View convertView, final ViewGroup parent) {
+
+ View resultView = convertView;
+ final LayoutInflater inflater =
+ (LayoutInflater) cacheListActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+
+ CacheListSpinnerAdapter.ViewHolder holder;
+ if (resultView == null) {
+ resultView = inflater.inflate(R.layout.cachelist_spinneritem, parent, false);
+ holder = new ViewHolder();
+ holder.title = (TextView) resultView.findViewById(android.R.id.text1);
+ holder.subtitle = (TextView) resultView.findViewById(android.R.id.text2);
+
+ resultView.setTag(holder);
+ } else {
+ holder = (CacheListSpinnerAdapter.ViewHolder) resultView.getTag();
+ }
+
+ final AbstractList list = getItem(position);
+ holder.title.setText(list.getTitle());
+ if (list.getNumberOfCaches() >= 0) {
+ holder.subtitle.setVisibility(View.VISIBLE);
+ holder.subtitle.setText(cacheListActivity.getCacheListSubtitle(list));
+ } else {
+ holder.subtitle.setVisibility(View.GONE);
+ }
+
+ return resultView;
+ }
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/CacheMenuHandler.java b/main/src/cgeo/geocaching/CacheMenuHandler.java
index cfe9eeb..9c8af50 100644
--- a/main/src/cgeo/geocaching/CacheMenuHandler.java
+++ b/main/src/cgeo/geocaching/CacheMenuHandler.java
@@ -5,13 +5,17 @@ import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.ui.AbstractUIFactory;
import android.app.Activity;
+import android.support.v4.app.Fragment;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.ShareActionProvider;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
/**
* Shared menu handling for all activities having menu items related to a cache. <br>
* TODO: replace by a fragment
- *
+ *
*/
public class CacheMenuHandler extends AbstractUIFactory {
@@ -19,7 +23,7 @@ public class CacheMenuHandler extends AbstractUIFactory {
* Methods to be implemented by the activity to react to the cache menu selections.
*
*/
- protected interface ActivityInterface {
+ interface ActivityInterface {
public void navigateTo();
public void showNavigationMenu();
@@ -28,9 +32,15 @@ public class CacheMenuHandler extends AbstractUIFactory {
}
- public static boolean onMenuItemSelected(MenuItem item, CacheMenuHandler.ActivityInterface activityInterface, Geocache cache) {
- assert activityInterface instanceof Activity;
- final Activity activity = (Activity) activityInterface;
+ public static boolean onMenuItemSelected(final MenuItem item, final CacheMenuHandler.ActivityInterface activityInterface, final Geocache cache) {
+ assert activityInterface instanceof Activity || activityInterface instanceof Fragment;
+ final Activity activity;
+ if (activityInterface instanceof Activity) {
+ activity = (Activity) activityInterface;
+ } else {
+ activity = ((Fragment)activityInterface).getActivity();
+ }
+
switch (item.getItemId()) {
case R.id.menu_default_navigation:
activityInterface.navigateTo();
@@ -45,8 +55,14 @@ public class CacheMenuHandler extends AbstractUIFactory {
cache.openInBrowser(activity);
return true;
case R.id.menu_share:
- cache.shareCache(activity, res);
- return true;
+ /* If the share menu is a shareActionProvider do nothing and let the share ActionProvider do the work */
+ final ShareActionProvider shareActionProvider = (ShareActionProvider)
+ MenuItemCompat.getActionProvider(item);
+ if (shareActionProvider == null) {
+ cache.shareCache(activity, res);
+ return true;
+ }
+ return false;
case R.id.menu_calendar:
CalendarAddon.addToCalendarWithIntent(activity, cache);
return true;
@@ -56,7 +72,6 @@ public class CacheMenuHandler extends AbstractUIFactory {
}
public static void onPrepareOptionsMenu(final Menu menu, final Geocache cache) {
- //
if (cache == null) {
return;
}
@@ -68,10 +83,22 @@ public class CacheMenuHandler extends AbstractUIFactory {
menu.findItem(R.id.menu_show_in_browser).setVisible(cache.canOpenInBrowser());
menu.findItem(R.id.menu_default_navigation).setTitle(NavigationAppFactory.getDefaultNavigationApplication().getName());
+
+ final MenuItem shareItem = menu.findItem(R.id.menu_share);
+ final ShareActionProvider shareActionProvider = (ShareActionProvider)
+ MenuItemCompat.getActionProvider(shareItem);
+ if(shareActionProvider != null) {
+ shareActionProvider.setShareIntent(cache.getShareIntent());
+ }
+
}
- public static void addMenuItems(Activity activity, Menu menu, Geocache cache) {
- activity.getMenuInflater().inflate(R.menu.cache_options, menu);
+ public static void addMenuItems(final MenuInflater inflater, final Menu menu, final Geocache cache) {
+ inflater.inflate(R.menu.cache_options, menu);
onPrepareOptionsMenu(menu, cache);
}
+
+ public static void addMenuItems(final Activity activity, final Menu menu, final Geocache cache) {
+ addMenuItems(activity.getMenuInflater(), menu, cache);
+ }
}
diff --git a/main/src/cgeo/geocaching/CachePopup.java b/main/src/cgeo/geocaching/CachePopup.java
index 543be22..9036d00 100644
--- a/main/src/cgeo/geocaching/CachePopup.java
+++ b/main/src/cgeo/geocaching/CachePopup.java
@@ -1,203 +1,63 @@
package cgeo.geocaching;
-import cgeo.geocaching.activity.Progress;
-import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
-import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.list.StoredList;
-import cgeo.geocaching.network.Network;
-import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.ui.CacheDetailsCreator;
-import cgeo.geocaching.utils.CancellableHandler;
-import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.ActivityMixin;
import org.apache.commons.lang3.StringUtils;
-import rx.Scheduler.Inner;
-import rx.functions.Action1;
-import rx.schedulers.Schedulers;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Configuration;
-import android.os.Handler;
-import android.os.Message;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.TextView;
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.view.Window;
-public class CachePopup extends AbstractPopupActivity {
- private final Progress progress = new Progress();
+public class CachePopup extends AbstractActivity {
- private class StoreCacheHandler extends CancellableHandler {
- private final int progressMessage;
+ protected String geocode = null;
- public StoreCacheHandler(final int progressMessage) {
- this.progressMessage = progressMessage;
- }
-
- @Override
- public void handleRegularMessage(Message msg) {
- if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) {
- updateStatusMsg((String) msg.obj);
- } else {
- init();
- }
- }
- private void updateStatusMsg(final String msg) {
- progress.setMessage(res.getString(progressMessage)
- + "\n\n"
- + msg);
+ void showDialog() {
+ // DialogFragment.show() will take care of adding the fragment
+ // in a transaction. We also want to remove any currently showing
+ // dialog, so make our own transaction and take care of that here.
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+ Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
+ if (prev != null) {
+ ft.remove(prev);
}
- }
+ ft.addToBackStack(null);
- private class DropCacheHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- CachePopup.this.finish();
- }
- }
-
- public CachePopup() {
- super(R.layout.popup);
+ // Create and show the dialog.
+ DialogFragment newFragment = CachePopupFragment.newInstance(geocode);
+ newFragment.show(ft, "dialog");
}
@Override
- public void showNavigationMenu() {
- NavigationAppFactory.showNavigationMenu(this, cache, null, null);
- }
-
- @Override
- protected void init() {
- super.init();
- try {
- if (StringUtils.isNotBlank(cache.getName())) {
- setTitle(cache.getName());
- } else {
- setTitle(geocode);
- }
-
- // actionbar icon
- ((TextView) findViewById(R.id.actionbar_title)).setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(cache.getType().markerId), null, null, null);
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
+ this.setTheme(ActivityMixin.getDialogTheme());
- details = new CacheDetailsCreator(this, (LinearLayout) findViewById(R.id.details_list));
- addCacheDetails();
-
- // offline use
- CacheDetailActivity.updateOfflineBox(findViewById(android.R.id.content), cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener());
-
- } catch (Exception e) {
- Log.e("CachePopup.init", e);
+ final Bundle extras = getIntent().getExtras();
+ if (extras != null) {
+ geocode = extras.getString(Intents.EXTRA_GEOCODE);
}
- // cache is loaded. remove progress-popup if any there
- progress.dismiss();
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
-
- init();
- }
-
- private class StoreCacheClickListener implements View.OnClickListener {
- @Override
- public void onClick(View arg0) {
- if (progress.isShowing()) {
- showToast(res.getString(R.string.err_detail_still_working));
- return;
- }
-
- if (Settings.getChooseList()) {
- // let user select list to store cache in
- new StoredList.UserInterface(CachePopup.this).promptForListSelection(R.string.list_title,
- new Action1<Integer>() {
- @Override
- public void call(final Integer selectedListId) {
- storeCache(selectedListId);
- }
- }, true, StoredList.TEMPORARY_LIST_ID);
- } else {
- storeCache(StoredList.TEMPORARY_LIST_ID);
- }
- }
+ if (StringUtils.isBlank(geocode)) {
+ showToast(res.getString(R.string.err_detail_cache_find));
- protected void storeCache(final int listId) {
- final StoreCacheHandler storeCacheHandler = new StoreCacheHandler(R.string.cache_dialog_offline_save_message);
- progress.show(CachePopup.this, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.cancelMessage());
- Schedulers.io().schedule(new Action1<Inner>() {
- @Override
- public void call(final Inner inner) {
- cache.store(listId, storeCacheHandler);
- invalidateOptionsMenuCompatible();
- }
- });
- }
- }
-
- private class RefreshCacheClickListener implements View.OnClickListener {
- @Override
- public void onClick(View arg0) {
- if (progress.isShowing()) {
- showToast(res.getString(R.string.err_detail_still_working));
- return;
- }
-
- if (!Network.isNetworkConnected(getApplicationContext())) {
- showToast(getString(R.string.err_server));
- return;
- }
-
- final StoreCacheHandler refreshCacheHandler = new StoreCacheHandler(R.string.cache_dialog_offline_save_message);
- progress.show(CachePopup.this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage());
- cache.refresh(cache.getListId(), refreshCacheHandler, Schedulers.io());
- }
- }
-
- private class DropCacheClickListener implements View.OnClickListener {
- @Override
- public void onClick(View arg0) {
- if (progress.isShowing()) {
- showToast(res.getString(R.string.err_detail_still_working));
- return;
- }
-
- final DropCacheHandler dropCacheHandler = new DropCacheHandler();
- progress.show(CachePopup.this, res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true, null);
- cache.drop(dropCacheHandler, Schedulers.io());
- }
- }
-
- @Override
- public void navigateTo() {
- NavigationAppFactory.startDefaultNavigationApplication(1, this, cache);
- }
-
- /**
- * Tries to navigate to the {@link Geocache} of this activity.
- */
- @Override
- protected void startDefaultNavigation2() {
- if (cache == null || cache.getCoords() == null) {
- showToast(res.getString(R.string.cache_coordinates_no));
+ finish();
return;
}
- NavigationAppFactory.startDefaultNavigationApplication(2, this, cache);
- finish();
+ showDialog();
}
- public static void startActivity(final Context context, final String geocode) {
+ public static void startActivity(Context context, String geocode) {
final Intent popupIntent = new Intent(context, CachePopup.class);
popupIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
context.startActivity(popupIntent);
}
-
- @Override
- protected Geopoint getCoordinates() {
- if (cache == null) {
- return null;
- }
- return cache.getCoords();
- }
}
diff --git a/main/src/cgeo/geocaching/CachePopupFragment.java b/main/src/cgeo/geocaching/CachePopupFragment.java
new file mode 100644
index 0000000..010d701
--- /dev/null
+++ b/main/src/cgeo/geocaching/CachePopupFragment.java
@@ -0,0 +1,229 @@
+package cgeo.geocaching;
+
+import cgeo.geocaching.activity.Progress;
+import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.list.StoredList;
+import cgeo.geocaching.network.Network;
+import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.ui.CacheDetailsCreator;
+import cgeo.geocaching.utils.CancellableHandler;
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+
+import rx.functions.Action0;
+import rx.functions.Action1;
+import rx.schedulers.Schedulers;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.v4.app.DialogFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class CachePopupFragment extends AbstractDialogFragment {
+ private final Progress progress = new Progress();
+
+ public static DialogFragment newInstance(String geocode) {
+
+ Bundle args = new Bundle();
+ args.putString(GEOCODE_ARG,geocode);
+
+ DialogFragment f = new CachePopupFragment();
+ f.setStyle(DialogFragment.STYLE_NO_TITLE,0);
+ f.setArguments(args);
+
+ return f;
+ }
+
+ private class StoreCacheHandler extends CancellableHandler {
+ private final int progressMessage;
+
+ public StoreCacheHandler(final int progressMessage) {
+ this.progressMessage = progressMessage;
+ }
+
+ @Override
+ public void handleRegularMessage(Message msg) {
+ if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) {
+ updateStatusMsg((String) msg.obj);
+ } else {
+ init();
+ }
+ }
+
+ private void updateStatusMsg(final String msg) {
+ progress.setMessage(res.getString(progressMessage)
+ + "\n\n"
+ + msg);
+ }
+ }
+
+ private class DropCacheHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ getActivity().finish();
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.popup, container, false);
+ initCustomActionBar(v);
+ return v;
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+
+ try {
+ if (StringUtils.isNotBlank(cache.getName())) {
+ setTitle(cache.getName());
+ } else {
+ setTitle(geocode);
+ }
+
+ ((TextView) getView().findViewById(R.id.actionbar_title)).setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(cache.getType().markerId), null, null, null);
+
+ details = new CacheDetailsCreator(getActivity(), (LinearLayout) getView().findViewById(R.id.details_list));
+
+ addCacheDetails();
+
+ // offline use
+ CacheDetailActivity.updateOfflineBox(getView(), cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener());
+
+ } catch (Exception e) {
+ Log.e("CachePopupFragment.init", e);
+ }
+
+ // cache is loaded. remove progress-popup if any there
+ progress.dismiss();
+ }
+
+
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ init();
+ }
+
+ private class StoreCacheClickListener implements View.OnClickListener {
+ @Override
+ public void onClick(View arg0) {
+ if (progress.isShowing()) {
+ showToast(res.getString(R.string.err_detail_still_working));
+ return;
+ }
+
+ if (Settings.getChooseList()) {
+ // let user select list to store cache in
+ new StoredList.UserInterface(getActivity()).promptForListSelection(R.string.list_title,
+ new Action1<Integer>() {
+ @Override
+ public void call(final Integer selectedListId) {
+ storeCache(selectedListId);
+ }
+ }, true, StoredList.TEMPORARY_LIST_ID);
+ } else {
+ storeCache(StoredList.TEMPORARY_LIST_ID);
+ }
+ }
+
+ protected void storeCache(final int listId) {
+ final StoreCacheHandler storeCacheHandler = new StoreCacheHandler(R.string.cache_dialog_offline_save_message);
+ progress.show(getActivity(), res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.cancelMessage());
+ Schedulers.io().createWorker().schedule(new Action0() {
+ @Override
+ public void call() {
+ cache.store(listId, storeCacheHandler);
+ getActivity().supportInvalidateOptionsMenu();
+ }
+ });
+ }
+ }
+
+ private class RefreshCacheClickListener implements View.OnClickListener {
+ @Override
+ public void onClick(View arg0) {
+ if (progress.isShowing()) {
+ showToast(res.getString(R.string.err_detail_still_working));
+ return;
+ }
+
+ if (!Network.isNetworkConnected(getActivity())) {
+ showToast(getString(R.string.err_server));
+ return;
+ }
+
+ final StoreCacheHandler refreshCacheHandler = new StoreCacheHandler(R.string.cache_dialog_offline_save_message);
+ progress.show(getActivity(), res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage());
+ cache.refresh(refreshCacheHandler, Schedulers.io());
+ }
+ }
+
+ private class DropCacheClickListener implements View.OnClickListener {
+ @Override
+ public void onClick(View arg0) {
+ if (progress.isShowing()) {
+ showToast(res.getString(R.string.err_detail_still_working));
+ return;
+ }
+
+ final DropCacheHandler dropCacheHandler = new DropCacheHandler();
+ progress.show(getActivity(), res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true, null);
+ cache.drop(dropCacheHandler, Schedulers.io());
+ }
+ }
+
+
+ @Override
+ public void navigateTo() {
+ NavigationAppFactory.startDefaultNavigationApplication(1, getActivity(), cache);
+ }
+
+ @Override
+ public void showNavigationMenu() {
+ // TODO
+ }
+
+
+ /**
+ * Tries to navigate to the {@link cgeo.geocaching.Geocache} of this activity.
+ */
+ @Override
+ protected void startDefaultNavigation2() {
+ if (cache == null || cache.getCoords() == null) {
+ showToast(res.getString(R.string.cache_coordinates_no));
+ return;
+ }
+ NavigationAppFactory.startDefaultNavigationApplication(2, getActivity(), cache);
+ getActivity().finish();
+ }
+
+ public static void startActivity(final Context context, final String geocode) {
+ final Intent popupIntent = new Intent(context, CachePopup.class);
+ popupIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
+ context.startActivity(popupIntent);
+ }
+
+ @Override
+ protected Geopoint getCoordinates() {
+ if (cache == null) {
+ return null;
+ }
+ return cache.getCoords();
+ }
+
+
+}
diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java
index 09aee93..2ee91be 100644
--- a/main/src/cgeo/geocaching/CgeoApplication.java
+++ b/main/src/cgeo/geocaching/CgeoApplication.java
@@ -10,6 +10,12 @@ import rx.functions.Action1;
import rx.observables.ConnectableObservable;
import android.app.Application;
+import android.os.Environment;
+import android.view.ViewConfiguration;
+
+import java.io.IOException;
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.lang.reflect.Field;
public class CgeoApplication extends Application {
@@ -22,6 +28,31 @@ public class CgeoApplication extends Application {
private volatile IGeoData currentGeo = null;
private volatile float currentDirection = 0.0f;
+ static {
+ final UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
+
+ Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
+
+ @Override
+ public void uncaughtException(final Thread thread, final Throwable ex) {
+ Log.e("UncaughtException", ex);
+ Throwable exx = ex;
+ while (exx.getCause() != null) {
+ exx = exx.getCause();
+ }
+ if (exx.getClass().equals(OutOfMemoryError.class)) {
+ try {
+ Log.e("OutOfMemory");
+ android.os.Debug.dumpHprofData(Environment.getExternalStorageDirectory().getPath() + "/dump.hprof");
+ } catch (final IOException e) {
+ Log.e("Error writing dump", e);
+ }
+ }
+ defaultHandler.uncaughtException(thread, ex);
+ }
+ });
+ }
+
public CgeoApplication() {
setInstance(this);
}
@@ -35,6 +66,21 @@ public class CgeoApplication extends Application {
}
@Override
+ public void onCreate() {
+ try {
+ final ViewConfiguration config = ViewConfiguration.get(this);
+ final Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
+
+ if (menuKeyField != null) {
+ menuKeyField.setAccessible(true);
+ menuKeyField.setBoolean(config, false);
+ }
+ } catch (final Exception ex) {
+ // Ignore
+ }
+ }
+
+ @Override
public void onLowMemory() {
Log.i("Cleaning applications cache.");
DataStore.removeAllFromCache();
@@ -69,7 +115,7 @@ public class CgeoApplication extends Application {
}
public IGeoData currentGeo() {
- return currentGeo != null ? currentGeo : geoDataObservable().toBlockingObservable().first();
+ return currentGeo != null ? currentGeo : geoDataObservable().toBlocking().first();
}
public float currentDirection() {
diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java
index 36dcf27..ef70837 100644
--- a/main/src/cgeo/geocaching/CompassActivity.java
+++ b/main/src/cgeo/geocaching/CompassActivity.java
@@ -3,7 +3,7 @@ package cgeo.geocaching;
import butterknife.ButterKnife;
import butterknife.InjectView;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Units;
@@ -38,7 +38,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-public class CompassActivity extends AbstractActivity {
+public class CompassActivity extends AbstractActionBarActivity {
private static final int COORDINATES_OFFSET = 10;
@@ -69,7 +69,7 @@ public class CompassActivity extends AbstractActivity {
private boolean hasMagneticFieldSensor;
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.compass_activity);
final SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
@@ -79,7 +79,7 @@ public class CompassActivity extends AbstractActivity {
}
// get parameters
- Bundle extras = getIntent().getExtras();
+ final Bundle extras = getIntent().getExtras();
if (extras != null) {
final String geocode = extras.getString(EXTRAS_GEOCODE);
if (StringUtils.isNotEmpty(geocode)) {
@@ -98,7 +98,7 @@ public class CompassActivity extends AbstractActivity {
}
}
} else {
- Intent pointIntent = new Intent(this, NavigateAnyPointActivity.class);
+ final Intent pointIntent = new Intent(this, NavigateAnyPointActivity.class);
startActivity(pointIntent);
finish();
@@ -129,7 +129,7 @@ public class CompassActivity extends AbstractActivity {
}
@Override
- public void onConfigurationChanged(Configuration newConfig) {
+ public void onConfigurationChanged(final Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.compass_activity);
@@ -150,7 +150,7 @@ public class CompassActivity extends AbstractActivity {
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.compass_activity_options, menu);
- menu.findItem(R.id.menu_switch_compass_gps).setVisible(hasMagneticFieldSensor);
+ menu.findItem(R.id.menu_compass_sensor).setVisible(hasMagneticFieldSensor);
final SubMenu subMenu = menu.findItem(R.id.menu_select_destination).getSubMenu();
if (coordinates.size() > 1) {
for (int i = 0; i < coordinates.size(); i++) {
@@ -167,43 +167,47 @@ public class CompassActivity extends AbstractActivity {
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
+ public boolean onPrepareOptionsMenu(final Menu menu) {
super.onPrepareOptionsMenu(menu);
- menu.findItem(R.id.menu_switch_compass_gps).setTitle(res.getString(Settings.isUseCompass() ? R.string.use_gps : R.string.use_compass));
+ if (Settings.isUseCompass()) {
+ menu.findItem(R.id.menu_compass_sensor_magnetic).setChecked(true);
+ }
+ else {
+ menu.findItem(R.id.menu_compass_sensor_gps).setChecked(true);
+ }
menu.findItem(R.id.menu_tts_start).setVisible(!SpeechService.isRunning());
menu.findItem(R.id.menu_tts_stop).setVisible(SpeechService.isRunning());
return true;
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- int id = item.getItemId();
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ final int id = item.getItemId();
switch (id) {
case R.id.menu_map:
CGeoMap.startActivityCoords(this, dstCoords, null, null);
return true;
- case R.id.menu_switch_compass_gps:
- boolean oldSetting = Settings.isUseCompass();
- Settings.setUseCompass(!oldSetting);
+ case R.id.menu_compass_sensor_gps:
+ Settings.setUseCompass(false);
invalidateOptionsMenuCompatible();
return true;
- case R.id.menu_edit_destination:
- Intent pointIntent = new Intent(this, NavigateAnyPointActivity.class);
- startActivity(pointIntent);
-
- finish();
+ case R.id.menu_compass_sensor_magnetic:
+ Settings.setUseCompass(true);
+ invalidateOptionsMenuCompatible();
return true;
case R.id.menu_tts_start:
SpeechService.startService(this, dstCoords);
+ invalidateOptionsMenuCompatible();
return true;
case R.id.menu_tts_stop:
SpeechService.stopService(this);
+ invalidateOptionsMenuCompatible();
return true;
default:
if (LoggingUI.onMenuItemSelected(item, this, cache)) {
return true;
}
- int coordinatesIndex = id - COORDINATES_OFFSET;
+ final int coordinatesIndex = id - COORDINATES_OFFSET;
if (coordinatesIndex >= 0 && coordinatesIndex < coordinates.size()) {
final IWaypoint coordinate = coordinates.get(coordinatesIndex);
title = coordinate.getName();
@@ -217,7 +221,7 @@ public class CompassActivity extends AbstractActivity {
return true;
}
}
- return false;
+ return super.onOptionsItemSelected(item);
}
private void setTitle() {
@@ -255,7 +259,7 @@ public class CompassActivity extends AbstractActivity {
headingView.setText(Math.round(cacheHeading) + "°");
}
- private GeoDirHandler geoDirHandler = new GeoDirHandler() {
+ private final GeoDirHandler geoDirHandler = new GeoDirHandler() {
@Override
public void updateGeoDir(final IGeoData geo, final float dir) {
try {
@@ -283,7 +287,7 @@ public class CompassActivity extends AbstractActivity {
}
updateNorthHeading(DirectionProvider.getDirectionNow(dir));
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.w("Failed to LocationUpdater location.");
}
}
@@ -299,7 +303,7 @@ public class CompassActivity extends AbstractActivity {
final String info) {
coordinates.clear();
if (coordinatesWithType != null) {
- for (IWaypoint coordinate : coordinatesWithType) {
+ for (final IWaypoint coordinate : coordinatesWithType) {
if (coordinate != null) {
coordinates.add(coordinate);
}
diff --git a/main/src/cgeo/geocaching/CreateShortcutActivity.java b/main/src/cgeo/geocaching/CreateShortcutActivity.java
index b6ea4f6..ffcf81b 100644
--- a/main/src/cgeo/geocaching/CreateShortcutActivity.java
+++ b/main/src/cgeo/geocaching/CreateShortcutActivity.java
@@ -1,6 +1,6 @@
package cgeo.geocaching;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.list.PseudoList;
import cgeo.geocaching.list.StoredList;
@@ -10,7 +10,7 @@ import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.os.Bundle;
-public class CreateShortcutActivity extends AbstractActivity {
+public class CreateShortcutActivity extends AbstractActionBarActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -27,7 +27,7 @@ public class CreateShortcutActivity extends AbstractActivity {
@Override
public void call(final Integer listId) {
- final Intent shortcut = createShortcut(listId.intValue());
+ final Intent shortcut = createShortcut(listId);
setResult(RESULT_OK, shortcut);
// finish activity to return the shortcut
diff --git a/main/src/cgeo/geocaching/DataStore.java b/main/src/cgeo/geocaching/DataStore.java
index 32a4b64..bdbb97e 100644
--- a/main/src/cgeo/geocaching/DataStore.java
+++ b/main/src/cgeo/geocaching/DataStore.java
@@ -16,6 +16,7 @@ import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.list.AbstractList;
import cgeo.geocaching.list.PseudoList;
import cgeo.geocaching.list.StoredList;
+import cgeo.geocaching.search.SearchSuggestionCursor;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.Dialogs;
import cgeo.geocaching.utils.FileUtils;
@@ -36,7 +37,6 @@ import rx.util.async.Async;
import android.app.Activity;
import android.app.ProgressDialog;
-import android.app.SearchManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.ContextWrapper;
@@ -49,7 +49,6 @@ import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteDoneException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
-import android.provider.BaseColumns;
import java.io.File;
import java.io.FilenameFilter;
@@ -57,6 +56,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
@@ -325,7 +325,7 @@ public class DataStore {
final DbHelper dbHelper = new DbHelper(new DBContext(CgeoApplication.getInstance()));
try {
database = dbHelper.getWritableDatabase();
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("DataStore.init: unable to open database for R/W", e);
recreateDatabase(dbHelper);
}
@@ -347,7 +347,7 @@ public class DataStore {
}
try {
database = dbHelper.getWritableDatabase();
- } catch (Exception f) {
+ } catch (final Exception f) {
Log.e("DataStore.init: unable to recreate database and open it for R/W", f);
}
}
@@ -420,14 +420,14 @@ public class DataStore {
init();
return true;
}
- })).subscribe(new Action1<Boolean>() {
+ })).subscribeOn(Schedulers.io()).subscribe(new Action1<Boolean>() {
@Override
public void call(final Boolean success) {
dialog.dismiss();
final String message = success ? fromActivity.getString(R.string.init_dbmove_success) : fromActivity.getString(R.string.init_dbmove_failed);
Dialogs.message(fromActivity, R.string.init_dbmove_dbmove, message);
}
- }, Schedulers.io());
+ });
}
private static File databasePath(final boolean internal) {
@@ -464,7 +464,7 @@ public class DataStore {
private static class DBContext extends ContextWrapper {
- public DBContext(Context base) {
+ public DBContext(final Context base) {
super(base);
}
@@ -473,8 +473,8 @@ public class DataStore {
* causes issues on other devices too.
*/
@Override
- public SQLiteDatabase openOrCreateDatabase(String name, int mode,
- CursorFactory factory) {
+ public SQLiteDatabase openOrCreateDatabase(final String name, final int mode,
+ final CursorFactory factory) {
final File file = new File(name);
FileUtils.mkdirs(file.getParentFile());
return SQLiteDatabase.openOrCreateDatabase(file, factory);
@@ -486,12 +486,12 @@ public class DataStore {
private static boolean firstRun = true;
- DbHelper(Context context) {
+ DbHelper(final Context context) {
super(context, databasePath().getPath(), null, dbVersion);
}
@Override
- public void onCreate(SQLiteDatabase db) {
+ public void onCreate(final SQLiteDatabase db) {
newlyCreatedDatabase = true;
db.execSQL(dbCreateCaches);
db.execSQL(dbCreateLists);
@@ -528,7 +528,7 @@ public class DataStore {
}
@Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
Log.i("Upgrade database from ver. " + oldVersion + " to ver. " + newVersion + ": start");
try {
@@ -553,7 +553,7 @@ public class DataStore {
db.execSQL(dbCreateSearchDestinationHistory);
Log.i("Added table " + dbTableSearchDestionationHistory + ".");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 52", e);
}
}
@@ -563,7 +563,7 @@ public class DataStore {
db.execSQL("alter table " + dbTableCaches + " add column onWatchlist integer");
Log.i("Column onWatchlist added to " + dbTableCaches + ".");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 53", e);
}
}
@@ -571,7 +571,7 @@ public class DataStore {
if (oldVersion < 54) { // update to 54
try {
db.execSQL(dbCreateLogImages);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 54", e);
}
@@ -580,7 +580,7 @@ public class DataStore {
if (oldVersion < 55) { // update to 55
try {
db.execSQL("alter table " + dbTableCaches + " add column personal_note text");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 55", e);
}
}
@@ -592,7 +592,7 @@ public class DataStore {
db.execSQL("update " + dbTableAttributes + " set attribute = " +
"lower(attribute) where attribute like \"%_yes\" " +
"or attribute like \"%_no\"");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 56", e);
}
}
@@ -607,7 +607,7 @@ public class DataStore {
db.execSQL("drop index in_e");
db.execSQL("drop index in_f");
createIndices(db);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 57", e);
}
}
@@ -696,7 +696,7 @@ public class DataStore {
db.setTransactionSuccessful();
Log.i("Removed latitude_string and longitude_string columns");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 58", e);
} finally {
db.endTransaction();
@@ -708,7 +708,7 @@ public class DataStore {
// Add new indices and remove obsolete cache files
createIndices(db);
removeObsoleteCacheDirectories(db);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 59", e);
}
}
@@ -716,7 +716,7 @@ public class DataStore {
if (oldVersion < 60) {
try {
removeSecEmptyDirs();
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 60", e);
}
}
@@ -724,7 +724,7 @@ public class DataStore {
try {
db.execSQL("alter table " + dbTableLogs + " add column friend integer");
db.execSQL("alter table " + dbTableCaches + " add column coordsChanged integer default 0");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 61", e);
}
@@ -735,7 +735,7 @@ public class DataStore {
db.execSQL("alter table " + dbTableCaches + " add column finalDefined integer default 0");
db.execSQL("alter table " + dbTableWaypoints + " add column own integer default 0");
db.execSQL("update " + dbTableWaypoints + " set own = 1 where type = 'own'");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 62", e);
}
@@ -743,7 +743,7 @@ public class DataStore {
if (oldVersion < 63) {
try {
removeDoubleUnderscoreMapFiles();
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 63", e);
}
@@ -755,7 +755,7 @@ public class DataStore {
// rather than symbolic ones because the fix must be applied with the values at the time
// of the problem. The problem was introduced in release 2012.06.01.
db.execSQL("update " + dbTableCaches + " set reason=1 where reason=2");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 64", e);
}
}
@@ -764,7 +764,7 @@ public class DataStore {
try {
// Set all waypoints where name is Original coordinates to type ORIGINAL
db.execSQL("update " + dbTableWaypoints + " set type='original', own=0 where name='Original Coordinates'");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 65:", e);
}
}
@@ -772,7 +772,7 @@ public class DataStore {
if (oldVersion < 66) {
try {
db.execSQL("alter table " + dbTableWaypoints + " add column visited integer default 0");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 66", e);
}
@@ -782,7 +782,7 @@ public class DataStore {
try {
db.execSQL("update " + dbTableAttributes + " set attribute = 'easy_climbing_yes' where geocode like 'OC%' and attribute = 'climbing_yes'");
db.execSQL("update " + dbTableAttributes + " set attribute = 'easy_climbing_no' where geocode like 'OC%' and attribute = 'climbing_no'");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 67", e);
}
@@ -791,7 +791,7 @@ public class DataStore {
if (oldVersion < 68) {
try {
db.execSQL("alter table " + dbTableCaches + " add column logPasswordRequired integer default 0");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Failed to upgrade to ver. 68", e);
}
@@ -838,7 +838,7 @@ public class DataStore {
if (ArrayUtils.isNotEmpty(geocodeDirs)) {
final FilenameFilter filter = new FilenameFilter() {
@Override
- public boolean accept(File dir, String filename) {
+ public boolean accept(final File dir, final String filename) {
return filename.startsWith("map_") && filename.contains("__");
}
};
@@ -914,7 +914,7 @@ public class DataStore {
}
}
- private static void dropDatabase(SQLiteDatabase db) {
+ private static void dropDatabase(final SQLiteDatabase db) {
db.execSQL("drop table if exists " + dbTableCaches);
db.execSQL("drop table if exists " + dbTableAttributes);
db.execSQL("drop table if exists " + dbTableWaypoints);
@@ -925,7 +925,7 @@ public class DataStore {
db.execSQL("drop table if exists " + dbTableTrackables);
}
- public static boolean isThere(String geocode, String guid, boolean detailed, boolean checkTime) {
+ public static boolean isThere(final String geocode, final String guid, final boolean detailed, final boolean checkTime) {
init();
long dataUpdated = 0;
@@ -990,7 +990,7 @@ public class DataStore {
}
/** is cache stored in one of the lists (not only temporary) */
- public static boolean isOffline(String geocode, String guid) {
+ public static boolean isOffline(final String geocode, final String guid) {
if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) {
return false;
}
@@ -1011,16 +1011,16 @@ public class DataStore {
listId.bindString(1, value);
return listId.simpleQueryForLong() != StoredList.TEMPORARY_LIST_ID;
}
- } catch (SQLiteDoneException e) {
+ } catch (final SQLiteDoneException e) {
// Do nothing, it only means we have no information on the cache
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("DataStore.isOffline", e);
}
return false;
}
- public static String getGeocodeForGuid(String guid) {
+ public static String getGeocodeForGuid(final String guid) {
if (StringUtils.isBlank(guid)) {
return null;
}
@@ -1032,16 +1032,16 @@ public class DataStore {
description.bindString(1, guid);
return description.simpleQueryForString();
}
- } catch (SQLiteDoneException e) {
+ } catch (final SQLiteDoneException e) {
// Do nothing, it only means we have no information on the cache
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("DataStore.getGeocodeForGuid", e);
}
return null;
}
- public static String getCacheidForGeocode(String geocode) {
+ public static String getCacheidForGeocode(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
@@ -1053,9 +1053,9 @@ public class DataStore {
description.bindString(1, geocode);
return description.simpleQueryForString();
}
- } catch (SQLiteDoneException e) {
+ } catch (final SQLiteDoneException e) {
// Do nothing, it only means we have no information on the cache
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("DataStore.getCacheidForGeocode", e);
}
@@ -1070,7 +1070,7 @@ public class DataStore {
* @param saveFlags
*
*/
- public static void saveCache(Geocache cache, EnumSet<LoadFlags.SaveFlag> saveFlags) {
+ public static void saveCache(final Geocache cache, final EnumSet<LoadFlags.SaveFlag> saveFlags) {
saveCaches(Collections.singletonList(cache), saveFlags);
}
@@ -1082,7 +1082,7 @@ public class DataStore {
* @param saveFlags
*
*/
- public static void saveCaches(Collection<Geocache> caches, EnumSet<LoadFlags.SaveFlag> saveFlags) {
+ public static void saveCaches(final Collection<Geocache> caches, final EnumSet<LoadFlags.SaveFlag> saveFlags) {
if (CollectionUtils.isEmpty(caches)) {
return;
}
@@ -1090,7 +1090,7 @@ public class DataStore {
final HashMap<String, Geocache> existingCaches = new HashMap<String, Geocache>();
// first check which caches are in the memory cache
- for (Geocache cache : caches) {
+ for (final Geocache cache : caches) {
final String geocode = cache.getGeocode();
final Geocache cacheFromCache = cacheCache.getCacheFromCache(geocode);
if (cacheFromCache == null) {
@@ -1102,7 +1102,7 @@ public class DataStore {
}
// then load all remaining caches from the database in one step
- for (Geocache cacheFromDatabase : loadCaches(cachesFromDatabase, LoadFlags.LOAD_ALL_DB_ONLY)) {
+ for (final Geocache cacheFromDatabase : loadCaches(cachesFromDatabase, LoadFlags.LOAD_ALL_DB_ONLY)) {
existingCaches.put(cacheFromDatabase.getGeocode(), cacheFromDatabase);
}
@@ -1113,7 +1113,7 @@ public class DataStore {
// (as it may be more recent than the version in the database), or if the
// version coming from the database is different than the version we are entering
// into the cache (that includes absence from the database).
- for (Geocache cache : caches) {
+ for (final Geocache cache : caches) {
final String geocode = cache.getGeocode();
final Geocache existingCache = existingCaches.get(geocode);
final boolean dbUpdateRequired = !cache.gatherMissingFrom(existingCache) || cacheCache.getCacheFromCache(geocode) != null;
@@ -1127,7 +1127,7 @@ public class DataStore {
}
}
- for (Geocache geocache : toBeStored) {
+ for (final Geocache geocache : toBeStored) {
storeIntoDatabase(geocache);
}
}
@@ -1137,7 +1137,7 @@ public class DataStore {
cacheCache.putCacheInCache(cache);
Log.d("Saving " + cache.toString() + " (" + cache.getListId() + ") to DB");
- ContentValues values = new ContentValues();
+ final ContentValues values = new ContentValues();
if (cache.getUpdated() == 0) {
values.put("updated", System.currentTimeMillis());
@@ -1200,7 +1200,7 @@ public class DataStore {
saveLogCountsWithoutTransaction(cache);
saveInventoryWithoutTransaction(cache.getGeocode(), cache.getInventory());
- int rows = database.update(dbTableCaches, values, "geocode = ?", new String[] { cache.getGeocode() });
+ final int rows = database.update(dbTableCaches, values, "geocode = ?", new String[] { cache.getGeocode() });
if (rows == 0) {
// cache is not in the DB, insert it
/* long id = */
@@ -1208,7 +1208,7 @@ public class DataStore {
}
database.setTransactionSuccessful();
return true;
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("SaveCache", e);
} finally {
database.endTransaction();
@@ -1228,7 +1228,7 @@ public class DataStore {
if (attributes.isEmpty()) {
return;
}
- SQLiteStatement statement = PreparedStatements.getInsertAttribute();
+ final SQLiteStatement statement = PreparedStatements.getInsertAttribute();
final long timestamp = System.currentTimeMillis();
for (final String attribute : attributes) {
statement.bindString(1, geocode);
@@ -1251,10 +1251,10 @@ public class DataStore {
database.beginTransaction();
try {
- SQLiteStatement insertDestination = PreparedStatements.getInsertSearchDestination(destination);
+ final SQLiteStatement insertDestination = PreparedStatements.getInsertSearchDestination(destination);
insertDestination.executeInsert();
database.setTransactionSuccessful();
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Updating searchedDestinations db failed", e);
} finally {
database.endTransaction();
@@ -1269,7 +1269,7 @@ public class DataStore {
saveWaypointsWithoutTransaction(cache);
database.setTransactionSuccessful();
return true;
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("saveWaypoints", e);
} finally {
database.endTransaction();
@@ -1278,14 +1278,14 @@ public class DataStore {
}
private static void saveWaypointsWithoutTransaction(final Geocache cache) {
- String geocode = cache.getGeocode();
+ final String geocode = cache.getGeocode();
- List<Waypoint> waypoints = cache.getWaypoints();
+ final List<Waypoint> waypoints = cache.getWaypoints();
if (CollectionUtils.isNotEmpty(waypoints)) {
final ArrayList<String> currentWaypointIds = new ArrayList<String>();
- ContentValues values = new ContentValues();
- long timeStamp = System.currentTimeMillis();
- for (Waypoint oneWaypoint : waypoints) {
+ final ContentValues values = new ContentValues();
+ final long timeStamp = System.currentTimeMillis();
+ for (final Waypoint oneWaypoint : waypoints) {
values.clear();
values.put("geocode", geocode);
@@ -1356,7 +1356,7 @@ public class DataStore {
return new Geopoint(cursor.getDouble(indexLat), cursor.getDouble(indexLon));
}
- private static boolean saveWaypointInternal(int id, String geocode, Waypoint waypoint) {
+ private static boolean saveWaypointInternal(final int id, final String geocode, final Waypoint waypoint) {
if ((StringUtils.isBlank(geocode) && id <= 0) || waypoint == null) {
return false;
}
@@ -1366,7 +1366,7 @@ public class DataStore {
database.beginTransaction();
boolean ok = false;
try {
- ContentValues values = new ContentValues();
+ final ContentValues values = new ContentValues();
values.put("geocode", geocode);
values.put("updated", System.currentTimeMillis());
values.put("type", waypoint.getWaypointType() != null ? waypoint.getWaypointType().id : null);
@@ -1394,7 +1394,7 @@ public class DataStore {
return ok;
}
- public static boolean deleteWaypoint(int id) {
+ public static boolean deleteWaypoint(final int id) {
if (id == 0) {
return false;
}
@@ -1405,14 +1405,14 @@ public class DataStore {
}
private static void saveSpoilersWithoutTransaction(final Geocache cache) {
- String geocode = cache.getGeocode();
+ final String geocode = cache.getGeocode();
database.delete(dbTableSpoilers, "geocode = ?", new String[]{geocode});
- List<Image> spoilers = cache.getSpoilers();
+ final List<Image> spoilers = cache.getSpoilers();
if (CollectionUtils.isNotEmpty(spoilers)) {
- SQLiteStatement insertSpoiler = PreparedStatements.getInsertSpoiler();
+ final SQLiteStatement insertSpoiler = PreparedStatements.getInsertSpoiler();
final long timestamp = System.currentTimeMillis();
- for (Image spoiler : spoilers) {
+ for (final Image spoiler : spoilers) {
insertSpoiler.bindString(1, geocode);
insertSpoiler.bindLong(2, timestamp);
insertSpoiler.bindString(3, spoiler.getUrl());
@@ -1429,17 +1429,13 @@ public class DataStore {
}
}
- public static void saveLogsWithoutTransaction(final String geocode, final List<LogEntry> logs) {
+ public static void saveLogsWithoutTransaction(final String geocode, final Iterable<LogEntry> logs) {
// TODO delete logimages referring these logs
database.delete(dbTableLogs, "geocode = ?", new String[]{geocode});
- if (logs.isEmpty()) {
- return;
- }
-
- SQLiteStatement insertLog = PreparedStatements.getInsertLog();
+ final SQLiteStatement insertLog = PreparedStatements.getInsertLog();
final long timestamp = System.currentTimeMillis();
- for (LogEntry log : logs) {
+ for (final LogEntry log : logs) {
insertLog.bindString(1, geocode);
insertLog.bindLong(2, timestamp);
insertLog.bindLong(3, log.type.id);
@@ -1448,10 +1444,10 @@ public class DataStore {
insertLog.bindLong(6, log.date);
insertLog.bindLong(7, log.found);
insertLog.bindLong(8, log.friend ? 1 : 0);
- long logId = insertLog.executeInsert();
+ final long logId = insertLog.executeInsert();
if (log.hasLogImages()) {
- SQLiteStatement insertImage = PreparedStatements.getInsertLogImage();
- for (Image img : log.getLogImages()) {
+ final SQLiteStatement insertImage = PreparedStatements.getInsertLogImage();
+ for (final Image img : log.getLogImages()) {
insertImage.bindLong(1, logId);
insertImage.bindString(2, img.getTitle());
insertImage.bindString(3, img.getUrl());
@@ -1462,15 +1458,15 @@ public class DataStore {
}
private static void saveLogCountsWithoutTransaction(final Geocache cache) {
- String geocode = cache.getGeocode();
+ final String geocode = cache.getGeocode();
database.delete(dbTableLogCount, "geocode = ?", new String[]{geocode});
- Map<LogType, Integer> logCounts = cache.getLogCounts();
+ final Map<LogType, Integer> logCounts = cache.getLogCounts();
if (MapUtils.isNotEmpty(logCounts)) {
- Set<Entry<LogType, Integer>> logCountsItems = logCounts.entrySet();
- SQLiteStatement insertLogCounts = PreparedStatements.getInsertLogCounts();
+ final Set<Entry<LogType, Integer>> logCountsItems = logCounts.entrySet();
+ final SQLiteStatement insertLogCounts = PreparedStatements.getInsertLogCounts();
final long timestamp = System.currentTimeMillis();
- for (Entry<LogType, Integer> pair : logCountsItems) {
+ for (final Entry<LogType, Integer> pair : logCountsItems) {
insertLogCounts.bindString(1, geocode);
insertLogCounts.bindLong(2, timestamp);
insertLogCounts.bindLong(3, pair.getKey().id);
@@ -1499,9 +1495,9 @@ public class DataStore {
}
if (CollectionUtils.isNotEmpty(trackables)) {
- ContentValues values = new ContentValues();
- long timeStamp = System.currentTimeMillis();
- for (Trackable trackable : trackables) {
+ final ContentValues values = new ContentValues();
+ final long timeStamp = System.currentTimeMillis();
+ for (final Trackable trackable : trackables) {
final String tbCode = trackable.getGeocode();
if (StringUtils.isNotBlank(tbCode)) {
database.delete(dbTableTrackables, "tbcode = ?", new String[] { tbCode });
@@ -1566,12 +1562,12 @@ public class DataStore {
return new HashSet<Geocache>();
}
- Set<Geocache> result = new HashSet<Geocache>();
- Set<String> remaining = new HashSet<String>(geocodes);
+ final Set<Geocache> result = new HashSet<Geocache>();
+ final Set<String> remaining = new HashSet<String>(geocodes);
if (loadFlags.contains(LoadFlag.LOAD_CACHE_BEFORE)) {
- for (String geocode : new HashSet<String>(remaining)) {
- Geocache cache = cacheCache.getCacheFromCache(geocode);
+ for (final String geocode : new HashSet<String>(remaining)) {
+ final Geocache cache = cacheCache.getCacheFromCache(geocode);
if (cache != null) {
result.add(cache);
remaining.remove(cache.getGeocode());
@@ -1595,8 +1591,8 @@ public class DataStore {
}
if (loadFlags.contains(LoadFlag.LOAD_CACHE_AFTER)) {
- for (String geocode : new HashSet<String>(remaining)) {
- Geocache cache = cacheCache.getCacheFromCache(geocode);
+ for (final String geocode : new HashSet<String>(remaining)) {
+ final Geocache cache = cacheCache.getCacheFromCache(geocode);
if (cache != null) {
result.add(cache);
remaining.remove(cache.getGeocode());
@@ -1638,13 +1634,13 @@ public class DataStore {
query.append(" WHERE ").append(dbTableCaches).append('.');
query.append(DataStore.whereGeocodeIn(geocodes));
- Cursor cursor = database.rawQuery(query.toString(), null);
+ final Cursor cursor = database.rawQuery(query.toString(), null);
try {
final Set<Geocache> caches = new HashSet<Geocache>();
int logIndex = -1;
while (cursor.moveToNext()) {
- Geocache cache = DataStore.createCacheFromDatabaseContent(cursor);
+ final Geocache cache = DataStore.createCacheFromDatabaseContent(cursor);
if (loadFlags.contains(LoadFlag.LOAD_ATTRIBUTES)) {
cache.setAttributes(loadAttributes(cache.getGeocode()));
@@ -1718,8 +1714,8 @@ public class DataStore {
* @param cursor
* @return Cache from DB
*/
- private static Geocache createCacheFromDatabaseContent(Cursor cursor) {
- Geocache cache = new Geocache();
+ private static Geocache createCacheFromDatabaseContent(final Cursor cursor) {
+ final Geocache cache = new Geocache();
cache.setUpdated(cursor.getLong(0));
cache.setListId(cursor.getInt(1));
@@ -1733,7 +1729,7 @@ public class DataStore {
cache.setName(cursor.getString(9));
cache.setOwnerDisplayName(cursor.getString(10));
cache.setOwnerUserId(cursor.getString(11));
- long dateValue = cursor.getLong(12);
+ final long dateValue = cursor.getLong(12);
if (dateValue != 0) {
cache.setHidden(new Date(dateValue));
}
@@ -1779,7 +1775,7 @@ public class DataStore {
return cache;
}
- public static List<String> loadAttributes(String geocode) {
+ public static List<String> loadAttributes(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
@@ -1796,7 +1792,7 @@ public class DataStore {
GET_STRING_0);
}
- public static Waypoint loadWaypoint(int id) {
+ public static Waypoint loadWaypoint(final int id) {
if (id == 0) {
return null;
}
@@ -1915,7 +1911,7 @@ public class DataStore {
database.delete(dbTableSearchDestionationHistory, null, null);
database.setTransactionSuccessful();
return true;
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Unable to clear searched destinations", e);
} finally {
database.endTransaction();
@@ -1929,8 +1925,8 @@ public class DataStore {
* @return an immutable, non null list of logs
*/
@NonNull
- public static List<LogEntry> loadLogs(String geocode) {
- List<LogEntry> logs = new ArrayList<LogEntry>();
+ public static List<LogEntry> loadLogs(final String geocode) {
+ final List<LogEntry> logs = new ArrayList<LogEntry>();
if (StringUtils.isBlank(geocode)) {
return logs;
@@ -1967,7 +1963,7 @@ public class DataStore {
return Collections.unmodifiableList(logs);
}
- public static Map<LogType, Integer> loadLogCounts(String geocode) {
+ public static Map<LogType, Integer> loadLogCounts(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
@@ -1995,7 +1991,7 @@ public class DataStore {
return logCounts;
}
- private static List<Trackable> loadInventory(String geocode) {
+ private static List<Trackable> loadInventory(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
@@ -2056,7 +2052,7 @@ public class DataStore {
final String released = cursor.getString(cursor.getColumnIndex("released"));
if (released != null) {
try {
- long releaseMilliSeconds = Long.parseLong(released);
+ final long releaseMilliSeconds = Long.parseLong(released);
trackable.setReleased(new Date(releaseMilliSeconds));
} catch (final NumberFormatException e) {
Log.e("createTrackableFromDatabaseContent", e);
@@ -2085,7 +2081,7 @@ public class DataStore {
init();
try {
- StringBuilder sql = new StringBuilder("select count(_id) from " + dbTableCaches + " where detailed = 1");
+ final StringBuilder sql = new StringBuilder("select count(_id) from " + dbTableCaches + " where detailed = 1");
String typeKey;
int reasonIndex;
if (cacheType != CacheType.ALL) {
@@ -2106,9 +2102,9 @@ public class DataStore {
listKey = "list";
}
- String key = "CountCaches_" + typeKey + "_" + listKey;
+ final String key = "CountCaches_" + typeKey + "_" + listKey;
- SQLiteStatement compiledStmnt = PreparedStatements.getStatement(key, sql.toString());
+ final SQLiteStatement compiledStmnt = PreparedStatements.getStatement(key, sql.toString());
if (cacheType != CacheType.ALL) {
compiledStmnt.bindString(1, cacheType.id);
}
@@ -2116,7 +2112,7 @@ public class DataStore {
compiledStmnt.bindLong(reasonIndex, list);
}
return (int) compiledStmnt.simpleQueryForLong();
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("DataStore.loadAllStoredCachesCount", e);
}
@@ -2128,7 +2124,7 @@ public class DataStore {
try {
return (int) PreparedStatements.getCountHistoryCaches().simpleQueryForLong();
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("DataStore.getAllHistoricCachesCount", e);
}
@@ -2239,7 +2235,7 @@ public class DataStore {
null,
new HashSet<String>(),
GET_STRING_0);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("DataStore.loadBatchOfHistoricGeocodes", e);
}
@@ -2399,7 +2395,7 @@ public class DataStore {
cacheCache.removeAllFromCache();
}
- public static void removeCache(final String geocode, EnumSet<LoadFlags.RemoveFlag> removeFlags) {
+ public static void removeCache(final String geocode, final EnumSet<LoadFlags.RemoveFlag> removeFlags) {
removeCaches(Collections.singleton(geocode), removeFlags);
}
@@ -2409,7 +2405,7 @@ public class DataStore {
* @param geocodes
* list of geocodes to drop from cache
*/
- public static void removeCaches(final Set<String> geocodes, EnumSet<LoadFlags.RemoveFlag> removeFlags) {
+ public static void removeCaches(final Set<String> geocodes, final EnumSet<LoadFlags.RemoveFlag> removeFlags) {
if (CollectionUtils.isEmpty(geocodes)) {
return;
}
@@ -2457,7 +2453,7 @@ public class DataStore {
}
}
- public static boolean saveLogOffline(String geocode, Date date, LogType type, String log) {
+ public static boolean saveLogOffline(final String geocode, final Date date, final LogType type, final String log) {
if (StringUtils.isBlank(geocode)) {
Log.e("DataStore.saveLogOffline: cannot log a blank geocode");
return false;
@@ -2484,7 +2480,7 @@ public class DataStore {
return id != -1;
}
- public static LogEntry loadLogOffline(String geocode) {
+ public static LogEntry loadLogOffline(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
@@ -2515,7 +2511,7 @@ public class DataStore {
return log;
}
- public static void clearLogOffline(String geocode) {
+ public static void clearLogOffline(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return;
}
@@ -2525,15 +2521,15 @@ public class DataStore {
database.delete(dbTableLogsOffline, "geocode = ?", new String[]{geocode});
}
- public static void clearLogsOffline(List<Geocache> caches) {
+ public static void clearLogsOffline(final List<Geocache> caches) {
if (CollectionUtils.isEmpty(caches)) {
return;
}
init();
- Set<String> geocodes = new HashSet<String>(caches.size());
- for (Geocache cache : caches) {
+ final Set<String> geocodes = new HashSet<String>(caches.size());
+ for (final Geocache cache : caches) {
geocodes.add(cache.getGeocode());
cache.setLogOffline(false);
}
@@ -2553,14 +2549,14 @@ public class DataStore {
logCount.bindString(1, geocode);
return logCount.simpleQueryForLong() > 0;
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("DataStore.hasLogOffline", e);
}
return false;
}
- private static void setVisitDate(List<String> geocodes, long visitedDate) {
+ private static void setVisitDate(final List<String> geocodes, final long visitedDate) {
if (geocodes.isEmpty()) {
return;
}
@@ -2569,9 +2565,9 @@ public class DataStore {
database.beginTransaction();
try {
- SQLiteStatement setVisit = PreparedStatements.getUpdateVisitDate();
+ final SQLiteStatement setVisit = PreparedStatements.getUpdateVisitDate();
- for (String geocode : geocodes) {
+ for (final String geocode : geocodes) {
setVisit.bindLong(1, visitedDate);
setVisit.bindString(2, geocode);
setVisit.execute();
@@ -2617,10 +2613,10 @@ public class DataStore {
});
}
- public static StoredList getList(int id) {
+ public static StoredList getList(final int id) {
init();
if (id >= customListIdOffset) {
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableLists,
new String[]{"_id", "title"},
"_id = ? ",
@@ -2628,13 +2624,13 @@ public class DataStore {
null,
null,
null);
- ArrayList<StoredList> lists = getListsFromCursor(cursor);
+ final ArrayList<StoredList> lists = getListsFromCursor(cursor);
if (!lists.isEmpty()) {
return lists.get(0);
}
}
- Resources res = CgeoApplication.getInstance().getResources();
+ final Resources res = CgeoApplication.getInstance().getResources();
if (id == PseudoList.ALL_LIST.id) {
return new StoredList(PseudoList.ALL_LIST.id, res.getString(R.string.list_all_lists), getAllCachesCount());
}
@@ -2658,7 +2654,7 @@ public class DataStore {
* Name
* @return new listId
*/
- public static int createList(String name) {
+ public static int createList(final String name) {
int id = -1;
if (StringUtils.isBlank(name)) {
return id;
@@ -2668,7 +2664,7 @@ public class DataStore {
database.beginTransaction();
try {
- ContentValues values = new ContentValues();
+ final ContentValues values = new ContentValues();
values.put("title", name);
values.put("updated", System.currentTimeMillis());
@@ -2698,7 +2694,7 @@ public class DataStore {
database.beginTransaction();
int count = 0;
try {
- ContentValues values = new ContentValues();
+ final ContentValues values = new ContentValues();
values.put("title", name);
values.put("updated", System.currentTimeMillis());
@@ -2717,7 +2713,7 @@ public class DataStore {
* @param listId
* @return true if the list got deleted, false else
*/
- public static boolean removeList(int listId) {
+ public static boolean removeList(final int listId) {
if (listId < customListIdOffset) {
return false;
}
@@ -2727,11 +2723,11 @@ public class DataStore {
database.beginTransaction();
boolean status = false;
try {
- int cnt = database.delete(dbTableLists, "_id = " + (listId - customListIdOffset), null);
+ final int cnt = database.delete(dbTableLists, "_id = " + (listId - customListIdOffset), null);
if (cnt > 0) {
// move caches from deleted list to standard list
- SQLiteStatement moveToStandard = PreparedStatements.getMoveToStandardList();
+ final SQLiteStatement moveToStandard = PreparedStatements.getMoveToStandardList();
moveToStandard.bindLong(1, listId);
moveToStandard.execute();
@@ -2763,11 +2759,11 @@ public class DataStore {
}
init();
- SQLiteStatement move = PreparedStatements.getMoveToList();
+ final SQLiteStatement move = PreparedStatements.getMoveToList();
database.beginTransaction();
try {
- for (Geocache cache : caches) {
+ for (final Geocache cache : caches) {
move.bindLong(1, listId);
move.bindString(2, cache.getGeocode());
move.execute();
@@ -2783,7 +2779,7 @@ public class DataStore {
return database != null;
}
- public static boolean removeSearchedDestination(Destination destination) {
+ public static boolean removeSearchedDestination(final Destination destination) {
if (destination == null) {
return false;
}
@@ -2794,7 +2790,7 @@ public class DataStore {
database.delete(dbTableSearchDestionationHistory, "_id = " + destination.getId(), null);
database.setTransactionSuccessful();
return true;
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Unable to remove searched destination", e);
} finally {
database.endTransaction();
@@ -2839,9 +2835,9 @@ public class DataStore {
}
cursor.close();
- } catch (SQLiteDoneException e) {
+ } catch (final SQLiteDoneException e) {
// Do nothing, it only means we have no information on the cache
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("DataStore.getCacheDescription", e);
}
@@ -2888,13 +2884,14 @@ public class DataStore {
* @return
*/
- public static Set<Waypoint> loadWaypoints(final Viewport viewport, boolean excludeMine, boolean excludeDisabled, CacheType type) {
+ public static Set<Waypoint> loadWaypoints(final Viewport viewport, final boolean excludeMine, final boolean excludeDisabled, final CacheType type) {
final StringBuilder where = buildCoordinateWhere(dbTableWaypoints, viewport);
if (excludeMine) {
where.append(" and ").append(dbTableCaches).append(".found == 0");
}
if (excludeDisabled) {
where.append(" and ").append(dbTableCaches).append(".disabled == 0");
+ where.append(" and ").append(dbTableCaches).append(".archived == 0");
}
if (type != CacheType.ALL) {
where.append(" and ").append(dbTableCaches).append(".type == '").append(type.id).append('\'');
@@ -2916,7 +2913,7 @@ public class DataStore {
});
}
- public static void saveChangedCache(Geocache cache) {
+ public static void saveChangedCache(final Geocache cache) {
DataStore.saveCache(cache, cache.getStorageLocation().contains(StorageLocation.DATABASE) ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.SAVE_CACHE));
}
@@ -2948,7 +2945,7 @@ public class DataStore {
return getStatement("InsertSpoiler", "INSERT INTO " + dbTableSpoilers + " (geocode, updated, url, title, description) VALUES (?, ?, ?, ?, ?)");
}
- public static SQLiteStatement getInsertSearchDestination(Destination destination) {
+ public static SQLiteStatement getInsertSearchDestination(final Destination destination) {
final SQLiteStatement statement = getStatement("InsertSearch", "INSERT INTO " + dbTableSearchDestionationHistory + " (date, latitude, longitude) VALUES (?, ?, ?)");
statement.bindLong(1, destination.getDate());
final Geopoint coords = destination.getCoords();
@@ -2958,7 +2955,7 @@ public class DataStore {
}
private static void clearPreparedStatements() {
- for (SQLiteStatement statement : statements.values()) {
+ for (final SQLiteStatement statement : statements.values()) {
statement.close();
}
statements.clear();
@@ -3020,11 +3017,11 @@ public class DataStore {
setVisitDate(Collections.singletonList(geocode), System.currentTimeMillis());
}
- public static void markDropped(List<Geocache> caches) {
+ public static void markDropped(final List<Geocache> caches) {
moveToList(caches, StoredList.TEMPORARY_LIST_ID);
}
- public static Viewport getBounds(String geocode) {
+ public static Viewport getBounds(final String geocode) {
if (geocode == null) {
return null;
}
@@ -3032,21 +3029,21 @@ public class DataStore {
return DataStore.getBounds(Collections.singleton(geocode));
}
- public static void clearVisitDate(String[] selected) {
+ public static void clearVisitDate(final String[] selected) {
setVisitDate(Arrays.asList(selected), 0);
}
- public static SearchResult getBatchOfStoredCaches(Geopoint coords, CacheType cacheType, int listId) {
+ public static SearchResult getBatchOfStoredCaches(final Geopoint coords, final CacheType cacheType, final int listId) {
final Set<String> geocodes = DataStore.loadBatchOfStoredGeocodes(coords, cacheType, listId);
return new SearchResult(geocodes, DataStore.getAllStoredCachesCount(cacheType, listId));
}
- public static SearchResult getHistoryOfCaches(boolean detailedOnly, CacheType cacheType) {
+ public static SearchResult getHistoryOfCaches(final boolean detailedOnly, final CacheType cacheType) {
final Set<String> geocodes = DataStore.loadBatchOfHistoricGeocodes(detailedOnly, cacheType);
return new SearchResult(geocodes, DataStore.getAllHistoryCachesCount());
}
- public static boolean saveWaypoint(int id, String geocode, Waypoint waypoint) {
+ public static boolean saveWaypoint(final int id, final String geocode, final Waypoint waypoint) {
if (DataStore.saveWaypointInternal(id, geocode, waypoint)) {
DataStore.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
return true;
@@ -3090,13 +3087,7 @@ public class DataStore {
return null;
}
init();
- final MatrixCursor resultCursor = new MatrixCursor(new String[] {
- BaseColumns._ID,
- SearchManager.SUGGEST_COLUMN_TEXT_1,
- SearchManager.SUGGEST_COLUMN_TEXT_2,
- SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
- SearchManager.SUGGEST_COLUMN_QUERY
- });
+ final SearchSuggestionCursor resultCursor = new SearchSuggestionCursor();
try {
final String selectionArg = getSuggestionArgument(searchTerm);
findCaches(resultCursor, selectionArg);
@@ -3107,10 +3098,10 @@ public class DataStore {
return resultCursor;
}
- private static void findCaches(final MatrixCursor resultCursor, final String selectionArg) {
- Cursor cursor = database.query(
+ private static void findCaches(final SearchSuggestionCursor resultCursor, final String selectionArg) {
+ final Cursor cursor = database.query(
dbTableCaches,
- new String[] { "geocode", "name" },
+ new String[] { "geocode", "name", "type" },
"geocode IS NOT NULL AND geocode != '' AND (geocode LIKE ? OR name LIKE ? OR owner LIKE ?)",
new String[] { selectionArg, selectionArg, selectionArg },
null,
@@ -3118,23 +3109,19 @@ public class DataStore {
"name");
while (cursor.moveToNext()) {
final String geocode = cursor.getString(0);
- resultCursor.addRow(new String[] {
- String.valueOf(resultCursor.getCount()),
- cursor.getString(1),
- geocode,
- Intents.ACTION_GEOCACHE,
- geocode
- });
+ final String cacheName = cursor.getString(1);
+ final String type = cursor.getString(2);
+ resultCursor.addCache(geocode, cacheName, type);
}
cursor.close();
}
- private static String getSuggestionArgument(String input) {
+ private static String getSuggestionArgument(final String input) {
return "%" + StringUtils.trim(input) + "%";
}
private static void findTrackables(final MatrixCursor resultCursor, final String selectionArg) {
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableTrackables,
new String[] { "tbcode", "title" },
"tbcode IS NOT NULL AND tbcode != '' AND (tbcode LIKE ? OR title LIKE ?)",
@@ -3156,31 +3143,53 @@ public class DataStore {
}
public static String[] getSuggestions(final String table, final String column, final String input) {
- Cursor cursor = database.rawQuery("SELECT DISTINCT " + column
+ final Cursor cursor = database.rawQuery("SELECT DISTINCT " + column
+ " FROM " + table
+ " WHERE " + column + " LIKE ?"
+ " ORDER BY " + column + " COLLATE NOCASE ASC;", new String[] { getSuggestionArgument(input) });
return cursorToColl(cursor, new LinkedList<String>(), GET_STRING_0).toArray(new String[cursor.getCount()]);
}
- public static String[] getSuggestionsOwnerName(String input) {
- return getSuggestions(dbTableCaches, "owner", input);
+ public static String[] getSuggestionsOwnerName(final String input) {
+ return getSuggestions(dbTableCaches, "owner_real", input);
}
- public static String[] getSuggestionsTrackableCode(String input) {
+ public static String[] getSuggestionsTrackableCode(final String input) {
return getSuggestions(dbTableTrackables, "tbcode", input);
}
- public static String[] getSuggestionsFinderName(String input) {
+ public static String[] getSuggestionsFinderName(final String input) {
return getSuggestions(dbTableLogs, "author", input);
}
- public static String[] getSuggestionsGeocode(String input) {
+ public static String[] getSuggestionsGeocode(final String input) {
return getSuggestions(dbTableCaches, "geocode", input);
}
- public static String[] getSuggestionsKeyword(String input) {
+ public static String[] getSuggestionsKeyword(final String input) {
return getSuggestions(dbTableCaches, "name", input);
}
+ /**
+ *
+ * @return list of last caches opened in the details view, ordered by most recent first
+ */
+ public static ArrayList<Geocache> getLastOpenedCaches() {
+ final List<String> geocodes = Settings.getLastOpenedCaches();
+ final Set<Geocache> cachesSet = DataStore.loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB);
+
+ // order result set by time again
+ final ArrayList<Geocache> caches = new ArrayList<Geocache>(cachesSet);
+ Collections.sort(caches, new Comparator<Geocache>() {
+
+ @Override
+ public int compare(final Geocache lhs, final Geocache rhs) {
+ final int lhsIndex = geocodes.indexOf(lhs.getGeocode());
+ final int rhsIndex = geocodes.indexOf(rhs.getGeocode());
+ return lhsIndex < rhsIndex ? -1 : (lhsIndex == rhsIndex ? 0 : 1);
+ }
+ });
+ return caches;
+ }
+
}
diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java
index 55de0a6..0eeb0d7 100644
--- a/main/src/cgeo/geocaching/EditWaypointActivity.java
+++ b/main/src/cgeo/geocaching/EditWaypointActivity.java
@@ -1,6 +1,6 @@
package cgeo.geocaching;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.enumerations.CacheType;
@@ -48,7 +48,7 @@ import java.util.EnumSet;
import java.util.List;
@EActivity
-public class EditWaypointActivity extends AbstractActivity {
+public class EditWaypointActivity extends AbstractActionBarActivity implements CoordinatesInputDialog.CoordinateUpdate {
private static final ArrayList<WaypointType> POSSIBLE_WAYPOINT_TYPES = new ArrayList<WaypointType>(WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL);
@ViewById(R.id.buttonLatitude) protected Button buttonLat;
@@ -294,17 +294,18 @@ public class EditWaypointActivity extends AbstractActivity {
// button text is blank when creating new waypoint
}
Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
- CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(EditWaypointActivity.this, cache, gp, app.currentGeo());
+ CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(cache, gp, app.currentGeo());
coordsDialog.setCancelable(true);
- coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
- @Override
- public void update(final Geopoint gp) {
- buttonLat.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
- buttonLon.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
- }
- });
- coordsDialog.show();
+ coordsDialog.show(getSupportFragmentManager(),"wpeditdialog");
}
+
+
+ }
+
+ @Override
+ public void updateCoordinates(Geopoint gp) {
+ buttonLat.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
+ buttonLon.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
}
public static final int SUCCESS = 0;
@@ -442,7 +443,7 @@ public class EditWaypointActivity extends AbstractActivity {
if (!StaticMapsProvider.hasAllStaticMapsForWaypoint(geocode, waypoint)) {
StaticMapsProvider.removeWpStaticMaps(oldWaypoint, geocode);
if (Settings.isStoreOfflineWpMaps()) {
- StaticMapsProvider.storeWaypointStaticMap(cache, waypoint, false);
+ StaticMapsProvider.storeWaypointStaticMap(cache, waypoint).subscribe();
}
}
if (modifyLocal.isChecked() || modifyBoth.isChecked()) {
diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java
index 19c15fd..f3ff487 100644
--- a/main/src/cgeo/geocaching/Geocache.java
+++ b/main/src/cgeo/geocaching/Geocache.java
@@ -2,6 +2,7 @@ package cgeo.geocaching;
import cgeo.geocaching.DataStore.StorageLocation;
import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.activity.SimpleWebviewActivity;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.connector.ILoggingManager;
@@ -32,6 +33,7 @@ import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.LogTemplateProvider;
import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
import cgeo.geocaching.utils.MatcherWrapper;
+import cgeo.geocaching.utils.RxUtils;
import cgeo.geocaching.utils.UncertainProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -46,9 +48,8 @@ import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import rx.Scheduler;
-import rx.Scheduler.Inner;
import rx.Subscription;
-import rx.functions.Action1;
+import rx.functions.Action0;
import android.app.Activity;
import android.content.Intent;
@@ -58,6 +59,7 @@ import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
+import android.os.Parcelable;
import android.text.Html;
import android.text.Html.ImageGetter;
@@ -80,10 +82,6 @@ import java.util.regex.Pattern;
/**
* Internal c:geo representation of a "cache"
*/
-/**
- * @author kep9fe
- *
- */
public class Geocache implements ICache, IWaypoint {
private static final int OWN_WP_PREFIX_OFFSET = 17;
@@ -160,7 +158,6 @@ public class Geocache implements ICache, IWaypoint {
private final EnumSet<StorageLocation> storageLocation = EnumSet.of(StorageLocation.HEAP);
private boolean finalDefined = false;
private boolean logPasswordRequired = false;
- // private int zoomlevel = Tile.ZOOMLEVEL_MIN - 1;
private static final Pattern NUMBER_PATTERN = Pattern.compile("\\d+");
@@ -183,13 +180,13 @@ public class Geocache implements ICache, IWaypoint {
*
* @param gpxParser
*/
- public Geocache(GPXParser gpxParser) {
+ public Geocache(final GPXParser gpxParser) {
setReliableLatLon(true);
setAttributes(Collections.<String> emptyList());
setWaypoints(Collections.<Waypoint> emptyList(), false);
}
- public void setChangeNotificationHandler(Handler newNotificationHandler) {
+ public void setChangeNotificationHandler(final Handler newNotificationHandler) {
changeNotificationHandler = newNotificationHandler;
}
@@ -471,7 +468,7 @@ public class Geocache implements ICache, IWaypoint {
logOffline(fromActivity, initial, Calendar.getInstance(), logType);
}
- void logOffline(final Activity fromActivity, final String log, Calendar date, final LogType logType) {
+ void logOffline(final Activity fromActivity, final String log, final Calendar date, final LogType logType) {
if (logType == LogType.UNKNOWN) {
return;
}
@@ -498,18 +495,30 @@ public class Geocache implements ICache, IWaypoint {
return getConnector().getPossibleLogTypes(this);
}
- public void openInBrowser(Activity fromActivity) {
- fromActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getBrowserCacheUrl())));
+ public void openInBrowser(final Activity fromActivity) {
+ final Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getUrl()));
+
+ // Check if cgeo is the default, show the chooser to let the user choose a browser
+ if (viewIntent.resolveActivity(fromActivity.getPackageManager()).getPackageName().equals(fromActivity.getPackageName())) {
+ final Intent chooser = Intent.createChooser(viewIntent, fromActivity.getString(R.string.cache_menu_browser));
+
+ final Intent internalBrowser = new Intent(fromActivity, SimpleWebviewActivity.class);
+ internalBrowser.setData(Uri.parse(getUrl()));
+
+ chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[] {internalBrowser});
+
+
+ fromActivity.startActivity(chooser);
+ } else {
+ fromActivity.startActivity(viewIntent);
+ }
}
+
private String getCacheUrl() {
return getConnector().getCacheUrl(this);
}
- private String getBrowserCacheUrl() {
- return getConnector().getLongCacheUrl(this);
- }
-
private IConnector getConnector() {
return ConnectorFactory.getConnector(this);
}
@@ -589,7 +598,7 @@ public class Geocache implements ICache, IWaypoint {
return BooleanUtils.isTrue(premiumMembersOnly);
}
- public void setPremiumMembersOnly(boolean members) {
+ public void setPremiumMembersOnly(final boolean members) {
this.premiumMembersOnly = members;
}
@@ -704,11 +713,16 @@ public class Geocache implements ICache, IWaypoint {
return getConnector() instanceof ISearchByCenter;
}
- public void shareCache(Activity fromActivity, Resources res) {
+ public void shareCache(final Activity fromActivity, final Resources res) {
if (geocode == null) {
return;
}
+ final Intent intent = getShareIntent();
+
+ fromActivity.startActivity(Intent.createChooser(intent, res.getText(R.string.cache_menu_share)));
+ }
+ public Intent getShareIntent() {
final StringBuilder subject = new StringBuilder("Geocache ");
subject.append(geocode);
if (StringUtils.isNotBlank(name)) {
@@ -720,13 +734,15 @@ public class Geocache implements ICache, IWaypoint {
intent.putExtra(Intent.EXTRA_SUBJECT, subject.toString());
intent.putExtra(Intent.EXTRA_TEXT, getUrl());
- fromActivity.startActivity(Intent.createChooser(intent, res.getText(R.string.action_bar_share_title)));
+ return intent;
}
public String getUrl() {
return getConnector().getCacheUrl(this);
}
+ public String getCgeoUrl() { return getConnector().getCacheUrl(this); }
+
public boolean supportsGCVote() {
return StringUtils.startsWithIgnoreCase(geocode, "GC");
}
@@ -745,7 +761,7 @@ public class Geocache implements ICache, IWaypoint {
return BooleanUtils.isTrue(favorite);
}
- public void setFavorite(boolean favorite) {
+ public void setFavorite(final boolean favorite) {
this.favorite = favorite;
}
@@ -816,7 +832,7 @@ public class Geocache implements ICache, IWaypoint {
return updated;
}
- public void setUpdated(long updated) {
+ public void setUpdated(final long updated) {
this.updated = updated;
}
@@ -824,7 +840,7 @@ public class Geocache implements ICache, IWaypoint {
return detailedUpdate;
}
- public void setDetailedUpdate(long detailedUpdate) {
+ public void setDetailedUpdate(final long detailedUpdate) {
this.detailedUpdate = detailedUpdate;
}
@@ -832,7 +848,7 @@ public class Geocache implements ICache, IWaypoint {
return visitedDate;
}
- public void setVisitedDate(long visitedDate) {
+ public void setVisitedDate(final long visitedDate) {
this.visitedDate = visitedDate;
}
@@ -840,7 +856,7 @@ public class Geocache implements ICache, IWaypoint {
return listId;
}
- public void setListId(int listId) {
+ public void setListId(final int listId) {
this.listId = listId;
}
@@ -848,7 +864,7 @@ public class Geocache implements ICache, IWaypoint {
return detailed;
}
- public void setDetailed(boolean detailed) {
+ public void setDetailed(final boolean detailed) {
this.detailed = detailed;
}
@@ -865,7 +881,7 @@ public class Geocache implements ICache, IWaypoint {
return direction;
}
- public void setDirection(Float direction) {
+ public void setDirection(final Float direction) {
this.direction = direction;
}
@@ -873,7 +889,7 @@ public class Geocache implements ICache, IWaypoint {
return distance;
}
- public void setDistance(Float distance) {
+ public void setDistance(final Float distance) {
this.distance = distance;
}
@@ -891,7 +907,7 @@ public class Geocache implements ICache, IWaypoint {
*
* @param coords
*/
- public void setCoords(Geopoint coords) {
+ public void setCoords(final Geopoint coords) {
this.coords = new UncertainProperty<Geopoint>(coords);
}
@@ -901,7 +917,7 @@ public class Geocache implements ICache, IWaypoint {
* @param coords
* @param zoomlevel
*/
- public void setCoords(Geopoint coords, int zoomlevel) {
+ public void setCoords(final Geopoint coords, final int zoomlevel) {
this.coords = new UncertainProperty<Geopoint>(coords, zoomlevel);
}
@@ -912,15 +928,15 @@ public class Geocache implements ICache, IWaypoint {
return getConnector().isReliableLatLon(reliableLatLon);
}
- public void setReliableLatLon(boolean reliableLatLon) {
+ public void setReliableLatLon(final boolean reliableLatLon) {
this.reliableLatLon = reliableLatLon;
}
- public void setShortDescription(String shortdesc) {
+ public void setShortDescription(final String shortdesc) {
this.shortdesc = shortdesc;
}
- public void setFavoritePoints(int favoriteCnt) {
+ public void setFavoritePoints(final int favoriteCnt) {
this.favoritePoints = favoriteCnt;
}
@@ -928,7 +944,7 @@ public class Geocache implements ICache, IWaypoint {
return rating;
}
- public void setRating(float rating) {
+ public void setRating(final float rating) {
this.rating = rating;
}
@@ -936,7 +952,7 @@ public class Geocache implements ICache, IWaypoint {
return votes;
}
- public void setVotes(int votes) {
+ public void setVotes(final int votes) {
this.votes = votes;
}
@@ -944,7 +960,7 @@ public class Geocache implements ICache, IWaypoint {
return myVote;
}
- public void setMyVote(float myVote) {
+ public void setMyVote(final float myVote) {
this.myVote = myVote;
}
@@ -952,7 +968,7 @@ public class Geocache implements ICache, IWaypoint {
return inventoryItems;
}
- public void setInventoryItems(int inventoryItems) {
+ public void setInventoryItems(final int inventoryItems) {
this.inventoryItems = inventoryItems;
}
@@ -961,7 +977,7 @@ public class Geocache implements ICache, IWaypoint {
return BooleanUtils.isTrue(onWatchlist);
}
- public void setOnWatchlist(boolean onWatchlist) {
+ public void setOnWatchlist(final boolean onWatchlist) {
this.onWatchlist = onWatchlist;
}
@@ -982,7 +998,7 @@ public class Geocache implements ICache, IWaypoint {
* called while loading or building a cache
* @return <code>true</code> if waypoints successfully added to waypoint database
*/
- public boolean setWaypoints(List<Waypoint> waypoints, boolean saveToDatabase) {
+ public boolean setWaypoints(final List<Waypoint> waypoints, final boolean saveToDatabase) {
this.waypoints.clear();
if (waypoints != null) {
this.waypoints.addAll(waypoints);
@@ -1029,7 +1045,7 @@ public class Geocache implements ICache, IWaypoint {
return BooleanUtils.isTrue(logOffline);
}
- public void setLogOffline(boolean logOffline) {
+ public void setLogOffline(final boolean logOffline) {
this.logOffline = logOffline;
}
@@ -1037,7 +1053,7 @@ public class Geocache implements ICache, IWaypoint {
return statusChecked;
}
- public void setStatusChecked(boolean statusChecked) {
+ public void setStatusChecked(final boolean statusChecked) {
this.statusChecked = statusChecked;
}
@@ -1045,39 +1061,39 @@ public class Geocache implements ICache, IWaypoint {
return directionImg;
}
- public void setDirectionImg(String directionImg) {
+ public void setDirectionImg(final String directionImg) {
this.directionImg = directionImg;
}
- public void setGeocode(String geocode) {
+ public void setGeocode(final String geocode) {
this.geocode = StringUtils.upperCase(geocode);
}
- public void setCacheId(String cacheId) {
+ public void setCacheId(final String cacheId) {
this.cacheId = cacheId;
}
- public void setGuid(String guid) {
+ public void setGuid(final String guid) {
this.guid = guid;
}
- public void setName(String name) {
+ public void setName(final String name) {
this.name = name;
}
- public void setOwnerDisplayName(String ownerDisplayName) {
+ public void setOwnerDisplayName(final String ownerDisplayName) {
this.ownerDisplayName = ownerDisplayName;
}
- public void setOwnerUserId(String ownerUserId) {
+ public void setOwnerUserId(final String ownerUserId) {
this.ownerUserId = ownerUserId;
}
- public void setHint(String hint) {
+ public void setHint(final String hint) {
this.hint = hint;
}
- public void setSize(CacheSize size) {
+ public void setSize(final CacheSize size) {
if (size == null) {
this.size = CacheSize.UNKNOWN;
}
@@ -1086,50 +1102,50 @@ public class Geocache implements ICache, IWaypoint {
}
}
- public void setDifficulty(float difficulty) {
+ public void setDifficulty(final float difficulty) {
this.difficulty = difficulty;
}
- public void setTerrain(float terrain) {
+ public void setTerrain(final float terrain) {
this.terrain = terrain;
}
- public void setLocation(String location) {
+ public void setLocation(final String location) {
this.location = location;
}
- public void setPersonalNote(String personalNote) {
+ public void setPersonalNote(final String personalNote) {
this.personalNote = StringUtils.trimToNull(personalNote);
}
- public void setDisabled(boolean disabled) {
+ public void setDisabled(final boolean disabled) {
this.disabled = disabled;
}
- public void setArchived(boolean archived) {
+ public void setArchived(final boolean archived) {
this.archived = archived;
}
- public void setFound(boolean found) {
+ public void setFound(final boolean found) {
this.found = found;
}
- public void setAttributes(List<String> attributes) {
+ public void setAttributes(final List<String> attributes) {
this.attributes.clear();
if (attributes != null) {
this.attributes.addAll(attributes);
}
}
- public void setSpoilers(List<Image> spoilers) {
+ public void setSpoilers(final List<Image> spoilers) {
this.spoilers = spoilers;
}
- public void setInventory(List<Trackable> inventory) {
+ public void setInventory(final List<Trackable> inventory) {
this.inventory = inventory;
}
- public void setLogCounts(Map<LogType, Integer> logCounts) {
+ public void setLogCounts(final Map<LogType, Integer> logCounts) {
this.logCounts = logCounts;
}
@@ -1145,14 +1161,14 @@ public class Geocache implements ICache, IWaypoint {
return cacheType.getValue();
}
- public void setType(CacheType cacheType) {
+ public void setType(final CacheType cacheType) {
if (cacheType == null || CacheType.ALL == cacheType) {
throw new IllegalArgumentException("Illegal cache type");
}
this.cacheType = new UncertainProperty<CacheType>(cacheType);
}
- public void setType(CacheType cacheType, final int zoomlevel) {
+ public void setType(final CacheType cacheType, final int zoomlevel) {
if (cacheType == null || CacheType.ALL == cacheType) {
throw new IllegalArgumentException("Illegal cache type");
}
@@ -1190,7 +1206,7 @@ public class Geocache implements ICache, IWaypoint {
* called while loading or building a cache
* @return <code>true</code> if waypoint successfully added to waypoint database
*/
- public boolean addOrChangeWaypoint(final Waypoint waypoint, boolean saveToDatabase) {
+ public boolean addOrChangeWaypoint(final Waypoint waypoint, final boolean saveToDatabase) {
waypoint.setGeocode(geocode);
if (waypoint.getId() < 0) { // this is a new waypoint
@@ -1202,7 +1218,7 @@ public class Geocache implements ICache, IWaypoint {
} else { // this is a waypoint being edited
final int index = getWaypointIndex(waypoint);
if (index >= 0) {
- Waypoint oldWaypoint = waypoints.remove(index);
+ final Waypoint oldWaypoint = waypoints.remove(index);
waypoint.setPrefix(oldWaypoint.getPrefix());
//migration
if (StringUtils.isBlank(waypoint.getPrefix())
@@ -1221,15 +1237,15 @@ public class Geocache implements ICache, IWaypoint {
* Assigns a unique two-digit (compatibility with gc.com)
* prefix within the scope of this cache.
*/
- private void assignUniquePrefix(Waypoint waypoint) {
+ private void assignUniquePrefix(final Waypoint waypoint) {
// gather existing prefixes
- Set<String> assignedPrefixes = new HashSet<String>();
- for (Waypoint wp : waypoints) {
+ final Set<String> assignedPrefixes = new HashSet<String>();
+ for (final Waypoint wp : waypoints) {
assignedPrefixes.add(wp.getPrefix());
}
for (int i = OWN_WP_PREFIX_OFFSET; i < 100; i++) {
- String prefixCandidate = StringUtils.leftPad(String.valueOf(i), 2, '0');
+ final String prefixCandidate = StringUtils.leftPad(String.valueOf(i), 2, '0');
if (!assignedPrefixes.contains(prefixCandidate)) {
waypoint.setPrefix(prefixCandidate);
break;
@@ -1247,7 +1263,7 @@ public class Geocache implements ICache, IWaypoint {
}
// Only for loading
- public void setFinalDefined(boolean finalDefined) {
+ public void setFinalDefined(final boolean finalDefined) {
this.finalDefined = finalDefined;
}
@@ -1268,7 +1284,7 @@ public class Geocache implements ICache, IWaypoint {
return userModifiedCoords;
}
- public void setUserModifiedCoords(boolean coordsChanged) {
+ public void setUserModifiedCoords(final boolean coordsChanged) {
userModifiedCoords = coordsChanged;
}
@@ -1325,7 +1341,7 @@ public class Geocache implements ICache, IWaypoint {
* @param waypoint
*/
- public void deleteWaypointForce(Waypoint waypoint) {
+ public void deleteWaypointForce(final Waypoint waypoint) {
final int index = getWaypointIndex(waypoint);
waypoints.remove(index);
DataStore.deleteWaypoint(waypoint.getId());
@@ -1405,17 +1421,17 @@ public class Geocache implements ICache, IWaypoint {
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
// TODO: explain the following line or remove this non-standard equality method
// just compare the geocode even if that is not what "equals" normally does
return this == obj || (obj instanceof Geocache && StringUtils.isNotEmpty(geocode) && geocode.equals(((Geocache) obj).geocode));
}
- public void store(CancellableHandler handler) {
+ public void store(final CancellableHandler handler) {
store(StoredList.TEMPORARY_LIST_ID, handler);
}
- public void store(final int listId, CancellableHandler handler) {
+ public void store(final int listId, final CancellableHandler handler) {
final int newListId = listId < StoredList.STANDARD_LIST_ID
? Math.max(getListId(), StoredList.STANDARD_LIST_ID)
: listId;
@@ -1438,9 +1454,9 @@ public class Geocache implements ICache, IWaypoint {
}
public Subscription drop(final Handler handler, final Scheduler scheduler) {
- return scheduler.schedule(new Action1<Inner>() {
+ return scheduler.createWorker().schedule(new Action0() {
@Override
- public void call(final Inner inner) {
+ public void call() {
try {
dropSynchronous();
handler.sendMessage(Message.obtain());
@@ -1498,22 +1514,22 @@ public class Geocache implements ICache, IWaypoint {
}
}
- public Subscription refresh(final int newListId, final CancellableHandler handler, final Scheduler scheduler) {
- return scheduler.schedule(new Action1<Inner>() {
+ public Subscription refresh(final CancellableHandler handler, final Scheduler scheduler) {
+ return scheduler.createWorker().schedule(new Action0() {
@Override
- public void call(final Inner inner) {
- refreshSynchronous(newListId, handler);
+ public void call() {
+ refreshSynchronous(handler);
handler.sendEmptyMessage(CancellableHandler.DONE);
}
});
}
- public void refreshSynchronous(final int newListId, final CancellableHandler handler) {
+ public void refreshSynchronous(final CancellableHandler handler) {
DataStore.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
- storeCache(null, geocode, newListId, true, handler);
+ storeCache(null, geocode, listId, true, handler);
}
- public static void storeCache(Geocache origCache, String geocode, int listId, boolean forceRedownload, CancellableHandler handler) {
+ public static void storeCache(final Geocache origCache, final String geocode, final int listId, final boolean forceRedownload, final CancellableHandler handler) {
try {
Geocache cache = null;
// get cache details, they may not yet be complete
@@ -1591,9 +1607,7 @@ public class Geocache implements ICache, IWaypoint {
return;
}
- StaticMapsProvider.downloadMaps(cache);
-
- imgGetter.waitForBackgroundLoading(handler);
+ RxUtils.waitForCompletion(StaticMapsProvider.downloadMaps(cache), imgGetter.waitForEndObservable(handler));
if (handler != null) {
handler.sendMessage(Message.obtain());
@@ -1643,7 +1657,7 @@ public class Geocache implements ICache, IWaypoint {
}
final String hourLocalized = CgeoApplication.getInstance().getString(R.string.cache_time_full_hours);
- ArrayList<Pattern> patterns = new ArrayList<Pattern>();
+ final ArrayList<Pattern> patterns = new ArrayList<Pattern>();
// 12:34
patterns.add(Pattern.compile("\\b(\\d{1,2})\\:(\\d\\d)\\b"));
@@ -1655,7 +1669,7 @@ public class Geocache implements ICache, IWaypoint {
}
final String searchText = getShortDescription() + ' ' + getDescription();
- for (Pattern pattern : patterns) {
+ for (final Pattern pattern : patterns) {
final MatcherWrapper matcher = new MatcherWrapper(pattern, searchText);
while (matcher.find()) {
try {
@@ -1683,7 +1697,7 @@ public class Geocache implements ICache, IWaypoint {
* true if we are looking for the attribute_yes version, false for the attribute_no version
* @return
*/
- public boolean hasAttribute(CacheAttribute attribute, boolean yes) {
+ public boolean hasAttribute(final CacheAttribute attribute, final boolean yes) {
Geocache fullCache = DataStore.loadCache(getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES));
if (fullCache == null) {
fullCache = this;
@@ -1762,7 +1776,7 @@ public class Geocache implements ICache, IWaypoint {
* Gets whether the user has logged the specific log type for this cache. Only checks the currently stored logs of
* the cache, so the result might be wrong.
*/
- public boolean hasOwnLog(LogType logType) {
+ public boolean hasOwnLog(final LogType logType) {
for (final LogEntry logEntry : getLogs()) {
if (logEntry.type == logType && logEntry.isOwn()) {
return true;
@@ -1779,15 +1793,15 @@ public class Geocache implements ICache, IWaypoint {
return logPasswordRequired;
}
- public void setLogPasswordRequired(boolean required) {
+ public void setLogPasswordRequired(final boolean required) {
logPasswordRequired = required;
}
- public String getWaypointGpxId(String prefix) {
+ public String getWaypointGpxId(final String prefix) {
return getConnector().getWaypointGpxId(prefix, geocode);
}
- public String getWaypointPrefix(String name) {
+ public String getWaypointPrefix(final String name) {
return getConnector().getWaypointPrefix(name);
}
@@ -1800,7 +1814,7 @@ public class Geocache implements ICache, IWaypoint {
if (getLogCounts().isEmpty()) {
setLogCounts(DataStore.loadLogCounts(getGeocode()));
}
- Integer logged = getLogCounts().get(LogType.FOUND_IT);
+ final Integer logged = getLogCounts().get(LogType.FOUND_IT);
if (logged != null) {
return logged;
}
@@ -1814,7 +1828,7 @@ public class Geocache implements ICache, IWaypoint {
public LogType getDefaultLogType() {
if (isEventCache()) {
final Date eventDate = getHiddenDate();
- boolean expired = DateUtils.isPastEvent(this);
+ final boolean expired = DateUtils.isPastEvent(this);
if (hasOwnLog(LogType.WILL_ATTEND) || expired || (eventDate != null && DateUtils.daysSince(eventDate.getTime()) == 0)) {
return hasOwnLog(LogType.ATTENDED) ? LogType.NOTE : LogType.ATTENDED;
diff --git a/main/src/cgeo/geocaching/ImageSelectActivity.java b/main/src/cgeo/geocaching/ImageSelectActivity.java
index b5fb38e..a64b4cf 100644
--- a/main/src/cgeo/geocaching/ImageSelectActivity.java
+++ b/main/src/cgeo/geocaching/ImageSelectActivity.java
@@ -3,7 +3,7 @@ package cgeo.geocaching;
import butterknife.ButterKnife;
import butterknife.InjectView;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.files.LocalStorage;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.Dialogs;
@@ -37,7 +37,7 @@ import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
-public class ImageSelectActivity extends AbstractActivity {
+public class ImageSelectActivity extends AbstractActionBarActivity {
@InjectView(R.id.caption) protected EditText captionView;
@InjectView(R.id.description) protected EditText descriptionView;
diff --git a/main/src/cgeo/geocaching/ImagesActivity.java b/main/src/cgeo/geocaching/ImagesActivity.java
index 3da1ade..bc2616b 100644
--- a/main/src/cgeo/geocaching/ImagesActivity.java
+++ b/main/src/cgeo/geocaching/ImagesActivity.java
@@ -1,6 +1,6 @@
package cgeo.geocaching;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.ImagesList;
import cgeo.geocaching.ui.ImagesList.ImageType;
@@ -19,7 +19,7 @@ import android.view.View;
import java.util.ArrayList;
import java.util.List;
-public class ImagesActivity extends AbstractActivity {
+public class ImagesActivity extends AbstractActionBarActivity {
private boolean offline;
private ArrayList<Image> imageNames;
diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java
index 2b05263..25906de 100644
--- a/main/src/cgeo/geocaching/LogCacheActivity.java
+++ b/main/src/cgeo/geocaching/LogCacheActivity.java
@@ -25,7 +25,6 @@ import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
-import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
@@ -35,12 +34,13 @@ import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.SubMenu;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
+import android.widget.RatingBar;
+import android.widget.RatingBar.OnRatingBarChangeListener;
import android.widget.TextView;
import java.util.ArrayList;
@@ -52,7 +52,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
static final String EXTRAS_GEOCODE = "geocode";
static final String EXTRAS_ID = "id";
- private static final int SUBMENU_VOTE = 3;
private static final String SAVED_STATE_RATING = "cgeo.geocaching.saved_state_rating";
private static final String SAVED_STATE_TYPE = "cgeo.geocaching.saved_state_type";
private static final String SAVED_STATE_DATE = "cgeo.geocaching.saved_state_date";
@@ -68,7 +67,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
private String text = null;
private List<LogType> possibleLogTypes = new ArrayList<LogType>();
private List<TrackableLog> trackables = null;
- private Button postButton = null;
private CheckBox tweetCheck = null;
private LinearLayout tweetBox = null;
private LinearLayout logPasswordBox = null;
@@ -84,6 +82,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
private String imageCaption;
private String imageDescription;
private Uri imageUri;
+ private boolean sendButtonEnabled;
public void onLoadFinished() {
@@ -123,7 +122,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
private void initializeTrackablesAction() {
if (Settings.isTrackableAutoVisit()) {
- for (TrackableLog trackable : trackables) {
+ for (final TrackableLog trackable : trackables) {
trackable.action = LogTypeTrackable.VISITED;
tbChanged = true;
}
@@ -142,8 +141,8 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
final LinearLayout inventoryView = (LinearLayout) findViewById(R.id.inventory);
inventoryView.removeAllViews();
- for (TrackableLog tb : trackables) {
- LinearLayout inventoryItem = (LinearLayout) inflater.inflate(R.layout.logcache_trackable_item, null);
+ for (final TrackableLog tb : trackables) {
+ final LinearLayout inventoryItem = (LinearLayout) inflater.inflate(R.layout.logcache_trackable_item, null);
((TextView) inventoryItem.findViewById(R.id.trackcode)).setText(tb.trackCode);
((TextView) inventoryItem.findViewById(R.id.name)).setText(tb.name);
@@ -154,7 +153,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
actionButton.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View view) {
+ public void onClick(final View view) {
selectTrackableAction(view);
}
});
@@ -164,7 +163,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
inventoryItem.findViewById(R.id.info).setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View view) {
+ public void onClick(final View view) {
final Intent trackablesIntent = new Intent(LogCacheActivity.this, TrackableActivity.class);
trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, tbCode);
startActivity(trackablesIntent);
@@ -184,7 +183,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
changeButton.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View view) {
+ public void onClick(final View view) {
selectAllTrackablesAction();
}
});
@@ -193,33 +192,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
}
- private void enablePostButton(boolean enabled) {
- postButton.setEnabled(enabled);
- if (enabled) {
- postButton.setOnClickListener(new PostListener());
- }
- else {
- postButton.setOnTouchListener(null);
- postButton.setOnClickListener(null);
- }
- updatePostButtonText();
- }
-
- private void updatePostButtonText() {
- postButton.setText(getPostButtonText());
- }
-
- private String getPostButtonText() {
- if (!postButton.isEnabled()) {
- return res.getString(R.string.log_post_not_possible);
- }
- if (!GCVote.isVotingPossible(cache)) {
- return res.getString(R.string.log_post);
- }
- if (GCVote.isValidRating(rating)) {
- return res.getString(R.string.log_post_rate) + " " + GCVote.getRatingText(rating) + "*";
- }
- return res.getString(R.string.log_post_no_rate);
+ private void enablePostButton(final boolean enabled) {
+ sendButtonEnabled = enabled;
+ invalidateOptionsMenuCompatible();
}
@Override
@@ -239,6 +214,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ invalidateOptionsMenuCompatible();
possibleLogTypes = cache.getPossibleLogTypes();
if (StringUtils.isNotBlank(cache.getName())) {
@@ -248,11 +224,13 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
// Get ids for later use
- postButton = (Button) findViewById(R.id.post);
tweetBox = (LinearLayout) findViewById(R.id.tweet_box);
tweetCheck = (CheckBox) findViewById(R.id.tweet);
logPasswordBox = (LinearLayout) findViewById(R.id.log_password_box);
+ final RatingBar ratingBar = (RatingBar) findViewById(R.id.gcvoteRating);
+ initializeRatingBar(ratingBar);
+
// initialize with default values
setDefaultValues();
@@ -277,8 +255,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(cache, null)), false);
}
}
- updatePostButtonText();
- updateImageButton();
enablePostButton(false);
final Button typeButton = (Button) findViewById(R.id.type);
@@ -286,7 +262,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
typeButton.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View view) {
+ public void onClick(final View view) {
selectLogType();
}
});
@@ -305,36 +281,30 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
updateTweetBox(typeSelected);
updateLogPasswordBox(typeSelected);
- final Button imageButton = (Button) findViewById(R.id.image_btn);
- imageButton.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View view) {
- selectImage();
- }
- });
-
- final Button saveButton = (Button) findViewById(R.id.save);
- saveButton.setOnClickListener(new View.OnClickListener() {
+ loggingManager = cache.getLoggingManager(this);
- @Override
- public void onClick(View v) {
- saveLog(true);
- }
- });
+ loggingManager.init();
+ }
- final Button clearButton = (Button) findViewById(R.id.clear);
- clearButton.setOnClickListener(new View.OnClickListener() {
+ private void initializeRatingBar(final RatingBar ratingBar) {
+ final TextView label = (TextView) findViewById(R.id.gcvoteLabel);
+ if (GCVote.isVotingPossible(cache)) {
+ ratingBar.setVisibility(View.VISIBLE);
+ label.setVisibility(View.VISIBLE);
+ }
+ ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {
@Override
- public void onClick(View v) {
- clearLog();
+ public void onRatingChanged(final RatingBar ratingBar, final float stars, final boolean fromUser) {
+ // 0.5 is not a valid rating, therefore we must limit
+ rating = GCVote.isValidRating(stars) ? stars : 0;
+ if (rating < stars) {
+ ratingBar.setRating(rating);
+ }
+ label.setText(GCVote.getDescription(rating));
}
});
-
- loggingManager = cache.getLoggingManager(this);
-
- loggingManager.init();
+ ratingBar.setRating(cache.getMyVote());
}
private void setDefaultValues() {
@@ -364,8 +334,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
final EditText logPasswordView = (EditText) findViewById(R.id.log_password);
logPasswordView.setText(StringUtils.EMPTY);
- updateImageButton();
-
showToast(res.getString(R.string.info_log_cleared));
}
@@ -382,53 +350,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
@Override
- public boolean onCreateOptionsMenu(final Menu menu) {
- super.onCreateOptionsMenu(menu);
-
- final SubMenu menuStars = menu.addSubMenu(0, SUBMENU_VOTE, 0, res.getString(R.string.log_rating)).setIcon(R.drawable.ic_menu_sort_by_size);
- menuStars.add(0, 10, 0, res.getString(R.string.log_no_rating));
- menuStars.add(0, 19, 0, res.getString(R.string.log_stars_5) + " (" + res.getString(R.string.log_stars_5_description) + ")");
- menuStars.add(0, 18, 0, res.getString(R.string.log_stars_45) + " (" + res.getString(R.string.log_stars_45_description) + ")");
- menuStars.add(0, 17, 0, res.getString(R.string.log_stars_4) + " (" + res.getString(R.string.log_stars_4_description) + ")");
- menuStars.add(0, 16, 0, res.getString(R.string.log_stars_35) + " (" + res.getString(R.string.log_stars_35_description) + ")");
- menuStars.add(0, 15, 0, res.getString(R.string.log_stars_3) + " (" + res.getString(R.string.log_stars_3_description) + ")");
- menuStars.add(0, 14, 0, res.getString(R.string.log_stars_25) + " (" + res.getString(R.string.log_stars_25_description) + ")");
- menuStars.add(0, 13, 0, res.getString(R.string.log_stars_2) + " (" + res.getString(R.string.log_stars_2_description) + ")");
- menuStars.add(0, 12, 0, res.getString(R.string.log_stars_15) + " (" + res.getString(R.string.log_stars_15_description) + ")");
- menuStars.add(0, 11, 0, res.getString(R.string.log_stars_1) + " (" + res.getString(R.string.log_stars_1_description) + ")");
-
- return true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
-
- menu.findItem(SUBMENU_VOTE).setVisible(GCVote.isVotingPossible(cache));
-
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (super.onOptionsItemSelected(item)) {
- return true;
- }
-
- final int id = item.getItemId();
- if (id >= 10 && id <= 19) {
- rating = (id - 9) / 2.0f;
- if (!GCVote.isValidRating(rating)) {
- rating = GCVote.NO_RATING;
- }
- updatePostButtonText();
- return true;
- }
-
- return false;
- }
-
- @Override
protected void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
outState.putDouble(SAVED_STATE_RATING, rating);
@@ -440,14 +361,14 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
@Override
- public void setDate(Calendar dateIn) {
+ public void setDate(final Calendar dateIn) {
date = dateIn;
final Button dateButton = (Button) findViewById(R.id.date);
dateButton.setText(Formatter.formatShortDateVerbally(date.getTime().getTime()));
}
- public void setType(LogType type) {
+ public void setType(final LogType type) {
final Button typeButton = (Button) findViewById(R.id.type);
typeSelected = type;
@@ -461,11 +382,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
updateTweetBox(type);
updateLogPasswordBox(type);
-
- updatePostButtonText();
}
- private void updateTweetBox(LogType type) {
+ private void updateTweetBox(final LogType type) {
if (type == LogType.FOUND_IT && Settings.isUseTwitter() && Settings.isTwitterLoginValid()) {
tweetBox.setVisibility(View.VISIBLE);
} else {
@@ -473,7 +392,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
}
- private void updateLogPasswordBox(LogType type) {
+ private void updateLogPasswordBox(final LogType type) {
if (type == LogType.FOUND_IT && cache.isLogPasswordRequired()) {
logPasswordBox.setVisibility(View.VISIBLE);
} else {
@@ -484,20 +403,10 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
private class DateListener implements View.OnClickListener {
@Override
- public void onClick(View arg0) {
- final Dialog dateDialog = new DateDialog(LogCacheActivity.this, LogCacheActivity.this, date);
+ public void onClick(final View arg0) {
+ final DateDialog dateDialog = DateDialog.getInstance(date);
dateDialog.setCancelable(true);
- dateDialog.show();
- }
- }
-
- private class PostListener implements View.OnClickListener {
- @Override
- public void onClick(View arg0) {
- final String message = res.getString(StringUtils.isBlank(imageUri.getPath()) ?
- R.string.log_saving :
- R.string.log_saving_and_uploading);
- new Poster(LogCacheActivity.this, message).execute(currentLogText(), currentLogPassword());
+ dateDialog.show(getSupportFragmentManager(), "date_dialog");
}
}
@@ -516,15 +425,16 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
if (logResult.getPostLogResult() == StatusCode.NO_ERROR) {
// update geocache in DB
- if (typeSelected == LogType.FOUND_IT || typeSelected == LogType.ATTENDED) {
+ if (typeSelected == LogType.FOUND_IT || typeSelected == LogType.ATTENDED || typeSelected == LogType.WEBCAM_PHOTO_TAKEN) {
cache.setFound(true);
cache.setVisitedDate(new Date().getTime());
}
DataStore.saveChangedCache(cache);
// update logs in DB
- ArrayList<LogEntry> newLogs = new ArrayList<LogEntry>(cache.getLogs());
+ final ArrayList<LogEntry> newLogs = new ArrayList<LogEntry>(cache.getLogs());
final LogEntry logNow = new LogEntry(date.getTimeInMillis(), typeSelected, log);
+ logNow.friend = true;
newLogs.add(0, logNow);
DataStore.saveLogsWithoutTransaction(cache.getGeocode(), newLogs);
@@ -541,7 +451,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
if (StringUtils.isNotBlank(imageUri.getPath())) {
- ImageResult imageResult = loggingManager.postLogImage(logResult.getLogId(), imageCaption, imageDescription, imageUri);
+ final ImageResult imageResult = loggingManager.postLogImage(logResult.getLogId(), imageCaption, imageDescription, imageUri);
final String uploadedImageUrl = imageResult.getImageUri();
if (StringUtils.isNotEmpty(uploadedImageUrl)) {
logNow.addLogImage(new Image(uploadedImageUrl, imageCaption, imageDescription));
@@ -552,7 +462,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
return logResult.getPostLogResult();
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.e("VisitCacheActivity.Poster.doInBackgroundInternal", e);
}
@@ -601,15 +511,15 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
private void selectAllTrackablesAction() {
- Builder alert = new AlertDialog.Builder(this);
+ final Builder alert = new AlertDialog.Builder(this);
alert.setTitle(res.getString(R.string.log_tb_changeall));
- String[] tbLogTypes = getTBLogTypes();
+ final String[] tbLogTypes = getTBLogTypes();
alert.setItems(tbLogTypes, new OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int position) {
+ public void onClick(final DialogInterface dialog, final int position) {
final LogTypeTrackable logType = LogTypeTrackable.values()[position];
- for (TrackableLog tb : trackables) {
+ for (final TrackableLog tb : trackables) {
tb.action = logType;
}
tbChanged = true;
@@ -622,7 +532,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
private static String[] getTBLogTypes() {
final LogTypeTrackable[] logTypeValues = LogTypeTrackable.values();
- String[] logTypes = new String[logTypeValues.length];
+ final String[] logTypes = new String[logTypeValues.length];
for (int i = 0; i < logTypes.length; i++) {
logTypes[i] = logTypeValues[i].getLabel();
}
@@ -633,15 +543,15 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
// use a local copy of the possible types, as that one might be modified in the background by the loader
final ArrayList<LogType> possible = new ArrayList<LogType>(possibleLogTypes);
- Builder alert = new AlertDialog.Builder(this);
- String[] choices = new String[possible.size()];
+ final Builder alert = new AlertDialog.Builder(this);
+ final String[] choices = new String[possible.size()];
for (int i = 0; i < choices.length; i++) {
choices[i] = possible.get(i).getL10n();
}
alert.setSingleChoiceItems(choices, possible.indexOf(typeSelected), new OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int position) {
+ public void onClick(final DialogInterface dialog, final int position) {
setType(possible.get(position));
dialog.dismiss();
}
@@ -649,16 +559,16 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
alert.create().show();
}
- private void selectTrackableAction(View view) {
+ private void selectTrackableAction(final View view) {
final int realViewId = view.getId();
- Builder alert = new AlertDialog.Builder(this);
+ final Builder alert = new AlertDialog.Builder(this);
final TrackableLog trackableLog = actionButtons.get(realViewId);
alert.setTitle(trackableLog.name);
- String[] tbLogTypes = getTBLogTypes();
+ final String[] tbLogTypes = getTBLogTypes();
alert.setItems(tbLogTypes, new OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int position) {
+ public void onClick(final DialogInterface dialog, final int position) {
final LogTypeTrackable logType = LogTypeTrackable.values()[position];
tbChanged = true;
trackableLog.action = logType;
@@ -671,7 +581,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
private void selectImage() {
- Intent selectImageIntent = new Intent(this, ImageSelectActivity.class);
+ final Intent selectImageIntent = new Intent(this, ImageSelectActivity.class);
selectImageIntent.putExtra(ImageSelectActivity.EXTRAS_CAPTION, imageCaption);
selectImageIntent.putExtra(ImageSelectActivity.EXTRAS_DESCRIPTION, imageDescription);
selectImageIntent.putExtra(ImageSelectActivity.EXTRAS_URI_AS_STRING, imageUri.toString());
@@ -680,7 +590,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
if (requestCode == SELECT_IMAGE) {
if (resultCode == RESULT_OK) {
imageCaption = data.getStringExtra(ImageSelectActivity.EXTRAS_CAPTION);
@@ -690,19 +600,51 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
// Image capture failed, advise user
showToast(getResources().getString(R.string.err_select_logimage_failed));
}
- updateImageButton();
+ }
+ }
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_send:
+ sendLog();
+ return true;
+ case R.id.menu_image:
+ selectImage();
+ return true;
+ case R.id.save:
+ saveLog(true);
+ finish();
+ return true;
+ case R.id.clear:
+ clearLog();
+ return true;
+ default:
+ break;
}
+
+ return super.onOptionsItemSelected(item);
}
- private void updateImageButton() {
- final Button imageButton = (Button) findViewById(R.id.image_btn);
- if (cache.supportsLogImages()) {
- imageButton.setVisibility(View.VISIBLE);
- imageButton.setText(StringUtils.isNotBlank(imageUri.getPath()) ?
- res.getString(R.string.log_image_edit) : res.getString(R.string.log_image_attach));
- } else {
- imageButton.setVisibility(View.GONE);
+ private void sendLog() {
+ if (!sendButtonEnabled) {
+ Dialogs.message(this, R.string.log_post_not_possible);
}
+ else {
+ final String message = res.getString(StringUtils.isBlank(imageUri.getPath()) ?
+ R.string.log_saving :
+ R.string.log_saving_and_uploading);
+ new Poster(LogCacheActivity.this, message).execute(currentLogText(), currentLogPassword());
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ menu.findItem(R.id.menu_image).setVisible(cache.supportsLogImages());
+ menu.findItem(R.id.save).setVisible(true);
+ menu.findItem(R.id.clear).setVisible(true);
+ return true;
}
+
}
diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java
index fabe391..9f1bc88 100644
--- a/main/src/cgeo/geocaching/LogTrackableActivity.java
+++ b/main/src/cgeo/geocaching/LogTrackableActivity.java
@@ -20,7 +20,6 @@ import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
@@ -240,9 +239,9 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
@Override
public void onClick(View arg0) {
- final Dialog dateDialog = new DateDialog(LogTrackableActivity.this, LogTrackableActivity.this, date);
+ final DateDialog dateDialog = DateDialog.getInstance(date);
dateDialog.setCancelable(true);
- dateDialog.show();
+ dateDialog.show(getSupportFragmentManager(),"date_dialog");
}
}
diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java
index 42dd58d..84bc960 100644
--- a/main/src/cgeo/geocaching/MainActivity.java
+++ b/main/src/cgeo/geocaching/MainActivity.java
@@ -3,9 +3,11 @@ package cgeo.geocaching;
import butterknife.ButterKnife;
import butterknife.InjectView;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.capability.ILogin;
+import cgeo.geocaching.connector.gc.GCConnector;
+import cgeo.geocaching.connector.gc.GCLogin;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.geopoint.Geopoint;
@@ -21,11 +23,14 @@ import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.ui.dialog.Dialogs;
import cgeo.geocaching.utils.DatabaseBackupUtils;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.TextUtils;
import cgeo.geocaching.utils.Version;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
+
import org.apache.commons.lang3.StringUtils;
+
import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Subscriber;
@@ -37,6 +42,7 @@ import rx.subscriptions.Subscriptions;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.SearchManager;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
@@ -45,6 +51,8 @@ import android.location.Geocoder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.SearchView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -61,7 +69,7 @@ import java.util.Comparator;
import java.util.List;
import java.util.Locale;
-public class MainActivity extends AbstractActivity {
+public class MainActivity extends AbstractActionBarActivity {
@InjectView(R.id.nav_satellites) protected TextView navSatellites;
@InjectView(R.id.filter_button_title)protected TextView filterTitle;
@InjectView(R.id.map) protected ImageView findOnMap;
@@ -86,24 +94,24 @@ public class MainActivity extends AbstractActivity {
private final UpdateLocation locationUpdater = new UpdateLocation();
- private Handler updateUserInfoHandler = new Handler() {
+ private final Handler updateUserInfoHandler = new Handler() {
@Override
public void handleMessage(final Message msg) {
// Get active connectors with login status
- ILogin[] loginConns = ConnectorFactory.getActiveLiveConnectors();
+ final ILogin[] loginConns = ConnectorFactory.getActiveLiveConnectors();
// Update UI
infoArea.removeAllViews();
- LayoutInflater inflater = getLayoutInflater();
+ final LayoutInflater inflater = getLayoutInflater();
- for (ILogin conn : loginConns) {
+ for (final ILogin conn : loginConns) {
- TextView connectorInfo = (TextView) inflater.inflate(R.layout.main_activity_connectorstatus, null);
+ final TextView connectorInfo = (TextView) inflater.inflate(R.layout.main_activity_connectorstatus, null);
infoArea.addView(connectorInfo);
- StringBuilder userInfo = new StringBuilder(conn.getName()).append(Formatter.SEPARATOR);
+ final StringBuilder userInfo = new StringBuilder(conn.getName()).append(Formatter.SEPARATOR);
if (conn.isLoggedIn()) {
userInfo.append(conn.getUserName());
if (conn.getCachesFound() >= 0) {
@@ -167,9 +175,9 @@ public class MainActivity extends AbstractActivity {
}
- private SatellitesHandler satellitesHandler = new SatellitesHandler();
+ private final SatellitesHandler satellitesHandler = new SatellitesHandler();
- private Handler firstLoginHandler = new Handler() {
+ private final Handler firstLoginHandler = new Handler() {
@Override
public void handleMessage(final Message msg) {
@@ -179,7 +187,7 @@ public class MainActivity extends AbstractActivity {
if (reason != null && reason != StatusCode.NO_ERROR) { //LoginFailed
showToast(res.getString(reason == StatusCode.MAINTENANCE ? reason.getErrorString() : R.string.err_login_failed_toast));
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("MainActivity.firstLoginHander", e);
}
}
@@ -189,6 +197,10 @@ public class MainActivity extends AbstractActivity {
public void onCreate(final Bundle savedInstanceState) {
// don't call the super implementation with the layout argument, as that would set the wrong theme
super.onCreate(savedInstanceState);
+
+ // Disable the up navigation for this activity
+ getSupportActionBar().setDisplayHomeAsUpEnabled(false);
+
setContentView(R.layout.main_activity);
ButterKnife.inject(this);
@@ -204,6 +216,8 @@ public class MainActivity extends AbstractActivity {
Log.i("Starting " + getPackageName() + ' ' + version + " a.k.a " + Version.getVersionName(this));
init();
+
+ checkShowChangelog();
}
@Override
@@ -231,6 +245,10 @@ public class MainActivity extends AbstractActivity {
new Thread() {
@Override
public void run() {
+ if (mustLogin && conn == GCConnector.getInstance()) {
+ // Properly log out from geocaching.com
+ GCLogin.getInstance().logout();
+ }
conn.login(firstLoginHandler, MainActivity.this);
updateUserInfoHandler.sendEmptyMessage(-1);
}
@@ -262,6 +280,11 @@ public class MainActivity extends AbstractActivity {
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.main_activity_options, menu);
+ final SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+ final MenuItem searchItem = menu.findItem(R.id.menu_gosearch);
+ final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
+ searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
+
return true;
}
@@ -276,6 +299,10 @@ public class MainActivity extends AbstractActivity {
public boolean onOptionsItemSelected(final MenuItem item) {
final int id = item.getItemId();
switch (id) {
+ case android.R.id.home:
+ // this activity must handle the home navigation different than all others
+ showAbout(null);
+ return true;
case R.id.menu_about:
showAbout(null);
return true;
@@ -303,13 +330,12 @@ public class MainActivity extends AbstractActivity {
}
});
return true;
- default:
- return super.onOptionsItemSelected(item);
}
+ return super.onOptionsItemSelected(item);
}
private void startScannerApplication() {
- IntentIntegrator integrator = new IntentIntegrator(this);
+ final IntentIntegrator integrator = new IntentIntegrator(this);
// integrator dialog is English only, therefore localize it
integrator.setButtonYesByID(android.R.string.yes);
integrator.setButtonNoByID(android.R.string.no);
@@ -320,9 +346,9 @@ public class MainActivity extends AbstractActivity {
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
- IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
+ final IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanResult != null) {
- String scan = scanResult.getContents();
+ final String scan = scanResult.getContents();
if (StringUtils.isBlank(scan)) {
return;
}
@@ -434,7 +460,7 @@ public class MainActivity extends AbstractActivity {
cacheTypes.add(CacheType.MYSTERY);
// then add all other cache types sorted alphabetically
- List<CacheType> sorted = new ArrayList<CacheType>();
+ final List<CacheType> sorted = new ArrayList<CacheType>();
sorted.addAll(Arrays.asList(CacheType.values()));
sorted.removeAll(cacheTypes);
@@ -453,18 +479,18 @@ public class MainActivity extends AbstractActivity {
checkedItem = 0;
}
- String[] items = new String[cacheTypes.size()];
+ final String[] items = new String[cacheTypes.size()];
for (int i = 0; i < cacheTypes.size(); i++) {
items[i] = cacheTypes.get(i).getL10n();
}
- Builder builder = new AlertDialog.Builder(this);
+ final Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.menu_filter);
builder.setSingleChoiceItems(items, checkedItem, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int position) {
- CacheType cacheType = cacheTypes.get(position);
+ final CacheType cacheType = cacheTypes.get(position);
Settings.setCacheType(cacheType);
setFilterTitle();
dialog.dismiss();
@@ -524,7 +550,7 @@ public class MainActivity extends AbstractActivity {
navType.setText(res.getString(geo.getLocationProvider().resourceId));
if (geo.getAccuracy() >= 0) {
- int speed = Math.round(geo.getSpeed()) * 60 * 60 / 1000;
+ final int speed = Math.round(geo.getSpeed()) * 60 * 60 / 1000;
navAccuracy.setText("±" + Units.getDistanceFromMeters(geo.getAccuracy()) + Formatter.SEPARATOR + Units.getSpeed(speed));
} else {
navAccuracy.setText(null);
@@ -553,12 +579,13 @@ public class MainActivity extends AbstractActivity {
}
});
AndroidObservable.bindActivity(MainActivity.this, address.onErrorResumeNext(Observable.from(geo.getCoords().toString())))
+ .subscribeOn(Schedulers.io())
.subscribe(new Action1<String>() {
@Override
public void call(final String address) {
navLocation.setText(address);
}
- }, Schedulers.io());
+ });
}
} else {
navLocation.setText(geo.getCoords().toString());
@@ -633,7 +660,7 @@ public class MainActivity extends AbstractActivity {
}
private class CountBubbleUpdateThread extends Thread {
- private Handler countBubbleHandler = new Handler() {
+ private final Handler countBubbleHandler = new Handler() {
@Override
public void handleMessage(final Message msg) {
@@ -645,7 +672,7 @@ public class MainActivity extends AbstractActivity {
countBubble.bringToFront();
countBubble.setVisibility(View.VISIBLE);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("MainActivity.countBubbleHander", e);
}
}
@@ -662,7 +689,7 @@ public class MainActivity extends AbstractActivity {
try {
sleep(500);
checks++;
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("MainActivity.CountBubbleUpdateThread.run", e);
}
@@ -705,20 +732,21 @@ public class MainActivity extends AbstractActivity {
}
}
- /**
- * @param view
- * unused here but needed since this method is referenced from XML layout
- */
- public void showAbout(final View view) {
- startActivity(new Intent(this, AboutActivity.class));
+ private void checkShowChangelog() {
+ final long lastChecksum = Settings.getLastChangelogChecksum();
+ final long checksum = TextUtils.checksum(getString(R.string.changelog_master) + getString(R.string.changelog_release));
+ Settings.setLastChangelogChecksum(checksum);
+ // don't show change log after new install...
+ if (lastChecksum > 0 && lastChecksum != checksum) {
+ AboutActivity.showChangeLog(this);
+ }
}
/**
* @param view
* unused here but needed since this method is referenced from XML layout
*/
- public void goSearch(final View view) {
- onSearchRequested();
+ public void showAbout(final View view) {
+ startActivity(new Intent(this, AboutActivity.class));
}
-
}
diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
index 0a750e0..39531f1 100644
--- a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
+++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
@@ -4,7 +4,7 @@ import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.Optional;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.geopoint.DistanceParser;
import cgeo.geocaching.geopoint.Geopoint;
@@ -44,7 +44,7 @@ import android.widget.TextView;
import java.util.List;
-public class NavigateAnyPointActivity extends AbstractActivity {
+public class NavigateAnyPointActivity extends AbstractActionBarActivity implements CoordinatesInputDialog.CoordinateUpdate {
@InjectView(R.id.historyList) protected ListView historyListView;
@@ -278,18 +278,17 @@ public class NavigateAnyPointActivity extends AbstractActivity {
if (latButton.getText().length() > 0 && lonButton.getText().length() > 0) {
gp = new Geopoint(latButton.getText().toString() + " " + lonButton.getText().toString());
}
- CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(NavigateAnyPointActivity.this, null, gp, app.currentGeo());
+ CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, gp, app.currentGeo());
coordsDialog.setCancelable(true);
- coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
- @Override
- public void update(Geopoint gp) {
- latButton.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
- lonButton.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
- changed = true;
- }
- });
- coordsDialog.show();
+ coordsDialog.show(getSupportFragmentManager(),"wpedit_dialog");
}
+
+ }
+ @Override
+ public void updateCoordinates(Geopoint gp) {
+ latButton.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
+ lonButton.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
+ changed = true;
}
private static class ChangeDistanceUnit implements OnItemSelectedListener {
@@ -328,7 +327,7 @@ public class NavigateAnyPointActivity extends AbstractActivity {
menu.findItem(R.id.menu_default_navigation).setVisible(visible);
menu.findItem(R.id.menu_caches_around).setVisible(visible);
- menu.findItem(R.id.menu_clear_history).setEnabled(!getHistoryOfSearchedLocations().isEmpty());
+ menu.findItem(R.id.menu_clear_history).setVisible(!getHistoryOfSearchedLocations().isEmpty());
} catch (RuntimeException e) {
// nothing
}
@@ -362,9 +361,8 @@ public class NavigateAnyPointActivity extends AbstractActivity {
case R.id.menu_navigate:
NavigationAppFactory.showNavigationMenu(this, null, null, coords);
return true;
- default:
- return false;
}
+ return super.onOptionsItemSelected(item);
}
private void addToHistory(final Geopoint coords) {
diff --git a/main/src/cgeo/geocaching/PocketQueryList.java b/main/src/cgeo/geocaching/PocketQueryList.java
index 2ac137f..4e84881 100644
--- a/main/src/cgeo/geocaching/PocketQueryList.java
+++ b/main/src/cgeo/geocaching/PocketQueryList.java
@@ -52,13 +52,13 @@ public final class PocketQueryList {
subscriber.onNext(GCParser.searchPocketQueryList());
subscriber.onCompleted();
}
- })).subscribe(new Action1<List<PocketQueryList>>() {
+ })).subscribeOn(Schedulers.io()).subscribe(new Action1<List<PocketQueryList>>() {
@Override
public void call(final List<PocketQueryList> pocketQueryLists) {
waitDialog.dismiss();
selectFromPocketQueries(activity, pocketQueryLists, runAfterwards);
}
- }, Schedulers.io());
+ });
}
private static void selectFromPocketQueries(final Activity activity, final List<PocketQueryList> pocketQueryList, final Action1<PocketQueryList> runAfterwards) {
if (CollectionUtils.isEmpty(pocketQueryList)) {
diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java
index 2a37e27..81dec98 100644
--- a/main/src/cgeo/geocaching/SearchActivity.java
+++ b/main/src/cgeo/geocaching/SearchActivity.java
@@ -3,7 +3,7 @@ package cgeo.geocaching;
import butterknife.ButterKnife;
import butterknife.InjectView;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.connector.capability.ISearchByGeocode;
@@ -37,7 +37,7 @@ import android.widget.Button;
import java.util.Locale;
-public class SearchActivity extends AbstractActivity {
+public class SearchActivity extends AbstractActionBarActivity implements CoordinatesInputDialog.CoordinateUpdate {
@InjectView(R.id.buttonLatitude) protected Button buttonLatitude;
@InjectView(R.id.buttonLongitude) protected Button buttonLongitude;
@@ -174,8 +174,20 @@ public class SearchActivity extends AbstractActivity {
}
private void init() {
- buttonLatitude.setOnClickListener(new FindByCoordsAction());
- buttonLongitude.setOnClickListener(new FindByCoordsAction());
+ buttonLatitude.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ updateCoordinates();
+ }
+ });
+ buttonLongitude.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ updateCoordinates();
+ }
+ });
buttonSearchCoords.setOnClickListener(new View.OnClickListener() {
@@ -277,21 +289,16 @@ public class SearchActivity extends AbstractActivity {
}
}
- private class FindByCoordsAction implements OnClickListener {
-
- @Override
- public void onClick(final View arg0) {
- final CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(SearchActivity.this, null, null, app.currentGeo());
- coordsDialog.setCancelable(true);
- coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
- @Override
- public void update(final Geopoint gp) {
- buttonLatitude.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
- buttonLongitude.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
- }
- });
- coordsDialog.show();
- }
+ private void updateCoordinates() {
+ final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, null, app.currentGeo());
+ coordsDialog.setCancelable(true);
+ coordsDialog.show(getSupportFragmentManager(), "wpedit_dialog");
+ }
+
+ @Override
+ public void updateCoordinates(final Geopoint gp) {
+ buttonLatitude.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
+ buttonLongitude.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
}
private void findByCoordsFn() {
diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java
index 12a2522..2e8a3f6 100644
--- a/main/src/cgeo/geocaching/SearchResult.java
+++ b/main/src/cgeo/geocaching/SearchResult.java
@@ -11,7 +11,9 @@ import cgeo.geocaching.gcvote.GCVote;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+
import rx.Observable;
import rx.functions.Func1;
import rx.functions.Func2;
@@ -60,6 +62,14 @@ public class SearchResult implements Parcelable {
}
/**
+ * Build a new empty search result with an error status.
+ */
+ public SearchResult(final StatusCode statusCode) {
+ this();
+ error = statusCode;
+ }
+
+ /**
* Copy a search result, for example to apply different filters on it.
*
* @param searchResult the original search result, which cannot be null
@@ -155,6 +165,7 @@ public class SearchResult implements Parcelable {
return 0;
}
+ @NonNull
public Set<String> getGeocodes() {
return Collections.unmodifiableSet(geocodes);
}
@@ -218,7 +229,7 @@ public class SearchResult implements Parcelable {
int excluded = 0;
for (Geocache cache : caches) {
// Is there any reason to exclude the cache from the list?
- final boolean excludeCache = (excludeDisabled && cache.isDisabled()) ||
+ final boolean excludeCache = (excludeDisabled && (cache.isDisabled() || cache.isArchived())) ||
(excludeMine && (cache.isOwner() || cache.isFound())) ||
(!cacheType.contains(cache));
if (excludeCache) {
@@ -319,7 +330,7 @@ public class SearchResult implements Parcelable {
searchResult.addSearchResult(searchResult2);
return searchResult;
}
- }).toBlockingObservable().first();
+ }).toBlocking().first();
}
}
diff --git a/main/src/cgeo/geocaching/SelectMapfileActivity.java b/main/src/cgeo/geocaching/SelectMapfileActivity.java
index c617012..b2cdf17 100644
--- a/main/src/cgeo/geocaching/SelectMapfileActivity.java
+++ b/main/src/cgeo/geocaching/SelectMapfileActivity.java
@@ -115,8 +115,7 @@ public class SelectMapfileActivity extends AbstractFileListActivity<FileSelectio
}
if (requestCode == REQUEST_DIRECTORY) {
- final String directory = new File(data.getData().getPath()).getAbsolutePath();
- mapFile = directory;
+ mapFile = new File(data.getData().getPath()).getAbsolutePath();
close();
}
}
diff --git a/main/src/cgeo/geocaching/StaticMapsActivity.java b/main/src/cgeo/geocaching/StaticMapsActivity.java
index 16fce37..134e134 100644
--- a/main/src/cgeo/geocaching/StaticMapsActivity.java
+++ b/main/src/cgeo/geocaching/StaticMapsActivity.java
@@ -1,8 +1,9 @@
package cgeo.geocaching;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RxUtils;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Extra;
@@ -11,7 +12,6 @@ import org.androidannotations.annotations.OptionsMenu;
import org.apache.commons.collections4.CollectionUtils;
import android.app.ProgressDialog;
-import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
@@ -25,7 +25,7 @@ import java.util.List;
@EActivity
@OptionsMenu(R.menu.static_maps_activity_options)
-public class StaticMapsActivity extends AbstractActivity {
+public class StaticMapsActivity extends AbstractActionBarActivity {
private static final String EXTRAS_WAYPOINT = "waypoint";
private static final String EXTRAS_DOWNLOAD = "download";
@@ -153,7 +153,7 @@ public class StaticMapsActivity extends AbstractActivity {
final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
if (waypointId == null) {
showToast(res.getString(R.string.info_storing_static_maps));
- StaticMapsProvider.storeCacheStaticMap(cache, true);
+ RxUtils.waitForCompletion(StaticMapsProvider.storeCacheStaticMap(cache));
return cache.hasStaticMap();
}
final Waypoint waypoint = cache.getWaypointById(waypointId);
@@ -161,18 +161,10 @@ public class StaticMapsActivity extends AbstractActivity {
showToast(res.getString(R.string.info_storing_static_maps));
// refresh always removes old waypoint files
StaticMapsProvider.removeWpStaticMaps(waypoint, geocode);
- StaticMapsProvider.storeWaypointStaticMap(cache, waypoint, true);
+ RxUtils.waitForCompletion(StaticMapsProvider.storeWaypointStaticMap(cache, waypoint));
return StaticMapsProvider.hasStaticMapForWaypoint(geocode, waypoint);
}
showToast(res.getString(R.string.err_detail_not_load_map_static));
return false;
}
-
- public static void startActivity(final Context activity, final String geocode, final boolean download, final Waypoint waypoint) {
- StaticMapsActivity_.IntentBuilder_ builder = StaticMapsActivity_.intent(activity).geocode(geocode).download(download);
- if (waypoint != null) {
- builder.waypointId(waypoint.getId());
- }
- builder.start();
- }
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java
index eaab159..0551fc0 100644
--- a/main/src/cgeo/geocaching/StaticMapsProvider.java
+++ b/main/src/cgeo/geocaching/StaticMapsProvider.java
@@ -1,7 +1,6 @@
package cgeo.geocaching;
import cgeo.geocaching.compatibility.Compatibility;
-import cgeo.geocaching.concurrent.BlockingThreadPool;
import cgeo.geocaching.files.LocalStorage;
import cgeo.geocaching.geopoint.GeopointFormatter.Format;
import cgeo.geocaching.network.Network;
@@ -11,15 +10,22 @@ import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
+
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
+import rx.Observable;
+import rx.functions.Action0;
+import rx.schedulers.Schedulers;
+import rx.util.async.Async;
+
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import java.io.File;
-import java.util.concurrent.TimeUnit;
+import java.util.LinkedList;
+import java.util.List;
public final class StaticMapsProvider {
static final int MAPS_LEVEL_MAX = 5;
@@ -34,9 +40,6 @@ public final class StaticMapsProvider {
/** We assume there is no real usable image with less than 1k. */
private static final int MIN_MAP_IMAGE_BYTES = 1000;
- /** ThreadPool restricting this to 1 Thread. **/
- private static final BlockingThreadPool POOL = new BlockingThreadPool(1, Thread.MIN_PRIORITY);
-
/**
* max size in free API version: https://developers.google.com/maps/documentation/staticmaps/#Imagesizes
*/
@@ -50,69 +53,78 @@ public final class StaticMapsProvider {
return LocalStorage.getStorageFile(geocode, MAP_FILENAME_PREFIX + prefix, false, createDirs);
}
- private static void downloadDifferentZooms(final String geocode, final String markerUrl, final String prefix, final String latlonMap, final int edge, final Parameters waypoints) {
- downloadMap(geocode, 20, SATELLITE, markerUrl, prefix + '1', "", latlonMap, edge, edge, waypoints);
- downloadMap(geocode, 18, SATELLITE, markerUrl, prefix + '2', "", latlonMap, edge, edge, waypoints);
- downloadMap(geocode, 16, ROADMAP, markerUrl, prefix + '3', "", latlonMap, edge, edge, waypoints);
- downloadMap(geocode, 14, ROADMAP, markerUrl, prefix + '4', "", latlonMap, edge, edge, waypoints);
- downloadMap(geocode, 11, ROADMAP, markerUrl, prefix + '5', "", latlonMap, edge, edge, waypoints);
+ private static Observable<String> downloadDifferentZooms(final String geocode, final String markerUrl, final String prefix, final String latlonMap, final int edge, final Parameters waypoints) {
+ return Observable.merge(downloadMap(geocode, 20, SATELLITE, markerUrl, prefix + '1', "", latlonMap, edge, edge, waypoints),
+ downloadMap(geocode, 18, SATELLITE, markerUrl, prefix + '2', "", latlonMap, edge, edge, waypoints),
+ downloadMap(geocode, 16, ROADMAP, markerUrl, prefix + '3', "", latlonMap, edge, edge, waypoints),
+ downloadMap(geocode, 14, ROADMAP, markerUrl, prefix + '4', "", latlonMap, edge, edge, waypoints),
+ downloadMap(geocode, 11, ROADMAP, markerUrl, prefix + '5', "", latlonMap, edge, edge, waypoints));
}
- private static void downloadMap(final String geocode, final int zoom, final String mapType, final String markerUrl, final String prefix, final String shadow, final String latlonMap, final int width, final int height, final Parameters waypoints) {
- final Parameters params = new Parameters(
- "center", latlonMap,
- "zoom", String.valueOf(zoom),
- "size", String.valueOf(limitSize(width)) + 'x' + String.valueOf(limitSize(height)),
- "maptype", mapType,
- "markers", "icon:" + markerUrl + '|' + shadow + latlonMap,
- "sensor", "false");
- if (waypoints != null) {
- params.addAll(waypoints);
- }
- final HttpResponse httpResponse = Network.getRequest(GOOGLE_STATICMAP_URL, params);
+ private static Observable<String> downloadMap(final String geocode, final int zoom, final String mapType, final String markerUrl, final String prefix, final String shadow, final String latlonMap, final int width, final int height, final Parameters waypoints) {
+ return Async.fromAction(new Action0() {
+ @Override
+ public void call() {
+ final Parameters params = new Parameters(
+ "center", latlonMap,
+ "zoom", String.valueOf(zoom),
+ "size", String.valueOf(limitSize(width)) + 'x' + String.valueOf(limitSize(height)),
+ "maptype", mapType,
+ "markers", "icon:" + markerUrl + '|' + shadow + latlonMap,
+ "sensor", "false");
+ if (waypoints != null) {
+ params.addAll(waypoints);
+ }
+ final HttpResponse httpResponse = Network.getRequest(GOOGLE_STATICMAP_URL, params);
- if (httpResponse == null) {
- Log.e("StaticMapsProvider.downloadMap: httpResponse is null");
- return;
- }
- if (httpResponse.getStatusLine().getStatusCode() != 200) {
- Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + httpResponse.getStatusLine().getStatusCode());
- return;
- }
- final File file = getMapFile(geocode, prefix, true);
- if (LocalStorage.saveEntityToFile(httpResponse, file)) {
- // Delete image if it has no contents
- final long fileSize = file.length();
- if (fileSize < MIN_MAP_IMAGE_BYTES) {
- FileUtils.deleteIgnoringFailure(file);
+ if (httpResponse == null) {
+ Log.e("StaticMapsProvider.downloadMap: httpResponse is null");
+ return;
+ }
+ if (httpResponse.getStatusLine().getStatusCode() != 200) {
+ Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + httpResponse.getStatusLine().getStatusCode());
+ return;
+ }
+ final File file = getMapFile(geocode, prefix, true);
+ if (LocalStorage.saveEntityToFile(httpResponse, file)) {
+ // Delete image if it has no contents
+ final long fileSize = file.length();
+ if (fileSize < MIN_MAP_IMAGE_BYTES) {
+ FileUtils.deleteIgnoringFailure(file);
+ }
+ }
}
- }
+ }, prefix, Schedulers.io());
}
private static int limitSize(final int imageSize) {
return Math.min(imageSize, GOOGLE_MAPS_MAX_SIZE);
}
- public static void downloadMaps(final Geocache cache) {
+ public static Observable<String> downloadMaps(final Geocache cache) {
if ((!Settings.isStoreOfflineMaps() && !Settings.isStoreOfflineWpMaps()) || StringUtils.isBlank(cache.getGeocode())) {
- return;
+ return Observable.empty();
}
int edge = guessMaxDisplaySide();
+ final List<Observable<String>> downloaders = new LinkedList<Observable<String>>();
+
if (Settings.isStoreOfflineMaps() && cache.getCoords() != null) {
- storeCachePreviewMap(cache);
- storeCacheStaticMap(cache, edge, false);
+ downloaders.add(storeCachePreviewMap(cache));
+ downloaders.add(storeCacheStaticMap(cache, edge));
}
// clean old and download static maps for waypoints if one is missing
if (Settings.isStoreOfflineWpMaps()) {
for (final Waypoint waypoint : cache.getWaypoints()) {
if (!hasAllStaticMapsForWaypoint(cache.getGeocode(), waypoint)) {
- refreshAllWpStaticMaps(cache, edge);
+ downloaders.add(refreshAllWpStaticMaps(cache, edge));
}
}
}
+
+ return Observable.merge(downloaders);
}
/**
@@ -123,44 +135,47 @@ public final class StaticMapsProvider {
* @param edge
* The boundings
*/
- private static void refreshAllWpStaticMaps(final Geocache cache, final int edge) {
+ private static Observable<String> refreshAllWpStaticMaps(final Geocache cache, final int edge) {
LocalStorage.deleteFilesWithPrefix(cache.getGeocode(), MAP_FILENAME_PREFIX + WAYPOINT_PREFIX);
+ final List<Observable<String>> downloaders = new LinkedList<Observable<String>>();
for (Waypoint waypoint : cache.getWaypoints()) {
- storeWaypointStaticMap(cache.getGeocode(), edge, waypoint, false);
+ downloaders.add(storeWaypointStaticMap(cache.getGeocode(), edge, waypoint));
}
+ return Observable.merge(downloaders);
}
- public static void storeWaypointStaticMap(final Geocache cache, final Waypoint waypoint, final boolean waitForResult) {
- int edge = StaticMapsProvider.guessMaxDisplaySide();
- storeWaypointStaticMap(cache.getGeocode(), edge, waypoint, waitForResult);
+ public static Observable<String> storeWaypointStaticMap(final Geocache cache, final Waypoint waypoint) {
+ final int edge = StaticMapsProvider.guessMaxDisplaySide();
+ return storeWaypointStaticMap(cache.getGeocode(), edge, waypoint);
}
- private static void storeWaypointStaticMap(final String geocode, final int edge, final Waypoint waypoint, final boolean waitForResult) {
+ private static Observable<String> storeWaypointStaticMap(final String geocode, final int edge, final Waypoint waypoint) {
if (geocode == null) {
Log.e("storeWaypointStaticMap - missing input parameter geocode");
- return;
+ return Observable.empty();
}
if (waypoint == null) {
Log.e("storeWaypointStaticMap - missing input parameter waypoint");
- return;
+ return Observable.empty();
}
if (waypoint.getCoords() == null) {
- return;
+ return Observable.empty();
}
String wpLatlonMap = waypoint.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA);
String wpMarkerUrl = getWpMarkerUrl(waypoint);
if (!hasAllStaticMapsForWaypoint(geocode, waypoint)) {
// download map images in separate background thread for higher performance
- downloadMaps(geocode, wpMarkerUrl, WAYPOINT_PREFIX + waypoint.getId() + '_' + waypoint.getStaticMapsHashcode() + "_", wpLatlonMap, edge, null, waitForResult);
+ return downloadMaps(geocode, wpMarkerUrl, WAYPOINT_PREFIX + waypoint.getId() + '_' + waypoint.getStaticMapsHashcode() + "_", wpLatlonMap, edge, null);
}
+ return Observable.empty();
}
- public static void storeCacheStaticMap(final Geocache cache, final boolean waitForResult) {
+ public static Observable<String> storeCacheStaticMap(final Geocache cache) {
int edge = guessMaxDisplaySide();
- storeCacheStaticMap(cache, edge, waitForResult);
+ return storeCacheStaticMap(cache, edge);
}
- private static void storeCacheStaticMap(final Geocache cache, final int edge, final boolean waitForResult) {
+ private static Observable<String> storeCacheStaticMap(final Geocache cache, final int edge) {
final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA);
final Parameters waypoints = new Parameters();
for (final Waypoint waypoint : cache.getWaypoints()) {
@@ -172,15 +187,15 @@ public final class StaticMapsProvider {
}
// download map images in separate background thread for higher performance
final String cacheMarkerUrl = getCacheMarkerUrl(cache);
- downloadMaps(cache.getGeocode(), cacheMarkerUrl, "", latlonMap, edge, waypoints, waitForResult);
+ return downloadMaps(cache.getGeocode(), cacheMarkerUrl, "", latlonMap, edge, waypoints);
}
- public static void storeCachePreviewMap(final Geocache cache) {
+ public static Observable<String> storeCachePreviewMap(final Geocache cache) {
final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA);
final Point displaySize = Compatibility.getDisplaySize();
final int minSize = Math.min(displaySize.x, displaySize.y);
final String markerUrl = MARKERS_URL + "my_location_mdpi.png";
- downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, minSize, minSize, null);
+ return downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, minSize, minSize, null);
}
private static int guessMaxDisplaySide() {
@@ -188,24 +203,10 @@ public final class StaticMapsProvider {
return Math.max(displaySize.x, displaySize.y) - 25;
}
- private static void downloadMaps(final String geocode, final String markerUrl, final String prefix, final String latlonMap, final int edge,
- final Parameters waypoints, final boolean waitForResult) {
- if (waitForResult) {
- downloadDifferentZooms(geocode, markerUrl, prefix, latlonMap, edge, waypoints);
- }
- else {
- final Runnable currentTask = new Runnable() {
- @Override
- public void run() {
- downloadDifferentZooms(geocode, markerUrl, prefix, latlonMap, edge, waypoints);
- }
- };
- try {
- POOL.add(currentTask, 20, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- Log.e("StaticMapsProvider.downloadMaps error adding task", e);
- }
- }
+ private static Observable<String> downloadMaps(final String geocode, final String markerUrl, final String prefix,
+ final String latlonMap, final int edge,
+ final Parameters waypoints) {
+ return downloadDifferentZooms(geocode, markerUrl, prefix, latlonMap, edge, waypoints);
}
private static String getCacheMarkerUrl(final Geocache cache) {
@@ -213,7 +214,7 @@ public final class StaticMapsProvider {
url.append("marker_cache_").append(cache.getType().id);
if (cache.isFound()) {
url.append("_found");
- } else if (cache.isDisabled()) {
+ } else if (cache.isDisabled() || cache.isArchived()) {
url.append("_disabled");
}
url.append(".png");
diff --git a/main/src/cgeo/geocaching/StatusFragment.java b/main/src/cgeo/geocaching/StatusFragment.java
index f8552d7..553acc1 100644
--- a/main/src/cgeo/geocaching/StatusFragment.java
+++ b/main/src/cgeo/geocaching/StatusFragment.java
@@ -31,7 +31,8 @@ public class StatusFragment extends Fragment {
final ViewGroup statusGroup = (ViewGroup) inflater.inflate(R.layout.status, container, false);
final ImageView statusIcon = (ImageView) statusGroup.findViewById(R.id.status_icon);
final TextView statusMessage = (TextView) statusGroup.findViewById(R.id.status_message);
- statusSubscription = AndroidObservable.bindFragment(this, StatusUpdater.latestStatus).subscribe(new Action1<Status>() {
+ statusSubscription = AndroidObservable.bindFragment(this, StatusUpdater.latestStatus).subscribeOn(Schedulers.io())
+ .subscribe(new Action1<Status>() {
@Override
public void call(final Status status) {
if (status == null) {
@@ -77,7 +78,7 @@ public class StatusFragment extends Fragment {
statusGroup.setClickable(false);
}
}
- }, Schedulers.io());
+ });
return statusGroup;
}
diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java
index 81d23c9..2a228c1 100644
--- a/main/src/cgeo/geocaching/TrackableActivity.java
+++ b/main/src/cgeo/geocaching/TrackableActivity.java
@@ -25,6 +25,7 @@ import cgeo.geocaching.utils.UnknownTagsHandler;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
+
import rx.android.observables.AndroidObservable;
import rx.android.observables.ViewObservable;
import rx.functions.Action1;
@@ -36,12 +37,15 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.support.v7.app.ActionBar;
+import android.support.v7.view.ActionMode;
import android.text.Html;
-import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
@@ -74,7 +78,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
private final Handler loadTrackableHandler = new Handler() {
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
if (trackable == null) {
if (waitDialog != null) {
waitDialog.dismiss();
@@ -110,13 +114,27 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
if (waitDialog != null) {
waitDialog.dismiss();
}
+
+ // if we have a newer Android device setup Android Beam for easy cache sharing
+ initializeAndroidBeam(
+ new ActivitySharingInterface() {
+ @Override
+ public String getUri() {
+ return trackable.getUrl();
+ }
+ }
+ );
}
};
private CharSequence clickedItemText = null;
+ /**
+ * Action mode of the current contextual action bar (e.g. for copy and share actions).
+ */
+ private ActionMode currentActionMode;
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.viewpager_activity);
// set title in code, as the activity needs a hard coded title due to the intent filters
@@ -198,43 +216,13 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
@Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) {
- super.onCreateContextMenu(menu, view, info);
- final int viewId = view.getId();
- assert view instanceof TextView;
- clickedItemText = ((TextView) view).getText();
- switch (viewId) {
- case R.id.value: // name, TB-code, origin, released, distance
- final String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText();
- buildDetailsContextMenu(menu, clickedItemText, itemTitle, true);
- break;
- case R.id.goal:
- buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.trackable_goal), false);
- break;
- case R.id.details:
- buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.trackable_details), false);
- break;
- case R.id.log:
- buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_logs), false);
- break;
- default:
- break;
- }
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- return onClipboardItemSelected(item, clickedItemText) || onOptionsItemSelected(item);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.trackable_activity, menu);
return true;
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_log_touch:
LogTrackableActivity.startActivity(this, trackable);
@@ -242,16 +230,15 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
case R.id.menu_browser_trackable:
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getUrl())));
return true;
- default:
- return false;
}
+ return super.onOptionsItemSelected(item);
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
+ public boolean onPrepareOptionsMenu(final Menu menu) {
if (trackable != null) {
- menu.findItem(R.id.menu_log_touch).setEnabled(StringUtils.isNotBlank(geocode) && trackable.isLoggable());
- menu.findItem(R.id.menu_browser_trackable).setEnabled(StringUtils.isNotBlank(trackable.getUrl()));
+ menu.findItem(R.id.menu_log_touch).setVisible(StringUtils.isNotBlank(geocode) && trackable.isLoggable());
+ menu.findItem(R.id.menu_browser_trackable).setVisible(StringUtils.isNotBlank(trackable.getUrl()));
}
return super.onPrepareOptionsMenu(menu);
}
@@ -262,7 +249,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
final private String guid;
final private String id;
- public LoadTrackableThread(Handler handlerIn, String geocodeIn, String guidIn, String idIn) {
+ public LoadTrackableThread(final Handler handlerIn, final String geocodeIn, final String guidIn, final String idIn) {
handler = handlerIn;
geocode = geocodeIn;
guid = guidIn;
@@ -272,19 +259,20 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
@Override
public void run() {
if (StringUtils.isNotEmpty(geocode)) {
- trackable = DataStore.loadTrackable(geocode);
-
- if (trackable == null || trackable.isLoggable()) {
- // iterate over the connectors as some codes may be handled by multiple connectors
- for (final TrackableConnector trackableConnector : ConnectorFactory.getTrackableConnectors()) {
- if (trackableConnector.canHandleTrackable(geocode)) {
- trackable = trackableConnector.searchTrackable(geocode, guid, id);
- if (trackable != null) {
- break;
- }
+
+ // iterate over the connectors as some codes may be handled by multiple connectors
+ for (final TrackableConnector trackableConnector : ConnectorFactory.getTrackableConnectors()) {
+ if (trackableConnector.canHandleTrackable(geocode)) {
+ trackable = trackableConnector.searchTrackable(geocode, guid, id);
+ if (trackable != null) {
+ break;
}
}
}
+ // Check local storage (offline case)
+ if (trackable == null) {
+ trackable = DataStore.loadTrackable(geocode);
+ }
}
// fall back to GC search by GUID
if (trackable == null) {
@@ -298,7 +286,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
final private String url;
final private Handler handler;
- public TrackableIconThread(String urlIn, Handler handlerIn) {
+ public TrackableIconThread(final String urlIn, final Handler handlerIn) {
url = urlIn;
handler = handlerIn;
}
@@ -322,18 +310,18 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
private static class TrackableIconHandler extends Handler {
- final private TextView view;
+ final private ActionBar view;
- public TrackableIconHandler(TextView viewIn) {
+ public TrackableIconHandler(final ActionBar viewIn) {
view = viewIn;
}
@Override
- public void handleMessage(Message message) {
+ public void handleMessage(final Message message) {
final BitmapDrawable image = (BitmapDrawable) message.obj;
if (image != null && view != null) {
image.setBounds(0, 0, view.getHeight(), view.getHeight());
- view.setCompoundDrawables(image, null, null, null);
+ view.setIcon(image);
}
}
}
@@ -348,7 +336,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
@Override
- protected PageViewCreator createViewCreator(Page page) {
+ protected PageViewCreator createViewCreator(final Page page) {
switch (page) {
case DETAILS:
return new DetailsViewCreator();
@@ -359,7 +347,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
@Override
- protected String getTitle(Page page) {
+ protected String getTitle(final Page page) {
return res.getString(page.resId);
}
@@ -392,13 +380,13 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
// action bar icon
if (StringUtils.isNotBlank(trackable.getIconUrl())) {
- final TrackableIconHandler iconHandler = new TrackableIconHandler(((TextView) findViewById(R.id.actionbar_title)));
+ final TrackableIconHandler iconHandler = new TrackableIconHandler(getSupportActionBar());
final TrackableIconThread iconThread = new TrackableIconThread(trackable.getIconUrl(), iconHandler);
iconThread.start();
}
// trackable name
- registerForContextMenu(details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown)));
+ addContextMenu(details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown)));
// trackable type
String tbType;
@@ -410,7 +398,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
details.add(R.string.trackable_type, tbType);
// trackable geocode
- registerForContextMenu(details.add(R.string.trackable_code, trackable.getGeocode()));
+ addContextMenu(details.add(R.string.trackable_code, trackable.getGeocode()));
// trackable owner
final TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown));
@@ -455,7 +443,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
if (Trackable.SPOTTED_CACHE == trackable.getSpottedType()) {
spotted.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View arg0) {
+ public void onClick(final View arg0) {
if (StringUtils.isNotBlank(trackable.getSpottedGuid())) {
CacheDetailActivity.startActivityGuid(TrackableActivity.this, trackable.getSpottedGuid(), trackable.getSpottedName());
}
@@ -479,17 +467,17 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
if (StringUtils.isNotBlank(trackable.getOrigin())) {
final TextView origin = details.add(R.string.trackable_origin, "");
origin.setText(Html.fromHtml(trackable.getOrigin()), TextView.BufferType.SPANNABLE);
- registerForContextMenu(origin);
+ addContextMenu(origin);
}
// trackable released
if (trackable.getReleased() != null) {
- registerForContextMenu(details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime())));
+ addContextMenu(details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime())));
}
// trackable distance
if (trackable.getDistance() >= 0) {
- registerForContextMenu(details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance())));
+ addContextMenu(details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance())));
}
// trackable goal
@@ -498,7 +486,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
goalTextView.setVisibility(View.VISIBLE);
goalTextView.setText(Html.fromHtml(trackable.getGoal(), new HtmlImage(geocode, true, 0, false), null), TextView.BufferType.SPANNABLE);
goalTextView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
- registerForContextMenu(goalTextView);
+ addContextMenu(goalTextView);
}
// trackable details
@@ -507,7 +495,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
detailsTextView.setVisibility(View.VISIBLE);
detailsTextView.setText(Html.fromHtml(trackable.getDetails(), new HtmlImage(geocode, true, 0, false), new UnknownTagsHandler()), TextView.BufferType.SPANNABLE);
detailsTextView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
- registerForContextMenu(detailsTextView);
+ addContextMenu(detailsTextView);
}
// trackable image
@@ -538,4 +526,70 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
+ public void addContextMenu(final View view) {
+ view.setOnLongClickListener(new OnLongClickListener() {
+
+ @Override
+ public boolean onLongClick(final View v) {
+ return startContextualActionBar(view);
+ }
+ });
+
+ view.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(final View v) {
+ startContextualActionBar(view);
+ }
+ });
+ }
+
+ private boolean startContextualActionBar(final View view) {
+ if (currentActionMode != null) {
+ return false;
+ }
+ currentActionMode = startSupportActionMode(new ActionMode.Callback() {
+
+ @Override
+ public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) {
+ final int viewId = view.getId();
+ assert view instanceof TextView;
+ clickedItemText = ((TextView) view).getText();
+ switch (viewId) {
+ case R.id.value: // name, TB-code, origin, released, distance
+ final String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText();
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, itemTitle, true);
+ return true;
+ case R.id.goal:
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.trackable_goal), false);
+ return true;
+ case R.id.details:
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.trackable_details), false);
+ return true;
+ case R.id.log:
+ buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_logs), false);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onDestroyActionMode(final ActionMode actionMode) {
+ currentActionMode = null;
+ }
+
+ @Override
+ public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) {
+ actionMode.getMenuInflater().inflate(R.menu.details_context, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onActionItemClicked(final ActionMode actionMode, final MenuItem menuItem) {
+ return onClipboardItemSelected(actionMode, menuItem, clickedItemText);
+ }
+ });
+ return false;
+ }
+
}
diff --git a/main/src/cgeo/geocaching/UsefulAppsActivity.java b/main/src/cgeo/geocaching/UsefulAppsActivity.java
index 39c527d..1159453 100644
--- a/main/src/cgeo/geocaching/UsefulAppsActivity.java
+++ b/main/src/cgeo/geocaching/UsefulAppsActivity.java
@@ -3,7 +3,7 @@ package cgeo.geocaching;
import butterknife.ButterKnife;
import butterknife.InjectView;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractActionBarActivity;
import cgeo.geocaching.ui.AbstractViewHolder;
import android.app.Activity;
@@ -18,7 +18,7 @@ import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
-public class UsefulAppsActivity extends AbstractActivity {
+public class UsefulAppsActivity extends AbstractActionBarActivity {
@InjectView(R.id.apps_list) protected ListView list;
diff --git a/main/src/cgeo/geocaching/Waypoint.java b/main/src/cgeo/geocaching/Waypoint.java
index efedff5..18b055b 100644
--- a/main/src/cgeo/geocaching/Waypoint.java
+++ b/main/src/cgeo/geocaching/Waypoint.java
@@ -122,22 +122,26 @@ public class Waypoint implements IWaypoint {
}
private int computeOrder() {
+ // first parking, then trailhead (as start of the journey)
+ // puzzles, stages, waypoints can all be mixed
+ // at last the final and the original coordinates of the final
switch (waypointType) {
case PARKING:
return -1;
case TRAILHEAD:
return 1;
- case STAGE: // puzzles and stages with same value
- return 2;
+ case STAGE:
case PUZZLE:
+ case WAYPOINT:
return 2;
case FINAL:
return 3;
- case OWN:
+ case ORIGINAL:
return 4;
- default:
- return 0;
+ case OWN:
+ return 5;
}
+ return 0;
}
private int order() {
@@ -151,13 +155,13 @@ public class Waypoint implements IWaypoint {
return prefix;
}
- public void setPrefix(String prefix) {
+ public void setPrefix(final String prefix) {
this.prefix = prefix;
cachedOrder = ORDER_UNDEFINED;
}
public String getUrl() {
- return "http://www.geocaching.com//seek/cache_details.aspx?wp=" + geocode;
+ return "http://www.geocaching.com/seek/cache_details.aspx?wp=" + geocode;
}
@Override
@@ -165,7 +169,7 @@ public class Waypoint implements IWaypoint {
return id;
}
- public void setId(int id) {
+ public void setId(final int id) {
this.id = id;
}
@@ -174,7 +178,7 @@ public class Waypoint implements IWaypoint {
return geocode;
}
- public void setGeocode(String geocode) {
+ public void setGeocode(final String geocode) {
this.geocode = StringUtils.upperCase(geocode);
}
@@ -187,7 +191,7 @@ public class Waypoint implements IWaypoint {
return lookup;
}
- public void setLookup(String lookup) {
+ public void setLookup(final String lookup) {
this.lookup = lookup;
}
@@ -196,7 +200,7 @@ public class Waypoint implements IWaypoint {
return name;
}
- public void setName(String name) {
+ public void setName(final String name) {
this.name = name;
}
@@ -204,7 +208,7 @@ public class Waypoint implements IWaypoint {
return latlon;
}
- public void setLatlon(String latlon) {
+ public void setLatlon(final String latlon) {
this.latlon = latlon;
}
@@ -213,7 +217,7 @@ public class Waypoint implements IWaypoint {
return coords;
}
- public void setCoords(Geopoint coords) {
+ public void setCoords(final Geopoint coords) {
this.coords = coords;
}
@@ -221,7 +225,7 @@ public class Waypoint implements IWaypoint {
return note;
}
- public void setNote(String note) {
+ public void setNote(final String note) {
this.note = note;
}
@@ -244,7 +248,7 @@ public class Waypoint implements IWaypoint {
return "waypoint";
}
- public void setVisited(boolean visited) {
+ public void setVisited(final boolean visited) {
this.visited = visited;
}
@@ -267,7 +271,7 @@ public class Waypoint implements IWaypoint {
public static final Comparator<? super Waypoint> WAYPOINT_COMPARATOR = new Comparator<Waypoint>() {
@Override
- public int compare(Waypoint left, Waypoint right) {
+ public int compare(final Waypoint left, final Waypoint right) {
return left.order() - right.order();
}
};
@@ -282,7 +286,7 @@ public class Waypoint implements IWaypoint {
String gpxId = prefix;
if (StringUtils.isNotBlank(geocode)) {
- Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
if (cache != null) {
gpxId = cache.getWaypointGpxId(prefix);
}
diff --git a/main/src/cgeo/geocaching/WaypointPopup.java b/main/src/cgeo/geocaching/WaypointPopup.java
index 916ad4c..f1ffc1d 100644
--- a/main/src/cgeo/geocaching/WaypointPopup.java
+++ b/main/src/cgeo/geocaching/WaypointPopup.java
@@ -1,115 +1,35 @@
package cgeo.geocaching;
-import butterknife.ButterKnife;
-import butterknife.InjectView;
-
-import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
-import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.Units;
-import cgeo.geocaching.sensors.IGeoData;
-import cgeo.geocaching.ui.CacheDetailsCreator;
-import cgeo.geocaching.utils.Log;
-
-import org.apache.commons.lang3.StringUtils;
-
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.TextView;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.view.Window;
-public class WaypointPopup extends AbstractPopupActivity {
- @InjectView(R.id.actionbar_title) protected TextView actionBarTitle;
- @InjectView(R.id.waypoint_details_list) protected LinearLayout waypointDetailsLayout;
- @InjectView(R.id.edit) protected Button buttonEdit;
- @InjectView(R.id.details_list) protected LinearLayout cacheDetailsLayout;
+import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.ActivityMixin;
+public class WaypointPopup extends AbstractActivity {
private int waypointId = 0;
- private Waypoint waypoint = null;
- private TextView waypointDistance = null;
-
- public WaypointPopup() {
- super(R.layout.waypoint_popup);
- }
+ private String geocode;
@Override
- public void onCreate(final Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ButterKnife.inject(this);
- // get parameters
- final Bundle extras = getIntent().getExtras();
- if (extras != null) {
- waypointId = extras.getInt(Intents.EXTRA_WAYPOINT_ID);
- }
- }
-
- @Override
- public void onUpdateGeoData(IGeoData geo) {
- if (geo.getCoords() != null && waypoint != null && waypoint.getCoords() != null) {
- waypointDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(waypoint.getCoords())));
- waypointDistance.bringToFront();
- }
- }
-
- @Override
- protected void init() {
- super.init();
- waypoint = DataStore.loadWaypoint(waypointId);
- try {
- if (StringUtils.isNotBlank(waypoint.getName())) {
- setTitle(waypoint.getName());
- } else {
- setTitle(waypoint.getGeocode());
- }
-
- actionBarTitle.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(waypoint.getWaypointType().markerId), null, null, null);
-
- details = new CacheDetailsCreator(this, waypointDetailsLayout);
+ supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
- //Waypoint geocode
- details.add(R.string.cache_geocode, waypoint.getPrefix() + waypoint.getGeocode().substring(2));
- details.addDistance(waypoint, waypointDistance);
- waypointDistance = details.getValueView();
- details.add(R.string.waypoint_note, waypoint.getNote());
+ this.setTheme(ActivityMixin.getDialogTheme());
- buttonEdit.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- EditWaypointActivity.startActivityEditWaypoint(WaypointPopup.this, cache, waypoint.getId());
- finish();
- }
- });
-
- details = new CacheDetailsCreator(this, cacheDetailsLayout);
- details.add(R.string.cache_name, cache.getName());
-
- addCacheDetails();
-
- } catch (Exception e) {
- Log.e("WaypointPopup.init", e);
+ final Bundle extras = getIntent().getExtras();
+ if (extras != null) {
+ waypointId = extras.getInt(Intents.EXTRA_WAYPOINT_ID);
+ geocode = extras.getString(Intents.EXTRA_GEOCODE);
}
- }
-
- @Override
- public void navigateTo() {
- NavigationAppFactory.startDefaultNavigationApplication(1, this, waypoint);
- }
+ showDialog();
- /**
- * Tries to navigate to the {@link Geocache} of this activity.
- */
- @Override
- protected void startDefaultNavigation2() {
- if (waypoint == null || waypoint.getCoords() == null) {
- showToast(res.getString(R.string.cache_coordinates_no));
- return;
- }
- NavigationAppFactory.startDefaultNavigationApplication(2, this, waypoint);
- finish();
}
public static void startActivity(final Context context, final int waypointId, final String geocode) {
@@ -119,16 +39,22 @@ public class WaypointPopup extends AbstractPopupActivity {
context.startActivity(popupIntent);
}
- @Override
- public void showNavigationMenu() {
- NavigationAppFactory.showNavigationMenu(this, null, waypoint, null);
- }
- @Override
- protected Geopoint getCoordinates() {
- if (waypoint == null) {
- return null;
+ void showDialog() {
+ // DialogFragment.show() will take care of adding the fragment
+ // in a transaction. We also want to remove any currently showing
+ // dialog, so make our own transaction and take care of that here.
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+ Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
+ if (prev != null) {
+ ft.remove(prev);
}
- return waypoint.getCoords();
+ ft.addToBackStack(null);
+
+ // Create and show the dialog.
+ DialogFragment newFragment = WaypointPopupFragment.newInstance(geocode, waypointId);
+ newFragment.show(ft, "dialog");
}
+
+
}
diff --git a/main/src/cgeo/geocaching/WaypointPopupFragment.java b/main/src/cgeo/geocaching/WaypointPopupFragment.java
new file mode 100644
index 0000000..03d95e5
--- /dev/null
+++ b/main/src/cgeo/geocaching/WaypointPopupFragment.java
@@ -0,0 +1,147 @@
+package cgeo.geocaching;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+
+import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.geopoint.Units;
+import cgeo.geocaching.sensors.IGeoData;
+import cgeo.geocaching.ui.CacheDetailsCreator;
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class WaypointPopupFragment extends AbstractDialogFragment {
+ @InjectView(R.id.actionbar_title) protected TextView actionBarTitle;
+ @InjectView(R.id.waypoint_details_list) protected LinearLayout waypointDetailsLayout;
+ @InjectView(R.id.edit) protected Button buttonEdit;
+ @InjectView(R.id.details_list) protected LinearLayout cacheDetailsLayout;
+
+ private int waypointId = 0;
+ private Waypoint waypoint = null;
+ private TextView waypointDistance = null;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.waypoint_popup, container, false);
+ initCustomActionBar(v);
+ ButterKnife.inject(this,v);
+
+ return v;
+ }
+
+ @Override
+ public void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ waypointId = getArguments().getInt(WAYPOINT_ARG);
+ }
+
+ @Override
+ protected void onUpdateGeoData(IGeoData geo) {
+ if (geo.getCoords() != null && waypoint != null && waypoint.getCoords() != null) {
+ waypointDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(waypoint.getCoords())));
+ waypointDistance.bringToFront();
+ }
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+
+ waypoint = DataStore.loadWaypoint(waypointId);
+ try {
+ if (StringUtils.isNotBlank(waypoint.getName())) {
+ setTitle(waypoint.getName());
+ } else {
+ setTitle(waypoint.getGeocode());
+ }
+
+
+ actionBarTitle.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(waypoint.getWaypointType().markerId), null, null, null);
+
+ //getSupportActionBar().setIcon(getResources().getDrawable(waypoint.getWaypointType().markerId));
+
+ details = new CacheDetailsCreator(getActivity(), waypointDetailsLayout);
+
+ //Waypoint geocode
+ details.add(R.string.cache_geocode, waypoint.getPrefix() + waypoint.getGeocode().substring(2));
+ details.addDistance(waypoint, waypointDistance);
+ waypointDistance = details.getValueView();
+ details.add(R.string.waypoint_note, waypoint.getNote());
+
+ buttonEdit.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View arg0) {
+ EditWaypointActivity.startActivityEditWaypoint(getActivity(), cache, waypoint.getId());
+ getActivity().finish();
+ }
+ });
+
+ details = new CacheDetailsCreator(getActivity(), cacheDetailsLayout);
+ details.add(R.string.cache_name, cache.getName());
+
+ addCacheDetails();
+
+ } catch (Exception e) {
+ Log.e("WaypointPopup.init", e);
+ }
+ }
+
+ @Override
+ public void navigateTo() {
+ NavigationAppFactory.startDefaultNavigationApplication(1, getActivity(), waypoint);
+ }
+
+ /**
+ * Tries to navigate to the {@link Geocache} of this activity.
+ */
+ @Override
+ public void startDefaultNavigation2() {
+ if (waypoint == null || waypoint.getCoords() == null) {
+ showToast(res.getString(R.string.cache_coordinates_no));
+ return;
+ }
+ NavigationAppFactory.startDefaultNavigationApplication(2, getActivity(), waypoint);
+ getActivity().finish();
+ }
+
+
+
+ @Override
+ public void showNavigationMenu() {
+ NavigationAppFactory.showNavigationMenu(getActivity(), null, waypoint, null);
+ }
+
+ @Override
+ protected Geopoint getCoordinates() {
+ if (waypoint == null) {
+ return null;
+ }
+ return waypoint.getCoords();
+ }
+
+ public static DialogFragment newInstance(String geocode, int waypointId) {
+
+ Bundle args = new Bundle();
+ args.putInt(WAYPOINT_ARG, waypointId);
+ args.putString(GEOCODE_ARG, geocode);
+
+ DialogFragment f = new WaypointPopupFragment();
+ f.setArguments(args);
+ f.setStyle(DialogFragment.STYLE_NO_TITLE,0);
+
+ return f;
+ }
+}
diff --git a/main/src/cgeo/geocaching/activity/AbstractActionBarActivity.java b/main/src/cgeo/geocaching/activity/AbstractActionBarActivity.java
new file mode 100644
index 0000000..a732f65
--- /dev/null
+++ b/main/src/cgeo/geocaching/activity/AbstractActionBarActivity.java
@@ -0,0 +1,34 @@
+package cgeo.geocaching.activity;
+
+import android.os.Bundle;
+
+/**
+ * Classes actually having an ActionBar (as opposed to the Dialog activities)
+ */
+public class AbstractActionBarActivity extends AbstractActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState, int resourceLayoutID) {
+ super.onCreate(savedInstanceState, resourceLayoutID);
+ initUpAction();
+ showProgress(false);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ initUpAction();
+ showProgress(false);
+ }
+
+
+ private void initUpAction() {
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ super.setTitle(title);
+ // reflect the title in the actionbar
+ ActivityMixin.setTitle(this, title);
+ }
+}
diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java
index 542dd05..e3df1f7 100644
--- a/main/src/cgeo/geocaching/activity/AbstractActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java
@@ -12,21 +12,31 @@ import cgeo.geocaching.utils.HtmlUtils;
import cgeo.geocaching.utils.TranslationUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import rx.Subscription;
+import rx.subscriptions.Subscriptions;
+
+import android.annotation.TargetApi;
import android.content.Intent;
import android.content.res.Resources;
+import android.nfc.NdefMessage;
+import android.nfc.NdefRecord;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcEvent;
+import android.os.Build;
import android.os.Bundle;
-import android.support.v4.app.FragmentActivity;
-import android.view.ContextMenu;
+import android.support.v7.app.ActionBarActivity;
+import android.support.v7.view.ActionMode;
+import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.view.Window;
import android.widget.EditText;
-import rx.Subscription;
-import rx.subscriptions.Subscriptions;
import java.util.Locale;
-public abstract class AbstractActivity extends FragmentActivity implements IAbstractActivity {
+public abstract class AbstractActivity extends ActionBarActivity implements IAbstractActivity {
protected CgeoApplication app = null;
protected Resources res = null;
@@ -41,15 +51,6 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
this.keepScreenOn = keepScreenOn;
}
- @Override
- final public void goHome(final View view) {
- ActivityMixin.goHome(this);
- }
-
- final protected void setTitle(final String title) {
- ActivityMixin.setTitle(this, title);
- }
-
final protected void showProgress(final boolean show) {
ActivityMixin.showProgress(this, show);
}
@@ -71,7 +72,18 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+
initializeCommonFields();
+
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ return ActivityMixin.navigateUp(this);
+ }
+ return super.onOptionsItemSelected(item);
}
public void onResume(final Subscription resumeSubscription) {
@@ -104,21 +116,14 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
}
protected void onCreate(final Bundle savedInstanceState, final int resourceLayoutID) {
- onCreate(savedInstanceState, resourceLayoutID, false);
- }
-
- protected void onCreate(final Bundle savedInstanceState, final int resourceLayoutID, boolean useDialogTheme) {
super.onCreate(savedInstanceState);
initializeCommonFields();
// non declarative part of layout
- if (useDialogTheme) {
- setTheme(ActivityMixin.getDialogTheme());
- } else {
- setTheme();
- }
+ setTheme();
+
setContentView(resourceLayoutID);
// create view variables
@@ -151,9 +156,8 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
new Keyboard(this).show(view);
}
- protected void buildDetailsContextMenu(final ContextMenu menu, final CharSequence clickedItemText, final CharSequence fieldTitle, final boolean copyOnly) {
- menu.setHeaderTitle(fieldTitle);
- getMenuInflater().inflate(R.menu.details_context, menu);
+ protected void buildDetailsContextMenu(final ActionMode actionMode, final Menu menu, final CharSequence clickedItemText, final CharSequence fieldTitle, final boolean copyOnly) {
+ actionMode.setTitle(fieldTitle);
menu.findItem(R.id.menu_translate_to_sys_lang).setVisible(!copyOnly);
if (!copyOnly) {
if (clickedItemText.length() > TranslationUtils.TRANSLATION_TEXT_LENGTH_WARN) {
@@ -165,27 +169,62 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
menu.findItem(R.id.menu_translate_to_english).setVisible(!copyOnly && !localeIsEnglish);
}
- protected boolean onClipboardItemSelected(final MenuItem item, final CharSequence clickedItemText) {
+ protected boolean onClipboardItemSelected(@NonNull final ActionMode actionMode, final MenuItem item, final CharSequence clickedItemText) {
switch (item.getItemId()) {
// detail fields
case R.id.menu_copy:
ClipboardUtils.copyToClipboard(clickedItemText);
showToast(res.getString(R.string.clipboard_copy_ok));
+ actionMode.finish();
return true;
case R.id.menu_translate_to_sys_lang:
TranslationUtils.startActivityTranslate(this, Locale.getDefault().getLanguage(), HtmlUtils.extractText(clickedItemText));
+ actionMode.finish();
return true;
case R.id.menu_translate_to_english:
TranslationUtils.startActivityTranslate(this, Locale.ENGLISH.getLanguage(), HtmlUtils.extractText(clickedItemText));
+ actionMode.finish();
return true;
case R.id.menu_cache_share_field:
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, clickedItemText.toString());
startActivity(Intent.createChooser(intent, res.getText(R.string.cache_share_field)));
+ actionMode.finish();
return true;
default:
return false;
}
}
+
+ // Do not support older devices than Android 4.0
+ // Although there even are 2.3 devices (Nexus S)
+ // these are so few that we don't want to deal with the older (non Android Beam) API
+
+ public interface ActivitySharingInterface {
+ /** Return an URL that represent the current activity for sharing */
+ public String getUri();
+ }
+
+ protected void initializeAndroidBeam(ActivitySharingInterface sharingInterface) {
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ initializeICSAndroidBeam(sharingInterface);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+ protected void initializeICSAndroidBeam(final ActivitySharingInterface sharingInterface) {
+ NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
+ if (nfcAdapter == null) {
+ return;
+ }
+ nfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() {
+ @Override
+ public NdefMessage createNdefMessage(NfcEvent event) {
+ NdefRecord record = NdefRecord.createUri(sharingInterface.getUri());
+ return new NdefMessage(new NdefRecord[]{record});
+ }
+ }, this);
+
+ }
}
diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
index a5d5c14..eac191a 100644
--- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
@@ -4,10 +4,10 @@ import cgeo.geocaching.CgeoApplication;
import android.content.res.Resources;
import android.os.Bundle;
-import android.support.v4.app.FragmentListActivity;
-import android.view.View;
+import android.view.MenuItem;
+import android.view.Window;
-public abstract class AbstractListActivity extends FragmentListActivity implements
+public abstract class AbstractListActivity extends ActionBarListActivity implements
IAbstractActivity {
private boolean keepScreenOn = false;
@@ -23,11 +23,6 @@ public abstract class AbstractListActivity extends FragmentListActivity implemen
this.keepScreenOn = keepScreenOn;
}
- @Override
- final public void goHome(View view) {
- ActivityMixin.goHome(this);
- }
-
final public void showProgress(final boolean show) {
ActivityMixin.showProgress(this, show);
}
@@ -49,7 +44,22 @@ public abstract class AbstractListActivity extends FragmentListActivity implemen
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+
initializeCommonFields();
+ initUpAction();
+ }
+
+ protected void initUpAction() {
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId()== android.R.id.home) {
+ return ActivityMixin.navigateUp(this);
+ }
+ return super.onOptionsItemSelected(item);
}
private void initializeCommonFields() {
diff --git a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
index 6e2900d..e98c935 100644
--- a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
@@ -30,7 +30,7 @@ import java.util.Map;
* Enum listing all available pages of this activity. The pages available at a certain point of time are
* defined by overriding {@link #getOrderedPages()}.
*/
-public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends AbstractActivity {
+public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends AbstractActionBarActivity {
/**
* A {@link List} of all available pages.
diff --git a/main/src/cgeo/geocaching/activity/ActionBarListActivity.java b/main/src/cgeo/geocaching/activity/ActionBarListActivity.java
new file mode 100644
index 0000000..07c7ec3
--- /dev/null
+++ b/main/src/cgeo/geocaching/activity/ActionBarListActivity.java
@@ -0,0 +1,34 @@
+package cgeo.geocaching.activity;
+
+import android.support.v7.app.ActionBarActivity;
+import android.widget.HeaderViewListAdapter;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+/**
+ * Compatbility Class until cgeo switches from ListActivities to ListFragments
+ */
+public class ActionBarListActivity extends ActionBarActivity {
+
+ private ListView mListView;
+ protected ListView getListView() {
+ if (mListView == null) {
+ mListView = (ListView) findViewById(android.R.id.list);
+ }
+ return mListView;
+ }
+
+ protected void setListAdapter(ListAdapter adapter) {
+ getListView().setAdapter(adapter);
+ }
+
+ protected ListAdapter getListAdapter() {
+ ListAdapter adapter = getListView().getAdapter();
+ if (adapter instanceof HeaderViewListAdapter) {
+ return ((HeaderViewListAdapter)adapter).getWrappedAdapter();
+ }
+ return adapter;
+ }
+}
+
+
diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java
index bfd45da..e2181d0 100644
--- a/main/src/cgeo/geocaching/activity/ActivityMixin.java
+++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java
@@ -1,55 +1,45 @@
package cgeo.geocaching.activity;
-import cgeo.geocaching.MainActivity;
import cgeo.geocaching.R;
-import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.settings.Settings;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
-import android.os.Build;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.NavUtils;
+import android.support.v4.app.TaskStackBuilder;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.ActionBarActivity;
import android.view.Gravity;
-import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
-import android.widget.ProgressBar;
-import android.widget.TextView;
import android.widget.Toast;
public final class ActivityMixin {
- public final static void goHome(final Activity fromActivity) {
- final Intent intent = new Intent(fromActivity, MainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-
- fromActivity.startActivity(intent);
- fromActivity.finish();
- }
-
public static void setTitle(final Activity activity, final CharSequence text) {
if (StringUtils.isBlank(text)) {
return;
}
- final TextView title = (TextView) activity.findViewById(R.id.actionbar_title);
- if (title != null) {
- title.setText(text);
+ if (activity instanceof ActionBarActivity) {
+ final ActionBar actionBar = ((ActionBarActivity) activity).getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setTitle(text);
+ }
}
}
- public static void showProgress(final Activity activity, final boolean show) {
+ public static void showProgress(final ActionBarActivity activity, final boolean show) {
if (activity == null) {
return;
}
- final ProgressBar progress = (ProgressBar) activity.findViewById(R.id.actionbar_progress);
- if (show) {
- progress.setVisibility(View.VISIBLE);
- } else {
- progress.setVisibility(View.GONE);
- }
+ activity.setSupportProgressBarIndeterminateVisibility(show);
+
}
public static void setTheme(final Activity activity) {
@@ -62,10 +52,10 @@ public final class ActivityMixin {
public static int getDialogTheme() {
// Light theme dialogs don't work on Android Api < 11
- if (Settings.isLightSkin() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ // The compat theme should fix this
+ if (Settings.isLightSkin()) {
return R.style.popup_light;
}
-
return R.style.popup_dark;
}
@@ -98,7 +88,12 @@ public final class ActivityMixin {
}
public static void invalidateOptionsMenu(Activity activity) {
- Compatibility.invalidateOptionsMenu(activity);
+ if (activity instanceof ActionBarActivity) {
+ ((ActionBarActivity) activity).supportInvalidateOptionsMenu();
+ }
+ else {
+ ActivityCompat.invalidateOptionsMenu(activity);
+ }
}
/**
@@ -127,4 +122,27 @@ public final class ActivityMixin {
int newCursor = moveCursor ? start + completeText.length() : start;
editText.setSelection(newCursor);
}
+
+ public static boolean navigateUp(@NonNull final Activity activity) {
+ // see http://developer.android.com/training/implementing-navigation/ancestral.html
+ Intent upIntent = NavUtils.getParentActivityIntent(activity);
+ if (upIntent == null) {
+ activity.finish();
+ return true;
+ }
+ if (NavUtils.shouldUpRecreateTask(activity, upIntent)) {
+ // This activity is NOT part of this app's task, so create a new task
+ // when navigating up, with a synthesized back stack.
+ TaskStackBuilder.create(activity)
+ // Add all of this activity's parents to the back stack
+ .addNextIntentWithParentStack(upIntent)
+ // Navigate up to the closest parent
+ .startActivities();
+ } else {
+ // This activity is part of this app's task, so simply
+ // navigate up to the logical parent activity.
+ NavUtils.navigateUpTo(activity, upIntent);
+ }
+ return true;
+ }
}
diff --git a/main/src/cgeo/geocaching/activity/IAbstractActivity.java b/main/src/cgeo/geocaching/activity/IAbstractActivity.java
index 7ca2322..4fb6a2a 100644
--- a/main/src/cgeo/geocaching/activity/IAbstractActivity.java
+++ b/main/src/cgeo/geocaching/activity/IAbstractActivity.java
@@ -1,11 +1,8 @@
package cgeo.geocaching.activity;
-import android.view.View;
public interface IAbstractActivity {
- public void goHome(View view);
-
public void showToast(String text);
public void showShortToast(String text);
diff --git a/main/src/cgeo/geocaching/activity/SimpleWebviewActivity.java b/main/src/cgeo/geocaching/activity/SimpleWebviewActivity.java
new file mode 100644
index 0000000..83b9281
--- /dev/null
+++ b/main/src/cgeo/geocaching/activity/SimpleWebviewActivity.java
@@ -0,0 +1,32 @@
+package cgeo.geocaching.activity;
+
+import cgeo.geocaching.R;
+
+import android.annotation.SuppressLint;
+import android.os.Bundle;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+public class SimpleWebviewActivity extends AbstractActionBarActivity {
+
+ private WebView webview;
+
+ class SimplelWebviewClient extends WebViewClient {
+ @Override
+ public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
+ webview.loadUrl(url);
+ return true;
+ }
+ }
+
+ @SuppressLint("SetJavaScriptEnabled")
+ @Override
+ public void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState, R.layout.internal_browser);
+
+ webview = (WebView) findViewById(R.id.webview);
+ webview.getSettings().setJavaScriptEnabled(true);
+ webview.setWebViewClient(new SimplelWebviewClient());
+ webview.loadUrl(String.valueOf(getIntent().getData()));
+ }
+}
diff --git a/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java b/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java
deleted file mode 100644
index 34c9074..0000000
--- a/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package cgeo.geocaching.apps.cache;
-
-import cgeo.geocaching.Geocache;
-import cgeo.geocaching.R;
-import cgeo.geocaching.enumerations.CacheAttribute;
-
-public class CacheBeaconApp extends AbstractGeneralApp {
-
- public CacheBeaconApp() {
- super(getString(R.string.cache_menu_cachebeacon), R.id.cache_app_cache_beacon, "de.fun2code.android.cachebeacon");
- }
-
- @Override
- public boolean isEnabled(Geocache cache) {
- return cache.hasAttribute(CacheAttribute.WIRELESSBEACON, true);
- }
-
-}
diff --git a/main/src/cgeo/geocaching/apps/cache/GccApp.java b/main/src/cgeo/geocaching/apps/cache/GccApp.java
deleted file mode 100644
index 4423977..0000000
--- a/main/src/cgeo/geocaching/apps/cache/GccApp.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package cgeo.geocaching.apps.cache;
-
-import cgeo.geocaching.R;
-import cgeo.geocaching.utils.ProcessUtils;
-
-import android.content.Intent;
-
-public class GccApp extends AbstractGeneralApp {
- private static final String PACKAGE = "eisbehr.gcc";
- private static final String PACKAGE_PRO = "eisbehr.gcc.pro";
-
- public GccApp() {
- super(getString(R.string.cache_menu_gcc), R.id.cache_app_gcc, null);
- }
-
- @Override
- public boolean isInstalled() {
- return ProcessUtils.isLaunchable(PACKAGE) || ProcessUtils.isLaunchable(PACKAGE_PRO);
- }
-
- @Override
- protected Intent getLaunchIntent() {
- if (ProcessUtils.isLaunchable(PACKAGE_PRO)) {
- return ProcessUtils.getLaunchIntent(PACKAGE_PRO);
- }
- return ProcessUtils.getLaunchIntent(PACKAGE);
- }
-}
diff --git a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java
index 79a5975..b2a2cad 100644
--- a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java
@@ -3,14 +3,34 @@ package cgeo.geocaching.apps.cache;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.enumerations.CacheType;
+import cgeo.geocaching.utils.TextUtils;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+
+import java.util.regex.Pattern;
public class WhereYouGoApp extends AbstractGeneralApp {
+ private static final Pattern PATTERN_CARTRIDGE = Pattern.compile("(" + Pattern.quote("http://www.wherigo.com/cartridge/details.aspx?") + ".*?)" + Pattern.quote("\""));
+
public WhereYouGoApp() {
super(getString(R.string.cache_menu_whereyougo), R.id.cache_app_whereyougo, "menion.android.whereyougo");
}
@Override
public boolean isEnabled(Geocache cache) {
- return cache.getType() == CacheType.WHERIGO;
+ return cache.getType() == CacheType.WHERIGO && StringUtils.isNotEmpty(getWhereIGoUrl(cache));
+ }
+
+ @Override
+ public void navigate(Activity activity, Geocache cache) {
+ activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getWhereIGoUrl(cache))));
+ }
+
+ protected static String getWhereIGoUrl(Geocache cache) {
+ return TextUtils.getMatch(cache.getDescription(), PATTERN_CARTRIDGE, null);
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
index c42c2a2..a2a5803 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
@@ -4,7 +4,7 @@ import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.ILogable;
import cgeo.geocaching.R;
-import cgeo.geocaching.StaticMapsActivity;
+import cgeo.geocaching.StaticMapsActivity_;
import cgeo.geocaching.StaticMapsProvider;
import cgeo.geocaching.Waypoint;
import cgeo.geocaching.activity.ActivityMixin;
@@ -49,7 +49,11 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat
}
final String geocode = StringUtils.upperCase(logable.getGeocode());
- StaticMapsActivity.startActivity(activity, geocode, download, waypoint);
+ StaticMapsActivity_.IntentBuilder_ builder = StaticMapsActivity_.intent(activity).geocode(geocode).download(download);
+ if (waypoint != null) {
+ builder.waypointId(waypoint.getId());
+ }
+ builder.start();
return true;
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
index 19b5e02..e9bdb74 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
@@ -13,22 +13,22 @@ class DownloadStaticMapsApp extends AbstractStaticMapsApp {
}
@Override
- public boolean isEnabled(Geocache cache) {
- return !cache.hasStaticMap();
+ public boolean isEnabled(final Geocache cache) {
+ return cache.isOffline() && !cache.hasStaticMap();
}
@Override
- public boolean isEnabled(Waypoint waypoint) {
+ public boolean isEnabled(final Waypoint waypoint) {
return !hasStaticMap(waypoint);
}
@Override
- public void navigate(Activity activity, Geocache cache) {
+ public void navigate(final Activity activity, final Geocache cache) {
invokeStaticMaps(activity, cache, null, true);
}
@Override
- public void navigate(Activity activity, Waypoint waypoint) {
+ public void navigate(final Activity activity, final Waypoint waypoint) {
invokeStaticMaps(activity, null, waypoint, true);
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
index 3177a29..6120116 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
@@ -7,8 +7,6 @@ import cgeo.geocaching.Waypoint;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.apps.AbstractAppFactory;
import cgeo.geocaching.apps.App;
-import cgeo.geocaching.apps.cache.CacheBeaconApp;
-import cgeo.geocaching.apps.cache.GccApp;
import cgeo.geocaching.apps.cache.WhereYouGoApp;
import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationBikeApp;
import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationDrivingApp;
@@ -69,8 +67,6 @@ public final class NavigationAppFactory extends AbstractAppFactory {
*/
GOOGLE_MAPS_DIRECTIONS(new GoogleMapsDirectionApp(), 13, R.string.pref_navigation_menu_google_maps_directions),
- CACHE_BEACON(new CacheBeaconApp(), 14, R.string.pref_navigation_menu_cache_beacon),
- GCC(new GccApp(), 15, R.string.pref_navigation_menu_gcc),
WHERE_YOU_GO(new WhereYouGoApp(), 16, R.string.pref_navigation_menu_where_you_go),
PEBBLE(new PebbleApp(), 17, R.string.pref_navigation_menu_pebble),
MAPSWITHME(new MapsWithMeApp(), 22, R.string.pref_navigation_menu_mapswithme);
@@ -182,7 +178,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
builder.setTitle(R.string.cache_menu_navigate);
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int item) {
+ public void onClick(final DialogInterface dialog, final int item) {
final NavigationAppsEnum selectedItem = adapter.getItem(item);
invokeNavigation(activity, cache, waypoint, destination, selectedItem.app);
}
@@ -230,27 +226,27 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* @param cache
* @return
*/
- public static boolean onMenuItemSelected(final MenuItem item, Activity activity, Geocache cache) {
+ public static boolean onMenuItemSelected(final MenuItem item, final Activity activity, final Geocache cache) {
final App menuItem = getAppFromMenuItem(item);
navigateCache(activity, cache, menuItem);
return menuItem != null;
}
- private static void navigateCache(Activity activity, Geocache cache, @Nullable App app) {
+ private static void navigateCache(final Activity activity, final Geocache cache, @Nullable final App app) {
if (app instanceof CacheNavigationApp) {
final CacheNavigationApp cacheApp = (CacheNavigationApp) app;
cacheApp.navigate(activity, cache);
}
}
- private static void navigateWaypoint(Activity activity, Waypoint waypoint, @Nullable App app) {
+ private static void navigateWaypoint(final Activity activity, final Waypoint waypoint, @Nullable final App app) {
if (app instanceof WaypointNavigationApp) {
final WaypointNavigationApp waypointApp = (WaypointNavigationApp) app;
waypointApp.navigate(activity, waypoint);
}
}
- private static void navigateGeopoint(Activity activity, Geopoint destination, App app) {
+ private static void navigateGeopoint(final Activity activity, final Geopoint destination, final App app) {
if (app instanceof GeopointNavigationApp) {
final GeopointNavigationApp geopointApp = (GeopointNavigationApp) app;
geopointApp.navigate(activity, destination);
@@ -258,7 +254,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
}
@Nullable
- private static App getAppFromMenuItem(MenuItem item) {
+ private static App getAppFromMenuItem(final MenuItem item) {
final int id = item.getItemId();
for (final NavigationAppsEnum navApp : NavigationAppsEnum.values()) {
if (navApp.id == id) {
@@ -276,7 +272,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* @param activity
* @param cache
*/
- public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, Geocache cache) {
+ public static void startDefaultNavigationApplication(final int defaultNavigation, final Activity activity, final Geocache cache) {
if (cache == null || cache.getCoords() == null) {
ActivityMixin.showToast(activity, CgeoApplication.getInstance().getString(R.string.err_location_unknown));
return;
@@ -285,7 +281,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
navigateCache(activity, cache, getDefaultNavigationApplication(defaultNavigation));
}
- private static App getDefaultNavigationApplication(int defaultNavigation) {
+ private static App getDefaultNavigationApplication(final int defaultNavigation) {
if (defaultNavigation == 2) {
return getNavigationAppForId(Settings.getDefaultNavigationTool2());
}
@@ -298,7 +294,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* @param activity
* @param waypoint
*/
- public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, Waypoint waypoint) {
+ public static void startDefaultNavigationApplication(final int defaultNavigation, final Activity activity, final Waypoint waypoint) {
if (waypoint == null || waypoint.getCoords() == null) {
ActivityMixin.showToast(activity, CgeoApplication.getInstance().getString(R.string.err_location_unknown));
return;
@@ -312,7 +308,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* @param activity
* @param destination
*/
- public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, final Geopoint destination) {
+ public static void startDefaultNavigationApplication(final int defaultNavigation, final Activity activity, final Geopoint destination) {
if (destination == null) {
ActivityMixin.showToast(activity, CgeoApplication.getInstance().getString(R.string.err_location_unknown));
return;
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
index da988aa..024bf37 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
@@ -23,8 +23,8 @@ class NavigonApp extends AbstractPointNavigationApp {
/*
* Long/Lat are float values in decimal degree format (+-DDD.DDDDD).
* Example:
- * intent.putExtra(INTENT_EXTRA_KEY_LATITUDE, 46.12345f);
- * intent.putExtra(INTENT_EXTRA_KEY_LONGITUDE, 23.12345f);
+ * intent.putExtra(INTENT_EXTRA_KEY_LATITUDE, 46.12345f)
+ * intent.putExtra(INTENT_EXTRA_KEY_LONGITUDE, 23.12345f)
*/
intent.putExtra(INTENT_EXTRA_KEY_LATITUDE, (float) point.getLatitude());
intent.putExtra(INTENT_EXTRA_KEY_LONGITUDE, (float) point.getLongitude());
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java b/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
index 9e1b3f0..5151088 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
@@ -13,22 +13,22 @@ class StaticMapApp extends AbstractStaticMapsApp {
}
@Override
- public boolean isEnabled(Geocache cache) {
- return cache.hasStaticMap();
+ public boolean isEnabled(final Geocache cache) {
+ return cache.isOffline() && cache.hasStaticMap();
}
@Override
- public boolean isEnabled(Waypoint waypoint) {
+ public boolean isEnabled(final Waypoint waypoint) {
return hasStaticMap(waypoint);
}
@Override
- public void navigate(Activity activity, Geocache cache) {
+ public void navigate(final Activity activity, final Geocache cache) {
invokeStaticMaps(activity, cache, null, false);
}
@Override
- public void navigate(Activity activity, Waypoint waypoint) {
+ public void navigate(final Activity activity, final Waypoint waypoint) {
invokeStaticMaps(activity, null, waypoint, false);
}
}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java
deleted file mode 100644
index a425ee5..0000000
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package cgeo.geocaching.compatibility;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-
-/**
- * Android level 11 support
- */
-@TargetApi(11)
-public class AndroidLevel11 implements AndroidLevel11Interface {
-
- @Override
- public void invalidateOptionsMenu(final Activity activity) {
- activity.invalidateOptionsMenu();
- }
-
-}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java
deleted file mode 100644
index 6a23ed5..0000000
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package cgeo.geocaching.compatibility;
-
-import android.app.Activity;
-
-/**
- * implement level 11 API using older methods
- */
-public class AndroidLevel11Emulation implements AndroidLevel11Interface {
-
- @Override
- public void invalidateOptionsMenu(final Activity activity) {
- // do nothing
- }
-
-}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java
deleted file mode 100644
index 236e92d..0000000
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package cgeo.geocaching.compatibility;
-
-import android.app.Activity;
-
-public interface AndroidLevel11Interface {
- public void invalidateOptionsMenu(final Activity activity);
-
-}
diff --git a/main/src/cgeo/geocaching/compatibility/Compatibility.java b/main/src/cgeo/geocaching/compatibility/Compatibility.java
index a293cfd..54e2966 100644
--- a/main/src/cgeo/geocaching/compatibility/Compatibility.java
+++ b/main/src/cgeo/geocaching/compatibility/Compatibility.java
@@ -8,35 +8,33 @@ import android.os.Build;
public final class Compatibility {
- private final static int sdkVersion = Build.VERSION.SDK_INT;
+ private static final int SDK_VERSION = Build.VERSION.SDK_INT;
- private final static AndroidLevel11Interface level11;
- private final static AndroidLevel13Interface level13;
- private final static AndroidLevel19Interface level19;
+ private static final AndroidLevel13Interface LEVEL_13;
+ private static final AndroidLevel19Interface LEVEL_19;
static {
- level11 = sdkVersion >= 11 ? new AndroidLevel11() : new AndroidLevel11Emulation();
- level13 = sdkVersion >= 13 ? new AndroidLevel13() : new AndroidLevel13Emulation();
- level19 = sdkVersion >= 19 ? new AndroidLevel19() : new AndroidLevel19Emulation();
+ LEVEL_13 = SDK_VERSION >= 13 ? new AndroidLevel13() : new AndroidLevel13Emulation();
+ LEVEL_19 = SDK_VERSION >= 19 ? new AndroidLevel19() : new AndroidLevel19Emulation();
}
- public static void invalidateOptionsMenu(final Activity activity) {
- level11.invalidateOptionsMenu(activity);
+ private Compatibility() {
+ // utility class
}
public static int getDisplayWidth() {
- return level13.getDisplayWidth();
+ return LEVEL_13.getDisplayWidth();
}
public static Point getDisplaySize() {
- return level13.getDisplaySize();
+ return LEVEL_13.getDisplaySize();
}
public static void importGpxFromStorageAccessFramework(final @NonNull Activity activity, int requestCodeImportGpx) {
- level19.importGpxFromStorageAccessFramework(activity, requestCodeImportGpx);
+ LEVEL_19.importGpxFromStorageAccessFramework(activity, requestCodeImportGpx);
}
public static boolean isStorageAccessFrameworkAvailable() {
- return sdkVersion >= 19;
+ return SDK_VERSION >= 19;
}
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index 925f6f0..294e969 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -50,7 +50,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
private static final String CACHE_URL_SHORT = "http://coord.info/";
// Double slash is used to force open in browser
- private static final String CACHE_URL_LONG = "http://www.geocaching.com//seek/cache_details.aspx?wp=";
+ private static final String CACHE_URL_LONG = "http://www.geocaching.com/seek/cache_details.aspx?wp=";
/**
* Pocket queries downloaded from the website use a numeric prefix. The pocket query creator Android app adds a
* verbatim "pocketquery" prefix.
@@ -192,8 +192,8 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
@Override
public boolean isOwner(final ICache cache) {
- return StringUtils.equalsIgnoreCase(cache.getOwnerUserId(), Settings.getUsername());
-
+ final String user = Settings.getUsername();
+ return StringUtils.isNotEmpty(user) && StringUtils.equalsIgnoreCase(cache.getOwnerUserId(), user);
}
@Override
diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index dc2408f..dd81507 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCMap.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -146,30 +146,6 @@ public class GCMap {
throw new JSONException("No data inside JSON");
}
- /*
- * Optimization: the grid can get ignored. The keys are the grid position in the format x_y
- * It's not used at the moment due to optimizations
- * But maybe we need it some day...
- *
- * // attach all keys with the cache positions in the tile
- * Map<String, UTFGridPosition> keyPositions = new HashMap<String, UTFGridPosition>(); // JSON key, (x/y) in
- * grid
- * for (int y = 0; y < grid.length(); y++) {
- * String rowUTF8 = grid.getString(y);
- * if (rowUTF8.length() != (UTFGrid.GRID_MAXX + 1)) {
- * throw new JSONException("Grid has wrong size");
- * }
- *
- * for (int x = 0; x < UTFGrid.GRID_MAXX; x++) {
- * char c = rowUTF8.charAt(x);
- * if (c != ' ') {
- * short id = UTFGrid.getUTFGridId(c);
- * keyPositions.put(keys.getString(id), new UTFGridPosition(x, y));
- * }
- * }
- * }
- */
-
// iterate over the data and construct all caches in this tile
Map<String, List<UTFGridPosition>> positions = new HashMap<String, List<UTFGridPosition>>(); // JSON id as key
Map<String, List<UTFGridPosition>> singlePositions = new HashMap<String, List<UTFGridPosition>>(); // JSON id as key
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index ec3a4bd..8114d2a 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -47,6 +47,14 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import rx.Observable;
+import rx.Observable.OnSubscribe;
+import rx.Subscriber;
+import rx.functions.Action1;
+import rx.functions.Func0;
+import rx.functions.Func2;
+import rx.schedulers.Schedulers;
+
import android.net.Uri;
import android.text.Html;
@@ -136,7 +144,6 @@ public abstract class GCParser {
while (matcherGuidAndDisabled.find()) {
if (matcherGuidAndDisabled.groupCount() > 0) {
- //cache.setGuid(matcherGuidAndDisabled.group(1));
if (matcherGuidAndDisabled.group(2) != null) {
cache.setName(Html.fromHtml(matcherGuidAndDisabled.group(2).trim()).toString());
}
@@ -335,32 +342,50 @@ public abstract class GCParser {
}
static SearchResult parseCache(final String page, final CancellableHandler handler) {
- final SearchResult searchResult = parseCacheFromText(page, handler);
+ final ImmutablePair<StatusCode, Geocache> parsed = parseCacheFromText(page, handler);
// attention: parseCacheFromText already stores implicitly through searchResult.addCache
- if (searchResult != null && !searchResult.getGeocodes().isEmpty()) {
- final Geocache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
- if (cache == null) {
- return null;
- }
- getExtraOnlineInfo(cache, page, handler);
- // too late: it is already stored through parseCacheFromText
- cache.setDetailedUpdatedNow();
- if (CancellableHandler.isCancelled(handler)) {
- return null;
- }
+ if (parsed.left != StatusCode.NO_ERROR) {
+ return new SearchResult(parsed.left);
+ }
+
+ final Geocache cache = parsed.right;
+ getExtraOnlineInfo(cache, page, handler);
+ // too late: it is already stored through parseCacheFromText
+ cache.setDetailedUpdatedNow();
+ if (CancellableHandler.isCancelled(handler)) {
+ return null;
+ }
- // save full detailed caches
- CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_cache);
- DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ // save full detailed caches
+ CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_cache);
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
- // update progress message so user knows we're still working. This is more of a place holder than
- // actual indication of what the program is doing
- CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_render);
+ // update progress message so user knows we're still working. This is more of a place holder than
+ // actual indication of what the program is doing
+ CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_render);
+ return new SearchResult(cache);
+ }
+
+ static SearchResult parseAndSaveCacheFromText(final String page, @Nullable final CancellableHandler handler) {
+ final ImmutablePair<StatusCode, Geocache> parsed = parseCacheFromText(page, handler);
+ final SearchResult result = new SearchResult(parsed.left);
+ if (parsed.left == StatusCode.NO_ERROR) {
+ result.addAndPutInCache(Collections.singletonList(parsed.right));
+ DataStore.saveLogsWithoutTransaction(parsed.right.getGeocode(), getLogsFromDetails(page).toBlocking().toIterable());
}
- return searchResult;
+ return result;
}
- static SearchResult parseCacheFromText(final String pageIn, final CancellableHandler handler) {
+ /**
+ * Parse cache from text and return either an error code or a cache object in a pair. Note that inline logs are
+ * not parsed nor saved, while the cache itself is.
+ *
+ * @param pageIn the page text to parse
+ * @param handler the handler to send the progress notifications to
+ * @return a pair, with a {@link StatusCode} on the left, and a non-nulll cache objet on the right
+ * iff the status code is {@link StatusCode.NO_ERROR}.
+ */
+ static private ImmutablePair<StatusCode, Geocache> parseCacheFromText(final String pageIn, @Nullable final CancellableHandler handler) {
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_details);
if (StringUtils.isBlank(pageIn)) {
@@ -368,22 +393,17 @@ public abstract class GCParser {
return null;
}
- final SearchResult searchResult = new SearchResult();
-
if (pageIn.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) {
- searchResult.setError(StatusCode.UNPUBLISHED_CACHE);
- return searchResult;
+ return ImmutablePair.of(StatusCode.UNPUBLISHED_CACHE, null);
}
if (pageIn.contains(GCConstants.STRING_PREMIUMONLY_1) || pageIn.contains(GCConstants.STRING_PREMIUMONLY_2)) {
- searchResult.setError(StatusCode.PREMIUM_ONLY);
- return searchResult;
+ return ImmutablePair.of(StatusCode.PREMIUM_ONLY, null);
}
final String cacheName = Html.fromHtml(TextUtils.getMatch(pageIn, GCConstants.PATTERN_NAME, true, "")).toString();
if (GCConstants.STRING_UNKNOWN_ERROR.equalsIgnoreCase(cacheName)) {
- searchResult.setError(StatusCode.UNKNOWN_ERROR);
- return searchResult;
+ return ImmutablePair.of(StatusCode.UNKNOWN_ERROR, null);
}
// first handle the content with line breaks, then trim everything for easier matching and reduced memory consumption in parsed fields
@@ -726,14 +746,11 @@ public abstract class GCParser {
// last check for necessary cache conditions
if (StringUtils.isBlank(cache.getGeocode())) {
- searchResult.setError(StatusCode.UNKNOWN_ERROR);
- return searchResult;
+ return ImmutablePair.of(StatusCode.UNKNOWN_ERROR, null);
}
cache.setDetailedUpdatedNow();
- searchResult.addAndPutInCache(Collections.singletonList(cache));
- DataStore.saveLogsWithoutTransaction(cache.getGeocode(), getLogsFromDetails(page, false));
- return searchResult;
+ return ImmutablePair.of(StatusCode.NO_ERROR, cache);
}
private static String getNumberString(final String numberWithPunctuation) {
@@ -1619,116 +1636,142 @@ public abstract class GCParser {
*
* @param page
* the text of the details page
- * @param friends
- * return friends logs only (will require a network request)
- * @return a list of log entries or <code>null</code> if the logs could not be retrieved
+ * @return a list of log entries which will be empty if the logs could not be retrieved
*
*/
- @Nullable
- private static List<LogEntry> getLogsFromDetails(final String page, final boolean friends) {
- String rawResponse;
+ @NonNull
+ private static Observable<LogEntry> getLogsFromDetails(final String page) {
+ // extract embedded JSON data from page
+ return parseLogs(false, TextUtils.getMatch(page, GCConstants.PATTERN_LOGBOOK, ""));
+ }
- if (friends) {
- final MatcherWrapper userTokenMatcher = new MatcherWrapper(GCConstants.PATTERN_USERTOKEN, page);
- if (!userTokenMatcher.find()) {
- Log.e("GCParser.loadLogsFromDetails: unable to extract userToken");
- return null;
- }
+ private enum SpecialLogs {
+ FRIENDS("sf"),
+ OWN("sp");
- final String userToken = userTokenMatcher.group(1);
- final Parameters params = new Parameters(
- "tkn", userToken,
- "idx", "1",
- "num", String.valueOf(GCConstants.NUMBER_OF_LOGS),
- "decrypt", "true",
- // "sp", Boolean.toString(personal), // personal logs
- "sf", Boolean.toString(friends));
+ final String paramName;
- final HttpResponse response = Network.getRequest("http://www.geocaching.com/seek/geocache.logbook", params);
- if (response == null) {
- Log.e("GCParser.loadLogsFromDetails: cannot log logs, response is null");
- return null;
- }
- final int statusCode = response.getStatusLine().getStatusCode();
- if (statusCode != 200) {
- Log.e("GCParser.loadLogsFromDetails: error " + statusCode + " when requesting log information");
- return null;
- }
- rawResponse = Network.getResponseData(response);
- if (rawResponse == null) {
- Log.e("GCParser.loadLogsFromDetails: unable to read whole response");
- return null;
- }
- } else {
- // extract embedded JSON data from page
- rawResponse = TextUtils.getMatch(page, GCConstants.PATTERN_LOGBOOK, "");
+ SpecialLogs(String paramName) {
+ this.paramName = paramName;
}
- return parseLogs(friends, rawResponse);
+ private String getParamName() {
+ return this.paramName;
+ }
}
- private static List<LogEntry> parseLogs(final boolean friends, String rawResponse) {
- final List<LogEntry> logs = new ArrayList<LogEntry>();
-
- // for non logged in users the log book is not shown
- if (StringUtils.isBlank(rawResponse)) {
- return logs;
- }
+ /**
+ * Extract special logs (friends, own) through seperate request.
+ *
+ * @param page
+ * The page to extrat userToken from
+ * @param logType
+ * The logType to request
+ * @return Observable<LogEntry> The logs
+ */
+ private static Observable<LogEntry> getSpecialLogs(final String page, final SpecialLogs logType) {
+ return Observable.defer(new Func0<Observable<? extends LogEntry>>() {
+ @Override
+ public Observable<? extends LogEntry> call() {
+ final MatcherWrapper userTokenMatcher = new MatcherWrapper(GCConstants.PATTERN_USERTOKEN, page);
+ if (!userTokenMatcher.find()) {
+ Log.e("GCParser.loadLogsFromDetails: unable to extract userToken");
+ return Observable.empty();
+ }
- try {
- final JSONObject resp = new JSONObject(rawResponse);
- if (!resp.getString("status").equals("success")) {
- Log.e("GCParser.loadLogsFromDetails: status is " + resp.getString("status"));
- return null;
+ final String userToken = userTokenMatcher.group(1);
+ final Parameters params = new Parameters(
+ "tkn", userToken,
+ "idx", "1",
+ "num", String.valueOf(GCConstants.NUMBER_OF_LOGS),
+ logType.getParamName(), Boolean.toString(Boolean.TRUE),
+ "decrypt", "true");
+ final HttpResponse response = Network.getRequest("http://www.geocaching.com/seek/geocache.logbook", params);
+ if (response == null) {
+ Log.e("GCParser.loadLogsFromDetails: cannot log logs, response is null");
+ return Observable.empty();
+ }
+ final int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode != 200) {
+ Log.e("GCParser.loadLogsFromDetails: error " + statusCode + " when requesting log information");
+ return Observable.empty();
+ }
+ String rawResponse = Network.getResponseData(response);
+ if (rawResponse == null) {
+ Log.e("GCParser.loadLogsFromDetails: unable to read whole response");
+ return Observable.empty();
+ }
+ return parseLogs(true, rawResponse);
}
+ }).subscribeOn(Schedulers.io());
+ }
- final JSONArray data = resp.getJSONArray("data");
+ private static Observable<LogEntry> parseLogs(final boolean markAsFriendsLog, final String rawResponse) {
+ 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;
+ }
- for (int index = 0; index < data.length(); index++) {
- final JSONObject entry = data.getJSONObject(index);
+ try {
+ final JSONObject resp = new JSONObject(rawResponse);
+ if (!resp.getString("status").equals("success")) {
+ Log.e("GCParser.loadLogsFromDetails: status is " + resp.getString("status"));
+ subscriber.onCompleted();
+ return;
+ }
- // FIXME: use the "LogType" field instead of the "LogTypeImage" one.
- final String logIconNameExt = entry.optString("LogTypeImage", ".gif");
- final String logIconName = logIconNameExt.substring(0, logIconNameExt.length() - 4);
+ final JSONArray data = resp.getJSONArray("data");
- long date = 0;
- try {
- date = GCLogin.parseGcCustomDate(entry.getString("Visited")).getTime();
- } catch (final ParseException e) {
- Log.e("GCParser.loadLogsFromDetails: failed to parse log date.");
- }
+ for (int index = 0; index < data.length(); index++) {
+ final JSONObject entry = data.getJSONObject(index);
- // TODO: we should update our log data structure to be able to record
- // proper coordinates, and make them clickable. In the meantime, it is
- // better to integrate those coordinates into the text rather than not
- // display them at all.
- final String latLon = entry.getString("LatLonString");
- final String logText = (StringUtils.isEmpty(latLon) ? "" : (latLon + "<br/><br/>")) + TextUtils.removeControlCharacters(entry.getString("LogText"));
- final LogEntry logDone = new LogEntry(
- TextUtils.removeControlCharacters(entry.getString("UserName")),
- date,
- LogType.getByIconName(logIconName),
- logText);
- logDone.found = entry.getInt("GeocacheFindCount");
- logDone.friend = friends;
-
- final JSONArray images = entry.getJSONArray("Images");
- for (int i = 0; i < images.length(); i++) {
- final JSONObject image = images.getJSONObject(i);
- final String url = "http://imgcdn.geocaching.com/cache/log/large/" + image.getString("FileName");
- final String title = TextUtils.removeControlCharacters(image.getString("Name"));
- final Image logImage = new Image(url, title);
- logDone.addLogImage(logImage);
- }
+ // FIXME: use the "LogType" field instead of the "LogTypeImage" one.
+ final String logIconNameExt = entry.optString("LogTypeImage", ".gif");
+ final String logIconName = logIconNameExt.substring(0, logIconNameExt.length() - 4);
- logs.add(logDone);
- }
- } catch (final JSONException e) {
- // failed to parse logs
- Log.w("GCParser.loadLogsFromDetails: Failed to parse cache logs", e);
- }
+ long date = 0;
+ try {
+ date = GCLogin.parseGcCustomDate(entry.getString("Visited")).getTime();
+ } catch (final ParseException e) {
+ Log.e("GCParser.loadLogsFromDetails: failed to parse log date.");
+ }
- return logs;
+ // TODO: we should update our log data structure to be able to record
+ // proper coordinates, and make them clickable. In the meantime, it is
+ // better to integrate those coordinates into the text rather than not
+ // display them at all.
+ final String latLon = entry.getString("LatLonString");
+ final String logText = (StringUtils.isEmpty(latLon) ? "" : (latLon + "<br/><br/>")) + TextUtils.removeControlCharacters(entry.getString("LogText"));
+ final LogEntry logDone = new LogEntry(
+ TextUtils.removeControlCharacters(entry.getString("UserName")),
+ date,
+ LogType.getByIconName(logIconName),
+ logText);
+ logDone.found = entry.getInt("GeocacheFindCount");
+ logDone.friend = markAsFriendsLog;
+
+ final JSONArray images = entry.getJSONArray("Images");
+ for (int i = 0; i < images.length(); i++) {
+ final JSONObject image = images.getJSONObject(i);
+ final String url = "http://imgcdn.geocaching.com/cache/log/large/" + image.getString("FileName");
+ final String title = TextUtils.removeControlCharacters(image.getString("Name"));
+ final Image logImage = new Image(url, title);
+ logDone.addLogImage(logImage);
+ }
+
+ subscriber.onNext(logDone);
+ }
+ } catch (final JSONException e) {
+ // failed to parse logs
+ Log.w("GCParser.loadLogsFromDetails: Failed to parse cache logs", e);
+ }
+ subscriber.onCompleted();
+ }
+ });
}
@NonNull
@@ -1820,32 +1863,39 @@ public abstract class GCParser {
}
private static void getExtraOnlineInfo(final Geocache cache, final String page, final CancellableHandler handler) {
+ // This method starts the page parsing for logs in the background, as well as retrieve the friends and own logs
+ // if requested. It merges them and stores them in the background, while the rating is retrieved if needed and
+ // stored. Then we wait for the log merging and saving to be completed before returning.
if (CancellableHandler.isCancelled(handler)) {
return;
}
- //cache.setLogs(loadLogsFromDetails(page, cache, false));
+ final Observable<LogEntry> logs = getLogsFromDetails(page).subscribeOn(Schedulers.computation());
+ Observable<LogEntry> specialLogs;
if (Settings.isFriendLogsWanted()) {
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs);
- final List<LogEntry> friendLogs = getLogsFromDetails(page, true);
- if (friendLogs != null && !friendLogs.isEmpty()) {
- // create new list, as the existing log list is immutable
- ArrayList<LogEntry> mergedLogs = new ArrayList<LogEntry>(cache.getLogs());
- for (final LogEntry log : friendLogs) {
- if (mergedLogs.contains(log)) {
- mergedLogs.get(mergedLogs.indexOf(log)).friend = true;
- } else {
- mergedLogs.add(log);
+ specialLogs = Observable.merge(getSpecialLogs(page, SpecialLogs.FRIENDS),
+ getSpecialLogs(page, SpecialLogs.OWN));
+ } else {
+ CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs);
+ specialLogs = Observable.empty();
+ }
+ final Observable<List<LogEntry>> mergedLogs = Observable.zip(logs.toList(), specialLogs.toList(),
+ new Func2<List<LogEntry>, List<LogEntry>, List<LogEntry>>() {
+ @Override
+ public List<LogEntry> call(final List<LogEntry> logEntries, final List<LogEntry> specialLogEntries) {
+ mergeFriendsLogs(logEntries, specialLogEntries);
+ return logEntries;
}
- }
- DataStore.saveLogsWithoutTransaction(cache.getGeocode(), mergedLogs);
- }
- }
-
- if (Settings.isRatingWanted()) {
- if (CancellableHandler.isCancelled(handler)) {
- return;
- }
+ }).cache();
+ mergedLogs.subscribe(new Action1<List<LogEntry>>() {
+ @Override
+ public void call(final List<LogEntry> logEntries) {
+ DataStore.saveLogsWithoutTransaction(cache.getGeocode(), logEntries);
+ }
+ });
+
+ if (Settings.isRatingWanted() && !CancellableHandler.isCancelled(handler)) {
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_gcvote);
final GCVoteRating rating = GCVote.getRating(cache.getGuid(), cache.getGeocode());
if (rating != null) {
@@ -1854,6 +1904,28 @@ public abstract class GCParser {
cache.setMyVote(rating.getMyVote());
}
}
+
+ // Wait for completion of logs parsing, retrieving and merging
+ mergedLogs.toBlocking().last();
+ }
+
+ /**
+ * Merge log entries and mark them as friends logs (personal and friends) to identify
+ * them on friends/personal logs tab.
+ *
+ * @param mergedLogs
+ * the list to merge logs with
+ * @param logsToMerge
+ * the list of logs to merge
+ */
+ private static void mergeFriendsLogs(final List<LogEntry> mergedLogs, final Iterable<LogEntry> logsToMerge) {
+ for (final LogEntry log : logsToMerge) {
+ if (mergedLogs.contains(log)) {
+ mergedLogs.get(mergedLogs.indexOf(log)).friend = true;
+ } else {
+ mergedLogs.add(log);
+ }
+ }
}
public static boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) {
diff --git a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java
index c7b470a..c6a2afc 100644
--- a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java
+++ b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java
@@ -35,7 +35,7 @@ public abstract class IconDecoder {
return false; //out of image position
}
- int numberOfDetections = 7; //for level 12 and 13;
+ int numberOfDetections = 7; //for level 12 and 13
if (zoomlevel < 12) {
numberOfDetections = 5;
}
diff --git a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java
index 7cced74..5327bea 100644
--- a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java
+++ b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java
@@ -57,7 +57,7 @@ public class RecaptchaHandler extends Handler {
return Observable.empty();
}
});
- AndroidObservable.bindActivity(activity, captcha).subscribe(new Action1<Bitmap>() {
+ AndroidObservable.bindActivity(activity, captcha).subscribeOn(Schedulers.io()).subscribe(new Action1<Bitmap>() {
@Override
public void call(final Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
@@ -67,7 +67,7 @@ public class RecaptchaHandler extends Handler {
public void call(final Throwable throwable) {
// Do nothing
}
- }, Schedulers.io());
+ });
reloadButton.setEnabled(true);
}
diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java
index ca70111..d7b3a48 100644
--- a/main/src/cgeo/geocaching/connector/gc/Tile.java
+++ b/main/src/cgeo/geocaching/connector/gc/Tile.java
@@ -9,6 +9,7 @@ import cgeo.geocaching.utils.LeastRecentlyUsedSet;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
+
import org.eclipse.jdt.annotation.NonNull;
import android.graphics.Bitmap;
@@ -88,10 +89,6 @@ public class Tile {
*
*/
private static int calcY(final Geopoint origin, final int zoomlevel) {
-
- // double latRad = Math.toRadians(origin.getLatitude());
- // return (int) ((1 - (Math.log(Math.tan(latRad) + (1 / Math.cos(latRad))) / Math.PI)) / 2 * numberOfTiles);
-
// Optimization from Bing
double sinLatRad = Math.sin(Math.toRadians(origin.getLatitude()));
// The cut of the fractional part instead of rounding to the nearest integer is intentional and part of the algorithm
diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
index 049c633..3771443 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
@@ -3,6 +3,7 @@ package cgeo.geocaching.connector.oc;
import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.ICache;
import cgeo.geocaching.LogCacheActivity;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.connector.ILoggingManager;
@@ -149,6 +150,11 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
}
@Override
+ public boolean isOwner(ICache cache) {
+ return StringUtils.isNotEmpty(getUserName()) && StringUtils.equals(cache.getOwnerDisplayName(), getUserName());
+ }
+
+ @Override
public String getUserName() {
return userInfo.getName();
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 3c93488..477830c 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -6,6 +6,7 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.Image;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
+import cgeo.geocaching.Trackable;
import cgeo.geocaching.Waypoint;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
@@ -79,6 +80,7 @@ final class OkapiClient {
private static final String CACHE_VOTES = "rating_votes";
private static final String CACHE_NOTFOUNDS = "notfounds";
private static final String CACHE_FOUNDS = "founds";
+ private static final String CACHE_WILLATTENDS = "willattends";
private static final String CACHE_HIDDEN = "date_hidden";
private static final String CACHE_LATEST_LOGS = "latest_logs";
private static final String CACHE_IMAGE_URL = "url";
@@ -98,6 +100,11 @@ final class OkapiClient {
private static final String CACHE_CODE = "code";
private static final String CACHE_REQ_PASSWORD = "req_passwd";
private static final String CACHE_MY_NOTES = "my_notes";
+ private static final String CACHE_TRACKABLES_COUNT = "trackables_count";
+ private static final String CACHE_TRACKABLES = "trackables";
+
+ private static final String TRK_GEOCODE = "code";
+ private static final String TRK_NAME = "name";
private static final String LOG_TYPE = "type";
private static final String LOG_COMMENT = "comment";
@@ -112,10 +119,10 @@ final class OkapiClient {
// the several realms of possible fields for cache retrieval:
// Core: for livemap requests (L3 - only with level 3 auth)
// Additional: additional fields for full cache (L3 - only for level 3 auth, current - only for connectors with current api)
- private static final String SERVICE_CACHE_CORE_FIELDS = "code|name|location|type|status|difficulty|terrain|size|size2|date_hidden";
+ private static final String SERVICE_CACHE_CORE_FIELDS = "code|name|location|type|status|difficulty|terrain|size|size2|date_hidden|trackables_count";
private static final String SERVICE_CACHE_CORE_L3_FIELDS = "is_found";
- private static final String SERVICE_CACHE_ADDITIONAL_FIELDS = "owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|alt_wpts|attrnames|req_passwd";
- private static final String SERVICE_CACHE_ADDITIONAL_CURRENT_FIELDS = "gc_code|attribution_note|attr_acodes";
+ private static final String SERVICE_CACHE_ADDITIONAL_FIELDS = "owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|alt_wpts|attrnames|req_passwd|trackables";
+ private static final String SERVICE_CACHE_ADDITIONAL_CURRENT_FIELDS = "gc_code|attribution_note|attr_acodes|willattends";
private static final String SERVICE_CACHE_ADDITIONAL_L3_FIELDS = "is_watched|my_notes";
private static final String METHOD_SEARCH_ALL = "services/caches/search/all";
@@ -328,11 +335,16 @@ final class OkapiClient {
parseCoreCache(response, cache);
// not used: url
- final JSONObject owner = response.getJSONObject(CACHE_OWNER);
- cache.setOwnerDisplayName(parseUser(owner));
+ final JSONObject ownerObject = response.getJSONObject(CACHE_OWNER);
+ final String owner = parseUser(ownerObject);
+ cache.setOwnerDisplayName(owner);
+ // OpenCaching has no distinction between user id and user display name. Set the ID anyway to simplify c:geo workflows.
+ cache.setOwnerUserId(owner);
cache.getLogCounts().put(LogType.FOUND_IT, response.getInt(CACHE_FOUNDS));
cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.getInt(CACHE_NOTFOUNDS));
+ // only current Api
+ cache.getLogCounts().put(LogType.WILL_ATTEND, response.optInt(CACHE_WILLATTENDS));
if (!response.isNull(CACHE_RATING)) {
cache.setRating((float) response.getDouble(CACHE_RATING));
@@ -375,6 +387,9 @@ final class OkapiClient {
//TODO: Store license per cache
//cache.setLicense(response.getString("attribution_note"));
cache.setWaypoints(parseWaypoints(response.getJSONArray(CACHE_WPTS)), false);
+
+ cache.setInventory(parseTrackables(response.getJSONArray(CACHE_TRACKABLES)));
+
if (!response.isNull(CACHE_IS_WATCHED)) {
cache.setOnWatchlist(response.getBoolean(CACHE_IS_WATCHED));
}
@@ -409,6 +424,8 @@ final class OkapiClient {
cache.setDifficulty((float) response.getDouble(CACHE_DIFFICULTY));
cache.setTerrain((float) response.getDouble(CACHE_TERRAIN));
+ cache.setInventoryItems(response.getInt(CACHE_TRACKABLES_COUNT));
+
if (!response.isNull(CACHE_IS_FOUND)) {
cache.setFound(response.getBoolean(CACHE_IS_FOUND));
}
@@ -478,6 +495,27 @@ final class OkapiClient {
return result;
}
+ private static List<Trackable> parseTrackables(final JSONArray trackablesJson) {
+ if (trackablesJson.length() == 0) {
+ return Collections.emptyList();
+ }
+ final List<Trackable> result = new ArrayList<Trackable>();
+ for (int i = 0; i < trackablesJson.length(); i++) {
+ try {
+ final JSONObject trackableResponse = trackablesJson.getJSONObject(i);
+ final Trackable trk = new Trackable();
+ trk.setGeocode(trackableResponse.getString(TRK_GEOCODE));
+ trk.setName(trackableResponse.getString(TRK_NAME));
+ result.add(trk);
+ } catch (final JSONException e) {
+ Log.e("OkapiClient.parseWaypoints", e);
+ // Don't overwrite internal state with possibly partial result
+ return null;
+ }
+ }
+ return result;
+ }
+
private static LogType parseLogType(final String logType) {
if ("Found it".equalsIgnoreCase(logType)) {
return LogType.FOUND_IT;
@@ -593,7 +631,7 @@ final class OkapiClient {
try {
final String size = response.getString(CACHE_SIZE2);
return CacheSize.getById(size);
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.getCacheSize", e);
return getCacheSizeDeprecated(response);
}
@@ -702,7 +740,7 @@ final class OkapiClient {
params.add("langpref", getPreferredLanguage());
if (connector.getSupportedAuthLevel() == OAuthLevel.Level3) {
- ImmutablePair<String, String> tokens = Settings.getTokenPair(connector.getTokenPublicPrefKeyId(), connector.getTokenSecretPrefKeyId());
+ final ImmutablePair<String, String> tokens = Settings.getTokenPair(connector.getTokenPublicPrefKeyId(), connector.getTokenSecretPrefKeyId());
OAuth.signOAuth(host, service.methodName, "GET", false, params, tokens.left, tokens.right, connector.getCK(), connector.getCS());
} else {
connector.addAuthentication(params);
@@ -769,7 +807,7 @@ final class OkapiClient {
return null;
}
- JSONObject data = result.data;
+ final JSONObject data = result.data;
if (!data.isNull(USER_UUID)) {
try {
return data.getString(USER_UUID);
@@ -792,7 +830,7 @@ final class OkapiClient {
return new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.getFromOkapiError(error.getResult()));
}
- JSONObject data = result.data;
+ final JSONObject data = result.data;
String name = StringUtils.EMPTY;
boolean successUserName = false;
@@ -828,7 +866,7 @@ final class OkapiClient {
* response containing an error object
* @return OkapiError object with detailed information
*/
- public static OkapiError decodeErrorResponse(HttpResponse response) {
+ public static OkapiError decodeErrorResponse(final HttpResponse response) {
final JSONResult result = new JSONResult(response);
if (!result.isSuccess) {
return new OkapiError(result.data);
@@ -846,7 +884,7 @@ final class OkapiClient {
public final JSONObject data;
public JSONResult(final @Nullable HttpResponse response) {
- boolean isSuccess = Network.isSuccess(response);
+ final boolean isSuccess = Network.isSuccess(response);
final String responseData = Network.getResponseDataAlways(response);
JSONObject data = null;
if (responseData != null) {
diff --git a/main/src/cgeo/geocaching/export/ExportFactory.java b/main/src/cgeo/geocaching/export/ExportFactory.java
deleted file mode 100644
index e743eb2..0000000
--- a/main/src/cgeo/geocaching/export/ExportFactory.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package cgeo.geocaching.export;
-
-import cgeo.geocaching.Geocache;
-import cgeo.geocaching.R;
-import cgeo.geocaching.utils.Log;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.widget.ArrayAdapter;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Factory to create a dialog with all available exporters.
- */
-public abstract class ExportFactory {
-
- /**
- * Contains instances of all available exporter classes.
- */
- private static final List<Class<? extends Export>> exporterClasses;
-
- static {
- final ArrayList<Class<? extends Export>> temp = new ArrayList<Class<? extends Export>>();
- temp.add(FieldnoteExport.class);
- temp.add(GpxExport.class);
- exporterClasses = Collections.unmodifiableList(temp);
- }
-
- /**
- * Creates a dialog so that the user can select an exporter.
- *
- * @param caches
- * The {@link List} of {@link cgeo.geocaching.Geocache} to be exported
- * @param activity
- * The {@link Activity} in whose context the dialog should be shown
- */
- public static void showExportMenu(final List<Geocache> caches, final Activity activity) {
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(R.string.export).setIcon(R.drawable.ic_menu_share);
-
- final ArrayList<Export> export = new ArrayList<Export>();
- for (Class<? extends Export> exporterClass : exporterClasses) {
- try {
- export.add(exporterClass.newInstance());
- } catch (Exception ex) {
- Log.e("showExportMenu", ex);
- }
- }
-
- final ArrayAdapter<Export> adapter = new ArrayAdapter<Export>(activity, android.R.layout.select_dialog_item, export);
-
- builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int item) {
- dialog.dismiss();
- final Export selectedExport = adapter.getItem(item);
- selectedExport.export(caches, activity);
- }
- });
-
- builder.create().show();
- }
-} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java
index 7d3e07e..dd3c8a1 100644
--- a/main/src/cgeo/geocaching/export/FieldnoteExport.java
+++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java
@@ -29,11 +29,11 @@ import java.util.List;
* Exports offline logs in the Groundspeak Field Note format.
*
*/
-class FieldnoteExport extends AbstractExport {
+public class FieldnoteExport extends AbstractExport {
private static final File exportLocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/field-notes");
private static int fieldNotesCount = 0;
- protected FieldnoteExport() {
+ public FieldnoteExport() {
super(getString(R.string.export_fieldnotes));
}
@@ -110,7 +110,7 @@ class FieldnoteExport extends AbstractExport {
@Override
protected Boolean doInBackgroundInternal(final Geocache[] caches) {
// export field notes separately for each connector, so the file can be uploaded to the respective site afterwards
- for (IConnector connector : ConnectorFactory.getConnectors()) {
+ for (final IConnector connector : ConnectorFactory.getConnectors()) {
if (connector instanceof FieldNotesCapability) {
exportFieldNotes((FieldNotesCapability) connector, caches);
}
@@ -118,7 +118,7 @@ class FieldnoteExport extends AbstractExport {
return true;
}
- private boolean exportFieldNotes(final FieldNotesCapability connector, Geocache[] caches) {
+ private boolean exportFieldNotes(final FieldNotesCapability connector, final Geocache[] caches) {
final FieldNotes fieldNotes = new FieldNotes();
try {
int i = 0;
diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java
index 08fca0b..5ca5179 100644
--- a/main/src/cgeo/geocaching/export/GpxExport.java
+++ b/main/src/cgeo/geocaching/export/GpxExport.java
@@ -8,6 +8,7 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.AsyncTaskWithProgress;
import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.ShareUtils;
import org.apache.commons.lang3.CharEncoding;
@@ -15,8 +16,6 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.Uri;
import android.os.Environment;
import android.view.ContextThemeWrapper;
import android.view.View;
@@ -35,9 +34,9 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
-class GpxExport extends AbstractExport {
+public class GpxExport extends AbstractExport {
- protected GpxExport() {
+ public GpxExport() {
super(getString(R.string.export_gpx));
}
@@ -71,7 +70,7 @@ class GpxExport extends AbstractExport {
shareOption.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View v) {
+ public void onClick(final View v) {
Settings.setShareAfterExport(shareOption.isChecked());
}
});
@@ -79,7 +78,7 @@ class GpxExport extends AbstractExport {
builder.setPositiveButton(R.string.export, new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int which) {
+ public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
new ExportTask(activity).execute(geocodes);
}
@@ -117,7 +116,7 @@ class GpxExport extends AbstractExport {
}
@Override
- protected File doInBackgroundInternal(String[] geocodes) {
+ protected File doInBackgroundInternal(final String[] geocodes) {
// quick check for being able to write the GPX file
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return null;
@@ -168,11 +167,7 @@ class GpxExport extends AbstractExport {
if (exportFile != null) {
ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString());
if (Settings.getShareAfterExport()) {
- final Intent shareIntent = new Intent();
- shareIntent.setAction(Intent.ACTION_SEND);
- shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(exportFile));
- shareIntent.setType("application/xml");
- activity.startActivity(Intent.createChooser(shareIntent, getString(R.string.export_gpx_to)));
+ ShareUtils.share(activity, exportFile, "application/xml", R.string.export_gpx_to);
}
} else {
ActivityMixin.showToast(activity, getString(R.string.export_failed));
diff --git a/main/src/cgeo/geocaching/files/FileParser.java b/main/src/cgeo/geocaching/files/FileParser.java
index 396a589..973e65f 100644
--- a/main/src/cgeo/geocaching/files/FileParser.java
+++ b/main/src/cgeo/geocaching/files/FileParser.java
@@ -4,6 +4,8 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.utils.CancellableHandler;
import org.apache.commons.io.IOUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
@@ -29,7 +31,7 @@ public abstract class FileParser {
* @throws ParserException
* if the input stream contains data not matching the file format of the parser
*/
- public abstract Collection<Geocache> parse(final InputStream stream, final CancellableHandler progressHandler) throws IOException, ParserException;
+ public abstract Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException;
/**
* Convenience method for parsing a file.
@@ -49,7 +51,7 @@ public abstract class FileParser {
}
}
- protected static StringBuilder readStream(InputStream is, CancellableHandler progressHandler) throws IOException {
+ protected static StringBuilder readStream(@NonNull final InputStream is, @Nullable final CancellableHandler progressHandler) throws IOException {
final StringBuilder buffer = new StringBuilder();
ProgressInputStream progressInputStream = new ProgressInputStream(is);
final BufferedReader input = new BufferedReader(new InputStreamReader(progressInputStream, "UTF-8"));
@@ -66,7 +68,7 @@ public abstract class FileParser {
}
}
- protected static void showProgressMessage(final CancellableHandler handler, final int bytesRead) {
+ protected static void showProgressMessage(@Nullable final CancellableHandler handler, final int bytesRead) {
if (handler != null) {
if (handler.isCancelled()) {
throw new CancellationException();
diff --git a/main/src/cgeo/geocaching/files/FileType.java b/main/src/cgeo/geocaching/files/FileType.java
new file mode 100644
index 0000000..ef62351
--- /dev/null
+++ b/main/src/cgeo/geocaching/files/FileType.java
@@ -0,0 +1,8 @@
+package cgeo.geocaching.files;
+
+public enum FileType {
+ UNKNOWN,
+ LOC,
+ GPX,
+ ZIP
+}
diff --git a/main/src/cgeo/geocaching/files/FileTypeDetector.java b/main/src/cgeo/geocaching/files/FileTypeDetector.java
new file mode 100644
index 0000000..389b83a
--- /dev/null
+++ b/main/src/cgeo/geocaching/files/FileTypeDetector.java
@@ -0,0 +1,77 @@
+package cgeo.geocaching.files;
+
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+
+import android.content.ContentResolver;
+import android.net.Uri;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class FileTypeDetector {
+
+ private final ContentResolver contentResolver;
+ private final Uri uri;
+
+ public FileTypeDetector(Uri uri, ContentResolver contentResolver) {
+ this.uri = uri;
+ this.contentResolver = contentResolver;
+ }
+
+ public @NonNull FileType getFileType() {
+ InputStream is = null;
+ BufferedReader reader = null;
+ FileType type = FileType.UNKNOWN;
+ try {
+ is = contentResolver.openInputStream(uri);
+ if (is == null) {
+ return FileType.UNKNOWN;
+ }
+ reader = new BufferedReader(new InputStreamReader(is));
+ type = detectHeader(reader);
+ reader.close();
+ } catch (FileNotFoundException e) {
+ Log.e("FileTypeDetector", e);
+ } catch (IOException e) {
+ Log.e("FileTypeDetector", e);
+ } finally {
+ IOUtils.closeQuietly(reader);
+ IOUtils.closeQuietly(is);
+ }
+ return type;
+ }
+
+ private static FileType detectHeader(BufferedReader reader)
+ throws IOException {
+ String line = reader.readLine();
+ if (isZip(line)) {
+ return FileType.ZIP;
+ }
+ // scan at most 5 lines of a GPX file
+ for (int i = 0; i < 5; i++) {
+ line = StringUtils.trim(line);
+ if (StringUtils.contains(line, "<loc")) {
+ return FileType.LOC;
+ }
+ if (StringUtils.contains(line, "<gpx")) {
+ return FileType.GPX;
+ }
+ line = reader.readLine();
+ }
+ return FileType.UNKNOWN;
+ }
+
+ private static boolean isZip(String line) {
+ return StringUtils.length(line) >= 4
+ && StringUtils.startsWith(line, "PK") && line.charAt(2) == 3
+ && line.charAt(3) == 4;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java
index cd2f445..52f68e1 100644
--- a/main/src/cgeo/geocaching/files/GPXImporter.java
+++ b/main/src/cgeo/geocaching/files/GPXImporter.java
@@ -12,8 +12,10 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.Dialogs;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RxUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import android.app.Activity;
@@ -93,46 +95,77 @@ public class GPXImporter {
*
* @param uri
* URI of the file to import
- * @param knownMimeType
- * @param knownPathName
+ * @param mimeType
+ * @param pathName
*/
- public void importGPX(final Uri uri, final @Nullable String knownMimeType, final @Nullable String knownPathName) {
+ public void importGPX(final Uri uri, final @Nullable String mimeType, final @Nullable String pathName) {
final ContentResolver contentResolver = fromActivity.getContentResolver();
- String mimeType = knownMimeType;
- final String pathName = knownPathName != null ? knownPathName : uri.getPath();
-
- // if mimetype can't be determined (e.g. for emulators email app), derive it from uri file extension
- // contentResolver.getType(uri) doesn't help but throws exception for emulators email app
- // Permission Denial: reading com.android.email.provider.EmailProvider uri
- // Google search says: there is no solution for this problem
- // Gmail doesn't work at all, see #967
- if (mimeType == null) {
- if (StringUtils.endsWithIgnoreCase(pathName, GPX_FILE_EXTENSION) || StringUtils.endsWithIgnoreCase(pathName, LOC_FILE_EXTENSION)) {
- mimeType = "application/xml";
- } else {
- // if we can't determine a better type, default to zip import
- // emulator email sends e.g. content://com.android.email.attachmentprovider/1/1/RAW, mimetype=null
- mimeType = "application/zip";
- }
- }
Log.i("importGPX: " + uri + ", mimetype=" + mimeType);
- if (GPX_MIME_TYPES.contains(mimeType)) {
- if (StringUtils.endsWithIgnoreCase(pathName, LOC_FILE_EXTENSION)) {
- new ImportLocAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start();
- } else {
- new ImportGpxAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start();
- }
- } else if (ZIP_MIME_TYPES.contains(mimeType)) {
- new ImportGpxZipAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start();
- } else {
- importFinished();
+ @NonNull
+ FileType fileType = new FileTypeDetector(uri, contentResolver)
+ .getFileType();
+
+ if (fileType == FileType.UNKNOWN) {
+ fileType = getFileTypeFromPathName(pathName);
+ }
+ if (fileType == FileType.UNKNOWN) {
+ fileType = getFileTypeFromMimeType(mimeType);
+ }
+
+ ImportThread importer = getImporterFromFileType(uri, contentResolver,
+ fileType);
+
+ if (importer != null) {
+ importer.start();
+ } else {
+ importFinished();
+ }
+ }
+
+ private static @NonNull FileType getFileTypeFromPathName(
+ final String pathName) {
+ if (StringUtils.endsWithIgnoreCase(pathName, GPX_FILE_EXTENSION)) {
+ return FileType.GPX;
}
- }
- /**
- * Import GPX provided via intent of activity that instantiated this GPXImporter.
- */
+ if (StringUtils.endsWithIgnoreCase(pathName, LOC_FILE_EXTENSION)) {
+ return FileType.LOC;
+ }
+ return FileType.UNKNOWN;
+ }
+
+ private static @NonNull FileType getFileTypeFromMimeType(
+ final String mimeType) {
+ if (GPX_MIME_TYPES.contains(mimeType)) {
+ return FileType.GPX;
+ } else if (ZIP_MIME_TYPES.contains(mimeType)) {
+ return FileType.ZIP;
+ }
+ return FileType.UNKNOWN;
+ }
+
+ private ImportThread getImporterFromFileType(Uri uri,
+ ContentResolver contentResolver, FileType fileType) {
+ switch (fileType) {
+ case ZIP:
+ return new ImportGpxZipAttachmentThread(uri, contentResolver,
+ listId, importStepHandler, progressHandler);
+ case GPX:
+ return new ImportGpxAttachmentThread(uri, contentResolver, listId,
+ importStepHandler, progressHandler);
+ case LOC:
+ return new ImportLocAttachmentThread(uri, contentResolver, listId,
+ importStepHandler, progressHandler);
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Import GPX provided via intent of activity that instantiated this
+ * GPXImporter.
+ */
public void importGPX() {
final Intent intent = fromActivity.getIntent();
final Uri uri = intent.getData();
@@ -194,7 +227,7 @@ public class GPXImporter {
final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
if (cache != null) {
Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode);
- StaticMapsProvider.downloadMaps(cache);
+ RxUtils.waitForCompletion(StaticMapsProvider.downloadMaps(cache));
} else {
Log.d("GPXImporter.ImportThread.importStaticMaps: no data found for " + geocode);
}
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
index 6161088..f3cd326 100644
--- a/main/src/cgeo/geocaching/files/GPXParser.java
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -25,6 +25,8 @@ import cgeo.geocaching.utils.SynchronizedDateFormat;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
@@ -270,7 +272,7 @@ public abstract class GPXParser extends FileParser {
}
@Override
- public Collection<Geocache> parse(final InputStream stream, final CancellableHandler progressHandler) throws IOException, ParserException {
+ public Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException {
resetCache();
final RootElement root = new RootElement(namespace, "gpx");
final Element waypoint = root.getChild(namespace, "wpt");
diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java
index 3d01c1b..223fb5a 100644
--- a/main/src/cgeo/geocaching/files/LocParser.java
+++ b/main/src/cgeo/geocaching/files/LocParser.java
@@ -12,6 +12,8 @@ import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
@@ -116,9 +118,9 @@ public final class LocParser extends FileParser {
}
@Override
- public Collection<Geocache> parse(InputStream stream, CancellableHandler progressHandler) throws IOException, ParserException {
- // TODO: progress reporting happens during reading stream only, not during parsing
- String streamContent = readStream(stream, progressHandler).toString();
+ public Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException {
+ final String streamContent = readStream(stream, null).toString();
+ final int maxSize = streamContent.length();
final Map<String, Geocache> coords = parseCoordinates(streamContent);
final List<Geocache> caches = new ArrayList<Geocache>();
for (Entry<String, Geocache> entry : coords.entrySet()) {
@@ -136,6 +138,9 @@ public final class LocParser extends FileParser {
cache.setListId(listId);
cache.setDetailed(true);
cache.store(null);
+ if (progressHandler != null) {
+ progressHandler.sendMessage(progressHandler.obtainMessage(0, maxSize * caches.size() / coords.size(), 0));
+ }
}
Log.i("Caches found in .loc file: " + caches.size());
return caches;
diff --git a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java
index 2d7207a..5bfab28 100644
--- a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java
+++ b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java
@@ -24,22 +24,15 @@ class PopularityRatioFilter extends AbstractFilter {
@Override
public boolean accepts(final Geocache cache) {
+ final int finds = getFindsCount(cache);
- int finds;
- int favorites;
- float ratio;
-
- finds = getFindsCount(cache);
-
- // prevent division by zero
- if (finds == 0) {
+ if (finds == 0) { // Prevent division by zero
return false;
}
- favorites = cache.getFavoritePoints();
- ratio = ((float) favorites / (float) finds) * 100.0f;
-
- return (ratio > minRatio) && (ratio <= maxRatio);
+ final int favorites = cache.getFavoritePoints();
+ final float ratio = 100.0f * favorites / finds;
+ return ratio > minRatio && ratio <= maxRatio;
}
private static int getFindsCount(Geocache cache) {
diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java
index f452259..fd14b69 100644
--- a/main/src/cgeo/geocaching/filter/StateFilter.java
+++ b/main/src/cgeo/geocaching/filter/StateFilter.java
@@ -32,6 +32,19 @@ abstract class StateFilter extends AbstractFilter {
}
+ static class StateNotFoundFilter extends StateFilter {
+
+ public StateNotFoundFilter() {
+ super(res.getString(R.string.cache_not_status_found));
+ }
+
+ @Override
+ public boolean accepts(final Geocache cache) {
+ return !cache.isFound();
+ }
+
+ }
+
static class StateArchivedFilter extends StateFilter {
public StateArchivedFilter() {
super(res.getString(R.string.cache_status_archived));
@@ -115,6 +128,7 @@ abstract class StateFilter extends AbstractFilter {
public List<StateFilter> getFilters() {
final List<StateFilter> filters = new ArrayList<StateFilter>(6);
filters.add(new StateFoundFilter());
+ filters.add(new StateNotFoundFilter());
filters.add(new StateArchivedFilter());
filters.add(new StateDisabledFilter());
filters.add(new StatePremiumFilter());
diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java
index 0ab1fe3..d77a4e6 100644
--- a/main/src/cgeo/geocaching/gcvote/GCVote.java
+++ b/main/src/cgeo/geocaching/gcvote/GCVote.java
@@ -1,6 +1,8 @@
package cgeo.geocaching.gcvote;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
@@ -253,7 +255,7 @@ public final class GCVote {
/**
* Get geocodes of all the caches, which can be used with GCVote. Non-GC caches will be filtered out.
- *
+ *
* @param caches
* @return
*/
@@ -281,4 +283,33 @@ public final class GCVote {
return Settings.isGCvoteLogin() && StringUtils.isNotBlank(cache.getGuid()) && cache.supportsGCVote();
}
+ public static String getDescription(final float rating) {
+ switch (Math.round(rating * 2f)) {
+ case 2:
+ return getString(R.string.log_stars_1_description);
+ case 3:
+ return getString(R.string.log_stars_15_description);
+ case 4:
+ return getString(R.string.log_stars_2_description);
+ case 5:
+ return getString(R.string.log_stars_25_description);
+ case 6:
+ return getString(R.string.log_stars_3_description);
+ case 7:
+ return getString(R.string.log_stars_35_description);
+ case 8:
+ return getString(R.string.log_stars_4_description);
+ case 9:
+ return getString(R.string.log_stars_45_description);
+ case 10:
+ return getString(R.string.log_stars_5_description);
+ default:
+ return getString(R.string.log_no_rating);
+ }
+ }
+
+ private static String getString(int resId) {
+ return CgeoApplication.getInstance().getString(resId);
+ }
+
}
diff --git a/main/src/cgeo/geocaching/geopoint/Geopoint.java b/main/src/cgeo/geocaching/geopoint/Geopoint.java
index 1655343..bb34114 100644
--- a/main/src/cgeo/geocaching/geopoint/Geopoint.java
+++ b/main/src/cgeo/geocaching/geopoint/Geopoint.java
@@ -556,15 +556,14 @@ public final class Geopoint implements ICoordinates, Parcelable {
* Gets distance in meters (workaround for 4.2.1 JIT bug).
*/
public static double getDistance(double lat1, double lon1, double lat2, double lon2) {
- double earthRadius = 6372.8; // for haversine use R = 6372.8 km instead of 6371 km
+ // for haversine use R = 6372.8 km instead of 6371 km
+ double earthRadius = 6372.8;
double dLat = toRadians(lat2 - lat1);
double dLon = toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
- //double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
- //return R * c * 1000;
- // simplify haversine:
+ // simplify haversine
return (2 * earthRadius * 1000 * Math.asin(Math.sqrt(a)));
}
@@ -582,8 +581,8 @@ public final class Geopoint implements ICoordinates, Parcelable {
}
/**
- * Check whether a lo bngitudeuilt from user supplied data is valid. We accept both E180/W180.
- *
+ * Check whether a longitude from user supplied data is valid. We accept both E180/W180.
+ *
* @return <tt>true</tt> if the longitude looks valid, <tt>false</tt> otherwise
*/
public static boolean isValidLongitude(final double longitude) {
diff --git a/main/src/cgeo/geocaching/geopoint/Units.java b/main/src/cgeo/geocaching/geopoint/Units.java
index b99e00e..d00e075 100644
--- a/main/src/cgeo/geocaching/geopoint/Units.java
+++ b/main/src/cgeo/geocaching/geopoint/Units.java
@@ -4,6 +4,8 @@ import cgeo.geocaching.settings.Settings;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import java.util.Locale;
+
public class Units {
public static ImmutablePair<Double, String> scaleDistance(final double distanceKilometers) {
@@ -51,11 +53,10 @@ public class Units {
return getDistanceFromKilometers(meters / 1000f);
}
- public static String getSpeed(float kilometersPerHour) {
- final String speed = getDistanceFromKilometers(kilometersPerHour);
- if (speed.endsWith("mi")) {
- return speed.substring(0, speed.length() - 2) + "mph";
+ public static String getSpeed(final float kilometersPerHour) {
+ if (Settings.isUseImperialUnits()) {
+ return String.format(Locale.US, "%.0f mph", kilometersPerHour / IConversion.MILES_TO_KILOMETER);
}
- return speed + (!Settings.isUseImperialUnits() ? "/h" : "ph");
+ return String.format(Locale.US, "%.0f km/h", kilometersPerHour);
}
}
diff --git a/main/src/cgeo/geocaching/list/AbstractList.java b/main/src/cgeo/geocaching/list/AbstractList.java
index ec783eb..06f44a2 100644
--- a/main/src/cgeo/geocaching/list/AbstractList.java
+++ b/main/src/cgeo/geocaching/list/AbstractList.java
@@ -20,6 +20,10 @@ public abstract class AbstractList {
public abstract boolean isConcrete();
+ public abstract String getTitle();
+
+ public abstract int getNumberOfCaches();
+
@Nullable
public static AbstractList getListById(int listId) {
return LISTS.get(listId);
diff --git a/main/src/cgeo/geocaching/list/PseudoList.java b/main/src/cgeo/geocaching/list/PseudoList.java
index f2cc7ed..9ee920c 100644
--- a/main/src/cgeo/geocaching/list/PseudoList.java
+++ b/main/src/cgeo/geocaching/list/PseudoList.java
@@ -1,32 +1,48 @@
package cgeo.geocaching.list;
import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.R;
-public class PseudoList extends AbstractList {
+public abstract class PseudoList extends AbstractList {
private static final int ALL_LIST_ID = 2;
/**
* list entry to show all caches
*/
- public static final PseudoList ALL_LIST = new PseudoList(ALL_LIST_ID, R.string.list_all_lists);
+ public static final PseudoList ALL_LIST = new PseudoList(ALL_LIST_ID, R.string.list_all_lists) {
+ @Override
+ public int getNumberOfCaches() {
+ return DataStore.getAllCachesCount();
+ }
+ };
private static final int NEW_LIST_ID = 3;
/**
* list entry to create a new list
*/
- public static final AbstractList NEW_LIST = new PseudoList(NEW_LIST_ID, R.string.list_menu_create);
+ public static final AbstractList NEW_LIST = new PseudoList(NEW_LIST_ID, R.string.list_menu_create) {
+ @Override
+ public int getNumberOfCaches() {
+ return -1;
+ }
+ };
private static final int HISTORY_LIST_ID = 4;
/**
* list entry to create a new list
*/
- public static final AbstractList HISTORY_LIST = new PseudoList(HISTORY_LIST_ID, R.string.menu_history);
+ public static final AbstractList HISTORY_LIST = new PseudoList(HISTORY_LIST_ID, R.string.menu_history) {
+ @Override
+ public int getNumberOfCaches() {
+ return DataStore.getAllHistoryCachesCount();
+ }
+ };
/**
* private constructor to have all instances as constants in the class
*/
- private PseudoList(int id, final int titleResourceId) {
+ private PseudoList(final int id, final int titleResourceId) {
super(id, CgeoApplication.getInstance().getResources().getString(titleResourceId));
}
@@ -36,6 +52,11 @@ public class PseudoList extends AbstractList {
}
@Override
+ public String getTitle() {
+ return title;
+ }
+
+ @Override
public boolean isConcrete() {
return false;
}
diff --git a/main/src/cgeo/geocaching/list/StoredList.java b/main/src/cgeo/geocaching/list/StoredList.java
index e557fc8..6dac1a7 100644
--- a/main/src/cgeo/geocaching/list/StoredList.java
+++ b/main/src/cgeo/geocaching/list/StoredList.java
@@ -16,6 +16,7 @@ import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.res.Resources;
+import java.lang.ref.WeakReference;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
@@ -58,12 +59,12 @@ public final class StoredList extends AbstractList {
}
public static class UserInterface {
- private final Activity activity;
+ private final WeakReference<Activity> activityRef;
private final CgeoApplication app;
private final Resources res;
- public UserInterface(final Activity activity) {
- this.activity = activity;
+ public UserInterface(final @NonNull Activity activity) {
+ this.activityRef = new WeakReference<Activity>(activity);
app = CgeoApplication.getInstance();
res = app.getResources();
}
@@ -77,25 +78,7 @@ public final class StoredList extends AbstractList {
}
public void promptForListSelection(final int titleId, @NonNull final Action1<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId, final String newListName) {
- final List<AbstractList> lists = new ArrayList<AbstractList>();
- lists.addAll(getSortedLists());
-
- if (exceptListId > StoredList.TEMPORARY_LIST_ID) {
- StoredList exceptList = DataStore.getList(exceptListId);
- if (exceptList != null) {
- lists.remove(exceptList);
- }
- }
-
- if (!onlyConcreteLists) {
- if (exceptListId != PseudoList.ALL_LIST.id) {
- lists.add(PseudoList.ALL_LIST);
- }
- if (exceptListId != PseudoList.HISTORY_LIST.id) {
- lists.add(PseudoList.HISTORY_LIST);
- }
- }
- lists.add(PseudoList.NEW_LIST);
+ final List<AbstractList> lists = getMenuLists(onlyConcreteLists, exceptListId);
final List<CharSequence> listsTitle = new ArrayList<CharSequence>();
for (AbstractList list : lists) {
@@ -104,6 +87,7 @@ public final class StoredList extends AbstractList {
final CharSequence[] items = new CharSequence[listsTitle.size()];
+ final Activity activity = activityRef.get();
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(res.getString(titleId));
builder.setItems(listsTitle.toArray(items), new DialogInterface.OnClickListener() {
@@ -122,6 +106,31 @@ public final class StoredList extends AbstractList {
builder.create().show();
}
+ public static List<AbstractList> getMenuLists(boolean onlyConcreteLists, int exceptListId) {
+ final List<AbstractList> lists = new ArrayList<AbstractList>();
+ lists.addAll(getSortedLists());
+
+ if (exceptListId > StoredList.TEMPORARY_LIST_ID) {
+ StoredList exceptList = DataStore.getList(exceptListId);
+ if (exceptList != null) {
+ lists.remove(exceptList);
+ }
+ }
+
+ if (!onlyConcreteLists) {
+ if (exceptListId != PseudoList.ALL_LIST.id) {
+ lists.add(PseudoList.ALL_LIST);
+ }
+ if (exceptListId != PseudoList.HISTORY_LIST.id) {
+ lists.add(PseudoList.HISTORY_LIST);
+ }
+ }
+ if (exceptListId != PseudoList.NEW_LIST.id) {
+ lists.add(PseudoList.NEW_LIST);
+ }
+ return lists;
+ }
+
@NonNull
private static List<StoredList> getSortedLists() {
final Collator collator = Collator.getInstance();
@@ -151,6 +160,10 @@ public final class StoredList extends AbstractList {
@SuppressWarnings("unused")
@Override
public void call(final String listName) {
+ final Activity activity = activityRef.get();
+ if (activity == null) {
+ return;
+ }
final int newId = DataStore.createList(listName);
new StoredList(newId, listName, 0);
@@ -165,6 +178,10 @@ public final class StoredList extends AbstractList {
}
private void handleListNameInput(final String defaultValue, int dialogTitle, int buttonTitle, final Action1<String> runnable) {
+ final Activity activity = activityRef.get();
+ if (activity == null) {
+ return;
+ }
Dialogs.input(activity, dialogTitle, defaultValue, buttonTitle, new Action1<String>() {
@Override
@@ -193,14 +210,18 @@ public final class StoredList extends AbstractList {
}
/**
- * Get the list title. This method is not public by intention to make clients use the {@link UserInterface} class.
- *
- * @return
+ * Get the list title.
*/
- protected String getTitle() {
+ @Override
+ public String getTitle() {
return title;
}
+ @Override
+ public int getNumberOfCaches() {
+ return count;
+ }
+
/**
* Return the given list, if it is a concrete list. Return the default list otherwise.
*/
diff --git a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java
index b80a1b8..0d5af6a 100644
--- a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java
+++ b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java
@@ -1,18 +1,20 @@
package cgeo.geocaching.loaders;
import cgeo.geocaching.DataStore;
+import cgeo.geocaching.Intents;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.settings.Settings;
import android.content.Context;
+import android.os.Bundle;
public class OfflineGeocacheListLoader extends AbstractSearchLoader {
- private int listId;
- private Geopoint searchCenter;
+ private final int listId;
+ private final Geopoint searchCenter;
- public OfflineGeocacheListLoader(Context context, Geopoint searchCenter, int listId) {
+ public OfflineGeocacheListLoader(final Context context, final Geopoint searchCenter, final int listId) {
super(context);
this.searchCenter = searchCenter;
this.listId = listId;
@@ -23,12 +25,14 @@ public class OfflineGeocacheListLoader extends AbstractSearchLoader {
return DataStore.getBatchOfStoredCaches(searchCenter, Settings.getCacheType(), listId);
}
- public void setListId(int listId) {
- this.listId = listId;
- }
-
- public void setSearchCenter(Geopoint searchCenter) {
- this.searchCenter = searchCenter;
+ /**
+ * @param listId
+ * @return the bundle needed for querying the LoaderManager for the offline list with the given id
+ */
+ public static Bundle getBundleForList(final int listId) {
+ final Bundle bundle = new Bundle();
+ bundle.putInt(Intents.EXTRA_LIST_ID, listId);
+ return bundle;
}
}
diff --git a/main/src/cgeo/geocaching/maps/AbstractMap.java b/main/src/cgeo/geocaching/maps/AbstractMap.java
index d341823..2eceadb 100644
--- a/main/src/cgeo/geocaching/maps/AbstractMap.java
+++ b/main/src/cgeo/geocaching/maps/AbstractMap.java
@@ -5,10 +5,11 @@ import cgeo.geocaching.maps.interfaces.MapActivityImpl;
import android.app.Activity;
import android.content.res.Resources;
+import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
+import android.view.Window;
/**
* Base class for the map activity. Delegates base class calls to the
@@ -31,7 +32,11 @@ public abstract class AbstractMap {
}
public void onCreate(Bundle savedInstanceState) {
+
mapActivity.superOnCreate(savedInstanceState);
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
+ mapActivity.getActivity().requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ }
}
public void onResume() {
@@ -64,8 +69,6 @@ public abstract class AbstractMap {
return mapActivity.superOnOptionsItemSelected(item);
}
- public abstract void goHome(View view);
-
public abstract void onSaveInstanceState(final Bundle outState);
}
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index 00aee36..4524dec 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -43,14 +43,17 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import rx.Scheduler;
import rx.Subscription;
+import rx.functions.Action0;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
import rx.subscriptions.CompositeSubscription;
import rx.subscriptions.Subscriptions;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@@ -61,6 +64,7 @@ import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.location.Location;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -70,9 +74,11 @@ import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
+import android.widget.CheckBox;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
+import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.ViewSwitcher.ViewFactory;
@@ -92,7 +98,7 @@ import java.util.concurrent.TimeUnit;
/**
* Class representing the Map in c:geo
*/
-public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFactory {
+public class CGeoMap extends AbstractMap implements ViewFactory {
/** max. number of caches displayed in the Live Map */
public static final int MAX_CACHES = 500;
@@ -171,7 +177,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private static final int[][] INSET_USERMODIFIEDCOORDS = { { 21, 28, 0, 0 }, { 19, 25, 0, 0 }, { 25, 33, 0, 0 } }; // bottom right, 12x12 / 26x26 / 35x35
private static final int[][] INSET_PERSONALNOTE = { { 0, 28, 21, 0 }, { 0, 25, 19, 0 }, { 0, 33, 25, 0 } }; // bottom left, 12x12 / 26x26 / 35x35
- private SparseArray<LayerDrawable> overlaysCache = new SparseArray<LayerDrawable>();
+ private final SparseArray<LayerDrawable> overlaysCache = new SparseArray<LayerDrawable>();
/** Count of caches currently visible */
private int cachesCnt = 0;
/** List of caches in the viewport */
@@ -184,9 +190,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private int detailProgress = 0;
private long detailProgressTime = 0L;
// views
- private ImageSwitcher myLocSwitch = null;
+ private CheckBox myLocSwitch = null;
- /** Controls the map behaviour */
+ /** Controls the map behavior */
private MapMode mapMode = null;
/** Live mode enabled for map. **/
private boolean isLiveEnabled;
@@ -210,74 +216,130 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
// handlers
/** Updates the titles */
- final private Handler displayHandler = new Handler() {
+ private final static class DisplayHandler extends Handler {
+
+ private final WeakReference<CGeoMap> mapRef;
+
+ public DisplayHandler(@NonNull final CGeoMap map) {
+ this.mapRef = new WeakReference<CGeoMap>(map);
+ }
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
final int what = msg.what;
+ final CGeoMap map = mapRef.get();
+ if (map == null) {
+ return;
+ }
switch (what) {
case UPDATE_TITLE:
// set title
final StringBuilder title = new StringBuilder();
- if (mapMode == MapMode.LIVE && isLiveEnabled) {
- title.append(res.getString(R.string.map_live));
+ if (map.mapMode == MapMode.LIVE && map.isLiveEnabled) {
+ title.append(map.res.getString(R.string.map_live));
} else {
- title.append(mapTitle);
+ title.append(map.mapTitle);
}
- countVisibleCaches();
- if (caches != null && !caches.isEmpty() && !mapTitle.contains("[")) {
- title.append(" [").append(cachesCnt);
- if (cachesCnt != caches.size()) {
- title.append('/').append(caches.size());
+ map.countVisibleCaches();
+ if (map.caches != null && !map.caches.isEmpty() && !map.mapTitle.contains("[")) {
+ title.append(" [").append(map.cachesCnt);
+ if (map.cachesCnt != map.caches.size()) {
+ title.append('/').append(map.caches.size());
}
title.append(']');
}
- if (Settings.isDebug() && lastSearchResult != null && StringUtils.isNotBlank(lastSearchResult.getUrl())) {
- title.append('[').append(lastSearchResult.getUrl()).append(']');
+ if (Settings.isDebug() && map.lastSearchResult != null && StringUtils.isNotBlank(map.lastSearchResult.getUrl())) {
+ title.append('[').append(map.lastSearchResult.getUrl()).append(']');
}
- ActivityMixin.setTitle(activity, title.toString());
+ map.setTitle(title.toString());
break;
case INVALIDATE_MAP:
- mapView.repaintRequired(null);
+ map.mapView.repaintRequired(null);
break;
default:
break;
}
}
- };
- /** Updates the progress. */
- final private Handler showProgressHandler = new Handler() {
+ }
+
+ final private Handler displayHandler = new DisplayHandler(this);
+
+ private void setTitle(final String title) {
+ /* Compatibility for the old Action Bar, only used by the maps activity at the moment */
+ final TextView titleview = (TextView) activity.findViewById(R.id.actionbar_title);
+ if (titleview != null) {
+ titleview.setText(title);
+
+ }
+ if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)) {
+ setTitleHoneyComb(title);
+ }
+ }
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void setTitleHoneyComb(final String title) {
+ activity.getActionBar().setTitle(title);
+ }
+
+ /** Updates the progress. */
+ private static final class ShowProgressHandler extends Handler {
private int counter = 0;
+ @NonNull private final WeakReference<CGeoMap> mapRef;
+
+ public ShowProgressHandler(@NonNull final CGeoMap map) {
+ this.mapRef = new WeakReference<CGeoMap>(map);
+ }
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
final int what = msg.what;
if (what == HIDE_PROGRESS) {
if (--counter == 0) {
- ActivityMixin.showProgress(activity, false);
+ showProgress(false);
}
} else if (what == SHOW_PROGRESS) {
- ActivityMixin.showProgress(activity, true);
+ showProgress(true);
counter++;
}
}
- };
+
+ private void showProgress(final boolean show) {
+ final CGeoMap map = mapRef.get();
+ if (map == null) {
+ return;
+ }
+
+ final ProgressBar progress = (ProgressBar) map.activity.findViewById(R.id.actionbar_progress);
+ if (progress != null) {
+ if (show) {
+ progress.setVisibility(View.VISIBLE);
+ } else {
+ progress.setVisibility(View.GONE);
+
+ }
+ }
+ if (Build.VERSION.SDK_INT >= 11) {
+ map.activity.setProgressBarIndeterminateVisibility(show);
+ }
+ }
+ }
+
+ final private Handler showProgressHandler = new ShowProgressHandler(this);
final private class LoadDetailsHandler extends CancellableHandler {
@Override
- public void handleRegularMessage(Message msg) {
+ public void handleRegularMessage(final Message msg) {
if (msg.what == UPDATE_PROGRESS) {
if (waitDialog != null) {
- int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000);
+ final int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000);
int secondsRemaining;
if (detailProgress > 0) {
secondsRemaining = (detailTotal - detailProgress) * secondsElapsed / detailProgress;
@@ -289,7 +351,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (secondsRemaining < 40) {
waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm));
} else {
- int minsRemaining = secondsRemaining / 60;
+ final int minsRemaining = secondsRemaining / 60;
waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + minsRemaining + " " + res.getQuantityString(R.plurals.caches_eta_mins, minsRemaining));
}
}
@@ -312,7 +374,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final private Handler noMapTokenHandler = new Handler() {
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
if (!noMapTokenShowed) {
ActivityMixin.showToast(activity, res.getString(R.string.map_token_err));
@@ -328,7 +390,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
/* Current source id */
private int currentSourceId;
- public CGeoMap(MapActivityImpl activity) {
+ public CGeoMap(final MapActivityImpl activity) {
super(activity);
geoDirUpdate = new UpdateLoc(this);
}
@@ -361,8 +423,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// class init
@@ -370,7 +433,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
activity = this.getActivity();
app = (CgeoApplication) activity.getApplication();
- int countBubbleCnt = DataStore.getAllCachesCount();
+ final int countBubbleCnt = DataStore.getAllCachesCount();
caches = new LeastRecentlyUsedSet<Geocache>(MAX_CACHES + countBubbleCnt);
final MapProvider mapProvider = Settings.getMapProvider();
@@ -418,10 +481,16 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
ActivityMixin.keepScreenOn(activity, true);
+
// set layout
- ActivityMixin.setTheme(activity);
+ //ActivityMixin.setTheme(activity);
+ // TODO: set a proper theme
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
+ activity.setTheme(android.R.style.Theme_Holo);
+ activity.getActionBar().setDisplayHomeAsUpEnabled(true);
+ }
activity.setContentView(mapProvider.getMapLayoutId());
- ActivityMixin.setTitle(activity, res.getString(R.string.map_map));
+ setTitle(res.getString(R.string.map_map));
// initialize map
mapView = (MapViewImpl) activity.findViewById(mapProvider.getMapViewId());
@@ -429,7 +498,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
mapView.setBuiltInZoomControls(true);
mapView.displayZoomControls(true);
mapView.preLoad();
- mapView.setOnDragListener(this);
+ mapView.setOnDragListener(new MapDragListener(this));
// initialize overlays
mapView.clearOverlays();
@@ -439,7 +508,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
if (overlayPositionAndScale == null) {
- overlayPositionAndScale = mapView.createAddPositionAndScaleOverlay(activity);
+ overlayPositionAndScale = mapView.createAddPositionAndScaleOverlay();
if (trailHistory != null) {
overlayPositionAndScale.setHistory(trailHistory);
}
@@ -462,14 +531,11 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
centerMap(geocodeIntent, searchIntent, coordsIntent, mapStateIntent);
}
- // prepare my location button
- myLocSwitch = (ImageSwitcher) activity.findViewById(R.id.my_position);
- myLocSwitch.setFactory(this);
- myLocSwitch.setInAnimation(activity, android.R.anim.fade_in);
- myLocSwitch.setOutAnimation(activity, android.R.anim.fade_out);
- myLocSwitch.setOnClickListener(new MyLocationListener());
- switchMyLocationButton();
+ final CheckBox locSwitch = (CheckBox) activity.findViewById(R.id.my_position);
+ if (locSwitch!=null) {
+ initMyLocationSwitchButton(locSwitch);
+ }
prepareFilterBar();
if (!app.isLiveMapHintShownInThisSession() && !Settings.getHideLiveMapHint() && Settings.getLiveMapHintShowCount() <= 3) {
@@ -477,6 +543,16 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
+ private void initMyLocationSwitchButton(final CheckBox locSwitch) {
+ myLocSwitch = locSwitch;
+ /* TODO: Switch back to ImageSwitcher for animations?
+ myLocSwitch.setFactory(this);
+ myLocSwitch.setInAnimation(activity, android.R.anim.fade_in);
+ myLocSwitch.setOutAnimation(activity, android.R.anim.fade_out); */
+ myLocSwitch.setOnClickListener(new MyLocationListener(this));
+ switchMyLocationButton();
+ }
+
/**
* Set the zoom of the map. The zoom is restricted to a certain minimum in case of live map.
*
@@ -489,7 +565,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private void prepareFilterBar() {
// show the filter warning bar if the filter is set
if (Settings.getCacheType() != CacheType.ALL) {
- String cacheType = Settings.getCacheType().getL10n();
+ final String cacheType = Settings.getCacheType().getL10n();
((TextView) activity.findViewById(R.id.filter_text)).setText(cacheType);
activity.findViewById(R.id.filter_bar).setVisibility(View.VISIBLE);
} else {
@@ -503,8 +579,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
resumeSubscription = Subscriptions.from(geoDirUpdate.start(GeoDirHandler.UPDATE_GEODIR), startTimer());
if (!CollectionUtils.isEmpty(dirtyCaches)) {
- for (String geocode : dirtyCaches) {
- Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ for (final String geocode : dirtyCaches) {
+ final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
if (cache != null) {
// new collection type needs to remove first
caches.remove(cache);
@@ -514,7 +590,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
dirtyCaches.clear();
// Update display
- displayExecutor.execute(new DisplayRunnable(mapView.getViewport()));
+ displayExecutor.execute(new DisplayRunnable(this));
}
}
@@ -532,8 +608,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
super.onPause();
}
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ public boolean onCreateOptionsMenu(final Menu menu) {
// menu inflation happens in Google/Mapsforge specific classes
super.onCreateOptionsMenu(menu);
@@ -541,26 +618,35 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final SubMenu subMenuStrategy = menu.findItem(R.id.submenu_strategy).getSubMenu();
subMenuStrategy.setHeaderTitle(res.getString(R.string.map_strategy_title));
+
+
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
+ /* if we have an Actionbar find the my position toggle */
+ final MenuItem item = menu.findItem(R.id.menu_toggle_mypos);
+ myLocSwitch = new CheckBox(activity);
+ myLocSwitch.setButtonDrawable(R.drawable.ic_menu_myposition);
+ item.setActionView(myLocSwitch);
+ initMyLocationSwitchButton(myLocSwitch);
+ } else {
+ // Already on the fake Actionbar
+ menu.removeItem(R.id.menu_toggle_mypos);
+ }
return true;
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
+ public boolean onPrepareOptionsMenu(final Menu menu) {
super.onPrepareOptionsMenu(menu);
- for (MapSource mapSource : MapProviderFactory.getMapSources()) {
+ for (final MapSource mapSource : MapProviderFactory.getMapSources()) {
final MenuItem menuItem = menu.findItem(mapSource.getNumericalId());
if (menuItem != null) {
- menuItem.setEnabled(mapSource.isAvailable());
+ menuItem.setVisible(mapSource.isAvailable());
}
}
try {
MenuItem item = menu.findItem(R.id.menu_trail_mode);
- if (Settings.isMapTrail()) {
- item.setTitle(res.getString(R.string.map_trail_hide));
- } else {
- item.setTitle(res.getString(R.string.map_trail_show));
- }
+ item.setChecked(Settings.isMapTrail());
item = menu.findItem(R.id.menu_map_live); // live map
if (isLiveEnabled) {
@@ -570,28 +656,20 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
item = menu.findItem(R.id.menu_mycaches_mode); // own & found caches
- if (Settings.isExcludeMyCaches()) {
- item.setTitle(res.getString(R.string.map_mycaches_show));
- } else {
- item.setTitle(res.getString(R.string.map_mycaches_hide));
- }
+ item.setChecked(Settings.isExcludeMyCaches());
final Set<String> geocodesInViewport = getGeocodesForCachesInViewport();
- menu.findItem(R.id.menu_store_caches).setEnabled(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && new SearchResult(geocodesInViewport).hasUnsavedCaches());
+ menu.findItem(R.id.menu_store_caches).setVisible(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && new SearchResult(geocodesInViewport).hasUnsavedCaches());
item = menu.findItem(R.id.menu_circle_mode); // show circles
- if (overlayCaches != null && overlayCaches.getCircles()) {
- item.setTitle(res.getString(R.string.map_circles_hide));
- } else {
- item.setTitle(res.getString(R.string.map_circles_show));
- }
+ item.setChecked(overlayCaches != null && overlayCaches.getCircles());
item = menu.findItem(R.id.menu_theme_mode); // show theme selection
item.setVisible(mapView.hasMapThemes());
- menu.findItem(R.id.menu_as_list).setEnabled(!isLoading());
+ menu.findItem(R.id.menu_as_list).setVisible(!isLoading());
- menu.findItem(R.id.submenu_strategy).setEnabled(isLiveEnabled);
+ menu.findItem(R.id.submenu_strategy).setVisible(isLiveEnabled);
switch (Settings.getLiveMapStrategy()) {
case FASTEST:
@@ -606,7 +684,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
default: // DETAILED
menu.findItem(R.id.menu_strategy_detailed).setChecked(true);
}
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.e("CGeoMap.onPrepareOptionsMenu", e);
}
@@ -614,9 +692,12 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public boolean onOptionsItemSelected(final MenuItem item) {
final int id = item.getItemId();
switch (id) {
+ case android.R.id.home:
+ ActivityMixin.navigateUp(activity);
+ return true;
case R.id.menu_trail_mode:
Settings.setMapTrail(!Settings.isMapTrail());
mapView.repaintRequired(overlayPositionAndScale);
@@ -726,16 +807,16 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final File[] themeFiles = Settings.getMapThemeFiles();
String currentTheme = StringUtils.EMPTY;
- String currentThemePath = Settings.getCustomRenderThemeFilePath();
+ final String currentThemePath = Settings.getCustomRenderThemeFilePath();
if (StringUtils.isNotEmpty(currentThemePath)) {
- File currentThemeFile = new File(currentThemePath);
+ final File currentThemeFile = new File(currentThemePath);
currentTheme = currentThemeFile.getName();
}
- List<String> names = new ArrayList<String>();
+ final List<String> names = new ArrayList<String>();
names.add(res.getString(R.string.map_theme_builtin));
int currentItem = 0;
- for (File file : themeFiles) {
+ for (final File file : themeFiles) {
if (currentTheme.equalsIgnoreCase(file.getName())) {
currentItem = names.size();
}
@@ -744,7 +825,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final int selectedItem = currentItem;
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.map_theme_select);
@@ -752,7 +833,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int newItem) {
+ public void onClick(final DialogInterface dialog, final int newItem) {
if (newItem != selectedItem) {
// Adjust index because of <default> selection
if (newItem > 0) {
@@ -818,7 +899,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
activity.finish();
// prepare information to restart a similar view
- Intent mapIntent = new Intent(activity, Settings.getMapProvider().getMapClass());
+ final Intent mapIntent = new Intent(activity, Settings.getMapProvider().getMapClass());
mapIntent.putExtra(EXTRAS_SEARCH, searchIntent);
mapIntent.putExtra(EXTRAS_GEOCODE, geocodeIntent);
@@ -896,7 +977,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
*/
private final WeakReference<CGeoMap> map;
- public UpdateLoc(CGeoMap map) {
+ public UpdateLoc(final CGeoMap map) {
this.map = new WeakReference<CGeoMap>(map);
}
@@ -922,15 +1003,15 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
timeLastPositionOverlayCalculation = currentTimeMillis;
try {
- CGeoMap cgeoMapRef = map.get();
+ final CGeoMap cgeoMapRef = map.get();
if (cgeoMapRef != null) {
if (cgeoMapRef.mapView != null) {
if (cgeoMapRef.overlayPositionAndScale == null) {
- cgeoMapRef.overlayPositionAndScale = cgeoMapRef.mapView.createAddPositionAndScaleOverlay(cgeoMapRef.activity);
+ cgeoMapRef.overlayPositionAndScale = cgeoMapRef.mapView.createAddPositionAndScaleOverlay();
}
- boolean needsRepaintForDistance = needsRepaintForDistance();
- boolean needsRepaintForHeading = needsRepaintForHeading();
+ final boolean needsRepaintForDistance = needsRepaintForDistance();
+ final boolean needsRepaintForHeading = needsRepaintForHeading();
if (needsRepaintForDistance) {
if (cgeoMapRef.followMyLocation) {
@@ -945,7 +1026,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
}
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.w("Failed to update location.");
}
}
@@ -1003,50 +1084,95 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
return loadTimer;
}
- /**
- * loading timer Triggers every 250ms and checks for viewport change and starts a {@link LoadRunnable}.
- */
- private Subscription startLoadTimer() {
- return Schedulers.newThread().schedulePeriodically(new Action1<Scheduler.Inner>() {
- @Override
- public void call(Scheduler.Inner inner) {
- try {
- if (mapView != null) {
- // get current viewport
- final Viewport viewportNow = mapView.getViewport();
- // Since zoomNow is used only for local comparison purposes,
- // it is ok to use the Google Maps compatible zoom level of OSM Maps
- final int zoomNow = mapView.getMapZoomLevel();
-
- // check if map moved or zoomed
- //TODO Portree Use Rectangle inside with bigger search window. That will stop reloading on every move
- final boolean moved = markersInvalidated || (isLiveEnabled && !downloaded) || (viewport == null) || zoomNow != zoom ||
- (mapMoved(viewport, viewportNow) && (cachesCnt <= 0 || CollectionUtils.isEmpty(caches) || !viewport.includes(viewportNow)));
-
- // update title on any change
- if (moved || !viewportNow.equals(viewport)) {
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
- }
- zoom = zoomNow;
+ private static final class LoadTimerAction implements Action0, Subscription {
- // save new values
- if (moved) {
- markersInvalidated = false;
+ private volatile boolean isUnsubscribed = false;
- long currentTime = System.currentTimeMillis();
+ private Scheduler.Worker worker;
- if (1000 < (currentTime - loadThreadRun)) {
- viewport = viewportNow;
- loadExecutor.execute(new LoadRunnable(viewport));
- }
+ @NonNull private final WeakReference<CGeoMap> mapRef;
+
+ public LoadTimerAction(@NonNull final CGeoMap map, final Scheduler.Worker worker) {
+ this.mapRef = new WeakReference<CGeoMap>(map);
+ this.worker = worker;
+ }
+
+ @Override
+ public void call() {
+ final CGeoMap map = mapRef.get();
+ if (map == null) {
+ return;
+ }
+ try {
+ if (map.mapView != null && !isUnsubscribed) {
+ // get current viewport
+ final Viewport viewportNow = map.mapView.getViewport();
+ // Since zoomNow is used only for local comparison purposes,
+ // it is ok to use the Google Maps compatible zoom level of OSM Maps
+ final int zoomNow = map.mapView.getMapZoomLevel();
+
+ // check if map moved or zoomed
+ //TODO Portree Use Rectangle inside with bigger search window. That will stop reloading on every move
+ final boolean moved = map.markersInvalidated || (map.isLiveEnabled && !map.downloaded) || (map.viewport == null) || zoomNow != map.zoom ||
+ (mapMoved(map.viewport, viewportNow) && (map.cachesCnt <= 0 || CollectionUtils.isEmpty(map.caches) || !map.viewport.includes(viewportNow)));
+
+ // update title on any change
+ if (moved || !viewportNow.equals(map.viewport)) {
+ map.displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ }
+ map.zoom = zoomNow;
+
+ // save new values
+ if (moved) {
+ map.markersInvalidated = false;
+
+ final long currentTime = System.currentTimeMillis();
+
+ if (1000 < (currentTime - map.loadThreadRun)) {
+ map.viewport = viewportNow;
+ loadExecutor.execute(new LoadRunnable(map));
}
}
+ }
- } catch (Exception e) {
- Log.w("CGeoMap.startLoadtimer.start", e);
+ } catch (final Exception e) {
+ Log.w("CGeoMap.startLoadtimer.start", e);
+ }
+
+ if (!isUnsubscribed) {
+ if (worker == null) {
+ worker = Schedulers.newThread().createWorker();
}
+ worker.schedule(this, 250, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ @Override
+ public void unsubscribe() {
+ isUnsubscribed = true;
+ if (worker != null) {
+ worker.unsubscribe();
+ worker = null;
}
- }, 250, 250, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public boolean isUnsubscribed() {
+ return isUnsubscribed;
+ }
+ }
+
+ /**
+ * loading timer Triggers every 250ms and checks for viewport change and starts a {@link LoadRunnable}.
+ */
+ private Subscription startLoadTimer() {
+ // We cannot use schedulePeriodically with RxJava 0.19 and earlier because the unsubscription
+ // mechanism fails. As a consequence, we reschedule periodically by hand as long as we are not
+ // unsubscribed. There may be a small drift, but it has no consequence.
+ final Scheduler.Worker worker = Schedulers.newThread().createWorker();
+ final LoadTimerAction action = new LoadTimerAction(this, worker);
+ worker.schedule(action, 250, TimeUnit.MILLISECONDS);
+ return action;
}
/**
@@ -1066,79 +1192,87 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
* started by {@link LoadTimer}
*/
- private class LoadRunnable extends DoRunnable {
+ private static class LoadRunnable extends DoRunnable {
- public LoadRunnable(final Viewport viewport) {
- super(viewport);
+ public LoadRunnable(@NonNull final CGeoMap map) {
+ super(map);
}
@Override
public void run() {
- try {
- showProgressHandler.sendEmptyMessage(SHOW_PROGRESS);
- loadThreadRun = System.currentTimeMillis();
-
- SearchResult searchResult;
- if (mapMode == MapMode.LIVE) {
- searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(DataStore.loadStoredInViewport(viewport, Settings.getCacheType()));
- } else {
- // map started from another activity
- searchResult = searchIntent != null ? new SearchResult(searchIntent) : new SearchResult();
- if (geocodeIntent != null) {
- searchResult.addGeocode(geocodeIntent);
- }
- }
- // live mode search result
- if (isLiveEnabled) {
- searchResult.addSearchResult(DataStore.loadCachedInViewport(viewport, Settings.getCacheType()));
- }
+ final CGeoMap map = getMap();
+ if (map != null) {
+ map.doLoadRun();
+ }
+ }
+ }
- downloaded = true;
- Set<Geocache> cachesFromSearchResult = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS);
- // update the caches
- // new collection type needs to remove first
- caches.removeAll(cachesFromSearchResult);
- caches.addAll(cachesFromSearchResult);
+ private void doLoadRun() {
+ try {
+ showProgressHandler.sendEmptyMessage(SHOW_PROGRESS);
+ loadThreadRun = System.currentTimeMillis();
- final boolean excludeMine = Settings.isExcludeMyCaches();
- final boolean excludeDisabled = Settings.isExcludeDisabledCaches();
- if (mapMode == MapMode.LIVE) {
- CGeoMap.filter(caches);
+ SearchResult searchResult;
+ if (mapMode == MapMode.LIVE) {
+ searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(DataStore.loadStoredInViewport(viewport, Settings.getCacheType()));
+ } else {
+ // map started from another activity
+ searchResult = searchIntent != null ? new SearchResult(searchIntent) : new SearchResult();
+ if (geocodeIntent != null) {
+ searchResult.addGeocode(geocodeIntent);
}
- countVisibleCaches();
- if (cachesCnt < Settings.getWayPointsThreshold() || geocodeIntent != null) {
- // we don't want to see any stale waypoints
- waypoints.clear();
- if (isLiveEnabled || mapMode == MapMode.LIVE
- || mapMode == MapMode.COORDS) {
- //All visible waypoints
- CacheType type = Settings.getCacheType();
- Set<Waypoint> waypointsInViewport = DataStore.loadWaypoints(viewport, excludeMine, excludeDisabled, type);
- waypoints.addAll(waypointsInViewport);
- }
- else {
- //All waypoints from the viewed caches
- for (Geocache c : caches.getAsList()) {
- waypoints.addAll(c.getWaypoints());
- }
- }
+ }
+ // live mode search result
+ if (isLiveEnabled) {
+ searchResult.addSearchResult(DataStore.loadCachedInViewport(viewport, Settings.getCacheType()));
+ }
+
+ downloaded = true;
+ final Set<Geocache> cachesFromSearchResult = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS);
+ // update the caches
+ // new collection type needs to remove first
+ caches.removeAll(cachesFromSearchResult);
+ caches.addAll(cachesFromSearchResult);
+
+ final boolean excludeMine = Settings.isExcludeMyCaches();
+ final boolean excludeDisabled = Settings.isExcludeDisabledCaches();
+ if (mapMode == MapMode.LIVE) {
+ CGeoMap.filter(caches);
+ }
+ countVisibleCaches();
+ if (cachesCnt < Settings.getWayPointsThreshold() || geocodeIntent != null) {
+ // we don't want to see any stale waypoints
+ waypoints.clear();
+ if (isLiveEnabled || mapMode == MapMode.LIVE
+ || mapMode == MapMode.COORDS) {
+ //All visible waypoints
+ final CacheType type = Settings.getCacheType();
+ final Set<Waypoint> waypointsInViewport = DataStore.loadWaypoints(viewport, excludeMine, excludeDisabled, type);
+ waypoints.addAll(waypointsInViewport);
}
else {
- // we don't want to see any stale waypoints when above threshold
- waypoints.clear();
+ //All waypoints from the viewed caches
+ for (final Geocache c : caches.getAsList()) {
+ waypoints.addAll(c.getWaypoints());
+ }
}
+ }
+ else {
+ // we don't want to see any stale waypoints when above threshold
+ waypoints.clear();
+ }
- //render
- displayExecutor.execute(new DisplayRunnable(viewport));
+ //render
+ displayExecutor.execute(new DisplayRunnable(this));
- if (isLiveEnabled) {
- downloadExecutor.execute(new DownloadRunnable(viewport));
- }
- lastSearchResult = searchResult;
- } finally {
- showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress
+ if (isLiveEnabled) {
+ downloadExecutor.execute(new DownloadRunnable(this));
}
+ lastSearchResult = searchResult;
+ } finally {
+ showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress
}
+
}
/**
@@ -1146,111 +1280,125 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
* Started by {@link LoadRunnable}.
*/
- private class DownloadRunnable extends DoRunnable {
+ private static class DownloadRunnable extends DoRunnable {
- public DownloadRunnable(final Viewport viewport) {
- super(viewport);
+ public DownloadRunnable(final CGeoMap map) {
+ super(map);
}
@Override
public void run() {
- try {
- showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); // show progress
- if (Settings.isGCConnectorActive()) {
- if (tokens == null) {
- tokens = GCLogin.getInstance().getMapTokens();
- if (noMapTokenHandler != null && (StringUtils.isEmpty(tokens.getUserSession()) || StringUtils.isEmpty(tokens.getSessionToken()))) {
- tokens = null;
- noMapTokenHandler.sendEmptyMessage(0);
- }
+ final CGeoMap map = getMap();
+ if (map != null) {
+ map.doDownloadRun();
+ }
+ }
+ }
+
+ private void doDownloadRun() {
+ try {
+ showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); // show progress
+ if (Settings.isGCConnectorActive()) {
+ if (tokens == null) {
+ tokens = GCLogin.getInstance().getMapTokens();
+ if (noMapTokenHandler != null && (StringUtils.isEmpty(tokens.getUserSession()) || StringUtils.isEmpty(tokens.getSessionToken()))) {
+ tokens = null;
+ noMapTokenHandler.sendEmptyMessage(0);
}
}
- final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens);
- downloaded = true;
-
- Set<Geocache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
- CGeoMap.filter(result);
- // update the caches
- // first remove filtered out
- final Set<String> filteredCodes = searchResult.getFilteredGeocodes();
- Log.d("Filtering out " + filteredCodes.size() + " caches: " + filteredCodes.toString());
- caches.removeAll(DataStore.loadCaches(filteredCodes, LoadFlags.LOAD_CACHE_ONLY));
- DataStore.removeCaches(filteredCodes, EnumSet.of(RemoveFlag.REMOVE_CACHE));
- // new collection type needs to remove first to refresh
- caches.removeAll(result);
- caches.addAll(result);
- lastSearchResult = searchResult;
-
- //render
- displayExecutor.execute(new DisplayRunnable(viewport));
-
- } catch (ThreadDeath e) {
- Log.d("DownloadThread stopped");
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
- } finally {
- showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress
}
+ final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens);
+ downloaded = true;
+
+ final Set<Geocache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
+ CGeoMap.filter(result);
+ // update the caches
+ // first remove filtered out
+ final Set<String> filteredCodes = searchResult.getFilteredGeocodes();
+ Log.d("Filtering out " + filteredCodes.size() + " caches: " + filteredCodes.toString());
+ caches.removeAll(DataStore.loadCaches(filteredCodes, LoadFlags.LOAD_CACHE_ONLY));
+ DataStore.removeCaches(filteredCodes, EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ // new collection type needs to remove first to refresh
+ caches.removeAll(result);
+ caches.addAll(result);
+ lastSearchResult = searchResult;
+
+ //render
+ displayExecutor.execute(new DisplayRunnable(this));
+
+ } catch (final ThreadDeath e) {
+ Log.d("DownloadThread stopped");
+ displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ } finally {
+ showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress
}
}
/**
* Thread to Display (down)loaded caches. Started by {@link LoadRunnable} and {@link DownloadRunnable}
*/
- private class DisplayRunnable extends DoRunnable {
+ private static class DisplayRunnable extends DoRunnable {
- public DisplayRunnable(final Viewport viewport) {
- super(viewport);
+ public DisplayRunnable(@NonNull final CGeoMap map) {
+ super(map);
}
@Override
public void run() {
- try {
- showProgressHandler.sendEmptyMessage(SHOW_PROGRESS);
- if (mapView == null || caches == null) {
- throw new ThreadDeath();
- }
-
- // display caches
- final List<Geocache> cachesToDisplay = caches.getAsList();
- final List<Waypoint> waypointsToDisplay = new ArrayList<Waypoint>(waypoints);
- final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<CachesOverlayItemImpl>();
+ final CGeoMap map = getMap();
+ if (map != null) {
+ map.doDisplayRun();
+ }
+ }
+ }
- if (!cachesToDisplay.isEmpty()) {
- // Only show waypoints for single view or setting
- // when less than showWaypointsthreshold Caches shown
- if (mapMode == MapMode.SINGLE || (cachesCnt < Settings.getWayPointsThreshold())) {
- for (Waypoint waypoint : waypointsToDisplay) {
+ private void doDisplayRun() {
+ try {
+ showProgressHandler.sendEmptyMessage(SHOW_PROGRESS);
+ if (mapView == null || caches == null) {
+ throw new ThreadDeath();
+ }
- if (waypoint == null || waypoint.getCoords() == null) {
- continue;
- }
+ // display caches
+ final List<Geocache> cachesToDisplay = caches.getAsList();
+ final List<Waypoint> waypointsToDisplay = new ArrayList<Waypoint>(waypoints);
+ final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<CachesOverlayItemImpl>();
- itemsToDisplay.add(getWaypointItem(waypoint));
- }
- }
- for (Geocache cache : cachesToDisplay) {
+ if (!cachesToDisplay.isEmpty()) {
+ // Only show waypoints for single view or setting
+ // when less than showWaypointsthreshold Caches shown
+ if (mapMode == MapMode.SINGLE || (cachesCnt < Settings.getWayPointsThreshold())) {
+ for (final Waypoint waypoint : waypointsToDisplay) {
- if (cache == null || cache.getCoords() == null) {
+ if (waypoint == null || waypoint.getCoords() == null) {
continue;
}
- itemsToDisplay.add(getCacheItem(cache));
- }
- overlayCaches.updateItems(itemsToDisplay);
- displayHandler.sendEmptyMessage(INVALIDATE_MAP);
+ itemsToDisplay.add(getWaypointItem(waypoint));
+ }
+ }
+ for (final Geocache cache : cachesToDisplay) {
- } else {
- overlayCaches.updateItems(itemsToDisplay);
- displayHandler.sendEmptyMessage(INVALIDATE_MAP);
+ if (cache == null || cache.getCoords() == null) {
+ continue;
+ }
+ itemsToDisplay.add(getCacheItem(cache));
}
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
- } catch (ThreadDeath e) {
- Log.d("DisplayThread stopped");
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
- } finally {
- showProgressHandler.sendEmptyMessage(HIDE_PROGRESS);
+ overlayCaches.updateItems(itemsToDisplay);
+ displayHandler.sendEmptyMessage(INVALIDATE_MAP);
+
+ } else {
+ overlayCaches.updateItems(itemsToDisplay);
+ displayHandler.sendEmptyMessage(INVALIDATE_MAP);
}
+
+ displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ } catch (final ThreadDeath e) {
+ Log.d("DisplayThread stopped");
+ displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ } finally {
+ showProgressHandler.sendEmptyMessage(HIDE_PROGRESS);
}
}
@@ -1268,10 +1416,15 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private static abstract class DoRunnable implements Runnable {
- final protected Viewport viewport;
+ private final WeakReference<CGeoMap> mapRef;
- protected DoRunnable(final Viewport viewport) {
- this.viewport = viewport;
+ protected DoRunnable(@NonNull final CGeoMap map) {
+ mapRef = new WeakReference<CGeoMap>(map);
+ }
+
+ protected @Nullable
+ final CGeoMap getMap() {
+ return mapRef.get();
}
}
@@ -1281,7 +1434,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
* @param listId
* the list to store the caches in
*/
- private void storeCaches(List<String> geocodes, int listId) {
+ private void storeCaches(final List<String> geocodes, final int listId) {
final LoadDetailsHandler loadDetailsHandler = new LoadDetailsHandler();
waitDialog = new ProgressDialog(activity);
@@ -1292,19 +1445,19 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
waitDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
- public void onCancel(DialogInterface arg0) {
+ public void onCancel(final DialogInterface arg0) {
try {
if (loadDetailsThread != null) {
loadDetailsThread.stopIt();
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("CGeoMap.storeCaches.onCancel", e);
}
}
});
- float etaTime = detailTotal * 7.0f / 60.0f;
- int roundedEta = Math.round(etaTime);
+ final float etaTime = detailTotal * 7.0f / 60.0f;
+ final int roundedEta = Math.round(etaTime);
if (etaTime < 0.4) {
waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm));
} else {
@@ -1353,7 +1506,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (!DataStore.isOffline(geocode, null)) {
Geocache.storeCache(null, geocode, listId, false, handler);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("CGeoMap.LoadDetails.run", e);
} finally {
// one more cache over
@@ -1367,13 +1520,13 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
- private static synchronized void filter(Collection<Geocache> caches) {
- boolean excludeMine = Settings.isExcludeMyCaches();
- boolean excludeDisabled = Settings.isExcludeDisabledCaches();
+ private static synchronized void filter(final Collection<Geocache> caches) {
+ final boolean excludeMine = Settings.isExcludeMyCaches();
+ final boolean excludeDisabled = Settings.isExcludeDisabledCaches();
- List<Geocache> removeList = new ArrayList<Geocache>();
- for (Geocache cache : caches) {
- if ((excludeMine && cache.isFound()) || (excludeMine && cache.isOwner()) || (excludeDisabled && cache.isDisabled())) {
+ final List<Geocache> removeList = new ArrayList<Geocache>();
+ for (final Geocache cache : caches) {
+ if ((excludeMine && cache.isFound()) || (excludeMine && cache.isOwner()) || (excludeDisabled && cache.isDisabled()) || (excludeDisabled && cache.isArchived())) {
removeList.add(cache);
}
}
@@ -1410,14 +1563,14 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
// move map to view results of searchIntent
- private void centerMap(String geocodeCenter, final SearchResult searchCenter, final Geopoint coordsCenter, int[] mapState) {
+ private void centerMap(final String geocodeCenter, final SearchResult searchCenter, final Geopoint coordsCenter, final int[] mapState) {
final MapControllerImpl mapController = mapView.getMapController();
if (!centered && mapState != null) {
try {
mapController.setCenter(mapItemFactory.getGeoPointBase(new Geopoint(mapState[0] / 1.0e6, mapState[1] / 1.0e6)));
setZoom(mapState[2]);
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.e("centermap", e);
}
@@ -1441,7 +1594,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (viewport.getLatitudeSpan() != 0 && viewport.getLongitudeSpan() != 0) {
mapController.zoomToSpan((int) (viewport.getLatitudeSpan() * 1e6), (int) (viewport.getLongitudeSpan() * 1e6));
}
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.e("centermap", e);
}
@@ -1450,7 +1603,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
} else if (!centered && coordsCenter != null) {
try {
mapController.setCenter(makeGeoPoint(coordsCenter));
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("centermap", e);
}
@@ -1461,25 +1614,54 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
// switch My Location button image
private void switchMyLocationButton() {
+ myLocSwitch.setChecked(followMyLocation);
if (followMyLocation) {
- myLocSwitch.setImageResource(R.drawable.actionbar_mylocation_on);
myLocationInMiddle(app.currentGeo());
- } else {
- myLocSwitch.setImageResource(R.drawable.actionbar_mylocation_off);
}
}
// set my location listener
- private class MyLocationListener implements View.OnClickListener {
+ private static class MyLocationListener implements View.OnClickListener {
+
+ private final WeakReference<CGeoMap> mapRef;
+
+ public MyLocationListener(@NonNull final CGeoMap map) {
+ mapRef = new WeakReference<CGeoMap>(map);
+ }
+
@Override
- public void onClick(View view) {
- followMyLocation = !followMyLocation;
- switchMyLocationButton();
+ public void onClick(final View view) {
+ final CGeoMap map = mapRef.get();
+ if (map != null) {
+ map.onFollowMyLocationClicked();
+ }
}
}
- @Override
- public void onDrag() {
+ private void onFollowMyLocationClicked() {
+ followMyLocation = !followMyLocation;
+ switchMyLocationButton();
+ }
+
+ public static class MapDragListener implements OnMapDragListener {
+
+ private final WeakReference<CGeoMap> mapRef;
+
+ public MapDragListener(@NonNull final CGeoMap map) {
+ mapRef = new WeakReference<CGeoMap>(map);
+ }
+
+ @Override
+ public void onDrag() {
+ final CGeoMap map = mapRef.get();
+ if (map != null) {
+ map.onDrag();
+ }
+ }
+
+ }
+
+ private void onDrag() {
if (followMyLocation) {
followMyLocation = false;
switchMyLocationButton();
@@ -1491,15 +1673,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
return mapItemFactory.getGeoPointBase(coords);
}
- // close activity and open homescreen
- @Override
- public void goHome(View view) {
- ActivityMixin.goHome(activity);
- }
-
@Override
public View makeView() {
- ImageView imageView = new ImageView(activity);
+ final ImageView imageView = new ImageView(activity);
imageView.setScaleType(ScaleType.CENTER);
imageView.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
return imageView;
@@ -1637,7 +1813,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private CachesOverlayItemImpl getWaypointItem(final Waypoint waypoint) {
final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(waypoint, waypoint.getWaypointType().applyDistanceRule());
- Drawable marker = getResources().getDrawable(!waypoint.isVisited() ? R.drawable.marker : R.drawable.marker_transparent);
+ final Drawable marker = getResources().getDrawable(!waypoint.isVisited() ? R.drawable.marker : R.drawable.marker_transparent);
final Drawable[] layers = new Drawable[] {
marker,
getResources().getDrawable(waypoint.getWaypointType().markerId)
diff --git a/main/src/cgeo/geocaching/maps/CachesOverlay.java b/main/src/cgeo/geocaching/maps/CachesOverlay.java
index 0c7c296..8607c88 100644
--- a/main/src/cgeo/geocaching/maps/CachesOverlay.java
+++ b/main/src/cgeo/geocaching/maps/CachesOverlay.java
@@ -211,9 +211,9 @@ public class CachesOverlay extends AbstractItemizedOverlay {
progress.show(context, context.getResources().getString(R.string.map_live), context.getResources().getString(R.string.cache_dialog_loading_details), true, null);
- CachesOverlayItemImpl item = null;
// prevent concurrent changes
getOverlayImpl().lock();
+ CachesOverlayItemImpl item = null;
try {
if (index < items.size()) {
item = items.get(index);
diff --git a/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java b/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java
index 6b34b75..63fcd73 100644
--- a/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java
+++ b/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java
@@ -5,7 +5,6 @@ import cgeo.geocaching.maps.interfaces.MapProjectionImpl;
import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OverlayImpl;
-import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Point;
import android.location.Location;
@@ -18,10 +17,10 @@ public class PositionAndScaleOverlay implements GeneralOverlay {
PositionDrawer positionDrawer = null;
ScaleDrawer scaleDrawer = null;
- public PositionAndScaleOverlay(Activity activity, OverlayImpl ovlImpl) {
+ public PositionAndScaleOverlay(OverlayImpl ovlImpl) {
this.ovlImpl = ovlImpl;
- positionDrawer = new PositionDrawer(activity);
- scaleDrawer = new ScaleDrawer(activity);
+ positionDrawer = new PositionDrawer();
+ scaleDrawer = new ScaleDrawer();
}
public void setCoordinates(Location coordinatesIn) {
diff --git a/main/src/cgeo/geocaching/maps/PositionDrawer.java b/main/src/cgeo/geocaching/maps/PositionDrawer.java
index 1a5dcaf..0e20e7c 100644
--- a/main/src/cgeo/geocaching/maps/PositionDrawer.java
+++ b/main/src/cgeo/geocaching/maps/PositionDrawer.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.maps;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.maps.interfaces.GeoPointImpl;
@@ -7,7 +8,6 @@ import cgeo.geocaching.maps.interfaces.MapItemFactory;
import cgeo.geocaching.maps.interfaces.MapProjectionImpl;
import cgeo.geocaching.settings.Settings;
-import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
@@ -36,11 +36,9 @@ public class PositionDrawer {
private PaintFlagsDrawFilter setfil = null;
private PaintFlagsDrawFilter remfil = null;
private PositionHistory positionHistory = new PositionHistory();
- private Activity activity;
private MapItemFactory mapItemFactory;
- public PositionDrawer(Activity activity) {
- this.activity = activity;
+ public PositionDrawer() {
this.mapItemFactory = Settings.getMapProvider().getMapItemFactory();
}
@@ -144,7 +142,7 @@ public class PositionDrawer {
}
if (arrow == null) {
- arrow = BitmapFactory.decodeResource(activity.getResources(), R.drawable.my_location_chevron);
+ arrow = BitmapFactory.decodeResource(CgeoApplication.getInstance().getResources(), R.drawable.my_location_chevron);
widthArrowHalf = arrow.getWidth() / 2;
heightArrowHalf = arrow.getHeight() / 2;
}
diff --git a/main/src/cgeo/geocaching/maps/ScaleDrawer.java b/main/src/cgeo/geocaching/maps/ScaleDrawer.java
index fb46408..95c987d 100644
--- a/main/src/cgeo/geocaching/maps/ScaleDrawer.java
+++ b/main/src/cgeo/geocaching/maps/ScaleDrawer.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.maps;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.maps.interfaces.GeoPointImpl;
@@ -7,12 +8,13 @@ import cgeo.geocaching.maps.interfaces.MapViewImpl;
import org.apache.commons.lang3.tuple.ImmutablePair;
-import android.app.Activity;
+import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.DisplayMetrics;
+import android.view.WindowManager;
public class ScaleDrawer {
private static final double SCALE_WIDTH_FACTOR = 1.0 / 2.5;
@@ -22,9 +24,10 @@ public class ScaleDrawer {
private BlurMaskFilter blur = null;
private float pixelDensity = 0;
- public ScaleDrawer(Activity activity) {
+ public ScaleDrawer() {
DisplayMetrics metrics = new DisplayMetrics();
- activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ WindowManager windowManager = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE);
+ windowManager.getDefaultDisplay().getMetrics(metrics);
pixelDensity = metrics.density;
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java
index a98241f..2a29cc9 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.maps.google;
+import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.activity.FilteredActivity;
import cgeo.geocaching.maps.AbstractMap;
import cgeo.geocaching.maps.CGeoMap;
@@ -97,6 +98,11 @@ public class GoogleMapActivity extends MapActivity implements MapActivityImpl, F
}
@Override
+ public void navigateUp(View view) {
+ ActivityMixin.navigateUp(this);
+ }
+
+ @Override
public void superOnResume() {
super.onResume();
}
@@ -116,12 +122,6 @@ public class GoogleMapActivity extends MapActivity implements MapActivityImpl, F
return super.onPrepareOptionsMenu(menu);
}
- // close activity and open homescreen
- @Override
- public void goHome(View view) {
- mapBase.goHome(view);
- }
-
@Override
public void showFilterMenu(View view) {
// do nothing, the filter bar only shows the global filter
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
index 610dbe1..ea815ab 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
@@ -20,7 +20,6 @@ import com.google.android.maps.MapView;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.eclipse.jdt.annotation.NonNull;
-import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
@@ -39,16 +38,23 @@ public class GoogleMapView extends MapView implements MapViewImpl {
public GoogleMapView(Context context, AttributeSet attrs) {
super(context, attrs);
- gestureDetector = new GestureDetector(context, new GestureListener());
+ initialize(context);
}
public GoogleMapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- gestureDetector = new GestureDetector(context, new GestureListener());
+ initialize(context);
}
public GoogleMapView(Context context, String apiKey) {
super(context, apiKey);
+ initialize(context);
+ }
+
+ private void initialize(Context context) {
+ if (isInEditMode()) {
+ return;
+ }
gestureDetector = new GestureDetector(context, new GestureListener());
}
@@ -120,9 +126,9 @@ public class GoogleMapView extends MapView implements MapViewImpl {
}
@Override
- public PositionAndScaleOverlay createAddPositionAndScaleOverlay(Activity activity) {
+ public PositionAndScaleOverlay createAddPositionAndScaleOverlay() {
- GoogleOverlay ovl = new GoogleOverlay(activity);
+ GoogleOverlay ovl = new GoogleOverlay();
getOverlays().add(ovl);
return (PositionAndScaleOverlay) ovl.getBase();
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java b/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java
index 0a5cf69..c684b9a 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java
@@ -8,7 +8,6 @@ import cgeo.geocaching.maps.interfaces.OverlayImpl;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
-import android.app.Activity;
import android.graphics.Canvas;
import java.util.concurrent.locks.Lock;
@@ -19,8 +18,8 @@ public class GoogleOverlay extends Overlay implements OverlayImpl {
private PositionAndScaleOverlay overlayBase = null;
private Lock lock = new ReentrantLock();
- public GoogleOverlay(Activity activityIn) {
- overlayBase = new PositionAndScaleOverlay(activityIn, this);
+ public GoogleOverlay() {
+ overlayBase = new PositionAndScaleOverlay(this);
}
@Override
diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java b/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java
index e7deebd..3596d5f 100644
--- a/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java
+++ b/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java
@@ -33,6 +33,5 @@ public interface MapActivityImpl {
boolean superOnOptionsItemSelected(MenuItem item);
- public abstract void goHome(View view);
-
+ public abstract void navigateUp(View view);
}
diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java b/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java
index 5ae8e15..4a6d733 100644
--- a/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java
+++ b/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java
@@ -6,7 +6,6 @@ import cgeo.geocaching.maps.PositionAndScaleOverlay;
import org.eclipse.jdt.annotation.NonNull;
-import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
@@ -47,7 +46,7 @@ public interface MapViewImpl {
CachesOverlay createAddMapOverlay(Context context, Drawable drawable);
- PositionAndScaleOverlay createAddPositionAndScaleOverlay(Activity activity);
+ PositionAndScaleOverlay createAddPositionAndScaleOverlay();
void setMapSource();
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java
index a0384b8..94213ba 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.maps.mapsforge;
+import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.activity.FilteredActivity;
import cgeo.geocaching.maps.AbstractMap;
import cgeo.geocaching.maps.CGeoMap;
@@ -111,10 +112,9 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl
return super.onPrepareOptionsMenu(menu);
}
- // close activity and open homescreen
@Override
- public void goHome(View view) {
- mapBase.goHome(view);
+ public void navigateUp(View view) {
+ ActivityMixin.navigateUp(this);
}
@Override
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
index 7a5aab2..d95cc80 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
@@ -24,7 +24,6 @@ import org.mapsforge.android.maps.mapgenerator.MapGeneratorInternal;
import org.mapsforge.android.maps.overlay.Overlay;
import org.mapsforge.core.GeoPoint;
-import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
@@ -43,6 +42,13 @@ public class MapsforgeMapView extends MapView implements MapViewImpl {
public MapsforgeMapView(Context context, AttributeSet attrs) {
super(context, attrs);
+ initialize(context);
+ }
+
+ private void initialize(Context context) {
+ if (isInEditMode()) {
+ return;
+ }
gestureDetector = new GestureDetector(context, new GestureListener());
if (Settings.isScaleMapsforgeText()) {
this.setTextScale(getResources().getDisplayMetrics().density);
@@ -105,8 +111,8 @@ public class MapsforgeMapView extends MapView implements MapViewImpl {
}
@Override
- public PositionAndScaleOverlay createAddPositionAndScaleOverlay(Activity activity) {
- MapsforgeOverlay ovl = new MapsforgeOverlay(activity);
+ public PositionAndScaleOverlay createAddPositionAndScaleOverlay() {
+ MapsforgeOverlay ovl = new MapsforgeOverlay();
getOverlays().add(ovl);
return (PositionAndScaleOverlay) ovl.getBase();
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
index 74a8601..3df4ab0 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
@@ -8,7 +8,6 @@ import cgeo.geocaching.maps.interfaces.OverlayImpl;
import org.mapsforge.android.maps.Projection;
import org.mapsforge.android.maps.overlay.Overlay;
-import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Point;
@@ -20,8 +19,8 @@ public class MapsforgeOverlay extends Overlay implements OverlayImpl {
private PositionAndScaleOverlay overlayBase = null;
private Lock lock = new ReentrantLock();
- public MapsforgeOverlay(Activity activityIn) {
- overlayBase = new PositionAndScaleOverlay(activityIn, this);
+ public MapsforgeOverlay() {
+ overlayBase = new PositionAndScaleOverlay(this);
}
@Override
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java
index 33ed30e..daeb2b8 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.maps.mapsforge.v024;
+import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.activity.FilteredActivity;
import cgeo.geocaching.maps.AbstractMap;
import cgeo.geocaching.maps.CGeoMap;
@@ -111,10 +112,9 @@ public class MapsforgeMapActivity024 extends MapActivity implements MapActivityI
return super.onPrepareOptionsMenu(menu);
}
- // close activity and open homescreen
@Override
- public void goHome(View view) {
- mapBase.goHome(view);
+ public void navigateUp(View view) {
+ ActivityMixin.navigateUp(this);
}
@Override
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
index 4fa4e02..8dd15fc 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
@@ -21,7 +21,6 @@ import org.mapsforge.android.mapsold.MapViewMode;
import org.mapsforge.android.mapsold.Overlay;
import org.mapsforge.android.mapsold.Projection;
-import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
@@ -37,6 +36,13 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl {
public MapsforgeMapView024(Context context, AttributeSet attrs) {
super(context, attrs);
+ initialize(context);
+ }
+
+ private void initialize(Context context) {
+ if (isInEditMode()) {
+ return;
+ }
gestureDetector = new GestureDetector(context, new GestureListener());
}
@@ -96,8 +102,8 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl {
}
@Override
- public PositionAndScaleOverlay createAddPositionAndScaleOverlay(Activity activity) {
- MapsforgeOverlay ovl = new MapsforgeOverlay(activity);
+ public PositionAndScaleOverlay createAddPositionAndScaleOverlay() {
+ MapsforgeOverlay ovl = new MapsforgeOverlay();
getOverlays().add(ovl);
return (PositionAndScaleOverlay) ovl.getBase();
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java
index 655e0b9..bfb3548 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java
@@ -8,7 +8,6 @@ import cgeo.geocaching.maps.interfaces.OverlayImpl;
import org.mapsforge.android.mapsold.Overlay;
import org.mapsforge.android.mapsold.Projection;
-import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Point;
@@ -20,8 +19,8 @@ public class MapsforgeOverlay extends Overlay implements OverlayImpl {
private PositionAndScaleOverlay overlayBase = null;
private Lock lock = new ReentrantLock();
- public MapsforgeOverlay(Activity activityIn) {
- overlayBase = new PositionAndScaleOverlay(activityIn, this);
+ public MapsforgeOverlay() {
+ overlayBase = new PositionAndScaleOverlay(this);
}
@Override
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java
index 9c55fe9..ce832fb 100644
--- a/main/src/cgeo/geocaching/network/HtmlImage.java
+++ b/main/src/cgeo/geocaching/network/HtmlImage.java
@@ -13,21 +13,20 @@ import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.RxUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
+
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+
import rx.Observable;
import rx.Observable.OnSubscribe;
-import rx.Scheduler;
-import rx.Scheduler.Inner;
import rx.Subscriber;
-import rx.functions.Action1;
+import rx.functions.Action0;
import rx.functions.Func0;
import rx.functions.Func1;
-import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject;
import rx.subscriptions.CompositeSubscription;
@@ -44,6 +43,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Date;
+import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -92,10 +92,9 @@ public class HtmlImage implements Html.ImageGetter {
// Background loading
final private PublishSubject<Observable<String>> loading = PublishSubject.create();
- final Observable<String> waitForEnd = Observable.merge(loading).publish().refCount();
+ final private Observable<String> waitForEnd = Observable.merge(loading).publish().refCount();
final CompositeSubscription subscription = new CompositeSubscription(waitForEnd.subscribe());
- final private Scheduler downloadScheduler = Schedulers.executor(new ThreadPoolExecutor(10, 10, 5, TimeUnit.SECONDS,
- new LinkedBlockingQueue<Runnable>()));
+ final private Executor downloadExecutor = new ThreadPoolExecutor(10, 10, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
public HtmlImage(final String geocode, final boolean returnErrorImage, final int listId, final boolean onlySave) {
this.geocode = geocode;
@@ -122,7 +121,7 @@ public class HtmlImage implements Html.ImageGetter {
}));
return null;
}
- return drawable.toBlockingObservable().lastOrDefault(null);
+ return drawable.toBlocking().lastOrDefault(null);
}
// Caches are loaded from disk on a computation scheduler to avoid using more threads than cores while decoding
@@ -152,9 +151,9 @@ public class HtmlImage implements Html.ImageGetter {
@Override
public void call(final Subscriber<? super BitmapDrawable> subscriber) {
subscription.add(subscriber);
- subscriber.add(RxUtils.computationScheduler.schedule(new Action1<Inner>() {
+ subscriber.add(RxUtils.computationScheduler.createWorker().schedule(new Action0() {
@Override
- public void call(final Inner inner) {
+ public void call() {
final Pair<BitmapDrawable, Boolean> loaded = loadFromDisk();
final BitmapDrawable bitmap = loaded.getLeft();
if (loaded.getRight()) {
@@ -165,12 +164,11 @@ public class HtmlImage implements Html.ImageGetter {
if (bitmap != null && !onlySave) {
subscriber.onNext(bitmap);
}
- subscriber.add(downloadScheduler.schedule(new Action1<Inner>() {
- @Override
- public void call(final Inner inner) {
+ downloadExecutor.execute(new Runnable() {
+ @Override public void run() {
downloadAndSave(subscriber);
}
- }));
+ });
}
}));
}
@@ -205,9 +203,9 @@ public class HtmlImage implements Html.ImageGetter {
if (onlySave) {
subscriber.onCompleted();
} else {
- RxUtils.computationScheduler.schedule(new Action1<Inner>() {
+ RxUtils.computationScheduler.createWorker().schedule(new Action0() {
@Override
- public void call(final Inner inner) {
+ public void call() {
final Pair<BitmapDrawable, Boolean> loaded = loadFromDisk();
final BitmapDrawable image = loaded.getLeft();
if (image != null) {
@@ -225,12 +223,12 @@ public class HtmlImage implements Html.ImageGetter {
});
}
- public void waitForBackgroundLoading(@Nullable final CancellableHandler handler) {
+ public Observable<String> waitForEndObservable(@Nullable final CancellableHandler handler) {
if (handler != null) {
handler.unsubscribeIfCancelled(subscription);
}
loading.onCompleted();
- waitForEnd.toBlockingObservable().lastOrDefault(null);
+ return waitForEnd;
}
/**
diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
index e74751b..eb56f0b 100644
--- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
@@ -106,7 +106,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState, R.layout.authorization_activity, true);
+ super.onCreate(savedInstanceState, R.layout.authorization_activity);
Bundle extras = getIntent().getExtras();
if (extras != null) {
diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java
index 4055f01..bf9ebdf 100644
--- a/main/src/cgeo/geocaching/network/StatusUpdater.java
+++ b/main/src/cgeo/geocaching/network/StatusUpdater.java
@@ -5,10 +5,9 @@ import cgeo.geocaching.utils.Version;
import org.json.JSONException;
import org.json.JSONObject;
-import rx.Scheduler;
+import rx.functions.Action0;
import rx.schedulers.Schedulers;
import rx.subjects.BehaviorSubject;
-import rx.functions.Action1;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
@@ -52,9 +51,9 @@ public class StatusUpdater {
final static public BehaviorSubject<Status> latestStatus = BehaviorSubject.create(Status.defaultStatus(null));
static {
- Schedulers.io().schedulePeriodically(new Action1<Scheduler.Inner>() {
+ Schedulers.io().createWorker().schedulePeriodically(new Action0() {
@Override
- public void call(final Scheduler.Inner inner) {
+ public void call() {
final JSONObject response =
Network.requestJSON("http://status.cgeo.org/api/status.json",
new Parameters("version_code", String.valueOf(Version.getVersionCode(CgeoApplication.getInstance())),
diff --git a/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java b/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java
index 45559f4..21cf089 100644
--- a/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java
+++ b/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.search;
import org.apache.commons.lang3.StringUtils;
+
import rx.functions.Func1;
import android.content.Context;
@@ -14,11 +15,11 @@ import android.widget.Filter;
*/
public class AutoCompleteAdapter extends ArrayAdapter<String> {
- private final String[] EMPTY = new String[0];
+ private final static String[] EMPTY = new String[0];
private String[] suggestions = EMPTY;
private final Func1<String, String[]> suggestionFunction;
- public AutoCompleteAdapter(Context context, int textViewResourceId, final Func1<String, String[]> suggestionFunction) {
+ public AutoCompleteAdapter(final Context context, final int textViewResourceId, final Func1<String, String[]> suggestionFunction) {
super(context, textViewResourceId);
this.suggestionFunction = suggestionFunction;
}
@@ -29,7 +30,7 @@ public class AutoCompleteAdapter extends ArrayAdapter<String> {
}
@Override
- public String getItem(int index) {
+ public String getItem(final int index) {
return suggestions[index];
}
@@ -38,14 +39,14 @@ public class AutoCompleteAdapter extends ArrayAdapter<String> {
return new Filter() {
@Override
- protected FilterResults performFiltering(CharSequence constraint) {
- FilterResults filterResults = new FilterResults();
+ protected FilterResults performFiltering(final CharSequence constraint) {
+ final FilterResults filterResults = new FilterResults();
if (constraint == null) {
return filterResults;
}
- String trimmed = StringUtils.trim(constraint.toString());
+ final String trimmed = StringUtils.trim(constraint.toString());
if (StringUtils.length(trimmed) >= 2) {
- String[] newResults = suggestionFunction.call(trimmed);
+ final String[] newResults = suggestionFunction.call(trimmed);
// Assign the data to the FilterResults, but do not yet store in the global member.
// Otherwise we might invalidate the adapter and cause an IllegalStateException.
@@ -56,7 +57,7 @@ public class AutoCompleteAdapter extends ArrayAdapter<String> {
}
@Override
- protected void publishResults(CharSequence constraint, FilterResults filterResults) {
+ protected void publishResults(final CharSequence constraint, final FilterResults filterResults) {
if (filterResults != null && filterResults.count > 0) {
suggestions = (String[]) filterResults.values;
notifyDataSetChanged();
diff --git a/main/src/cgeo/geocaching/search/SearchSuggestionCursor.java b/main/src/cgeo/geocaching/search/SearchSuggestionCursor.java
new file mode 100644
index 0000000..350e23a
--- /dev/null
+++ b/main/src/cgeo/geocaching/search/SearchSuggestionCursor.java
@@ -0,0 +1,46 @@
+package cgeo.geocaching.search;
+
+import cgeo.geocaching.Intents;
+import cgeo.geocaching.enumerations.CacheType;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+import android.app.SearchManager;
+import android.database.MatrixCursor;
+import android.provider.BaseColumns;
+
+/**
+ * Fixed fields cursor holding the necessary data for the search provider of the global search bar.
+ *
+ */
+public class SearchSuggestionCursor extends MatrixCursor {
+
+ /**
+ * id of the row for callbacks after selection
+ */
+ private int rowId = 0;
+
+ public SearchSuggestionCursor() {
+ super(new String[] {
+ BaseColumns._ID,
+ SearchManager.SUGGEST_COLUMN_TEXT_1,
+ SearchManager.SUGGEST_COLUMN_TEXT_2,
+ SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
+ SearchManager.SUGGEST_COLUMN_QUERY,
+ SearchManager.SUGGEST_COLUMN_ICON_1 });
+ }
+
+ public void addCache(@NonNull final String geocode, @NonNull final String name, final String type) {
+ final int icon = CacheType.getById(type).markerId;
+ addRow(new String[] {
+ String.valueOf(rowId),
+ name,
+ geocode,
+ Intents.ACTION_GEOCACHE,
+ geocode,
+ String.valueOf(icon)
+ });
+ rowId++;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/search/SuggestionProvider.java b/main/src/cgeo/geocaching/search/SuggestionProvider.java
index c0a7728..f60a43e 100644
--- a/main/src/cgeo/geocaching/search/SuggestionProvider.java
+++ b/main/src/cgeo/geocaching/search/SuggestionProvider.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.search;
import cgeo.geocaching.DataStore;
+import cgeo.geocaching.Geocache;
import org.apache.commons.lang3.StringUtils;
@@ -12,8 +13,6 @@ import android.net.Uri;
public class SuggestionProvider extends ContentProvider {
- private static Cursor lastCursor;
-
@Override
public boolean onCreate() {
return true;
@@ -29,14 +28,21 @@ public class SuggestionProvider extends ContentProvider {
final String searchTerm = uri.getLastPathSegment();
// can be empty when deleting the query
if (StringUtils.equals(searchTerm, SearchManager.SUGGEST_URI_PATH_QUERY)) {
- return lastCursor;
+ return getLastOpenedCaches();
}
return getSuggestions(searchTerm);
}
+ private static Cursor getLastOpenedCaches() {
+ final SearchSuggestionCursor resultCursor = new SearchSuggestionCursor();
+ for (final Geocache geocache : DataStore.getLastOpenedCaches()) {
+ resultCursor.addCache(geocache.getGeocode(), geocache.getName(), geocache.getType().id);
+ }
+ return resultCursor;
+ }
+
private static Cursor getSuggestions(final String searchTerm) {
- lastCursor = DataStore.findSuggestions(searchTerm);
- return lastCursor;
+ return DataStore.findSuggestions(searchTerm);
}
@Override
diff --git a/main/src/cgeo/geocaching/sensors/DirectionProvider.java b/main/src/cgeo/geocaching/sensors/DirectionProvider.java
index ff4a439..ed5d76a 100644
--- a/main/src/cgeo/geocaching/sensors/DirectionProvider.java
+++ b/main/src/cgeo/geocaching/sensors/DirectionProvider.java
@@ -21,9 +21,13 @@ import android.view.WindowManager;
public class DirectionProvider {
- private static final BehaviorSubject<Float> subject = BehaviorSubject.create(0.0f);
+ private static final BehaviorSubject<Float> SUBJECT = BehaviorSubject.create(0.0f);
- private static final WindowManager windowManager = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE);
+ private static final WindowManager WINDOW_MANAGER = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE);
+
+ private DirectionProvider() {
+ // utility class
+ }
static class Listener implements SensorEventListener, StartableHandlerThread.Callback {
@@ -33,22 +37,17 @@ public class DirectionProvider {
@Override
public void onSensorChanged(final SensorEvent event) {
- subject.onNext(event.values[0]);
+ SUBJECT.onNext(event.values[0]);
}
@Override
public void onAccuracyChanged(final Sensor sensor, final int accuracy) {
- /*
- * There is a bug in Android, which apparently causes this method to be called every
- * time the sensor _value_ changed, even if the _accuracy_ did not change. So logging
- * this event leads to the log being flooded with multiple entries _per second_,
- * which I experienced when running cgeo in a building (with GPS and network being
- * unreliable).
- *
- * See for example https://code.google.com/p/android/issues/detail?id=14792
- */
-
- //Log.i(Settings.tag, "Compass' accuracy is low (" + accuracy + ")");
+ /*
+ * There is a bug in Android, which apparently causes this method to be called every
+ * time the sensor _value_ changed, even if the _accuracy_ did not change. Do not have any code in here.
+ *
+ * See for example https://code.google.com/p/android/issues/detail?id=14792
+ */
}
@Override
@@ -83,7 +82,7 @@ public class DirectionProvider {
private boolean hasSensorChecked = false;
public boolean hasSensor(Context context) {
- if (hasSensorChecked == false) {
+ if (!hasSensorChecked) {
hasSensor = getOrientationSensor(context) != null;
hasSensorChecked = true;
}
@@ -99,18 +98,19 @@ public class DirectionProvider {
}
- private static final StartableHandlerThread handlerThread =
+ private static final StartableHandlerThread HANDLER_THREAD =
new StartableHandlerThread("DirectionProvider thread", Process.THREAD_PRIORITY_BACKGROUND, new Listener());
static {
- handlerThread.start();
+ HANDLER_THREAD.start();
}
- static public Observable<Float> create(final Context context) {
+
+ public static Observable<Float> create(final Context context) {
return Observable.create(new OnSubscribe<Float>() {
@Override
public void call(final Subscriber<? super Float> subscriber) {
- handlerThread.start(subscriber, context);
- subject.subscribe(subscriber);
+ HANDLER_THREAD.start(subscriber, context);
+ SUBJECT.subscribe(subscriber);
}
});
}
@@ -131,7 +131,7 @@ public class DirectionProvider {
}
private static int getRotationOffset() {
- switch (windowManager.getDefaultDisplay().getRotation()) {
+ switch (WINDOW_MANAGER.getDefaultDisplay().getRotation()) {
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
diff --git a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java
index a77b477..a4799cb 100644
--- a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java
+++ b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java
@@ -1,13 +1,12 @@
package cgeo.geocaching.sensors;
-import android.os.*;
import cgeo.geocaching.utils.Log;
-
import cgeo.geocaching.utils.StartableHandlerThread;
+
import org.apache.commons.lang3.StringUtils;
+
import rx.Observable;
import rx.Observable.OnSubscribe;
-import rx.Scheduler.Inner;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
@@ -24,6 +23,7 @@ import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
+import android.os.Bundle;
import java.util.concurrent.TimeUnit;
@@ -96,11 +96,11 @@ public class GeoDataProvider implements OnSubscribe<IGeoData> {
final private Listener gpsListener = new Listener(LocationManager.GPS_PROVIDER, gpsLocation);
@Override
- public Subscription connect() {
+ public void connect(Action1<? super Subscription> connection) {
final CompositeSubscription subscription = new CompositeSubscription();
- AndroidSchedulers.handlerThread(handlerThread.getHandler()).schedule(new Action1<Inner>() {
+ AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() {
@Override
- public void call(final Inner inner) {
+ public void call() {
synchronized(lock) {
if (count++ == 0) {
Log.d("GeoDataProvider: starting the GPS and network listeners" + " (" + ++debugSessionCounter + ")");
@@ -118,9 +118,9 @@ public class GeoDataProvider implements OnSubscribe<IGeoData> {
subscription.add(Subscriptions.create(new Action0() {
@Override
public void call() {
- AndroidSchedulers.handlerThread(handlerThread.getHandler()).schedule(new Action1<Inner>() {
+ AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() {
@Override
- public void call(final Inner inner) {
+ public void call() {
synchronized (lock) {
if (--count == 0) {
Log.d("GeoDataProvider: stopping the GPS and network listeners" + " (" + debugSessionCounter + ")");
@@ -135,7 +135,7 @@ public class GeoDataProvider implements OnSubscribe<IGeoData> {
}));
}
});
- return subscription;
+ connection.call(subscription);
}
};
diff --git a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java
index 917c9c4..b209a70 100644
--- a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java
+++ b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java
@@ -70,7 +70,7 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab
public ImmutablePair<StatusCode, ? extends Drawable> call() {
return login();
}
- })).subscribe(new Action1<ImmutablePair<StatusCode, ? extends Drawable>>() {
+ })).subscribeOn(Schedulers.io()).subscribe(new Action1<ImmutablePair<StatusCode, ? extends Drawable>>() {
@Override
public void call(final ImmutablePair<StatusCode, ? extends Drawable> loginInfo) {
loginDialog.dismiss();
@@ -86,7 +86,7 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab
}
activity.initBasicMemberPreferences();
}
- }, Schedulers.io());
+ });
return false; // no shared preference has to be changed
}
diff --git a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
index cc2de9f..e899be9 100644
--- a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
+++ b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
@@ -75,7 +75,7 @@ public class RegisterSend2CgeoPreference extends AbstractClickablePreference {
return Observable.empty();
}
- }).firstOrDefault(0)).subscribe(new Action1<Integer>() {
+ }).firstOrDefault(0)).subscribeOn(Schedulers.io()).subscribe(new Action1<Integer>() {
@Override
public void call(final Integer pin) {
progressDialog.dismiss();
@@ -87,7 +87,7 @@ public class RegisterSend2CgeoPreference extends AbstractClickablePreference {
Dialogs.message(activity, R.string.init_sendToCgeo, R.string.init_sendToCgeo_register_fail);
}
}
- }, Schedulers.io());
+ });
return true;
}
diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java
index 7a4dfdd..0ed5aef 100644
--- a/main/src/cgeo/geocaching/settings/Settings.java
+++ b/main/src/cgeo/geocaching/settings/Settings.java
@@ -39,6 +39,7 @@ import android.preference.PreferenceManager;
import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@@ -47,6 +48,7 @@ import java.util.Locale;
*/
public class Settings {
+ private static final char HISTORY_SEPARATOR = ',';
public static final int SHOW_WP_THRESHOLD_DEFAULT = 10;
public static final int SHOW_WP_THRESHOLD_MAX = 50;
private static final int MAP_SOURCE_DEFAULT = GoogleMapProvider.GOOGLE_MAP_ID.hashCode();
@@ -63,7 +65,7 @@ public class Settings {
Min,
Sec;
- public static CoordInputFormatEnum fromInt(int id) {
+ public static CoordInputFormatEnum fromInt(final int id) {
final CoordInputFormatEnum[] values = CoordInputFormatEnum.values();
if (id < 0 || id >= values.length) {
return Min;
@@ -91,7 +93,7 @@ public class Settings {
private static void migrateSettings() {
// migrate from non standard file location and integer based boolean types
- int oldVersion = getInt(R.string.pref_settingsversion, 0);
+ final int oldVersion = getInt(R.string.pref_settingsversion, 0);
if (oldVersion < 1) {
final String oldPreferencesName = "cgeo.pref";
final SharedPreferences old = CgeoApplication.getInstance().getSharedPreferences(oldPreferencesName, Context.MODE_PRIVATE);
@@ -173,13 +175,13 @@ public class Settings {
e.putInt(getKey(R.string.pref_showwaypointsthreshold), wpThreshold);
// KEY_MAP_SOURCE must be string, because it is the key for a ListPreference now
- int ms = sharedPrefs.getInt(getKey(R.string.pref_mapsource), MAP_SOURCE_DEFAULT);
+ final int ms = sharedPrefs.getInt(getKey(R.string.pref_mapsource), MAP_SOURCE_DEFAULT);
e.remove(getKey(R.string.pref_mapsource));
e.putString(getKey(R.string.pref_mapsource), String.valueOf(ms));
// navigation tool ids must be string, because ListPreference uses strings as keys
- int dnt1 = sharedPrefs.getInt(getKey(R.string.pref_defaultNavigationTool), NavigationAppsEnum.COMPASS.id);
- int dnt2 = sharedPrefs.getInt(getKey(R.string.pref_defaultNavigationTool2), NavigationAppsEnum.INTERNAL_MAP.id);
+ final int dnt1 = sharedPrefs.getInt(getKey(R.string.pref_defaultNavigationTool), NavigationAppsEnum.COMPASS.id);
+ final int dnt2 = sharedPrefs.getInt(getKey(R.string.pref_defaultNavigationTool2), NavigationAppsEnum.INTERNAL_MAP.id);
e.remove(getKey(R.string.pref_defaultNavigationTool));
e.remove(getKey(R.string.pref_defaultNavigationTool2));
e.putString(getKey(R.string.pref_defaultNavigationTool), String.valueOf(dnt1));
@@ -258,7 +260,7 @@ public class Settings {
return sharedPrefs.contains(getKey(prefKeyId));
}
- public static void setLanguage(boolean useEnglish) {
+ public static void setLanguage(final boolean useEnglish) {
final Configuration config = new Configuration();
config.locale = useEnglish ? Locale.ENGLISH : Locale.getDefault();
final Resources resources = CgeoApplication.getInstance().getResources();
@@ -346,11 +348,11 @@ public class Settings {
}
}
- public static boolean isOCConnectorActive(int isActivePrefKeyId) {
+ public static boolean isOCConnectorActive(final int isActivePrefKeyId) {
return getBoolean(isActivePrefKeyId, false);
}
- public static boolean hasOCAuthorization(int tokenPublicPrefKeyId, int tokenSecretPrefKeyId) {
+ public static boolean hasOCAuthorization(final int tokenPublicPrefKeyId, final int tokenSecretPrefKeyId) {
return StringUtils.isNotBlank(getString(tokenPublicPrefKeyId, ""))
&& StringUtils.isNotBlank(getString(tokenSecretPrefKeyId, ""));
}
@@ -374,7 +376,7 @@ public class Settings {
}
public static String getSignature() {
- return getString(R.string.pref_signature, null);
+ return getString(R.string.pref_signature, StringUtils.EMPTY);
}
public static boolean setCookieStore(final String cookies) {
@@ -424,7 +426,7 @@ public class Settings {
}
public static boolean setMapFile(final String mapFile) {
- boolean result = putString(R.string.pref_mapfile, mapFile);
+ final boolean result = putString(R.string.pref_mapfile, mapFile);
if (mapFile != null) {
setMapFileDirectory(new File(mapFile).getParent());
}
@@ -444,7 +446,7 @@ public class Settings {
}
public static boolean setMapFileDirectory(final String mapFileDirectory) {
- boolean result = putString(R.string.pref_mapDirectory, mapFileDirectory);
+ final boolean result = putString(R.string.pref_mapDirectory, mapFileDirectory);
MapsforgeMapProvider.getInstance().updateOfflineMaps();
return result;
}
@@ -624,6 +626,7 @@ public class Settings {
private final static int MAPNIK = 1;
private final static int CYCLEMAP = 3;
private final static int OFFLINE = 4;
+ private static final int HISTORY_SIZE = 10;
/**
* convert old preference ids for maps (based on constant values) into new hash based ids
@@ -676,8 +679,8 @@ public class Settings {
public static Geopoint getAnyCoordinates() {
if (contains(R.string.pref_anylatitude) && contains(R.string.pref_anylongitude)) {
- float lat = getFloat(R.string.pref_anylatitude, 0);
- float lon = getFloat(R.string.pref_anylongitude, 0);
+ final float lat = getFloat(R.string.pref_anylatitude, 0);
+ final float lon = getFloat(R.string.pref_anylongitude, 0);
return new Geopoint(lat, lon);
}
return null;
@@ -760,7 +763,7 @@ public class Settings {
}
public static void setTwitterTokens(@Nullable final String tokenPublic,
- @Nullable final String tokenSecret, boolean enableTwitter) {
+ @Nullable final String tokenSecret, final boolean enableTwitter) {
putString(R.string.pref_twitter_token_public, tokenPublic);
putString(R.string.pref_twitter_token_secret, tokenSecret);
if (tokenPublic != null) {
@@ -777,8 +780,8 @@ public class Settings {
}
public static ImmutablePair<String, String> getTempToken() {
- String tokenPublic = getString(R.string.pref_temp_twitter_token_public, null);
- String tokenSecret = getString(R.string.pref_temp_twitter_token_secret, null);
+ final String tokenPublic = getString(R.string.pref_temp_twitter_token_public, null);
+ final String tokenSecret = getString(R.string.pref_temp_twitter_token_secret, null);
return new ImmutablePair<String, String>(tokenPublic, tokenSecret);
}
@@ -889,8 +892,8 @@ public class Settings {
}
public static File[] getMapThemeFiles() {
- File directory = new File(Settings.getCustomRenderThemeBaseFolder());
- List<File> result = new ArrayList<File>();
+ final File directory = new File(Settings.getCustomRenderThemeBaseFolder());
+ final List<File> result = new ArrayList<File>();
FileUtils.listDir(result, directory, new ExtensionsBasedFileSelector(new String[] { "xml" }), null);
return result.toArray(new File[result.size()]);
@@ -898,13 +901,13 @@ public class Settings {
private static class ExtensionsBasedFileSelector extends FileSelector {
private final String[] extensions;
- public ExtensionsBasedFileSelector(String[] extensions) {
+ public ExtensionsBasedFileSelector(final String[] extensions) {
this.extensions = extensions;
}
@Override
- public boolean isSelected(File file) {
- String filename = file.getName();
- for (String ext : extensions) {
+ public boolean isSelected(final File file) {
+ final String filename = file.getName();
+ for (final String ext : extensions) {
if (StringUtils.endsWithIgnoreCase(filename, ext)) {
return true;
}
@@ -970,7 +973,7 @@ public class Settings {
putLong(R.string.pref_fieldNoteExportDate, date);
}
- public static boolean isUseNavigationApp(NavigationAppsEnum navApp) {
+ public static boolean isUseNavigationApp(final NavigationAppsEnum navApp) {
return getBoolean(navApp.preferenceKey, true);
}
@@ -979,7 +982,7 @@ public class Settings {
*
* @param upload
*/
- public static void setFieldNoteExportUpload(boolean upload) {
+ public static void setFieldNoteExportUpload(final boolean upload) {
putBoolean(R.string.pref_fieldNoteExportUpload, upload);
}
@@ -992,7 +995,7 @@ public class Settings {
*
* @param onlyNew
*/
- public static void setFieldNoteExportOnlyNew(boolean onlyNew) {
+ public static void setFieldNoteExportOnlyNew(final boolean onlyNew) {
putBoolean(R.string.pref_fieldNoteExportOnlyNew, onlyNew);
}
@@ -1004,4 +1007,25 @@ public class Settings {
return getString(R.string.pref_ec_icons, "1");
}
+ /* Store last checksum of changelog for changelog display */
+ public static long getLastChangelogChecksum() {
+ return getLong(R.string.pref_changelog_last_checksum, 0);
+ }
+
+ public static void setLastChangelogChecksum(final long checksum) {
+ putLong(R.string.pref_changelog_last_checksum, checksum);
+ }
+
+ public static List<String> getLastOpenedCaches() {
+ final List<String> history = Arrays.asList(StringUtils.split(getString(R.string.pref_caches_history, StringUtils.EMPTY), HISTORY_SEPARATOR));
+ return history.subList(0, Math.min(HISTORY_SIZE, history.size()));
+ }
+
+ public static void addCacheToHistory(@NonNull final String geocode) {
+ final ArrayList<String> history = new ArrayList<String>(getLastOpenedCaches());
+ // bring entry to front, if it already existed
+ history.remove(geocode);
+ history.add(0, geocode);
+ putString(R.string.pref_caches_history, StringUtils.join(history, HISTORY_SEPARATOR));
+ }
}
diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java
index dc1a39d..8f64d77 100644
--- a/main/src/cgeo/geocaching/settings/SettingsActivity.java
+++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java
@@ -9,11 +9,11 @@ import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum;
import cgeo.geocaching.connector.gc.GCConnector;
-import cgeo.geocaching.connector.gc.GCLogin;
import cgeo.geocaching.files.SimpleDirChooser;
import cgeo.geocaching.maps.MapProviderFactory;
import cgeo.geocaching.maps.interfaces.MapSource;
import cgeo.geocaching.utils.DatabaseBackupUtils;
+import cgeo.geocaching.utils.DebugUtils;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
@@ -62,7 +62,7 @@ public class SettingsActivity extends PreferenceActivity {
* directory and preference key in onActivityResult() easily just by knowing
* the result code.
*/
- private enum DirChooserType {
+ private static enum DirChooserType {
GPX_IMPORT_DIR(1, R.string.pref_gpxImportDir,
Environment.getExternalStorageDirectory().getPath() + "/gpx", false),
GPX_EXPORT_DIR(2, R.string.pref_gpxExportDir,
@@ -90,21 +90,21 @@ public class SettingsActivity extends PreferenceActivity {
SettingsActivity.addPreferencesFromResource(this, R.xml.preferences);
initPreferences();
- Intent intent = getIntent();
+ final Intent intent = getIntent();
openInitialScreen(intent.getIntExtra(INTENT_OPEN_SCREEN, 0));
}
- private void openInitialScreen(int initialScreen) {
+ private void openInitialScreen(final int initialScreen) {
if (initialScreen == 0) {
return;
}
- PreferenceScreen screen = (PreferenceScreen) getPreference(initialScreen);
+ final PreferenceScreen screen = (PreferenceScreen) getPreference(initialScreen);
if (screen == null) {
return;
}
try {
setPreferenceScreen(screen);
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.e("could not open preferences " + initialScreen, e);
}
}
@@ -129,7 +129,7 @@ public class SettingsActivity extends PreferenceActivity {
initNavigationMenuPreferences();
initMaintenanceButtons();
- for (int k : new int[] { R.string.pref_username, R.string.pref_password,
+ for (final int k : new int[] { R.string.pref_username, R.string.pref_password,
R.string.pref_pass_vote, R.string.pref_signature,
R.string.pref_mapsource, R.string.pref_renderthemepath,
R.string.pref_gpxExportDir, R.string.pref_gpxImportDir,
@@ -143,7 +143,7 @@ public class SettingsActivity extends PreferenceActivity {
}
private void initNavigationMenuPreferences() {
- for (NavigationAppsEnum appEnum : NavigationAppsEnum.values()) {
+ for (final NavigationAppsEnum appEnum : NavigationAppsEnum.values()) {
if (appEnum.app.isInstalled()) {
getPreference(appEnum.preferenceKey).setEnabled(true);
}
@@ -154,7 +154,7 @@ public class SettingsActivity extends PreferenceActivity {
}
private void initServicePreferences() {
- for (OCPreferenceKeys key : OCPreferenceKeys.values()) {
+ for (final OCPreferenceKeys key : OCPreferenceKeys.values()) {
getPreference(key.isActivePrefId).setOnPreferenceChangeListener(VALUE_CHANGE_LISTENER);
setWebsite(key.websitePrefId, key.authParams.host);
setServiceScreenSummary(getPreferenceManager(), key.isActivePrefId);
@@ -173,7 +173,7 @@ public class SettingsActivity extends PreferenceActivity {
}
private void setWebsite(final int preferenceKey, final String host) {
- Preference preference = getPreference(preferenceKey);
+ final Preference preference = getPreference(preferenceKey);
preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(final Preference preference) {
@@ -183,13 +183,13 @@ public class SettingsActivity extends PreferenceActivity {
});
}
- private static String getServiceSummary(boolean status) {
+ private static String getServiceSummary(final boolean status) {
return status ? CgeoApplication.getInstance().getString(R.string.settings_service_active) : StringUtils.EMPTY;
}
- private static void setServiceScreenSummary(PreferenceManager preferenceManager, final int preferenceKey) {
+ private static void setServiceScreenSummary(final PreferenceManager preferenceManager, final int preferenceKey) {
- String summary = StringUtils.EMPTY;
+ String summary;
switch (preferenceKey) {
case R.string.pref_connectorGCActive:
@@ -206,7 +206,7 @@ public class SettingsActivity extends PreferenceActivity {
break;
default:
if (OCPreferenceKeys.isOCPreference(preferenceKey)) {
- OCPreferenceKeys prefKey = OCPreferenceKeys.getById(preferenceKey);
+ final OCPreferenceKeys prefKey = OCPreferenceKeys.getById(preferenceKey);
summary = getServiceSummary(Settings.isOCConnectorActive(prefKey.isActivePrefId));
preferenceManager.findPreference(getKey(prefKey.prefScreenId)).setSummary(summary);
}
@@ -225,11 +225,11 @@ public class SettingsActivity extends PreferenceActivity {
* Fill the choice list for map sources.
*/
private void initMapSourcePreference() {
- ListPreference pref = (ListPreference) getPreference(R.string.pref_mapsource);
+ final ListPreference pref = (ListPreference) getPreference(R.string.pref_mapsource);
- List<MapSource> mapSources = MapProviderFactory.getMapSources();
- CharSequence[] entries = new CharSequence[mapSources.size()];
- CharSequence[] values = new CharSequence[mapSources.size()];
+ final List<MapSource> mapSources = MapProviderFactory.getMapSources();
+ final CharSequence[] entries = new CharSequence[mapSources.size()];
+ final CharSequence[] values = new CharSequence[mapSources.size()];
for (int i = 0; i < mapSources.size(); ++i) {
entries[i] = mapSources.get(i).getName();
values[i] = String.valueOf(mapSources.get(i).getNumericalId());
@@ -245,8 +245,8 @@ public class SettingsActivity extends PreferenceActivity {
final List<NavigationAppsEnum> apps = NavigationAppFactory.getInstalledDefaultNavigationApps();
- CharSequence[] entries = new CharSequence[apps.size()];
- CharSequence[] values = new CharSequence[apps.size()];
+ final CharSequence[] entries = new CharSequence[apps.size()];
+ final CharSequence[] values = new CharSequence[apps.size()];
for (int i = 0; i < apps.size(); ++i) {
entries[i] = apps.get(i).toString();
values[i] = String.valueOf(apps.get(i).id);
@@ -277,7 +277,7 @@ public class SettingsActivity extends PreferenceActivity {
new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(final Preference preference) {
- Intent i = new Intent(SettingsActivity.this,
+ final Intent i = new Intent(SettingsActivity.this,
SelectMapfileActivity.class);
startActivityForResult(i, R.string.pref_mapDirectory);
return false;
@@ -307,7 +307,7 @@ public class SettingsActivity extends PreferenceActivity {
dirChooser.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT,
getString(android.R.string.ok));
startActivityForResult(dirChooser, dct.requestCode);
- } catch (android.content.ActivityNotFoundException ex) {
+ } catch (final android.content.ActivityNotFoundException ex) {
// OI file manager not available
final Intent dirChooser = new Intent(this, SimpleDirChooser.class);
dirChooser.putExtra(Intents.EXTRA_START_DIR, startDirectory);
@@ -319,7 +319,7 @@ public class SettingsActivity extends PreferenceActivity {
private void setChosenDirectory(final DirChooserType dct, final Intent data) {
final String directory = new File(data.getData().getPath()).getAbsolutePath();
if (StringUtils.isNotBlank(directory)) {
- Preference p = getPreference(dct.keyId);
+ final Preference p = getPreference(dct.keyId);
if (p == null) {
return;
}
@@ -329,7 +329,7 @@ public class SettingsActivity extends PreferenceActivity {
}
public void initBackupButtons() {
- Preference backup = getPreference(R.string.pref_fakekey_preference_backup);
+ final Preference backup = getPreference(R.string.pref_fakekey_preference_backup);
backup.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(final Preference preference) {
@@ -343,7 +343,7 @@ public class SettingsActivity extends PreferenceActivity {
}
});
- Preference restore = getPreference(R.string.pref_fakekey_preference_restore);
+ final Preference restore = getPreference(R.string.pref_fakekey_preference_restore);
restore.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(final Preference preference) {
@@ -354,14 +354,14 @@ public class SettingsActivity extends PreferenceActivity {
}
public void initMaintenanceButtons() {
- Preference dirMaintenance = getPreference(R.string.pref_fakekey_preference_maintenance_directories);
+ final Preference dirMaintenance = getPreference(R.string.pref_fakekey_preference_maintenance_directories);
dirMaintenance.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(final Preference preference) {
// disable the button, as the cleanup runs in background and should not be invoked a second time
preference.setEnabled(false);
- Resources res = getResources();
+ final Resources res = getResources();
final SettingsActivity activity = SettingsActivity.this;
final ProgressDialog dialog = ProgressDialog.show(activity, res.getString(R.string.init_maintenance), res.getString(R.string.init_maintenance_directories), true, false);
new Thread() {
@@ -380,10 +380,19 @@ public class SettingsActivity extends PreferenceActivity {
return true;
}
});
+ final Preference memoryDumpPref = getPreference(R.string.pref_memory_dump);
+ memoryDumpPref
+ .setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override public boolean onPreferenceClick(
+ final Preference preference) {
+ DebugUtils.createMemoryDump(SettingsActivity.this);
+ return true;
+ }
+ });
}
private void initDbLocationPreference() {
- Preference p = getPreference(R.string.pref_dbonsdcard);
+ final Preference p = getPreference(R.string.pref_dbonsdcard);
p.setPersistent(false);
p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
@@ -396,7 +405,7 @@ public class SettingsActivity extends PreferenceActivity {
}
private void initDebugPreference() {
- Preference p = getPreference(R.string.pref_debug);
+ final Preference p = getPreference(R.string.pref_debug);
p.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(final Preference preference, final Object newValue) {
@@ -434,7 +443,7 @@ public class SettingsActivity extends PreferenceActivity {
return;
}
final PreferenceScreen screen = (PreferenceScreen) preference;
- ListAdapter adapter = screen.getRootAdapter();
+ final ListAdapter adapter = screen.getRootAdapter();
if (adapter instanceof BaseAdapter) {
((BaseAdapter) adapter).notifyDataSetChanged();
}
@@ -444,7 +453,7 @@ public class SettingsActivity extends PreferenceActivity {
Settings.putString(R.string.pref_webDeviceName, Settings.getWebDeviceName());
}
- public void setAuthTitle(int prefKeyId) {
+ public void setAuthTitle(final int prefKeyId) {
switch (prefKeyId) {
case R.string.pref_fakekey_ocde_authorization:
case R.string.pref_fakekey_ocpl_authorization:
@@ -490,7 +499,7 @@ public class SettingsActivity extends PreferenceActivity {
return;
}
- for (DirChooserType dct : DirChooserType.values()) {
+ for (final DirChooserType dct : DirChooserType.values()) {
if (requestCode == dct.requestCode) {
setChosenDirectory(dct, data);
return;
@@ -501,7 +510,7 @@ public class SettingsActivity extends PreferenceActivity {
case R.string.pref_mapDirectory:
if (data.hasExtra(Intents.EXTRA_MAP_FILE)) {
final String mapFile = data.getStringExtra(Intents.EXTRA_MAP_FILE);
- File file = new File(mapFile);
+ final File file = new File(mapFile);
if (!file.isDirectory()) {
Settings.setMapFile(mapFile);
if (!Settings.isValidMapFile(Settings.getMapFile())) {
@@ -509,8 +518,8 @@ public class SettingsActivity extends PreferenceActivity {
} else {
// Ensure map source preference is updated accordingly.
// TODO: There should be a better way to find and select the map source for a map file
- Integer mapSourceId = mapFile.hashCode();
- ListPreference mapSource = (ListPreference) getPreference(R.string.pref_mapsource);
+ final Integer mapSourceId = mapFile.hashCode();
+ final ListPreference mapSource = (ListPreference) getPreference(R.string.pref_mapsource);
mapSource.setValue(mapSourceId.toString());
VALUE_CHANGE_LISTENER.onPreferenceChange(mapSource, mapSourceId);
}
@@ -526,7 +535,7 @@ public class SettingsActivity extends PreferenceActivity {
case R.string.pref_fakekey_ocnl_authorization:
case R.string.pref_fakekey_ocus_authorization:
case R.string.pref_fakekey_ocro_authorization:
- OCPreferenceKeys key = OCPreferenceKeys.getByAuthId(requestCode);
+ final OCPreferenceKeys key = OCPreferenceKeys.getByAuthId(requestCode);
if (key != null) {
setOCAuthTitle(key);
redrawScreen(key.prefScreenId);
@@ -548,7 +557,7 @@ public class SettingsActivity extends PreferenceActivity {
private static final Preference.OnPreferenceChangeListener VALUE_CHANGE_LISTENER = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(final Preference preference, final Object value) {
- String stringValue = value.toString();
+ final String stringValue = value.toString();
if (isPreference(preference, R.string.pref_mapsource)) {
// reset the cached map source
@@ -582,10 +591,10 @@ public class SettingsActivity extends PreferenceActivity {
|| isPreference(preference, R.string.pref_connectorOXActive)
|| isPreference(preference, R.string.pref_connectorECActive)) {
// update summary
- boolean boolVal = ((Boolean) value).booleanValue();
- String summary = getServiceSummary(boolVal);
+ final boolean boolVal = (Boolean) value;
+ final String summary = getServiceSummary(boolVal);
if (OCPreferenceKeys.isOCPreference(preference.getKey())) {
- OCPreferenceKeys prefKey = OCPreferenceKeys.getByKey(preference.getKey());
+ final OCPreferenceKeys prefKey = OCPreferenceKeys.getByKey(preference.getKey());
preference.getPreferenceManager().findPreference(getKey(prefKey.prefScreenId)).setSummary(summary);
} else if (isPreference(preference, R.string.pref_connectorGCActive)) {
preference.getPreferenceManager().findPreference(getKey(R.string.preference_screen_gc)).setSummary(summary);
@@ -600,8 +609,8 @@ public class SettingsActivity extends PreferenceActivity {
} else if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
- ListPreference listPreference = (ListPreference) preference;
- int index = listPreference.findIndexOfValue(stringValue);
+ final ListPreference listPreference = (ListPreference) preference;
+ final int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
@@ -625,9 +634,6 @@ public class SettingsActivity extends PreferenceActivity {
// TODO: do not special case geocaching.com here
if ((isPreference(preference, R.string.pref_username) && !stringValue.equals(Settings.getUsername())) || (isPreference(preference, R.string.pref_password) && !stringValue.equals(Settings.getGcCredentials().getRight()))) {
// reset log-in if gc user or password is changed
- if (GCLogin.getInstance().isActualLoginStatus()) {
- GCLogin.getInstance().logout();
- }
CgeoApplication.getInstance().forceRelog();
}
return true;
@@ -662,12 +668,12 @@ public class SettingsActivity extends PreferenceActivity {
*/
private void bindSummaryToStringValue(final int key) {
- Preference pref = getPreference(key);
+ final Preference pref = getPreference(key);
if (pref == null) {
return;
}
- String value = PreferenceManager
+ final String value = PreferenceManager
.getDefaultSharedPreferences(pref.getContext())
.getString(pref.getKey(), "");
@@ -686,7 +692,7 @@ public class SettingsActivity extends PreferenceActivity {
@SuppressWarnings("deprecation")
@Override
- public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+ public void setPreferenceScreen(final PreferenceScreen preferenceScreen) {
// TODO replace with fragment based code
super.setPreferenceScreen(preferenceScreen);
}
@@ -698,7 +704,7 @@ public class SettingsActivity extends PreferenceActivity {
return super.getPreferenceManager();
}
- private static boolean isPreference(final Preference preference, int preferenceKeyId) {
+ private static boolean isPreference(final Preference preference, final int preferenceKeyId) {
return getKey(preferenceKeyId).equals(preference.getKey());
}
}
diff --git a/main/src/cgeo/geocaching/settings/TemplateTextPreference.java b/main/src/cgeo/geocaching/settings/TemplateTextPreference.java
index 667b02b..1f420ef 100644
--- a/main/src/cgeo/geocaching/settings/TemplateTextPreference.java
+++ b/main/src/cgeo/geocaching/settings/TemplateTextPreference.java
@@ -58,7 +58,7 @@ public class TemplateTextPreference extends DialogPreference {
public void onClick(View button) {
AlertDialog.Builder alert = new AlertDialog.Builder(TemplateTextPreference.this.getContext());
alert.setTitle(R.string.init_signature_template_button);
- final ArrayList<LogTemplate> templates = LogTemplateProvider.getTemplates();
+ final ArrayList<LogTemplate> templates = LogTemplateProvider.getTemplatesWithoutSignature();
String[] items = new String[templates.size()];
for (int i = 0; i < templates.size(); i++) {
items[i] = settingsActivity.getResources().getString(templates.get(i).getResourceId());
diff --git a/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java b/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
deleted file mode 100644
index 7f10353..0000000
--- a/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package cgeo.geocaching.sorting;
-
-import cgeo.geocaching.R;
-import cgeo.geocaching.utils.Log;
-
-import rx.functions.Action1;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.res.Resources;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-
-public class ComparatorUserInterface {
- private final Activity activity;
- private final ArrayList<ComparatorEntry> registry;
- private final Resources res;
-
- private static final class ComparatorEntry {
- private final String name;
- private final Class<? extends CacheComparator> cacheComparator;
-
- public ComparatorEntry(final String name, final Class<? extends CacheComparator> cacheComparator) {
- this.name = name;
- this.cacheComparator = cacheComparator;
- }
-
- @Override
- public String toString() {
- return name;
- }
- }
-
- public ComparatorUserInterface(final Activity activity) {
- this.activity = activity;
- res = activity.getResources();
-
- registry = new ArrayList<ComparatorUserInterface.ComparatorEntry>(20);
-
- register(R.string.caches_sort_distance, null);
- register(R.string.caches_sort_date_hidden, DateComparator.class);
- register(R.string.caches_sort_difficulty, DifficultyComparator.class);
- register(R.string.caches_sort_finds, FindsComparator.class);
- register(R.string.caches_sort_geocode, GeocodeComparator.class);
- register(R.string.caches_sort_inventory, InventoryComparator.class);
- register(R.string.caches_sort_name, NameComparator.class);
- register(R.string.caches_sort_favorites, PopularityComparator.class);
- register(R.string.caches_sort_favorites_ratio, PopularityRatioComparator.class);
- register(R.string.caches_sort_rating, RatingComparator.class);
- register(R.string.caches_sort_size, SizeComparator.class);
- register(R.string.caches_sort_state, StateComparator.class);
- register(R.string.caches_sort_storage, StorageTimeComparator.class);
- register(R.string.caches_sort_terrain, TerrainComparator.class);
- register(R.string.caches_sort_date_logged, VisitComparator.class);
- register(R.string.caches_sort_vote, VoteComparator.class);
-
- // sort the menu labels alphabetically for easier reading
- Collections.sort(registry, new Comparator<ComparatorEntry>() {
-
- @Override
- public int compare(ComparatorEntry lhs, ComparatorEntry rhs) {
- return lhs.name.compareToIgnoreCase(rhs.name);
- }
- });
- }
-
- private void register(final int resourceId, Class<? extends CacheComparator> comparatorClass) {
- registry.add(new ComparatorEntry(res.getString(resourceId), comparatorClass));
- }
-
- public void selectComparator(final CacheComparator current, final Action1<CacheComparator> runAfterwards) {
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(R.string.caches_sort_title);
-
- // adapter doesn't work correctly here, therefore using the string array based method
- final String[] items = new String[registry.size()];
- for (int i = 0; i < items.length; i++) {
- items[i] = registry.get(i).name;
- }
- builder.setSingleChoiceItems(items, getCurrentIndex(current), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int itemIndex) {
- ComparatorEntry entry = registry.get(itemIndex);
- try {
- if (entry.cacheComparator == null) {
- runAfterwards.call(null);
- }
- else {
- CacheComparator comparator = entry.cacheComparator.newInstance();
- runAfterwards.call(comparator);
- }
- } catch (InstantiationException e) {
- Log.e("selectComparator", e);
- } catch (IllegalAccessException e) {
- Log.e("selectComparator", e);
- }
- dialog.dismiss();
- }
- });
-
- builder.create().show();
- }
-
- private int getCurrentIndex(final CacheComparator current) {
- for (int index = 0; index < registry.size(); index++) {
- final ComparatorEntry entry = registry.get(index);
- if (current == null) {
- if (entry.cacheComparator == null) {
- return index;
- }
- }
- else if (current.getClass().equals(entry.cacheComparator)) {
- return index;
- }
- }
- return -1;
- }
-
-}
diff --git a/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java b/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java
index 1ed8e68..57a69ee 100644
--- a/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java
+++ b/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java
@@ -12,16 +12,14 @@ public class PopularityRatioComparator extends AbstractCacheComparator {
@Override
protected int compareCaches(final Geocache cache1, final Geocache cache2) {
-
- float ratio1 = 0.0f;
- float ratio2 = 0.0f;
-
int finds1 = cache1.getFindsCount();
int finds2 = cache2.getFindsCount();
+ float ratio1 = 0.0f;
if (finds1 != 0) {
ratio1 = (((float) cache1.getFavoritePoints()) / ((float) finds1));
}
+ float ratio2 = 0.0f;
if (finds2 != 0) {
ratio2 = (((float) cache2.getFavoritePoints()) / ((float) finds2));
}
diff --git a/main/src/cgeo/geocaching/sorting/SortActionProvider.java b/main/src/cgeo/geocaching/sorting/SortActionProvider.java
new file mode 100644
index 0000000..8663391
--- /dev/null
+++ b/main/src/cgeo/geocaching/sorting/SortActionProvider.java
@@ -0,0 +1,153 @@
+package cgeo.geocaching.sorting;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.utils.Log;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+import rx.functions.Action1;
+
+import android.content.Context;
+import android.support.v4.view.ActionProvider;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.SubMenu;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+/**
+ * Provides a sub menu for sorting caches. Register your listener in the onCreateOptionsMenu of the containing activity.
+ *
+ */
+public class SortActionProvider extends ActionProvider implements OnMenuItemClickListener {
+
+ private static final int MENU_GROUP = 1;
+ private final Context mContext;
+ private final ArrayList<ComparatorEntry> registry = new ArrayList<ComparatorEntry>(20);
+ /**
+ * Callback triggered on selecting a new sort order.
+ */
+ private Action1<CacheComparator> onClickListener;
+ /**
+ * Currently selected filter. Used for radio button indication.
+ */
+ private CacheComparator selection;
+
+ private static final class ComparatorEntry {
+ private final String name;
+ private final Class<? extends CacheComparator> cacheComparator;
+
+ public ComparatorEntry(final String name, final Class<? extends CacheComparator> cacheComparator) {
+ this.name = name;
+ this.cacheComparator = cacheComparator;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ public SortActionProvider(final Context context) {
+ super(context);
+ mContext = context;
+ registerComparators();
+ }
+
+ private void register(final int resourceId, final Class<? extends CacheComparator> comparatorClass) {
+ registry.add(new ComparatorEntry(mContext.getString(resourceId), comparatorClass));
+ }
+
+ private void registerComparators() {
+ register(R.string.caches_sort_distance, null);
+ register(R.string.caches_sort_date_hidden, DateComparator.class);
+ register(R.string.caches_sort_difficulty, DifficultyComparator.class);
+ register(R.string.caches_sort_finds, FindsComparator.class);
+ register(R.string.caches_sort_geocode, GeocodeComparator.class);
+ register(R.string.caches_sort_inventory, InventoryComparator.class);
+ register(R.string.caches_sort_name, NameComparator.class);
+ register(R.string.caches_sort_favorites, PopularityComparator.class);
+ register(R.string.caches_sort_favorites_ratio, PopularityRatioComparator.class);
+ register(R.string.caches_sort_rating, RatingComparator.class);
+ register(R.string.caches_sort_size, SizeComparator.class);
+ register(R.string.caches_sort_state, StateComparator.class);
+ register(R.string.caches_sort_storage, StorageTimeComparator.class);
+ register(R.string.caches_sort_terrain, TerrainComparator.class);
+ register(R.string.caches_sort_date_logged, VisitComparator.class);
+ register(R.string.caches_sort_vote, VoteComparator.class);
+
+ // sort the menu labels alphabetically for easier reading
+ Collections.sort(registry, new Comparator<ComparatorEntry>() {
+
+ @Override
+ public int compare(final ComparatorEntry lhs, final ComparatorEntry rhs) {
+ return lhs.name.compareToIgnoreCase(rhs.name);
+ }
+ });
+ }
+
+ @Override
+ public View onCreateActionView(){
+ // must return null, otherwise onPrepareSubMenu is not called
+ return null;
+ }
+
+ @Override
+ public boolean hasSubMenu(){
+ return true;
+ }
+
+ @Override
+ public void onPrepareSubMenu(final SubMenu subMenu){
+ subMenu.clear();
+ for (int i = 0; i < registry.size(); i++) {
+ final ComparatorEntry comparatorEntry = registry.get(i);
+ final MenuItem menuItem = subMenu.add(MENU_GROUP, i, i, comparatorEntry.name);
+ menuItem.setOnMenuItemClickListener(this).setCheckable(true);
+ if (selection == null) {
+ if (comparatorEntry.cacheComparator == null) {
+ menuItem.setChecked(true);
+ }
+ }
+ else {
+ if (selection.getClass().equals(comparatorEntry.cacheComparator)) {
+ menuItem.setChecked(true);
+ }
+ }
+ }
+ subMenu.setGroupCheckable(MENU_GROUP, true, true);
+ }
+
+ @Override
+ public boolean onMenuItemClick(final MenuItem item){
+ callListener(registry.get(item.getItemId()).cacheComparator);
+ return true;
+ }
+
+ private void callListener(final Class<? extends CacheComparator> cacheComparator) {
+ try {
+ if (cacheComparator == null) {
+ onClickListener.call(null);
+ }
+ else {
+ final CacheComparator comparator = cacheComparator.newInstance();
+ onClickListener.call(comparator);
+ }
+ } catch (final InstantiationException e) {
+ Log.e("selectComparator", e);
+ } catch (final IllegalAccessException e) {
+ Log.e("selectComparator", e);
+ }
+ }
+
+ public void setClickListener(final @NonNull Action1<CacheComparator> onClickListener) {
+ this.onClickListener = onClickListener;
+ }
+
+ public void setSelection(final CacheComparator selection) {
+ this.selection = selection;
+ }
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/ui/AbstractCachingListViewPageViewCreator.java b/main/src/cgeo/geocaching/ui/AbstractCachingListViewPageViewCreator.java
index 799b695..06fa1fa 100644
--- a/main/src/cgeo/geocaching/ui/AbstractCachingListViewPageViewCreator.java
+++ b/main/src/cgeo/geocaching/ui/AbstractCachingListViewPageViewCreator.java
@@ -51,7 +51,6 @@ public abstract class AbstractCachingListViewPageViewCreator extends AbstractCac
int logViewPosition = state.getInt(STATE_POSITION);
int logViewPositionFromTop = state.getInt(STATE_POSITION_FROM_TOP);
view.setSelectionFromTop(logViewPosition, logViewPositionFromTop);
- return;
}
}
diff --git a/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java
index 0c67384..71cd3b4 100644
--- a/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java
+++ b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java
@@ -52,6 +52,5 @@ public abstract class AbstractCachingPageViewCreator<ViewClass extends View> imp
*/
@Override
public void setViewState(@NonNull Bundle state) {
- return;
}
}
diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
index 0d90d9f..3a451a5 100644
--- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
@@ -45,6 +45,7 @@ import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -377,7 +378,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
final boolean lightSkin = Settings.isLightSkin();
- final TouchListener touchListener = new TouchListener(cache);
+ final TouchListener touchListener = new TouchListener(cache, this);
v.setOnClickListener(touchListener);
v.setOnLongClickListener(touchListener);
v.setOnTouchListener(touchListener);
@@ -536,24 +537,30 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
}
}
- private class TouchListener implements View.OnClickListener, View.OnLongClickListener, View.OnTouchListener {
+ private static class TouchListener implements View.OnClickListener, View.OnLongClickListener, View.OnTouchListener {
private final Geocache cache;
private final GestureDetector gestureDetector;
+ private final @NonNull WeakReference<CacheListAdapter> adapterRef;
- public TouchListener(final Geocache cache) {
+ public TouchListener(final Geocache cache, final @NonNull CacheListAdapter adapter) {
this.cache = cache;
- gestureDetector = new GestureDetector(getContext(), new FlingGesture(cache));
+ gestureDetector = new GestureDetector(adapter.getContext(), new FlingGesture(cache, adapter));
+ adapterRef = new WeakReference<CacheListAdapter>(adapter);
}
// Tap on item
@Override
public void onClick(final View view) {
- if (isSelectMode()) {
+ final CacheListAdapter adapter = adapterRef.get();
+ if (adapter == null) {
+ return;
+ }
+ if (adapter.isSelectMode()) {
cache.setStatusChecked(!cache.isStatusChecked());
- notifyDataSetChanged();
+ adapter.notifyDataSetChanged();
} else {
- CacheDetailActivity.startActivity(getContext(), cache.getGeocode(), cache.getName());
+ CacheDetailActivity.startActivity(adapter.getContext(), cache.getGeocode(), cache.getName());
}
}
@@ -572,12 +579,14 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
}
}
- private class FlingGesture extends GestureDetector.SimpleOnGestureListener {
+ private static class FlingGesture extends GestureDetector.SimpleOnGestureListener {
private final Geocache cache;
+ private final @NonNull WeakReference<CacheListAdapter> adapterRef;
- public FlingGesture(final Geocache cache) {
+ public FlingGesture(final Geocache cache, final @NonNull CacheListAdapter adapter) {
this.cache = cache;
+ adapterRef = new WeakReference<CacheListAdapter>(adapter);
}
@Override
@@ -586,11 +595,15 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
return false;
}
+ final CacheListAdapter adapter = adapterRef.get();
+ if (adapter == null) {
+ return false;
+ }
// left to right swipe
if ((e2.getX() - e1.getX()) > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > Math.abs(velocityY)) {
- if (!selectMode) {
- switchSelectMode();
+ if (!adapter.selectMode) {
+ adapter.switchSelectMode();
cache.setStatusChecked(true);
}
return true;
@@ -598,8 +611,8 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
// right to left swipe
if ((e1.getX() - e2.getX()) > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > Math.abs(velocityY)) {
- if (selectMode) {
- switchSelectMode();
+ if (adapter.selectMode) {
+ adapter.switchSelectMode();
}
return true;
}
diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java
index f7111f7..60982a9 100644
--- a/main/src/cgeo/geocaching/ui/CompassView.java
+++ b/main/src/cgeo/geocaching/ui/CompassView.java
@@ -3,10 +3,9 @@ package cgeo.geocaching.ui;
import cgeo.geocaching.R;
import cgeo.geocaching.utils.AngleUtils;
-import rx.Scheduler;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
-import rx.functions.Action1;
+import rx.functions.Action0;
import android.content.Context;
import android.content.res.Resources;
@@ -18,6 +17,7 @@ import android.graphics.PaintFlagsDrawFilter;
import android.util.AttributeSet;
import android.view.View;
+import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;
public class CompassView extends View {
@@ -56,11 +56,40 @@ public class CompassView extends View {
private boolean initialDisplay;
private Subscription periodicUpdate;
+ private static final class UpdateAction implements Action0 {
+
+ private final WeakReference<CompassView> compassViewRef;
+
+ private UpdateAction(CompassView view) {
+ this.compassViewRef = new WeakReference<CompassView>(view);
+ }
+
+ @Override
+ public void call() {
+ final CompassView compassView = compassViewRef.get();
+ if (compassView == null) {
+ return;
+ }
+ compassView.updateGraphics();
+ }
+ }
+
public CompassView(Context contextIn) {
super(contextIn);
context = contextIn;
}
+ public void updateGraphics() {
+ final float newAzimuthShown = smoothUpdate(northMeasured, azimuthShown);
+ final float newCacheHeadingShown = smoothUpdate(cacheHeadingMeasured, cacheHeadingShown);
+ if (Math.abs(AngleUtils.difference(azimuthShown, newAzimuthShown)) >= 2 ||
+ Math.abs(AngleUtils.difference(cacheHeadingShown, newCacheHeadingShown)) >= 2) {
+ azimuthShown = newAzimuthShown;
+ cacheHeadingShown = newCacheHeadingShown;
+ invalidate();
+ }
+ }
+
public CompassView(Context contextIn, AttributeSet attrs) {
super(contextIn, attrs);
context = contextIn;
@@ -88,24 +117,13 @@ public class CompassView extends View {
initialDisplay = true;
- periodicUpdate = AndroidSchedulers.mainThread().schedulePeriodically(new Action1<Scheduler.Inner>() {
- @Override
- public void call(final Scheduler.Inner inner) {
- final float newAzimuthShown = smoothUpdate(northMeasured, azimuthShown);
- final float newCacheHeadingShown = smoothUpdate(cacheHeadingMeasured, cacheHeadingShown);
- if (Math.abs(AngleUtils.difference(azimuthShown, newAzimuthShown)) >= 2 ||
- Math.abs(AngleUtils.difference(cacheHeadingShown, newCacheHeadingShown)) >= 2) {
- azimuthShown = newAzimuthShown;
- cacheHeadingShown = newCacheHeadingShown;
- invalidate();
- }
- }
- }, 0, 40, TimeUnit.MILLISECONDS);
+ periodicUpdate = AndroidSchedulers.mainThread().createWorker().schedulePeriodically(new UpdateAction(this), 0, 40, TimeUnit.MILLISECONDS);
}
@Override
public void onDetachedFromWindow() {
periodicUpdate.unsubscribe();
+
super.onDetachedFromWindow();
if (compassUnderlay != null) {
diff --git a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
index b2ce11a..00b5abe 100644
--- a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
@@ -1,12 +1,11 @@
package cgeo.geocaching.ui.dialog;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.sensors.IGeoData;
import cgeo.geocaching.R;
import cgeo.geocaching.activity.AbstractActivity;
-import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.sensors.IGeoData;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.settings.Settings.CoordInputFormatEnum;
import cgeo.geocaching.utils.EditUtils;
@@ -14,9 +13,12 @@ import cgeo.geocaching.utils.EditUtils;
import org.apache.commons.lang3.StringUtils;
import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextWatcher;
+import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
@@ -25,12 +27,11 @@ import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
-public class CoordinatesInputDialog extends NoTitleDialog {
+public class CoordinatesInputDialog extends DialogFragment {
- final private AbstractActivity context;
- final private IGeoData geo;
- final private Geocache cache;
private Geopoint gp;
+ private Geopoint gpinitial;
+ private Geopoint cacheCoords;
private EditText eLat, eLon;
private Button bLat, bLon;
@@ -39,34 +40,64 @@ public class CoordinatesInputDialog extends NoTitleDialog {
private TextView tLatSep1, tLatSep2, tLatSep3;
private TextView tLonSep1, tLonSep2, tLonSep3;
- private CoordinateUpdate cuListener;
-
private CoordInputFormatEnum currentFormat = null;
- public CoordinatesInputDialog(final AbstractActivity context, final Geocache cache, final Geopoint gp, final IGeoData geo) {
- super(context, ActivityMixin.getDialogTheme());
- this.context = context;
- this.geo = geo;
- this.cache = cache;
+
+ private static final String GEOPOINT_ARG = "GEOPOINT";
+ private static final String GEOPOINT_INTIAL_ARG = "GEOPOINT_INITIAL";
+ private static final String CACHECOORDS_ARG = "CACHECOORDS";
+
+
+ public static CoordinatesInputDialog getInstance(final Geocache cache, final Geopoint gp, final IGeoData geo) {
+
+ Bundle args = new Bundle();
if (gp != null) {
- this.gp = gp;
+ args.putParcelable(GEOPOINT_ARG, gp);
} else if (geo != null && geo.getCoords() != null) {
- this.gp = geo.getCoords();
+ args.putParcelable(GEOPOINT_ARG, geo.getCoords());
} else {
- this.gp = Geopoint.ZERO;
+ args.putParcelable(GEOPOINT_ARG, Geopoint.ZERO);
}
+
+ if (geo !=null)
+ args.putParcelable(GEOPOINT_INTIAL_ARG, geo.getCoords());
+
+ if (cache != null)
+ args.putParcelable(CACHECOORDS_ARG, cache.getCoords());
+
+ CoordinatesInputDialog cid = new CoordinatesInputDialog();
+ cid.setArguments(args);
+ return cid;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ gp = getArguments().getParcelable(GEOPOINT_ARG);
+ gpinitial = getArguments().getParcelable(GEOPOINT_INTIAL_ARG);
+ cacheCoords = getArguments().getParcelable(CACHECOORDS_ARG);
- setContentView(R.layout.coordinatesinput_dialog);
+ if (savedInstanceState != null && savedInstanceState.getParcelable(GEOPOINT_ARG)!=null)
+ gp = savedInstanceState.getParcelable(GEOPOINT_ARG);
- final Spinner spinner = (Spinner) findViewById(R.id.spinnerCoordinateFormats);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ // TODO: if current input is not commited in gp, read the current input into gp
+ outState.putParcelable(GEOPOINT_ARG, gp);
+ }
+
+ @Override
+ public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
+ getDialog().setTitle(R.string.cache_coordinates);
+
+ View v = inflater.inflate(R.layout.coordinatesinput_dialog, container, false);
+ final Spinner spinner = (Spinner) v.findViewById(R.id.spinnerCoordinateFormats);
final ArrayAdapter<CharSequence> adapter =
- ArrayAdapter.createFromResource(context,
+ ArrayAdapter.createFromResource(getActivity(),
R.array.waypoint_coordinate_formats,
android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -74,25 +105,25 @@ public class CoordinatesInputDialog extends NoTitleDialog {
spinner.setSelection(Settings.getCoordInputFormat().ordinal());
spinner.setOnItemSelectedListener(new CoordinateFormatListener());
- bLat = (Button) findViewById(R.id.ButtonLat);
- eLat = (EditText) findViewById(R.id.latitude);
- eLatDeg = (EditText) findViewById(R.id.EditTextLatDeg);
- eLatMin = (EditText) findViewById(R.id.EditTextLatMin);
- eLatSec = (EditText) findViewById(R.id.EditTextLatSec);
- eLatSub = (EditText) findViewById(R.id.EditTextLatSecFrac);
- tLatSep1 = (TextView) findViewById(R.id.LatSeparator1);
- tLatSep2 = (TextView) findViewById(R.id.LatSeparator2);
- tLatSep3 = (TextView) findViewById(R.id.LatSeparator3);
-
- bLon = (Button) findViewById(R.id.ButtonLon);
- eLon = (EditText) findViewById(R.id.longitude);
- eLonDeg = (EditText) findViewById(R.id.EditTextLonDeg);
- eLonMin = (EditText) findViewById(R.id.EditTextLonMin);
- eLonSec = (EditText) findViewById(R.id.EditTextLonSec);
- eLonSub = (EditText) findViewById(R.id.EditTextLonSecFrac);
- tLonSep1 = (TextView) findViewById(R.id.LonSeparator1);
- tLonSep2 = (TextView) findViewById(R.id.LonSeparator2);
- tLonSep3 = (TextView) findViewById(R.id.LonSeparator3);
+ bLat = (Button) v.findViewById(R.id.ButtonLat);
+ eLat = (EditText) v.findViewById(R.id.latitude);
+ eLatDeg = (EditText) v.findViewById(R.id.EditTextLatDeg);
+ eLatMin = (EditText) v.findViewById(R.id.EditTextLatMin);
+ eLatSec = (EditText) v.findViewById(R.id.EditTextLatSec);
+ eLatSub = (EditText) v.findViewById(R.id.EditTextLatSecFrac);
+ tLatSep1 = (TextView) v.findViewById(R.id.LatSeparator1);
+ tLatSep2 = (TextView) v.findViewById(R.id.LatSeparator2);
+ tLatSep3 = (TextView) v.findViewById(R.id.LatSeparator3);
+
+ bLon = (Button) v.findViewById(R.id.ButtonLon);
+ eLon = (EditText) v.findViewById(R.id.longitude);
+ eLonDeg = (EditText) v.findViewById(R.id.EditTextLonDeg);
+ eLonMin = (EditText) v.findViewById(R.id.EditTextLonMin);
+ eLonSec = (EditText) v.findViewById(R.id.EditTextLonSec);
+ eLonSub = (EditText) v.findViewById(R.id.EditTextLonSecFrac);
+ tLonSep1 = (TextView) v.findViewById(R.id.LonSeparator1);
+ tLonSep2 = (TextView) v.findViewById(R.id.LonSeparator2);
+ tLonSep3 = (TextView) v.findViewById(R.id.LonSeparator3);
eLatDeg.addTextChangedListener(new TextChanged(eLatDeg));
eLatMin.addTextChangedListener(new TextChanged(eLatMin));
@@ -115,18 +146,24 @@ public class CoordinatesInputDialog extends NoTitleDialog {
bLat.setOnClickListener(new ButtonClickListener());
bLon.setOnClickListener(new ButtonClickListener());
- final Button buttonCurrent = (Button) findViewById(R.id.current);
+ final Button buttonCurrent = (Button) v.findViewById(R.id.current);
buttonCurrent.setOnClickListener(new CurrentListener());
- final Button buttonCache = (Button) findViewById(R.id.cache);
- if (cache != null) {
+ final Button buttonCache = (Button) v.findViewById(R.id.cache);
+
+ if (cacheCoords != null) {
buttonCache.setOnClickListener(new CacheListener());
} else {
buttonCache.setVisibility(View.GONE);
}
- final Button buttonDone = (Button) findViewById(R.id.done);
+
+ final Button buttonDone = (Button) v.findViewById(R.id.done);
buttonDone.setOnClickListener(new InputDoneListener());
+
+ return v;
}
+
+
private void updateGUI() {
if (gp == null) {
return;
@@ -137,14 +174,14 @@ public class CoordinatesInputDialog extends NoTitleDialog {
switch (currentFormat) {
case Plain:
- findViewById(R.id.coordTable).setVisibility(View.GONE);
+ getView().findViewById(R.id.coordTable).setVisibility(View.GONE);
eLat.setVisibility(View.VISIBLE);
eLon.setVisibility(View.VISIBLE);
eLat.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
eLon.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
break;
case Deg: // DDD.DDDDD°
- findViewById(R.id.coordTable).setVisibility(View.VISIBLE);
+ getView().findViewById(R.id.coordTable).setVisibility(View.VISIBLE);
eLat.setVisibility(View.GONE);
eLon.setVisibility(View.GONE);
eLatSec.setVisibility(View.GONE);
@@ -165,7 +202,7 @@ public class CoordinatesInputDialog extends NoTitleDialog {
eLonMin.setText(addZeros(gp.getLonDegFrac(), 5));
break;
case Min: // DDD° MM.MMM
- findViewById(R.id.coordTable).setVisibility(View.VISIBLE);
+ getView().findViewById(R.id.coordTable).setVisibility(View.VISIBLE);
eLat.setVisibility(View.GONE);
eLon.setVisibility(View.GONE);
eLatSec.setVisibility(View.VISIBLE);
@@ -190,7 +227,7 @@ public class CoordinatesInputDialog extends NoTitleDialog {
eLonSec.setText(addZeros(gp.getLonMinFrac(), 3));
break;
case Sec: // DDD° MM SS.SSS
- findViewById(R.id.coordTable).setVisibility(View.VISIBLE);
+ getView().findViewById(R.id.coordTable).setVisibility(View.VISIBLE);
eLat.setVisibility(View.GONE);
eLon.setVisibility(View.GONE);
eLatSec.setVisibility(View.VISIBLE);
@@ -371,7 +408,8 @@ public class CoordinatesInputDialog extends NoTitleDialog {
// Signaled and returned below
}
if (signalError) {
- context.showToast(context.getResources().getString(R.string.err_parse_lat_lon));
+ final AbstractActivity activity = (AbstractActivity) getActivity();
+ activity.showToast(activity.getResources().getString(R.string.err_parse_lat_lon));
}
return false;
}
@@ -399,8 +437,8 @@ public class CoordinatesInputDialog extends NoTitleDialog {
// Start new format with an acceptable value: either the current one
// entered by the user, else our current coordinates, else (0,0).
if (!areCurrentCoordinatesValid(false)) {
- if (geo != null && geo.getCoords() != null) {
- gp = geo.getCoords();
+ if (gpinitial != null) {
+ gp = gpinitial;
} else {
gp = Geopoint.ZERO;
}
@@ -422,12 +460,13 @@ public class CoordinatesInputDialog extends NoTitleDialog {
@Override
public void onClick(View v) {
- if (geo == null || geo.getCoords() == null) {
- context.showToast(context.getResources().getString(R.string.err_point_unknown_position));
+ if (gpinitial == null) {
+ final AbstractActivity activity = (AbstractActivity) getActivity();
+ activity.showToast(activity.getResources().getString(R.string.err_point_unknown_position));
return;
}
- gp = geo.getCoords();
+ gp = gpinitial;
updateGUI();
}
}
@@ -436,16 +475,18 @@ public class CoordinatesInputDialog extends NoTitleDialog {
@Override
public void onClick(View v) {
- if (cache == null || cache.getCoords() == null) {
- context.showToast(context.getResources().getString(R.string.err_location_unknown));
+ if (cacheCoords == null) {
+ final AbstractActivity activity = (AbstractActivity) getActivity();
+ activity.showToast(activity.getResources().getString(R.string.err_location_unknown));
return;
}
- gp = cache.getCoords();
+ gp = cacheCoords;
updateGUI();
}
}
+
private class InputDoneListener implements View.OnClickListener {
@Override
@@ -454,18 +495,14 @@ public class CoordinatesInputDialog extends NoTitleDialog {
return;
}
if (gp != null) {
- cuListener.update(gp);
+ ((CoordinateUpdate) getActivity()).updateCoordinates(gp);
}
dismiss();
}
}
- public void setOnCoordinateUpdate(CoordinateUpdate cu) {
- cuListener = cu;
- }
-
public interface CoordinateUpdate {
- public void update(final Geopoint gp);
+ public void updateCoordinates(final Geopoint gp);
}
}
diff --git a/main/src/cgeo/geocaching/ui/dialog/DateDialog.java b/main/src/cgeo/geocaching/ui/dialog/DateDialog.java
index 18f8e2e..fc69f44 100644
--- a/main/src/cgeo/geocaching/ui/dialog/DateDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/DateDialog.java
@@ -2,48 +2,56 @@ package cgeo.geocaching.ui.dialog;
import cgeo.geocaching.R;
-import android.app.Activity;
import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import android.widget.DatePicker;
import java.util.Calendar;
-public class DateDialog extends NoTitleDialog {
+public class DateDialog extends DialogFragment {
public interface DateDialogParent {
abstract public void setDate(final Calendar date);
}
- private final DateDialogParent parent;
- private final Calendar date;
+ private Calendar date;
- public DateDialog(Activity contextIn, DateDialogParent parentIn, Calendar dateIn) {
- super(contextIn);
-
- // init
- this.date = dateIn;
- this.parent = parentIn;
+ public static DateDialog getInstance(Calendar date) {
+ DateDialog dd = new DateDialog();
+ Bundle args = new Bundle();
+ args.putSerializable("date", date);
+ dd.setArguments(args);
+ return dd;
}
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setStyle(DialogFragment.STYLE_NO_TITLE, 0);
+ Bundle args = getArguments();
+ date = (Calendar) args.getSerializable("date");
+ }
- setContentView(R.layout.date);
+ @Override
+ public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.date, container, false);
- final DatePicker picker = (DatePicker) findViewById(R.id.picker);
+ final DatePicker picker = (DatePicker) v.findViewById(R.id.picker);
picker.init(date.get(Calendar.YEAR), date.get(Calendar.MONTH), date.get(Calendar.DATE), new DatePickerListener());
+ return v;
}
private class DatePickerListener implements DatePicker.OnDateChangedListener {
@Override
public void onDateChanged(DatePicker picker, int year, int month, int day) {
- if (parent != null) {
- date.set(year, month, day);
+ date.set(year, month, day);
+
+ ((DateDialogParent) getActivity()).setDate(date);
- parent.setDate(date);
- }
}
}
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/ui/dialog/Dialogs.java b/main/src/cgeo/geocaching/ui/dialog/Dialogs.java
index cb8926a..6a2f9a5 100644
--- a/main/src/cgeo/geocaching/ui/dialog/Dialogs.java
+++ b/main/src/cgeo/geocaching/ui/dialog/Dialogs.java
@@ -218,7 +218,19 @@ public final class Dialogs {
/**
* Show a message dialog with a single "OK" button.
- *
+ *
+ * @param context
+ * activity owning the dialog
+ * @param message
+ * message dialog content
+ */
+ public static void message(final Activity context, final int message) {
+ message(context, null, getString(message));
+ }
+
+ /**
+ * Show a message dialog with a single "OK" button.
+ *
* @param context
* activity owning the dialog
* @param title
diff --git a/main/src/cgeo/geocaching/ui/dialog/NoTitleDialog.java b/main/src/cgeo/geocaching/ui/dialog/NoTitleDialog.java
deleted file mode 100644
index 8660a7b..0000000
--- a/main/src/cgeo/geocaching/ui/dialog/NoTitleDialog.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package cgeo.geocaching.ui.dialog;
-
-import cgeo.geocaching.utils.Log;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.view.ViewGroup.LayoutParams;
-import android.view.Window;
-
-public abstract class NoTitleDialog extends Dialog {
-
- public NoTitleDialog(Context context) {
- super(context);
- }
-
- public NoTitleDialog(Context context, int theme) {
- super(context, theme);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- try {
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
- } catch (final Exception e) {
- Log.e("NoTitleDialog.onCreate", e);
- }
- }
-}
diff --git a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java
index 4ce2e0c..14840b9 100644
--- a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java
+++ b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java
@@ -10,7 +10,6 @@ import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
import android.app.ProgressDialog;
-import android.content.Context;
import android.content.res.Resources;
import java.io.File;
@@ -53,7 +52,6 @@ public class DatabaseBackupUtils {
}
public static boolean createBackup(final Activity activity, final Runnable runAfterwards) {
- final Context context = activity;
// avoid overwriting an existing backup with an empty database
// (can happen directly after reinstalling the app)
if (DataStore.getAllCachesCount() == 0) {
@@ -61,9 +59,9 @@ public class DatabaseBackupUtils {
return false;
}
- final ProgressDialog dialog = ProgressDialog.show(context,
- context.getString(R.string.init_backup),
- context.getString(R.string.init_backup_running), true, false);
+ final ProgressDialog dialog = ProgressDialog.show(activity,
+ activity.getString(R.string.init_backup),
+ activity.getString(R.string.init_backup_running), true, false);
new Thread() {
@Override
public void run() {
@@ -75,9 +73,9 @@ public class DatabaseBackupUtils {
Dialogs.message(activity,
R.string.init_backup_backup,
backupFileName != null
- ? context.getString(R.string.init_backup_success)
+ ? activity.getString(R.string.init_backup_success)
+ "\n" + backupFileName
- : context.getString(R.string.init_backup_failed));
+ : activity.getString(R.string.init_backup_failed));
if (runAfterwards != null) {
runAfterwards.run();
}
diff --git a/main/src/cgeo/geocaching/utils/DebugUtils.java b/main/src/cgeo/geocaching/utils/DebugUtils.java
new file mode 100644
index 0000000..07aac64
--- /dev/null
+++ b/main/src/cgeo/geocaching/utils/DebugUtils.java
@@ -0,0 +1,37 @@
+package cgeo.geocaching.utils;
+
+import cgeo.geocaching.R;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+import android.content.Context;
+import android.os.Environment;
+import android.widget.Toast;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class DebugUtils {
+
+ private DebugUtils() {
+ // utility class
+ }
+
+ public static void createMemoryDump(final @NonNull Context context) {
+ try {
+ final Date now = new Date();
+ final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyy-MM-dd_hh-mm", Locale.US);
+ File file = FileUtils.getUniqueNamedFile(Environment.getExternalStorageDirectory().getPath()
+ + File.separatorChar + "cgeo_dump_" + fileNameDateFormat.format(now) + ".hprof");
+ android.os.Debug.dumpHprofData(file.getPath());
+ Toast.makeText(context, context.getString(R.string.init_memory_dumped, file.getAbsolutePath()),
+ Toast.LENGTH_LONG).show();
+ ShareUtils.share(context, file, R.string.init_memory_dump);
+ } catch (IOException e) {
+ Log.e("createMemoryDump", e);
+ }
+ }
+}
diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
index 5fa0982..3507116 100644
--- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
+++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
@@ -36,9 +36,9 @@ public final class LogTemplateProvider {
private Geocache cache;
private Trackable trackable;
private boolean offline = false;
- private LogEntry logEntry;
+ private final LogEntry logEntry;
- public LogContext(final Geocache cache, LogEntry logEntry) {
+ public LogContext(final Geocache cache, final LogEntry logEntry) {
this(cache, logEntry, false);
}
@@ -47,7 +47,7 @@ public final class LogTemplateProvider {
this.logEntry = logEntry;
}
- public LogContext(final Geocache cache, LogEntry logEntry, final boolean offline) {
+ public LogContext(final Geocache cache, final LogEntry logEntry, final boolean offline) {
this.cache = cache;
this.offline = offline;
this.logEntry = logEntry;
@@ -104,8 +104,11 @@ public final class LogTemplateProvider {
}
}
- public static ArrayList<LogTemplate> getTemplates() {
- ArrayList<LogTemplate> templates = new ArrayList<LogTemplateProvider.LogTemplate>();
+ /**
+ * @return all templates, but not the signature template itself
+ */
+ public static ArrayList<LogTemplate> getTemplatesWithoutSignature() {
+ final ArrayList<LogTemplate> templates = new ArrayList<LogTemplateProvider.LogTemplate>();
templates.add(new LogTemplate("DATE", R.string.init_signature_template_date) {
@Override
@@ -132,6 +135,13 @@ public final class LogTemplateProvider {
@Override
public String getValue(final LogContext context) {
+ final Geocache cache = context.getCache();
+ if (cache != null) {
+ final IConnector connector = ConnectorFactory.getConnector(cache);
+ if (connector instanceof ILogin) {
+ return ((ILogin) connector).getUserName();
+ }
+ }
return Settings.getUsername();
}
});
@@ -171,11 +181,11 @@ public final class LogTemplateProvider {
@Override
public String getValue(final LogContext context) {
- Trackable trackable = context.getTrackable();
+ final Trackable trackable = context.getTrackable();
if (trackable != null) {
return trackable.getOwner();
}
- Geocache cache = context.getCache();
+ final Geocache cache = context.getCache();
if (cache != null) {
return cache.getOwnerDisplayName();
}
@@ -184,12 +194,12 @@ public final class LogTemplateProvider {
});
templates.add(new LogTemplate("NAME", R.string.init_signature_template_name) {
@Override
- public String getValue(LogContext context) {
- Trackable trackable = context.getTrackable();
+ public String getValue(final LogContext context) {
+ final Trackable trackable = context.getTrackable();
if (trackable != null) {
return trackable.getName();
}
- Geocache cache = context.getCache();
+ final Geocache cache = context.getCache();
if (cache != null) {
return cache.getName();
}
@@ -199,12 +209,12 @@ public final class LogTemplateProvider {
templates.add(new LogTemplate("URL", R.string.init_signature_template_url) {
@Override
- public String getValue(LogContext context) {
- Trackable trackable = context.getTrackable();
+ public String getValue(final LogContext context) {
+ final Trackable trackable = context.getTrackable();
if (trackable != null) {
return trackable.getUrl();
}
- Geocache cache = context.getCache();
+ final Geocache cache = context.getCache();
if (cache != null) {
return cache.getUrl();
}
@@ -213,8 +223,8 @@ public final class LogTemplateProvider {
});
templates.add(new LogTemplate("LOG", R.string.init_signature_template_log) {
@Override
- public String getValue(LogContext context) {
- LogEntry logEntry = context.getLogEntry();
+ public String getValue(final LogContext context) {
+ final LogEntry logEntry = context.getLogEntry();
if (logEntry != null) {
return logEntry.getDisplayText();
}
@@ -224,8 +234,26 @@ public final class LogTemplateProvider {
return templates;
}
+ /**
+ * @return all templates, including the signature template
+ */
+ public static ArrayList<LogTemplate> getTemplatesWithSignature() {
+ final ArrayList<LogTemplate> templates = getTemplatesWithoutSignature();
+ templates.add(new LogTemplate("SIGNATURE", R.string.init_signature) {
+ @Override
+ public String getValue(final LogContext context) {
+ final String nestedTemplate = StringUtils.defaultString(Settings.getSignature());
+ if (StringUtils.contains(nestedTemplate, "SIGNATURE")) {
+ return "invalid signature template";
+ }
+ return LogTemplateProvider.applyTemplates(nestedTemplate, context);
+ }
+ });
+ return templates;
+ }
+
public static LogTemplate getTemplate(final int itemId) {
- for (LogTemplate template : getTemplates()) {
+ for (final LogTemplate template : getTemplatesWithSignature()) {
if (template.getItemId() == itemId) {
return template;
}
@@ -238,7 +266,7 @@ public final class LogTemplateProvider {
return StringUtils.EMPTY;
}
String result = signature;
- for (LogTemplate template : getTemplates()) {
+ for (final LogTemplate template : getTemplatesWithSignature()) {
result = template.apply(result, context);
}
return result;
diff --git a/main/src/cgeo/geocaching/utils/RxUtils.java b/main/src/cgeo/geocaching/utils/RxUtils.java
index 8e7864c..b865f0b 100644
--- a/main/src/cgeo/geocaching/utils/RxUtils.java
+++ b/main/src/cgeo/geocaching/utils/RxUtils.java
@@ -1,18 +1,23 @@
package cgeo.geocaching.utils;
+import rx.Observable;
import rx.Scheduler;
+import rx.observables.BlockingObservable;
import rx.schedulers.Schedulers;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
public class RxUtils {
// Utility class, not to be instanciated
private RxUtils() {}
- final static private int cores = Runtime.getRuntime().availableProcessors();
- public final static Scheduler computationScheduler = Schedulers.executor(new ThreadPoolExecutor(1, cores, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()));
+ public final static Scheduler computationScheduler = Schedulers.computation();
+
+ public static <T> void waitForCompletion(final BlockingObservable<T> observable) {
+ observable.lastOrDefault(null);
+ return;
+ }
+ public static void waitForCompletion(final Observable<?>... observables) {
+ waitForCompletion(Observable.merge(observables).toBlocking());
+ }
}
diff --git a/main/src/cgeo/geocaching/utils/ShareUtils.java b/main/src/cgeo/geocaching/utils/ShareUtils.java
new file mode 100644
index 0000000..bfd6838
--- /dev/null
+++ b/main/src/cgeo/geocaching/utils/ShareUtils.java
@@ -0,0 +1,27 @@
+package cgeo.geocaching.utils;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import java.io.File;
+
+public class ShareUtils {
+ private ShareUtils() {
+ // utility class
+ }
+
+ public static void share(final Context context, final @NonNull File file, final @NonNull String mimeType, final int titleResourceId) {
+ final Intent shareIntent = new Intent();
+ shareIntent.setAction(Intent.ACTION_SEND);
+ shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
+ shareIntent.setType(mimeType);
+ context.startActivity(Intent.createChooser(shareIntent, context.getString(titleResourceId)));
+ }
+
+ public static void share(final Context context, final @NonNull File file, final int titleResourceId) {
+ share(context, file, "*/*", titleResourceId);
+ }
+}
diff --git a/main/src/cgeo/geocaching/utils/TextUtils.java b/main/src/cgeo/geocaching/utils/TextUtils.java
index ef09f32..77aa167 100644
--- a/main/src/cgeo/geocaching/utils/TextUtils.java
+++ b/main/src/cgeo/geocaching/utils/TextUtils.java
@@ -4,11 +4,13 @@
package cgeo.geocaching.utils;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
import org.eclipse.jdt.annotation.Nullable;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.zip.CRC32;
/**
* Misc. utils. All methods don't use Android specific stuff to use these methods in plain JUnit tests.
@@ -52,7 +54,7 @@ public final class TextUtils {
result = matcher.group(group);
}
if (null != result) {
- Matcher remover = PATTERN_REMOVE_NONPRINTABLE.matcher(result);
+ final Matcher remover = PATTERN_REMOVE_NONPRINTABLE.matcher(result);
result = remover.replaceAll(" ");
return trim ? new String(result).trim() : new String(result);
@@ -134,7 +136,7 @@ public final class TextUtils {
data.getChars(0, length, chars, 0);
int resultSize = 0;
boolean lastWasWhitespace = true;
- for (char c : chars) {
+ for (final char c : chars) {
if (c == ' ' || c == '\n' || c == '\r' || c == '\t') {
if (!lastWasWhitespace) {
chars[resultSize++] = ' ';
@@ -167,8 +169,20 @@ public final class TextUtils {
* @return
*/
public static String removeControlCharacters(final String input) {
- Matcher remover = PATTERN_REMOVE_NONPRINTABLE.matcher(input);
+ final Matcher remover = PATTERN_REMOVE_NONPRINTABLE.matcher(input);
return remover.replaceAll(" ").trim();
}
+ /**
+ * Calculate a simple checksum for change-checking (not usable for security/cryptography!)
+ *
+ * @param input
+ * String to check
+ * @return resulting checksum
+ */
+ public static long checksum(final String input) {
+ final CRC32 checksum = new CRC32();
+ checksum.update(input.getBytes());
+ return checksum.getValue();
+ }
}
diff --git a/main/src/cgeo/geocaching/utils/TranslationUtils.java b/main/src/cgeo/geocaching/utils/TranslationUtils.java
index 619db08..ea3c395 100644
--- a/main/src/cgeo/geocaching/utils/TranslationUtils.java
+++ b/main/src/cgeo/geocaching/utils/TranslationUtils.java
@@ -1,10 +1,10 @@
package cgeo.geocaching.utils;
-import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.network.Network;
import org.apache.commons.lang3.StringUtils;
+import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
@@ -51,7 +51,7 @@ public final class TranslationUtils {
* @param text
* The text to be translated
*/
- public static void startActivityTranslate(final AbstractActivity context, final String toLang, final String text) {
+ public static void startActivityTranslate(final Activity context, final String toLang, final String text) {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(buildTranslationURI(toLang, text))));
}
}