diff options
Diffstat (limited to 'main/src/cgeo')
165 files changed, 1501 insertions, 1096 deletions
diff --git a/main/src/cgeo/calendar/CalendarAddon.java b/main/src/cgeo/calendar/CalendarAddon.java index 8737447..88c67a8 100644 --- a/main/src/cgeo/calendar/CalendarAddon.java +++ b/main/src/cgeo/calendar/CalendarAddon.java @@ -8,6 +8,7 @@ import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.ProcessUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; import android.content.DialogInterface; @@ -27,10 +28,11 @@ public class CalendarAddon { return ProcessUtils.isIntentAvailable(ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST)); } - public static void addToCalendarWithIntent(final Activity activity, final Geocache cache) { + public static void addToCalendarWithIntent(@NonNull final Activity activity, @NonNull final Geocache cache) { final Resources res = activity.getResources(); if (CalendarAddon.isAvailable()) { final Date hiddenDate = cache.getHiddenDate(); + final String startTime = cache.guessEventTimeMinutes() >= 0 ? String.valueOf(cache.guessEventTimeMinutes()) : StringUtils.EMPTY; final Parameters params = new Parameters( ICalendar.PARAM_NAME, cache.getName(), ICalendar.PARAM_NOTE, StringUtils.defaultString(cache.getPersonalNote()), @@ -39,7 +41,7 @@ public class CalendarAddon { ICalendar.PARAM_COORDS, cache.getCoords() == null ? "" : cache.getCoords().format(GeopointFormatter.Format.LAT_LON_DECMINUTE_RAW), ICalendar.PARAM_LOCATION, StringUtils.defaultString(cache.getLocation()), ICalendar.PARAM_SHORT_DESC, StringUtils.defaultString(cache.getShortDescription()), - ICalendar.PARAM_START_TIME_MINUTES, StringUtils.defaultString(cache.guessEventTimeMinutes()) + ICalendar.PARAM_START_TIME_MINUTES, startTime ); activity.startActivity(new Intent(ICalendar.INTENT, @@ -51,10 +53,8 @@ public class CalendarAddon { .append(res.getString(R.string.addon_download_prompt)) .toString(), new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int id) { - final Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(ICalendar.CALENDAR_ADDON_URI)); - activity.startActivity(intent); + public void onClick(final DialogInterface dialog, final int id) { + ProcessUtils.openMarket(activity, "cgeo.calendar"); } }); } diff --git a/main/src/cgeo/calendar/ICalendar.java b/main/src/cgeo/calendar/ICalendar.java index 6ecb6d5..9001198 100644 --- a/main/src/cgeo/calendar/ICalendar.java +++ b/main/src/cgeo/calendar/ICalendar.java @@ -1,19 +1,22 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + public interface ICalendar { - static final String CALENDAR_ADDON_URI = "market://details?id=cgeo.calendar"; + @Deprecated + @NonNull static final String CALENDAR_ADDON_URI = "market://details?id=cgeo.calendar"; - static final String INTENT = "cgeo.calendar.RESERVE"; + @NonNull static final String INTENT = "cgeo.calendar.RESERVE"; - static final String URI_SCHEME = "add"; - static final String URI_HOST = "cgeo.org"; + @NonNull static final String URI_SCHEME = "add"; + @NonNull static final String URI_HOST = "cgeo.org"; - static final String PARAM_SHORT_DESC = "shortDesc"; // cache short description - static final String PARAM_HIDDEN_DATE = "hiddenDate"; // cache hidden date in milliseconds - static final String PARAM_URL = "url"; // cache URL - static final String PARAM_NOTE = "note"; // personal note - static final String PARAM_NAME = "name"; // cache name - static final String PARAM_LOCATION = "location"; // cache location, or empty string - static final String PARAM_COORDS = "coords"; // cache coordinates, or empty string - static final String PARAM_START_TIME_MINUTES = "time"; // time of start + @NonNull static final String PARAM_SHORT_DESC = "shortDesc"; // cache short description + @NonNull static final String PARAM_HIDDEN_DATE = "hiddenDate"; // cache hidden date in milliseconds + @NonNull static final String PARAM_URL = "url"; // cache URL + @NonNull static final String PARAM_NOTE = "note"; // personal note + @NonNull static final String PARAM_NAME = "name"; // cache name + @NonNull static final String PARAM_LOCATION = "location"; // cache location, or empty string + @NonNull static final String PARAM_COORDS = "coords"; // cache coordinates, or empty string + @NonNull static final String PARAM_START_TIME_MINUTES = "time"; // time of start } diff --git a/main/src/cgeo/contacts/ContactsAddon.java b/main/src/cgeo/contacts/ContactsAddon.java index 7165a77..6c0dd21 100644 --- a/main/src/cgeo/contacts/ContactsAddon.java +++ b/main/src/cgeo/contacts/ContactsAddon.java @@ -3,6 +3,8 @@ package cgeo.contacts; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.ProcessUtils; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.content.Intent; import android.net.Uri; @@ -13,7 +15,7 @@ public class ContactsAddon { // utility class } - public static void openContactCard(Activity context, String userName) { + public static void openContactCard(@NonNull final Activity context, @NonNull final String userName) { final Parameters params = new Parameters( IContacts.PARAM_NAME, userName ); diff --git a/main/src/cgeo/contacts/IContacts.java b/main/src/cgeo/contacts/IContacts.java index d68b78a..5a6c04d 100644 --- a/main/src/cgeo/contacts/IContacts.java +++ b/main/src/cgeo/contacts/IContacts.java @@ -1,10 +1,12 @@ package cgeo.contacts; +import org.eclipse.jdt.annotation.NonNull; + public interface IContacts { - static final String INTENT = "cgeo.contacts.FIND"; + @NonNull static final String INTENT = "cgeo.contacts.FIND"; - static final String URI_SCHEME = "find"; - static final String URI_HOST = "cgeo.org"; + @NonNull static final String URI_SCHEME = "find"; + @NonNull static final String URI_HOST = "cgeo.org"; - static final String PARAM_NAME = "name"; // user name + @NonNull static final String PARAM_NAME = "name"; // user name } diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java index ceafc31..ffc4b35 100644 --- a/main/src/cgeo/geocaching/AboutActivity.java +++ b/main/src/cgeo/geocaching/AboutActivity.java @@ -4,12 +4,14 @@ import butterknife.ButterKnife; import butterknife.InjectView; import cgeo.geocaching.activity.AbstractViewPagerActivity; +import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.sensors.OrientationProvider; import cgeo.geocaching.sensors.RotationProvider; import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.AbstractCachingPageViewCreator; import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; +import cgeo.geocaching.utils.ProcessUtils; import cgeo.geocaching.utils.Version; import org.apache.commons.io.IOUtils; @@ -98,6 +100,7 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> ButterKnife.inject(this, view); system.setText(systemInformation(AboutActivity.this)); system.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); + Compatibility.setTextIsSelectable(system, true); return view; } } @@ -125,7 +128,7 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> @Override public void onClick(final View v) { - market(); + ProcessUtils.openMarket(AboutActivity.this, getPackageName()); } }); return view; @@ -190,12 +193,6 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); } - final void market() { - final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName())); - marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - startActivity(marketIntent); - } - @Override protected final cgeo.geocaching.activity.AbstractViewPagerActivity.PageViewCreator createViewCreator(final Page page) { switch (page) { diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 2be802f..93f2d31 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -61,6 +61,7 @@ import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; +import org.eclipse.jdt.annotation.Nullable; import rx.Observable; import rx.Observable.OnSubscribe; @@ -101,6 +102,7 @@ import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.text.style.StrikethroughSpan; import android.text.style.StyleSpan; +import android.text.util.Linkify; import android.util.TypedValue; import android.view.ContextMenu; import android.view.Menu; @@ -206,6 +208,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc geocode = MapsWithMeCacheListApp.getCacheFromMapsWithMe(this, getIntent()); } + if (geocode == null && uri != null) { + geocode = ConnectorFactory.getGeocodeFromURL(uri.toString()); + } + // try to get data from URI if (geocode == null && guid == null && uri != null) { final String uriHost = uri.getHost().toLowerCase(Locale.US); @@ -237,31 +243,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc return; } } - } else if (uriHost.contains("coord.info")) { - if (StringUtils.startsWith(uriPath, "/gc")) { - geocode = uriPath.substring(1).toUpperCase(Locale.US); - } else { - showToast(res.getString(R.string.err_detail_open)); - finish(); - return; - } - } else if (uriHost.contains("opencaching.de") || uriHost.contains("opencaching.fr")) { - if (StringUtils.startsWith(uriPath, "/oc")) { - geocode = uriPath.substring(1).toUpperCase(Locale.US); - } else { - geocode = uri.getQueryParameter("wp"); - if (StringUtils.isNotBlank(geocode)) { - geocode = geocode.toUpperCase(Locale.US); - } else { - showToast(res.getString(R.string.err_detail_open)); - finish(); - return; - } - } - } else { - showToast(res.getString(R.string.err_detail_open)); - finish(); - return; } } @@ -305,6 +286,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } requireGeodata = getPage(position) == Page.DETAILS; startOrStopGeoDataListener(); + + // cancel contextual actions on page change + if (currentActionMode != null) { + currentActionMode.finish(); + } } }); requireGeodata = pageToOpen == 1; @@ -326,6 +312,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } @Override + @Nullable public String getAndroidBeamUri() { return cache != null ? cache.getCgeoUrl() : null; } @@ -494,13 +481,12 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public boolean onCreateOptionsMenu(final Menu menu) { CacheMenuHandler.addMenuItems(this, menu, cache); - MenuItem menuItem = menu.findItem(R.id.menu_default_navigation); + final MenuItem menuItem = menu.findItem(R.id.menu_default_navigation); final NavigationActionProvider navAction = (NavigationActionProvider) MenuItemCompat.getActionProvider(menuItem); if (navAction != null) { navAction.setNavigationSource(this); } - menuItem = menu.findItem(R.id.menu_navigate); - NavigationSelectionActionProvider.initialize(menuItem, cache); + NavigationSelectionActionProvider.initialize(menu.findItem(R.id.menu_navigate), cache); return true; } @@ -1287,6 +1273,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc }); + /** + * Reflect the (contextual) action mode of the action bar. + */ + protected ActionMode currentActionMode; + protected class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> { @InjectView(R.id.personalnote) protected TextView personalNoteView; @@ -1462,9 +1453,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (unknownTagsHandler.isProblematicDetected()) { final int startPos = description.length(); final IConnector connector = ConnectorFactory.getConnector(cache); - final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>")); - ((Editable) description).append("\n\n").append(tableNote); - ((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (StringUtils.isNotEmpty(cache.getUrl())) { + final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>")); + ((Editable) description).append("\n\n").append(tableNote); + ((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } } } /** @@ -1785,7 +1778,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public boolean onLongClick(final View v) { - startSupportActionMode(new ActionMode.Callback() { + currentActionMode = startSupportActionMode(new ActionMode.Callback() { @Override public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) { @@ -1834,7 +1827,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public void onDestroyActionMode(final ActionMode actionMode) { - // do nothing + currentActionMode = null; } @Override @@ -2176,6 +2169,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc personalNoteView.setText(personalNote, TextView.BufferType.SPANNABLE); if (StringUtils.isNotBlank(personalNote)) { personalNoteView.setVisibility(View.VISIBLE); + Linkify.addLinks(personalNoteView, Linkify.ALL); } else { personalNoteView.setVisibility(View.GONE); } @@ -2195,4 +2189,8 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc public void cachesAround() { CacheListActivity.startActivityCoordinates(this, cache.getCoords()); } + + public void setNeedsRefresh() { + refreshOnResume = true; + } } diff --git a/main/src/cgeo/geocaching/CacheListActivity.java b/main/src/cgeo/geocaching/CacheListActivity.java index 9090a4e..d4d46fd 100644 --- a/main/src/cgeo/geocaching/CacheListActivity.java +++ b/main/src/cgeo/geocaching/CacheListActivity.java @@ -9,7 +9,9 @@ import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.activity.ShowcaseViewBuilder; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; -import cgeo.geocaching.apps.cachelist.CacheListAppFactory; +import cgeo.geocaching.apps.cachelist.CacheListApp; +import cgeo.geocaching.apps.cachelist.CacheListApps; +import cgeo.geocaching.apps.cachelist.ListNavigationSelectionActionProvider; import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.connector.gc.RecaptchaHandler; import cgeo.geocaching.enumerations.CacheListType; @@ -55,7 +57,7 @@ import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.AngleUtils; import cgeo.geocaching.utils.AsyncTaskWithProgress; import cgeo.geocaching.utils.CancellableHandler; -import cgeo.geocaching.utils.DateUtils; +import cgeo.geocaching.utils.CalendarUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.RxUtils; @@ -558,7 +560,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA 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)); assert sortProvider != null; // We set it in the XML file sortProvider.setSelection(adapter.getCacheComparator()); @@ -579,6 +580,15 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA sortProvider.setSelection(selectedComparator); } }); + + ListNavigationSelectionActionProvider.initialize(menu.findItem(R.id.menu_cache_list_app_provider), new ListNavigationSelectionActionProvider.Callback() { + + @Override + public void onListNavigationSelected(final CacheListApp app) { + app.invoke(cacheList, CacheListActivity.this, getFilteredSearch()); + } + }); + return true; } @@ -639,6 +649,11 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA setMenuItemLabel(menu, R.id.menu_remove_from_history, R.string.cache_remove_from_history, R.string.cache_clear_history); menu.findItem(R.id.menu_import_android).setVisible(Compatibility.isStorageAccessFrameworkAvailable() && isOffline); + + final List<CacheListApp> listNavigationApps = CacheListApps.getActiveApps(); + menu.findItem(R.id.menu_cache_list_app_provider).setVisible(listNavigationApps.size() > 1); + menu.findItem(R.id.menu_cache_list_app).setVisible(listNavigationApps.size() == 1); + } catch (final RuntimeException e) { Log.e("CacheListActivity.onPrepareOptionsMenu", e); } @@ -648,7 +663,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA private boolean containsPastEvents() { for (final Geocache cache : adapter.getCheckedOrAllCaches()) { - if (DateUtils.isPastEvent(cache)) { + if (CalendarUtils.isPastEvent(cache)) { return true; } } @@ -679,9 +694,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA @Override public boolean onOptionsItemSelected(final MenuItem item) { - if (super.onOptionsItemSelected(item)) { - return true; - } switch (item.getItemId()) { case R.id.menu_show_on_map: goMap(); @@ -705,23 +717,23 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA case R.id.menu_import_android: importGpxFromAndroid(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_create_list: new StoredList.UserInterface(this).promptForListCreation(getListSwitchingRunnable(), listNameMemento.getTerm()); refreshSpinnerAdapter(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_drop_list: removeList(false); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_rename_list: renameList(); - return false; + return true; case R.id.menu_invert_selection: adapter.invertSelection(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_filter: showFilterMenu(null); return true; @@ -737,7 +749,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA case R.id.menu_remove_from_history: removeFromHistoryCheck(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_move_to_list: moveCachesToOtherList(); invalidateOptionsMenuCompatible(); @@ -751,13 +763,12 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA invalidateOptionsMenuCompatible(); return true; case R.id.menu_cache_list_app: - if (!cacheToShow()) { - return false; + if (cacheToShow()) { + CacheListApps.getActiveApps().get(0).invoke(cacheList, this, getFilteredSearch()); } - return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, getFilteredSearch()); - default: - return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, search); + return true; } + return super.onOptionsItemSelected(item); } private boolean cacheToShow() { @@ -775,7 +786,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA private void deletePastEvents() { final List<Geocache> deletion = new ArrayList<>(); for (final Geocache cache : adapter.getCheckedOrAllCaches()) { - if (DateUtils.isPastEvent(cache)) { + if (CalendarUtils.isPastEvent(cache)) { deletion.add(cache); } } @@ -1639,8 +1650,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA /** * 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 @@ -1658,7 +1667,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA /** * Calculate the subtitle of the current list depending on (optional) filters. * - * @return */ private CharSequence getCurrentSubtitle() { final ArrayList<String> numbers = new ArrayList<>(); diff --git a/main/src/cgeo/geocaching/CacheMenuHandler.java b/main/src/cgeo/geocaching/CacheMenuHandler.java index fa2f994..fbd8771 100644 --- a/main/src/cgeo/geocaching/CacheMenuHandler.java +++ b/main/src/cgeo/geocaching/CacheMenuHandler.java @@ -6,6 +6,8 @@ import cgeo.geocaching.apps.cache.navi.NavigationSelectionActionProvider; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.AbstractUIFactory; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.support.v4.app.Fragment; import android.support.v4.view.MenuItemCompat; @@ -38,7 +40,7 @@ public final class CacheMenuHandler extends AbstractUIFactory { } - public static boolean onMenuItemSelected(final MenuItem item, final CacheMenuHandler.ActivityInterface activityInterface, final Geocache cache) { + public static boolean onMenuItemSelected(final MenuItem item, @NonNull final CacheMenuHandler.ActivityInterface activityInterface, final Geocache cache) { assert activityInterface instanceof Activity || activityInterface instanceof Fragment; final Activity activity; if (activityInterface instanceof Activity) { diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java index 27dbb4a..d481d58 100644 --- a/main/src/cgeo/geocaching/CompassActivity.java +++ b/main/src/cgeo/geocaching/CompassActivity.java @@ -182,7 +182,12 @@ public class CompassActivity extends AbstractActionBarActivity { final int id = item.getItemId(); switch (id) { case R.id.menu_map: - CGeoMap.startActivityCoords(this, dstCoords, null, null); + if (cache != null) { + CGeoMap.startActivityGeoCode(this, cache.getGeocode()); + } + else { + CGeoMap.startActivityCoords(this, dstCoords, null, null); + } return true; case R.id.menu_compass_sensor_gps: Settings.setUseCompass(false); @@ -203,6 +208,9 @@ public class CompassActivity extends AbstractActionBarActivity { case R.id.menu_compass_cache: setTarget(cache); return true; + case R.id.menu_hint: + cache.showHintToast(this); + return true; default: if (LoggingUI.onMenuItemSelected(item, this, cache)) { return true; diff --git a/main/src/cgeo/geocaching/CreateShortcutActivity.java b/main/src/cgeo/geocaching/CreateShortcutActivity.java index 70ab900..ecb7dc4 100644 --- a/main/src/cgeo/geocaching/CreateShortcutActivity.java +++ b/main/src/cgeo/geocaching/CreateShortcutActivity.java @@ -1,6 +1,7 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActionBarActivity; +import cgeo.geocaching.list.PseudoList; import cgeo.geocaching.list.StoredList; import cgeo.geocaching.maps.MapActivity; import cgeo.geocaching.ui.dialog.Dialogs; @@ -67,8 +68,11 @@ public class CreateShortcutActivity extends AbstractActionBarActivity { // shortcuts.add(new Shortcut(R.string.cache_menu_visit, new Intent(this, LogCacheActivity.class))); // shortcuts.add(new Shortcut(R.string.trackable_log_touch, new Intent(this, LogTrackableActivity.class))); - final Shortcut offlineShortcut = new Shortcut(R.string.stored_caches_button, R.drawable.main_stored, null); + final Shortcut offlineShortcut = new Shortcut(R.string.list_title, R.drawable.main_stored, null); shortcuts.add(offlineShortcut); + final Intent allIntent = new Intent(this, CacheListActivity.class); + allIntent.putExtra(Intents.EXTRA_LIST_ID, PseudoList.ALL_LIST.id); + shortcuts.add(new Shortcut(R.string.list_all_lists, R.drawable.main_stored, allIntent)); shortcuts.add(new Shortcut(R.string.advanced_search_button, R.drawable.main_search, new Intent(this, SearchActivity.class))); shortcuts.add(new Shortcut(R.string.any_button, R.drawable.main_any, new Intent(this, NavigateAnyPointActivity.class))); shortcuts.add(new Shortcut(R.string.menu_history, R.drawable.main_stored, CacheListActivity.getHistoryIntent(this))); @@ -94,7 +98,7 @@ public class CreateShortcutActivity extends AbstractActionBarActivity { public void call(final Integer listId) { createOfflineListShortcut(listId); } - }, true, -1); + }, true, PseudoList.NEW_LIST.id); } protected void createOfflineListShortcut(final int listId) { diff --git a/main/src/cgeo/geocaching/DataStore.java b/main/src/cgeo/geocaching/DataStore.java index 02f48a0..b7ca577 100644 --- a/main/src/cgeo/geocaching/DataStore.java +++ b/main/src/cgeo/geocaching/DataStore.java @@ -39,7 +39,6 @@ import rx.functions.Action1; import rx.functions.Func0; import rx.functions.Func1; import rx.schedulers.Schedulers; -import rx.util.async.Async; import android.app.Activity; import android.app.ProgressDialog; @@ -403,16 +402,15 @@ public class DataStore { * Move the database to/from external cgdata in a new thread, * showing a progress window * - * @param fromActivity */ public static void moveDatabase(final Activity fromActivity) { final ProgressDialog dialog = ProgressDialog.show(fromActivity, fromActivity.getString(R.string.init_dbmove_dbmove), fromActivity.getString(R.string.init_dbmove_running), true, false); - AppObservable.bindActivity(fromActivity, Async.fromCallable(new Func0<Boolean>() { + AppObservable.bindActivity(fromActivity, Observable.defer(new Func0<Observable<Boolean>>() { @Override - public Boolean call() { + public Observable<Boolean> call() { if (!LocalStorage.isExternalStorageAvailable()) { Log.w("Database was not moved: external memory not available"); - return false; + return Observable.just(false); } closeDb(); @@ -421,7 +419,7 @@ public class DataStore { if (!LocalStorage.copy(source, target)) { Log.e("Database could not be moved to " + target); init(); - return false; + return Observable.just(false); } if (!FileUtils.delete(source)) { Log.e("Original database could not be deleted during move"); @@ -430,7 +428,7 @@ public class DataStore { Log.i("Database was moved to " + target); init(); - return true; + return Observable.just(true); } })).subscribeOn(Schedulers.io()).subscribe(new Action1<Boolean>() { @Override @@ -884,7 +882,7 @@ public class DataStore { final File[] files = LocalStorage.getStorage().listFiles(); if (ArrayUtils.isNotEmpty(files)) { final Pattern oldFilePattern = Pattern.compile("^[GC|TB|EC|GK|O][A-Z0-9]{4,7}$"); - final SQLiteStatement select = db.compileStatement("select count(*) from " + dbTableCaches + " where geocode = ?"); + final SQLiteStatement select = PreparedStatement.CHECK_IF_PRESENT.getStatement(); final ArrayList<File> toRemove = new ArrayList<>(files.length); for (final File file : files) { if (file.isDirectory()) { @@ -907,7 +905,7 @@ public class DataStore { public void call() { for (final File dir : toRemove) { Log.i("Removing obsolete cache directory for " + dir.getName()); - LocalStorage.deleteDirectory(dir); + FileUtils.deleteDirectory(dir); } } }); @@ -1062,7 +1060,6 @@ public class DataStore { * * @param cache * the Cache to save in the CacheCache/DB - * @param saveFlags * */ public static void saveCache(final Geocache cache, final Set<LoadFlags.SaveFlag> saveFlags) { @@ -1074,7 +1071,6 @@ public class DataStore { * * @param caches * the caches to save in the CacheCache/DB - * @param saveFlags * */ public static void saveCaches(final Collection<Geocache> caches, final Set<LoadFlags.SaveFlag> saveFlags) { @@ -1313,7 +1309,6 @@ public class DataStore { /** * remove all waypoints of the given cache, where the id is not in the given list * - * @param cache * @param remainingWaypointIds * ids of waypoints which shall not be deleted */ @@ -1563,7 +1558,6 @@ public class DataStore { /** * Load caches. * - * @param geocodes * @return Set of loaded caches. Never null. */ @NonNull @@ -1619,8 +1613,6 @@ public class DataStore { /** * Load caches. * - * @param geocodes - * @param loadFlags * @return Set of loaded caches. Never null. */ @NonNull @@ -1710,9 +1702,6 @@ public class DataStore { /** * Builds a where for a viewport with the size enhanced by 50%. * - * @param dbTable - * @param viewport - * @return */ @NonNull @@ -1723,7 +1712,6 @@ public class DataStore { /** * creates a Cache from the cursor. Doesn't next. * - * @param cursor * @return Cache from DB */ @NonNull @@ -1939,7 +1927,6 @@ public class DataStore { } /** - * @param geocode * @return an immutable, non null list of logs */ @NonNull @@ -2089,9 +2076,6 @@ public class DataStore { /** * Number of caches stored for a given type and/or list * - * @param cacheType - * @param list - * @return */ public static int getAllStoredCachesCount(final CacheType cacheType, final int list) { if (cacheType == null) { @@ -2177,8 +2161,6 @@ public class DataStore { * * @param coords * the current coordinates to sort by distance, or null to sort by geocode - * @param cacheType - * @param listId * @return a non-null set of geocodes */ @NonNull @@ -2374,7 +2356,7 @@ public class DataStore { database.delete(dbTableLogImages, "log_id NOT IN (SELECT _id FROM " + dbTableLogs + ")", null); // Remove the obsolete "_others" directory where the user avatar used to be stored. - LocalStorage.deleteDirectory(LocalStorage.getStorageDir("_others")); + FileUtils.deleteDirectory(LocalStorage.getStorageDir("_others")); if (version > -1) { Settings.setVersion(version); @@ -2391,8 +2373,6 @@ public class DataStore { /** * remove all geocodes from the given list of geocodes where an offline log exists * - * @param geocodes - * @return */ @NonNull private static Set<String> exceptCachesWithOfflineLog(@NonNull final Set<String> geocodes) { @@ -2472,7 +2452,7 @@ public class DataStore { // Delete cache directories for (final String geocode : geocodes) { - LocalStorage.deleteDirectory(LocalStorage.getStorageDir(geocode)); + FileUtils.deleteDirectory(LocalStorage.getStorageDir(geocode)); } } } @@ -2739,7 +2719,6 @@ public class DataStore { /** * Remove a list. Caches in the list are moved to the standard list. * - * @param listId * @return true if the list got deleted, false else */ public static boolean removeList(final int listId) { @@ -2831,8 +2810,6 @@ public class DataStore { /** * Load the lazily initialized fields of a cache and return them as partial cache (all other fields unset). * - * @param geocode - * @return */ @NonNull public static Geocache loadCacheTexts(final String geocode) { @@ -2909,10 +2886,6 @@ public class DataStore { /** * Loads all Waypoints in the coordinate rectangle. * - * @param excludeDisabled - * @param excludeMine - * @param type - * @return */ @NonNull @@ -2951,7 +2924,7 @@ public class DataStore { private static enum PreparedStatement { - HISTORY_COUNT("select count(_id) from " + dbTableCaches + " where visiteddate > 0"), + HISTORY_COUNT("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE visiteddate > 0"), MOVE_TO_STANDARD_LIST("UPDATE " + dbTableCaches + " SET reason = " + StoredList.STANDARD_LIST_ID + " WHERE reason = ?"), MOVE_TO_LIST("UPDATE " + dbTableCaches + " SET reason = ? WHERE geocode = ?"), UPDATE_VISIT_DATE("UPDATE " + dbTableCaches + " SET visiteddate = ? WHERE geocode = ?"), @@ -2967,10 +2940,11 @@ public class DataStore { LIST_ID_OF_GUID("SELECT reason FROM " + dbTableCaches + " WHERE guid = ?"), GEOCODE_OF_GUID("SELECT geocode FROM " + dbTableCaches + " WHERE guid = ?"), INSERT_SEARCH_DESTINATION("INSERT INTO " + dbTableSearchDestinationHistory + " (date, latitude, longitude) VALUES (?, ?, ?)"), - COUNT_TYPE_ALL_LIST("select count(_id) from " + dbTableCaches + " where detailed = 1 and type = ? and reason > 0"), // See use of COUNT_TYPE_LIST for synchronization - COUNT_ALL_TYPES_ALL_LIST("select count(_id) from " + dbTableCaches + " where detailed = 1 and reason > 0"), // See use of COUNT_TYPE_LIST for synchronization - COUNT_TYPE_LIST("select count(_id) from " + dbTableCaches + " where detailed = 1 and type = ? and reason = ?"), - COUNT_ALL_TYPES_LIST("select count(_id) from " + dbTableCaches + " where detailed = 1 and reason = ?"); // See use of COUNT_TYPE_LIST for synchronization + COUNT_TYPE_ALL_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND type = ? AND reason > 0"), // See use of COUNT_TYPE_LIST for synchronization + COUNT_ALL_TYPES_ALL_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND reason > 0"), // See use of COUNT_TYPE_LIST for synchronization + COUNT_TYPE_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND type = ? AND reason = ?"), + COUNT_ALL_TYPES_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND reason = ?"), // See use of COUNT_TYPE_LIST for synchronization + CHECK_IF_PRESENT("SELECT COUNT(*) FROM " + dbTableCaches + " WHERE geocode = ?"); private static final List<PreparedStatement> statements = new ArrayList<>(); diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java index 8cb947a..ce279bf 100644 --- a/main/src/cgeo/geocaching/EditWaypointActivity.java +++ b/main/src/cgeo/geocaching/EditWaypointActivity.java @@ -331,7 +331,6 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C * @param type * type to create a new default name for * - * @return */ private String getDefaultWaypointName(final WaypointType type) { final ArrayList<String> wpNames = new ArrayList<>(); diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java index 8e9485e..e87495f 100644 --- a/main/src/cgeo/geocaching/Geocache.java +++ b/main/src/cgeo/geocaching/Geocache.java @@ -25,7 +25,7 @@ import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.network.HtmlImage; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.CancellableHandler; -import cgeo.geocaching.utils.DateUtils; +import cgeo.geocaching.utils.CalendarUtils; import cgeo.geocaching.utils.ImageUtils; import cgeo.geocaching.utils.LazyInitializedList; import cgeo.geocaching.utils.Log; @@ -85,6 +85,8 @@ public class Geocache implements IWaypoint { private long visitedDate = 0; private int listId = StoredList.TEMPORARY_LIST.id; private boolean detailed = false; + + @NonNull private String geocode = ""; private String cacheId = ""; private String guid = ""; @@ -484,6 +486,9 @@ public class Geocache implements IWaypoint { } public void openInBrowser(final Activity fromActivity) { + if (getUrl() == null) { + return; + } final Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getLongUrl())); // Check if cgeo is the default, show the chooser to let the user choose a browser @@ -696,11 +701,7 @@ public class Geocache implements IWaypoint { return getConnector() instanceof ISearchByCenter; } - public void shareCache(final Activity fromActivity, final Resources res) { - if (geocode == null) { - return; - } - + public void shareCache(@NonNull final Activity fromActivity, final Resources res) { final Intent intent = getShareIntent(); fromActivity.startActivity(Intent.createChooser(intent, res.getText(R.string.cache_menu_share))); @@ -717,22 +718,22 @@ public class Geocache implements IWaypoint { final Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_SUBJECT, subject.toString()); - intent.putExtra(Intent.EXTRA_TEXT, getUrl()); + intent.putExtra(Intent.EXTRA_TEXT, StringUtils.defaultString(getUrl())); return intent; } - @NonNull + @Nullable public String getUrl() { return getConnector().getCacheUrl(this); } - @NonNull + @Nullable public String getLongUrl() { return getConnector().getLongCacheUrl(this); } - @NonNull + @Nullable public String getCgeoUrl() { return getConnector().getCacheUrl(this); } @@ -1060,7 +1061,7 @@ public class Geocache implements IWaypoint { this.directionImg = directionImg; } - public void setGeocode(final String geocode) { + public void setGeocode(@NonNull final String geocode) { this.geocode = StringUtils.upperCase(geocode); } @@ -1631,10 +1632,9 @@ public class Geocache implements IWaypoint { * * @return start time in minutes after midnight */ - @Nullable - public String guessEventTimeMinutes() { + public int guessEventTimeMinutes() { if (!isEventCache()) { - return null; + return -1; } final String hourLocalized = CgeoApplication.getInstance().getString(R.string.cache_time_full_hours); @@ -1660,14 +1660,14 @@ public class Geocache implements IWaypoint { minutes = Integer.parseInt(matcher.group(2)); } if (hours >= 0 && hours < 24 && minutes >= 0 && minutes < 60) { - return String.valueOf(hours * 60 + minutes); + return hours * 60 + minutes; } } catch (final NumberFormatException ignored) { // cannot happen, but static code analysis doesn't know } } } - return null; + return -1; } public boolean hasStaticMap() { @@ -1771,9 +1771,9 @@ public class Geocache implements IWaypoint { public LogType getDefaultLogType() { if (isEventCache()) { final Date eventDate = getHiddenDate(); - final boolean expired = DateUtils.isPastEvent(this); + final boolean expired = CalendarUtils.isPastEvent(this); - if (hasOwnLog(LogType.WILL_ATTEND) || expired || (eventDate != null && DateUtils.daysSince(eventDate.getTime()) == 0)) { + if (hasOwnLog(LogType.WILL_ATTEND) || expired || (eventDate != null && CalendarUtils.daysSince(eventDate.getTime()) == 0)) { return hasOwnLog(LogType.ATTENDED) ? LogType.NOTE : LogType.ATTENDED; } return LogType.WILL_ATTEND; @@ -1805,4 +1805,12 @@ public class Geocache implements IWaypoint { return geocodes; } + /** + * Show the hint as toast message. If no hint is available, a default "no hint available" will be shown instead. + */ + public void showHintToast(final Activity activity) { + final String hint = getHint(); + ActivityMixin.showToast(activity, StringUtils.defaultIfBlank(hint, activity.getString(R.string.cache_hint_not_available))); + } + } diff --git a/main/src/cgeo/geocaching/Image.java b/main/src/cgeo/geocaching/Image.java index f592fc1..5c0e4f0 100644 --- a/main/src/cgeo/geocaching/Image.java +++ b/main/src/cgeo/geocaching/Image.java @@ -31,7 +31,7 @@ public class Image implements Parcelable { } public Image(final File file) { - this("file://" + file.getAbsolutePath(), file.getName(), null); + this(FileUtils.fileToUrl(file), file.getName(), null); } public Image(final Parcel in) { @@ -46,7 +46,7 @@ public class Image implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(final Parcel dest, final int flags) { dest.writeString(url); dest.writeString(title); dest.writeString(description); @@ -54,12 +54,12 @@ public class Image implements Parcelable { public static final Parcelable.Creator<Image> CREATOR = new Parcelable.Creator<Image>() { @Override - public Image createFromParcel(Parcel in) { + public Image createFromParcel(final Parcel in) { return new Image(in); } @Override - public Image[] newArray(int size) { + public Image[] newArray(final int size) { return new Image[size]; } }; diff --git a/main/src/cgeo/geocaching/ImageSelectActivity.java b/main/src/cgeo/geocaching/ImageSelectActivity.java index 26f105e..9d1c1e0 100644 --- a/main/src/cgeo/geocaching/ImageSelectActivity.java +++ b/main/src/cgeo/geocaching/ImageSelectActivity.java @@ -293,7 +293,6 @@ public class ImageSelectActivity extends AbstractActionBarActivity { /** * Scales and writes the scaled image. * - * @param filePath * @return the scaled image path, or <tt>null</tt> if the image cannot be decoded */ @Nullable diff --git a/main/src/cgeo/geocaching/ImagesActivity.java b/main/src/cgeo/geocaching/ImagesActivity.java index b75e5eb..975a720 100644 --- a/main/src/cgeo/geocaching/ImagesActivity.java +++ b/main/src/cgeo/geocaching/ImagesActivity.java @@ -6,6 +6,7 @@ import cgeo.geocaching.ui.ImagesList; import cgeo.geocaching.ui.ImagesList.ImageType; import org.apache.commons.collections4.CollectionUtils; + import rx.Subscription; import android.content.Context; @@ -28,7 +29,7 @@ public class ImagesActivity extends AbstractActionBarActivity { private Subscription subscription; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // get parameters @@ -78,11 +79,12 @@ public class ImagesActivity extends AbstractActionBarActivity { super.onStop(); } - public static void startActivityLogImages(final Context fromActivity, final String geocode, List<Image> logImages) { + public static void startActivityLogImages(final Context fromActivity, final String geocode, final List<Image> logImages) { startActivity(fromActivity, geocode, logImages, ImageType.LogImages); } - private static void startActivity(final Context fromActivity, final String geocode, List<Image> logImages, ImageType imageType) { + @SuppressWarnings("deprecation") + private static void startActivity(final Context fromActivity, final String geocode, final List<Image> logImages, final ImageType imageType) { final Intent logImgIntent = new Intent(fromActivity, ImagesActivity.class); // if resuming our app within this activity, finish it and return to the cache activity logImgIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) @@ -95,18 +97,18 @@ public class ImagesActivity extends AbstractActionBarActivity { fromActivity.startActivity(logImgIntent); } - public static void startActivitySpoilerImages(final Context fromActivity, String geocode, List<Image> spoilers) { + public static void startActivitySpoilerImages(final Context fromActivity, final String geocode, final List<Image> spoilers) { startActivity(fromActivity, geocode, spoilers, ImageType.SpoilerImages); } @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + public void onCreateContextMenu(final ContextMenu menu, final View v, final ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); imagesList.onCreateContextMenu(menu, v); } @Override - public boolean onContextItemSelected(MenuItem item) { + public boolean onContextItemSelected(final MenuItem item) { if (imagesList.onContextItemSelected(item)) { return true; } diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java index 1d31e27..2f50232 100644 --- a/main/src/cgeo/geocaching/LogCacheActivity.java +++ b/main/src/cgeo/geocaching/LogCacheActivity.java @@ -19,7 +19,7 @@ import cgeo.geocaching.twitter.Twitter; import cgeo.geocaching.ui.dialog.DateDialog; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.AsyncTaskWithProgress; -import cgeo.geocaching.utils.DateUtils; +import cgeo.geocaching.utils.CalendarUtils; import cgeo.geocaching.utils.Formatter; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; @@ -301,7 +301,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia rating = GCVote.NO_RATING; typeSelected = cache.getDefaultLogType(); // it this is an attended event log, use the event date by default instead of the current date - if (cache.isEventCache() && DateUtils.isPastEvent(cache) && typeSelected == LogType.ATTENDED) { + if (cache.isEventCache() && CalendarUtils.isPastEvent(cache) && typeSelected == LogType.ATTENDED) { date.setTime(cache.getHiddenDate()); } text = null; @@ -618,6 +618,10 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia Dialogs.message(this, R.string.log_post_not_possible); return; } + if (CalendarUtils.isFuture(date)) { + Dialogs.message(this, R.string.log_date_future_not_allowed); + return; + } if (typeSelected.mustConfirmLog()) { Dialogs.confirm(this, R.string.confirm_log_title, res.getString(R.string.confirm_log_message, typeSelected.getL10n()), new OnClickListener() { diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java index fc4a066..5f0b8c5 100644 --- a/main/src/cgeo/geocaching/LogTrackableActivity.java +++ b/main/src/cgeo/geocaching/LogTrackableActivity.java @@ -334,7 +334,6 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat * Adds the new log to the list of log entries for this trackable to be able to show it in the trackable activity. * * - * @param logText */ private void addLocalTrackableLog(final String logText) { final LogEntry logEntry = new LogEntry(date.getTimeInMillis(), typeSelected, logText); diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java index 64ed46e..5de1298 100644 --- a/main/src/cgeo/geocaching/SearchResult.java +++ b/main/src/cgeo/geocaching/SearchResult.java @@ -19,7 +19,6 @@ import rx.Observable; import rx.functions.Func0; import rx.functions.Func1; import rx.functions.Func2; -import rx.util.async.Async; import android.os.Parcel; import android.os.Parcelable; @@ -217,10 +216,6 @@ public class SearchResult implements Parcelable { } /** - * @param excludeDisabled - * @param excludeMine - * @param cacheType - * @return */ public SearchResult filterSearchResults(final boolean excludeDisabled, final boolean excludeMine, final CacheType cacheType) { @@ -319,12 +314,12 @@ public class SearchResult implements Parcelable { return Observable.from(connectors).flatMap(new Func1<C, Observable<SearchResult>>() { @Override public Observable<SearchResult> call(final C connector) { - return connector.isActive() ? Async.start(new Func0<SearchResult>() { + return connector.isActive() ? Observable.defer(new Func0<Observable<SearchResult>>() { @Override - public SearchResult call() { - return func.call(connector); + public Observable<SearchResult> call() { + return Observable.just(func.call(connector)); } - }, RxUtils.networkScheduler) : Observable.<SearchResult>empty(); + }).subscribeOn(RxUtils.networkScheduler) : Observable.<SearchResult>empty(); } }).reduce(new SearchResult(), new Func2<SearchResult, SearchResult, SearchResult>() { @Override diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 5184f71..8c399af 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -16,9 +16,7 @@ import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import rx.Observable; -import rx.functions.Action0; import rx.functions.Func0; -import rx.util.async.Async; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -86,9 +84,9 @@ public final class StaticMapsProvider { final int requestWidth = Math.min(width / scale, GOOGLE_MAPS_MAX_SIZE); final int requestHeight = (aspectRatio > 1) ? Math.round(requestWidth / aspectRatio) : requestWidth; final int requestZoom = Math.min((scale == 2) ? zoom + 1 : zoom, GOOGLE_MAX_ZOOM); - return checkDownloadPermission(Async.fromAction(new Action0() { + return checkDownloadPermission(Observable.defer(new Func0<Observable<String>>() { @Override - public void call() { + public Observable<String> call() { final Parameters params = new Parameters( "center", latlonMap, "zoom", String.valueOf(requestZoom), @@ -104,7 +102,7 @@ public final class StaticMapsProvider { if (httpResponse == null) { Log.e("StaticMapsProvider.downloadMap: httpResponse is null"); - return; + return Observable.just(prefix); } final int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode != 200) { @@ -112,7 +110,7 @@ public final class StaticMapsProvider { if (statusCode == 403) { last403 = System.currentTimeMillis(); } - return; + return Observable.just(prefix); } final File file = getMapFile(geocode, prefix, true); if (LocalStorage.saveEntityToFile(httpResponse, file)) { @@ -122,8 +120,9 @@ public final class StaticMapsProvider { FileUtils.deleteIgnoringFailure(file); } } + return Observable.just(prefix); } - }, prefix, RxUtils.networkScheduler)); + }).subscribeOn(RxUtils.networkScheduler)); } public static Observable<String> downloadMaps(final Geocache cache) { @@ -216,9 +215,8 @@ public final class StaticMapsProvider { 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"; - return 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, displaySize.x, displaySize.y, null); } private static Observable<String> downloadMaps(final String geocode, final String markerUrl, final String prefix, @@ -261,7 +259,6 @@ public final class StaticMapsProvider { /** * Check if at least one map file exists for the given cache. * - * @param cache * @return <code>true</code> if at least one map file exists; <code>false</code> otherwise */ public static boolean hasStaticMap(@NonNull final Geocache cache) { @@ -281,8 +278,6 @@ public final class StaticMapsProvider { /** * Checks if at least one map file exists for the given geocode and waypoint ID. * - * @param geocode - * @param waypoint * @return <code>true</code> if at least one map file exists; <code>false</code> otherwise */ public static boolean hasStaticMapForWaypoint(final String geocode, final Waypoint waypoint) { @@ -300,8 +295,6 @@ public final class StaticMapsProvider { /** * Checks if all map files exist for the given geocode and waypoint ID. * - * @param geocode - * @param waypoint * @return <code>true</code> if all map files exist; <code>false</code> otherwise */ public static boolean hasAllStaticMapsForWaypoint(final String geocode, final Waypoint waypoint) { diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java index 139b136..d921acb 100644 --- a/main/src/cgeo/geocaching/TrackableActivity.java +++ b/main/src/cgeo/geocaching/TrackableActivity.java @@ -127,7 +127,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi geocode = ConnectorFactory.getTrackableFromURL(uri.toString()); final String uriHost = uri.getHost().toLowerCase(Locale.US); - if (uriHost.contains("geocaching.com")) { + if (uriHost.endsWith("geocaching.com")) { geocode = uri.getQueryParameter("tracker"); guid = uri.getQueryParameter("guid"); id = uri.getQueryParameter("id"); @@ -149,17 +149,6 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi finish(); return; } - } else if (uriHost.contains("coord.info")) { - final String uriPath = uri.getPath().toLowerCase(Locale.US); - if (StringUtils.startsWith(uriPath, "/tb")) { - geocode = uriPath.substring(1).toUpperCase(Locale.US); - guid = null; - id = null; - } else { - showToast(res.getString(R.string.err_tb_details_open)); - finish(); - return; - } } } diff --git a/main/src/cgeo/geocaching/UsefulAppsActivity.java b/main/src/cgeo/geocaching/UsefulAppsActivity.java index dd92350..d4517dc 100644 --- a/main/src/cgeo/geocaching/UsefulAppsActivity.java +++ b/main/src/cgeo/geocaching/UsefulAppsActivity.java @@ -5,8 +5,10 @@ import butterknife.InjectView; import cgeo.geocaching.activity.AbstractActionBarActivity; import cgeo.geocaching.ui.AbstractViewHolder; +import cgeo.geocaching.utils.ProcessUtils; + +import org.eclipse.jdt.annotation.NonNull; -import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -36,27 +38,16 @@ public class UsefulAppsActivity extends AbstractActionBarActivity { private final int titleId; private final int descriptionId; private final int iconId; + @NonNull private final String packageName; - public HelperApp(final int title, final int description, final int icon, final String packageName) { + public HelperApp(final int title, final int description, final int icon, @NonNull final String packageName) { this.titleId = title; this.descriptionId = description; this.iconId = icon; this.packageName = packageName; } - private void installFromMarket(final Activity activity) { - try { - // allow also opening pure http URLs in addition to market packages - final String url = (packageName.startsWith("http:")) ? packageName : "market://details?id=" + packageName; - final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - activity.startActivity(marketIntent); - - } catch (final RuntimeException ignored) { - // market not available in standard emulator - } - } } private static final HelperApp[] HELPER_APPS = { @@ -106,7 +97,12 @@ public class UsefulAppsActivity extends AbstractActionBarActivity { @Override public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) { final HelperApp helperApp = HELPER_APPS[position]; - helperApp.installFromMarket(UsefulAppsActivity.this); + if (helperApp.packageName.startsWith("http")) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(helperApp.packageName))); + } + else { + ProcessUtils.openMarket(UsefulAppsActivity.this, helperApp.packageName); + } } }); } diff --git a/main/src/cgeo/geocaching/Waypoint.java b/main/src/cgeo/geocaching/Waypoint.java index 5cac4db..cc00b1c 100644 --- a/main/src/cgeo/geocaching/Waypoint.java +++ b/main/src/cgeo/geocaching/Waypoint.java @@ -37,8 +37,6 @@ public class Waypoint implements IWaypoint { /** * require name and type for every waypoint * - * @param name - * @param type */ public Waypoint(final String name, final WaypointType type, final boolean own) { this.name = name; @@ -49,7 +47,6 @@ public class Waypoint implements IWaypoint { /** * copy constructor * - * @param other */ public Waypoint(final Waypoint other) { merge(other); @@ -262,7 +259,6 @@ public class Waypoint implements IWaypoint { /** * Delegates the creation of the waypoint-id for gpx-export to the waypoint * - * @return */ public String getGpxId() { diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index 4cddfe6..7626ba8 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -212,6 +212,7 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs public interface ActivitySharingInterface { /** Return an URL that represent the current activity for sharing or null for no sharing. */ + @Nullable public String getAndroidBeamUri(); } diff --git a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java index 64186a0..11a5436 100644 --- a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java @@ -68,14 +68,12 @@ public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends /** * Returns a validated view. * - * @return */ public View getDispatchedView(final ViewGroup parentView); /** * Returns a (maybe cached) view. * - * @return */ public View getView(final ViewGroup parentView); diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java index 14a2fbf..e9d3249 100644 --- a/main/src/cgeo/geocaching/activity/ActivityMixin.java +++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java @@ -133,8 +133,6 @@ public final class ActivityMixin { /** * insert text into the EditText at the current cursor position * - * @param editText - * @param insertText * @param moveCursor * place the cursor after the inserted text */ @@ -163,8 +161,6 @@ public final class ActivityMixin { * was created from an intent by another app, and our own app is not yet running. The bug seems to be fixed in * Android 4.4.something, however. * - * @param activity - * @return */ public static boolean navigateUp(@NonNull final Activity activity) { // see http://developer.android.com/training/implementing-navigation/ancestral.html @@ -190,7 +186,7 @@ public final class ActivityMixin { } public static void presentShowcase(final IAbstractActivity activity) { - if (VERSION.SDK_INT < 11) { + if (VERSION.SDK_INT < 14) { return; } final ShowcaseViewBuilder builder = activity.getShowcase(); diff --git a/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java b/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java index 14f9281..86f5302 100644 --- a/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java +++ b/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java @@ -29,7 +29,6 @@ public class ShowcaseViewBuilder extends Builder { /** * Use the hash of the title for the single shot remembering * - * @param title */ private void setSingleshot(final CharSequence title) { super.singleShot(title.hashCode()); diff --git a/main/src/cgeo/geocaching/apps/AbstractApp.java b/main/src/cgeo/geocaching/apps/AbstractApp.java index 494e245..fa052f1 100644 --- a/main/src/cgeo/geocaching/apps/AbstractApp.java +++ b/main/src/cgeo/geocaching/apps/AbstractApp.java @@ -5,28 +5,31 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.utils.ProcessUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import android.content.Intent; public abstract class AbstractApp implements App { - private final String packageName; - private final String intent; + @Nullable private final String packageName; + @Nullable private final String intent; + @NonNull private final String name; /** * a unique id, defined in res/values/ids.xml */ private final int id; - protected AbstractApp(final String name, final int id, final String intent, - final String packageName) { + protected AbstractApp(@NonNull final String name, final int id, @Nullable final String intent, + @Nullable final String packageName) { this.name = name; this.id = id; this.intent = intent; this.packageName = packageName; } - protected AbstractApp(final String name, final int id, final String intent) { + protected AbstractApp(@NonNull final String name, final int id, @Nullable final String intent) { this(name, id, intent, null); } @@ -38,6 +41,7 @@ public abstract class AbstractApp implements App { return ProcessUtils.isIntentAvailable(intent); } + @Nullable protected Intent getLaunchIntent() { return ProcessUtils.getLaunchIntent(packageName); } @@ -48,6 +52,7 @@ public abstract class AbstractApp implements App { } @Override + @NonNull public String getName() { return name; } @@ -57,12 +62,12 @@ public abstract class AbstractApp implements App { return id; } - protected static String getString(int ressourceId) { + protected static String getString(final int ressourceId) { return CgeoApplication.getInstance().getString(ressourceId); } @Override - public boolean isEnabled(Geocache cache) { + public boolean isEnabled(final Geocache cache) { return cache != null; } } diff --git a/main/src/cgeo/geocaching/apps/AbstractAppFactory.java b/main/src/cgeo/geocaching/apps/AbstractAppFactory.java deleted file mode 100644 index 945f7d6..0000000 --- a/main/src/cgeo/geocaching/apps/AbstractAppFactory.java +++ /dev/null @@ -1,16 +0,0 @@ -package cgeo.geocaching.apps; - -import android.view.MenuItem; - -public abstract class AbstractAppFactory { - - protected static App getAppFromMenuItem(MenuItem item, final App[] availableApps) { - final int id = item.getItemId(); - for (App app : availableApps) { - if (app.getId() == id) { - return app; - } - } - return null; - } -} diff --git a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java index baf36a4..dfd148d 100644 --- a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java +++ b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java @@ -8,6 +8,7 @@ import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.utils.SynchronizedDateFormat; +import menion.android.locus.LocusDataStorageProvider; import menion.android.locus.addon.publiclib.DisplayData; import menion.android.locus.addon.publiclib.LocusUtils; import menion.android.locus.addon.publiclib.geoData.Point; @@ -15,6 +16,9 @@ import menion.android.locus.addon.publiclib.geoData.PointGeocachingData; import menion.android.locus.addon.publiclib.geoData.PointGeocachingDataWaypoint; import menion.android.locus.addon.publiclib.geoData.PointsData; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import android.app.Activity; import android.location.Location; @@ -31,7 +35,7 @@ import java.util.Locale; public abstract class AbstractLocusApp extends AbstractApp { private static final SynchronizedDateFormat ISO8601DATE = new SynchronizedDateFormat("yyyy-MM-dd'T'", Locale.US); - protected AbstractLocusApp(final String text, int id, final String intent) { + protected AbstractLocusApp(@NonNull final String text, final int id, @NonNull final String intent) { super(text, id, intent); } @@ -47,7 +51,6 @@ public abstract class AbstractLocusApp extends AbstractApp { * which caches/waypoints to show * @param withCacheWaypoints * Whether to give waypoints of caches to Locus or not - * @param activity */ protected static boolean showInLocus(final List<?> objectsToShow, final boolean withCacheWaypoints, final boolean export, final Activity activity) { @@ -57,7 +60,7 @@ public abstract class AbstractLocusApp extends AbstractApp { final boolean withCacheDetails = objectsToShow.size() < 200; final PointsData pd = new PointsData("c:geo"); - for (Object o : objectsToShow) { + for (final Object o : objectsToShow) { Point p = null; // get icon and Point if (o instanceof Geocache) { @@ -90,7 +93,6 @@ public abstract class AbstractLocusApp extends AbstractApp { /** * This method constructs a <code>Point</code> for displaying in Locus * - * @param cache * @param withWaypoints * whether to give waypoints to Locus or not * @param withCacheDetails @@ -98,7 +100,8 @@ public abstract class AbstractLocusApp extends AbstractApp { * should be false for all if more then 200 Caches are transferred * @return null, when the <code>Point</code> could not be constructed */ - private static Point getCachePoint(Geocache cache, boolean withWaypoints, boolean withCacheDetails) { + @Nullable + private static Point getCachePoint(final Geocache cache, final boolean withWaypoints, final boolean withCacheDetails) { if (cache == null || cache.getCoords() == null) { return null; } @@ -141,19 +144,24 @@ public abstract class AbstractLocusApp extends AbstractApp { if (withWaypoints && cache.hasWaypoints()) { pg.waypoints = new ArrayList<>(); - for (Waypoint waypoint : cache.getWaypoints()) { - if (waypoint == null || waypoint.getCoords() == null) { + for (final Waypoint waypoint : cache.getWaypoints()) { + if (waypoint == null) { continue; } - PointGeocachingDataWaypoint wp = new PointGeocachingDataWaypoint(); - wp.code = waypoint.getGeocode(); + + final PointGeocachingDataWaypoint wp = new PointGeocachingDataWaypoint(); + wp.code = waypoint.getLookup(); wp.name = waypoint.getName(); - String locusWpId = toLocusWaypoint(waypoint.getWaypointType()); + wp.description = waypoint.getNote(); + final String locusWpId = toLocusWaypoint(waypoint.getWaypointType()); if (locusWpId != null) { wp.type = locusWpId; } - wp.lat = waypoint.getCoords().getLatitude(); - wp.lon = waypoint.getCoords().getLongitude(); + + if (waypoint.getCoords() != null) { + wp.lat = waypoint.getCoords().getLatitude(); + wp.lon = waypoint.getCoords().getLongitude(); + } pg.waypoints.add(wp); } } @@ -174,10 +182,10 @@ public abstract class AbstractLocusApp extends AbstractApp { /** * This method constructs a <code>Point</code> for displaying in Locus * - * @param waypoint * @return null, when the <code>Point</code> could not be constructed */ - private static Point getWaypointPoint(Waypoint waypoint) { + @Nullable + private static Point getWaypointPoint(final Waypoint waypoint) { if (waypoint == null || waypoint.getCoords() == null) { return null; } @@ -248,6 +256,7 @@ public abstract class AbstractLocusApp extends AbstractApp { } } + @Nullable private static String toLocusWaypoint(final WaypointType wt) { switch (wt) { case FINAL: @@ -268,5 +277,4 @@ public abstract class AbstractLocusApp extends AbstractApp { return null; } } - } diff --git a/main/src/cgeo/geocaching/apps/App.java b/main/src/cgeo/geocaching/apps/App.java index 7e70581..1383809 100644 --- a/main/src/cgeo/geocaching/apps/App.java +++ b/main/src/cgeo/geocaching/apps/App.java @@ -2,6 +2,8 @@ package cgeo.geocaching.apps; import cgeo.geocaching.Geocache; +import org.eclipse.jdt.annotation.NonNull; + public interface App { public boolean isInstalled(); @@ -10,6 +12,7 @@ public interface App { */ public boolean isUsableAsDefaultNavigationApp(); + @NonNull public String getName(); /** @@ -20,8 +23,6 @@ public interface App { /** * Whether or not the app can be used with the given cache (may depend on properties of the cache). * - * @param cache - * @return */ boolean isEnabled(final Geocache cache); } diff --git a/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java b/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java deleted file mode 100644 index 03954f5..0000000 --- a/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java +++ /dev/null @@ -1,63 +0,0 @@ -package cgeo.geocaching.apps; - -import menion.android.locus.addon.publiclib.geoData.PointsData; -import menion.android.locus.addon.publiclib.utils.DataCursor; -import menion.android.locus.addon.publiclib.utils.DataStorage; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; -import android.os.Parcel; - -/** - * code provided by menion - developer of Locus - */ -public class LocusDataStorageProvider extends ContentProvider { - - @Override - public Cursor query(Uri aUri, String[] aProjection, String aSelection, - String[] aSelectionArgs, String aSortOrder) { - - final DataCursor cursor = new DataCursor(new String[] { "data" }); - - for (final PointsData item : DataStorage.getData()) { - final Parcel par = Parcel.obtain(); - item.writeToParcel(par, 0); - // add byte array to row - cursor.addRow(new Object[] { par.marshall() }); - par.recycle(); - } - // data filled to cursor, clear reference to prevent some memory issue - DataStorage.clearData(); - // now finally return filled cursor - return cursor; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - @Override - public String getType(Uri uri) { - return null; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - return null; - } - - @Override - public boolean onCreate() { - return false; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, - String[] selectionArgs) { - return 0; - } - -} diff --git a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java index c4f2723..4e542b8 100644 --- a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java +++ b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java @@ -4,17 +4,19 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.apps.AbstractApp; import cgeo.geocaching.apps.cache.navi.CacheNavigationApp; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.content.Intent; abstract class AbstractGeneralApp extends AbstractApp implements CacheNavigationApp { - protected AbstractGeneralApp(final String name, final int id, final String packageName) { + protected AbstractGeneralApp(@NonNull final String name, final int id, @NonNull final String packageName) { super(name, id, null, packageName); } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { final Intent intent = getLaunchIntent(); if (intent != null) { intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java index 5e7a5cc..0bf2c1c 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java @@ -7,6 +7,8 @@ import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.apps.AbstractApp; import cgeo.geocaching.location.Geopoint; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.content.Intent; @@ -15,20 +17,20 @@ import android.content.Intent; */ abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp, GeopointNavigationApp { - protected AbstractPointNavigationApp(final String name, final int id, final String intent) { + protected AbstractPointNavigationApp(@NonNull final String name, final int id, final String intent) { super(name, id, intent); } - protected AbstractPointNavigationApp(final String name, final int id, final String intent, final String packageName) { + protected AbstractPointNavigationApp(@NonNull final String name, final int id, final String intent, final String packageName) { super(name, id, intent, packageName); } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { navigateWithNullCheck(activity, cache.getCoords()); } - private void navigateWithNullCheck(Activity activity, final Geopoint coords) { + private void navigateWithNullCheck(final Activity activity, final Geopoint coords) { if (coords != null) { navigate(activity, coords); } else { @@ -37,17 +39,17 @@ abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNa } @Override - public void navigate(Activity activity, Waypoint waypoint) { + public void navigate(final Activity activity, final Waypoint waypoint) { navigateWithNullCheck(activity, waypoint.getCoords()); } @Override - public boolean isEnabled(Geocache cache) { + public boolean isEnabled(final Geocache cache) { return cache.getCoords() != null; } @Override - public boolean isEnabled(Waypoint waypoint) { + public boolean isEnabled(final Waypoint waypoint) { return waypoint.getCoords() != null; } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java index a2a5803..700c8aa 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java @@ -11,11 +11,12 @@ import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.apps.AbstractApp; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp { - protected AbstractStaticMapsApp(final String name, final int id) { + protected AbstractStaticMapsApp(@NonNull final String name, final int id) { super(name, id, null); } @@ -29,11 +30,11 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat return false; } - protected static boolean hasStaticMap(Waypoint waypoint) { + protected static boolean hasStaticMap(final Waypoint waypoint) { if (waypoint==null) { return false; } - String geocode = waypoint.getGeocode(); + final String geocode = waypoint.getGeocode(); if (StringUtils.isNotEmpty(geocode) && DataStore.isOffline(geocode, null)) { return StaticMapsProvider.hasStaticMapForWaypoint(geocode, waypoint); } @@ -49,7 +50,7 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat } final String geocode = StringUtils.upperCase(logable.getGeocode()); - StaticMapsActivity_.IntentBuilder_ builder = StaticMapsActivity_.intent(activity).geocode(geocode).download(download); + final StaticMapsActivity_.IntentBuilder_ builder = StaticMapsActivity_.intent(activity).geocode(geocode).download(download); if (waypoint != null) { builder.waypointId(waypoint.getId()); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java index d542541..32eba7e 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java @@ -5,7 +5,6 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.Waypoint; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.apps.AbstractAppFactory; import cgeo.geocaching.apps.App; import cgeo.geocaching.apps.cache.WhereYouGoApp; import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationBikeApp; @@ -25,7 +24,7 @@ import android.widget.ArrayAdapter; import java.util.ArrayList; import java.util.List; -public final class NavigationAppFactory extends AbstractAppFactory { +public final class NavigationAppFactory { private NavigationAppFactory() { // utility class @@ -117,10 +116,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { * Delegates to {@link #showNavigationMenu(Activity, cgeo.geocaching.Geocache, cgeo.geocaching.Waypoint, Geopoint, boolean, boolean)} with * <code>showInternalMap = true</code> and <code>showDefaultNavigation = false</code> * - * @param activity - * @param cache - * @param waypoint - * @param destination */ public static void showNavigationMenu(final Activity activity, final Geocache cache, final Waypoint waypoint, final Geopoint destination) { @@ -131,7 +126,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { * Specialized way to handle selection of navigation tool.<br /> * A dialog is created for tool selection and the selected tool is started afterwards. * - * @param activity * @param cache * may be <code>null</code> * @param waypoint @@ -196,7 +190,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Returns all installed navigation apps. * - * @return */ static List<NavigationAppsEnum> getInstalledNavigationApps() { final List<NavigationAppsEnum> installedNavigationApps = new ArrayList<>(); @@ -224,7 +217,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Returns all installed navigation apps for default navigation. * - * @return */ public static List<NavigationAppsEnum> getInstalledDefaultNavigationApps() { final List<NavigationAppsEnum> installedNavigationApps = new ArrayList<>(); @@ -240,10 +232,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { * Handles menu selections for menu entries created with * {@link #showNavigationMenu(Activity, Geocache, Waypoint, Geopoint)}. * - * @param item - * @param activity - * @param cache - * @return */ public static boolean onMenuItemSelected(final MenuItem item, final Activity activity, final Geocache cache) { final App menuItem = getAppFromMenuItem(item); @@ -286,10 +274,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Starts the default navigation tool if correctly set and installed or the compass app as default fallback. * - * @param defaultNavigation * - * @param activity - * @param cache */ public static void startDefaultNavigationApplication(final int defaultNavigation, final Activity activity, final Geocache cache) { if (cache == null || cache.getCoords() == null) { @@ -310,8 +295,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Starts the default navigation tool if correctly set and installed or the compass app as default fallback. * - * @param activity - * @param waypoint */ public static void startDefaultNavigationApplication(final int defaultNavigation, final Activity activity, final Waypoint waypoint) { if (waypoint == null || waypoint.getCoords() == null) { @@ -324,8 +307,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Starts the default navigation tool if correctly set and installed or the compass app as default fallback. * - * @param activity - * @param destination */ public static void startDefaultNavigationApplication(final int defaultNavigation, final Activity activity, final Geopoint destination) { if (destination == null) { diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java index 82883a2..43eaee3 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java @@ -3,6 +3,7 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.Geocache; import cgeo.geocaching.apps.App; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum; +import cgeo.geocaching.ui.AbstractMenuActionProvider; import android.app.Activity; import android.content.Context; @@ -12,11 +13,13 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MenuItem.OnMenuItemClickListener; import android.view.SubMenu; -import android.view.View; import java.util.List; -public class NavigationSelectionActionProvider extends ActionProvider { +/** + * Action provider listing all available navigation actions as sub menu. + */ +public class NavigationSelectionActionProvider extends AbstractMenuActionProvider { private Geocache geocache; private final Activity activity; @@ -26,17 +29,6 @@ public class NavigationSelectionActionProvider extends ActionProvider { activity = (Activity) context; } - @Override - public boolean hasSubMenu() { - return true; - } - - @Override - public View onCreateActionView() { - // must return null, otherwise the menu will not work - return null; - } - public void setTarget(final Geocache cache) { geocache = cache; } diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java index 40c4d92..8beb5e4 100644 --- a/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java +++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java @@ -8,7 +8,7 @@ import android.app.Activity; import java.util.List; -interface CacheListApp extends App { +public interface CacheListApp extends App { boolean invoke(final List<Geocache> caches, final Activity activity, final SearchResult search); diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java deleted file mode 100644 index b6706a0..0000000 --- a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java +++ /dev/null @@ -1,89 +0,0 @@ -package cgeo.geocaching.apps.cachelist; - -import cgeo.geocaching.Geocache; -import cgeo.geocaching.R; -import cgeo.geocaching.SearchResult; -import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.apps.AbstractAppFactory; -import cgeo.geocaching.utils.Log; - -import android.app.Activity; -import android.content.res.Resources; -import android.view.Menu; -import android.view.MenuItem; -import android.view.SubMenu; - -import java.util.ArrayList; -import java.util.List; - -public final class CacheListAppFactory extends AbstractAppFactory { - - private CacheListAppFactory() { - // utility class - } - - private static class LazyHolder { - public static final CacheListApp[] apps = { - new InternalCacheListMap(), - new LocusShowCacheListApp(), - new LocusExportCacheListApp(), - new MapsWithMeCacheListApp() - }; - } - - /** - * @param menu - * @param activity - * @param res - */ - public static void addMenuItems(final Menu menu, final Activity activity, final Resources res) { - final List<CacheListApp> activeApps = getActiveApps(); - if (activeApps.isEmpty()) { - return; - } - if (activeApps.size() == 1) { - final MenuItem subItem = menu.findItem(R.id.menu_cache_list_app); - subItem.setVisible(true); - subItem.setTitle(activeApps.get(0).getName()); - } else { - final MenuItem subItem = menu.findItem(R.id.submenu_cache_list_app); - subItem.setVisible(true); - final SubMenu subMenu = subItem.getSubMenu(); - for (final CacheListApp app : activeApps) { - subMenu.add(0, app.getId(), 0, app.getName()); - } - } - } - - private static List<CacheListApp> getActiveApps() { - final List<CacheListApp> activeApps = new ArrayList<>(LazyHolder.apps.length); - for (final CacheListApp app : LazyHolder.apps) { - if (app.isInstalled()) { - activeApps.add(app); - } - } - return activeApps; - } - - public static boolean onMenuItemSelected(final MenuItem item, final List<Geocache> caches, final Activity activity, - final SearchResult search) { - CacheListApp app; - if (item.getItemId() == R.id.menu_cache_list_app) { - app = getActiveApps().get(0); - } - else { - app = (CacheListApp) getAppFromMenuItem(item, LazyHolder.apps); - } - if (app != null) { - try { - final boolean result = app.invoke(caches, activity, search); - ActivityMixin.invalidateOptionsMenu(activity); - return result; - } catch (final Exception e) { - Log.e("CacheListAppFactory.onMenuItemSelected", e); - } - } - return false; - } - -} diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListApps.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListApps.java new file mode 100644 index 0000000..e8e81a8 --- /dev/null +++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListApps.java @@ -0,0 +1,29 @@ +package cgeo.geocaching.apps.cachelist; + +import java.util.ArrayList; +import java.util.List; + +public enum CacheListApps { + INTERNAL(new InternalCacheListMap()), + LOCUS_SHOW(new LocusShowCacheListApp()), + LOCUS_EXPORT(new LocusExportCacheListApp()), + MAPS_ME(new MapsWithMeCacheListApp()); + + private final CacheListApp app; + + private CacheListApps(final CacheListApp app) { + this.app = app; + } + + public static List<CacheListApp> getActiveApps() { + final List<CacheListApp> activeApps = new ArrayList<>(); + for (final CacheListApps appEnum : values()) { + if (appEnum.app.isInstalled()) { + activeApps.add(appEnum.app); + } + } + return activeApps; + } + +} + diff --git a/main/src/cgeo/geocaching/apps/cachelist/ListNavigationSelectionActionProvider.java b/main/src/cgeo/geocaching/apps/cachelist/ListNavigationSelectionActionProvider.java new file mode 100644 index 0000000..6a49995 --- /dev/null +++ b/main/src/cgeo/geocaching/apps/cachelist/ListNavigationSelectionActionProvider.java @@ -0,0 +1,60 @@ +package cgeo.geocaching.apps.cachelist; + +import cgeo.geocaching.ui.AbstractMenuActionProvider; + +import android.content.Context; +import android.support.v4.view.ActionProvider; +import android.support.v4.view.MenuItemCompat; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.SubMenu; + +import java.util.List; + +public class ListNavigationSelectionActionProvider extends AbstractMenuActionProvider { + + public static interface Callback { + void onListNavigationSelected(final CacheListApp app); + } + + private Callback callback; + + public ListNavigationSelectionActionProvider(final Context context) { + super(context); + } + + public void setCallback(final Callback callback) { + this.callback = callback; + } + + @Override + public void onPrepareSubMenu(final SubMenu subMenu) { + subMenu.clear(); + if (callback == null) { + return; + } + final List<CacheListApp> activeApps = CacheListApps.getActiveApps(); + for (int i = 0; i < activeApps.size(); i++) { + final CacheListApp app = activeApps.get(i); + subMenu.add(Menu.NONE, i, Menu.NONE, app.getName()).setOnMenuItemClickListener(new OnMenuItemClickListener() { + + @Override + public boolean onMenuItemClick(final MenuItem item) { + final CacheListApp app = activeApps.get(item.getItemId()); + callback.onListNavigationSelected(app); + return true; + } + }); + } + } + + public static void initialize(final MenuItem menuItem, final Callback callback) { + final ActionProvider actionProvider = MenuItemCompat.getActionProvider(menuItem); + if (actionProvider instanceof ListNavigationSelectionActionProvider) { + final ListNavigationSelectionActionProvider navigateAction = (ListNavigationSelectionActionProvider) actionProvider; + navigateAction.setCallback(callback); + } + } + +} diff --git a/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java index c6c7709..ed64d2d 100644 --- a/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java +++ b/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java @@ -45,7 +45,6 @@ public class MapsWithMeCacheListApp extends AbstractApp implements CacheListApp /** * get cache code from a PendingIntent after an invocation of MapsWithMe * - * @return */ @Nullable public static String getCacheFromMapsWithMe(final Context context, final Intent intent) { diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java new file mode 100644 index 0000000..8398eb3 --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java @@ -0,0 +1,15 @@ +package cgeo.geocaching.compatibility; + +import android.annotation.TargetApi; +import android.os.Build; +import android.widget.TextView; + +@TargetApi(Build.VERSION_CODES.HONEYCOMB) +public class AndroidLevel11 implements AndroidLevel11Interface { + + @Override + public void setTextIsSelectable(final TextView textView, final boolean selectable) { + textView.setTextIsSelectable(selectable); + } + +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java new file mode 100644 index 0000000..b4111ab --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java @@ -0,0 +1,12 @@ +package cgeo.geocaching.compatibility; + +import android.widget.TextView; + +public class AndroidLevel11Emulation implements AndroidLevel11Interface { + + @Override + public void setTextIsSelectable(final TextView textView, final boolean selectable) { + // do nothing + } + +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java new file mode 100644 index 0000000..45c06a4 --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java @@ -0,0 +1,9 @@ +package cgeo.geocaching.compatibility; + +import android.widget.TextView; + +public interface AndroidLevel11Interface { + + void setTextIsSelectable(TextView textView, boolean selectable); + +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java index 946d20e..f599611 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java @@ -11,11 +11,6 @@ import android.view.WindowManager; class AndroidLevel13 implements AndroidLevel13Interface { @Override - public int getDisplayWidth() { - return getDisplaySize().x; - } - - @Override public Point getDisplaySize() { final Point dimensions = new Point(); ((WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE)) diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java index 8e2e7ec..f9fd3bc 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java @@ -11,11 +11,6 @@ import android.view.WindowManager; class AndroidLevel13Emulation implements AndroidLevel13Interface { @Override - public int getDisplayWidth() { - return getDisplay().getWidth(); - } - - @Override public Point getDisplaySize() { final Display display = getDisplay(); return new Point(display.getWidth(), display.getHeight()); diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java index 6d3f3c3..b78875f 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java @@ -3,7 +3,6 @@ package cgeo.geocaching.compatibility; import android.graphics.Point; interface AndroidLevel13Interface { - int getDisplayWidth(); Point getDisplaySize(); } diff --git a/main/src/cgeo/geocaching/compatibility/Compatibility.java b/main/src/cgeo/geocaching/compatibility/Compatibility.java index 54e2966..56e18bf 100644 --- a/main/src/cgeo/geocaching/compatibility/Compatibility.java +++ b/main/src/cgeo/geocaching/compatibility/Compatibility.java @@ -5,15 +5,18 @@ import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; import android.graphics.Point; import android.os.Build; +import android.widget.TextView; public final class Compatibility { private static final int SDK_VERSION = Build.VERSION.SDK_INT; + private static final AndroidLevel11Interface LEVEL_11; private static final AndroidLevel13Interface LEVEL_13; private static final AndroidLevel19Interface LEVEL_19; static { + LEVEL_11 = SDK_VERSION >= 11 ? new AndroidLevel11() : new AndroidLevel11Emulation(); LEVEL_13 = SDK_VERSION >= 13 ? new AndroidLevel13() : new AndroidLevel13Emulation(); LEVEL_19 = SDK_VERSION >= 19 ? new AndroidLevel19() : new AndroidLevel19Emulation(); } @@ -22,19 +25,19 @@ public final class Compatibility { // utility class } - public static int getDisplayWidth() { - return LEVEL_13.getDisplayWidth(); - } - public static Point getDisplaySize() { return LEVEL_13.getDisplaySize(); } - public static void importGpxFromStorageAccessFramework(final @NonNull Activity activity, int requestCodeImportGpx) { + public static void importGpxFromStorageAccessFramework(final @NonNull Activity activity, final int requestCodeImportGpx) { LEVEL_19.importGpxFromStorageAccessFramework(activity, requestCodeImportGpx); } public static boolean isStorageAccessFrameworkAvailable() { return SDK_VERSION >= 19; } + + public static void setTextIsSelectable(final TextView textView, final boolean selectable) { + LEVEL_11.setTextIsSelectable(textView, selectable); + } } diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java index 4984273..0583aa1 100644 --- a/main/src/cgeo/geocaching/connector/AbstractConnector.java +++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java @@ -19,6 +19,7 @@ import cgeo.geocaching.location.Geopoint; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import rx.functions.Action1; @@ -129,7 +130,8 @@ public abstract class AbstractConnector implements IConnector { } @Override - public String getGeocodeFromUrl(final String url) { + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { final String urlPrefix = getCacheUrlPrefix(); if (StringUtils.isEmpty(urlPrefix) || StringUtils.startsWith(url, urlPrefix)) { @NonNull final String geocode = url.substring(urlPrefix.length()); @@ -144,7 +146,7 @@ public abstract class AbstractConnector implements IConnector { abstract protected String getCacheUrlPrefix(); @Override - @NonNull + @Nullable public String getLongCacheUrl(final @NonNull Geocache cache) { return getCacheUrl(cache); } @@ -201,7 +203,7 @@ public abstract class AbstractConnector implements IConnector { } @Override - public String getWaypointGpxId(final String prefix, final String geocode) { + public String getWaypointGpxId(final String prefix, @NonNull final String geocode) { // Default: just return the prefix return prefix; } diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java index b78b009..918911a 100644 --- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java +++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java @@ -15,9 +15,11 @@ import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.MapTokens; import cgeo.geocaching.connector.oc.OCApiConnector.ApiSupport; import cgeo.geocaching.connector.oc.OCApiLiveConnector; +import cgeo.geocaching.connector.oc.OCCZConnector; import cgeo.geocaching.connector.oc.OCConnector; import cgeo.geocaching.connector.ox.OXConnector; import cgeo.geocaching.connector.trackable.GeokretyConnector; +import cgeo.geocaching.connector.trackable.SwaggieConnector; import cgeo.geocaching.connector.trackable.TrackableConnector; import cgeo.geocaching.connector.trackable.TravelBugConnector; import cgeo.geocaching.connector.trackable.UnknownTrackableConnector; @@ -43,7 +45,7 @@ public final class ConnectorFactory { new OCApiLiveConnector("opencaching.de", "www.opencaching.de", "OC", "CC BY-NC-ND, alle Logeinträge © jeweiliger Autor", R.string.oc_de_okapi_consumer_key, R.string.oc_de_okapi_consumer_secret, R.string.pref_connectorOCActive, R.string.pref_ocde_tokenpublic, R.string.pref_ocde_tokensecret, ApiSupport.current), - new OCConnector("OpenCaching.CZ", "www.opencaching.cz", "OZ"), + new OCCZConnector(), new OCApiLiveConnector("opencaching.org.uk", "www.opencaching.org.uk", "OK", "CC BY-NC-SA 2.5", R.string.oc_uk_okapi_consumer_key, R.string.oc_uk_okapi_consumer_secret, R.string.pref_connectorOCUKActive, R.string.pref_ocuk_tokenpublic, R.string.pref_ocuk_tokensecret, ApiSupport.oldapi), @@ -74,8 +76,9 @@ public final class ConnectorFactory { @NonNull private static final Collection<TrackableConnector> TRACKABLE_CONNECTORS = Collections.unmodifiableCollection(Arrays.asList(new TrackableConnector[] { - new GeokretyConnector(), // GK must be first, as it overlaps with the secret codes of travel bugs - TravelBugConnector.getInstance(), + new GeokretyConnector(), + new SwaggieConnector(), + TravelBugConnector.getInstance(), // travel bugs last, as their secret codes overlap with other connectors UNKNOWN_TRACKABLE_CONNECTOR // must be last })); @@ -212,9 +215,12 @@ public final class ConnectorFactory { } @Nullable - public static String getGeocodeFromURL(final String url) { + public static String getGeocodeFromURL(@Nullable final String url) { + if (url == null) { + return null; + } for (final IConnector connector : CONNECTORS) { - final String geocode = connector.getGeocodeFromUrl(url); + @Nullable final String geocode = connector.getGeocodeFromUrl(url); if (StringUtils.isNotBlank(geocode)) { return geocode; } @@ -230,7 +236,6 @@ public final class ConnectorFactory { /** * Get the geocode of a trackable from a URL. * - * @param url * @return {@code null} if the URL cannot be decoded */ @Nullable diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java index 0863723..74b1028 100644 --- a/main/src/cgeo/geocaching/connector/IConnector.java +++ b/main/src/cgeo/geocaching/connector/IConnector.java @@ -6,6 +6,7 @@ import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.location.Geopoint; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.util.Collection; import java.util.List; @@ -14,7 +15,6 @@ public interface IConnector { /** * get name for display (currently only used in links) * - * @return */ @NonNull public String getName(); @@ -31,32 +31,26 @@ public interface IConnector { /** * Get the browser URL for the given cache. * - * @param cache - * @return */ - @NonNull + @Nullable public String getCacheUrl(final @NonNull Geocache cache); /** * get long browser URL for the given cache * - * @param cache - * @return */ - @NonNull + @Nullable public String getLongCacheUrl(final @NonNull Geocache cache); /** * enable/disable watchlist controls in cache details * - * @return */ public boolean supportsWatchList(); /** * Add the cache to the watchlist * - * @param cache * @return True - success/False - failure */ public boolean addToWatchlist(@NonNull Geocache cache); @@ -64,7 +58,6 @@ public interface IConnector { /** * Remove the cache from the watchlist * - * @param cache * @return True - success/False - failure */ public boolean removeFromWatchlist(@NonNull Geocache cache); @@ -72,28 +65,24 @@ public interface IConnector { /** * enable/disable favorite points controls in cache details * - * @return */ public boolean supportsFavoritePoints(@NonNull final Geocache cache); /** * enable/disable logging controls in cache details * - * @return */ public boolean supportsLogging(); /** * enable/disable attaching image to log * - * @return */ public boolean supportsLogImages(); /** * Get an ILoggingManager to guide the logging process. * - * @return */ @NonNull public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache); @@ -101,7 +90,6 @@ public interface IConnector { /** * Get host name of the connector server for dynamic loading of data. * - * @return */ @NonNull public String getHost(); @@ -109,8 +97,6 @@ public interface IConnector { /** * Get cache data license text. This is displayed somewhere near the cache details. * - * @param cache - * @return */ @NonNull public String getLicenseText(final @NonNull Geocache cache); @@ -118,8 +104,6 @@ public interface IConnector { /** * return true if this is a ZIP file containing a GPX file * - * @param fileName - * @return */ public boolean isZippedGPXFile(@NonNull final String fileName); @@ -128,17 +112,15 @@ public interface IConnector { * * @param cacheHasReliableLatLon * flag of the cache - * @return */ public boolean isReliableLatLon(boolean cacheHasReliableLatLon); /** * extract a geocode from the given URL, if this connector can handle that URL somehow * - * @param url - * @return */ - public String getGeocodeFromUrl(final String url); + @Nullable + public String getGeocodeFromUrl(@NonNull final String url); /** * enable/disable uploading personal note @@ -150,7 +132,6 @@ public interface IConnector { /** * Uploading personal note to website * - * @param cache * @return success */ public boolean uploadPersonalNote(@NonNull Geocache cache); @@ -165,7 +146,6 @@ public interface IConnector { /** * Resetting of modified coordinates on website to details * - * @param cache * @return success */ public boolean deleteModifiedCoordinates(@NonNull Geocache cache); @@ -173,8 +153,6 @@ public interface IConnector { /** * Uploading modified coordinates to website * - * @param cache - * @param wpt * @return success */ public boolean uploadModifiedCoordinates(@NonNull Geocache cache, @NonNull Geopoint wpt); @@ -183,7 +161,6 @@ public interface IConnector { * Return {@code true} if this connector is active for online interaction (download details, do searches, ...). If * this is {@code false}, the connector will still be used for already stored offline caches. * - * @return */ public boolean isActive(); @@ -200,8 +177,6 @@ public interface IConnector { * Check if the cache information is complete enough to be * able to log online. * - * @param geocache - * @return */ public boolean canLog(@NonNull Geocache geocache); @@ -218,8 +193,6 @@ public interface IConnector { * Get the list of <b>potentially</b> possible log types for a cache. Those may still be filtered further during the * actual logging activity. * - * @param geocache - * @return */ @NonNull public List<LogType> getPossibleLogTypes(@NonNull Geocache geocache); @@ -228,16 +201,12 @@ public interface IConnector { * Get the GPX id for a waypoint when exporting. For some connectors there is an inherent name logic, * for others its just the 'prefix'. * - * @param prefix - * @return */ - public String getWaypointGpxId(String prefix, String geocode); + public String getWaypointGpxId(String prefix, @NonNull String geocode); /** * Get the 'prefix' (key) for a waypoint from the 'name' in the GPX file * - * @param name - * @return */ @NonNull public String getWaypointPrefix(String name); @@ -245,14 +214,12 @@ public interface IConnector { /** * Get the maximum value for Terrain * - * @return */ public int getMaxTerrain(); /** * Get a user readable collection of all online features of this connector. * - * @return */ @NonNull public Collection<String> getCapabilities(); diff --git a/main/src/cgeo/geocaching/connector/ILoggingManager.java b/main/src/cgeo/geocaching/connector/ILoggingManager.java index 40a5377..2b0a067 100644 --- a/main/src/cgeo/geocaching/connector/ILoggingManager.java +++ b/main/src/cgeo/geocaching/connector/ILoggingManager.java @@ -16,13 +16,8 @@ public interface ILoggingManager { /** * Post a log for a cache online * - * @param logType - * @param date - * @param log * @param logPassword * optional, maybe null - * @param trackableLogs - * @return */ @NonNull LogResult postLog(@NonNull LogType logType, diff --git a/main/src/cgeo/geocaching/connector/UnknownConnector.java b/main/src/cgeo/geocaching/connector/UnknownConnector.java index fcf1152..cabf03e 100644 --- a/main/src/cgeo/geocaching/connector/UnknownConnector.java +++ b/main/src/cgeo/geocaching/connector/UnknownConnector.java @@ -4,6 +4,7 @@ import cgeo.geocaching.Geocache; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; class UnknownConnector extends AbstractConnector { @@ -14,9 +15,9 @@ class UnknownConnector extends AbstractConnector { } @Override - @NonNull + @Nullable public String getCacheUrl(@NonNull final Geocache cache) { - return StringUtils.EMPTY; + return null; } @Override @@ -42,7 +43,8 @@ class UnknownConnector extends AbstractConnector { } @Override - public String getGeocodeFromUrl(final String url) { + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { return null; } diff --git a/main/src/cgeo/geocaching/connector/WaymarkingConnector.java b/main/src/cgeo/geocaching/connector/WaymarkingConnector.java index 5a6f362..3361341 100644 --- a/main/src/cgeo/geocaching/connector/WaymarkingConnector.java +++ b/main/src/cgeo/geocaching/connector/WaymarkingConnector.java @@ -4,6 +4,7 @@ import cgeo.geocaching.Geocache; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; class WaymarkingConnector extends AbstractConnector { @@ -41,4 +42,20 @@ class WaymarkingConnector extends AbstractConnector { public boolean canHandle(@NonNull final String geocode) { return StringUtils.startsWith(geocode, "WM"); } + + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + // coord.info URLs + String code = StringUtils.substringAfterLast(url, "coord.info/"); + if (code != null && canHandle(code)) { + return code; + } + // waymarking URLs http://www.waymarking.com/waymarks/WMNCDT_American_Legion_Flagpole_1983_University_of_Oregon + code = StringUtils.substringBetween(url, "waymarks/", "_"); + if (code != null && canHandle(code)) { + return code; + } + return null; + } } diff --git a/main/src/cgeo/geocaching/connector/capability/ILogin.java b/main/src/cgeo/geocaching/connector/capability/ILogin.java index 003ccf4..437eec8 100644 --- a/main/src/cgeo/geocaching/connector/capability/ILogin.java +++ b/main/src/cgeo/geocaching/connector/capability/ILogin.java @@ -27,14 +27,12 @@ public interface ILogin extends IConnector { /** * Returns the status of the last {@link #login(Handler, Context)} request. * - * @return */ boolean isLoggedIn(); /** * User-centered string describing the current login/connection status * - * @return */ String getLoginStatusString(); @@ -42,7 +40,6 @@ public interface ILogin extends IConnector { * Name the user has in this connector or empty string if not applicable. * It might be necessary to execute {@link #login(Handler, Context)} before this information is valid. * - * @return */ String getUserName(); @@ -51,7 +48,6 @@ public interface ILogin extends IConnector { * Normally retrieved/updated with {@link #login(Handler, Context)}. * Might be stale as changes on the connectors site are generally not notified. * - * @return */ int getCachesFound(); diff --git a/main/src/cgeo/geocaching/connector/ec/ECConnector.java b/main/src/cgeo/geocaching/connector/ec/ECConnector.java index 15c2dc2..68dbee7 100644 --- a/main/src/cgeo/geocaching/connector/ec/ECConnector.java +++ b/main/src/cgeo/geocaching/connector/ec/ECConnector.java @@ -234,4 +234,14 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode, return R.string.pref_ecpassword; } + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + final String geocode = "EC" + StringUtils.substringAfter(url, "extremcaching.com/index.php/output-2/"); + if (canHandle(geocode)) { + return geocode; + } + return super.getGeocodeFromUrl(url); + } + } diff --git a/main/src/cgeo/geocaching/connector/ec/ECLogin.java b/main/src/cgeo/geocaching/connector/ec/ECLogin.java index 3ae8298..94b450b 100644 --- a/main/src/cgeo/geocaching/connector/ec/ECLogin.java +++ b/main/src/cgeo/geocaching/connector/ec/ECLogin.java @@ -88,7 +88,6 @@ public class ECLogin extends AbstractLogin { /** * Check if the user has been logged in when he retrieved the data. * - * @param data * @return <code>true</code> if user is logged in, <code>false</code> otherwise */ private boolean getLoginStatus(@Nullable final String data) { diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java index e43b9b5..3ad8117 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java @@ -305,7 +305,8 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public String getGeocodeFromUrl(final String url) { + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { // coord.info URLs String code = StringUtils.substringAfterLast(url, "coord.info/"); if (code != null && canHandle(code)) { @@ -375,7 +376,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public String getWaypointGpxId(final String prefix, final String geocode) { + public String getWaypointGpxId(final String prefix, @NonNull final String geocode) { String gpxId = prefix; if (StringUtils.isNotBlank(geocode) && geocode.length() > 2) { gpxId += geocode.substring(2); diff --git a/main/src/cgeo/geocaching/connector/gc/GCLogin.java b/main/src/cgeo/geocaching/connector/gc/GCLogin.java index 035176b..71c31c1 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCLogin.java +++ b/main/src/cgeo/geocaching/connector/gc/GCLogin.java @@ -166,7 +166,6 @@ public class GCLogin extends AbstractLogin { /** * Check if the user has been logged in when he retrieved the data. * - * @param page * @return <code>true</code> if user is logged in, <code>false</code> otherwise */ boolean getLoginStatus(@Nullable final String page) { @@ -412,8 +411,6 @@ public class GCLogin extends AbstractLogin { /** * POST HTTP request. Do the request a second time if the user is not logged in * - * @param uri - * @return */ String postRequestLogged(final String uri, final Parameters params) { final String data = Network.getResponseData(Network.postRequest(uri, params)); @@ -433,9 +430,6 @@ public class GCLogin extends AbstractLogin { /** * GET HTTP request. Do the request a second time if the user is not logged in * - * @param uri - * @param params - * @return */ @Nullable String getRequestLogged(@NonNull final String uri, @Nullable final Parameters params) { @@ -459,8 +453,6 @@ public class GCLogin extends AbstractLogin { * Unfortunately the cache details page contains user generated whitespace in the personal note, therefore we cannot * remove the white space from cache details pages. * - * @param uri - * @return */ private static boolean canRemoveWhitespace(final String uri) { return !StringUtils.contains(uri, "cache_details"); diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java index 1571faa..243d84c 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCMap.java +++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java @@ -11,8 +11,8 @@ import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.location.GeopointFormatter.Format; import cgeo.geocaching.location.Units; import cgeo.geocaching.location.Viewport; -import cgeo.geocaching.maps.LiveMapStrategy.Strategy; -import cgeo.geocaching.maps.LiveMapStrategy.StrategyFlag; +import cgeo.geocaching.maps.LivemapStrategy; +import cgeo.geocaching.maps.LivemapStrategy.Flag; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; @@ -110,7 +110,7 @@ public class GCMap { * Retrieved data. * @return SearchResult. Never null. */ - public static SearchResult parseMapJSON(final String data, final Tile tile, final Bitmap bitmap, final Strategy strategy) { + public static SearchResult parseMapJSON(final String data, final Tile tile, final Bitmap bitmap, final LivemapStrategy strategy) { final SearchResult searchResult = new SearchResult(); try { @@ -185,7 +185,7 @@ public class GCMap { cache.setGeocode(id); cache.setName(nameCache.get(id)); cache.setCoords(tile.getCoord(xy), tile.getZoomLevel()); - if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && bitmap != null) { + if (strategy.flags.contains(LivemapStrategy.Flag.PARSE_TILES) && bitmap != null) { for (final UTFGridPosition singlePos : singlePositions.get(id)) { if (IconDecoder.parseMapPNG(cache, bitmap, singlePos, tile.getZoomLevel())) { break; // cache parsed @@ -226,14 +226,13 @@ public class GCMap { * Area to search * @param tokens * Live map tokens - * @return */ @NonNull public static SearchResult searchByViewport(final Viewport viewport, final MapTokens tokens) { final int speed = (int) Sensors.getInstance().currentGeo().getSpeed() * 60 * 60 / 1000; // in km/h - Strategy strategy = Settings.getLiveMapStrategy(); - if (strategy == Strategy.AUTO) { - strategy = speed >= 30 ? Strategy.FAST : Strategy.DETAILED; + LivemapStrategy strategy = Settings.getLiveMapStrategy(); + if (strategy == LivemapStrategy.AUTO) { + strategy = speed >= 30 ? LivemapStrategy.FAST : LivemapStrategy.DETAILED; } final SearchResult result = searchByViewport(viewport, tokens, strategy); @@ -257,10 +256,9 @@ public class GCMap { * Live map tokens * @param strategy * Strategy for data retrieval and parsing, @see Strategy - * @return */ @NonNull - private static SearchResult searchByViewport(final Viewport viewport, final MapTokens tokens, final Strategy strategy) { + private static SearchResult searchByViewport(final Viewport viewport, final MapTokens tokens, final LivemapStrategy strategy) { Log.d("GCMap.searchByViewport" + viewport.toString()); final SearchResult searchResult = new SearchResult(); @@ -269,7 +267,7 @@ public class GCMap { searchResult.setUrl(viewport.getCenter().format(Format.LAT_LON_DECMINUTE)); } - if (strategy.flags.contains(StrategyFlag.LOAD_TILES)) { + if (strategy.flags.contains(LivemapStrategy.Flag.LOAD_TILES)) { final Set<Tile> tiles = Tile.getTilesForViewport(viewport); if (Settings.isDebug()) { @@ -339,7 +337,7 @@ public class GCMap { } } - if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY) && Settings.isGCPremiumMember()) { + if (strategy.flags.contains(Flag.SEARCH_NEARBY) && Settings.isGCPremiumMember()) { final Geopoint center = viewport.getCenter(); if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) { //FIXME We don't have a RecaptchaReceiver!? @@ -360,7 +358,6 @@ public class GCMap { * * @param typeToDisplay * - cache type to omit from exclusion list so it gets displayed - * @return * * cache types for live map filter: * 2 = traditional, 9 = ape, 5 = letterbox diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index f20df8d..4a8451b 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -57,7 +57,6 @@ import rx.functions.Action1; import rx.functions.Func0; import rx.functions.Func2; import rx.schedulers.Schedulers; -import rx.util.async.Async; import android.net.Uri; import android.text.Html; @@ -65,6 +64,7 @@ import android.text.Html; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.text.Collator; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; @@ -304,12 +304,13 @@ public abstract class GCParser { if (!cids.isEmpty() && (Settings.isGCPremiumMember() || showCaptcha) && ((recaptchaReceiver == null || StringUtils.isBlank(recaptchaReceiver.getChallenge())) || StringUtils.isNotBlank(recaptchaText))) { Log.i("Trying to get .loc for " + cids.size() + " caches"); - final Observable<Set<Geocache>> storedCaches = Async.start(new Func0<Set<Geocache>>() { + final Observable<Set<Geocache>> storedCaches = Observable.defer(new Func0<Observable<Set<Geocache>>>() { @Override - public Set<Geocache> call() { - return DataStore.loadCaches(Geocache.getGeocodes(caches), LoadFlags.LOAD_CACHE_OR_DB); + public Observable<Set<Geocache>> call() { + return Observable.just(DataStore.loadCaches(Geocache.getGeocodes(caches), LoadFlags.LOAD_CACHE_OR_DB)); } - }, Schedulers.io()); + }).subscribeOn(Schedulers.io()).cache(); + storedCaches.subscribe(); // Force asynchronous start of database loading try { // get coordinates for parsed caches @@ -979,22 +980,22 @@ public abstract class GCParser { * Observable that fetches a list of pocket queries. Returns a single element (which may be an empty list). * Executes on the network scheduler. */ - public static final Observable<List<PocketQueryList>> searchPocketQueryListObservable = Async.fromCallable(new Func0<List<PocketQueryList>>() { + public static final Observable<List<PocketQueryList>> searchPocketQueryListObservable = Observable.defer(new Func0<Observable<List<PocketQueryList>>>() { @Override - public List<PocketQueryList> call() { + public Observable<List<PocketQueryList>> call() { final Parameters params = new Parameters(); final String page = GCLogin.getInstance().getRequestLogged("http://www.geocaching.com/pocket/default.aspx", params); if (StringUtils.isBlank(page)) { Log.e("GCParser.searchPocketQueryList: No data from server"); - return Collections.emptyList(); + return Observable.just(Collections.<PocketQueryList>emptyList()); } final String subPage = StringUtils.substringAfter(page, "class=\"PocketQueryListTable"); if (StringUtils.isEmpty(subPage)) { Log.e("GCParser.searchPocketQueryList: class \"PocketQueryListTable\" not found on page"); - return Collections.emptyList(); + return Observable.just(Collections.<PocketQueryList>emptyList()); } final List<PocketQueryList> list = new ArrayList<>(); @@ -1016,17 +1017,18 @@ public abstract class GCParser { } // just in case, lets sort the resulting list + final Collator collator = TextUtils.getCollator(); Collections.sort(list, new Comparator<PocketQueryList>() { @Override public int compare(final PocketQueryList left, final PocketQueryList right) { - return String.CASE_INSENSITIVE_ORDER.compare(left.getName(), right.getName()); + return collator.compare(left.getName(), right.getName()); } }); - return list; + return Observable.just(list); } - }, RxUtils.networkScheduler); + }).subscribeOn(RxUtils.networkScheduler); public static ImmutablePair<StatusCode, String> postLog(final String geocode, final String cacheid, final String[] viewstates, final LogType logType, final int year, final int month, final int day, diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java index 93b61f9..dd6371b 100644 --- a/main/src/cgeo/geocaching/connector/gc/Tile.java +++ b/main/src/cgeo/geocaching/connector/gc/Tile.java @@ -15,7 +15,6 @@ import org.eclipse.jdt.annotation.NonNull; import rx.Observable; import rx.functions.Func0; -import rx.util.async.Async; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -144,7 +143,6 @@ public class Tile { * First point * @param right * Second point - * @return */ static int calcZoomLon(final Geopoint left, final Geopoint right, final int numberOfTiles) { @@ -177,7 +175,6 @@ public class Tile { * First point * @param top * Second point - * @return */ static int calcZoomLat(final Geopoint bottom, final Geopoint top, final int numberOfTiles) { @@ -208,8 +205,6 @@ public class Tile { * Calculates the inverted hyperbolic sine * (after Bronstein, Semendjajew: Taschenbuch der Mathematik) * - * @param x - * @return */ private static double asinh(final double x) { return Math.log(x + Math.sqrt(x * x + 1.0)); @@ -241,12 +236,12 @@ public class Tile { static Observable<String> requestMapInfo(final String url, final Parameters params, final String referer) { final HttpResponse response = Network.getRequest(url, params, new Parameters("Referer", referer)); - return Async.start(new Func0<String>() { + return Observable.defer(new Func0<Observable<String>>() { @Override - public String call() { - return Network.getResponseData(response); + public Observable<String> call() { + return Observable.just(Network.getResponseData(response)); } - }, RxUtils.networkScheduler); + }).subscribeOn(RxUtils.networkScheduler); } /** Request .png image for a tile. Return as soon as the request has been made, before the answer has been @@ -256,17 +251,17 @@ public class Tile { */ static Observable<Bitmap> requestMapTile(final Parameters params) { final HttpResponse response = Network.getRequest(GCConstants.URL_MAP_TILE, params, new Parameters("Referer", GCConstants.URL_LIVE_MAP)); - return Async.start(new Func0<Bitmap>() { + return Observable.defer(new Func0<Observable<Bitmap>>() { @Override - public Bitmap call() { + public Observable<Bitmap> call() { try { - return response != null ? BitmapFactory.decodeStream(response.getEntity().getContent()) : null; + return Observable.just(response != null ? BitmapFactory.decodeStream(response.getEntity().getContent()) : null); } catch (final IOException e) { Log.e("Tile.requestMapTile() ", e); - return null; + return Observable.just(null); } } - }, RxUtils.computationScheduler); + }).subscribeOn(RxUtils.computationScheduler); } public boolean containsPoint(final @NonNull ICoordinates point) { @@ -281,8 +276,6 @@ public class Tile { * Calculate needed tiles for the given viewport to cover it with * max 2x2 tiles * - * @param viewport - * @return */ protected static Set<Tile> getTilesForViewport(final Viewport viewport) { return getTilesForViewport(viewport, 2, Tile.ZOOMLEVEL_MIN); @@ -293,10 +286,6 @@ public class Tile { * You can define the minimum number of tiles on the longer axis * and/or the minimum zoom level. * - * @param viewport - * @param tilesOnAxis - * @param minZoom - * @return */ protected static Set<Tile> getTilesForViewport(final Viewport viewport, final int tilesOnAxis, final int minZoom) { final Set<Tile> tiles = new HashSet<>(); diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java index 9de7e1e..f5cd208 100644 --- a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java +++ b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java @@ -36,7 +36,6 @@ final class UTFGridPosition { /** * @param key * Key in the format (xx, xx) - * @return */ static UTFGridPosition fromString(final String key) { final MatcherWrapper matcher = new MatcherWrapper(UTFGridPosition.PATTERN_JSON_KEY, key); diff --git a/main/src/cgeo/geocaching/connector/gc/UncertainProperty.java b/main/src/cgeo/geocaching/connector/gc/UncertainProperty.java index 71adcbd..c9e01a2 100644 --- a/main/src/cgeo/geocaching/connector/gc/UncertainProperty.java +++ b/main/src/cgeo/geocaching/connector/gc/UncertainProperty.java @@ -4,7 +4,6 @@ package cgeo.geocaching.connector.gc; /** * Property with certainty. When merging properties, the one with higher certainty wins. * - * @param <T> */ public class UncertainProperty<T> { diff --git a/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java b/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java index acf7b48..5e5151a 100644 --- a/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java +++ b/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java @@ -7,7 +7,6 @@ public interface IOCAuthParams { /** * The site name: 'www.opencaching...' * - * @return */ @NonNull String getSite(); @@ -15,56 +14,48 @@ public interface IOCAuthParams { /** * ResId of the Consumer key * - * @return */ int getCKResId(); /** * ResId of the Consumer secret * - * @return */ int getCSResId(); /** * ResId of the Authorization title * - * @return */ int getAuthTitleResId(); /** * Preference key of the public token * - * @return */ int getTokenPublicPrefKey(); /** * Preference key of the secret token * - * @return */ int getTokenSecretPrefKey(); /** * Preference key of the temporary public token (OAuth) * - * @return */ int getTempTokenPublicPrefKey(); /** * Preference key of the temporary secret token (OAuth) * - * @return */ int getTempTokenSecretPrefKey(); /** * The URI to use as a callback (OAuth) * - * @return */ @NonNull String getCallbackUri(); diff --git a/main/src/cgeo/geocaching/connector/oc/OCCZConnector.java b/main/src/cgeo/geocaching/connector/oc/OCCZConnector.java new file mode 100644 index 0000000..0ffbbef --- /dev/null +++ b/main/src/cgeo/geocaching/connector/oc/OCCZConnector.java @@ -0,0 +1,31 @@ +package cgeo.geocaching.connector.oc; + +import cgeo.geocaching.utils.Log; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +public class OCCZConnector extends OCConnector { + + private static final String GEOCODE_PREFIX = "OZ"; + + public OCCZConnector() { + super("OpenCaching.CZ", "www.opencaching.cz", GEOCODE_PREFIX); + } + + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + final String id = StringUtils.substringAfter(url, "cacheid="); + try { + final String geocode = GEOCODE_PREFIX + StringUtils.leftPad(Integer.toHexString(Integer.valueOf(id)), 4, '0'); + if (canHandle(geocode)) { + return geocode; + } + } catch (final NumberFormatException e) { + Log.e("Unexpected URL for opencaching.cz " + url); + } + return super.getGeocodeFromUrl(url); + } +} diff --git a/main/src/cgeo/geocaching/connector/oc/OCConnector.java b/main/src/cgeo/geocaching/connector/oc/OCConnector.java index 8ac457b..6d7b23a 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCConnector.java @@ -5,7 +5,9 @@ import cgeo.geocaching.R; import cgeo.geocaching.connector.AbstractConnector; import cgeo.geocaching.enumerations.LogType; +import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.util.Arrays; import java.util.List; @@ -83,4 +85,24 @@ public class OCConnector extends AbstractConnector { return STANDARD_LOG_TYPES; } + + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + // different opencaching installations have different supported URLs + + // host.tld/geocode + final String shortHost = StringUtils.remove(getHost(), "www."); + String geocode = StringUtils.substringAfter(url, shortHost + "/"); + if (canHandle(geocode)) { + return geocode; + } + + // host.tld/viewcache.php?wp=geocode + geocode = StringUtils.substringAfter(url, shortHost + "/viewcache.php?wp="); + if (canHandle(geocode)) { + return geocode; + } + return super.getGeocodeFromUrl(url); + } } diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java index 275a103..e7d4e6f 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java @@ -30,6 +30,7 @@ import cgeo.geocaching.network.OAuth; import cgeo.geocaching.network.OAuthTokens; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.HtmlUtils; import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.SynchronizedDateFormat; @@ -62,8 +63,16 @@ import java.util.Map; import java.util.TimeZone; import java.util.regex.Pattern; +/** + * Client for the OpenCaching API (Okapi). + * + * @see <a href="http://www.opencaching.de/okapi/introduction.html">Okapi overview</a> + * + */ final class OkapiClient { + private static final String PARAMETER_LOGCOUNT_VALUE = "all"; + private static final String PARAMETER_LOGCOUNT_KEY = "lpc"; private static final char SEPARATOR = '|'; private static final String SEPARATOR_STRING = Character.toString(SEPARATOR); private static final SynchronizedDateFormat LOG_DATE_FORMAT = new SynchronizedDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", TimeZone.getTimeZone("UTC"), Locale.US); @@ -149,6 +158,7 @@ final class OkapiClient { params.add("fields", getFullFields(ocapiConn)); params.add("attribution_append", "none"); + params.add(PARAMETER_LOGCOUNT_KEY, PARAMETER_LOGCOUNT_VALUE); final JSONResult result = request(ocapiConn, OkapiService.SERVICE_CACHE, params); @@ -458,7 +468,7 @@ final class OkapiClient { parseUser(logResponse.get(LOG_USER)), parseDate(logResponse.get(LOG_DATE).asText()).getTime(), parseLogType(logResponse.get(LOG_TYPE).asText()), - logResponse.get(LOG_COMMENT).asText().trim()); + HtmlUtils.removeExtraParagraph(logResponse.get(LOG_COMMENT).asText().trim())); result.add(log); } catch (final NullPointerException e) { Log.e("OkapiClient.parseLogs", e); diff --git a/main/src/cgeo/geocaching/connector/ox/OXConnector.java b/main/src/cgeo/geocaching/connector/ox/OXConnector.java index 41035d1..d1db301 100644 --- a/main/src/cgeo/geocaching/connector/ox/OXConnector.java +++ b/main/src/cgeo/geocaching/connector/ox/OXConnector.java @@ -14,6 +14,7 @@ import cgeo.geocaching.location.Viewport; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.CancellableHandler; +import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -109,4 +110,14 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I } return new SearchResult(caches); } + + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + final String geocode = StringUtils.substringAfter(url, "http://www.opencaching.com/de/#!geocache/"); + if (canHandle(geocode)) { + return geocode; + } + return super.getGeocodeFromUrl(url); + } } diff --git a/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java b/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java index 7896826..25f66f4 100644 --- a/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java +++ b/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java @@ -29,7 +29,6 @@ public class OXGPXParser extends GPX10Parser { * The short description of OX caches contains "title by owner, type(T/D/Awesomeness)". That is a lot of * duplication. Additionally a space between type and (T/D/Awesomeness) is introduced. * - * @param cache */ private static void removeTitleFromShortDescription(final @NonNull Geocache cache) { cache.setShortDescription(StringUtils.replace(StringUtils.trim(StringUtils.substringAfterLast(cache.getShortDescription(), ",")), "(", " (")); diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java index b6792f0..6f9b21a 100644 --- a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java @@ -26,6 +26,7 @@ public class GeokretyConnector extends AbstractTrackableConnector { } @Override + @Nullable public Trackable searchTrackable(final String geocode, final String guid, final String id) { final String page = Network.getResponseData(Network.getRequest("http://geokrety.org/export2.php?gkid=" + getId(geocode))); if (page == null) { @@ -48,7 +49,12 @@ public class GeokretyConnector extends AbstractTrackableConnector { public @Nullable String getTrackableCodeFromUrl(@NonNull final String url) { // http://geokrety.org/konkret.php?id=38545 - final String id = StringUtils.substringAfterLast(url, "konkret.php?id="); + String id = StringUtils.substringAfterLast(url, "konkret.php?id="); + if (StringUtils.isNumeric(id)) { + return geocode(Integer.parseInt(id)); + } + // http://geokretymap.org/38545 + id = StringUtils.substringAfterLast(url, "geokretymap.org/"); if (StringUtils.isNumeric(id)) { return geocode(Integer.parseInt(id)); } @@ -58,8 +64,6 @@ public class GeokretyConnector extends AbstractTrackableConnector { /** * Get geocode from geokrety id * - * @param id - * @return */ public static String geocode(final int id) { return String.format("GK%04X", id); diff --git a/main/src/cgeo/geocaching/connector/trackable/SwaggieConnector.java b/main/src/cgeo/geocaching/connector/trackable/SwaggieConnector.java new file mode 100644 index 0000000..dcd618c --- /dev/null +++ b/main/src/cgeo/geocaching/connector/trackable/SwaggieConnector.java @@ -0,0 +1,51 @@ +package cgeo.geocaching.connector.trackable; + +import cgeo.geocaching.Trackable; +import cgeo.geocaching.network.Network; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import java.util.regex.Pattern; + +public final class SwaggieConnector extends AbstractTrackableConnector { + + private static final Pattern PATTERN_SW_CODE = Pattern.compile("SW[0-9]{4}"); + + @Override + public boolean canHandleTrackable(final String geocode) { + return geocode != null && PATTERN_SW_CODE.matcher(geocode).matches(); + } + + @Override + @NonNull + public String getUrl(@NonNull final Trackable trackable) { + return getUrl(trackable.getGeocode()); + } + + @Override + @Nullable + public Trackable searchTrackable(final String geocode, final String guid, final String id) { + final String page = Network.getResponseData(Network.getRequest(getUrl(geocode))); + if (page == null) { + return null; + } + return SwaggieParser.parse(page); + } + + @Override + @Nullable + public String getTrackableCodeFromUrl(@NonNull final String url) { + final String geocode = StringUtils.upperCase(StringUtils.substringAfterLast(url, "swaggie/")); + if (canHandleTrackable(geocode)) { + return geocode; + } + return null; + } + + private static String getUrl(final String geocode) { + return "http://geocaching.com.au/swaggie/" + geocode; + } + +} diff --git a/main/src/cgeo/geocaching/connector/trackable/SwaggieParser.java b/main/src/cgeo/geocaching/connector/trackable/SwaggieParser.java new file mode 100644 index 0000000..1883056 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/trackable/SwaggieParser.java @@ -0,0 +1,55 @@ +package cgeo.geocaching.connector.trackable; + +import cgeo.geocaching.Trackable; +import cgeo.geocaching.utils.TextUtils; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import java.util.regex.Pattern; + +final class SwaggieParser { + + private SwaggieParser() { + // utility class + } + + private static final Pattern PATTERN_NAME = Pattern.compile(Pattern.quote("<h1><a") + ".*?>(.*?)<"); + private static final Pattern PATTERN_GEOCODE = Pattern.compile(Pattern.quote("'/swaggie/") + "(.*?)'"); + private static final Pattern PATTERN_DESCRIPTION = Pattern.compile(Pattern.quote("'swaggie_description'>") + "(.*?)</div"); + private static final Pattern PATTERN_OWNER = Pattern.compile(">([^<]*?)</a> released"); + + @Nullable + public static Trackable parse(@NonNull final String page) { + final Trackable trackable = new Trackable(); + final String name = TextUtils.getMatch(page, PATTERN_NAME, null); + if (StringUtils.isEmpty(name)) { + return null; + } + trackable.setName(name); + + final String geocode = TextUtils.getMatch(page, PATTERN_GEOCODE, null); + if (StringUtils.isEmpty(geocode)) { + return null; + } + trackable.setGeocode(geocode); + + final String description = StringUtils.trim(TextUtils.getMatch(page, PATTERN_DESCRIPTION, StringUtils.EMPTY)); + if (StringUtils.isEmpty(description)) { + return null; + } + trackable.setDetails(description); + + final String owner = StringUtils.trim(TextUtils.getMatch(page, PATTERN_OWNER, StringUtils.EMPTY)); + if (StringUtils.isEmpty(owner)) { + return null; + } + trackable.setOwner(owner); + + trackable.setType("Swaggie"); + + return trackable; + } + +} diff --git a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java index 01c1897..1281683 100644 --- a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java @@ -21,6 +21,7 @@ public interface TrackableConnector { public boolean isLoggable(); + @Nullable public Trackable searchTrackable(String geocode, String guid, String id); @Nullable diff --git a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java index 5d825a3..665ebea 100644 --- a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java @@ -36,6 +36,7 @@ public class TravelBugConnector extends AbstractTrackableConnector { } @Override + @Nullable public Trackable searchTrackable(final String geocode, final String guid, final String id) { return GCParser.searchTrackable(geocode, guid, id); } diff --git a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java index 7e7e1b6..5fc7bf1 100644 --- a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java @@ -3,6 +3,7 @@ package cgeo.geocaching.connector.trackable; import cgeo.geocaching.Trackable; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; public class UnknownTrackableConnector extends AbstractTrackableConnector { @@ -18,6 +19,7 @@ public class UnknownTrackableConnector extends AbstractTrackableConnector { } @Override + @Nullable public Trackable searchTrackable(final String geocode, final String guid, final String id) { return null; } diff --git a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java index 585b890..770b63b 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java +++ b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java @@ -130,19 +130,22 @@ public enum CacheAttribute { // THIS LIST IS GENERATED: don't change anything here but read // project/attributes/readme.txt + @NonNull private static final String INTERNAL_YES = "_yes"; + @NonNull private static final String INTERNAL_NO = "_no"; public static final int NO_ID = -1; public final int gcid; public final int ocacode; + @NonNull public final String rawName; public final int drawableId; public final int stringIdYes; public final int stringIdNo; - CacheAttribute(final int gcid, final int ocacode, final String rawName, + CacheAttribute(final int gcid, final int ocacode, @NonNull final String rawName, final int drawableId, final int stringIdYes, final int stringIdNo) { this.gcid = gcid; this.ocacode = ocacode; @@ -159,12 +162,15 @@ public enum CacheAttribute { * true: for positive text, false: for negative text * @return the localized text */ + @NonNull public String getL10n(final boolean enabled) { return CgeoApplication.getInstance().getResources().getString( enabled ? stringIdYes : stringIdNo); } + @NonNull private final static Map<String, CacheAttribute> FIND_BY_GCRAWNAME = new HashMap<>(); + @NonNull private final static SparseArray<CacheAttribute> FIND_BY_OCACODE = new SparseArray<>(); static { for (final CacheAttribute attr : values()) { @@ -176,7 +182,7 @@ public enum CacheAttribute { } @Nullable - public static CacheAttribute getByRawName(final String rawName) { + public static CacheAttribute getByRawName(@Nullable final String rawName) { return rawName != null ? FIND_BY_GCRAWNAME.get(rawName) : null; } @@ -186,14 +192,14 @@ public enum CacheAttribute { } @NonNull - public static String trimAttributeName(final String attributeName) { + public static String trimAttributeName(@Nullable final String attributeName) { if (null == attributeName) { return ""; } return attributeName.replace(INTERNAL_YES, "").replace(INTERNAL_NO, "").trim(); } - public static boolean isEnabled(final String attributeName) { + public static boolean isEnabled(@Nullable final String attributeName) { return !StringUtils.endsWithIgnoreCase(attributeName, INTERNAL_NO); } diff --git a/main/src/cgeo/geocaching/enumerations/CacheListType.java b/main/src/cgeo/geocaching/enumerations/CacheListType.java index 1fce282..297e1be 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheListType.java +++ b/main/src/cgeo/geocaching/enumerations/CacheListType.java @@ -2,6 +2,8 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.loaders.AbstractSearchLoader.CacheListLoaderType; +import org.eclipse.jdt.annotation.NonNull; + public enum CacheListType { OFFLINE(true, CacheListLoaderType.OFFLINE), POCKET(false, CacheListLoaderType.POCKET), @@ -19,9 +21,9 @@ public enum CacheListType { */ public final boolean canSwitch; - public final CacheListLoaderType loaderType; + @NonNull public final CacheListLoaderType loaderType; - CacheListType(final boolean canSwitch, final CacheListLoaderType loaderType) { + CacheListType(final boolean canSwitch, @NonNull final CacheListLoaderType loaderType) { this.canSwitch = canSwitch; this.loaderType = loaderType; } diff --git a/main/src/cgeo/geocaching/enumerations/CacheSize.java b/main/src/cgeo/geocaching/enumerations/CacheSize.java index 54e12e0..10c8c9f 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheSize.java +++ b/main/src/cgeo/geocaching/enumerations/CacheSize.java @@ -4,6 +4,7 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.util.HashMap; import java.util.Locale; @@ -24,6 +25,7 @@ public enum CacheSize { OTHER("Other", 8, R.string.cache_size_other, "other"), UNKNOWN("Unknown", -1, R.string.cache_size_unknown, ""); // CacheSize not init. yet + @NonNull public final String id; public final int comparable; private final int stringId; @@ -32,13 +34,14 @@ public enum CacheSize { */ private final String ocSize2; - CacheSize(final String id, final int comparable, final int stringId, final String ocSize2) { + CacheSize(@NonNull final String id, final int comparable, final int stringId, final String ocSize2) { this.id = id; this.comparable = comparable; this.stringId = stringId; this.ocSize2 = ocSize2; } + @NonNull final private static Map<String, CacheSize> FIND_BY_ID = new HashMap<>(); static { for (final CacheSize cs : values()) { @@ -50,7 +53,7 @@ public enum CacheSize { } @NonNull - public static CacheSize getById(final String id) { + public static CacheSize getById(@Nullable final String id) { if (id == null) { return UNKNOWN; } @@ -87,6 +90,7 @@ public enum CacheSize { return UNKNOWN; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java index e66c742..4b882aa 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheType.java +++ b/main/src/cgeo/geocaching/enumerations/CacheType.java @@ -57,8 +57,11 @@ public enum CacheType { this.markerId = markerId; } + @NonNull private final static Map<String, CacheType> FIND_BY_ID = new HashMap<>(); + @NonNull private final static Map<String, CacheType> FIND_BY_PATTERN = new HashMap<>(); + @NonNull private final static Map<String, CacheType> FIND_BY_GUID = new HashMap<>(); static { @@ -102,6 +105,7 @@ public enum CacheType { return result; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } @@ -118,7 +122,6 @@ public enum CacheType { /** * Whether this type contains the given cache. * - * @param cache * @return true if this is the ALL type or if this type equals the type of the cache. */ public boolean contains(final Geocache cache) { diff --git a/main/src/cgeo/geocaching/enumerations/LoadFlags.java b/main/src/cgeo/geocaching/enumerations/LoadFlags.java index 69d8df2..0f08690 100644 --- a/main/src/cgeo/geocaching/enumerations/LoadFlags.java +++ b/main/src/cgeo/geocaching/enumerations/LoadFlags.java @@ -1,5 +1,7 @@ package cgeo.geocaching.enumerations; +import org.eclipse.jdt.annotation.NonNull; + import java.util.EnumSet; /** @@ -33,6 +35,7 @@ public interface LoadFlags { DB // include saving to CacheCache } + @NonNull public final static EnumSet<SaveFlag> SAVE_ALL = EnumSet.allOf(SaveFlag.class); public enum RemoveFlag { @@ -41,6 +44,7 @@ public interface LoadFlags { OWN_WAYPOINTS_ONLY_FOR_TESTING // only to be used in unit testing (as we never delete own waypoints) } + @NonNull public final static EnumSet<RemoveFlag> REMOVE_ALL = EnumSet.of(RemoveFlag.CACHE, RemoveFlag.DB); }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/enumerations/LogType.java b/main/src/cgeo/geocaching/enumerations/LogType.java index a27ec1a..bf0d66c 100644 --- a/main/src/cgeo/geocaching/enumerations/LogType.java +++ b/main/src/cgeo/geocaching/enumerations/LogType.java @@ -4,6 +4,7 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.util.HashMap; import java.util.Locale; @@ -47,13 +48,16 @@ public enum LogType { UNKNOWN(0, "unknown", "", "", R.string.err_unknown, R.drawable.mark_red); // LogType not init. yet public final int id; + @Nullable public final String iconName; + @NonNull public final String type; + @NonNull public final String oc_type; private final int stringId; public final int markerId; - LogType(final int id, final String iconName, final String type, final String oc_type, final int stringId, final int markerId) { + LogType(final int id, @Nullable final String iconName, @NonNull final String type, @NonNull final String oc_type, final int stringId, final int markerId) { this.id = id; this.iconName = iconName; this.type = type; @@ -110,6 +114,7 @@ public enum LogType { return result; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } diff --git a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java index fefeb62..05ce6fd 100644 --- a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java +++ b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java @@ -18,6 +18,7 @@ public enum LogTypeTrackable { this.resourceId = resourceId; } + @NonNull public String getLabel() { return CgeoApplication.getInstance().getString(resourceId); } diff --git a/main/src/cgeo/geocaching/enumerations/StatusCode.java b/main/src/cgeo/geocaching/enumerations/StatusCode.java index 9030e2b..37d027f 100644 --- a/main/src/cgeo/geocaching/enumerations/StatusCode.java +++ b/main/src/cgeo/geocaching/enumerations/StatusCode.java @@ -2,6 +2,8 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.R; +import org.eclipse.jdt.annotation.NonNull; + import android.content.res.Resources; public enum StatusCode { @@ -35,6 +37,7 @@ public enum StatusCode { return error_string; } + @NonNull public String getErrorString(final Resources res) { return res.getString(error_string); } diff --git a/main/src/cgeo/geocaching/enumerations/WaypointType.java b/main/src/cgeo/geocaching/enumerations/WaypointType.java index 732a665..d2281ef 100644 --- a/main/src/cgeo/geocaching/enumerations/WaypointType.java +++ b/main/src/cgeo/geocaching/enumerations/WaypointType.java @@ -49,6 +49,7 @@ public enum WaypointType { } } } + @NonNull public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL = Collections.unmodifiableSet(ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL_TMP); /** @@ -67,6 +68,7 @@ public enum WaypointType { return waypointType; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java index b3201f8..af564da 100644 --- a/main/src/cgeo/geocaching/export/GpxExport.java +++ b/main/src/cgeo/geocaching/export/GpxExport.java @@ -117,8 +117,7 @@ public class GpxExport extends AbstractExport { private File getExportFile() { final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US); - final Date now = new Date(); - return FileUtils.getUniqueNamedFile(Settings.getGpxExportDir() + File.separatorChar + "export_" + fileNameDateFormat.format(now) + ".gpx"); + return FileUtils.getUniqueNamedFile(new File(Settings.getGpxExportDir(), "export_" + fileNameDateFormat.format(new Date()) + ".gpx")); } @Override diff --git a/main/src/cgeo/geocaching/export/GpxSerializer.java b/main/src/cgeo/geocaching/export/GpxSerializer.java index fe53f37..8139c76 100644 --- a/main/src/cgeo/geocaching/export/GpxSerializer.java +++ b/main/src/cgeo/geocaching/export/GpxSerializer.java @@ -55,7 +55,7 @@ public final class GpxSerializer { } - public void writeGPX(List<String> allGeocodesIn, Writer writer, final ProgressListener progressListener) throws IOException { + public void writeGPX(final List<String> allGeocodesIn, final Writer writer, final ProgressListener progressListener) throws IOException { // create a copy of the geocode list, as we need to modify it, but it might be immutable final ArrayList<String> allGeocodes = new ArrayList<>(allGeocodesIn); @@ -88,7 +88,7 @@ public final class GpxSerializer { gpx.endDocument(); } - private void exportBatch(final XmlSerializer gpx, Collection<String> geocodesOfBatch) throws IOException { + private void exportBatch(final XmlSerializer gpx, final Collection<String> geocodesOfBatch) throws IOException { final Set<Geocache> caches = DataStore.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY); for (final Geocache cache : caches) { if (cache == null) { @@ -174,11 +174,10 @@ public final class GpxSerializer { } /** - * @param boolFlag * @return XML schema compliant boolean representation of the boolean flag. This must be either true, false, 0 or 1, * but no other value (also not upper case True/False). */ - private static String gpxBoolean(boolean boolFlag) { + private static String gpxBoolean(final boolean boolFlag) { return boolFlag ? "true" : "false"; } @@ -255,7 +254,7 @@ public final class GpxSerializer { } private void writeLogs(final Geocache cache) throws IOException { - List<LogEntry> logs = cache.getLogs(); + final List<LogEntry> logs = cache.getLogs(); if (logs.isEmpty()) { return; } @@ -291,7 +290,7 @@ public final class GpxSerializer { } private void writeTravelBugs(final Geocache cache) throws IOException { - List<Trackable> inventory = cache.getInventory(); + final List<Trackable> inventory = cache.getInventory(); if (CollectionUtils.isEmpty(inventory)) { return; } @@ -338,7 +337,7 @@ public final class GpxSerializer { return getLocationPart(cache, 0); } - private static String getLocationPart(final Geocache cache, int partIndex) { + private static String getLocationPart(final Geocache cache, final int partIndex) { final String location = cache.getLocation(); if (StringUtils.contains(location, ", ")) { final String[] parts = StringUtils.split(location, ','); @@ -350,7 +349,7 @@ public final class GpxSerializer { } public static String getCountry(final Geocache cache) { - String country = getLocationPart(cache, 1); + final String country = getLocationPart(cache, 1); if (StringUtils.isNotEmpty(country)) { return country; } diff --git a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java index 427fd48..3ec9849 100644 --- a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java +++ b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java @@ -201,7 +201,6 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext * Check if a filename belongs to the AbstractFileListActivity. This implementation checks for file extensions. * Subclasses may override this method to filter out specific files. * - * @param filename * @return <code>true</code> if the filename belongs to the list */ protected boolean filenameBelongsToList(@NonNull final String filename) { diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java index e7523f3..5699ebe 100644 --- a/main/src/cgeo/geocaching/files/GPXImporter.java +++ b/main/src/cgeo/geocaching/files/GPXImporter.java @@ -95,8 +95,6 @@ public class GPXImporter { * * @param uri * URI of the file to import - * @param mimeType - * @param pathName */ public void importGPX(final Uri uri, final @Nullable String mimeType, final @Nullable String pathName) { final ContentResolver contentResolver = fromActivity.getContentResolver(); diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java index 4f8979b..e4bb7e1 100644 --- a/main/src/cgeo/geocaching/files/GPXParser.java +++ b/main/src/cgeo/geocaching/files/GPXParser.java @@ -840,7 +840,6 @@ public abstract class GPXParser extends FileParser { /** * Add listeners for GSAK extensions * - * @param cacheParent */ private void registerGsakExtensions(final Element cacheParent) { for (final String gsakNamespace : GSAK_NS) { @@ -901,7 +900,6 @@ public abstract class GPXParser extends FileParser { /** * Add listeners for c:geo extensions * - * @param cacheParent */ private void registerCgeoExtensions(final Element cacheParent) { final Element cgeoVisited = cacheParent.getChild(CGEO_NS, "visited"); @@ -940,8 +938,6 @@ public abstract class GPXParser extends FileParser { * GPX 1.0 and 1.1 use different XML elements to put the cache into, therefore needs to be overwritten in the * version specific subclasses * - * @param waypoint - * @return */ protected abstract Element getCacheParent(Element waypoint); diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java index 7fce27d..cfeac9a 100644 --- a/main/src/cgeo/geocaching/files/LocalStorage.java +++ b/main/src/cgeo/geocaching/files/LocalStorage.java @@ -364,24 +364,6 @@ public final class LocalStorage { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); } - public static boolean deleteDirectory(@NonNull final File dir) { - final File[] files = dir.listFiles(); - - // Although we are called on an existing directory, it might have been removed concurrently - // in the meantime, for example by the user or by another cleanup task. - if (files != null) { - for (final File file : files) { - if (file.isDirectory()) { - deleteDirectory(file); - } else { - FileUtils.delete(file); - } - } - } - - return FileUtils.delete(dir); - } - /** * Deletes all files from directory geocode with the given prefix. * diff --git a/main/src/cgeo/geocaching/filter/AbstractFilter.java b/main/src/cgeo/geocaching/filter/AbstractFilter.java index 248c9c2..20575a6 100644 --- a/main/src/cgeo/geocaching/filter/AbstractFilter.java +++ b/main/src/cgeo/geocaching/filter/AbstractFilter.java @@ -1,5 +1,6 @@ package cgeo.geocaching.filter; +import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import org.eclipse.jdt.annotation.NonNull; @@ -8,12 +9,18 @@ import java.util.ArrayList; import java.util.List; abstract class AbstractFilter implements IFilter { + @NonNull private final String name; - protected AbstractFilter(final String name) { + protected AbstractFilter(final int nameResourceId) { + this(CgeoApplication.getInstance().getString(nameResourceId)); + } + + protected AbstractFilter(@NonNull final String name) { this.name = name; } + @Override public void filter(@NonNull final List<Geocache> list) { final List<Geocache> itemsToRemove = new ArrayList<>(); @@ -26,6 +33,7 @@ abstract class AbstractFilter implements IFilter { } @Override + @NonNull public String getName() { return name; } diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java index 2fc6eb2..6ed4a8f 100644 --- a/main/src/cgeo/geocaching/filter/AttributeFilter.java +++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java @@ -15,7 +15,7 @@ class AttributeFilter extends AbstractFilter { private final String attribute; - public AttributeFilter(final String name, final String attribute) { + public AttributeFilter(@NonNull final String name, final String attribute) { super(name); this.attribute = attribute; } diff --git a/main/src/cgeo/geocaching/filter/DistanceFilter.java b/main/src/cgeo/geocaching/filter/DistanceFilter.java index f1ba7f8..b352f5d 100644 --- a/main/src/cgeo/geocaching/filter/DistanceFilter.java +++ b/main/src/cgeo/geocaching/filter/DistanceFilter.java @@ -17,7 +17,7 @@ class DistanceFilter extends AbstractFilter { private final int minDistance; private final int maxDistance; - public DistanceFilter(final String name, final int minDistance, final int maxDistance) { + public DistanceFilter(@NonNull final String name, final int minDistance, final int maxDistance) { super(name); this.minDistance = minDistance; this.maxDistance = maxDistance; diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java index 2d7dafc..97e70ba 100644 --- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java +++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java @@ -7,6 +7,9 @@ import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.TextUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import rx.functions.Action1; import android.app.Activity; @@ -24,10 +27,10 @@ import java.util.List; public final class FilterUserInterface { private static class FactoryEntry { - private final String name; - private final Class<? extends IFilterFactory> filterFactory; + @NonNull private final String name; + @Nullable private final Class<? extends IFilterFactory> filterFactory; - public FactoryEntry(final String name, final Class<? extends IFilterFactory> filterFactory) { + public FactoryEntry(@NonNull final String name, @Nullable final Class<? extends IFilterFactory> filterFactory) { this.name = name; this.filterFactory = filterFactory; } @@ -77,7 +80,7 @@ public final class FilterUserInterface { register(R.string.caches_filter_clear, null); } - private void register(final int resourceId, final Class<? extends IFilterFactory> factoryClass) { + private void register(final int resourceId, @Nullable final Class<? extends IFilterFactory> factoryClass) { registry.add(new FactoryEntry(res.getString(resourceId), factoryClass)); } @@ -92,12 +95,13 @@ public final class FilterUserInterface { public void onClick(final DialogInterface dialog, final int itemIndex) { final FactoryEntry entry = adapter.getItem(itemIndex); // reset? - if (entry.filterFactory == null) { + final Class<? extends IFilterFactory> filterFactory = entry.filterFactory; + if (filterFactory == null) { runAfterwards.call(null); } else { try { - final IFilterFactory factoryInstance = entry.filterFactory.newInstance(); + final IFilterFactory factoryInstance = filterFactory.newInstance(); selectFromFactory(factoryInstance, entry.name, runAfterwards); } catch (final Exception e) { Log.e("selectFilter", e); @@ -109,7 +113,7 @@ public final class FilterUserInterface { builder.create().show(); } - private void selectFromFactory(final IFilterFactory factory, final String menuTitle, final Action1<IFilter> runAfterwards) { + private void selectFromFactory(@NonNull final IFilterFactory factory, final String menuTitle, final Action1<IFilter> runAfterwards) { final List<IFilter> filters = Collections.unmodifiableList(factory.getFilters()); if (filters.size() == 1) { runAfterwards.call(filters.get(0)); diff --git a/main/src/cgeo/geocaching/filter/IFilter.java b/main/src/cgeo/geocaching/filter/IFilter.java index de39e5a..2bc2004 100644 --- a/main/src/cgeo/geocaching/filter/IFilter.java +++ b/main/src/cgeo/geocaching/filter/IFilter.java @@ -8,10 +8,10 @@ import java.util.List; public interface IFilter { + @NonNull String getName(); /** - * @param cache * @return true if the filter accepts the cache, false otherwise */ boolean accepts(@NonNull final Geocache cache); diff --git a/main/src/cgeo/geocaching/filter/ModifiedFilter.java b/main/src/cgeo/geocaching/filter/ModifiedFilter.java index c224cb4..9b5c856 100644 --- a/main/src/cgeo/geocaching/filter/ModifiedFilter.java +++ b/main/src/cgeo/geocaching/filter/ModifiedFilter.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; @@ -12,7 +11,7 @@ import java.util.List; class ModifiedFilter extends AbstractFilter implements IFilterFactory { public ModifiedFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_modified)); + super(R.string.caches_filter_modified); } @Override diff --git a/main/src/cgeo/geocaching/filter/OfflineLogFilter.java b/main/src/cgeo/geocaching/filter/OfflineLogFilter.java new file mode 100644 index 0000000..0ed9618 --- /dev/null +++ b/main/src/cgeo/geocaching/filter/OfflineLogFilter.java @@ -0,0 +1,19 @@ +package cgeo.geocaching.filter; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; + +import org.eclipse.jdt.annotation.NonNull; + +public class OfflineLogFilter extends AbstractFilter { + + protected OfflineLogFilter() { + super(R.string.caches_filter_offline_log); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.isLogOffline(); + } + +} diff --git a/main/src/cgeo/geocaching/filter/OriginFilter.java b/main/src/cgeo/geocaching/filter/OriginFilter.java index 4fb3301..d51b02c 100644 --- a/main/src/cgeo/geocaching/filter/OriginFilter.java +++ b/main/src/cgeo/geocaching/filter/OriginFilter.java @@ -15,7 +15,7 @@ public class OriginFilter extends AbstractFilter { private final IConnector connector; - public OriginFilter(final IConnector connector) { + public OriginFilter(@NonNull final IConnector connector) { super(connector.getName()); this.connector = connector; } diff --git a/main/src/cgeo/geocaching/filter/OwnRatingFilter.java b/main/src/cgeo/geocaching/filter/OwnRatingFilter.java index 0c468a9..1b86bab 100644 --- a/main/src/cgeo/geocaching/filter/OwnRatingFilter.java +++ b/main/src/cgeo/geocaching/filter/OwnRatingFilter.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.gcvote.GCVote; @@ -18,7 +17,7 @@ import java.util.List; public class OwnRatingFilter extends AbstractFilter implements IFilterFactory { protected OwnRatingFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_own_rating)); + super(R.string.caches_filter_own_rating); } @Override diff --git a/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java b/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java index 6c6186b..e9780da 100644 --- a/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java +++ b/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java @@ -10,7 +10,7 @@ public class PersonalDataFilterFactory implements IFilterFactory { @Override @NonNull public List<? extends IFilter> getFilters() { - return Arrays.asList(new OwnRatingFilter(), new PersonalNoteFilter(), new ModifiedFilter()); + return Arrays.asList(new OwnRatingFilter(), new PersonalNoteFilter(), new ModifiedFilter(), new OfflineLogFilter()); } } diff --git a/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java b/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java index 978ad6b..11c623e 100644 --- a/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java +++ b/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; @@ -16,7 +15,7 @@ import java.util.List; public class PersonalNoteFilter extends AbstractFilter implements IFilterFactory { protected PersonalNoteFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_personal_note)); + super(R.string.caches_filter_personal_note); } @Override diff --git a/main/src/cgeo/geocaching/filter/PopularityFilter.java b/main/src/cgeo/geocaching/filter/PopularityFilter.java index bb564e8..eabc533 100644 --- a/main/src/cgeo/geocaching/filter/PopularityFilter.java +++ b/main/src/cgeo/geocaching/filter/PopularityFilter.java @@ -13,7 +13,7 @@ class PopularityFilter extends AbstractFilter { private final int minFavorites; private final int maxFavorites; - public PopularityFilter(final String name, final int minFavorites, final int maxFavorites) { + public PopularityFilter(@NonNull final String name, final int minFavorites, final int maxFavorites) { super(name); this.minFavorites = minFavorites; this.maxFavorites = maxFavorites; diff --git a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java index 53904f1..0548345 100644 --- a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java +++ b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java @@ -18,7 +18,7 @@ class PopularityRatioFilter extends AbstractFilter { private final int minRatio; private final int maxRatio; - public PopularityRatioFilter(final String name, final int minRatio, final int maxRatio) { + public PopularityRatioFilter(@NonNull final String name, final int minRatio, final int maxRatio) { super(name); this.minRatio = minRatio; this.maxRatio = maxRatio; diff --git a/main/src/cgeo/geocaching/filter/RatingFilter.java b/main/src/cgeo/geocaching/filter/RatingFilter.java index 3edfcb6..63e9c0b 100644 --- a/main/src/cgeo/geocaching/filter/RatingFilter.java +++ b/main/src/cgeo/geocaching/filter/RatingFilter.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.gcvote.GCVote; @@ -18,7 +17,7 @@ import java.util.List; public class RatingFilter extends AbstractFilter implements IFilterFactory { protected RatingFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_rating)); + super(R.string.caches_filter_rating); } @Override diff --git a/main/src/cgeo/geocaching/filter/SizeFilter.java b/main/src/cgeo/geocaching/filter/SizeFilter.java index 4c7c122..a48da2c 100644 --- a/main/src/cgeo/geocaching/filter/SizeFilter.java +++ b/main/src/cgeo/geocaching/filter/SizeFilter.java @@ -11,7 +11,7 @@ import java.util.List; class SizeFilter extends AbstractFilter { private final CacheSize cacheSize; - public SizeFilter(final CacheSize cacheSize) { + public SizeFilter(@NonNull final CacheSize cacheSize) { super(cacheSize.id); this.cacheSize = cacheSize; } @@ -22,6 +22,7 @@ class SizeFilter extends AbstractFilter { } @Override + @NonNull public String getName() { return cacheSize.getL10n(); } diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java index f574045..289f656 100644 --- a/main/src/cgeo/geocaching/filter/StateFilter.java +++ b/main/src/cgeo/geocaching/filter/StateFilter.java @@ -1,13 +1,10 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import org.eclipse.jdt.annotation.NonNull; -import android.content.res.Resources; - import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -15,16 +12,14 @@ import java.util.List; abstract class StateFilter extends AbstractFilter { - static final Resources res = CgeoApplication.getInstance().getResources(); - - protected StateFilter(final String name) { - super(name); + protected StateFilter(final int nameResourceId) { + super(nameResourceId); } static class StateFoundFilter extends StateFilter { public StateFoundFilter() { - super(res.getString(R.string.cache_status_found)); + super(R.string.cache_status_found); } @Override @@ -37,7 +32,7 @@ abstract class StateFilter extends AbstractFilter { static class StateNotFoundFilter extends StateFilter { public StateNotFoundFilter() { - super(res.getString(R.string.cache_not_status_found)); + super(R.string.cache_not_status_found); } @Override @@ -49,7 +44,7 @@ abstract class StateFilter extends AbstractFilter { static class StateArchivedFilter extends StateFilter { public StateArchivedFilter() { - super(res.getString(R.string.cache_status_archived)); + super(R.string.cache_status_archived); } @Override @@ -60,7 +55,7 @@ abstract class StateFilter extends AbstractFilter { static class StateDisabledFilter extends StateFilter { public StateDisabledFilter() { - super(res.getString(R.string.cache_status_disabled)); + super(R.string.cache_status_disabled); } @Override @@ -71,7 +66,7 @@ abstract class StateFilter extends AbstractFilter { static class StatePremiumFilter extends StateFilter { public StatePremiumFilter() { - super(res.getString(R.string.cache_status_premium)); + super(R.string.cache_status_premium); } @Override @@ -82,7 +77,7 @@ abstract class StateFilter extends AbstractFilter { static class StateNonPremiumFilter extends StateFilter { public StateNonPremiumFilter() { - super(res.getString(R.string.cache_status_not_premium)); + super(R.string.cache_status_not_premium); } @Override @@ -93,7 +88,7 @@ abstract class StateFilter extends AbstractFilter { private static class StateOfflineLogFilter extends StateFilter { public StateOfflineLogFilter() { - super(res.getString(R.string.cache_status_offline_log)); + super(R.string.cache_status_offline_log); } @Override @@ -104,7 +99,7 @@ abstract class StateFilter extends AbstractFilter { static class StateStoredFilter extends StateFilter { public StateStoredFilter() { - super(res.getString(R.string.cache_status_stored)); + super(R.string.cache_status_stored); } @Override @@ -115,7 +110,7 @@ abstract class StateFilter extends AbstractFilter { static class StateNotStoredFilter extends StateFilter { public StateNotStoredFilter() { - super(res.getString(R.string.cache_status_not_stored)); + super(R.string.cache_status_not_stored); } @Override diff --git a/main/src/cgeo/geocaching/filter/TrackablesFilter.java b/main/src/cgeo/geocaching/filter/TrackablesFilter.java index 7ad06a1..bdf91f7 100644 --- a/main/src/cgeo/geocaching/filter/TrackablesFilter.java +++ b/main/src/cgeo/geocaching/filter/TrackablesFilter.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; @@ -11,7 +10,7 @@ import java.util.List; class TrackablesFilter extends AbstractFilter implements IFilterFactory { public TrackablesFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_track)); + super(R.string.caches_filter_track); } @Override diff --git a/main/src/cgeo/geocaching/filter/TypeFilter.java b/main/src/cgeo/geocaching/filter/TypeFilter.java index 412cbc2..70a8068 100644 --- a/main/src/cgeo/geocaching/filter/TypeFilter.java +++ b/main/src/cgeo/geocaching/filter/TypeFilter.java @@ -11,7 +11,7 @@ import java.util.List; class TypeFilter extends AbstractFilter { private final CacheType cacheType; - public TypeFilter(final CacheType cacheType) { + public TypeFilter(@NonNull final CacheType cacheType) { super(cacheType.id); this.cacheType = cacheType; } @@ -22,6 +22,7 @@ class TypeFilter extends AbstractFilter { } @Override + @NonNull public String getName() { return cacheType.getL10n(); } diff --git a/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java b/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java index e5717ab..0738274 100644 --- a/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java +++ b/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java @@ -87,9 +87,8 @@ public class GCVoteDialog { cache.setMyVote(rating); DataStore.saveChangedCache(cache); return true; - } else { - Log.w("GCVoteDialog.vote: could not send vote"); } + Log.w("GCVoteDialog.vote: could not send vote"); } } catch (final RuntimeException e) { Log.e("GCVoteDialog.vote: could not send vote", e); diff --git a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java index 04d720e..b9fbc76 100644 --- a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java +++ b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java @@ -26,7 +26,6 @@ public class OfflineGeocacheListLoader extends AbstractSearchLoader { } /** - * @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) { diff --git a/main/src/cgeo/geocaching/location/Geopoint.java b/main/src/cgeo/geocaching/location/Geopoint.java index ad693ca..a746a1e 100644 --- a/main/src/cgeo/geocaching/location/Geopoint.java +++ b/main/src/cgeo/geocaching/location/Geopoint.java @@ -97,12 +97,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Create new Geopoint from individual textual components. * - * @param latDir - * @param latDeg - * @param latDegFrac - * @param lonDir - * @param lonDeg - * @param lonDegFrac */ public Geopoint(final String latDir, final String latDeg, final String latDegFrac, final String lonDir, final String lonDeg, final String lonDegFrac) { @@ -113,14 +107,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Create new Geopoint from individual textual components. * - * @param latDir - * @param latDeg - * @param latMin - * @param latMinFrac - * @param lonDir - * @param lonDeg - * @param lonMin - * @param lonMinFrac */ public Geopoint(final String latDir, final String latDeg, final String latMin, final String latMinFrac, final String lonDir, final String lonDeg, final String lonMin, final String lonMinFrac) { @@ -131,16 +117,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Create new Geopoint from individual textual components. * - * @param latDir - * @param latDeg - * @param latMin - * @param latSec - * @param latSecFrac - * @param lonDir - * @param lonDeg - * @param lonMin - * @param lonSec - * @param lonSecFrac */ public Geopoint(final String latDir, final String latDeg, final String latMin, final String latSec, final String latSecFrac, final String lonDir, final String lonDeg, final String lonMin, final String lonSec, final String lonSecFrac) { @@ -202,8 +178,8 @@ public final class Geopoint implements ICoordinates, Parcelable { * @return An array of floats: the distance in meters, then the bearing in degrees */ private float[] pathTo(final Geopoint target) { - float[] results = new float[2]; - android.location.Location.distanceBetween(latitude, longitude, target.latitude, target.longitude, results); + final float[] results = new float[2]; + Location.distanceBetween(latitude, longitude, target.latitude, target.longitude, results); return results; } @@ -283,7 +259,7 @@ public final class Geopoint implements ICoordinates, Parcelable { * @see GeopointFormatter * @return formatted coordinates */ - public String format(GeopointFormatter.Format format) { + public String format(final GeopointFormatter.Format format) { return GeopointFormatter.format(format, this); } @@ -301,7 +277,7 @@ public final class Geopoint implements ICoordinates, Parcelable { abstract public static class GeopointException extends NumberFormatException { private static final long serialVersionUID = 1L; - protected GeopointException(String msg) { + protected GeopointException(final String msg) { super(msg); } } @@ -347,7 +323,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get latitude character (N or S). * - * @return */ public char getLatDir() { return latitude >= 0 ? 'N' : 'S'; @@ -356,7 +331,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get longitude character (E or W). * - * @return */ public char getLonDir() { return longitude >= 0 ? 'E' : 'W'; @@ -365,7 +339,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral non-negative latitude degrees. * - * @return */ public int getLatDeg() { return getDeg(latitude); @@ -374,7 +347,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral non-negative longitude degrees. * - * @return */ public int getLonDeg() { return getDeg(longitude); @@ -387,7 +359,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the latitude degrees scaled up by 10^5. * - * @return */ public int getLatDegFrac() { return getDegFrac(latitude); @@ -396,7 +367,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the longitude degrees scaled up by 10^5. * - * @return */ public int getLonDegFrac() { return getDegFrac(longitude); @@ -409,7 +379,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral latitude minutes. * - * @return */ public int getLatMin() { return getMin(latitude); @@ -418,7 +387,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral longitude minutes. * - * @return */ public int getLonMin() { return getMin(longitude); @@ -431,7 +399,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the latitude minutes scaled up by 1000. * - * @return */ public int getLatMinFrac() { return getMinFrac(latitude); @@ -440,7 +407,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the longitude minutes scaled up by 1000. * - * @return */ public int getLonMinFrac() { return getMinFrac(longitude); @@ -453,7 +419,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the latitude minutes. * - * @return */ public double getLatMinRaw() { return getMinRaw(latitude); @@ -462,7 +427,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the longitude minutes. * - * @return */ public double getLonMinRaw() { return getMinRaw(longitude); @@ -475,7 +439,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral part of the latitude seconds. * - * @return */ public int getLatSec() { return getSec(latitude); @@ -484,7 +447,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral part of the longitude seconds. * - * @return */ public int getLonSec() { return getSec(longitude); @@ -497,7 +459,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the latitude seconds scaled up by 1000. * - * @return */ public int getLatSecFrac() { @@ -507,7 +468,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the longitude seconds scaled up by 1000. * - * @return */ public int getLonSecFrac() { @@ -521,7 +481,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the latitude seconds. * - * @return */ public double getLatSecRaw() { return getSecRaw(latitude); @@ -530,7 +489,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the longitude seconds. * - * @return */ public double getLonSecRaw() { return getSecRaw(longitude); @@ -555,19 +513,19 @@ 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) { + public static double getDistance(final double lat1, final double lon1, final double lat2, final double lon2) { // 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) + + final double earthRadius = 6372.8; + final double dLat = toRadians(lat2 - lat1); + final double dLon = toRadians(lon2 - lon1); + final 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); // simplify haversine return (2 * earthRadius * 1000 * Math.asin(Math.sqrt(a))); } - private static double toRadians(double angdeg) { + private static double toRadians(final double angdeg) { return angdeg * DEG_TO_RAD; } diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index 457b06c..b2bb8a6 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -4,6 +4,7 @@ import butterknife.ButterKnife; import cgeo.geocaching.CacheListActivity; import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.CompassActivity; import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; import cgeo.geocaching.Intents; @@ -22,7 +23,6 @@ import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.list.StoredList; import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.location.Viewport; -import cgeo.geocaching.maps.LiveMapStrategy.Strategy; import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import cgeo.geocaching.maps.interfaces.MapActivityImpl; @@ -449,11 +449,14 @@ public class CGeoMap extends AbstractMap implements ViewFactory { mapView.clearOverlays(); overlayCaches = mapView.createAddMapOverlay(mapView.getContext(), getResources().getDrawable(R.drawable.marker)); - overlayPositionAndScale = mapView.createAddPositionAndScaleOverlay(); + + + overlayPositionAndScale = mapView.createAddPositionAndScaleOverlay(coordsIntent, geocodeIntent); if (trailHistory != null) { overlayPositionAndScale.setHistory(trailHistory); } + mapView.repaintRequired(null); setZoom(Settings.getMapZoom(mapMode)); @@ -508,7 +511,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { /** * Set the zoom of the map. The zoom is restricted to a certain minimum in case of live map. * - * @param zoom */ private void setZoom(final int zoom) { mapView.getMapController().setZoom(isLiveEnabled ? Math.max(zoom, MIN_LIVEMAP_ZOOM) : zoom); @@ -663,7 +665,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { item = menu.findItem(R.id.menu_theme_mode); // show theme selection item.setVisible(mapView.hasMapThemes()); - menu.findItem(R.id.menu_as_list).setVisible(!isLoading()); + menu.findItem(R.id.menu_as_list).setVisible(!isLoading() && caches.size() > 1); menu.findItem(R.id.submenu_strategy).setVisible(isLiveEnabled); @@ -680,6 +682,8 @@ public class CGeoMap extends AbstractMap implements ViewFactory { default: // DETAILED menu.findItem(R.id.menu_strategy_detailed).setChecked(true); } + menu.findItem(R.id.menu_hint).setVisible(mapMode == MapMode.SINGLE); + menu.findItem(R.id.menu_compass).setVisible(mapMode == MapMode.SINGLE); } catch (final RuntimeException e) { Log.e("CGeoMap.onPrepareOptionsMenu", e); } @@ -765,24 +769,34 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } case R.id.menu_strategy_fastest: { item.setChecked(true); - Settings.setLiveMapStrategy(Strategy.FASTEST); + Settings.setLiveMapStrategy(LivemapStrategy.FASTEST); return true; } case R.id.menu_strategy_fast: { item.setChecked(true); - Settings.setLiveMapStrategy(Strategy.FAST); + Settings.setLiveMapStrategy(LivemapStrategy.FAST); return true; } case R.id.menu_strategy_auto: { item.setChecked(true); - Settings.setLiveMapStrategy(Strategy.AUTO); + Settings.setLiveMapStrategy(LivemapStrategy.AUTO); return true; } case R.id.menu_strategy_detailed: { item.setChecked(true); - Settings.setLiveMapStrategy(Strategy.DETAILED); + Settings.setLiveMapStrategy(LivemapStrategy.DETAILED); return true; } + case R.id.menu_hint: + if (caches.size() == 1) { + caches.iterator().next().showHintToast(getActivity()); + } + return true; + case R.id.menu_compass: + if (caches.size() == 1) { + CompassActivity.startActivityCache(this.getActivity(), caches.iterator().next()); + } + return true; default: final MapSource mapSource = MapProviderFactory.getMapSource(id); if (mapSource != null) { @@ -994,12 +1008,13 @@ public class CGeoMap extends AbstractMap implements ViewFactory { final boolean needsRepaintForHeading = needsRepaintForHeading(); if (needsRepaintForDistanceOrAccuracy) { - if (map.followMyLocation) { + if (CGeoMap.followMyLocation) { map.centerMap(new Geopoint(currentLocation)); } } if (needsRepaintForDistanceOrAccuracy || needsRepaintForHeading) { + map.overlayPositionAndScale.setCoordinates(currentLocation); map.overlayPositionAndScale.setHeading(currentHeading); map.mapView.repaintRequired(map.overlayPositionAndScale); @@ -1116,7 +1131,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { /** * get if map is loading something * - * @return */ public boolean isLoading() { return !loadTimer.isUnsubscribed() && diff --git a/main/src/cgeo/geocaching/maps/CachesOverlay.java b/main/src/cgeo/geocaching/maps/CachesOverlay.java index c4c4465..048217e 100644 --- a/main/src/cgeo/geocaching/maps/CachesOverlay.java +++ b/main/src/cgeo/geocaching/maps/CachesOverlay.java @@ -158,8 +158,6 @@ public class CachesOverlay extends AbstractItemizedOverlay { * reality and therefore the minor changes due to the projection will not make any visible difference at the zoom * levels which are used to see the circles. * - * @param projection - * @return */ private int calculateDrawingRadius(MapProjectionImpl projection) { float[] distanceArray = new float[1]; diff --git a/main/src/cgeo/geocaching/maps/DirectionDrawer.java b/main/src/cgeo/geocaching/maps/DirectionDrawer.java new file mode 100644 index 0000000..c746221 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/DirectionDrawer.java @@ -0,0 +1,60 @@ +package cgeo.geocaching.maps; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.maps.interfaces.MapItemFactory; +import cgeo.geocaching.maps.interfaces.MapProjectionImpl; +import cgeo.geocaching.settings.Settings; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Point; +import android.location.Location; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +public class DirectionDrawer { + private Geopoint currentCoords; + private final Geopoint destinationCoords; + private final MapItemFactory mapItemFactory; + private final float width; + + private Paint line = null; + + public DirectionDrawer(final Geopoint coords) { + this.destinationCoords = coords; + this.mapItemFactory = Settings.getMapProvider().getMapItemFactory(); + + final DisplayMetrics metrics = new DisplayMetrics(); + final WindowManager windowManager = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE); + windowManager.getDefaultDisplay().getMetrics(metrics); + + width = 4f * metrics.density; + + } + + public void setCoordinates(final Location coordinatesIn) { + currentCoords = new Geopoint(coordinatesIn); + } + + void drawDirection(final Canvas canvas, final MapProjectionImpl projection) { + if (currentCoords == null) { + return; + } + + if (line == null) { + line = new Paint(); + line.setAntiAlias(true); + line.setStrokeWidth(width); + line.setColor(0x80EB391E); + } + + final Point pos = new Point(); + final Point dest = new Point(); + projection.toPixels(mapItemFactory.getGeoPointBase(currentCoords), pos); + projection.toPixels(mapItemFactory.getGeoPointBase(destinationCoords), dest); + + canvas.drawLine(pos.x, pos.y, dest.x, dest.y, line); + } +} diff --git a/main/src/cgeo/geocaching/maps/DistanceDrawer.java b/main/src/cgeo/geocaching/maps/DistanceDrawer.java new file mode 100644 index 0000000..f2d11bb --- /dev/null +++ b/main/src/cgeo/geocaching/maps/DistanceDrawer.java @@ -0,0 +1,131 @@ +package cgeo.geocaching.maps; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Units; +import cgeo.geocaching.maps.interfaces.MapViewImpl; + +import android.content.Context; +import android.graphics.BlurMaskFilter; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.location.Location; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +public class DistanceDrawer { + private Geopoint currentCoords; + private final Geopoint destinationCoords; + + private Paint paintBox = null; + private Paint paintBoxShadow = null; + private Paint paintText = null; + private BlurMaskFilter blurBoxShadow = null; + + private final boolean needsInvertedColors; + private float pixelDensity = 0; + private final float boxWidth, boxHeight, boxCornerRadius, boxShadowSize, boxPadding; + private final float textHeight, maxTextWidth; + private final float boxX, boxY; + + private String distanceText = null; + + public DistanceDrawer(final MapViewImpl mapView, final Geopoint destinationCoords) { + this.destinationCoords = destinationCoords; + + final DisplayMetrics metrics = new DisplayMetrics(); + final WindowManager windowManager = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE); + windowManager.getDefaultDisplay().getMetrics(metrics); + + pixelDensity = metrics.density; + + boxPadding = 2; + boxWidth = 100 * pixelDensity + 3 * boxPadding; + boxHeight = 30 * pixelDensity + 2 * boxPadding; + boxCornerRadius = 5 * pixelDensity; + boxShadowSize = 1 * pixelDensity; + textHeight = 20 * pixelDensity; + + needsInvertedColors = mapView.needsInvertedColors(); + boxX = metrics.widthPixels - boxWidth; + boxY = 0; + + maxTextWidth = boxWidth - 3 * boxPadding; + } + + public void setCoordinates(final Location coordinatesIn) { + currentCoords = new Geopoint(coordinatesIn); + + final float distance = currentCoords.distanceTo(destinationCoords); + distanceText = Units.getDistanceFromKilometers(distance); + } + + void drawDistance(final Canvas canvas) { + if (currentCoords == null) { + return; + } + + if (blurBoxShadow == null) { + blurBoxShadow = new BlurMaskFilter(3, BlurMaskFilter.Blur.NORMAL); + + paintBoxShadow = new Paint(); + paintBoxShadow.setAntiAlias(true); + paintBoxShadow.setMaskFilter(blurBoxShadow); + + paintBox = new Paint(); + paintBox.setAntiAlias(true); + + paintText = new Paint(); + paintText.setAntiAlias(true); + paintText.setTextAlign(Paint.Align.LEFT); + paintText.setTypeface(Typeface.DEFAULT_BOLD); + + final int TRANSPARENCY = 0x80000000; + if (needsInvertedColors) { + paintBoxShadow.setColor(0x000000 | TRANSPARENCY); + paintBox.setColor(0xFFFFFF | TRANSPARENCY); + paintText.setColor(0xFF000000); + } else { + paintBoxShadow.setColor(0xFFFFFF | TRANSPARENCY); + paintBox.setColor(0x000000 | TRANSPARENCY); + paintText.setColor(0xFFFFFFFF); + } + } + + /* Calculate text size */ + final Rect textBounds = new Rect(); + paintText.setTextSize(textHeight); + paintText.getTextBounds(distanceText, 0, distanceText.length(), textBounds); + while (textBounds.height() > maxTextWidth) { + paintText.setTextSize(paintText.getTextSize() - 1); + paintText.getTextBounds(distanceText, 0, distanceText.length(), textBounds); + } + + final float textX = (boxWidth - 3 * boxPadding - textBounds.width()) / 2 + boxX + 2 * boxPadding; + final float textY = (boxHeight + textBounds.height()) / 2 + boxY; + + /* Paint background box */ + canvas.drawRoundRect( + new RectF( + boxX - boxShadowSize, boxY - boxShadowSize - boxCornerRadius, + boxX + boxWidth + boxShadowSize + boxCornerRadius, boxY + boxHeight + boxShadowSize + ), + boxCornerRadius, boxCornerRadius, + paintBoxShadow + ); + canvas.drawRoundRect( + new RectF( + boxX, boxY - boxCornerRadius, + boxX + boxWidth + boxCornerRadius, boxY + boxHeight + ), + boxCornerRadius, boxCornerRadius, + paintBox + ); + + /* Paint distance */ + canvas.drawText(distanceText, textX, textY, paintText); + } +} diff --git a/main/src/cgeo/geocaching/maps/LiveMapStrategy.java b/main/src/cgeo/geocaching/maps/LiveMapStrategy.java deleted file mode 100644 index 16d5e8b..0000000 --- a/main/src/cgeo/geocaching/maps/LiveMapStrategy.java +++ /dev/null @@ -1,48 +0,0 @@ -package cgeo.geocaching.maps; - -import cgeo.geocaching.CgeoApplication; -import cgeo.geocaching.R; - -import java.util.EnumSet; - -/** - * Defines the strategy for the Live Map - */ -public interface LiveMapStrategy { - - public enum StrategyFlag { - LOAD_TILES, // 2x2 tiles filling the complete viewport - PARSE_TILES, // parse PNG images - SEARCH_NEARBY // searchByCoords() - } - - public enum Strategy { - FASTEST(1, EnumSet.of(StrategyFlag.LOAD_TILES), R.string.map_strategy_fastest), - FAST(2, EnumSet.of(StrategyFlag.LOAD_TILES, StrategyFlag.PARSE_TILES), R.string.map_strategy_fast), - AUTO(3, EnumSet.noneOf(StrategyFlag.class), R.string.map_strategy_auto), - DETAILED(4, EnumSet.allOf(StrategyFlag.class), R.string.map_strategy_detailed); - - public final int id; - public final EnumSet<StrategyFlag> flags; - private final int stringId; - - Strategy(int id, EnumSet<StrategyFlag> flags, int stringId) { - this.id = id; - this.flags = flags; - this.stringId = stringId; - } - - public static Strategy getById(final int id) { - for (Strategy strategy : Strategy.values()) { - if (strategy.id == id) { - return strategy; - } - } - return AUTO; - } - - public final String getL10n() { - return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); - } - } -} diff --git a/main/src/cgeo/geocaching/maps/LivemapStrategy.java b/main/src/cgeo/geocaching/maps/LivemapStrategy.java new file mode 100644 index 0000000..c135fc8 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/LivemapStrategy.java @@ -0,0 +1,45 @@ +package cgeo.geocaching.maps; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.R; + +import java.util.EnumSet; + +/** + * Defines the strategy for the Live Map + */ +public enum LivemapStrategy { + FASTEST(1, EnumSet.of(Flag.LOAD_TILES), R.string.map_strategy_fastest), + FAST(2, EnumSet.of(Flag.LOAD_TILES, Flag.PARSE_TILES), R.string.map_strategy_fast), + AUTO(3, EnumSet.noneOf(Flag.class), R.string.map_strategy_auto), + DETAILED(4, EnumSet.allOf(Flag.class), R.string.map_strategy_detailed); + + public final int id; + public final EnumSet<Flag> flags; + private final int stringId; + + public enum Flag { + LOAD_TILES, // 2x2 tiles filling the complete viewport + PARSE_TILES, // parse PNG images + SEARCH_NEARBY // searchByCoords() + } + + LivemapStrategy(final int id, final EnumSet<Flag> flags, final int stringId) { + this.id = id; + this.flags = flags; + this.stringId = stringId; + } + + public static LivemapStrategy getById(final int id) { + for (final LivemapStrategy strategy : LivemapStrategy.values()) { + if (strategy.id == id) { + return strategy; + } + } + return AUTO; + } + + public final String getL10n() { + return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); + } +} diff --git a/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java b/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java index 63fcd73..9a6e4b9 100644 --- a/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java +++ b/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java @@ -1,5 +1,8 @@ package cgeo.geocaching.maps; +import cgeo.geocaching.DataStore; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.maps.interfaces.GeneralOverlay; import cgeo.geocaching.maps.interfaces.MapProjectionImpl; import cgeo.geocaching.maps.interfaces.MapViewImpl; @@ -16,22 +19,40 @@ public class PositionAndScaleOverlay implements GeneralOverlay { PositionDrawer positionDrawer = null; ScaleDrawer scaleDrawer = null; + DirectionDrawer directionDrawer = null; + DistanceDrawer distanceDrawer = null; - public PositionAndScaleOverlay(OverlayImpl ovlImpl) { + public PositionAndScaleOverlay(final OverlayImpl ovlImpl, final MapViewImpl mapView, final Geopoint coords, final String geocode) { this.ovlImpl = ovlImpl; positionDrawer = new PositionDrawer(); scaleDrawer = new ScaleDrawer(); + + if (coords != null) { + directionDrawer = new DirectionDrawer(coords); + distanceDrawer = new DistanceDrawer(mapView, coords); + } else if (geocode != null) { + final Viewport bounds = DataStore.getBounds(geocode); + if (bounds != null) { + directionDrawer = new DirectionDrawer(bounds.center); + distanceDrawer = new DistanceDrawer(mapView, bounds.center); + } + } } - public void setCoordinates(Location coordinatesIn) { + public void setCoordinates(final Location coordinatesIn) { positionDrawer.setCoordinates(coordinatesIn); + if (directionDrawer != null) { + directionDrawer.setCoordinates(coordinatesIn); + distanceDrawer.setCoordinates(coordinatesIn); + } + } public Location getCoordinates() { return positionDrawer.getCoordinates(); } - public void setHeading(float bearingNow) { + public void setHeading(final float bearingNow) { positionDrawer.setHeading(bearingNow); } @@ -40,21 +61,27 @@ public class PositionAndScaleOverlay implements GeneralOverlay { } @Override - public void drawOverlayBitmap(Canvas canvas, Point drawPosition, - MapProjectionImpl projection, byte drawZoomLevel) { + public void drawOverlayBitmap(final Canvas canvas, final Point drawPosition, + final MapProjectionImpl projection, final byte drawZoomLevel) { drawInternal(canvas, projection, getOverlayImpl().getMapViewImpl()); } @Override - public void draw(Canvas canvas, MapViewImpl mapView, boolean shadow) { + public void draw(final Canvas canvas, final MapViewImpl mapView, final boolean shadow) { drawInternal(canvas, mapView.getMapProjection(), mapView); } - private void drawInternal(Canvas canvas, MapProjectionImpl projection, MapViewImpl mapView) { + private void drawInternal(final Canvas canvas, final MapProjectionImpl projection, final MapViewImpl mapView) { + if (directionDrawer != null) { + directionDrawer.drawDirection(canvas, projection); + } positionDrawer.drawPosition(canvas, projection); scaleDrawer.drawScale(canvas, mapView); + if (distanceDrawer != null) { + distanceDrawer.drawDistance(canvas); + } } @Override @@ -66,7 +93,7 @@ public class PositionAndScaleOverlay implements GeneralOverlay { return positionDrawer.getHistory(); } - public void setHistory(ArrayList<Location> history) { + public void setHistory(final ArrayList<Location> history) { positionDrawer.setHistory(history); } } diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleMapView.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapView.java index d474e1d..f3b7e9e 100644 --- a/main/src/cgeo/geocaching/maps/google/v1/GoogleMapView.java +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapView.java @@ -2,6 +2,7 @@ package cgeo.geocaching.maps.google.v1; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.location.Viewport; import cgeo.geocaching.maps.CachesOverlay; import cgeo.geocaching.maps.PositionAndScaleOverlay; @@ -36,22 +37,22 @@ public class GoogleMapView extends MapView implements MapViewImpl { private OnMapDragListener onDragListener; private final GoogleMapController mapController = new GoogleMapController(getController()); - public GoogleMapView(Context context, AttributeSet attrs) { + public GoogleMapView(final Context context, final AttributeSet attrs) { super(context, attrs); initialize(context); } - public GoogleMapView(Context context, AttributeSet attrs, int defStyle) { + public GoogleMapView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); initialize(context); } - public GoogleMapView(Context context, String apiKey) { + public GoogleMapView(final Context context, final String apiKey) { super(context, apiKey); initialize(context); } - private void initialize(Context context) { + private void initialize(final Context context) { if (isInEditMode()) { return; } @@ -66,16 +67,16 @@ public class GoogleMapView extends MapView implements MapViewImpl { } super.draw(canvas); - } catch (Exception e) { + } catch (final Exception e) { Log.e("GoogleMapView.draw", e); } } @Override - public void displayZoomControls(boolean takeFocus) { + public void displayZoomControls(final boolean takeFocus) { try { // Push zoom controls to the right - FrameLayout.LayoutParams zoomParams = new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + final FrameLayout.LayoutParams zoomParams = new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); zoomParams.gravity = Gravity.RIGHT; // The call to retrieve the zoom buttons controller is undocumented and works so far on all devices // supported by Google Play, but fails at least on one Jolla. @@ -83,9 +84,9 @@ public class GoogleMapView extends MapView implements MapViewImpl { controller.getZoomControls().setLayoutParams(zoomParams); super.displayZoomControls(takeFocus); - } catch (NoSuchMethodException ignored) { + } catch (final NoSuchMethodException ignored) { Log.w("GoogleMapView.displayZoomControls: unable to explicitly place the zoom buttons"); - } catch (Exception e) { + } catch (final Exception e) { Log.e("GoogleMapView.displayZoomControls", e); } } @@ -98,7 +99,7 @@ public class GoogleMapView extends MapView implements MapViewImpl { @Override @NonNull public GeoPointImpl getMapViewCenter() { - GeoPoint point = getMapCenter(); + final GeoPoint point = getMapCenter(); return new GoogleGeoPoint(point.getLatitudeE6(), point.getLongitudeE6()); } @@ -118,17 +119,17 @@ public class GoogleMapView extends MapView implements MapViewImpl { } @Override - public CachesOverlay createAddMapOverlay(Context context, Drawable drawable) { + public CachesOverlay createAddMapOverlay(final Context context, final Drawable drawable) { - GoogleCacheOverlay ovl = new GoogleCacheOverlay(context, drawable); + final GoogleCacheOverlay ovl = new GoogleCacheOverlay(context, drawable); getOverlays().add(ovl); return ovl.getBase(); } @Override - public PositionAndScaleOverlay createAddPositionAndScaleOverlay() { + public PositionAndScaleOverlay createAddPositionAndScaleOverlay(final Geopoint coords, final String geocode) { - GoogleOverlay ovl = new GoogleOverlay(); + final GoogleOverlay ovl = new GoogleOverlay(this, coords, geocode); getOverlays().add(ovl); return (PositionAndScaleOverlay) ovl.getBase(); } @@ -144,21 +145,21 @@ public class GoogleMapView extends MapView implements MapViewImpl { } @Override - public void repaintRequired(GeneralOverlay overlay) { + public void repaintRequired(final GeneralOverlay overlay) { invalidate(); } @Override - public void setOnDragListener(OnMapDragListener onDragListener) { + public void setOnDragListener(final OnMapDragListener onDragListener) { this.onDragListener = onDragListener; } @Override - public boolean onTouchEvent(MotionEvent ev) { + public boolean onTouchEvent(final MotionEvent ev) { try { gestureDetector.onTouchEvent(ev); return super.onTouchEvent(ev); - } catch (Exception e) { + } catch (final Exception e) { Log.e("GoogleMapView.onTouchEvent", e); } return false; @@ -166,7 +167,7 @@ public class GoogleMapView extends MapView implements MapViewImpl { private class GestureListener extends SimpleOnGestureListener { @Override - public boolean onDoubleTap(MotionEvent e) { + public boolean onDoubleTap(final MotionEvent e) { getController().zoomInFixing((int) e.getX(), (int) e.getY()); if (onDragListener != null) { onDragListener.onDrag(); @@ -175,8 +176,8 @@ public class GoogleMapView extends MapView implements MapViewImpl { } @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, - float distanceX, float distanceY) { + public boolean onScroll(final MotionEvent e1, final MotionEvent e2, + final float distanceX, final float distanceY) { if (onDragListener != null) { onDragListener.onDrag(); } diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleOverlay.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleOverlay.java index 40a5539..415de1f 100644 --- a/main/src/cgeo/geocaching/maps/google/v1/GoogleOverlay.java +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleOverlay.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.google.v1; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.PositionAndScaleOverlay; import cgeo.geocaching.maps.interfaces.GeneralOverlay; import cgeo.geocaching.maps.interfaces.MapViewImpl; @@ -16,14 +17,14 @@ import java.util.concurrent.locks.ReentrantLock; public class GoogleOverlay extends Overlay implements OverlayImpl { private PositionAndScaleOverlay overlayBase = null; - private Lock lock = new ReentrantLock(); + private final Lock lock = new ReentrantLock(); - public GoogleOverlay() { - overlayBase = new PositionAndScaleOverlay(this); + public GoogleOverlay(final MapViewImpl mapView, final Geopoint coords, final String geocode) { + overlayBase = new PositionAndScaleOverlay(this, mapView, coords, geocode); } @Override - public void draw(Canvas canvas, MapView mapView, boolean shadow) { + public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) { super.draw(canvas, mapView, shadow); if (overlayBase != null) { diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java b/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java index 3596d5f..1e69b44 100644 --- a/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java +++ b/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java @@ -33,5 +33,8 @@ public interface MapActivityImpl { boolean superOnOptionsItemSelected(MenuItem item); + /** + * called from the pseudo actionbar layout + */ 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 0560ad4..1876dfc 100644 --- a/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java +++ b/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.interfaces; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.location.Viewport; import cgeo.geocaching.maps.CachesOverlay; import cgeo.geocaching.maps.PositionAndScaleOverlay; @@ -46,7 +47,7 @@ public interface MapViewImpl { CachesOverlay createAddMapOverlay(Context context, Drawable drawable); - PositionAndScaleOverlay createAddPositionAndScaleOverlay(); + PositionAndScaleOverlay createAddPositionAndScaleOverlay(final Geopoint coords, final String geocode); void setMapSource(); diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java index 73d87b0..71bf583 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java @@ -1,6 +1,7 @@ package cgeo.geocaching.maps.mapsforge; import cgeo.geocaching.R; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.location.Viewport; import cgeo.geocaching.maps.CachesOverlay; import cgeo.geocaching.maps.PositionAndScaleOverlay; @@ -40,12 +41,12 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { private OnMapDragListener onDragListener; private final MapsforgeMapController mapController = new MapsforgeMapController(getController(), getMapGenerator().getZoomLevelMax()); - public MapsforgeMapView(Context context, AttributeSet attrs) { + public MapsforgeMapView(final Context context, final AttributeSet attrs) { super(context, attrs); initialize(context); } - private void initialize(Context context) { + private void initialize(final Context context) { if (isInEditMode()) { return; } @@ -56,7 +57,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } @Override - public void draw(@NonNull Canvas canvas) { + public void draw(@NonNull final Canvas canvas) { try { // Google Maps and OSM Maps use different zoom levels for the same view. // Here we don't want the Google Maps compatible zoom level, but the actual one. @@ -65,13 +66,13 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } super.draw(canvas); - } catch (Exception e) { + } catch (final Exception e) { Log.e("MapsforgeMapView.draw", e); } } @Override - public void displayZoomControls(boolean takeFocus) { + public void displayZoomControls(final boolean takeFocus) { // nothing to do here } @@ -83,7 +84,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { @Override @NonNull public GeoPointImpl getMapViewCenter() { - GeoPoint point = getMapPosition().getMapCenter(); + final GeoPoint point = getMapPosition().getMapCenter(); return new MapsforgeGeoPoint(point.latitudeE6, point.longitudeE6); } @@ -103,16 +104,16 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } @Override - public CachesOverlay createAddMapOverlay(Context context, Drawable drawable) { + public CachesOverlay createAddMapOverlay(final Context context, final Drawable drawable) { - MapsforgeCacheOverlay ovl = new MapsforgeCacheOverlay(context, drawable); + final MapsforgeCacheOverlay ovl = new MapsforgeCacheOverlay(context, drawable); getOverlays().add(ovl); return ovl.getBase(); } @Override - public PositionAndScaleOverlay createAddPositionAndScaleOverlay() { - MapsforgeOverlay ovl = new MapsforgeOverlay(); + public PositionAndScaleOverlay createAddPositionAndScaleOverlay(final Geopoint coords, final String geocode) { + final MapsforgeOverlay ovl = new MapsforgeOverlay(this, coords, geocode); getOverlays().add(ovl); return (PositionAndScaleOverlay) ovl.getBase(); } @@ -122,12 +123,12 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { int span = 0; - Projection projection = getProjection(); + final Projection projection = getProjection(); if (projection != null && getHeight() > 0) { - GeoPoint low = projection.fromPixels(0, 0); - GeoPoint high = projection.fromPixels(0, getHeight()); + final GeoPoint low = projection.fromPixels(0, 0); + final GeoPoint high = projection.fromPixels(0, getHeight()); if (low != null && high != null) { span = Math.abs(high.latitudeE6 - low.latitudeE6); @@ -142,11 +143,11 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { int span = 0; - Projection projection = getProjection(); + final Projection projection = getProjection(); if (projection != null && getWidth() > 0) { - GeoPoint low = projection.fromPixels(0, 0); - GeoPoint high = projection.fromPixels(getWidth(), 0); + final GeoPoint low = projection.fromPixels(0, 0); + final GeoPoint high = projection.fromPixels(getWidth(), 0); if (low != null && high != null) { span = Math.abs(high.longitudeE6 - low.longitudeE6); @@ -191,7 +192,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { newMapType = ((MapsforgeMapSource) mapSource).getGenerator(); } - MapGenerator mapGenerator = MapGeneratorFactory.createMapGenerator(newMapType); + final MapGenerator mapGenerator = MapGeneratorFactory.createMapGenerator(newMapType); // When swapping map sources, make sure we aren't exceeding max zoom. See bug #1535 final int maxZoom = mapGenerator.getZoomLevelMax(); @@ -230,11 +231,11 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { @Override public void setMapTheme() { - String customRenderTheme = Settings.getCustomRenderThemeFilePath(); + final String customRenderTheme = Settings.getCustomRenderThemeFilePath(); if (StringUtils.isNotEmpty(customRenderTheme)) { try { setRenderTheme(new File(customRenderTheme)); - } catch (FileNotFoundException ignored) { + } catch (final FileNotFoundException ignored) { Toast.makeText( getContext(), getContext().getResources().getString(R.string.warn_rendertheme_missing), @@ -247,38 +248,38 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } @Override - public void repaintRequired(GeneralOverlay overlay) { + public void repaintRequired(final GeneralOverlay overlay) { if (null == overlay) { invalidate(); } else { try { - Overlay ovl = (Overlay) overlay.getOverlayImpl(); + final Overlay ovl = (Overlay) overlay.getOverlayImpl(); if (ovl != null) { ovl.requestRedraw(); } - } catch (Exception e) { + } catch (final Exception e) { Log.e("MapsforgeMapView.repaintRequired", e); } } } @Override - public void setOnDragListener(OnMapDragListener onDragListener) { + public void setOnDragListener(final OnMapDragListener onDragListener) { this.onDragListener = onDragListener; } @Override - public boolean onTouchEvent(MotionEvent ev) { + public boolean onTouchEvent(final MotionEvent ev) { gestureDetector.onTouchEvent(ev); return super.onTouchEvent(ev); } private class GestureListener extends SimpleOnGestureListener { @Override - public boolean onDoubleTap(MotionEvent e) { + public boolean onDoubleTap(final MotionEvent e) { if (onDragListener != null) { onDragListener.onDrag(); } @@ -286,8 +287,8 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, - float distanceX, float distanceY) { + public boolean onScroll(final MotionEvent e1, final MotionEvent e2, + final float distanceX, final float distanceY) { if (onDragListener != null) { onDragListener.onDrag(); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java index 3df4ab0..3926eb6 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.mapsforge; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.PositionAndScaleOverlay; import cgeo.geocaching.maps.interfaces.GeneralOverlay; import cgeo.geocaching.maps.interfaces.MapViewImpl; @@ -17,15 +18,15 @@ import java.util.concurrent.locks.ReentrantLock; public class MapsforgeOverlay extends Overlay implements OverlayImpl { private PositionAndScaleOverlay overlayBase = null; - private Lock lock = new ReentrantLock(); + private final Lock lock = new ReentrantLock(); - public MapsforgeOverlay() { - overlayBase = new PositionAndScaleOverlay(this); + public MapsforgeOverlay(final MapViewImpl mapView, final Geopoint coords, final String geocode) { + overlayBase = new PositionAndScaleOverlay(this, mapView, coords, geocode); } @Override - protected void drawOverlayBitmap(Canvas canvas, Point drawPosition, - Projection projection, byte drawZoomLevel) { + protected void drawOverlayBitmap(final Canvas canvas, final Point drawPosition, + final Projection projection, final byte drawZoomLevel) { if (overlayBase != null) { overlayBase.drawOverlayBitmap(canvas, drawPosition, new MapsforgeMapProjection(projection), drawZoomLevel); diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java index 42c55fe..af9b756 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java @@ -1,6 +1,7 @@ package cgeo.geocaching.maps.mapsforge.v024; import cgeo.geocaching.R; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.location.Viewport; import cgeo.geocaching.maps.CachesOverlay; import cgeo.geocaching.maps.PositionAndScaleOverlay; @@ -34,12 +35,12 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { private OnMapDragListener onDragListener; private final MapsforgeMapController mapController = new MapsforgeMapController(getController(), getMaxZoomLevel()); - public MapsforgeMapView024(Context context, AttributeSet attrs) { + public MapsforgeMapView024(final Context context, final AttributeSet attrs) { super(context, attrs); initialize(context); } - private void initialize(Context context) { + private void initialize(final Context context) { if (isInEditMode()) { return; } @@ -47,7 +48,7 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { } @Override - public void draw(@NonNull Canvas canvas) { + public void draw(@NonNull final Canvas canvas) { try { // Google Maps and OSM Maps use different zoom levels for the same view. // Here we don't want the Google Maps compatible zoom level, but the actual one. @@ -56,13 +57,13 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { } super.draw(canvas); - } catch (Exception e) { + } catch (final Exception e) { Log.e("MapsforgeMapView024.draw", e); } } @Override - public void displayZoomControls(boolean takeFocus) { + public void displayZoomControls(final boolean takeFocus) { // nothing to do here } @@ -74,7 +75,7 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { @Override @NonNull public GeoPointImpl getMapViewCenter() { - GeoPoint point = getMapCenter(); + final GeoPoint point = getMapCenter(); return new MapsforgeGeoPoint(point.getLatitudeE6(), point.getLongitudeE6()); } @@ -94,16 +95,16 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { } @Override - public CachesOverlay createAddMapOverlay(Context context, Drawable drawable) { + public CachesOverlay createAddMapOverlay(final Context context, final Drawable drawable) { - MapsforgeCacheOverlay ovl = new MapsforgeCacheOverlay(context, drawable); + final MapsforgeCacheOverlay ovl = new MapsforgeCacheOverlay(context, drawable); getOverlays().add(ovl); return ovl.getBase(); } @Override - public PositionAndScaleOverlay createAddPositionAndScaleOverlay() { - MapsforgeOverlay ovl = new MapsforgeOverlay(); + public PositionAndScaleOverlay createAddPositionAndScaleOverlay(final Geopoint coords, final String geocode) { + final MapsforgeOverlay ovl = new MapsforgeOverlay(this, coords, geocode); getOverlays().add(ovl); return (PositionAndScaleOverlay) ovl.getBase(); } @@ -113,12 +114,12 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { int span = 0; - Projection projection = getProjection(); + final Projection projection = getProjection(); if (projection != null && getHeight() > 0) { - GeoPoint low = projection.fromPixels(0, 0); - GeoPoint high = projection.fromPixels(0, getHeight()); + final GeoPoint low = projection.fromPixels(0, 0); + final GeoPoint high = projection.fromPixels(0, getHeight()); if (low != null && high != null) { span = Math.abs(high.getLatitudeE6() - low.getLatitudeE6()); @@ -133,11 +134,11 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { int span = 0; - Projection projection = getProjection(); + final Projection projection = getProjection(); if (projection != null && getWidth() > 0) { - GeoPoint low = projection.fromPixels(0, 0); - GeoPoint high = projection.fromPixels(getWidth(), 0); + final GeoPoint low = projection.fromPixels(0, 0); + final GeoPoint high = projection.fromPixels(getWidth(), 0); if (low != null && high != null) { span = Math.abs(high.getLongitudeE6() - low.getLongitudeE6()); @@ -188,38 +189,38 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { } @Override - public void repaintRequired(GeneralOverlay overlay) { + public void repaintRequired(final GeneralOverlay overlay) { if (null == overlay) { invalidate(); } else { try { - Overlay ovl = (Overlay) overlay.getOverlayImpl(); + final Overlay ovl = (Overlay) overlay.getOverlayImpl(); if (ovl != null) { ovl.requestRedraw(); } - } catch (Exception e) { + } catch (final Exception e) { Log.e("MapsforgeMapView024.repaintRequired", e); } } } @Override - public void setOnDragListener(OnMapDragListener onDragListener) { + public void setOnDragListener(final OnMapDragListener onDragListener) { this.onDragListener = onDragListener; } @Override - public boolean onTouchEvent(MotionEvent ev) { + public boolean onTouchEvent(final MotionEvent ev) { gestureDetector.onTouchEvent(ev); return super.onTouchEvent(ev); } private class GestureListener extends SimpleOnGestureListener { @Override - public boolean onDoubleTap(MotionEvent e) { + public boolean onDoubleTap(final MotionEvent e) { if (onDragListener != null) { onDragListener.onDrag(); } @@ -227,8 +228,8 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { } @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, - float distanceX, float distanceY) { + public boolean onScroll(final MotionEvent e1, final MotionEvent e2, + final float distanceX, final float distanceY) { if (onDragListener != null) { onDragListener.onDrag(); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java index bfb3548..fda6dc1 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.mapsforge.v024; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.PositionAndScaleOverlay; import cgeo.geocaching.maps.interfaces.GeneralOverlay; import cgeo.geocaching.maps.interfaces.MapViewImpl; @@ -17,15 +18,15 @@ import java.util.concurrent.locks.ReentrantLock; public class MapsforgeOverlay extends Overlay implements OverlayImpl { private PositionAndScaleOverlay overlayBase = null; - private Lock lock = new ReentrantLock(); + private final Lock lock = new ReentrantLock(); - public MapsforgeOverlay() { - overlayBase = new PositionAndScaleOverlay(this); + public MapsforgeOverlay(final MapViewImpl mapView, final Geopoint coords, final String geocode) { + overlayBase = new PositionAndScaleOverlay(this, mapView, coords, geocode); } @Override - protected void drawOverlayBitmap(Canvas canvas, Point drawPosition, - Projection projection, byte drawZoomLevel) { + protected void drawOverlayBitmap(final Canvas canvas, final Point drawPosition, + final Projection projection, final byte drawZoomLevel) { if (overlayBase != null) { overlayBase.drawOverlayBitmap(canvas, drawPosition, new MapsforgeMapProjection(projection), drawZoomLevel); diff --git a/main/src/cgeo/geocaching/playservices/LocationProvider.java b/main/src/cgeo/geocaching/playservices/LocationProvider.java index 9d193b5..027ae29 100644 --- a/main/src/cgeo/geocaching/playservices/LocationProvider.java +++ b/main/src/cgeo/geocaching/playservices/LocationProvider.java @@ -102,12 +102,12 @@ public class LocationProvider implements GoogleApiClient.ConnectionCallbacks, Go // no less precise than 20 meters. final Observable<GeoData> untilPreciseEnoughObservable = lowPowerObservable.mergeWith(highPowerObservable.delaySubscription(6, TimeUnit.SECONDS)) - .lift(RxUtils.operatorTakeUntil(new Func1<GeoData, Boolean>() { + .takeUntil(new Func1<GeoData, Boolean>() { @Override public Boolean call(final GeoData geoData) { return geoData.getAccuracy() <= 20; } - })); + }); // After sending the last known location, try to get a precise location then use the low-power mode. If no // location information is given for 25 seconds (if the network location is turned off for example), get diff --git a/main/src/cgeo/geocaching/sensors/RotationProvider.java b/main/src/cgeo/geocaching/sensors/RotationProvider.java index 02dbc8c..c63e39f 100644 --- a/main/src/cgeo/geocaching/sensors/RotationProvider.java +++ b/main/src/cgeo/geocaching/sensors/RotationProvider.java @@ -43,6 +43,7 @@ public class RotationProvider extends LooperCallbacks<Float> implements SensorEv return ((SensorManager) context.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) != null; } + @TargetApi(19) public static boolean hasGeomagneticRotationSensor(final Context context) { return ((SensorManager) context.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR) != null; } diff --git a/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java b/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java index 1930c17..4a78037 100644 --- a/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java +++ b/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java @@ -42,7 +42,6 @@ public abstract class AbstractAttributeBasedPrefence extends Preference { /** * Evaluate the attributes which where requested in {@link AbstractAttributeBasedPrefence#getAttributeNames()}. * - * @param values */ protected abstract void processAttributeValues(TypedArray values); diff --git a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java index ed09757..6130c4c 100644 --- a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java +++ b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java @@ -14,7 +14,6 @@ import rx.Observable; import rx.android.app.AppObservable; import rx.functions.Action1; import rx.functions.Func0; -import rx.util.async.Async; import android.app.ProgressDialog; import android.content.Context; @@ -74,10 +73,10 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab loginDialog.setCancelable(false); Cookies.clearCookies(); - AppObservable.bindActivity(settingsActivity, Async.start(new Func0<ImmutablePair<StatusCode, Observable<Drawable>>>() { + AppObservable.bindActivity(settingsActivity, Observable.defer(new Func0<Observable<ImmutablePair<StatusCode, Observable<Drawable>>>>() { @Override - public ImmutablePair<StatusCode, Observable<Drawable>> call() { - return login(); + public Observable<ImmutablePair<StatusCode, Observable<Drawable>>> call() { + return Observable.just(login()); } })).subscribeOn(RxUtils.networkScheduler).subscribe(new Action1<ImmutablePair<StatusCode, Observable<Drawable>>>() { @Override diff --git a/main/src/cgeo/geocaching/settings/InfoPreference.java b/main/src/cgeo/geocaching/settings/InfoPreference.java index 8040a62..b1c7fed 100644 --- a/main/src/cgeo/geocaching/settings/InfoPreference.java +++ b/main/src/cgeo/geocaching/settings/InfoPreference.java @@ -91,8 +91,6 @@ public class InfoPreference extends AbstractAttributeBasedPrefence { /** * Add an info icon at the left hand side of the preference. * - * @param parent - * @return */ private View addInfoIcon(ViewGroup parent) { View preferenceView = super.onCreateView(parent); diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java index 0b54fe1..3d47f8b 100644 --- a/main/src/cgeo/geocaching/settings/Settings.java +++ b/main/src/cgeo/geocaching/settings/Settings.java @@ -11,8 +11,8 @@ import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.list.StoredList; import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.CGeoMap.MapMode; -import cgeo.geocaching.maps.LiveMapStrategy.Strategy; import cgeo.geocaching.maps.MapProviderFactory; +import cgeo.geocaching.maps.LivemapStrategy; import cgeo.geocaching.maps.google.v1.GoogleMapProvider; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import cgeo.geocaching.maps.interfaces.MapProvider; @@ -188,7 +188,7 @@ public class Settings { e.putInt(getKey(R.string.pref_lastdetailspage), prefsV0.getInt(getKey(R.string.pref_lastdetailspage), 1)); e.putInt(getKey(R.string.pref_defaultNavigationTool), prefsV0.getInt(getKey(R.string.pref_defaultNavigationTool), NavigationAppsEnum.COMPASS.id)); e.putInt(getKey(R.string.pref_defaultNavigationTool2), prefsV0.getInt(getKey(R.string.pref_defaultNavigationTool2), NavigationAppsEnum.INTERNAL_MAP.id)); - e.putInt(getKey(R.string.pref_livemapstrategy), prefsV0.getInt(getKey(R.string.pref_livemapstrategy), Strategy.AUTO.id)); + e.putInt(getKey(R.string.pref_livemapstrategy), prefsV0.getInt(getKey(R.string.pref_livemapstrategy), LivemapStrategy.AUTO.id)); e.putBoolean(getKey(R.string.pref_debug), prefsV0.getBoolean(getKey(R.string.pref_debug), false)); e.putInt(getKey(R.string.pref_livemaphintshowcount), prefsV0.getInt(getKey(R.string.pref_livemaphintshowcount), 0)); @@ -906,11 +906,11 @@ public class Settings { String.valueOf(NavigationAppsEnum.INTERNAL_MAP.id))); } - public static Strategy getLiveMapStrategy() { - return Strategy.getById(getInt(R.string.pref_livemapstrategy, Strategy.AUTO.id)); + public static LivemapStrategy getLiveMapStrategy() { + return LivemapStrategy.getById(getInt(R.string.pref_livemapstrategy, LivemapStrategy.AUTO.id)); } - public static void setLiveMapStrategy(final Strategy strategy) { + public static void setLiveMapStrategy(final LivemapStrategy strategy) { putInt(R.string.pref_livemapstrategy, strategy.id); } diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java index 99de30f..776b621 100644 --- a/main/src/cgeo/geocaching/settings/SettingsActivity.java +++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java @@ -327,13 +327,14 @@ public class SettingsActivity extends PreferenceActivity { backup.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(final Preference preference) { - return DatabaseBackupUtils.createBackup(SettingsActivity.this, new Runnable() { + DatabaseBackupUtils.createBackup(SettingsActivity.this, new Runnable() { @Override public void run() { VALUE_CHANGE_LISTENER.onPreferenceChange(SettingsActivity.this.getPreference(R.string.pref_fakekey_preference_backup_info), ""); } }); + return true; } }); diff --git a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java index a0c5a9f..d7c46e1 100644 --- a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java +++ b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java @@ -35,9 +35,11 @@ abstract class AbstractCacheComparator implements CacheComparator { * Check necessary preconditions (like missing fields) before running the comparison itself. * Caches not filling the conditions will be placed last, sorted by Geocode. * - * The default returns <code>true</code> and can be overridden if needed in child classes. - * + * The default implementation returns <code>true</code> and can be overridden if needed in sub classes. + * * @param cache + * the cache to be sorted + * * @return <code>true</code> if the cache holds the necessary data to be compared meaningfully */ @SuppressWarnings("static-method") @@ -51,8 +53,6 @@ abstract class AbstractCacheComparator implements CacheComparator { * A cache is smaller than another cache if it is desirable to show it first when presented to the user. * For example, a highly rated cache must be considered smaller than a poorly rated one. * - * @param cache1 - * @param cache2 * @return an integer < 0 if cache1 is less than cache2, 0 if they are equal, and > 0 if cache1 is greater than * cache2. */ diff --git a/main/src/cgeo/geocaching/sorting/DateComparator.java b/main/src/cgeo/geocaching/sorting/DateComparator.java index af50213..347eb44 100644 --- a/main/src/cgeo/geocaching/sorting/DateComparator.java +++ b/main/src/cgeo/geocaching/sorting/DateComparator.java @@ -17,13 +17,8 @@ class DateComparator extends AbstractCacheComparator { final Date date2 = cache2.getHiddenDate(); if (date1 != null && date2 != null) { final int dateDifference = date1.compareTo(date2); - // for equal dates, sort by distance if (dateDifference == 0) { - final ArrayList<Geocache> list = new ArrayList<>(); - list.add(cache1); - list.add(cache2); - final DistanceComparator distanceComparator = new DistanceComparator(Sensors.getInstance().currentGeo().getCoords(), list); - return distanceComparator.compare(cache1, cache2); + return sortSameDate(cache1, cache2); } return dateDifference; } @@ -35,4 +30,13 @@ class DateComparator extends AbstractCacheComparator { } return 0; } + + @SuppressWarnings("static-method") + protected int sortSameDate(final Geocache cache1, final Geocache cache2) { + final ArrayList<Geocache> list = new ArrayList<>(); + list.add(cache1); + list.add(cache2); + final DistanceComparator distanceComparator = new DistanceComparator(Sensors.getInstance().currentGeo().getCoords(), list); + return distanceComparator.compare(cache1, cache2); + } } diff --git a/main/src/cgeo/geocaching/sorting/EventDateComparator.java b/main/src/cgeo/geocaching/sorting/EventDateComparator.java index 197946a..efeeb5d 100644 --- a/main/src/cgeo/geocaching/sorting/EventDateComparator.java +++ b/main/src/cgeo/geocaching/sorting/EventDateComparator.java @@ -1,5 +1,7 @@ package cgeo.geocaching.sorting; +import cgeo.geocaching.Geocache; + /** * Compares caches by date. Used only for event caches. */ @@ -7,4 +9,16 @@ public class EventDateComparator extends DateComparator { final static public EventDateComparator singleton = new EventDateComparator(); + @Override + protected int sortSameDate(final Geocache left, final Geocache right) { + return compare(left.guessEventTimeMinutes(), right.guessEventTimeMinutes()); + } + + /** + * copy of {@link Integer#compare(int, int)}, as that is not available on lower API levels + * + */ + private static int compare(final int left, final int right) { + return left < right ? -1 : (left == right ? 0 : 1); + } } diff --git a/main/src/cgeo/geocaching/sorting/NameComparator.java b/main/src/cgeo/geocaching/sorting/NameComparator.java index 376c8b9..ab7bbcb 100644 --- a/main/src/cgeo/geocaching/sorting/NameComparator.java +++ b/main/src/cgeo/geocaching/sorting/NameComparator.java @@ -1,15 +1,20 @@ package cgeo.geocaching.sorting; import cgeo.geocaching.Geocache; +import cgeo.geocaching.utils.TextUtils; import org.apache.commons.lang3.StringUtils; +import java.text.Collator; + /** * sorts caches by name * */ class NameComparator extends AbstractCacheComparator { + private final Collator collator = TextUtils.getCollator(); + @Override protected boolean canCompare(final Geocache cache) { return StringUtils.isNotBlank(cache.getName()); @@ -17,6 +22,6 @@ class NameComparator extends AbstractCacheComparator { @Override protected int compareCaches(final Geocache cache1, final Geocache cache2) { - return cache1.getNameForSorting().compareToIgnoreCase(cache2.getNameForSorting()); + return collator.compare(cache1.getNameForSorting(), cache2.getNameForSorting()); } } diff --git a/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java index 306c686..60e8b2d 100644 --- a/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java +++ b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java @@ -14,7 +14,6 @@ import android.view.ViewGroup; /** * View creator which destroys the created view on every {@link #notifyDataSetChanged()}. * - * @param <ViewClass> */ public abstract class AbstractCachingPageViewCreator<ViewClass extends View> implements PageViewCreator { diff --git a/main/src/cgeo/geocaching/ui/AbstractMenuActionProvider.java b/main/src/cgeo/geocaching/ui/AbstractMenuActionProvider.java new file mode 100644 index 0000000..fbea675 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/AbstractMenuActionProvider.java @@ -0,0 +1,24 @@ +package cgeo.geocaching.ui; + +import android.content.Context; +import android.support.v4.view.ActionProvider; +import android.view.View; + +public abstract class AbstractMenuActionProvider extends ActionProvider { + + public AbstractMenuActionProvider(final Context context) { + super(context); + } + + @Override + public boolean hasSubMenu() { + return true; + } + + @Override + public View onCreateActionView() { + // must return null, otherwise the menu will not work + return null; + } + +} diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java index ebbe23f..d9daa1d 100644 --- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java +++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java @@ -18,7 +18,7 @@ import cgeo.geocaching.sorting.EventDateComparator; import cgeo.geocaching.sorting.InverseComparator; import cgeo.geocaching.sorting.VisitComparator; import cgeo.geocaching.utils.AngleUtils; -import cgeo.geocaching.utils.DateUtils; +import cgeo.geocaching.utils.CalendarUtils; import cgeo.geocaching.utils.Formatter; import cgeo.geocaching.utils.Log; @@ -112,7 +112,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { @InjectView(R.id.distance) protected DistanceView distance; @InjectView(R.id.favorite) protected TextView favorite; @InjectView(R.id.info) protected TextView info; - @InjectView(R.id.inventory) protected ImageView inventory; + @InjectView(R.id.inventory) protected TextView inventory; @InjectView(R.id.direction) protected CompassMiniView direction; @InjectView(R.id.dirimg) protected ImageView dirImg; public Geocache cache = null; @@ -160,7 +160,6 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { /** * change the sort order * - * @param comparator */ public void setComparator(final CacheComparator comparator) { cacheComparator = comparator; @@ -415,7 +414,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { } Spannable spannable = null; - if (cache.isDisabled() || cache.isArchived() || DateUtils.isPastEvent(cache)) { // strike + if (cache.isDisabled() || cache.isArchived() || CalendarUtils.isPastEvent(cache)) { // strike spannable = Spannable.Factory.getInstance().newSpannable(cache.getName()); spannable.setSpan(new StrikethroughSpan(), 0, spannable.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } @@ -434,7 +433,9 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { } holder.text.setCompoundDrawablesWithIntrinsicBounds(getCacheIcon(cache), null, null, null); - if (cache.getInventoryItems() > 0) { + final int inventorySize = cache.getInventoryItems(); + if (inventorySize > 0) { + holder.inventory.setText(Integer.toString(inventorySize)); holder.inventory.setVisibility(View.VISIBLE); } else { holder.inventory.setVisibility(View.GONE); diff --git a/main/src/cgeo/geocaching/ui/CompassMiniView.java b/main/src/cgeo/geocaching/ui/CompassMiniView.java index a811fa0..d50d806 100644 --- a/main/src/cgeo/geocaching/ui/CompassMiniView.java +++ b/main/src/cgeo/geocaching/ui/CompassMiniView.java @@ -50,18 +50,19 @@ final public class CompassMiniView extends View { private static final float MINIMUM_ROTATION_DEGREES_FOR_REPAINT = 5; private float azimuthRelative; - public CompassMiniView(Context context) { + public CompassMiniView(final Context context) { super(context); } - public CompassMiniView(Context context, AttributeSet attrs) { + public CompassMiniView(final Context context, final AttributeSet attrs) { super(context, attrs); } @Override public void onAttachedToWindow() { if (instances++ == 0) { - compassArrow = BitmapFactory.decodeResource(getResources(), Settings.isLightSkin() ? R.drawable.compass_arrow_mini_black : R.drawable.compass_arrow_mini_white); + final int drawable = isInEditMode() || !Settings.isLightSkin() ? R.drawable.compass_arrow_mini_white : R.drawable.compass_arrow_mini_black; + compassArrow = BitmapFactory.decodeResource(getResources(), drawable); compassArrowWidth = compassArrow.getWidth(); compassArrowHeight = compassArrow.getWidth(); } @@ -79,12 +80,12 @@ final public class CompassMiniView extends View { targetCoords = point; } - public void updateAzimuth(float azimuth) { + public void updateAzimuth(final float azimuth) { this.azimuth = azimuth; updateDirection(); } - public void updateHeading(float heading) { + public void updateHeading(final float heading) { this.heading = heading; updateDirection(); } @@ -106,7 +107,7 @@ final public class CompassMiniView extends View { azimuthRelative = AngleUtils.normalize(azimuth - heading); // avoid updates on very small changes, which are not visible to the user - float change = Math.abs(azimuthRelative - lastDrawnAzimuth); + final float change = Math.abs(azimuthRelative - lastDrawnAzimuth); if (change < MINIMUM_ROTATION_DEGREES_FOR_REPAINT) { return; } @@ -119,7 +120,7 @@ final public class CompassMiniView extends View { } @Override - protected void onDraw(Canvas canvas) { + protected void onDraw(final Canvas canvas) { super.onDraw(canvas); lastDrawnAzimuth = azimuthRelative; @@ -137,11 +138,11 @@ final public class CompassMiniView extends View { } @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); } - private int measureWidth(int measureSpec) { + private int measureWidth(final int measureSpec) { final int specMode = MeasureSpec.getMode(measureSpec); final int specSize = MeasureSpec.getSize(measureSpec); @@ -158,7 +159,7 @@ final public class CompassMiniView extends View { return result; } - private int measureHeight(int measureSpec) { + private int measureHeight(final int measureSpec) { final int specMode = MeasureSpec.getMode(measureSpec); final int specSize = MeasureSpec.getSize(measureSpec); diff --git a/main/src/cgeo/geocaching/ui/NavigationActionProvider.java b/main/src/cgeo/geocaching/ui/NavigationActionProvider.java index 5840e27..ed4455d 100644 --- a/main/src/cgeo/geocaching/ui/NavigationActionProvider.java +++ b/main/src/cgeo/geocaching/ui/NavigationActionProvider.java @@ -9,6 +9,10 @@ import android.support.v4.view.ActionProvider; import android.view.LayoutInflater; import android.view.View; +/** + * Action provider showing the compass icon, and reacting to normal click (primary navigation) and long click (secondary + * navigation). + */ public class NavigationActionProvider extends ActionProvider { private final Context context; diff --git a/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java b/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java index d51e697..aa75db7 100644 --- a/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java +++ b/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java @@ -11,7 +11,6 @@ import java.lang.ref.WeakReference; * * Create static private subclasses of this handler class in your activity. * - * @param <ActivityType> */ public abstract class WeakReferenceHandler<ActivityType extends Activity> extends Handler { diff --git a/main/src/cgeo/geocaching/ui/dialog/Dialogs.java b/main/src/cgeo/geocaching/ui/dialog/Dialogs.java index 47ce6e1..3729677 100644 --- a/main/src/cgeo/geocaching/ui/dialog/Dialogs.java +++ b/main/src/cgeo/geocaching/ui/dialog/Dialogs.java @@ -408,7 +408,6 @@ public final class Dialogs { /** * Move the cursor to the end of the input field. * - * @param input */ public static void moveCursorToEnd(final EditText input) { input.setSelection(input.getText().length(), input.getText().length()); diff --git a/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java index 7e49c97..076c412 100644 --- a/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java +++ b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java @@ -2,6 +2,7 @@ package cgeo.geocaching.ui.logs; import cgeo.geocaching.CacheDetailActivity; import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; @@ -24,28 +25,33 @@ import java.util.Map.Entry; public class CacheLogsViewCreator extends LogsViewCreator { private final boolean allLogs; private final Resources res = CgeoApplication.getInstance().getResources(); + private final CacheDetailActivity cacheDetailActivity; - public CacheLogsViewCreator(CacheDetailActivity cacheDetailActivity, boolean allLogs) { + public CacheLogsViewCreator(final CacheDetailActivity cacheDetailActivity, final boolean allLogs) { super(cacheDetailActivity); + this.cacheDetailActivity = cacheDetailActivity; this.allLogs = allLogs; } - /** - * May return null! - * - * @return - */ private Geocache getCache() { - if (this.activity instanceof CacheDetailActivity) { - CacheDetailActivity details = (CacheDetailActivity) this.activity; - return details.getCache(); - } - return null; + return cacheDetailActivity.getCache(); } @Override protected List<LogEntry> getLogs() { - return allLogs ? getCache().getLogs() : getCache().getFriendsLogs(); + final Geocache cache = getCache(); + final List<LogEntry> logs = allLogs ? cache.getLogs() : cache.getFriendsLogs(); + return addOwnOfflineLog(cache, logs); + } + + private List<LogEntry> addOwnOfflineLog(final Geocache cache, final List<LogEntry> logsIn) { + final LogEntry log = DataStore.loadLogOffline(cache.getGeocode()); + final ArrayList<LogEntry> logs = new ArrayList<>(logsIn); + if (log != null) { + log.author = res.getString(R.string.log_your_saved_log); + logs.add(0, log); + } + return logs; } @Override @@ -56,7 +62,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { final List<Entry<LogType, Integer>> sortedLogCounts = new ArrayList<>(logCounts.size()); for (final Entry<LogType, Integer> entry : logCounts.entrySet()) { // it may happen that the label is unknown -> then avoid any output for this type - if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getKey().getL10n() != null && entry.getValue() != 0) { + if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getValue() != 0) { sortedLogCounts.add(entry); } } @@ -66,7 +72,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() { @Override - public int compare(Entry<LogType, Integer> logCountItem1, Entry<LogType, Integer> logCountItem2) { + public int compare(final Entry<LogType, Integer> logCountItem1, final Entry<LogType, Integer> logCountItem2) { return logCountItem1.getKey().compareTo(logCountItem2.getKey()); } }); @@ -84,7 +90,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { } @Override - protected void fillCountOrLocation(LogViewHolder holder, final LogEntry log) { + protected void fillCountOrLocation(final LogViewHolder holder, final LogEntry log) { // finds count if (log.found == -1) { holder.countOrLocation.setVisibility(View.GONE); @@ -95,6 +101,21 @@ public class CacheLogsViewCreator extends LogsViewCreator { } @Override + protected void fillViewHolder(final View convertView, final LogViewHolder holder, final LogEntry log) { + super.fillViewHolder(convertView, holder, log); + if (isOfflineLog(log)) { + holder.author.setOnClickListener(new EditOfflineLogListener(getCache(), cacheDetailActivity)); + holder.text.setOnClickListener(new EditOfflineLogListener(getCache(), cacheDetailActivity)); + holder.marker.setVisibility(View.VISIBLE); + holder.marker.setImageResource(R.drawable.mark_orange); + } + } + + private boolean isOfflineLog(final LogEntry log) { + return log.author.equals(activity.getString(R.string.log_your_saved_log)); + } + + @Override protected boolean isValid() { return getCache() != null; } diff --git a/main/src/cgeo/geocaching/ui/logs/EditOfflineLogListener.java b/main/src/cgeo/geocaching/ui/logs/EditOfflineLogListener.java new file mode 100644 index 0000000..2e0f154 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/logs/EditOfflineLogListener.java @@ -0,0 +1,25 @@ +package cgeo.geocaching.ui.logs; + +import cgeo.geocaching.CacheDetailActivity; +import cgeo.geocaching.Geocache; + +import android.view.View; +import android.view.View.OnClickListener; + +class EditOfflineLogListener implements OnClickListener { + + private final Geocache cache; + private final CacheDetailActivity activity; + + public EditOfflineLogListener(final Geocache cache, final CacheDetailActivity activity) { + this.cache = cache; + this.activity = activity; + } + + @Override + public void onClick(final View v) { + activity.setNeedsRefresh(); + cache.logVisit(activity); + } + +} diff --git a/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java index 3aaeec1..a6fd5aa 100644 --- a/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java +++ b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java @@ -68,7 +68,7 @@ public abstract class LogsViewCreator extends AbstractCachingListViewPageViewCre return view; } - protected void fillViewHolder(final View convertView, final LogViewHolder holder, final LogEntry log) { + protected void fillViewHolder(@SuppressWarnings("unused") final View convertView, final LogViewHolder holder, final LogEntry log) { if (log.date > 0) { holder.date.setText(Formatter.formatShortDateVerbally(log.date)); holder.date.setVisibility(View.VISIBLE); @@ -116,12 +116,10 @@ public abstract class LogsViewCreator extends AbstractCachingListViewPageViewCre holder.marker.setVisibility(View.GONE); } - if (null == convertView) { - holder.author.setOnClickListener(createUserActionsListener()); - holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - holder.text.setOnClickListener(new DecryptTextClickListener(holder.text)); - activity.registerForContextMenu(holder.text); - } + holder.author.setOnClickListener(createUserActionsListener()); + holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); + holder.text.setOnClickListener(new DecryptTextClickListener(holder.text)); + activity.registerForContextMenu(holder.text); } abstract protected UserActionsClickListener createUserActionsListener(); diff --git a/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java index 24c8871..c120286 100644 --- a/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java +++ b/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java @@ -19,7 +19,6 @@ public class TrackableLogsViewCreator extends LogsViewCreator { private final TrackableActivity trackableActivity; /** - * @param trackableActivity */ public TrackableLogsViewCreator(final TrackableActivity trackableActivity) { super(trackableActivity); diff --git a/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java b/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java index 3d2b2b1..c2edd24 100644 --- a/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java +++ b/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java @@ -14,8 +14,6 @@ import android.os.AsyncTask; * automatically derived from the number of {@code Params} given to the task in {@link #execute(Object...)}. * </p> * - * @param <Params> - * @param <Result> */ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Params, Integer, Result> { @@ -28,9 +26,6 @@ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Pa /** * Creates an AsyncTask with progress dialog. * - * @param activity - * @param progressTitle - * @param progressMessage */ public AsyncTaskWithProgress(final Activity activity, final String progressTitle, final String progressMessage) { this(activity, progressTitle, progressMessage, false); @@ -39,8 +34,6 @@ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Pa /** * Creates an AsyncTask with progress dialog. * - * @param activity - * @param progressTitle */ public AsyncTaskWithProgress(final Activity activity, final String progressTitle) { this(activity, progressTitle, null); @@ -49,9 +42,6 @@ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Pa /** * Creates an AsyncTask with progress dialog. * - * @param activity - * @param progressTitle - * @param progressMessage */ public AsyncTaskWithProgress(final Activity activity, final String progressTitle, final String progressMessage, final boolean indeterminate) { this.activity = activity; @@ -63,8 +53,6 @@ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Pa /** * Creates an AsyncTask with progress dialog. * - * @param activity - * @param progressTitle */ public AsyncTaskWithProgress(final Activity activity, final String progressTitle, final boolean indeterminate) { this(activity, progressTitle, null, indeterminate); @@ -102,6 +90,8 @@ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Pa * This method should typically be overridden by sub classes instead of {@link #onPostExecute(Object)}. * * @param result + * The result of the operation computed by {@link #doInBackground(Object...)}. + * */ protected void onPostExecuteInternal(final Result result) { // empty by default diff --git a/main/src/cgeo/geocaching/utils/DateUtils.java b/main/src/cgeo/geocaching/utils/CalendarUtils.java index 9aa4222..ed3b18c 100644 --- a/main/src/cgeo/geocaching/utils/DateUtils.java +++ b/main/src/cgeo/geocaching/utils/CalendarUtils.java @@ -5,13 +5,13 @@ import cgeo.geocaching.Geocache; import java.util.Calendar; import java.util.Date; -public final class DateUtils { +public final class CalendarUtils { - private DateUtils() { + private CalendarUtils() { // utility class } - public static int daysSince(long date) { + public static int daysSince(final long date) { final Calendar logDate = Calendar.getInstance(); logDate.setTimeInMillis(date); logDate.set(Calendar.SECOND, 0); @@ -24,12 +24,27 @@ public final class DateUtils { return (int) Math.round((today.getTimeInMillis() - logDate.getTimeInMillis()) / 86400000d); } + public static int daysSince(final Calendar date) { + return daysSince(date.getTimeInMillis()); + } + public static boolean isPastEvent(final Geocache cache) { if (!cache.isEventCache()) { return false; } final Date hiddenDate = cache.getHiddenDate(); - return hiddenDate != null && DateUtils.daysSince(hiddenDate.getTime()) > 0; + return hiddenDate != null && CalendarUtils.daysSince(hiddenDate.getTime()) > 0; + } + + /** + * Return whether the given date is *more* than 1 day away. We allow 1 day to be "present time" to compensate for + * potential timezone issues. + * + * @param date + * the date + */ + public static boolean isFuture(final Calendar date) { + return daysSince(date) < -1; } } diff --git a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java index ab27264..a65a9fb 100644 --- a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java +++ b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java @@ -6,6 +6,8 @@ import cgeo.geocaching.R; import cgeo.geocaching.ui.dialog.Dialogs; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import rx.functions.Action0; import rx.functions.Action1; @@ -14,6 +16,8 @@ import rx.schedulers.Schedulers; import android.app.Activity; import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; import android.content.res.Resources; import java.io.File; @@ -26,7 +30,8 @@ public class DatabaseBackupUtils { } /** - * restore the database in a new thread, showing a progress window + * After confirming to overwrite the existing caches on the devices, restore the database in a new thread, showing a + * progress window * * @param activity * calling activity @@ -35,6 +40,23 @@ public class DatabaseBackupUtils { if (!hasBackup()) { return; } + final int caches = DataStore.getAllCachesCount(); + if (caches == 0) { + restoreDatabaseInternal(activity); + } + else { + Dialogs.confirm(activity, R.string.init_backup_restore, activity.getString(R.string.restore_confirm_overwrite, activity.getResources().getQuantityString(R.plurals.cache_counts, caches, caches)), new OnClickListener() { + + @Override + public void onClick(final DialogInterface dialog, final int which) { + restoreDatabaseInternal(activity); + } + }); + + } + } + + private static void restoreDatabaseInternal(final Activity activity) { final Resources res = activity.getResources(); final ProgressDialog dialog = ProgressDialog.show(activity, res.getString(R.string.init_backup_restore), res.getString(R.string.init_restore_running), true, false); final AtomicBoolean restoreSuccessful = new AtomicBoolean(false); @@ -57,14 +79,32 @@ public class DatabaseBackupUtils { }); } - public static boolean createBackup(final Activity activity, final Runnable runAfterwards) { + /** + * Create a backup after confirming to overwrite the existing backup. + * + */ + public static void createBackup(final Activity activity, final Runnable runAfterwards) { // avoid overwriting an existing backup with an empty database // (can happen directly after reinstalling the app) if (DataStore.getAllCachesCount() == 0) { Dialogs.message(activity, R.string.init_backup, R.string.init_backup_unnecessary); - return false; + return; + } + if (hasBackup()) { + Dialogs.confirm(activity, R.string.init_backup, activity.getString(R.string.backup_confirm_overwrite, getBackupDateTime()), new OnClickListener() { + + @Override + public void onClick(final DialogInterface dialog, final int which) { + createBackupInternal(activity, runAfterwards); + } + }); } + else { + createBackupInternal(activity, runAfterwards); + } + } + private static void createBackupInternal(final Activity activity, final Runnable runAfterwards) { final ProgressDialog dialog = ProgressDialog.show(activity, activity.getString(R.string.init_backup), activity.getString(R.string.init_backup_running), true, false); @@ -88,9 +128,9 @@ public class DatabaseBackupUtils { } } }); - return true; } + @Nullable public static File getRestoreFile() { final File fileSourceFile = DataStore.getBackupFileInternal(); return fileSourceFile.exists() && fileSourceFile.length() > 0 ? fileSourceFile : null; @@ -100,6 +140,7 @@ public class DatabaseBackupUtils { return getRestoreFile() != null; } + @NonNull public static String getBackupDateTime() { final File restoreFile = getRestoreFile(); if (restoreFile == null) { diff --git a/main/src/cgeo/geocaching/utils/DebugUtils.java b/main/src/cgeo/geocaching/utils/DebugUtils.java index 07aac64..1f95e7c 100644 --- a/main/src/cgeo/geocaching/utils/DebugUtils.java +++ b/main/src/cgeo/geocaching/utils/DebugUtils.java @@ -22,15 +22,14 @@ public class DebugUtils { 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"); + final File file = FileUtils.getUniqueNamedFile(new File(Environment.getExternalStorageDirectory(), + "cgeo_dump_" + fileNameDateFormat.format(new Date()) + ".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) { + } catch (final IOException e) { Log.e("createMemoryDump", e); } } diff --git a/main/src/cgeo/geocaching/utils/FileUtils.java b/main/src/cgeo/geocaching/utils/FileUtils.java index c123469..778b9c7 100644 --- a/main/src/cgeo/geocaching/utils/FileUtils.java +++ b/main/src/cgeo/geocaching/utils/FileUtils.java @@ -4,6 +4,7 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.os.Handler; import android.os.Message; @@ -75,6 +76,24 @@ public final class FileUtils { } } + public static boolean deleteDirectory(@NonNull final File dir) { + final File[] files = dir.listFiles(); + + // Although we are called on an existing directory, it might have been removed concurrently + // in the meantime, for example by the user or by another cleanup task. + if (files != null) { + for (final File file : files) { + if (file.isDirectory()) { + deleteDirectory(file); + } else { + delete(file); + } + } + } + + return delete(dir); + } + public static abstract class FileSelector { public abstract boolean isSelected(File file); @@ -92,18 +111,20 @@ public final class FileUtils { * </ul> * which does not yet exist. */ - public static File getUniqueNamedFile(final String baseNameAndPath) { - final String extension = StringUtils.substringAfterLast(baseNameAndPath, "."); - final String pathName = StringUtils.substringBeforeLast(baseNameAndPath, "."); - int number = 1; - while (new File(getNumberedFileName(pathName, extension, number)).exists()) { - number++; + public static File getUniqueNamedFile(final File file) { + if (!file.exists()) { + return file; } - return new File(getNumberedFileName(pathName, extension, number)); - } - - private static String getNumberedFileName(final String pathName, final String extension, final int number) { - return pathName + (number > 1 ? "_" + Integer.toString(number) : "") + "." + extension; + final String baseNameAndPath = file.getPath(); + final String prefix = StringUtils.substringBeforeLast(baseNameAndPath, ".") + "_"; + final String extension = "." + StringUtils.substringAfterLast(baseNameAndPath, "."); + for (int i = 1; i < Integer.MAX_VALUE; i++) { + final File numbered = new File(prefix + i + extension); + if (!numbered.exists()) { + return numbered; + } + } + throw new IllegalStateException("Unable to generate a non-existing file name"); } /** diff --git a/main/src/cgeo/geocaching/utils/Formatter.java b/main/src/cgeo/geocaching/utils/Formatter.java index c764c5a..db649d8 100644 --- a/main/src/cgeo/geocaching/utils/Formatter.java +++ b/main/src/cgeo/geocaching/utils/Formatter.java @@ -76,6 +76,10 @@ public abstract class Formatter { return dateFormat.format(date); } + private static String formatShortDateIncludingWeekday(final long time) { + return DateUtils.formatDateTime(CgeoApplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_WEEKDAY) + ", " + formatShortDate(time); + } + /** * Generate a numeric date string according to system-wide settings (locale, date format) * such as "10/20/2010". Today and yesterday will be presented as strings "today" and "yesterday". @@ -85,7 +89,7 @@ public abstract class Formatter { * @return the formatted string */ public static String formatShortDateVerbally(final long date) { - final int diff = cgeo.geocaching.utils.DateUtils.daysSince(date); + final int diff = CalendarUtils.daysSince(date); switch (diff) { case 0: return CgeoApplication.getInstance().getString(R.string.log_today); @@ -157,7 +161,7 @@ public abstract class Formatter { } else if (cache.isEventCache()) { final Date hiddenDate = cache.getHiddenDate(); if (hiddenDate != null) { - infos.add(Formatter.formatShortDate(hiddenDate.getTime())); + infos.add(Formatter.formatShortDateIncludingWeekday(hiddenDate.getTime())); } } } @@ -190,7 +194,7 @@ public abstract class Formatter { } public static String formatDaysAgo(final long date) { - final int days = cgeo.geocaching.utils.DateUtils.daysSince(date); + final int days = CalendarUtils.daysSince(date); switch (days) { case 0: return CgeoApplication.getInstance().getString(R.string.log_today); @@ -204,7 +208,6 @@ public abstract class Formatter { /** * Formatting of the hidden date of a cache * - * @param cache * @return {@code null} or hidden date of the cache (or event date of the cache) in human readable format */ public static String formatHiddenDate(final Geocache cache) { diff --git a/main/src/cgeo/geocaching/utils/HtmlUtils.java b/main/src/cgeo/geocaching/utils/HtmlUtils.java index e90b70d..ab6e8fe 100644 --- a/main/src/cgeo/geocaching/utils/HtmlUtils.java +++ b/main/src/cgeo/geocaching/utils/HtmlUtils.java @@ -21,8 +21,6 @@ public final class HtmlUtils { * Extract the text from a HTML based string. This is similar to what HTML.fromHtml(...) does, but this method also * removes the embedded images instead of replacing them by a small rectangular representation character. * - * @param html - * @return */ public static String extractText(final CharSequence html) { if (StringUtils.isBlank(html)) { @@ -61,7 +59,8 @@ public final class HtmlUtils { return Html.fromHtml(result).toString().trim(); } - public static String removeExtraParagraph(final String html) { + public static String removeExtraParagraph(final String htmlIn) { + final String html = StringUtils.trim(htmlIn); if (StringUtils.startsWith(html, "<p>") && StringUtils.endsWith(html, "</p>")) { final String paragraph = StringUtils.substring(html, "<p>".length(), html.length() - "</p>".length()).trim(); if (extractText(paragraph).equals(paragraph)) { diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java index 6122532..f89c040 100644 --- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java +++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java @@ -117,7 +117,6 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { * Interface for handlers that wish to get notified when items are * removed from the LRUMap * - * @param <V> */ public interface RemoveHandler<V> { diff --git a/main/src/cgeo/geocaching/utils/Log.java b/main/src/cgeo/geocaching/utils/Log.java index 2f51e42..861faaa 100644 --- a/main/src/cgeo/geocaching/utils/Log.java +++ b/main/src/cgeo/geocaching/utils/Log.java @@ -37,7 +37,6 @@ public final class Log { /** * Save a copy of the debug flag from the settings for performance reasons. * - * @param isDebug */ public static void setDebug(final boolean isDebug) { Log.isDebug = isDebug; diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java index ff4013c..1db3d5b 100644 --- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java +++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java @@ -215,7 +215,7 @@ public final class LogTemplateProvider { } final Geocache cache = context.getCache(); if (cache != null) { - return cache.getUrl(); + return StringUtils.defaultString(cache.getUrl()); } return StringUtils.EMPTY; } diff --git a/main/src/cgeo/geocaching/utils/MatcherWrapper.java b/main/src/cgeo/geocaching/utils/MatcherWrapper.java index e116269..733a18e 100644 --- a/main/src/cgeo/geocaching/utils/MatcherWrapper.java +++ b/main/src/cgeo/geocaching/utils/MatcherWrapper.java @@ -45,8 +45,6 @@ public class MatcherWrapper { * <p> * Do not change this method, even if Findbugs and other tools will report a violation for that line! * - * @param input - * @return */ @SuppressFBWarnings("DM_STRING_CTOR") private static String newString(final String input) { diff --git a/main/src/cgeo/geocaching/utils/ProcessUtils.java b/main/src/cgeo/geocaching/utils/ProcessUtils.java index ce05483..d04c1fe 100644 --- a/main/src/cgeo/geocaching/utils/ProcessUtils.java +++ b/main/src/cgeo/geocaching/utils/ProcessUtils.java @@ -3,7 +3,10 @@ package cgeo.geocaching.utils; import cgeo.geocaching.CgeoApplication; import org.apache.commons.collections4.CollectionUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import android.app.Activity; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -21,10 +24,8 @@ public final class ProcessUtils { /** * Preferred method to detect the availability of an external app * - * @param packageName - * @return */ - public static boolean isLaunchable(final String packageName) { + public static boolean isLaunchable(@Nullable final String packageName) { return getLaunchIntent(packageName) != null; } @@ -33,17 +34,15 @@ public final class ProcessUtils { * This function is relatively costly, so if you know that the package in question has * a launch intent, use isLaunchable() instead. * - * @param packageName - * @return */ - public static boolean isInstalled(final String packageName) { + public static boolean isInstalled(@NonNull final String packageName) { return isLaunchable(packageName) || hasPackageInstalled(packageName); } /** * This will find installed applications even without launch intent (e.g. the streetview plugin). */ - private static boolean hasPackageInstalled(final String packageName) { + private static boolean hasPackageInstalled(@NonNull final String packageName) { final List<PackageInfo> packs = CgeoApplication.getInstance().getPackageManager().getInstalledPackages(0); for (final PackageInfo packageInfo : packs) { if (packageName.equals(packageInfo.packageName)) { @@ -56,7 +55,8 @@ public final class ProcessUtils { /** * This will find applications, which can be launched. */ - public static Intent getLaunchIntent(final String packageName) { + @Nullable + public static Intent getLaunchIntent(@Nullable final String packageName) { if (packageName == null) { return null; } @@ -79,16 +79,16 @@ public final class ProcessUtils { * method queries the package manager for installed packages that can * respond to an intent with the specified action. If no suitable package is * found, this method returns false. - * + * * @param action * The Intent action to check for availability. * @param uri * The Intent URI to check for availability. - * + * * @return True if an Intent with the specified action can be sent and * responded to, false otherwise. */ - public static boolean isIntentAvailable(final String action, final Uri uri) { + public static boolean isIntentAvailable(@NonNull final String action, @Nullable final Uri uri) { final PackageManager packageManager = CgeoApplication.getInstance().getPackageManager(); final Intent intent; if (uri == null) { @@ -103,4 +103,18 @@ public final class ProcessUtils { return CollectionUtils.isNotEmpty(list) || CollectionUtils.isNotEmpty(servicesList); } + @SuppressWarnings("deprecation") + public static void openMarket(final Activity activity, @NonNull final String packageName) { + try { + final String url = "market://details?id=" + packageName; + final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + activity.startActivity(marketIntent); + + } catch (final RuntimeException ignored) { + // market not available, fall back to browser + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id=" + packageName))); + } + } + } diff --git a/main/src/cgeo/geocaching/utils/RxUtils.java b/main/src/cgeo/geocaching/utils/RxUtils.java index 280575b..08cc3e7 100644 --- a/main/src/cgeo/geocaching/utils/RxUtils.java +++ b/main/src/cgeo/geocaching/utils/RxUtils.java @@ -2,7 +2,6 @@ package cgeo.geocaching.utils; import rx.Observable; import rx.Observable.OnSubscribe; -import rx.Observable.Operator; import rx.Scheduler; import rx.Scheduler.Worker; import rx.Subscriber; @@ -17,7 +16,6 @@ import rx.observers.Subscribers; import rx.schedulers.Schedulers; import rx.subjects.PublishSubject; import rx.subscriptions.Subscriptions; -import rx.util.async.Async; import android.os.Handler; import android.os.HandlerThread; @@ -115,49 +113,6 @@ public class RxUtils { abstract protected void onStop(); } - public static <T> Operator<T, T> operatorTakeUntil(final Func1<? super T, Boolean> predicate) { - return new Operator<T, T>() { - @Override - public Subscriber<? super T> call(final Subscriber<? super T> subscriber) { - return new Subscriber<T>(subscriber) { - private boolean done = false; - - @Override - public void onCompleted() { - if (!done) { - subscriber.onCompleted(); - } - } - - @Override - public void onError(final Throwable throwable) { - if (!done) { - subscriber.onError(throwable); - } - } - - @Override - public void onNext(final T value) { - subscriber.onNext(value); - boolean shouldEnd = false; - try { - shouldEnd = predicate.call(value); - } catch (final Throwable e) { - done = true; - subscriber.onError(e); - unsubscribe(); - } - if (shouldEnd) { - done = true; - subscriber.onCompleted(); - unsubscribe(); - } - } - }; - } - }; - } - public static<T> Observable<T> rememberLast(final Observable<T> observable, final T initialValue) { final AtomicReference<T> lastValue = new AtomicReference<>(initialValue); return observable.doOnNext(new Action1<T>() { @@ -175,20 +130,26 @@ public class RxUtils { } public static <T> void andThenOnUi(final Scheduler scheduler, final Func0<T> background, final Action1<T> foreground) { - Async.fromCallable(background, scheduler).observeOn(AndroidSchedulers.mainThread()).subscribe(foreground); + scheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + final T value = background.call(); + AndroidSchedulers.mainThread().createWorker().schedule(new Action0() { + @Override + public void call() { + foreground.call(value); + } + }); + } + }); } public static void andThenOnUi(final Scheduler scheduler, final Action0 background, final Action0 foreground) { - andThenOnUi(scheduler, new Func0<Void>() { + scheduler.createWorker().schedule(new Action0() { @Override - public Void call() { + public void call() { background.call(); - return null; - } - }, new Action1<Void>() { - @Override - public void call(final Void ignored) { - foreground.call(); + AndroidSchedulers.mainThread().createWorker().schedule(foreground); } }); } diff --git a/main/src/cgeo/geocaching/utils/TextUtils.java b/main/src/cgeo/geocaching/utils/TextUtils.java index 9fc960c..1f14f8d 100644 --- a/main/src/cgeo/geocaching/utils/TextUtils.java +++ b/main/src/cgeo/geocaching/utils/TextUtils.java @@ -106,8 +106,6 @@ public final class TextUtils { /** * Searches for the pattern pattern in the data. * - * @param data - * @param pattern * @return true if data contains the pattern pattern */ public static boolean matches(final String data, final Pattern pattern) { @@ -164,8 +162,6 @@ public final class TextUtils { * Remove all control characters (which are not valid in XML or HTML), as those should not appear in cache texts * anyway * - * @param input - * @return */ public static String removeControlCharacters(final String input) { final Matcher remover = PATTERN_REMOVE_NONPRINTABLE.matcher(input); diff --git a/main/src/cgeo/geocaching/utils/XmlUtils.java b/main/src/cgeo/geocaching/utils/XmlUtils.java index c36fb53..004fd1b 100644 --- a/main/src/cgeo/geocaching/utils/XmlUtils.java +++ b/main/src/cgeo/geocaching/utils/XmlUtils.java @@ -17,7 +17,6 @@ public final class XmlUtils { * @param prefix an XML prefix, see {@link XmlSerializer#startTag(String, String)} * @param tag an XML tag * @param text some text to insert, or <tt>null</tt> to omit completely this tag - * @throws IOException */ public static void simpleText(final XmlSerializer serializer, final String prefix, final String tag, final String text) throws IOException { if (text != null) { @@ -34,7 +33,6 @@ public final class XmlUtils { * @param prefix an XML prefix, see {@link XmlSerializer#startTag(String, String)} shared by all tags * @param tagAndText an XML tag, the corresponding text, another XML tag, the corresponding text. <tt>null</tt> texts * will be omitted along with their respective tag. - * @throws IOException */ public static void multipleTexts(final XmlSerializer serializer, final String prefix, final String... tagAndText) throws IOException { for (int i = 0; i < tagAndText.length; i += 2) { |
