aboutsummaryrefslogtreecommitdiffstats
path: root/main/src
diff options
context:
space:
mode:
Diffstat (limited to 'main/src')
-rw-r--r--main/src/cgeo/geocaching/AddressListActivity.java51
-rw-r--r--main/src/cgeo/geocaching/AttributesGridAdapter.java79
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java276
-rw-r--r--main/src/cgeo/geocaching/CacheListActivity.java35
-rw-r--r--main/src/cgeo/geocaching/CacheMenuHandler.java1
-rw-r--r--main/src/cgeo/geocaching/CgeoApplication.java97
-rw-r--r--main/src/cgeo/geocaching/CompassActivity.java40
-rw-r--r--main/src/cgeo/geocaching/CreateShortcutActivity.java3
-rw-r--r--main/src/cgeo/geocaching/DataStore.java64
-rw-r--r--main/src/cgeo/geocaching/EditWaypointActivity.java5
-rw-r--r--main/src/cgeo/geocaching/Geocache.java58
-rw-r--r--main/src/cgeo/geocaching/GpxFileListActivity.java9
-rw-r--r--main/src/cgeo/geocaching/LogCacheActivity.java24
-rw-r--r--main/src/cgeo/geocaching/LogTrackableActivity.java18
-rw-r--r--main/src/cgeo/geocaching/MainActivity.java13
-rw-r--r--main/src/cgeo/geocaching/NavigateAnyPointActivity.java7
-rw-r--r--main/src/cgeo/geocaching/SearchActivity.java13
-rw-r--r--main/src/cgeo/geocaching/SelectMapfileActivity.java2
-rw-r--r--main/src/cgeo/geocaching/StaticMapsActivity.java8
-rw-r--r--main/src/cgeo/geocaching/StaticMapsProvider.java46
-rw-r--r--main/src/cgeo/geocaching/Trackable.java4
-rw-r--r--main/src/cgeo/geocaching/Waypoint.java12
-rw-r--r--main/src/cgeo/geocaching/WaypointPopupFragment.java7
-rw-r--r--main/src/cgeo/geocaching/activity/ActivityMixin.java11
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java3
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractConnector.java56
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractLoggingManager.java3
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractLogin.java7
-rw-r--r--main/src/cgeo/geocaching/connector/ConnectorFactory.java33
-rw-r--r--main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java6
-rw-r--r--main/src/cgeo/geocaching/connector/GeopeitusConnector.java6
-rw-r--r--main/src/cgeo/geocaching/connector/IConnector.java35
-rw-r--r--main/src/cgeo/geocaching/connector/ILoggingManager.java21
-rw-r--r--main/src/cgeo/geocaching/connector/ImageResult.java8
-rw-r--r--main/src/cgeo/geocaching/connector/LogResult.java8
-rw-r--r--main/src/cgeo/geocaching/connector/NoLoggingManager.java8
-rw-r--r--main/src/cgeo/geocaching/connector/UnknownConnector.java15
-rw-r--r--main/src/cgeo/geocaching/connector/UserAction.java12
-rw-r--r--main/src/cgeo/geocaching/connector/WaymarkingConnector.java6
-rw-r--r--main/src/cgeo/geocaching/connector/capability/FieldNotesCapability.java4
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ILogin.java22
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java3
-rw-r--r--main/src/cgeo/geocaching/connector/ec/ECApi.java24
-rw-r--r--main/src/cgeo/geocaching/connector/ec/ECConnector.java44
-rw-r--r--main/src/cgeo/geocaching/connector/ec/ECLoggingManager.java18
-rw-r--r--main/src/cgeo/geocaching/connector/ec/ECLogin.java4
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java74
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java9
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCLogin.java7
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java45
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java56
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java11
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiConnector.java1
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java18
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCConnector.java17
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java3
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java10
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OXConnector.java20
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java8
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java13
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java11
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java3
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java11
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheAttribute.java8
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheSize.java5
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheType.java11
-rw-r--r--main/src/cgeo/geocaching/enumerations/LogType.java8
-rw-r--r--main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java6
-rw-r--r--main/src/cgeo/geocaching/enumerations/WaypointType.java13
-rw-r--r--main/src/cgeo/geocaching/export/FieldnoteExport.java11
-rw-r--r--main/src/cgeo/geocaching/files/AbstractFileListActivity.java3
-rw-r--r--main/src/cgeo/geocaching/files/FileParser.java19
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java1
-rw-r--r--main/src/cgeo/geocaching/files/LocParser.java15
-rw-r--r--main/src/cgeo/geocaching/files/LocalStorage.java34
-rw-r--r--main/src/cgeo/geocaching/filter/AbstractFilter.java6
-rw-r--r--main/src/cgeo/geocaching/filter/AttributeFilter.java5
-rw-r--r--main/src/cgeo/geocaching/filter/DifficultyFilter.java5
-rw-r--r--main/src/cgeo/geocaching/filter/DistanceFilter.java12
-rw-r--r--main/src/cgeo/geocaching/filter/FilterUserInterface.java10
-rw-r--r--main/src/cgeo/geocaching/filter/IFilter.java6
-rw-r--r--main/src/cgeo/geocaching/filter/IFilterFactory.java3
-rw-r--r--main/src/cgeo/geocaching/filter/ModifiedFilter.java5
-rw-r--r--main/src/cgeo/geocaching/filter/OriginFilter.java7
-rw-r--r--main/src/cgeo/geocaching/filter/OwnRatingFilter.java35
-rw-r--r--main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java16
-rw-r--r--main/src/cgeo/geocaching/filter/PersonalNoteFilter.java7
-rw-r--r--main/src/cgeo/geocaching/filter/PopularityFilter.java7
-rw-r--r--main/src/cgeo/geocaching/filter/PopularityRatioFilter.java5
-rw-r--r--main/src/cgeo/geocaching/filter/RatingFilter.java35
-rw-r--r--main/src/cgeo/geocaching/filter/SizeFilter.java7
-rw-r--r--main/src/cgeo/geocaching/filter/StateFilter.java21
-rw-r--r--main/src/cgeo/geocaching/filter/TerrainFilter.java5
-rw-r--r--main/src/cgeo/geocaching/filter/TrackablesFilter.java5
-rw-r--r--main/src/cgeo/geocaching/filter/TypeFilter.java7
-rw-r--r--main/src/cgeo/geocaching/gcvote/GCVote.java9
-rw-r--r--main/src/cgeo/geocaching/gcvote/GCVoteDialog.java74
-rw-r--r--main/src/cgeo/geocaching/gcvote/GCVotePoster.java53
-rw-r--r--main/src/cgeo/geocaching/gcvote/GCVoteRatingBarUtil.java58
-rw-r--r--main/src/cgeo/geocaching/list/StoredList.java7
-rw-r--r--main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java23
-rw-r--r--main/src/cgeo/geocaching/location/AndroidGeocoder.java59
-rw-r--r--main/src/cgeo/geocaching/location/GCGeocoder.java65
-rw-r--r--main/src/cgeo/geocaching/location/Geocoder.java61
-rw-r--r--main/src/cgeo/geocaching/location/GeopointParser.java2
-rw-r--r--main/src/cgeo/geocaching/location/MapQuestGeocoder.java117
-rw-r--r--main/src/cgeo/geocaching/location/Viewport.java5
-rw-r--r--main/src/cgeo/geocaching/maps/CGeoMap.java9
-rw-r--r--main/src/cgeo/geocaching/network/HtmlImage.java94
-rw-r--r--main/src/cgeo/geocaching/network/OAuth.java8
-rw-r--r--main/src/cgeo/geocaching/sensors/GeoData.java2
-rw-r--r--main/src/cgeo/geocaching/sensors/GeoDirHandler.java33
-rw-r--r--main/src/cgeo/geocaching/sensors/Sensors.java160
-rw-r--r--main/src/cgeo/geocaching/settings/Settings.java3
-rw-r--r--main/src/cgeo/geocaching/settings/SettingsActivity.java9
-rw-r--r--main/src/cgeo/geocaching/sorting/DateComparator.java4
-rw-r--r--main/src/cgeo/geocaching/sorting/SizeComparator.java5
-rw-r--r--main/src/cgeo/geocaching/ui/AddressListAdapter.java9
-rw-r--r--main/src/cgeo/geocaching/ui/CacheDetailsCreator.java31
-rw-r--r--main/src/cgeo/geocaching/ui/CacheListAdapter.java4
-rw-r--r--main/src/cgeo/geocaching/ui/ImagesList.java4
-rw-r--r--main/src/cgeo/geocaching/ui/WrappingGridView.java38
-rw-r--r--main/src/cgeo/geocaching/utils/CryptUtils.java4
-rw-r--r--main/src/cgeo/geocaching/utils/Log.java26
-rw-r--r--main/src/cgeo/geocaching/utils/RxUtils.java16
126 files changed, 1830 insertions, 1055 deletions
diff --git a/main/src/cgeo/geocaching/AddressListActivity.java b/main/src/cgeo/geocaching/AddressListActivity.java
index 4f71ab6..4f81f8b 100644
--- a/main/src/cgeo/geocaching/AddressListActivity.java
+++ b/main/src/cgeo/geocaching/AddressListActivity.java
@@ -1,14 +1,17 @@
package cgeo.geocaching;
import cgeo.geocaching.activity.AbstractListActivity;
-import cgeo.geocaching.location.Geocoder;
+import cgeo.geocaching.location.AndroidGeocoder;
+import cgeo.geocaching.location.GCGeocoder;
+import cgeo.geocaching.location.MapQuestGeocoder;
import cgeo.geocaching.ui.AddressListAdapter;
-import org.apache.commons.collections4.CollectionUtils;
+import rx.Observable;
+import rx.android.observables.AndroidObservable;
+import rx.functions.Action1;
import android.app.ProgressDialog;
import android.location.Address;
-import android.os.AsyncTask;
import android.os.Bundle;
import java.util.List;
@@ -19,47 +22,35 @@ public class AddressListActivity extends AbstractListActivity {
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.addresslist_activity);
- // get parameters
- final String keyword = getIntent().getStringExtra(Intents.EXTRA_KEYWORD);
-
- if (keyword == null) {
- showToast(res.getString(R.string.err_search_address_forgot));
- finish();
- return;
- }
final AddressListAdapter adapter = new AddressListAdapter(this);
setListAdapter(adapter);
+ final String keyword = getIntent().getStringExtra(Intents.EXTRA_KEYWORD);
final ProgressDialog waitDialog =
ProgressDialog.show(this, res.getString(R.string.search_address_started), keyword, true);
waitDialog.setCancelable(true);
-
lookupAddressInBackground(keyword, adapter, waitDialog);
}
private void lookupAddressInBackground(final String keyword, final AddressListAdapter adapter, final ProgressDialog waitDialog) {
- new AsyncTask<Void, Void, List<Address>>() {
-
+ final Observable<Address> geocoderObservable = new AndroidGeocoder(this).getFromLocationName(keyword)
+ .onErrorResumeNext(MapQuestGeocoder.getFromLocationName(keyword))
+ .onErrorResumeNext(GCGeocoder.getFromLocationName(keyword));
+ AndroidObservable.bindActivity(this, geocoderObservable.toList()).subscribe(new Action1<List<Address>>() {
@Override
- protected List<Address> doInBackground(final Void... params) {
- final Geocoder geocoder = new Geocoder(AddressListActivity.this);
- return geocoder.getFromLocationName(keyword);
- }
-
- @Override
- protected void onPostExecute(final List<Address> addresses) {
+ public void call(final List<Address> addresses) {
waitDialog.dismiss();
- if (CollectionUtils.isNotEmpty(addresses)) {
- for (final Address address : addresses) {
- adapter.add(address); // don't use addAll, it's only available with API >= 11
- }
- } else {
- finish();
- CacheListActivity.startActivityAddress(AddressListActivity.this, null, keyword);
+ for (final Address address : addresses) {
+ adapter.add(address); // don't use addAll, it's only available with API >= 11
}
}
-
- }.execute();
+ }, new Action1<Throwable>() {
+ @Override
+ public void call(final Throwable throwable) {
+ finish();
+ showToast(res.getString(R.string.err_unknown_address));
+ }
+ });
}
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/AttributesGridAdapter.java b/main/src/cgeo/geocaching/AttributesGridAdapter.java
new file mode 100644
index 0000000..fd81339
--- /dev/null
+++ b/main/src/cgeo/geocaching/AttributesGridAdapter.java
@@ -0,0 +1,79 @@
+package cgeo.geocaching;
+
+import cgeo.geocaching.enumerations.CacheAttribute;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import java.util.List;
+
+public class AttributesGridAdapter extends BaseAdapter {
+ private final Context context;
+ private final Resources resources;
+ private final List<String> attributes;
+ private final LayoutInflater inflater;
+
+ public AttributesGridAdapter(final Context context, final Geocache cache) {
+ this.context = context;
+ resources = context.getResources();
+ attributes = cache.getAttributes();
+ inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ @Override
+ public int getCount() {
+ return attributes.size();
+ }
+
+ @Override
+ public Object getItem(final int position) {
+ return attributes.get(position);
+ }
+
+ @Override
+ public long getItemId(final int position) {
+ return 0;
+ }
+
+ @Override
+ public View getView(final int position, final View convertView, final ViewGroup parent) {
+ final FrameLayout attributeLayout;
+ if (convertView == null) {
+ attributeLayout = (FrameLayout) inflater.inflate(R.layout.attribute_image, parent, false);
+ } else {
+ attributeLayout = (FrameLayout) convertView;
+ }
+
+ drawAttribute(attributeLayout, attributes.get(position));
+ return attributeLayout;
+ }
+
+ private void drawAttribute(final FrameLayout attributeLayout, final String attributeName) {
+ final ImageView imageView = (ImageView) attributeLayout.getChildAt(0);
+
+ final boolean strikeThrough = !CacheAttribute.isEnabled(attributeName);
+ final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName));
+ if (attrib != null) {
+ Drawable drawable = resources.getDrawable(attrib.drawableId);
+ imageView.setImageDrawable(drawable);
+ if (strikeThrough) {
+ // generate strike through image with same properties as attribute image
+ final ImageView strikeThroughImage = new ImageView(context);
+ strikeThroughImage.setLayoutParams(imageView.getLayoutParams());
+ drawable = resources.getDrawable(R.drawable.attribute__strikethru);
+ strikeThroughImage.setImageDrawable(drawable);
+ attributeLayout.addView(strikeThroughImage);
+ }
+ } else {
+ imageView.setImageDrawable(resources.getDrawable(R.drawable.attribute_unknown));
+ }
+ }
+
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index e74b2d2..ef3823e 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -12,7 +12,6 @@ import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.apps.cache.navi.NavigationSelectionActionProvider;
import cgeo.geocaching.apps.cachelist.MapsWithMeCacheListApp;
-import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.connector.gc.GCConnector;
@@ -21,6 +20,8 @@ import cgeo.geocaching.enumerations.CacheAttribute;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.WaypointType;
+import cgeo.geocaching.gcvote.GCVote;
+import cgeo.geocaching.gcvote.GCVoteDialog;
import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.location.Units;
import cgeo.geocaching.network.HtmlImage;
@@ -105,13 +106,11 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.ViewParent;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
-import android.widget.FrameLayout;
+import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
@@ -505,6 +504,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
menu.findItem(R.id.menu_store).setVisible(cache != null && !cache.isOffline());
menu.findItem(R.id.menu_delete).setVisible(cache != null && cache.isOffline());
menu.findItem(R.id.menu_refresh).setVisible(cache != null && cache.isOffline());
+ menu.findItem(R.id.menu_gcvote).setVisible(cache != null && GCVote.isVotingPossible(cache));
return super.onPrepareOptionsMenu(menu);
}
@@ -526,6 +526,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
case R.id.menu_refresh:
refreshCache();
return true;
+ case R.id.menu_gcvote:
+ showVoteDialog();
+ return true;
default:
if (NavigationAppFactory.onMenuItemSelected(item, this, cache)) {
return true;
@@ -539,6 +542,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return super.onOptionsItemSelected(item);
}
+ private void showVoteDialog() {
+ GCVoteDialog.show(this, cache, new Runnable() {
+ @Override
+ public void run() {
+ notifyDataSetChanged();
+ }
+ });
+ }
+
private static final class CacheDetailsGeoDirHandler extends GeoDirHandler {
private final WeakReference<CacheDetailActivity> activityRef;
@@ -617,7 +629,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
private void notifyDataSetChanged() {
- // This might get called asynchronically when the activity is shut down
+ // This might get called asynchronous when the activity is shut down
if (isFinishing()) {
return;
}
@@ -722,185 +734,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- private class AttributeViewBuilder {
- private ViewGroup attributeIconsLayout; // layout for attribute icons
- private ViewGroup attributeDescriptionsLayout; // layout for attribute descriptions
- private boolean attributesShowAsIcons = true; // default: show icons
- /**
- * If the cache is from a non GC source, it might be without icons. Disable switching in those cases.
- */
- private boolean noAttributeIconsFound = false;
- private int attributeBoxMaxWidth;
-
- public void fillView(final LinearLayout attributeBox) {
- // first ensure that the view is empty
- attributeBox.removeAllViews();
-
- // maximum width for attribute icons is screen width - paddings of parents
- attributeBoxMaxWidth = Compatibility.getDisplayWidth();
- ViewParent child = attributeBox;
- do {
- if (child instanceof View) {
- attributeBoxMaxWidth -= ((View) child).getPaddingLeft() + ((View) child).getPaddingRight();
- }
- child = child.getParent();
- } while (child != null);
-
- // delete views holding description / icons
- attributeDescriptionsLayout = null;
- attributeIconsLayout = null;
-
- attributeBox.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(final View v) {
- // toggle between attribute icons and descriptions
- toggleAttributeDisplay(attributeBox, attributeBoxMaxWidth);
- }
- });
-
- // icons or text?
- //
- // also show icons when noAttributeImagesFound == true. Explanation:
- // 1. no icons could be found in the first invocation of this method
- // 2. user refreshes cache from web
- // 3. now this method is called again
- // 4. attributeShowAsIcons is false but noAttributeImagesFound is true
- // => try to show them now
- if (attributesShowAsIcons || noAttributeIconsFound) {
- showAttributeIcons(attributeBox, attributeBoxMaxWidth);
- } else {
- showAttributeDescriptions(attributeBox);
- }
- }
-
- /**
- * lazy-creates the layout holding the icons of the caches attributes
- * and makes it visible
- */
- private void showAttributeIcons(final LinearLayout attribBox, final int parentWidth) {
- if (attributeIconsLayout == null) {
- attributeIconsLayout = createAttributeIconsLayout(parentWidth);
- // no matching icons found? show text
- if (noAttributeIconsFound) {
- showAttributeDescriptions(attribBox);
- return;
- }
- }
- attribBox.removeAllViews();
- attribBox.addView(attributeIconsLayout);
- attributesShowAsIcons = true;
- }
-
- /**
- * lazy-creates the layout holding the descriptions of the caches attributes
- * and makes it visible
- */
- private void showAttributeDescriptions(final LinearLayout attribBox) {
- if (attributeDescriptionsLayout == null) {
- attributeDescriptionsLayout = createAttributeDescriptionsLayout(attribBox);
- }
- attribBox.removeAllViews();
- attribBox.addView(attributeDescriptionsLayout);
- attributesShowAsIcons = false;
- }
-
- /**
- * toggle attribute descriptions and icons
- */
- private void toggleAttributeDisplay(final LinearLayout attribBox, final int parentWidth) {
- // Don't toggle when there are no icons to show.
- if (noAttributeIconsFound) {
- return;
- }
-
- // toggle
- if (attributesShowAsIcons) {
- showAttributeDescriptions(attribBox);
- } else {
- showAttributeIcons(attribBox, parentWidth);
- }
- }
-
- private ViewGroup createAttributeIconsLayout(final int parentWidth) {
- final LinearLayout rows = new LinearLayout(CacheDetailActivity.this);
- rows.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
- rows.setOrientation(LinearLayout.VERTICAL);
-
- LinearLayout attributeRow = newAttributeIconsRow();
- rows.addView(attributeRow);
-
- noAttributeIconsFound = true;
-
- for (final String attributeName : cache.getAttributes()) {
- // check if another attribute icon fits in this row
- attributeRow.measure(0, 0);
- final int rowWidth = attributeRow.getMeasuredWidth();
- final FrameLayout fl = (FrameLayout) getLayoutInflater().inflate(R.layout.attribute_image, attributeRow, false);
- final ImageView iv = (ImageView) fl.getChildAt(0);
- if ((parentWidth - rowWidth) < iv.getLayoutParams().width) {
- // make a new row
- attributeRow = newAttributeIconsRow();
- rows.addView(attributeRow);
- }
-
- final boolean strikeThrough = !CacheAttribute.isEnabled(attributeName);
- final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName));
- if (attrib != null) {
- noAttributeIconsFound = false;
- Drawable drawable = res.getDrawable(attrib.drawableId);
- iv.setImageDrawable(drawable);
- // strike through?
- if (strikeThrough) {
- // generate strike through image with same properties as attribute image
- final ImageView strikeThroughImage = new ImageView(CacheDetailActivity.this);
- strikeThroughImage.setLayoutParams(iv.getLayoutParams());
- drawable = res.getDrawable(R.drawable.attribute__strikethru);
- strikeThroughImage.setImageDrawable(drawable);
- fl.addView(strikeThroughImage);
- }
- } else {
- iv.setImageDrawable(res.getDrawable(R.drawable.attribute_unknown));
- }
-
- attributeRow.addView(fl);
- }
-
- return rows;
- }
-
- private LinearLayout newAttributeIconsRow() {
- final LinearLayout rowLayout = new LinearLayout(CacheDetailActivity.this);
- rowLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.WRAP_CONTENT));
- rowLayout.setOrientation(LinearLayout.HORIZONTAL);
- return rowLayout;
- }
-
- private ViewGroup createAttributeDescriptionsLayout(final LinearLayout parentView) {
- final LinearLayout descriptions = (LinearLayout) getLayoutInflater().inflate(
- R.layout.attribute_descriptions, parentView, false);
- final TextView attribView = (TextView) descriptions.getChildAt(0);
-
- final StringBuilder buffer = new StringBuilder();
- for (String attributeName : cache.getAttributes()) {
- final boolean enabled = CacheAttribute.isEnabled(attributeName);
- // search for a translation of the attribute
- final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName));
- if (attrib != null) {
- attributeName = attrib.getL10n(enabled);
- }
- if (buffer.length() > 0) {
- buffer.append('\n');
- }
- buffer.append(attributeName);
- }
-
- attribView.setText(buffer);
-
- return descriptions;
- }
- }
-
private void refreshCache() {
if (progress.isShowing()) {
showToast(res.getString(R.string.err_detail_still_working));
@@ -916,7 +749,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
progress.show(this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage());
- cache.refresh(refreshCacheHandler, RxUtils.networkScheduler);
+ cache.refresh(refreshCacheHandler, RxUtils.refreshScheduler);
}
private void dropCache() {
@@ -1043,11 +876,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
// cache attributes
- if (!cache.getAttributes().isEmpty()) {
- final LinearLayout innerLayout = ButterKnife.findById(view, R.id.attributes_innerbox);
- new AttributeViewBuilder().fillView(innerLayout);
- view.findViewById(R.id.attributes_box).setVisibility(View.VISIBLE);
- }
+ updateAttributesText();
+ updateAttributesIcons();
+ ButterKnife.findById(view, R.id.attributes_box).setVisibility(cache.getAttributes().isEmpty() ? View.GONE : View.VISIBLE);
updateOfflineBox(view, cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener());
@@ -1086,6 +917,61 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return view;
}
+ private void updateAttributesIcons() {
+ final GridView gridView = ButterKnife.findById(view, R.id.attributes_grid);
+ final List<String> attributes = cache.getAttributes();
+ if (attributes.isEmpty()) {
+ gridView.setVisibility(View.GONE);
+ return;
+ }
+ gridView.setAdapter(new AttributesGridAdapter(CacheDetailActivity.this, cache));
+ gridView.setVisibility(View.VISIBLE);
+ gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(final android.widget.AdapterView<?> parent, final View view, final int position, final long id) {
+ toggleAttributesView();
+ }
+ });
+ }
+
+ protected void toggleAttributesView() {
+ final View textView = ButterKnife.findById(view, R.id.attributes_text);
+ textView.setVisibility(textView.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
+ final View gridView = ButterKnife.findById(view, R.id.attributes_grid);
+ gridView.setVisibility(gridView.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
+ }
+
+ private void updateAttributesText() {
+ final TextView attribView = ButterKnife.findById(view, R.id.attributes_text);
+ final List<String> attributes = cache.getAttributes();
+ if (attributes.isEmpty()) {
+ attribView.setVisibility(View.GONE);
+ return;
+ }
+ final StringBuilder text = new StringBuilder();
+ for (String attributeName : attributes) {
+ final boolean enabled = CacheAttribute.isEnabled(attributeName);
+ // search for a translation of the attribute
+ final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName));
+ if (attrib != null) {
+ attributeName = attrib.getL10n(enabled);
+ }
+ if (text.length() > 0) {
+ text.append('\n');
+ }
+ text.append(attributeName);
+ }
+ attribView.setText(text);
+ attribView.setVisibility(View.GONE);
+ attribView.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(final View v) {
+ toggleAttributesView();
+ }
+ });
+ }
+
private class StoreCacheClickListener implements View.OnClickListener {
@Override
public void onClick(final View arg0) {
@@ -1304,11 +1190,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
buttonRemove.setEnabled(false);
buttonRemove.setVisibility(View.GONE);
}
-
}
/**
- * Show/hide buttons, set text in favourite line and box
+ * Show/hide buttons, set text in favorite line and box
*/
private void updateFavPointBox() {
// Favorite counts
@@ -1361,12 +1246,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// update text
final TextView text = ButterKnife.findById(view, R.id.list_text);
final StoredList list = DataStore.getList(cache.getListId());
- if (list != null) {
- text.setText(res.getString(R.string.cache_list_text) + " " + list.title);
- } else {
- // this should not happen
- text.setText(R.string.cache_list_unknown);
- }
+ text.setText(res.getString(R.string.cache_list_text) + " " + list.title);
} else {
// hide box
box.setVisibility(View.GONE);
diff --git a/main/src/cgeo/geocaching/CacheListActivity.java b/main/src/cgeo/geocaching/CacheListActivity.java
index c8f1101..4b84d08 100644
--- a/main/src/cgeo/geocaching/CacheListActivity.java
+++ b/main/src/cgeo/geocaching/CacheListActivity.java
@@ -27,7 +27,6 @@ import cgeo.geocaching.list.PseudoList;
import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.loaders.AbstractSearchLoader;
import cgeo.geocaching.loaders.AbstractSearchLoader.CacheListLoaderType;
-import cgeo.geocaching.loaders.AddressGeocacheListLoader;
import cgeo.geocaching.loaders.CoordsGeocacheListLoader;
import cgeo.geocaching.loaders.FinderGeocacheListLoader;
import cgeo.geocaching.loaders.HistoryGeocacheListLoader;
@@ -44,6 +43,7 @@ import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Send2CgeoDownloader;
import cgeo.geocaching.sensors.GeoData;
import cgeo.geocaching.sensors.GeoDirHandler;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.settings.SettingsActivity;
import cgeo.geocaching.sorting.CacheComparator;
@@ -296,21 +296,18 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
progress.setMessage(res.getString(R.string.caches_downloading) + " " + res.getQuantityString(R.plurals.caches_eta_mins, minutesRemaining, minutesRemaining));
}
} else {
- new AsyncTask<Void, Void, Void>() {
+ new AsyncTask<Void, Void, Set<Geocache>>() {
@Override
- protected Void doInBackground(final Void... params) {
- if (search != null) {
- final Set<Geocache> cacheListTmp = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
- if (CollectionUtils.isNotEmpty(cacheListTmp)) {
- cacheList.clear();
- cacheList.addAll(cacheListTmp);
- }
- }
- return null;
+ protected Set<Geocache> doInBackground(final Void... params) {
+ return search != null ? search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB) : null;
}
@Override
- protected void onPostExecute(final Void result) {
+ protected void onPostExecute(final Set<Geocache> result) {
+ if (CollectionUtils.isNotEmpty(result)) {
+ cacheList.clear();
+ cacheList.addAll(result);
+ }
setAdapterCurrentCoordinates(false);
showProgress(false);
@@ -412,7 +409,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
}
if (type == CacheListType.NEAREST) {
- coords = CgeoApplication.getInstance().currentGeo().getCoords();
+ coords = Sensors.getInstance().currentGeo().getCoords();
}
setTitle(title);
@@ -542,7 +539,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
}
private void setAdapterCurrentCoordinates(final boolean forceSort) {
- adapter.setActualCoordinates(app.currentGeo().getCoords());
+ adapter.setActualCoordinates(Sensors.getInstance().currentGeo().getCoords());
if (forceSort) {
adapter.forceSort();
}
@@ -1295,9 +1292,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
title = res.getString(R.string.list_all_lists);
} else {
final StoredList list = DataStore.getList(id);
- if (list == null) {
- return;
- }
listId = list.id;
title = list.title;
}
@@ -1549,12 +1543,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA
} else {
title = coords.toString();
}
- if (coords != null) {
- loader = new CoordsGeocacheListLoader(app, coords);
- }
- else {
- loader = new AddressGeocacheListLoader(app, address);
- }
+ loader = new CoordsGeocacheListLoader(app, coords);
break;
case FINDER:
final String username = extras.getString(Intents.EXTRA_USERNAME);
diff --git a/main/src/cgeo/geocaching/CacheMenuHandler.java b/main/src/cgeo/geocaching/CacheMenuHandler.java
index 82eb061..fa2f994 100644
--- a/main/src/cgeo/geocaching/CacheMenuHandler.java
+++ b/main/src/cgeo/geocaching/CacheMenuHandler.java
@@ -90,7 +90,6 @@ public final class CacheMenuHandler extends AbstractUIFactory {
menu.findItem(R.id.menu_navigate).setVisible(hasCoords);
menu.findItem(R.id.menu_caches_around).setVisible(hasCoords && cache.supportsCachesAround());
menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar());
- menu.findItem(R.id.menu_show_in_browser).setVisible(cache.canOpenInBrowser());
menu.findItem(R.id.menu_log_visit).setVisible(cache.supportsLogging() && !Settings.getLogOffline());
menu.findItem(R.id.menu_log_visit_offline).setVisible(cache.supportsLogging() && Settings.getLogOffline());
diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java
index eea8154..2217e11 100644
--- a/main/src/cgeo/geocaching/CgeoApplication.java
+++ b/main/src/cgeo/geocaching/CgeoApplication.java
@@ -1,12 +1,6 @@
package cgeo.geocaching;
-import cgeo.geocaching.playservices.LocationProvider;
-import cgeo.geocaching.sensors.GeoData;
-import cgeo.geocaching.sensors.GeoDataProvider;
-import cgeo.geocaching.sensors.GpsStatusProvider;
-import cgeo.geocaching.sensors.GpsStatusProvider.Status;
-import cgeo.geocaching.sensors.OrientationProvider;
-import cgeo.geocaching.sensors.RotationProvider;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.OOMDumpingUncaughtExceptionHandler;
@@ -17,10 +11,6 @@ import com.google.android.gms.common.GooglePlayServicesUtil;
import org.eclipse.jdt.annotation.NonNull;
-import rx.Observable;
-import rx.functions.Action1;
-import rx.functions.Func1;
-
import android.app.Application;
import android.view.ViewConfiguration;
@@ -32,21 +22,7 @@ public class CgeoApplication extends Application {
public boolean showLoginToast = true; //login toast shown just once.
private boolean liveMapHintShownInThisSession = false; // livemap hint has been shown
private static CgeoApplication instance;
- private Observable<GeoData> geoDataObservable;
- private Observable<GeoData> geoDataObservableLowPower;
- private Observable<Float> directionObservable;
- private Observable<Status> gpsStatusObservable;
- @NonNull private volatile GeoData currentGeo = GeoData.DUMMY_LOCATION;
- private volatile boolean hasValidLocation = false;
- private volatile float currentDirection = 0.0f;
private boolean isGooglePlayServicesAvailable = false;
- private final Action1<GeoData> rememberGeodataAction = new Action1<GeoData>() {
- @Override
- public void call(final GeoData geoData) {
- currentGeo = geoData;
- hasValidLocation = true;
- }
- };
public static void dumpOnOutOfMemory(final boolean enable) {
@@ -66,7 +42,7 @@ public class CgeoApplication extends Application {
setInstance(this);
}
- private static void setInstance(final CgeoApplication application) {
+ private static void setInstance(@NonNull final CgeoApplication application) {
instance = application;
}
@@ -95,47 +71,14 @@ public class CgeoApplication extends Application {
isGooglePlayServicesAvailable = true;
}
Log.i("Google Play services are " + (isGooglePlayServicesAvailable ? "" : "not ") + "available");
- setupGeoDataObservables(Settings.useGooglePlayServices(), Settings.useLowPowerMode());
- setupDirectionObservable(Settings.useLowPowerMode());
- gpsStatusObservable = GpsStatusProvider.create(this).replay(1).refCount();
+ final Sensors sensors = Sensors.getInstance();
+ sensors.setupGeoDataObservables(Settings.useGooglePlayServices(), Settings.useLowPowerMode());
+ sensors.setupDirectionObservable(Settings.useLowPowerMode());
// Attempt to acquire an initial location before any real activity happens.
- geoDataObservableLowPower.subscribeOn(RxUtils.looperCallbacksScheduler).first().subscribe();
- }
-
- public void setupGeoDataObservables(final boolean useGooglePlayServices, final boolean useLowPowerLocation) {
- if (useGooglePlayServices) {
- geoDataObservable = LocationProvider.getMostPrecise(this).doOnNext(rememberGeodataAction);
- if (useLowPowerLocation) {
- geoDataObservableLowPower = LocationProvider.getLowPower(this).doOnNext(rememberGeodataAction);
- } else {
- geoDataObservableLowPower = geoDataObservable;
- }
- } else {
- geoDataObservable = RxUtils.rememberLast(GeoDataProvider.create(this).doOnNext(rememberGeodataAction));
- geoDataObservableLowPower = geoDataObservable;
- }
+ sensors.geoDataObservable(true).subscribeOn(RxUtils.looperCallbacksScheduler).first().subscribe();
}
- public void setupDirectionObservable(final boolean useLowPower) {
- directionObservable = RxUtils.rememberLast(RotationProvider.create(this, useLowPower).onErrorResumeNext(new Func1<Throwable, Observable<? extends Float>>() {
- @Override
- public Observable<? extends Float> call(final Throwable throwable) {
- return OrientationProvider.create(CgeoApplication.this);
- }
- }).onErrorResumeNext(new Func1<Throwable, Observable<? extends Float>>() {
- @Override
- public Observable<? extends Float> call(final Throwable throwable) {
- Log.e("Device orientation will not be available as no suitable sensors were found");
- return Observable.<Float>never().startWith(0.0f);
- }
- }).doOnNext(new Action1<Float>() {
- @Override
- public void call(final Float direction) {
- currentDirection = direction;
- }
- }));
- }
@Override
public void onLowMemory() {
@@ -143,34 +86,6 @@ public class CgeoApplication extends Application {
DataStore.removeAllFromCache();
}
- public Observable<GeoData> geoDataObservable(final boolean lowPower) {
- return lowPower ? geoDataObservableLowPower : geoDataObservable;
- }
-
- public Observable<Float> directionObservable() {
- return directionObservable;
- }
-
- public Observable<Status> gpsStatusObservable() {
- if (gpsStatusObservable == null) {
- gpsStatusObservable = GpsStatusProvider.create(this).share();
- }
- return gpsStatusObservable;
- }
-
- @NonNull
- public GeoData currentGeo() {
- return currentGeo;
- }
-
- public boolean hasValidLocation() {
- return hasValidLocation;
- }
-
- public float currentDirection() {
- return currentDirection;
- }
-
public boolean isLiveMapHintShownInThisSession() {
return liveMapHintShownInThisSession;
}
diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java
index 1a1bad2..8b0fc73 100644
--- a/main/src/cgeo/geocaching/CompassActivity.java
+++ b/main/src/cgeo/geocaching/CompassActivity.java
@@ -11,6 +11,7 @@ import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.sensors.GeoData;
import cgeo.geocaching.sensors.GeoDirHandler;
import cgeo.geocaching.sensors.GpsStatusProvider.Status;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.speech.SpeechService;
import cgeo.geocaching.ui.CompassView;
@@ -29,8 +30,6 @@ import rx.functions.Action1;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
import android.media.AudioManager;
import android.os.Bundle;
import android.view.Menu;
@@ -59,7 +58,6 @@ public class CompassActivity extends AbstractActionBarActivity {
private Geocache cache = null;
private Geopoint dstCoords = null;
private float cacheHeading = 0;
- private boolean hasMagneticFieldSensor;
private String description;
@Override
@@ -67,12 +65,6 @@ public class CompassActivity extends AbstractActionBarActivity {
super.onCreate(savedInstanceState, R.layout.compass_activity);
ButterKnife.inject(this);
- final SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
- hasMagneticFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null;
- if (!hasMagneticFieldSensor) {
- Settings.setUseCompass(false);
- }
-
// get parameters
final Bundle extras = getIntent().getExtras();
if (extras == null) {
@@ -89,12 +81,13 @@ public class CompassActivity extends AbstractActionBarActivity {
// find the wanted navigation target
if (extras.containsKey(Intents.EXTRA_WAYPOINT_ID)) {
final int waypointId = extras.getInt(Intents.EXTRA_WAYPOINT_ID);
- setTarget(DataStore.loadWaypoint(waypointId));
+ final Waypoint waypoint = DataStore.loadWaypoint(waypointId);
+ if (waypoint != null) {
+ setTarget(waypoint);
+ }
}
else if (extras.containsKey(Intents.EXTRA_COORDS)) {
- final Geopoint coords = extras.getParcelable(Intents.EXTRA_COORDS);
- final String description = extras.getString(Intents.EXTRA_DESCRIPTION);
- setTarget(coords, description);
+ setTarget(extras.<Geopoint>getParcelable(Intents.EXTRA_COORDS), extras.getString(Intents.EXTRA_DESCRIPTION));
}
else {
setTarget(cache);
@@ -115,7 +108,7 @@ public class CompassActivity extends AbstractActionBarActivity {
@Override
public void onResume() {
super.onResume(geoDirHandler.start(GeoDirHandler.UPDATE_GEODIR),
- app.gpsStatusObservable().observeOn(AndroidSchedulers.mainThread()).subscribe(gpsStatusHandler));
+ Sensors.getInstance().gpsStatusObservable().observeOn(AndroidSchedulers.mainThread()).subscribe(gpsStatusHandler));
forceRefresh();
}
@@ -139,15 +132,14 @@ public class CompassActivity extends AbstractActionBarActivity {
private void forceRefresh() {
// Force a refresh of location and direction when data is available.
- final CgeoApplication app = CgeoApplication.getInstance();
- final GeoData geo = app.currentGeo();
- geoDirHandler.updateGeoDir(geo, app.currentDirection());
+ final Sensors sensors = Sensors.getInstance();
+ geoDirHandler.updateGeoDir(sensors.currentGeo(), sensors.currentDirection());
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.compass_activity_options, menu);
- menu.findItem(R.id.menu_compass_sensor).setVisible(hasMagneticFieldSensor);
+ menu.findItem(R.id.menu_compass_sensor).setVisible(Sensors.getInstance().hasMagneticFieldSensor());
if (cache != null) {
LoggingUI.addMenuItems(this, menu, cache);
}
@@ -226,12 +218,12 @@ public class CompassActivity extends AbstractActionBarActivity {
return super.onOptionsItemSelected(item);
}
- private void setTarget(final Geopoint coords, final String description) {
+ private void setTarget(@NonNull final Geopoint coords, final String newDescription) {
setDestCoords(coords);
- setTargetDescription(description);
- updateDistanceInfo(app.currentGeo());
+ setTargetDescription(newDescription);
+ updateDistanceInfo(Sensors.getInstance().currentGeo());
- Log.d("destination set: " + description + " (" + dstCoords + ")");
+ Log.d("destination set: " + newDescription + " (" + dstCoords + ")");
}
private void setTarget(final @NonNull Waypoint waypoint) {
@@ -253,12 +245,12 @@ public class CompassActivity extends AbstractActionBarActivity {
private void setTargetDescription(final @Nullable String newDescription) {
description = newDescription;
- if (description == null) {
+ if (this.description == null) {
cacheInfoView.setVisibility(View.GONE);
return;
}
cacheInfoView.setVisibility(View.VISIBLE);
- cacheInfoView.setText(description);
+ cacheInfoView.setText(this.description);
}
private void updateDistanceInfo(final GeoData geo) {
diff --git a/main/src/cgeo/geocaching/CreateShortcutActivity.java b/main/src/cgeo/geocaching/CreateShortcutActivity.java
index 01754e2..70ab900 100644
--- a/main/src/cgeo/geocaching/CreateShortcutActivity.java
+++ b/main/src/cgeo/geocaching/CreateShortcutActivity.java
@@ -99,9 +99,6 @@ public class CreateShortcutActivity extends AbstractActionBarActivity {
protected void createOfflineListShortcut(final int listId) {
final StoredList list = DataStore.getList(listId);
- if (list == null) {
- return;
- }
// target to be executed by the shortcut
final Intent targetIntent = new Intent(this, CacheListActivity.class);
targetIntent.putExtra(Intents.EXTRA_LIST_ID, list.id);
diff --git a/main/src/cgeo/geocaching/DataStore.java b/main/src/cgeo/geocaching/DataStore.java
index 3403f3a..b5a4a7a 100644
--- a/main/src/cgeo/geocaching/DataStore.java
+++ b/main/src/cgeo/geocaching/DataStore.java
@@ -374,6 +374,7 @@ public class DataStore {
database = null;
}
+ @NonNull
public static File getBackupFileInternal() {
return new File(LocalStorage.getStorage(), "cgeo.sqlite");
}
@@ -441,14 +442,17 @@ public class DataStore {
});
}
+ @NonNull
private static File databasePath(final boolean internal) {
return new File(internal ? LocalStorage.getInternalDbDirectory() : LocalStorage.getExternalDbDirectory(), dbName);
}
+ @NonNull
private static File databasePath() {
return databasePath(!Settings.isDbOnSDCard());
}
+ @NonNull
private static File databaseAlternatePath() {
return databasePath(Settings.isDbOnSDCard());
}
@@ -1029,6 +1033,7 @@ public class DataStore {
return false;
}
+ @Nullable
public static String getGeocodeForGuid(final String guid) {
if (StringUtils.isBlank(guid)) {
return null;
@@ -1104,7 +1109,9 @@ public class DataStore {
for (final Geocache cache : caches) {
final String geocode = cache.getGeocode();
final Geocache existingCache = existingCaches.get(geocode);
- final boolean dbUpdateRequired = !cache.gatherMissingFrom(existingCache) || cacheCache.getCacheFromCache(geocode) != null;
+ boolean dbUpdateRequired = !cache.gatherMissingFrom(existingCache) || cacheCache.getCacheFromCache(geocode) != null;
+ // parse the note AFTER merging the local information in
+ dbUpdateRequired |= cache.parseWaypointsFromNote();
cache.addStorageLocation(StorageLocation.CACHE);
cacheCache.putCacheInCache(cache);
@@ -1150,7 +1157,7 @@ public class DataStore {
values.put("hidden", hiddenDate.getTime());
}
values.put("hint", cache.getHint());
- values.put("size", cache.getSize() == null ? "" : cache.getSize().id);
+ values.put("size", cache.getSize().id);
values.put("difficulty", cache.getDifficulty());
values.put("terrain", cache.getTerrain());
values.put("location", cache.getLocation());
@@ -1340,6 +1347,7 @@ public class DataStore {
* index of the longitude column
* @return the coordinates, or null if latitude or longitude is null or the coordinates are invalid
*/
+ @Nullable
private static Geopoint getCoords(final Cursor cursor, final int indexLat, final int indexLon) {
if (cursor.isNull(indexLat) || cursor.isNull(indexLon)) {
return null;
@@ -1517,6 +1525,7 @@ public class DataStore {
}
}
+ @Nullable
public static Viewport getBounds(final Set<String> geocodes) {
if (CollectionUtils.isEmpty(geocodes)) {
return null;
@@ -1533,6 +1542,7 @@ public class DataStore {
* The Geocode GCXXXX
* @return the loaded cache (if found). Can be null
*/
+ @Nullable
public static Geocache loadCache(final String geocode, final EnumSet<LoadFlag> loadFlags) {
if (StringUtils.isBlank(geocode)) {
throw new IllegalArgumentException("geocode must not be empty");
@@ -1548,6 +1558,7 @@ public class DataStore {
* @param geocodes
* @return Set of loaded caches. Never null.
*/
+ @NonNull
public static Set<Geocache> loadCaches(final Collection<String> geocodes, final EnumSet<LoadFlag> loadFlags) {
if (CollectionUtils.isEmpty(geocodes)) {
return new HashSet<>();
@@ -1604,6 +1615,7 @@ public class DataStore {
* @param loadFlags
* @return Set of loaded caches. Never null.
*/
+ @NonNull
private static Set<Geocache> loadCachesFromGeocodes(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) {
if (CollectionUtils.isEmpty(geocodes)) {
return Collections.emptySet();
@@ -1695,6 +1707,7 @@ public class DataStore {
* @return
*/
+ @NonNull
private static StringBuilder buildCoordinateWhere(final String dbTable, final Viewport viewport) {
return viewport.resize(1.5).sqlWhere(dbTable);
}
@@ -1705,6 +1718,7 @@ public class DataStore {
* @param cursor
* @return Cache from DB
*/
+ @NonNull
private static Geocache createCacheFromDatabaseContent(final Cursor cursor) {
final Geocache cache = new Geocache();
@@ -1766,6 +1780,7 @@ public class DataStore {
return cache;
}
+ @Nullable
public static List<String> loadAttributes(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
@@ -1783,6 +1798,7 @@ public class DataStore {
GET_STRING_0);
}
+ @Nullable
public static Waypoint loadWaypoint(final int id) {
if (id == 0) {
return null;
@@ -1809,6 +1825,7 @@ public class DataStore {
return waypoint;
}
+ @Nullable
public static List<Waypoint> loadWaypoints(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
@@ -1831,6 +1848,7 @@ public class DataStore {
});
}
+ @NonNull
private static Waypoint createWaypointFromDatabaseContent(final Cursor cursor) {
final String name = cursor.getString(cursor.getColumnIndex("name"));
final WaypointType type = WaypointType.findById(cursor.getString(cursor.getColumnIndex("type")));
@@ -1847,6 +1865,7 @@ public class DataStore {
return waypoint;
}
+ @Nullable
private static List<Image> loadSpoilers(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
@@ -1875,6 +1894,7 @@ public class DataStore {
*
* @return A list of previously entered destinations or an empty list.
*/
+ @NonNull
public static List<Destination> loadHistoryOfSearchedLocations() {
return queryToColl(dbTableSearchDestinationHistory,
new String[]{"_id", "date", "latitude", "longitude"},
@@ -1953,6 +1973,7 @@ public class DataStore {
return Collections.unmodifiableList(logs);
}
+ @Nullable
public static Map<LogType, Integer> loadLogCounts(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
@@ -1981,6 +2002,7 @@ public class DataStore {
return logCounts;
}
+ @Nullable
private static List<Trackable> loadInventory(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
@@ -2034,6 +2056,7 @@ public class DataStore {
return trackable;
}
+ @NonNull
private static Trackable createTrackableFromDatabaseContent(final Cursor cursor) {
final Trackable trackable = new Trackable();
trackable.setGeocode(cursor.getString(cursor.getColumnIndex("tbcode")));
@@ -2113,6 +2136,7 @@ public class DataStore {
return 0;
}
+ @NonNull
private static<T, U extends Collection<? super T>> U queryToColl(@NonNull final String table,
final String[] columns,
final String selection,
@@ -2148,6 +2172,7 @@ public class DataStore {
* @param listId
* @return a non-null set of geocodes
*/
+ @NonNull
private static Set<String> loadBatchOfStoredGeocodes(final Geopoint coords, final CacheType cacheType, final int listId) {
if (cacheType == null) {
throw new IllegalArgumentException("cacheType must not be null");
@@ -2194,6 +2219,7 @@ public class DataStore {
}
}
+ @NonNull
private static Set<String> loadBatchOfHistoricGeocodes(final boolean detailedOnly, final CacheType cacheType) {
final StringBuilder selection = new StringBuilder("visiteddate > 0");
@@ -2225,11 +2251,13 @@ public class DataStore {
}
/** Retrieve all stored caches from DB */
+ @NonNull
public static SearchResult loadCachedInViewport(final Viewport viewport, final CacheType cacheType) {
return loadInViewport(false, viewport, cacheType);
}
/** Retrieve stored caches from DB with listId >= 1 */
+ @NonNull
public static SearchResult loadStoredInViewport(final Viewport viewport, final CacheType cacheType) {
return loadInViewport(true, viewport, cacheType);
}
@@ -2242,6 +2270,7 @@ public class DataStore {
* @param cacheType the cache type
* @return the matching caches
*/
+ @NonNull
private static SearchResult loadInViewport(final boolean stored, final Viewport viewport, final CacheType cacheType) {
final Set<String> geocodes = new HashSet<>();
@@ -2335,6 +2364,9 @@ public class DataStore {
Log.d("Database clean: removing obsolete log images records");
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"));
+
if (version > -1) {
Settings.setVersion(version);
}
@@ -2353,7 +2385,8 @@ public class DataStore {
* @param geocodes
* @return
*/
- private static Set<String> exceptCachesWithOfflineLog(final Set<String> geocodes) {
+ @NonNull
+ private static Set<String> exceptCachesWithOfflineLog(@NonNull final Set<String> geocodes) {
if (geocodes.isEmpty()) {
return geocodes;
}
@@ -2462,6 +2495,7 @@ public class DataStore {
return id != -1;
}
+ @Nullable
public static LogEntry loadLogOffline(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
@@ -2580,6 +2614,7 @@ public class DataStore {
return lists;
}
+ @NonNull
private static ArrayList<StoredList> getListsFromCursor(final Cursor cursor) {
final int indexId = cursor.getColumnIndex("_id");
final int indexTitle = cursor.getColumnIndex("title");
@@ -2593,6 +2628,7 @@ public class DataStore {
});
}
+ @NonNull
public static StoredList getList(final int id) {
init();
if (id >= customListIdOffset) {
@@ -2616,11 +2652,7 @@ public class DataStore {
}
// fall back to standard list in case of invalid list id
- if (id == StoredList.STANDARD_LIST_ID || id >= customListIdOffset) {
- return new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatement.COUNT_CACHES_ON_STANDARD_LIST.simpleQueryForLong());
- }
-
- return null;
+ return new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatement.COUNT_CACHES_ON_STANDARD_LIST.simpleQueryForLong());
}
public static int getAllCachesCount() {
@@ -2794,6 +2826,7 @@ public class DataStore {
* @param geocode
* @return
*/
+ @NonNull
public static Geocache loadCacheTexts(final String geocode) {
final Geocache partial = new Geocache();
@@ -2851,6 +2884,7 @@ public class DataStore {
* Creates the WHERE clause for matching multiple geocodes. This automatically converts all given codes to
* UPPERCASE.
*/
+ @NonNull
private static StringBuilder whereGeocodeIn(final Collection<String> geocodes) {
final StringBuilder whereExpr = new StringBuilder("geocode in (");
final Iterator<String> iterator = geocodes.iterator();
@@ -2873,6 +2907,7 @@ public class DataStore {
* @return
*/
+ @NonNull
public static Set<Waypoint> loadWaypoints(final Viewport viewport, final boolean excludeMine, final boolean excludeDisabled, final CacheType type) {
final StringBuilder where = buildCoordinateWhere(dbTableWaypoints, viewport);
if (excludeMine) {
@@ -2969,6 +3004,7 @@ public class DataStore {
moveToList(caches, StoredList.TEMPORARY_LIST.id);
}
+ @Nullable
public static Viewport getBounds(final String geocode) {
if (geocode == null) {
return null;
@@ -2981,11 +3017,13 @@ public class DataStore {
setVisitDate(Arrays.asList(selected), 0);
}
+ @NonNull
public static SearchResult getBatchOfStoredCaches(final Geopoint coords, final CacheType cacheType, final int listId) {
final Set<String> geocodes = DataStore.loadBatchOfStoredGeocodes(coords, cacheType, listId);
return new SearchResult(geocodes, DataStore.getAllStoredCachesCount(cacheType, listId));
}
+ @NonNull
public static SearchResult getHistoryOfCaches(final boolean detailedOnly, final CacheType cacheType) {
final Set<String> geocodes = DataStore.loadBatchOfHistoricGeocodes(detailedOnly, cacheType);
return new SearchResult(geocodes, DataStore.getAllHistoryCachesCount());
@@ -2999,6 +3037,7 @@ public class DataStore {
return false;
}
+ @NonNull
public static Set<String> getCachedMissingFromSearch(final SearchResult searchResult, final Set<Tile> tiles, final IConnector connector, final int maxZoom) {
// get cached CacheListActivity
@@ -3029,6 +3068,7 @@ public class DataStore {
return missingFromSearch;
}
+ @Nullable
public static Cursor findSuggestions(final String searchTerm) {
// require 3 characters, otherwise there are to many results
if (StringUtils.length(searchTerm) < 3) {
@@ -3064,6 +3104,7 @@ public class DataStore {
cursor.close();
}
+ @NonNull
private static String getSuggestionArgument(final String input) {
return "%" + StringUtils.trim(input) + "%";
}
@@ -3091,6 +3132,7 @@ public class DataStore {
cursor.close();
}
+ @NonNull
public static String[] getSuggestions(final String table, final String column, final String input) {
try {
final Cursor cursor = database.rawQuery("SELECT DISTINCT " + column
@@ -3104,22 +3146,27 @@ public class DataStore {
}
}
+ @NonNull
public static String[] getSuggestionsOwnerName(final String input) {
return getSuggestions(dbTableCaches, "owner_real", input);
}
+ @NonNull
public static String[] getSuggestionsTrackableCode(final String input) {
return getSuggestions(dbTableTrackables, "tbcode", input);
}
+ @NonNull
public static String[] getSuggestionsFinderName(final String input) {
return getSuggestions(dbTableLogs, "author", input);
}
+ @NonNull
public static String[] getSuggestionsGeocode(final String input) {
return getSuggestions(dbTableCaches, "geocode", input);
}
+ @NonNull
public static String[] getSuggestionsKeyword(final String input) {
return getSuggestions(dbTableCaches, "name", input);
}
@@ -3128,6 +3175,7 @@ public class DataStore {
*
* @return list of last caches opened in the details view, ordered by most recent first
*/
+ @NonNull
public static ArrayList<Geocache> getLastOpenedCaches() {
final List<String> geocodes = Settings.getLastOpenedCaches();
final Set<Geocache> cachesSet = DataStore.loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB);
diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java
index 7cfb9f9..8cb947a 100644
--- a/main/src/cgeo/geocaching/EditWaypointActivity.java
+++ b/main/src/cgeo/geocaching/EditWaypointActivity.java
@@ -12,6 +12,7 @@ import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.location.GeopointFormatter;
import cgeo.geocaching.sensors.GeoData;
import cgeo.geocaching.sensors.GeoDirHandler;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
import cgeo.geocaching.ui.dialog.Dialogs;
@@ -308,7 +309,7 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C
@Override
protected void onPostExecute(final Geocache cache) {
- final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(cache, geopoint, app.currentGeo());
+ final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(cache, geopoint, Sensors.getInstance().currentGeo());
coordsDialog.setCancelable(true);
coordsDialog.show(getSupportFragmentManager(), "wpeditdialog");
}
@@ -391,7 +392,7 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C
return;
}
} else {
- coords = app.currentGeo().getCoords();
+ coords = Sensors.getInstance().currentGeo().getCoords();
}
if (StringUtils.isNotBlank(bearingText) && StringUtils.isNotBlank(distanceText)) {
diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java
index 69babc4..c842a7f 100644
--- a/main/src/cgeo/geocaching/Geocache.java
+++ b/main/src/cgeo/geocaching/Geocache.java
@@ -98,7 +98,7 @@ public class Geocache implements IWaypoint {
* lazy initialized
*/
private String hint = null;
- private CacheSize size = CacheSize.UNKNOWN;
+ @NonNull private CacheSize size = CacheSize.UNKNOWN;
private float difficulty = 0;
private float terrain = 0;
private Float direction = null;
@@ -271,7 +271,7 @@ public class Geocache implements IWaypoint {
if (!detailed && StringUtils.isBlank(getHint())) {
hint = other.getHint();
}
- if (size == null || CacheSize.UNKNOWN == size) {
+ if (size == CacheSize.UNKNOWN) {
size = other.size;
}
if (difficulty == 0) {
@@ -479,6 +479,7 @@ public class Geocache implements IWaypoint {
notifyChange();
}
+ @NonNull
public List<LogType> getPossibleLogTypes() {
return getConnector().getPossibleLogTypes(this);
}
@@ -502,19 +503,11 @@ public class Geocache implements IWaypoint {
}
}
-
- private String getCacheUrl() {
- return getConnector().getCacheUrl(this);
- }
-
+ @NonNull
private IConnector getConnector() {
return ConnectorFactory.getConnector(this);
}
- public boolean canOpenInBrowser() {
- return getCacheUrl() != null;
- }
-
public boolean supportsRefresh() {
return getConnector() instanceof ISearchByGeocode;
}
@@ -539,6 +532,7 @@ public class Geocache implements IWaypoint {
return getConnector().supportsOwnCoordinates();
}
+ @NonNull
public ILoggingManager getLoggingManager(final LogCacheActivity activity) {
return getConnector().getLoggingManager(activity, this);
}
@@ -559,10 +553,8 @@ public class Geocache implements IWaypoint {
return ownerDisplayName;
}
+ @NonNull
public CacheSize getSize() {
- if (size == null) {
- return CacheSize.UNKNOWN;
- }
return size;
}
@@ -597,7 +589,8 @@ public class Geocache implements IWaypoint {
/**
* @return GC username of the (actual) owner, might differ from the owner. Never empty.
*/
- @NonNull public String getOwnerUserId() {
+ @NonNull
+ public String getOwnerUserId() {
return ownerUserId;
}
@@ -706,6 +699,8 @@ public class Geocache implements IWaypoint {
fromActivity.startActivity(Intent.createChooser(intent, res.getText(R.string.cache_menu_share)));
}
+
+ @NonNull
public Intent getShareIntent() {
final StringBuilder subject = new StringBuilder("Geocache ");
subject.append(geocode);
@@ -721,15 +716,20 @@ public class Geocache implements IWaypoint {
return intent;
}
+ @NonNull
public String getUrl() {
return getConnector().getCacheUrl(this);
}
+ @NonNull
public String getLongUrl() {
return getConnector().getLongCacheUrl(this);
}
- public String getCgeoUrl() { return getConnector().getCacheUrl(this); }
+ @NonNull
+ public String getCgeoUrl() {
+ return getConnector().getCacheUrl(this);
+ }
public boolean supportsGCVote() {
return StringUtils.startsWithIgnoreCase(geocode, "GC");
@@ -760,6 +760,7 @@ public class Geocache implements IWaypoint {
return hidden;
}
+ @NonNull
public List<String> getAttributes() {
return attributes.getUnderlyingList();
}
@@ -775,6 +776,7 @@ public class Geocache implements IWaypoint {
spoilers.add(spoiler);
}
+ @NonNull
public List<Image> getSpoilers() {
return ListUtils.unmodifiableList(ListUtils.emptyIfNull(spoilers));
}
@@ -972,6 +974,7 @@ public class Geocache implements IWaypoint {
*
* @return always non <code>null</code>
*/
+ @NonNull
public List<Waypoint> getWaypoints() {
return waypoints.getUnderlyingList();
}
@@ -1079,13 +1082,8 @@ public class Geocache implements IWaypoint {
this.hint = hint;
}
- public void setSize(final CacheSize size) {
- if (size == null) {
- this.size = CacheSize.UNKNOWN;
- }
- else {
- this.size = size;
- }
+ public void setSize(@NonNull final CacheSize size) {
+ this.size = size;
}
public void setDifficulty(final float difficulty) {
@@ -1368,12 +1366,15 @@ public class Geocache implements IWaypoint {
/**
* Detect coordinates in the personal note and convert them to user defined waypoints. Works by rule of thumb.
*/
- public void parseWaypointsFromNote() {
+ public boolean parseWaypointsFromNote() {
+ boolean changed = false;
for (final Waypoint waypoint : Waypoint.parseWaypointsFromNote(StringUtils.defaultString(getPersonalNote()))) {
if (!hasIdenticalWaypoint(waypoint.getCoords())) {
addOrChangeWaypoint(waypoint, false);
+ changed = true;
}
}
+ return changed;
}
private boolean hasIdenticalWaypoint(final Geopoint point) {
@@ -1475,7 +1476,7 @@ public class Geocache implements IWaypoint {
warnIncorrectParsingIfBlank(getOwnerUserId(), "owner");
warnIncorrectParsingIf(getHiddenDate() == null, "hidden");
warnIncorrectParsingIf(getFavoritePoints() < 0, "favoriteCount");
- warnIncorrectParsingIf(getSize() == null, "size");
+ warnIncorrectParsingIf(getSize() == CacheSize.UNKNOWN, "size");
warnIncorrectParsingIf(getType() == null || getType() == CacheType.UNKNOWN, "type");
warnIncorrectParsingIf(getCoords() == null, "coordinates");
warnIncorrectParsingIfBlank(getLocation(), "location");
@@ -1617,6 +1618,7 @@ public class Geocache implements IWaypoint {
*
* @return start time in minutes after midnight
*/
+ @Nullable
public String guessEventTimeMinutes() {
if (!isEventCache()) {
return null;
@@ -1666,6 +1668,7 @@ public class Geocache implements IWaypoint {
}
};
+ @NonNull
public Collection<Image> getImages() {
final LinkedList<Image> result = new LinkedList<>();
result.addAll(getSpoilers());
@@ -1735,6 +1738,7 @@ public class Geocache implements IWaypoint {
return getConnector().getWaypointGpxId(prefix, geocode);
}
+ @NonNull
public String getWaypointPrefix(final String name) {
return getConnector().getWaypointPrefix(name);
}
@@ -1757,6 +1761,7 @@ public class Geocache implements IWaypoint {
return (getType().applyDistanceRule() || hasUserModifiedCoords()) && getConnector() == GCConnector.getInstance();
}
+ @NonNull
public LogType getDefaultLogType() {
if (isEventCache()) {
final Date eventDate = getHiddenDate();
@@ -1782,7 +1787,8 @@ public class Geocache implements IWaypoint {
* @param caches a collection of caches
* @return the non-blank geocodes of the caches
*/
- public static Set<String> getGeocodes(final Collection<Geocache> caches) {
+ @NonNull
+ public static Set<String> getGeocodes(@NonNull final Collection<Geocache> caches) {
final Set<String> geocodes = new HashSet<>(caches.size());
for (final Geocache cache : caches) {
final String geocode = cache.getGeocode();
diff --git a/main/src/cgeo/geocaching/GpxFileListActivity.java b/main/src/cgeo/geocaching/GpxFileListActivity.java
index 3da4927..352dbab 100644
--- a/main/src/cgeo/geocaching/GpxFileListActivity.java
+++ b/main/src/cgeo/geocaching/GpxFileListActivity.java
@@ -9,6 +9,7 @@ import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.GPXListAdapter;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
@@ -24,7 +25,7 @@ public class GpxFileListActivity extends AbstractFileListActivity<GPXListAdapter
}
@Override
- protected GPXListAdapter getAdapter(List<File> files) {
+ protected GPXListAdapter getAdapter(final List<File> files) {
return new GPXListAdapter(this, files);
}
@@ -33,17 +34,17 @@ public class GpxFileListActivity extends AbstractFileListActivity<GPXListAdapter
return Collections.singletonList(new File(Settings.getGpxImportDir()));
}
- public static void startSubActivity(Activity fromActivity, int listId) {
+ public static void startSubActivity(final Activity fromActivity, final int listId) {
final Intent intent = new Intent(fromActivity, GpxFileListActivity.class);
intent.putExtra(Intents.EXTRA_LIST_ID, StoredList.getConcreteList(listId));
fromActivity.startActivityForResult(intent, 0);
}
@Override
- protected boolean filenameBelongsToList(final String filename) {
+ protected boolean filenameBelongsToList(@NonNull final String filename) {
if (super.filenameBelongsToList(filename)) {
if (StringUtils.endsWithIgnoreCase(filename, GPXImporter.ZIP_FILE_EXTENSION)) {
- for (IConnector connector : ConnectorFactory.getConnectors()) {
+ for (final IConnector connector : ConnectorFactory.getConnectors()) {
if (connector.isZippedGPXFile(filename)) {
return true;
}
diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java
index 996b2d8..118c47b 100644
--- a/main/src/cgeo/geocaching/LogCacheActivity.java
+++ b/main/src/cgeo/geocaching/LogCacheActivity.java
@@ -12,6 +12,8 @@ import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.LogTypeTrackable;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.gcvote.GCVote;
+import cgeo.geocaching.gcvote.GCVoteRatingBarUtil;
+import cgeo.geocaching.gcvote.GCVoteRatingBarUtil.OnRatingChangeListener;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.twitter.Twitter;
import cgeo.geocaching.ui.dialog.DateDialog;
@@ -45,8 +47,6 @@ import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
-import android.widget.RatingBar;
-import android.widget.RatingBar.OnRatingBarChangeListener;
import android.widget.TextView;
import java.util.ArrayList;
@@ -86,7 +86,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
private String imageDescription;
private Uri imageUri;
private boolean sendButtonEnabled;
- private boolean isRatingBarShown = false;
public void onLoadFinished() {
if (loggingManager.hasLoaderError()) {
@@ -286,25 +285,14 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
private void initializeRatingBar() {
- if (GCVote.isVotingPossible(cache) && !isRatingBarShown) {
- final RatingBar ratingBar = ButterKnife.findById(this, R.id.gcvoteRating);
- final TextView label = ButterKnife.findById(this, R.id.gcvoteLabel);
- isRatingBarShown = true;
- ratingBar.setVisibility(View.VISIBLE);
- label.setVisibility(View.VISIBLE);
- ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {
+ if (GCVote.isVotingPossible(cache)) {
+ GCVoteRatingBarUtil.initializeRatingBar(cache, getWindow().getDecorView().getRootView(), new OnRatingChangeListener() {
@Override
- public void onRatingChanged(final RatingBar ratingBar, final float stars, final boolean fromUser) {
- // 0.5 is not a valid rating, therefore we must limit
- rating = GCVote.isValidRating(stars) ? stars : 0;
- if (rating < stars) {
- ratingBar.setRating(rating);
- }
- label.setText(GCVote.getDescription(rating));
+ public void onRatingChanged(final float stars) {
+ rating = stars;
}
});
- ratingBar.setRating(cache.getMyVote());
}
}
diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java
index fde328a..fc4a066 100644
--- a/main/src/cgeo/geocaching/LogTrackableActivity.java
+++ b/main/src/cgeo/geocaching/LogTrackableActivity.java
@@ -136,19 +136,18 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
trackable = DataStore.loadTrackable(geocode);
+ if (trackable == null) {
+ Log.e("LogTrackableActivity.onCreate: cannot load trackable " + geocode);
+ finish();
+ return;
+ }
+
if (StringUtils.isNotBlank(trackable.getName())) {
setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getName());
} else {
setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getGeocode());
}
- if (guid == null) {
- showToast(res.getString(R.string.err_tb_forgot_saw));
-
- finish();
- return;
- }
-
init();
requestKeyboardForLogging();
}
@@ -256,11 +255,6 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
public LoadDataThread() {
super("Load data for logging trackable");
- if (guid == null) {
- showToast(res.getString(R.string.err_tb_forgot_saw));
-
- finish();
- }
}
@Override
diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java
index 321eaca..558c70a 100644
--- a/main/src/cgeo/geocaching/MainActivity.java
+++ b/main/src/cgeo/geocaching/MainActivity.java
@@ -19,6 +19,7 @@ import cgeo.geocaching.sensors.GeoData;
import cgeo.geocaching.sensors.GeoDirHandler;
import cgeo.geocaching.sensors.GpsStatusProvider;
import cgeo.geocaching.sensors.GpsStatusProvider.Status;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.settings.SettingsActivity;
import cgeo.geocaching.ui.dialog.Dialogs;
@@ -113,7 +114,7 @@ public class MainActivity extends AbstractActionBarActivity {
for (final ILogin conn : loginConns) {
- final TextView connectorInfo = (TextView) inflater.inflate(R.layout.main_activity_connectorstatus, null);
+ final TextView connectorInfo = (TextView) inflater.inflate(R.layout.main_activity_connectorstatus, infoArea, false);
infoArea.addView(connectorInfo);
final StringBuilder userInfo = new StringBuilder(conn.getName()).append(Formatter.SEPARATOR);
@@ -226,11 +227,8 @@ public class MainActivity extends AbstractActionBarActivity {
@Override
public void onResume() {
super.onResume(locationUpdater.start(GeoDirHandler.UPDATE_GEODATA | GeoDirHandler.LOW_POWER),
- app.gpsStatusObservable().observeOn(AndroidSchedulers.mainThread()).subscribe(satellitesHandler));
+ Sensors.getInstance().gpsStatusObservable().observeOn(AndroidSchedulers.mainThread()).subscribe(satellitesHandler));
updateUserInfoHandler.sendEmptyMessage(-1);
- if (app.hasValidLocation()) {
- locationUpdater.updateGeoData(app.currentGeo());
- }
startBackgroundLogin();
init();
@@ -239,7 +237,7 @@ public class MainActivity extends AbstractActionBarActivity {
}
private void startBackgroundLogin() {
- assert(app != null);
+ assert app != null;
final boolean mustLogin = app.mustRelog();
@@ -585,8 +583,7 @@ public class MainActivity extends AbstractActionBarActivity {
try {
addCoords = geo.getCoords();
final Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
- final Geopoint coords = app.currentGeo().getCoords();
- final List<Address> addresses = geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 1);
+ final List<Address> addresses = geocoder.getFromLocation(addCoords.getLatitude(), addCoords.getLongitude(), 1);
if (!addresses.isEmpty()) {
subscriber.onNext(formatAddress(addresses.get(0)));
}
diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
index e75d6b1..d92e441 100644
--- a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
+++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
@@ -12,6 +12,7 @@ import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.location.GeopointFormatter;
import cgeo.geocaching.sensors.GeoData;
import cgeo.geocaching.sensors.GeoDirHandler;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.AbstractViewHolder;
import cgeo.geocaching.ui.NavigationActionProvider;
@@ -286,7 +287,7 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen
if (latButton.getText().length() > 0 && lonButton.getText().length() > 0) {
gp = new Geopoint(latButton.getText().toString() + " " + lonButton.getText().toString());
}
- final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, gp, app.currentGeo());
+ final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, gp, Sensors.getInstance().currentGeo());
coordsDialog.setCancelable(true);
coordsDialog.show(getSupportFragmentManager(),"wpedit_dialog");
}
@@ -477,7 +478,7 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen
@Override
public void onClick(final View arg0) {
- final Geopoint coords = app.currentGeo().getCoords();
+ final Geopoint coords = Sensors.getInstance().currentGeo().getCoords();
latButton.setText(coords.format(GeopointFormatter.Format.LAT_DECMINUTE));
lonButton.setText(coords.format(GeopointFormatter.Format.LON_DECMINUTE));
changed = false;
@@ -507,7 +508,7 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen
return null;
}
} else {
- coords = app.currentGeo().getCoords();
+ coords = Sensors.getInstance().currentGeo().getCoords();
}
// apply projection
diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java
index 9de279d..8842603 100644
--- a/main/src/cgeo/geocaching/SearchActivity.java
+++ b/main/src/cgeo/geocaching/SearchActivity.java
@@ -13,6 +13,7 @@ import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.location.GeopointFormatter;
import cgeo.geocaching.search.AutoCompleteAdapter;
import cgeo.geocaching.sensors.GeoData;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
import cgeo.geocaching.ui.dialog.Dialogs;
@@ -144,7 +145,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin
}
final IConnector connector = ConnectorFactory.getConnector(geocode);
- if (connector instanceof ISearchByGeocode) {
+ if (connector instanceof ISearchByGeocode && geocode != null) {
CacheDetailActivity.startActivity(this, geocode.toUpperCase(Locale.US));
return true;
}
@@ -161,7 +162,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin
}
}
- if (trackableConnector != ConnectorFactory.UNKNOWN_TRACKABLE_CONNECTOR) {
+ if (trackableConnector != ConnectorFactory.UNKNOWN_TRACKABLE_CONNECTOR && geocode != null) {
final Intent trackablesIntent = new Intent(this, TrackableActivity.class);
trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, geocode.toUpperCase(Locale.US));
startActivity(trackablesIntent);
@@ -293,7 +294,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin
}
private void updateCoordinates() {
- final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, null, app.currentGeo());
+ final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, null, Sensors.getInstance().currentGeo());
coordsDialog.setCancelable(true);
coordsDialog.show(getSupportFragmentManager(), "wpedit_dialog");
}
@@ -309,7 +310,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin
final String lonText = StringUtils.trim(buttonLongitude.getText().toString());
if (StringUtils.isEmpty(latText) || StringUtils.isEmpty(lonText)) {
- final GeoData geo = app.currentGeo();
+ final GeoData geo = Sensors.getInstance().currentGeo();
buttonLatitude.setText(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE));
buttonLongitude.setText(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE));
} else {
@@ -373,7 +374,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin
}
private void findByGeocodeFn() {
- final String geocodeText = StringUtils.trim(geocodeEditText.getText().toString());
+ final String geocodeText = StringUtils.trimToEmpty(geocodeEditText.getText().toString());
if (StringUtils.isBlank(geocodeText) || geocodeText.equalsIgnoreCase("GC")) {
Dialogs.message(this, R.string.warn_search_help_title, R.string.warn_search_help_gccode);
@@ -384,7 +385,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin
}
private void findTrackableFn() {
- final String trackableText = StringUtils.trim(trackableEditText.getText().toString());
+ final String trackableText = StringUtils.trimToEmpty(trackableEditText.getText().toString());
if (StringUtils.isBlank(trackableText) || trackableText.equalsIgnoreCase("TB")) {
Dialogs.message(this, R.string.warn_search_help_title, R.string.warn_search_help_tb);
diff --git a/main/src/cgeo/geocaching/SelectMapfileActivity.java b/main/src/cgeo/geocaching/SelectMapfileActivity.java
index 697f609..a506f16 100644
--- a/main/src/cgeo/geocaching/SelectMapfileActivity.java
+++ b/main/src/cgeo/geocaching/SelectMapfileActivity.java
@@ -87,7 +87,7 @@ public class SelectMapfileActivity extends AbstractFileListActivity<FileSelectio
for (File dir : LocalStorage.getStorages()) {
folders.add(new File(dir, "mfmaps"));
folders.add(new File(new File(dir, "Locus"), "mapsVector"));
- folders.add(new File(dir, LocalStorage.cache));
+ folders.add(new File(dir, LocalStorage.CACHE_DIRNAME));
}
return folders;
}
diff --git a/main/src/cgeo/geocaching/StaticMapsActivity.java b/main/src/cgeo/geocaching/StaticMapsActivity.java
index 7d822ec..be363f0 100644
--- a/main/src/cgeo/geocaching/StaticMapsActivity.java
+++ b/main/src/cgeo/geocaching/StaticMapsActivity.java
@@ -91,12 +91,14 @@ public class StaticMapsActivity extends AbstractActionBarActivity {
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.staticmaps_activity);
- if (geocode == null) {
- showToast("Sorry, c:geo forgot for what cache you want to load static maps.");
+ cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+
+ if (cache == null) {
+ Log.e("StaticMapsActivity.onCreate: cannot find the cache " + geocode);
finish();
return;
}
- cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+
setCacheTitleBar(cache);
waitDialog = ProgressDialog.show(this, null, res.getString(R.string.map_static_loading), true);
diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java
index fd7b751..5184f71 100644
--- a/main/src/cgeo/geocaching/StaticMapsProvider.java
+++ b/main/src/cgeo/geocaching/StaticMapsProvider.java
@@ -17,6 +17,7 @@ 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;
@@ -38,6 +39,8 @@ public final class StaticMapsProvider {
private static final String MAP_FILENAME_PREFIX = "map_";
private static final String MARKERS_URL = "http://status.cgeo.org/assets/markers/";
+ private static volatile long last403 = 0;
+
/** We assume there is no real usable image with less than 1k. */
private static final int MIN_MAP_IMAGE_BYTES = 1000;
@@ -54,32 +57,43 @@ public final class StaticMapsProvider {
return LocalStorage.getStorageFile(geocode, MAP_FILENAME_PREFIX + prefix, false, createDirs);
}
+ private static <T> Observable<T> checkDownloadPermission(final Observable<T> ifPermitted) {
+ return Observable.defer(new Func0<Observable<T>>() {
+ @Override
+ public Observable<T> call() {
+ if (System.currentTimeMillis() - last403 >= 30000) {
+ return ifPermitted;
+ }
+ Log.d("StaticMaps.downloadMap: request ignored because of recent \"permission denied\" answer");
+ return Observable.empty();
+ }
+ });
+ }
+
private static Observable<String> downloadDifferentZooms(final String geocode, final String markerUrl, final String prefix, final String latlonMap, final int width, final int height, final Parameters waypoints) {
- return Observable.merge(downloadMap(geocode, 20, SATELLITE, markerUrl, prefix + '1', "", latlonMap, width, height, waypoints),
+ return checkDownloadPermission(Observable.merge(downloadMap(geocode, 20, SATELLITE, markerUrl, prefix + '1', "", latlonMap, width, height, waypoints),
downloadMap(geocode, 18, SATELLITE, markerUrl, prefix + '2', "", latlonMap, width, height, waypoints),
downloadMap(geocode, 16, ROADMAP, markerUrl, prefix + '3', "", latlonMap, width, height, waypoints),
downloadMap(geocode, 14, ROADMAP, markerUrl, prefix + '4', "", latlonMap, width, height, waypoints),
- downloadMap(geocode, 11, ROADMAP, markerUrl, prefix + '5', "", latlonMap, width, height, waypoints));
+ downloadMap(geocode, 11, ROADMAP, markerUrl, prefix + '5', "", latlonMap, width, height, waypoints)));
}
private static Observable<String> downloadMap(final String geocode, final int zoom, final String mapType, final String markerUrl, final String prefix, final String shadow, final String latlonMap, final int width, final int height, final Parameters waypoints) {
- int scale = 1;
- if (width > GOOGLE_MAPS_MAX_SIZE) {
- scale = 2;
- }
+ // If it has been less than 30 seconds since we got a 403 (permission denied) from Google servers,
+ // do not try again.
+ final int scale = width <= GOOGLE_MAPS_MAX_SIZE ? 1 : 2;
final float aspectRatio = width / (float) height;
final int requestWidth = Math.min(width / scale, GOOGLE_MAPS_MAX_SIZE);
final int requestHeight = (aspectRatio > 1) ? Math.round(requestWidth / aspectRatio) : requestWidth;
- final int requestScale = scale;
final int requestZoom = Math.min((scale == 2) ? zoom + 1 : zoom, GOOGLE_MAX_ZOOM);
- return Async.fromAction(new Action0() {
+ return checkDownloadPermission(Async.fromAction(new Action0() {
@Override
public void call() {
final Parameters params = new Parameters(
"center", latlonMap,
"zoom", String.valueOf(requestZoom),
"size", String.valueOf(requestWidth) + 'x' + String.valueOf(requestHeight),
- "scale", String.valueOf(requestScale),
+ "scale", String.valueOf(scale),
"maptype", mapType,
"markers", "icon:" + markerUrl + '|' + shadow + latlonMap,
"sensor", "false");
@@ -92,8 +106,12 @@ public final class StaticMapsProvider {
Log.e("StaticMapsProvider.downloadMap: httpResponse is null");
return;
}
- if (httpResponse.getStatusLine().getStatusCode() != 200) {
- Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + httpResponse.getStatusLine().getStatusCode());
+ final int statusCode = httpResponse.getStatusLine().getStatusCode();
+ if (statusCode != 200) {
+ Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + statusCode);
+ if (statusCode == 403) {
+ last403 = System.currentTimeMillis();
+ }
return;
}
final File file = getMapFile(geocode, prefix, true);
@@ -105,7 +123,7 @@ public final class StaticMapsProvider {
}
}
}
- }, prefix, RxUtils.networkScheduler);
+ }, prefix, RxUtils.networkScheduler));
}
public static Observable<String> downloadMaps(final Geocache cache) {
@@ -132,7 +150,7 @@ public final class StaticMapsProvider {
}
- return Observable.merge(downloaders);
+ return checkDownloadPermission(Observable.merge(downloaders));
}
/**
@@ -144,7 +162,7 @@ public final class StaticMapsProvider {
for (final Waypoint waypoint : cache.getWaypoints()) {
downloaders.add(storeWaypointStaticMap(cache.getGeocode(), width, height, waypoint));
}
- return Observable.merge(downloaders);
+ return checkDownloadPermission(Observable.merge(downloaders));
}
public static Observable<String> storeWaypointStaticMap(final Geocache cache, final Waypoint waypoint) {
diff --git a/main/src/cgeo/geocaching/Trackable.java b/main/src/cgeo/geocaching/Trackable.java
index 15416bc..f93ec7b 100644
--- a/main/src/cgeo/geocaching/Trackable.java
+++ b/main/src/cgeo/geocaching/Trackable.java
@@ -42,10 +42,12 @@ public class Trackable implements ILogable {
private List<LogEntry> logs = new ArrayList<>();
private String trackingcode = null;
+ @NonNull
public String getUrl() {
return getConnector().getUrl(this);
}
+ @NonNull
private TrackableConnector getConnector() {
return ConnectorFactory.getConnector(this);
}
@@ -219,6 +221,7 @@ public class Trackable implements ILogable {
this.trackingcode = trackingcode;
}
+ @NonNull
public Collection<Image> getImages() {
final List<Image> images = new LinkedList<>();
if (StringUtils.isNotBlank(image)) {
@@ -231,6 +234,7 @@ public class Trackable implements ILogable {
return images;
}
+ @NonNull
static List<LogType> getPossibleLogTypes() {
final List<LogType> logTypes = new ArrayList<>();
logTypes.add(LogType.RETRIEVED_IT);
diff --git a/main/src/cgeo/geocaching/Waypoint.java b/main/src/cgeo/geocaching/Waypoint.java
index 5cfeb29..5cac4db 100644
--- a/main/src/cgeo/geocaching/Waypoint.java
+++ b/main/src/cgeo/geocaching/Waypoint.java
@@ -97,18 +97,11 @@ public class Waypoint implements IWaypoint {
if (newPrefixes.containsKey(prefix)) {
newPrefixes.get(prefix).merge(oldWaypoint);
} else if (oldWaypoint.isUserDefined() || forceMerge) {
- // personal note waypoints should always be taken from the new list only
- if (!isPersonalNoteWaypoint(oldWaypoint)) {
- newPoints.add(oldWaypoint);
- }
+ newPoints.add(oldWaypoint);
}
}
}
- private static boolean isPersonalNoteWaypoint(final @NonNull Waypoint waypoint) {
- return StringUtils.startsWith(waypoint.getName(), CgeoApplication.getInstance().getString(R.string.cache_personal_note) + " ");
- }
-
public boolean isUserDefined() {
return own || WaypointType.OWN == waypointType;
}
@@ -157,6 +150,7 @@ public class Waypoint implements IWaypoint {
cachedOrder = ORDER_UNDEFINED;
}
+ @NonNull
public String getUrl() {
return "http://www.geocaching.com/seek/cache_details.aspx?wp=" + geocode;
}
@@ -304,7 +298,7 @@ public class Waypoint implements IWaypoint {
((point.getLatitudeE6() % 1000) != 0 || (point.getLongitudeE6() % 1000) != 0)) {
final String name = CgeoApplication.getInstance().getString(R.string.cache_personal_note) + " " + count;
final String potentialWaypointType = note.substring(Math.max(0, matcher.start() - 15));
- final Waypoint waypoint = new Waypoint(name, parseWaypointType(potentialWaypointType), false);
+ final Waypoint waypoint = new Waypoint(name, parseWaypointType(potentialWaypointType), true);
waypoint.setCoords(point);
waypoints.add(waypoint);
count++;
diff --git a/main/src/cgeo/geocaching/WaypointPopupFragment.java b/main/src/cgeo/geocaching/WaypointPopupFragment.java
index 83dad09..227e30d 100644
--- a/main/src/cgeo/geocaching/WaypointPopupFragment.java
+++ b/main/src/cgeo/geocaching/WaypointPopupFragment.java
@@ -60,6 +60,13 @@ public class WaypointPopupFragment extends AbstractDialogFragment {
super.init();
waypoint = DataStore.loadWaypoint(waypointId);
+
+ if (waypoint == null) {
+ Log.e("WaypointPopupFragment.init: unable to get waypoint " + waypointId);
+ getActivity().finish();
+ return;
+ }
+
try {
if (StringUtils.isNotBlank(waypoint.getName())) {
setTitle(waypoint.getName());
diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java
index b135358..14a2fbf 100644
--- a/main/src/cgeo/geocaching/activity/ActivityMixin.java
+++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java
@@ -157,6 +157,15 @@ public final class ActivityMixin {
editText.setSelection(newCursor);
}
+ /**
+ * This is the exact code from Google to implement Up navigation, with one exception: activity.isTaskRoot() was
+ * added as {@link NavUtils#shouldUpRecreateTask(Activity, Intent)} seems not to handle the case, that this activity
+ * 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
final Intent upIntent = NavUtils.getParentActivityIntent(activity);
@@ -164,7 +173,7 @@ public final class ActivityMixin {
activity.finish();
return true;
}
- if (NavUtils.shouldUpRecreateTask(activity, upIntent)) {
+ if (NavUtils.shouldUpRecreateTask(activity, upIntent) || activity.isTaskRoot()) {
// This activity is NOT part of this app's task, so create a new task
// when navigating up, with a synthesized back stack.
TaskStackBuilder.create(activity)
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java
index ccfd7a1..d14fca4 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java
@@ -1,10 +1,10 @@
package cgeo.geocaching.apps.cache.navi;
-import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.maps.MapProviderFactory;
import cgeo.geocaching.sensors.GeoData;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.utils.Log;
import android.app.Activity;
@@ -25,7 +25,7 @@ class GoogleMapsDirectionApp extends AbstractPointNavigationApp {
@Override
public void navigate(final Activity activity, final Geopoint coords) {
try {
- final GeoData geo = CgeoApplication.getInstance().currentGeo();
+ final GeoData geo = Sensors.getInstance().currentGeo();
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri
.parse("http://maps.google.com/maps?f=d&saddr="
+ geo.getCoords().getLatitude() + "," + geo.getCoords().getLongitude() + "&daddr="
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
index f346fc0..d542541 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
@@ -80,6 +80,9 @@ public final class NavigationAppFactory extends AbstractAppFactory {
this.app = app;
this.id = id;
this.preferenceKey = preferenceKey;
+ if (preferenceKey == 0 || preferenceKey == -1) {
+ throw new IllegalStateException("Every navigation app must have a boolean preference in the settings to be enabled/disabled.");
+ }
}
/**
diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java
index 834167a..4984273 100644
--- a/main/src/cgeo/geocaching/connector/AbstractConnector.java
+++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java
@@ -39,12 +39,12 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
- public boolean addToWatchlist(Geocache cache) {
+ public boolean addToWatchlist(@NonNull final Geocache cache) {
return false;
}
@Override
- public boolean removeFromWatchlist(Geocache cache) {
+ public boolean removeFromWatchlist(@NonNull final Geocache cache) {
return false;
}
@@ -54,7 +54,7 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
- public boolean uploadPersonalNote(Geocache cache) {
+ public boolean uploadPersonalNote(@NonNull final Geocache cache) {
throw new UnsupportedOperationException();
}
@@ -64,7 +64,7 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
- public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) {
+ public boolean uploadModifiedCoordinates(@NonNull final Geocache cache, @NonNull final Geopoint wpt) {
throw new UnsupportedOperationException();
}
@@ -72,12 +72,12 @@ public abstract class AbstractConnector implements IConnector {
* {@link IConnector}
*/
@Override
- public boolean deleteModifiedCoordinates(Geocache cache) {
+ public boolean deleteModifiedCoordinates(@NonNull final Geocache cache) {
throw new UnsupportedOperationException();
}
@Override
- public boolean supportsFavoritePoints(final Geocache cache) {
+ public boolean supportsFavoritePoints(@NonNull final Geocache cache) {
return false;
}
@@ -92,36 +92,38 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
- public boolean canLog(Geocache cache) {
+ public boolean canLog(@NonNull final Geocache cache) {
return false;
}
@Override
- public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) {
+ @NonNull
+ public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache) {
return new NoLoggingManager();
}
@Override
+ @NonNull
public String getLicenseText(final @NonNull Geocache cache) {
- return null;
+ return StringUtils.EMPTY;
}
protected static boolean isNumericId(final String str) {
try {
return Integer.parseInt(str) > 0;
- } catch (NumberFormatException ignored) {
+ } catch (final NumberFormatException ignored) {
}
return false;
}
@Override
- public boolean isZippedGPXFile(String fileName) {
+ public boolean isZippedGPXFile(@NonNull final String fileName) {
// don't accept any file by default
return false;
}
@Override
- public boolean isReliableLatLon(boolean cacheHasReliableLatLon) {
+ public boolean isReliableLatLon(final boolean cacheHasReliableLatLon) {
// let every cache have reliable coordinates by default
return true;
}
@@ -129,9 +131,8 @@ public abstract class AbstractConnector implements IConnector {
@Override
public String getGeocodeFromUrl(final String url) {
final String urlPrefix = getCacheUrlPrefix();
- if (StringUtils.startsWith(url, urlPrefix)) {
- @NonNull
- String geocode = url.substring(urlPrefix.length());
+ if (StringUtils.isEmpty(urlPrefix) || StringUtils.startsWith(url, urlPrefix)) {
+ @NonNull final String geocode = url.substring(urlPrefix.length());
if (canHandle(geocode)) {
return geocode;
}
@@ -139,9 +140,11 @@ public abstract class AbstractConnector implements IConnector {
return null;
}
+ @NonNull
abstract protected String getCacheUrlPrefix();
@Override
+ @NonNull
public String getLongCacheUrl(final @NonNull Geocache cache) {
return getCacheUrl(cache);
}
@@ -152,7 +155,7 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
- public int getCacheMapMarkerId(boolean disabled) {
+ public int getCacheMapMarkerId(final boolean disabled) {
if (disabled) {
return R.drawable.marker_disabled_other;
}
@@ -160,7 +163,8 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
- public List<LogType> getPossibleLogTypes(Geocache geocache) {
+ @NonNull
+ public List<LogType> getPossibleLogTypes(@NonNull final Geocache geocache) {
final List<LogType> logTypes = new ArrayList<>();
if (geocache.isEventCache()) {
logTypes.add(LogType.WILL_ATTEND);
@@ -197,13 +201,14 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
- public String getWaypointGpxId(String prefix, String geocode) {
+ public String getWaypointGpxId(final String prefix, final String geocode) {
// Default: just return the prefix
return prefix;
}
@Override
- public String getWaypointPrefix(String name) {
+ @NonNull
+ public String getWaypointPrefix(final String name) {
// Default: just return the name
return name;
}
@@ -214,8 +219,9 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
+ @NonNull
public final Collection<String> getCapabilities() {
- ArrayList<String> list = new ArrayList<>();
+ final ArrayList<String> list = new ArrayList<>();
addCapability(list, ISearchByViewPort.class, R.string.feature_search_live_map);
addCapability(list, ISearchByKeyword.class, R.string.feature_search_keyword);
addCapability(list, ISearchByCenter.class, R.string.feature_search_center);
@@ -246,20 +252,20 @@ public abstract class AbstractConnector implements IConnector {
}
}
- private static String feature(int featureResourceId) {
+ private static String feature(final int featureResourceId) {
return CgeoApplication.getInstance().getString(featureResourceId);
}
@Override
public @NonNull
List<UserAction> getUserActions() {
- List<UserAction> actions = getDefaultUserActions();
+ final List<UserAction> actions = getDefaultUserActions();
if (this instanceof ISearchByOwner) {
actions.add(new UserAction(R.string.user_menu_view_hidden, new Action1<Context>() {
@Override
- public void call(Context context) {
+ public void call(final Context context) {
CacheListActivity.startActivityOwner(context.activity, context.userName);
}
}));
@@ -269,7 +275,7 @@ public abstract class AbstractConnector implements IConnector {
actions.add(new UserAction(R.string.user_menu_view_found, new Action1<UserAction.Context>() {
@Override
- public void call(Context context) {
+ public void call(final Context context) {
CacheListActivity.startActivityFinder(context.activity, context.userName);
}
}));
@@ -287,7 +293,7 @@ public abstract class AbstractConnector implements IConnector {
actions.add(new UserAction(R.string.user_menu_open_contact, new Action1<UserAction.Context>() {
@Override
- public void call(Context context) {
+ public void call(final Context context) {
ContactsAddon.openContactCard(context.activity, context.userName);
}
}));
diff --git a/main/src/cgeo/geocaching/connector/AbstractLoggingManager.java b/main/src/cgeo/geocaching/connector/AbstractLoggingManager.java
index 9e702c4..e53fcf1 100644
--- a/main/src/cgeo/geocaching/connector/AbstractLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/AbstractLoggingManager.java
@@ -2,6 +2,8 @@ package cgeo.geocaching.connector;
import cgeo.geocaching.TrackableLog;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.Collections;
import java.util.List;
@@ -13,6 +15,7 @@ public abstract class AbstractLoggingManager implements ILoggingManager {
}
@Override
+ @NonNull
public List<TrackableLog> getTrackables() {
return Collections.emptyList();
}
diff --git a/main/src/cgeo/geocaching/connector/AbstractLogin.java b/main/src/cgeo/geocaching/connector/AbstractLogin.java
index b40ed4f..252daeb 100644
--- a/main/src/cgeo/geocaching/connector/AbstractLogin.java
+++ b/main/src/cgeo/geocaching/connector/AbstractLogin.java
@@ -8,6 +8,7 @@ import cgeo.geocaching.network.Network;
import cgeo.geocaching.settings.Settings;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
public abstract class AbstractLogin {
@@ -39,7 +40,7 @@ public abstract class AbstractLogin {
return actualLoginStatus;
}
- protected void setActualLoginStatus(boolean loginStatus) {
+ protected void setActualLoginStatus(final boolean loginStatus) {
actualLoginStatus = loginStatus;
}
@@ -47,7 +48,7 @@ public abstract class AbstractLogin {
return actualUserName;
}
- protected void setActualUserName(String userName) {
+ protected void setActualUserName(final String userName) {
actualUserName = userName;
}
@@ -69,6 +70,7 @@ public abstract class AbstractLogin {
setActualStatus(CgeoApplication.getInstance().getString(R.string.err_login));
}
+ @NonNull
public StatusCode login() {
if (!Network.isNetworkConnected()) {
return StatusCode.COMMUNICATION_ERROR;
@@ -76,6 +78,7 @@ public abstract class AbstractLogin {
return login(true);
}
+ @NonNull
protected abstract StatusCode login(boolean retry);
}
diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
index d4d051f..b78b009 100644
--- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java
+++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
@@ -36,8 +36,8 @@ import java.util.Collections;
import java.util.List;
public final class ConnectorFactory {
- private static final @NonNull UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector();
- private static final Collection<IConnector> CONNECTORS = Collections.unmodifiableCollection(Arrays.asList(new IConnector[] {
+ @NonNull private static final UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector();
+ @NonNull private static final Collection<IConnector> CONNECTORS = Collections.unmodifiableCollection(Arrays.asList(new IConnector[] {
GCConnector.getInstance(),
ECConnector.getInstance(),
new OCApiLiveConnector("opencaching.de", "www.opencaching.de", "OC", "CC BY-NC-ND, alle Logeinträge © jeweiliger Autor",
@@ -71,22 +71,30 @@ public final class ConnectorFactory {
}));
@NonNull public static final UnknownTrackableConnector UNKNOWN_TRACKABLE_CONNECTOR = new UnknownTrackableConnector();
+
+ @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(),
UNKNOWN_TRACKABLE_CONNECTOR // must be last
}));
+ @NonNull
private static final Collection<ISearchByViewPort> searchByViewPortConns = getMatchingConnectors(ISearchByViewPort.class);
+ @NonNull
private static final Collection<ISearchByCenter> searchByCenterConns = getMatchingConnectors(ISearchByCenter.class);
+ @NonNull
private static final Collection<ISearchByKeyword> searchByKeywordConns = getMatchingConnectors(ISearchByKeyword.class);
+ @NonNull
private static final Collection<ISearchByOwner> SEARCH_BY_OWNER_CONNECTORS = getMatchingConnectors(ISearchByOwner.class);
+ @NonNull
private static final Collection<ISearchByFinder> SEARCH_BY_FINDER_CONNECTORS = getMatchingConnectors(ISearchByFinder.class);
+ @NonNull
@SuppressWarnings("unchecked")
private static <T extends IConnector> Collection<T> getMatchingConnectors(final Class<T> clazz) {
final List<T> matching = new ArrayList<>();
@@ -98,26 +106,32 @@ public final class ConnectorFactory {
return Collections.unmodifiableCollection(matching);
}
+ @NonNull
public static Collection<IConnector> getConnectors() {
return CONNECTORS;
}
+ @NonNull
public static Collection<ISearchByCenter> getSearchByCenterConnectors() {
return searchByCenterConns;
}
+ @NonNull
public static Collection<ISearchByKeyword> getSearchByKeywordConnectors() {
return searchByKeywordConns;
}
+ @NonNull
public static Collection<ISearchByOwner> getSearchByOwnerConnectors() {
return SEARCH_BY_OWNER_CONNECTORS;
}
+ @NonNull
public static Collection<ISearchByFinder> getSearchByFinderConnectors() {
return SEARCH_BY_FINDER_CONNECTORS;
}
+ @NonNull
public static ILogin[] getActiveLiveConnectors() {
final List<ILogin> liveConns = new ArrayList<>();
for (final IConnector conn : CONNECTORS) {
@@ -143,11 +157,12 @@ public final class ConnectorFactory {
return false;
}
- public static @NonNull
- IConnector getConnector(final Geocache cache) {
+ @NonNull
+ public static IConnector getConnector(final Geocache cache) {
return getConnector(cache.getGeocode());
}
+ @NonNull
public static TrackableConnector getConnector(final Trackable trackable) {
return getTrackableConnector(trackable.getGeocode());
}
@@ -162,8 +177,8 @@ public final class ConnectorFactory {
return UNKNOWN_TRACKABLE_CONNECTOR; // avoid null checks by returning a non implementing connector
}
- public static @NonNull
- IConnector getConnector(final String geocodeInput) {
+ @NonNull
+ public static IConnector getConnector(final String geocodeInput) {
// this may come from user input
final String geocode = StringUtils.trim(geocodeInput);
if (geocode == null) {
@@ -186,7 +201,8 @@ public final class ConnectorFactory {
}
/** @see ISearchByViewPort#searchByViewport */
- public static SearchResult searchByViewport(final @NonNull Viewport viewport, final MapTokens tokens) {
+ @NonNull
+ public static SearchResult searchByViewport(final @NonNull Viewport viewport, @NonNull final MapTokens tokens) {
return SearchResult.parallelCombineActive(searchByViewPortConns, new Func1<ISearchByViewPort, SearchResult>() {
@Override
public SearchResult call(final ISearchByViewPort connector) {
@@ -195,6 +211,7 @@ public final class ConnectorFactory {
});
}
+ @Nullable
public static String getGeocodeFromURL(final String url) {
for (final IConnector connector : CONNECTORS) {
final String geocode = connector.getGeocodeFromUrl(url);
@@ -205,6 +222,7 @@ public final class ConnectorFactory {
return null;
}
+ @NonNull
public static Collection<TrackableConnector> getTrackableConnectors() {
return TRACKABLE_CONNECTORS;
}
@@ -215,6 +233,7 @@ public final class ConnectorFactory {
* @param url
* @return {@code null} if the URL cannot be decoded
*/
+ @Nullable
public static String getTrackableFromURL(final String url) {
if (url == null) {
return null;
diff --git a/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java b/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java
index 5535472..9377d6d 100644
--- a/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java
+++ b/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java
@@ -8,22 +8,25 @@ import org.eclipse.jdt.annotation.NonNull;
class GeocachingAustraliaConnector extends AbstractConnector {
@Override
+ @NonNull
public String getName() {
return "Geocaching Australia";
}
@Override
+ @NonNull
public String getCacheUrl(final @NonNull Geocache cache) {
return getCacheUrlPrefix() + cache.getGeocode();
}
@Override
+ @NonNull
public String getHost() {
return "geocaching.com.au";
}
@Override
- public boolean isOwner(final Geocache cache) {
+ public boolean isOwner(@NonNull final Geocache cache) {
return false;
}
@@ -33,6 +36,7 @@ class GeocachingAustraliaConnector extends AbstractConnector {
}
@Override
+ @NonNull
protected String getCacheUrlPrefix() {
return "http://" + getHost() + "/cache/";
}
diff --git a/main/src/cgeo/geocaching/connector/GeopeitusConnector.java b/main/src/cgeo/geocaching/connector/GeopeitusConnector.java
index 0dc7a44..4340cac 100644
--- a/main/src/cgeo/geocaching/connector/GeopeitusConnector.java
+++ b/main/src/cgeo/geocaching/connector/GeopeitusConnector.java
@@ -8,22 +8,25 @@ import org.eclipse.jdt.annotation.NonNull;
class GeopeitusConnector extends AbstractConnector {
@Override
+ @NonNull
public String getName() {
return "geopeitus.ee";
}
@Override
+ @NonNull
public String getCacheUrl(final @NonNull Geocache cache) {
return getCacheUrlPrefix() + StringUtils.stripStart(cache.getGeocode().substring(2), "0");
}
@Override
+ @NonNull
public String getHost() {
return "www.geopeitus.ee";
}
@Override
- public boolean isOwner(final Geocache cache) {
+ public boolean isOwner(@NonNull final Geocache cache) {
return false;
}
@@ -33,6 +36,7 @@ class GeopeitusConnector extends AbstractConnector {
}
@Override
+ @NonNull
protected String getCacheUrlPrefix() {
return "http://" + getHost() + "/aare/";
}
diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java
index 9c1e8fc..0863723 100644
--- a/main/src/cgeo/geocaching/connector/IConnector.java
+++ b/main/src/cgeo/geocaching/connector/IConnector.java
@@ -16,6 +16,7 @@ public interface IConnector {
*
* @return
*/
+ @NonNull
public String getName();
/**
@@ -33,6 +34,7 @@ public interface IConnector {
* @param cache
* @return
*/
+ @NonNull
public String getCacheUrl(final @NonNull Geocache cache);
/**
@@ -41,6 +43,7 @@ public interface IConnector {
* @param cache
* @return
*/
+ @NonNull
public String getLongCacheUrl(final @NonNull Geocache cache);
/**
@@ -56,7 +59,7 @@ public interface IConnector {
* @param cache
* @return True - success/False - failure
*/
- public boolean addToWatchlist(Geocache cache);
+ public boolean addToWatchlist(@NonNull Geocache cache);
/**
* Remove the cache from the watchlist
@@ -64,14 +67,14 @@ public interface IConnector {
* @param cache
* @return True - success/False - failure
*/
- public boolean removeFromWatchlist(Geocache cache);
+ public boolean removeFromWatchlist(@NonNull Geocache cache);
/**
* enable/disable favorite points controls in cache details
*
* @return
*/
- public boolean supportsFavoritePoints(final Geocache cache);
+ public boolean supportsFavoritePoints(@NonNull final Geocache cache);
/**
* enable/disable logging controls in cache details
@@ -92,13 +95,15 @@ public interface IConnector {
*
* @return
*/
- public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache);
+ @NonNull
+ public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache);
/**
* Get host name of the connector server for dynamic loading of data.
*
* @return
*/
+ @NonNull
public String getHost();
/**
@@ -107,6 +112,7 @@ public interface IConnector {
* @param cache
* @return
*/
+ @NonNull
public String getLicenseText(final @NonNull Geocache cache);
/**
@@ -115,7 +121,7 @@ public interface IConnector {
* @param fileName
* @return
*/
- public boolean isZippedGPXFile(final String fileName);
+ public boolean isZippedGPXFile(@NonNull final String fileName);
/**
* return true if coordinates of a cache are reliable. only implemented by GC connector
@@ -147,7 +153,7 @@ public interface IConnector {
* @param cache
* @return success
*/
- public boolean uploadPersonalNote(Geocache cache);
+ public boolean uploadPersonalNote(@NonNull Geocache cache);
/**
* enable/disable uploading modified coordinates to website
@@ -162,7 +168,7 @@ public interface IConnector {
* @param cache
* @return success
*/
- public boolean deleteModifiedCoordinates(Geocache cache);
+ public boolean deleteModifiedCoordinates(@NonNull Geocache cache);
/**
* Uploading modified coordinates to website
@@ -171,7 +177,7 @@ public interface IConnector {
* @param wpt
* @return success
*/
- public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt);
+ public boolean uploadModifiedCoordinates(@NonNull Geocache cache, @NonNull Geopoint wpt);
/**
* Return {@code true} if this connector is active for online interaction (download details, do searches, ...). If
@@ -188,7 +194,7 @@ public interface IConnector {
* @param cache a cache that this connector must be able to handle
* @return <code>true</code> if the current user is the cache owner, <code>false</code> otherwise
*/
- public boolean isOwner(final Geocache cache);
+ public boolean isOwner(@NonNull final Geocache cache);
/**
* Check if the cache information is complete enough to be
@@ -197,7 +203,7 @@ public interface IConnector {
* @param geocache
* @return
*/
- public boolean canLog(Geocache geocache);
+ public boolean canLog(@NonNull Geocache geocache);
/**
* Return the marker id of the caches for this connector. This creates the different backgrounds for cache markers
@@ -215,7 +221,8 @@ public interface IConnector {
* @param geocache
* @return
*/
- public List<LogType> getPossibleLogTypes(Geocache geocache);
+ @NonNull
+ public List<LogType> getPossibleLogTypes(@NonNull Geocache geocache);
/**
* Get the GPX id for a waypoint when exporting. For some connectors there is an inherent name logic,
@@ -232,6 +239,7 @@ public interface IConnector {
* @param name
* @return
*/
+ @NonNull
public String getWaypointPrefix(String name);
/**
@@ -246,8 +254,9 @@ public interface IConnector {
*
* @return
*/
+ @NonNull
public Collection<String> getCapabilities();
- public @NonNull
- List<UserAction> getUserActions();
+ @NonNull
+ public List<UserAction> getUserActions();
}
diff --git a/main/src/cgeo/geocaching/connector/ILoggingManager.java b/main/src/cgeo/geocaching/connector/ILoggingManager.java
index a8caf69..40a5377 100644
--- a/main/src/cgeo/geocaching/connector/ILoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/ILoggingManager.java
@@ -3,6 +3,9 @@ package cgeo.geocaching.connector;
import cgeo.geocaching.TrackableLog;
import cgeo.geocaching.enumerations.LogType;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
import android.net.Uri;
import java.util.Calendar;
@@ -12,7 +15,7 @@ public interface ILoggingManager {
/**
* Post a log for a cache online
- *
+ *
* @param logType
* @param date
* @param log
@@ -21,12 +24,14 @@ public interface ILoggingManager {
* @param trackableLogs
* @return
*/
- LogResult postLog(LogType logType,
- Calendar date,
- String log,
- String logPassword,
- List<TrackableLog> trackableLogs);
-
+ @NonNull
+ LogResult postLog(@NonNull LogType logType,
+ @NonNull Calendar date,
+ @NonNull String log,
+ @Nullable String logPassword,
+ @NonNull List<TrackableLog> trackableLogs);
+
+ @NonNull
ImageResult postLogImage(String logId,
String imageCaption,
String imageDescription,
@@ -34,8 +39,10 @@ public interface ILoggingManager {
public boolean hasLoaderError();
+ @NonNull
public List<TrackableLog> getTrackables();
+ @NonNull
public List<LogType> getPossibleLogTypes();
public void init();
diff --git a/main/src/cgeo/geocaching/connector/ImageResult.java b/main/src/cgeo/geocaching/connector/ImageResult.java
index 9314cad..ec11a6d 100644
--- a/main/src/cgeo/geocaching/connector/ImageResult.java
+++ b/main/src/cgeo/geocaching/connector/ImageResult.java
@@ -2,20 +2,26 @@ package cgeo.geocaching.connector;
import cgeo.geocaching.enumerations.StatusCode;
+import org.eclipse.jdt.annotation.NonNull;
+
public class ImageResult {
+ @NonNull
private final StatusCode postResult;
+ @NonNull
private final String imageUri;
- public ImageResult(StatusCode postResult, String imageUri) {
+ public ImageResult(@NonNull final StatusCode postResult, @NonNull final String imageUri) {
this.postResult = postResult;
this.imageUri = imageUri;
}
+ @NonNull
public StatusCode getPostResult() {
return postResult;
}
+ @NonNull
public String getImageUri() {
return imageUri;
}
diff --git a/main/src/cgeo/geocaching/connector/LogResult.java b/main/src/cgeo/geocaching/connector/LogResult.java
index 62111a4..9d0cb61 100644
--- a/main/src/cgeo/geocaching/connector/LogResult.java
+++ b/main/src/cgeo/geocaching/connector/LogResult.java
@@ -2,20 +2,26 @@ package cgeo.geocaching.connector;
import cgeo.geocaching.enumerations.StatusCode;
+import org.eclipse.jdt.annotation.NonNull;
+
public class LogResult {
+ @NonNull
private final StatusCode postLogResult;
+ @NonNull
private final String logId;
- public LogResult(StatusCode postLogResult, String logId) {
+ public LogResult(@NonNull final StatusCode postLogResult, @NonNull final String logId) {
this.postLogResult = postLogResult;
this.logId = logId;
}
+ @NonNull
public StatusCode getPostLogResult() {
return postLogResult;
}
+ @NonNull
public String getLogId() {
return logId;
}
diff --git a/main/src/cgeo/geocaching/connector/NoLoggingManager.java b/main/src/cgeo/geocaching/connector/NoLoggingManager.java
index ff8b33a..103db68 100644
--- a/main/src/cgeo/geocaching/connector/NoLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/NoLoggingManager.java
@@ -4,6 +4,9 @@ import cgeo.geocaching.TrackableLog;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.StatusCode;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
import android.net.Uri;
import java.util.Calendar;
@@ -18,11 +21,13 @@ class NoLoggingManager extends AbstractLoggingManager {
}
@Override
- public LogResult postLog(final LogType logType, final Calendar date, final String log, final String logPassword, final List<TrackableLog> trackableLogs) {
+ @NonNull
+ public LogResult postLog(@NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, @Nullable final String logPassword, @NonNull final List<TrackableLog> trackableLogs) {
return new LogResult(StatusCode.LOG_POST_ERROR, "");
}
@Override
+ @NonNull
public ImageResult postLogImage(final String logId, final String imageCaption, final String imageDescription, final Uri imageUri) {
return new ImageResult(StatusCode.LOG_POST_ERROR, "");
}
@@ -33,6 +38,7 @@ class NoLoggingManager extends AbstractLoggingManager {
}
@Override
+ @NonNull
public List<LogType> getPossibleLogTypes() {
return Collections.emptyList();
}
diff --git a/main/src/cgeo/geocaching/connector/UnknownConnector.java b/main/src/cgeo/geocaching/connector/UnknownConnector.java
index a88f2c5..8ed1da4 100644
--- a/main/src/cgeo/geocaching/connector/UnknownConnector.java
+++ b/main/src/cgeo/geocaching/connector/UnknownConnector.java
@@ -8,22 +8,25 @@ import org.eclipse.jdt.annotation.NonNull;
class UnknownConnector extends AbstractConnector {
@Override
+ @NonNull
public String getName() {
return "Unknown caches";
}
@Override
+ @NonNull
public String getCacheUrl(@NonNull final Geocache cache) {
- return null; // we have no url for these caches
+ throw new IllegalStateException("getCacheUrl cannot be called on unknown caches");
}
@Override
+ @NonNull
public String getHost() {
- return null; // we have no host for these caches
+ return StringUtils.EMPTY; // we have no host for these caches
}
@Override
- public boolean isOwner(final Geocache cache) {
+ public boolean isOwner(@NonNull final Geocache cache) {
return false;
}
@@ -33,7 +36,13 @@ class UnknownConnector extends AbstractConnector {
}
@Override
+ @NonNull
protected String getCacheUrlPrefix() {
+ throw new IllegalStateException("getCacheUrl cannot be called on unknown caches");
+ }
+
+ @Override
+ public String getGeocodeFromUrl(final String url) {
return null;
}
diff --git a/main/src/cgeo/geocaching/connector/UserAction.java b/main/src/cgeo/geocaching/connector/UserAction.java
index e9ee4a3..082e32c 100644
--- a/main/src/cgeo/geocaching/connector/UserAction.java
+++ b/main/src/cgeo/geocaching/connector/UserAction.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.connector;
import org.eclipse.jdt.annotation.NonNull;
+
import rx.functions.Action1;
import android.app.Activity;
@@ -8,25 +9,26 @@ import android.app.Activity;
public class UserAction {
public static class Context {
+ @NonNull
public final String userName;
+ @NonNull
public final Activity activity;
- public Context(String userName, Activity activity) {
+ public Context(@NonNull final String userName, @NonNull final Activity activity) {
this.userName = userName;
this.activity = activity;
}
}
public final int displayResourceId;
- private final @NonNull
- Action1<Context> runnable;
+ @NonNull private final Action1<Context> runnable;
- public UserAction(int displayResourceId, final @NonNull Action1<Context> runnable) {
+ public UserAction(final int displayResourceId, final @NonNull Action1<Context> runnable) {
this.displayResourceId = displayResourceId;
this.runnable = runnable;
}
- public void run(Context context) {
+ public void run(@NonNull final Context context) {
runnable.call(context);
}
}
diff --git a/main/src/cgeo/geocaching/connector/WaymarkingConnector.java b/main/src/cgeo/geocaching/connector/WaymarkingConnector.java
index 2ed54a0..5a6f362 100644
--- a/main/src/cgeo/geocaching/connector/WaymarkingConnector.java
+++ b/main/src/cgeo/geocaching/connector/WaymarkingConnector.java
@@ -8,27 +8,31 @@ import org.eclipse.jdt.annotation.NonNull;
class WaymarkingConnector extends AbstractConnector {
@Override
+ @NonNull
public String getName() {
return "Waymarking";
}
@Override
+ @NonNull
public String getCacheUrl(@NonNull final Geocache cache) {
return getCacheUrlPrefix() + cache.getGeocode();
}
@Override
+ @NonNull
public String getHost() {
return "www.waymarking.com";
}
@Override
- public boolean isOwner(final Geocache cache) {
+ public boolean isOwner(@NonNull final Geocache cache) {
// this connector has no user management
return false;
}
@Override
+ @NonNull
protected String getCacheUrlPrefix() {
return "http://" + getHost() + "/waymarks/";
}
diff --git a/main/src/cgeo/geocaching/connector/capability/FieldNotesCapability.java b/main/src/cgeo/geocaching/connector/capability/FieldNotesCapability.java
index 4da9705..dd2bc8d 100644
--- a/main/src/cgeo/geocaching/connector/capability/FieldNotesCapability.java
+++ b/main/src/cgeo/geocaching/connector/capability/FieldNotesCapability.java
@@ -2,6 +2,8 @@ package cgeo.geocaching.connector.capability;
import cgeo.geocaching.connector.IConnector;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.io.File;
/**
@@ -9,5 +11,5 @@ import java.io.File;
*
*/
public interface FieldNotesCapability extends IConnector {
- public boolean uploadFieldNotes(final File exportFile);
+ public boolean uploadFieldNotes(@NonNull final File exportFile);
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ILogin.java b/main/src/cgeo/geocaching/connector/capability/ILogin.java
index b8b4975..003ccf4 100644
--- a/main/src/cgeo/geocaching/connector/capability/ILogin.java
+++ b/main/src/cgeo/geocaching/connector/capability/ILogin.java
@@ -7,13 +7,10 @@ import android.os.Handler;
public interface ILogin extends IConnector {
-
/**
- * Contacts the server the connector belongs to
- * and verifies/establishes authentication and
- * retrieves information about the current user
- * (Name, found caches) if applicable.
- *
+ * Contacts the server the connector belongs to and verifies/establishes authentication and retrieves information
+ * about the current user (Name, found caches) if applicable.
+ *
* @param handler
* Handler to receive status feedback
* @param fromActivity
@@ -28,7 +25,7 @@ public interface ILogin extends IConnector {
void logout();
/**
- * Returns the status of the last {@link}login() request
+ * Returns the status of the last {@link #login(Handler, Context)} request.
*
* @return
*/
@@ -42,18 +39,17 @@ public interface ILogin extends IConnector {
String getLoginStatusString();
/**
- * Name the user has in this connector or empty string if not applicable
- * It might be necessary to execute login before this information is valid.
+ * 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();
/**
- * Number of caches the user has found in this connector
- * Normally retrieved/updated with (@see login).
- * Might be out dated as changes on the connectors site
- * are generally not notified.
+ * Number of caches the user has found in this connector.
+ * Normally retrieved/updated with {@link #login(Handler, Context)}.
+ * Might be stale as changes on the connectors site are generally not notified.
*
* @return
*/
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
index ef81c4c..0137c3b 100644
--- a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
@@ -8,5 +8,6 @@ import cgeo.geocaching.location.Viewport;
import org.eclipse.jdt.annotation.NonNull;
public interface ISearchByViewPort extends IConnector {
- public SearchResult searchByViewport(final @NonNull Viewport viewport, final MapTokens tokens);
+ @NonNull
+ public SearchResult searchByViewport(final @NonNull Viewport viewport, @NonNull final MapTokens tokens);
}
diff --git a/main/src/cgeo/geocaching/connector/ec/ECApi.java b/main/src/cgeo/geocaching/connector/ec/ECApi.java
index 4d4ca76..86f7717 100644
--- a/main/src/cgeo/geocaching/connector/ec/ECApi.java
+++ b/main/src/cgeo/geocaching/connector/ec/ECApi.java
@@ -24,6 +24,8 @@ import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import java.io.IOException;
import java.util.ArrayList;
@@ -37,9 +39,13 @@ import java.util.TimeZone;
final class ECApi {
+ @NonNull
private static final String API_HOST = "https://extremcaching.com/exports/";
+ @NonNull
private static final ECLogin ecLogin = ECLogin.getInstance();
+
+ @NonNull
private static final SynchronizedDateFormat LOG_DATE_FORMAT = new SynchronizedDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", TimeZone.getTimeZone("UTC"), Locale.US);
private ECApi() {
@@ -50,6 +56,7 @@ final class ECApi {
return StringUtils.removeStartIgnoreCase(geocode, "EC");
}
+ @Nullable
static Geocache searchByGeoCode(final String geocode) {
final Parameters params = new Parameters("id", getIdFromGeocode(geocode));
final HttpResponse response = apiRequest("gpx.php", params);
@@ -61,6 +68,7 @@ final class ECApi {
return null;
}
+ @NonNull
static Collection<Geocache> searchByBBox(final Viewport viewport) {
if (viewport.getLatitudeSpan() == 0 || viewport.getLongitudeSpan() == 0) {
@@ -77,7 +85,7 @@ final class ECApi {
return importCachesFromJSON(response);
}
-
+ @NonNull
static Collection<Geocache> searchByCenter(final Geopoint center) {
final Parameters params = new Parameters("fnc", "center");
@@ -89,11 +97,13 @@ final class ECApi {
return importCachesFromJSON(response);
}
- static LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log) {
+ @NonNull
+ static LogResult postLog(@NonNull final Geocache cache, @NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log) {
return postLog(cache, logType, date, log, false);
}
- private static LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log, final boolean isRetry) {
+ @NonNull
+ private static LogResult postLog(@NonNull final Geocache cache, @NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, final boolean isRetry) {
final Parameters params = new Parameters("cache_id", cache.getGeocode());
params.add("type", logType.type);
params.add("log", log);
@@ -127,15 +137,17 @@ final class ECApi {
return new LogResult(StatusCode.LOG_POST_ERROR, "");
}
-
+ @Nullable
private static HttpResponse apiRequest(final Parameters params) {
return apiRequest("api.php", params);
}
+ @Nullable
private static HttpResponse apiRequest(final String uri, final Parameters params) {
return apiRequest(uri, params, false);
}
+ @Nullable
private static HttpResponse apiRequest(final String uri, final Parameters params, final boolean isRetry) {
// add session and cgeo marker on every request
if (!isRetry) {
@@ -160,6 +172,7 @@ final class ECApi {
return response;
}
+ @NonNull
private static Collection<Geocache> importCachesFromGPXResponse(final HttpResponse response) {
if (response == null) {
return Collections.emptyList();
@@ -173,6 +186,7 @@ final class ECApi {
}
}
+ @NonNull
private static List<Geocache> importCachesFromJSON(final HttpResponse response) {
if (response != null) {
try {
@@ -196,6 +210,7 @@ final class ECApi {
return Collections.emptyList();
}
+ @Nullable
private static Geocache parseCache(final JsonNode response) {
try {
final Geocache cache = new Geocache();
@@ -216,6 +231,7 @@ final class ECApi {
}
}
+ @NonNull
private static CacheType getCacheType(final String cacheType) {
if (cacheType.equalsIgnoreCase("Tradi")) {
return CacheType.TRADITIONAL;
diff --git a/main/src/cgeo/geocaching/connector/ec/ECConnector.java b/main/src/cgeo/geocaching/connector/ec/ECConnector.java
index e884f85..15c2dc2 100644
--- a/main/src/cgeo/geocaching/connector/ec/ECConnector.java
+++ b/main/src/cgeo/geocaching/connector/ec/ECConnector.java
@@ -36,13 +36,18 @@ import java.util.regex.Pattern;
public class ECConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort, ILogin, ICredentials {
+ @NonNull
private static final String CACHE_URL = "http://extremcaching.com/index.php/output-2/";
/**
* Pattern for EC codes
*/
+ @NonNull
private final static Pattern PATTERN_EC_CODE = Pattern.compile("EC[0-9]+", Pattern.CASE_INSENSITIVE);
+
private final CgeoApplication app = CgeoApplication.getInstance();
+
+ @NonNull
private final ECLogin ecLogin = ECLogin.getInstance();
private ECConnector() {
@@ -56,27 +61,30 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode,
private static final @NonNull ECConnector INSTANCE = new ECConnector();
}
- public static @NonNull
- ECConnector getInstance() {
+ @NonNull
+ public static ECConnector getInstance() {
return Holder.INSTANCE;
}
@Override
- public boolean canHandle(@NonNull String geocode) {
+ public boolean canHandle(@NonNull final String geocode) {
return ECConnector.PATTERN_EC_CODE.matcher(geocode).matches();
}
@Override
- public String getCacheUrl(@NonNull Geocache cache) {
+ @NonNull
+ public String getCacheUrl(@NonNull final Geocache cache) {
return CACHE_URL + cache.getGeocode().replace("EC", "");
}
@Override
+ @NonNull
public String getName() {
return "extremcaching.com";
}
@Override
+ @NonNull
public String getHost() {
return "extremcaching.com";
}
@@ -94,31 +102,28 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public SearchResult searchByViewport(@NonNull Viewport viewport, final MapTokens tokens) {
+ @NonNull
+ public SearchResult searchByViewport(@NonNull final Viewport viewport, @NonNull final MapTokens tokens) {
final Collection<Geocache> caches = ECApi.searchByBBox(viewport);
- if (caches == null) {
- return null;
- }
final SearchResult searchResult = new SearchResult(caches);
return searchResult.filterSearchResults(false, false, Settings.getCacheType());
}
@Override
- public SearchResult searchByCenter(@NonNull Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) {
+ @NonNull
+ public SearchResult searchByCenter(@NonNull final Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) {
final Collection<Geocache> caches = ECApi.searchByCenter(center);
- if (caches == null) {
- return null;
- }
final SearchResult searchResult = new SearchResult(caches);
return searchResult.filterSearchResults(false, false, Settings.getCacheType());
}
@Override
- public boolean isOwner(final Geocache cache) {
+ public boolean isOwner(@NonNull final Geocache cache) {
return false;
}
@Override
+ @NonNull
protected String getCacheUrlPrefix() {
return CACHE_URL;
}
@@ -129,7 +134,7 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public boolean login(Handler handler, Context fromActivity) {
+ public boolean login(final Handler handler, final Context fromActivity) {
// login
final StatusCode status = ecLogin.login();
@@ -166,7 +171,7 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public int getCacheMapMarkerId(boolean disabled) {
+ public int getCacheMapMarkerId(final boolean disabled) {
final String icons = Settings.getECIconSet();
if (StringUtils.equals(icons, "1")) {
return disabled ? R.drawable.marker_disabled_other : R.drawable.marker_other;
@@ -175,6 +180,7 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
+ @NonNull
public String getLicenseText(final @NonNull Geocache cache) {
// NOT TO BE TRANSLATED
return "© " + cache.getOwnerDisplayName() + ", <a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a>, CC BY-NC-ND 3.0, alle Logeinträge © jeweiliger Autor";
@@ -186,17 +192,19 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public boolean canLog(Geocache cache) {
+ public boolean canLog(@NonNull final Geocache cache) {
return true;
}
@Override
- public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) {
+ @NonNull
+ public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache) {
return new ECLoggingManager(activity, this, cache);
}
@Override
- public List<LogType> getPossibleLogTypes(Geocache geocache) {
+ @NonNull
+ public List<LogType> getPossibleLogTypes(@NonNull final Geocache geocache) {
final List<LogType> logTypes = new ArrayList<>();
if (geocache.isEventCache()) {
logTypes.add(LogType.WILL_ATTEND);
diff --git a/main/src/cgeo/geocaching/connector/ec/ECLoggingManager.java b/main/src/cgeo/geocaching/connector/ec/ECLoggingManager.java
index f380a6b..34c3d1b 100644
--- a/main/src/cgeo/geocaching/connector/ec/ECLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/ec/ECLoggingManager.java
@@ -7,6 +7,10 @@ import cgeo.geocaching.connector.AbstractLoggingManager;
import cgeo.geocaching.connector.ImageResult;
import cgeo.geocaching.connector.LogResult;
import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.enumerations.StatusCode;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import android.net.Uri;
@@ -15,11 +19,16 @@ import java.util.List;
class ECLoggingManager extends AbstractLoggingManager {
+ @NonNull
private final ECConnector connector;
+
+ @NonNull
private final Geocache cache;
+
+ @NonNull
private final LogCacheActivity activity;
- ECLoggingManager(final LogCacheActivity activity, final ECConnector connector, final Geocache cache) {
+ ECLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final ECConnector connector, @NonNull final Geocache cache) {
this.connector = connector;
this.cache = cache;
this.activity = activity;
@@ -31,16 +40,19 @@ class ECLoggingManager extends AbstractLoggingManager {
}
@Override
- public final LogResult postLog(final LogType logType, final Calendar date, final String log, final String logPassword, final List<TrackableLog> trackableLogs) {
+ @NonNull
+ public final LogResult postLog(@NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, @Nullable final String logPassword, @NonNull final List<TrackableLog> trackableLogs) {
return ECApi.postLog(cache, logType, date, log);
}
@Override
+ @NonNull
public final ImageResult postLogImage(final String logId, final String imageCaption, final String imageDescription, final Uri imageUri) {
- return null;
+ return new ImageResult(StatusCode.LOG_POST_ERROR, "");
}
@Override
+ @NonNull
public List<LogType> getPossibleLogTypes() {
return connector.getPossibleLogTypes(cache);
}
diff --git a/main/src/cgeo/geocaching/connector/ec/ECLogin.java b/main/src/cgeo/geocaching/connector/ec/ECLogin.java
index 342cbc6..3ae8298 100644
--- a/main/src/cgeo/geocaching/connector/ec/ECLogin.java
+++ b/main/src/cgeo/geocaching/connector/ec/ECLogin.java
@@ -16,6 +16,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import java.io.IOException;
@@ -30,14 +31,17 @@ public class ECLogin extends AbstractLogin {
}
private static class SingletonHolder {
+ @NonNull
private final static ECLogin INSTANCE = new ECLogin();
}
+ @NonNull
public static ECLogin getInstance() {
return SingletonHolder.INSTANCE;
}
@Override
+ @NonNull
protected StatusCode login(final boolean retry) {
final ImmutablePair<String, String> login = Settings.getCredentials(ECConnector.getInstance());
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index 099fd79..e43b9b5 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -49,18 +49,22 @@ import java.util.regex.Pattern;
public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort, ISearchByKeyword, ILogin, ICredentials, ISearchByOwner, ISearchByFinder, FieldNotesCapability {
+ @NonNull
private static final String CACHE_URL_SHORT = "http://coord.info/";
// Double slash is used to force open in browser
+ @NonNull
private static final String CACHE_URL_LONG = "http://www.geocaching.com/seek/cache_details.aspx?wp=";
/**
* Pocket queries downloaded from the website use a numeric prefix. The pocket query creator Android app adds a
* verbatim "pocketquery" prefix.
*/
+ @NonNull
private static final Pattern GPX_ZIP_FILE_PATTERN = Pattern.compile("((\\d{7,})|(pocketquery))" + "(_.+)?" + "\\.zip", Pattern.CASE_INSENSITIVE);
/**
* Pattern for GC codes
*/
+ @NonNull
private final static Pattern PATTERN_GC_CODE = Pattern.compile("GC[0-9A-Z]+", Pattern.CASE_INSENSITIVE);
private GCConnector() {
@@ -74,23 +78,25 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
private static final @NonNull GCConnector INSTANCE = new GCConnector();
}
- public static @NonNull
- GCConnector getInstance() {
+ @NonNull
+ public static GCConnector getInstance() {
return Holder.INSTANCE;
}
@Override
- public boolean canHandle(@NonNull String geocode) {
+ public boolean canHandle(@NonNull final String geocode) {
return GCConnector.PATTERN_GC_CODE.matcher(geocode).matches();
}
@Override
- public String getLongCacheUrl(@NonNull Geocache cache) {
+ @NonNull
+ public String getLongCacheUrl(@NonNull final Geocache cache) {
return CACHE_URL_LONG + cache.getGeocode();
}
@Override
- public String getCacheUrl(@NonNull Geocache cache) {
+ @NonNull
+ public String getCacheUrl(@NonNull final Geocache cache) {
return CACHE_URL_SHORT + cache.getGeocode();
}
@@ -120,21 +126,24 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) {
+ @NonNull
+ public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache) {
return new GCLoggingManager(activity, cache);
}
@Override
- public boolean canLog(Geocache cache) {
+ public boolean canLog(@NonNull final Geocache cache) {
return StringUtils.isNotBlank(cache.getCacheId());
}
@Override
+ @NonNull
public String getName() {
return "geocaching.com";
}
@Override
+ @NonNull
public String getHost() {
return "www.geocaching.com";
}
@@ -177,28 +186,29 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public SearchResult searchByViewport(@NonNull Viewport viewport, final MapTokens tokens) {
+ @NonNull
+ public SearchResult searchByViewport(@NonNull final Viewport viewport, @NonNull final MapTokens tokens) {
return GCMap.searchByViewport(viewport, tokens);
}
@Override
- public boolean isZippedGPXFile(final String fileName) {
+ public boolean isZippedGPXFile(@NonNull final String fileName) {
return GPX_ZIP_FILE_PATTERN.matcher(fileName).matches();
}
@Override
- public boolean isReliableLatLon(boolean cacheHasReliableLatLon) {
+ public boolean isReliableLatLon(final boolean cacheHasReliableLatLon) {
return cacheHasReliableLatLon;
}
@Override
- public boolean isOwner(final Geocache cache) {
+ public boolean isOwner(@NonNull final Geocache cache) {
final String user = Settings.getUsername();
return StringUtils.isNotEmpty(user) && StringUtils.equalsIgnoreCase(cache.getOwnerUserId(), user);
}
@Override
- public boolean addToWatchlist(Geocache cache) {
+ public boolean addToWatchlist(@NonNull final Geocache cache) {
final boolean added = GCParser.addToWatchlist(cache);
if (added) {
DataStore.saveChangedCache(cache);
@@ -207,7 +217,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public boolean removeFromWatchlist(Geocache cache) {
+ public boolean removeFromWatchlist(@NonNull final Geocache cache) {
final boolean removed = GCParser.removeFromWatchlist(cache);
if (removed) {
DataStore.saveChangedCache(cache);
@@ -225,7 +235,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
* @return <code>true</code> if the cache was successfully added, <code>false</code> otherwise
*/
- public static boolean addToFavorites(Geocache cache) {
+ public static boolean addToFavorites(final Geocache cache) {
final boolean added = GCParser.addToFavorites(cache);
if (added) {
DataStore.saveChangedCache(cache);
@@ -243,7 +253,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
* @return <code>true</code> if the cache was successfully added, <code>false</code> otherwise
*/
- public static boolean removeFromFavorites(Geocache cache) {
+ public static boolean removeFromFavorites(final Geocache cache) {
final boolean removed = GCParser.removeFromFavorites(cache);
if (removed) {
DataStore.saveChangedCache(cache);
@@ -252,7 +262,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) {
+ public boolean uploadModifiedCoordinates(@NonNull final Geocache cache, @NonNull final Geopoint wpt) {
final boolean uploaded = GCParser.uploadModifiedCoordinates(cache, wpt);
if (uploaded) {
DataStore.saveChangedCache(cache);
@@ -261,7 +271,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public boolean deleteModifiedCoordinates(Geocache cache) {
+ public boolean deleteModifiedCoordinates(@NonNull final Geocache cache) {
final boolean deleted = GCParser.deleteModifiedCoordinates(cache);
if (deleted) {
DataStore.saveChangedCache(cache);
@@ -270,7 +280,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public boolean uploadPersonalNote(Geocache cache) {
+ public boolean uploadPersonalNote(@NonNull final Geocache cache) {
final boolean uploaded = GCParser.uploadPersonalNote(cache);
if (uploaded) {
DataStore.saveChangedCache(cache);
@@ -279,22 +289,23 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public SearchResult searchByCenter(@NonNull Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) {
+ public SearchResult searchByCenter(@NonNull final Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) {
return GCParser.searchByCoords(center, Settings.getCacheType(), Settings.isShowCaptcha(), recaptchaReceiver);
}
@Override
- public boolean supportsFavoritePoints(final Geocache cache) {
+ public boolean supportsFavoritePoints(@NonNull final Geocache cache) {
return !cache.getType().isEvent();
}
@Override
+ @NonNull
protected String getCacheUrlPrefix() {
- return null; // UNUSED
+ return StringUtils.EMPTY; // UNUSED
}
@Override
- public String getGeocodeFromUrl(String url) {
+ public String getGeocodeFromUrl(final String url) {
// coord.info URLs
String code = StringUtils.substringAfterLast(url, "coord.info/");
if (code != null && canHandle(code)) {
@@ -314,7 +325,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public int getCacheMapMarkerId(boolean disabled) {
+ public int getCacheMapMarkerId(final boolean disabled) {
if (disabled) {
return R.drawable.marker_disabled;
}
@@ -322,7 +333,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public boolean login(Handler handler, Context fromActivity) {
+ public boolean login(final Handler handler, final Context fromActivity) {
// login
final StatusCode status = GCLogin.getInstance().login();
@@ -364,7 +375,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public String getWaypointGpxId(String prefix, String geocode) {
+ public String getWaypointGpxId(final String prefix, final String geocode) {
String gpxId = prefix;
if (StringUtils.isNotBlank(geocode) && geocode.length() > 2) {
gpxId += geocode.substring(2);
@@ -373,7 +384,8 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public String getWaypointPrefix(String name) {
+ @NonNull
+ public String getWaypointPrefix(final String name) {
String prefix = name;
if (StringUtils.isNotBlank(prefix) && prefix.length() >= 2) {
prefix = name.substring(0, 2);
@@ -382,7 +394,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public SearchResult searchByKeyword(@NonNull String keyword, final @NonNull RecaptchaReceiver recaptchaReceiver) {
+ public SearchResult searchByKeyword(@NonNull final String keyword, final @NonNull RecaptchaReceiver recaptchaReceiver) {
return GCParser.searchByKeyword(keyword, Settings.getCacheType(), Settings.isShowCaptcha(), recaptchaReceiver);
}
@@ -399,18 +411,18 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
@Override
public @NonNull
List<UserAction> getUserActions() {
- List<UserAction> actions = super.getUserActions();
+ final List<UserAction> actions = super.getUserActions();
actions.add(new UserAction(R.string.user_menu_open_browser, new Action1<UserAction.Context>() {
@Override
- public void call(cgeo.geocaching.connector.UserAction.Context context) {
+ public void call(final cgeo.geocaching.connector.UserAction.Context context) {
context.activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(context.userName))));
}
}));
actions.add(new UserAction(R.string.user_menu_send_message, new Action1<UserAction.Context>() {
@Override
- public void call(cgeo.geocaching.connector.UserAction.Context context) {
+ public void call(final cgeo.geocaching.connector.UserAction.Context context) {
try {
context.activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/email/?u=" + Network.encode(context.userName))));
} catch (final ActivityNotFoundException e) {
@@ -433,7 +445,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public boolean uploadFieldNotes(final File exportFile) {
+ public boolean uploadFieldNotes(@NonNull final File exportFile) {
if (!GCLogin.getInstance().isActualLoginStatus()) {
// no need to upload (possibly large file) if we're not logged in
final StatusCode loginState = GCLogin.getInstance().login();
diff --git a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
index 057d97b..bdea155 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
@@ -19,6 +19,7 @@ import cgeo.geocaching.utils.TextUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import android.net.Uri;
@@ -36,7 +37,7 @@ class GCLoggingManager extends AbstractLoggingManager implements LoaderManager.L
private final Geocache cache;
private String[] viewstates;
- private List<TrackableLog> trackables;
+ @NonNull private List<TrackableLog> trackables = Collections.emptyList();
private List<LogType> possibleLogTypes;
private boolean hasLoaderError = true;
@@ -92,7 +93,8 @@ class GCLoggingManager extends AbstractLoggingManager implements LoaderManager.L
}
@Override
- public LogResult postLog(final LogType logType, final Calendar date, final String log, final String logPassword, final List<TrackableLog> trackableLogs) {
+ @NonNull
+ public LogResult postLog(@NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, @Nullable final String logPassword, @NonNull final List<TrackableLog> trackableLogs) {
try {
final ImmutablePair<StatusCode, String> postResult = GCParser.postLog(cache.getGeocode(), cache.getCacheId(), viewstates, logType,
@@ -115,6 +117,7 @@ class GCLoggingManager extends AbstractLoggingManager implements LoaderManager.L
}
@Override
+ @NonNull
public ImageResult postLogImage(final String logId, final String imageCaption, final String imageDescription, final Uri imageUri) {
if (StringUtils.isNotBlank(imageUri.getPath())) {
@@ -133,6 +136,7 @@ class GCLoggingManager extends AbstractLoggingManager implements LoaderManager.L
}
@Override
+ @NonNull
public List<TrackableLog> getTrackables() {
if (hasLoaderError) {
return Collections.emptyList();
@@ -141,6 +145,7 @@ class GCLoggingManager extends AbstractLoggingManager implements LoaderManager.L
}
@Override
+ @NonNull
public List<LogType> getPossibleLogTypes() {
if (hasLoaderError) {
return Collections.emptyList();
diff --git a/main/src/cgeo/geocaching/connector/gc/GCLogin.java b/main/src/cgeo/geocaching/connector/gc/GCLogin.java
index 3d4f2af..035176b 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCLogin.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCLogin.java
@@ -57,6 +57,7 @@ public class GCLogin extends AbstractLogin {
}
@Override
+ @NonNull
protected StatusCode login(final boolean retry) {
final ImmutablePair<String, String> credentials = Settings.getGcCredentials();
final String username = credentials.left;
@@ -256,7 +257,7 @@ public class GCLogin extends AbstractLogin {
final String avatarURL = TextUtils.getMatch(profile, GCConstants.PATTERN_AVATAR_IMAGE_PROFILE_PAGE, false, null);
if (avatarURL != null) {
- final HtmlImage imgGetter = new HtmlImage("", false, 0, false);
+ final HtmlImage imgGetter = new HtmlImage(HtmlImage.SHARED, false, 0, false);
return imgGetter.fetchDrawable(avatarURL.replace("avatar", "user/large")).cast(Drawable.class);
}
// No match? There may be no avatar set by user.
@@ -470,8 +471,8 @@ public class GCLogin extends AbstractLogin {
*
* @return first is user session, second is session token
*/
- public @NonNull
- MapTokens getMapTokens() {
+ @NonNull
+ public MapTokens getMapTokens() {
final String data = getRequestLogged(GCConstants.URL_LIVE_MAP, null);
final String userSession = TextUtils.getMatch(data, GCConstants.PATTERN_USERSESSION, "");
final String sessionToken = TextUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, "");
diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index 32c8b42..1571faa 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCMap.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -1,6 +1,5 @@
package cgeo.geocaching.connector.gc;
-import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.SearchResult;
@@ -9,12 +8,13 @@ import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.files.ParserException;
import cgeo.geocaching.location.Geopoint;
+import cgeo.geocaching.location.GeopointFormatter.Format;
import cgeo.geocaching.location.Units;
import cgeo.geocaching.location.Viewport;
-import cgeo.geocaching.location.GeopointFormatter.Format;
import cgeo.geocaching.maps.LiveMapStrategy.Strategy;
import cgeo.geocaching.maps.LiveMapStrategy.StrategyFlag;
import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Formatter;
import cgeo.geocaching.utils.JsonUtils;
@@ -27,6 +27,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import rx.Observable;
import rx.functions.Func2;
@@ -47,7 +48,7 @@ import java.util.Set;
public class GCMap {
private static Viewport lastSearchViewport = null;
- public static SearchResult searchByGeocodes(Set<String> geocodes) {
+ public static SearchResult searchByGeocodes(final Set<String> geocodes) {
final SearchResult result = new SearchResult();
final String geocodeList = StringUtils.join(geocodes.toArray(), "|");
@@ -109,7 +110,7 @@ public class GCMap {
* Retrieved data.
* @return SearchResult. Never null.
*/
- public static SearchResult parseMapJSON(final String data, Tile tile, Bitmap bitmap, final Strategy strategy) {
+ public static SearchResult parseMapJSON(final String data, final Tile tile, final Bitmap bitmap, final Strategy strategy) {
final SearchResult searchResult = new SearchResult();
try {
@@ -142,13 +143,13 @@ public class GCMap {
}
// iterate over the data and construct all caches in this tile
- Map<String, List<UTFGridPosition>> positions = new HashMap<>(); // JSON id as key
- Map<String, List<UTFGridPosition>> singlePositions = new HashMap<>(); // JSON id as key
+ final Map<String, List<UTFGridPosition>> positions = new HashMap<>(); // JSON id as key
+ final Map<String, List<UTFGridPosition>> singlePositions = new HashMap<>(); // JSON id as key
for (final JsonNode rawKey: keys) {
final String key = rawKey.asText();
if (StringUtils.isNotBlank(key)) { // index 0 is empty
- UTFGridPosition pos = UTFGridPosition.fromString(key);
+ final UTFGridPosition pos = UTFGridPosition.fromString(key);
final ArrayNode dataForKey = (ArrayNode) dataObject.get(key);
for (final JsonNode cacheInfo: dataForKey) {
final String id = cacheInfo.get("i").asText();
@@ -174,18 +175,18 @@ public class GCMap {
}
final ArrayList<Geocache> caches = new ArrayList<>();
- for (Entry<String, List<UTFGridPosition>> entry : positions.entrySet()) {
- String id = entry.getKey();
- List<UTFGridPosition> pos = entry.getValue();
- UTFGridPosition xy = UTFGrid.getPositionInGrid(pos);
- Geocache cache = new Geocache();
+ for (final Entry<String, List<UTFGridPosition>> entry : positions.entrySet()) {
+ final String id = entry.getKey();
+ final List<UTFGridPosition> pos = entry.getValue();
+ final UTFGridPosition xy = UTFGrid.getPositionInGrid(pos);
+ final Geocache cache = new Geocache();
cache.setDetailed(false);
cache.setReliableLatLon(false);
cache.setGeocode(id);
cache.setName(nameCache.get(id));
cache.setCoords(tile.getCoord(xy), tile.getZoomLevel());
if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && bitmap != null) {
- for (UTFGridPosition singlePos : singlePositions.get(id)) {
+ for (final UTFGridPosition singlePos : singlePositions.get(id)) {
if (IconDecoder.parseMapPNG(cache, bitmap, singlePos, tile.getZoomLevel())) {
break; // cache parsed
}
@@ -227,17 +228,18 @@ public class GCMap {
* Live map tokens
* @return
*/
+ @NonNull
public static SearchResult searchByViewport(final Viewport viewport, final MapTokens tokens) {
- int speed = (int) CgeoApplication.getInstance().currentGeo().getSpeed() * 60 * 60 / 1000; // in km/h
+ 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;
}
- SearchResult result = searchByViewport(viewport, tokens, strategy);
+ final SearchResult result = searchByViewport(viewport, tokens, strategy);
if (Settings.isDebug()) {
- StringBuilder text = new StringBuilder(Formatter.SEPARATOR).append(strategy.getL10n()).append(Formatter.SEPARATOR).append(Units.getSpeed(speed));
+ final StringBuilder text = new StringBuilder(Formatter.SEPARATOR).append(strategy.getL10n()).append(Formatter.SEPARATOR).append(Units.getSpeed(speed));
result.setUrl(result.getUrl() + text);
}
@@ -257,6 +259,7 @@ public class GCMap {
* Strategy for data retrieval and parsing, @see Strategy
* @return
*/
+ @NonNull
private static SearchResult searchByViewport(final Viewport viewport, final MapTokens tokens, final Strategy strategy) {
Log.d("GCMap.searchByViewport" + viewport.toString());
@@ -340,7 +343,7 @@ public class GCMap {
final Geopoint center = viewport.getCenter();
if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) {
//FIXME We don't have a RecaptchaReceiver!?
- SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false, null);
+ final SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false, null);
if (search != null && !search.isEmpty()) {
final Set<String> geocodes = search.getGeocodes();
lastSearchViewport = DataStore.getBounds(geocodes);
@@ -354,11 +357,11 @@ public class GCMap {
/**
* Creates a list of caches types to filter on the live map (exclusion string)
- *
+ *
* @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
* 3 = multi
@@ -366,8 +369,8 @@ public class GCMap {
* 4 = virtual, 11 = webcam, 137 = earth
* 8 = mystery, 1858 = whereigo
*/
- private static String getCacheTypeFilter(CacheType typeToDisplay) {
- Set<String> filterTypes = new HashSet<>();
+ private static String getCacheTypeFilter(final CacheType typeToDisplay) {
+ final Set<String> filterTypes = new HashSet<>();
// Put all types in set, remove what should be visible in a second step
filterTypes.addAll(Arrays.asList("2", "9", "5", "3", "6", "453", "13", "1304", "4", "11", "137", "8", "1858"));
switch (typeToDisplay) {
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index 33447c7..a25cba8 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -78,10 +78,16 @@ import java.util.Set;
import java.util.regex.Pattern;
public abstract class GCParser {
+ @NonNull
private final static SynchronizedDateFormat DATE_TB_IN_1 = new SynchronizedDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009
+
+ @NonNull
private final static SynchronizedDateFormat DATE_TB_IN_2 = new SynchronizedDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009
+
+ @NonNull
private final static ImmutablePair<StatusCode, Geocache> UNKNOWN_PARSE_ERROR = ImmutablePair.of(StatusCode.UNKNOWN_ERROR, null);
+ @Nullable
private static SearchResult parseSearch(final String url, final String pageContent, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(pageContent)) {
Log.e("GCParser.parseSearch: No page given");
@@ -349,11 +355,13 @@ public abstract class GCParser {
return searchResult;
}
+ @Nullable
private static Float parseStars(final String value) {
final float floatValue = Float.parseFloat(StringUtils.replaceChars(value, ',', '.'));
return floatValue >= 0.5 && floatValue <= 5.0 ? floatValue : null;
}
+ @Nullable
static SearchResult parseCache(final String page, final CancellableHandler handler) {
final ImmutablePair<StatusCode, Geocache> parsed = parseCacheFromText(page, handler);
// attention: parseCacheFromText already stores implicitly through searchResult.addCache
@@ -379,6 +387,7 @@ public abstract class GCParser {
return new SearchResult(cache);
}
+ @NonNull
static SearchResult parseAndSaveCacheFromText(final String page, @Nullable final CancellableHandler handler) {
final ImmutablePair<StatusCode, Geocache> parsed = parseCacheFromText(page, handler);
final SearchResult result = new SearchResult(parsed.left);
@@ -771,8 +780,6 @@ public abstract class GCParser {
}
}
- cache.parseWaypointsFromNote();
-
// last check for necessary cache conditions
if (StringUtils.isBlank(cache.getGeocode())) {
return UNKNOWN_PARSE_ERROR;
@@ -782,10 +789,12 @@ public abstract class GCParser {
return ImmutablePair.of(StatusCode.NO_ERROR, cache);
}
+ @Nullable
private static String getNumberString(final String numberWithPunctuation) {
return StringUtils.replaceChars(numberWithPunctuation, ".,", "");
}
+ @Nullable
public static SearchResult searchByNextPage(final SearchResult search, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (search == null) {
return null;
@@ -858,7 +867,7 @@ public abstract class GCParser {
}
@Nullable
- private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, final RecaptchaReceiver recaptchaReceiver) {
+ private static SearchResult searchByAny(@NonNull final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, final RecaptchaReceiver recaptchaReceiver) {
insertCacheType(params, cacheType);
final String uri = "http://www.geocaching.com/seek/nearest.aspx";
@@ -885,12 +894,12 @@ public abstract class GCParser {
return search;
}
- public static SearchResult searchByCoords(final @NonNull Geopoint coords, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByCoords(final @NonNull Geopoint coords, @NonNull final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
final Parameters params = new Parameters("lat", Double.toString(coords.getLatitude()), "lng", Double.toString(coords.getLongitude()));
return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver);
}
- public static SearchResult searchByKeyword(final @NonNull String keyword, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByKeyword(final @NonNull String keyword, @NonNull final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(keyword)) {
Log.e("GCParser.searchByKeyword: No keyword given");
return null;
@@ -908,7 +917,7 @@ public abstract class GCParser {
return false;
}
- public static SearchResult searchByUsername(final String userName, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByUsername(final String userName, @NonNull final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(userName)) {
Log.e("GCParser.searchByUsername: No user name given");
return null;
@@ -919,7 +928,7 @@ public abstract class GCParser {
return searchByAny(cacheType, isSearchForMyCaches(userName), showCaptcha, params, recaptchaReceiver);
}
- public static SearchResult searchByPocketQuery(final String pocketGuid, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByPocketQuery(final String pocketGuid, @NonNull final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(pocketGuid)) {
Log.e("GCParser.searchByPocket: No guid name given");
return null;
@@ -930,7 +939,7 @@ public abstract class GCParser {
return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver);
}
- public static SearchResult searchByOwner(final String userName, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByOwner(final String userName, @NonNull final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(userName)) {
Log.e("GCParser.searchByOwner: No user name given");
return null;
@@ -940,30 +949,6 @@ public abstract class GCParser {
return searchByAny(cacheType, isSearchForMyCaches(userName), showCaptcha, params, recaptchaReceiver);
}
- public static SearchResult searchByAddress(final String address, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
- if (StringUtils.isBlank(address)) {
- Log.e("GCParser.searchByAddress: No address given");
- return null;
- }
-
- final ObjectNode response = Network.requestJSON("http://www.geocaching.com/api/geocode", new Parameters("q", address));
- if (response == null) {
- return null;
- }
-
- if (!StringUtils.equalsIgnoreCase(response.path("status").asText(), "success")) {
- return null;
- }
-
- final JsonNode data = response.path("data");
- final JsonNode latNode = data.get("lat");
- final JsonNode lngNode = data.get("lng");
- if (latNode == null || lngNode == null) {
- return null;
- }
- return searchByCoords(new Geopoint(latNode.asDouble(), lngNode.asDouble()), cacheType, showCaptcha, recaptchaReceiver);
- }
-
@Nullable
public static Trackable searchTrackable(final String geocode, final String guid, final String id) {
if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid) && StringUtils.isBlank(id)) {
@@ -1816,9 +1801,10 @@ public abstract class GCParser {
return types;
}
+ @NonNull
public static List<TrackableLog> parseTrackableLog(final String page) {
if (StringUtils.isEmpty(page)) {
- return null;
+ return Collections.emptyList();
}
String table = StringUtils.substringBetween(page, "<table id=\"tblTravelBugs\"", "</table>");
@@ -1831,7 +1817,7 @@ public abstract class GCParser {
table = StringUtils.substringBetween(table, "<tbody>", "</tbody>");
if (StringUtils.isBlank(table)) {
Log.e("GCParser.parseTrackableLog: tbody not found on page");
- return null;
+ return Collections.emptyList();
}
final List<TrackableLog> trackableLogs = new ArrayList<>();
@@ -1922,7 +1908,7 @@ public abstract class GCParser {
}
// Wait for completion of logs parsing, retrieving and merging
- mergedLogs.toBlocking().last();
+ RxUtils.waitForCompletion(mergedLogs);
}
/**
diff --git a/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java b/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java
index eba9301..071c3b0 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java
@@ -1,5 +1,7 @@
package cgeo.geocaching.connector.gc;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
public class GCSmiliesProvider {
public enum Smiley {
@@ -24,9 +26,10 @@ public class GCSmiliesProvider {
DISAPPROVE("V"),
QUESTION("?");
+ @NonNull
public final String text;
- Smiley(final String text) {
+ Smiley(@NonNull final String text) {
this.text = text;
}
@@ -35,12 +38,14 @@ public class GCSmiliesProvider {
}
}
+ @NonNull
public static Smiley[] getSmilies() {
return Smiley.values();
}
- public static Smiley getSmiley(int itemId) {
- for (Smiley smiley : getSmilies()) {
+ @Nullable
+ public static Smiley getSmiley(final int itemId) {
+ for (final Smiley smiley : getSmilies()) {
if (smiley.getItemId() == itemId) {
return smiley;
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
index 9e9ec7f..a2322e0 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
@@ -48,6 +48,7 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode {
}
@Override
+ @NonNull
public String getLicenseText(final @NonNull Geocache cache) {
// NOT TO BE TRANSLATED
return "© " + cache.getOwnerDisplayName() + ", <a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a>, " + licenseString;
diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
index e8f20c9..2c783fb 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
@@ -17,6 +17,7 @@ import cgeo.geocaching.connector.oc.UserInfo.UserInfoStatus;
import cgeo.geocaching.loaders.RecaptchaReceiver;
import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.location.Viewport;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.CryptUtils;
@@ -49,7 +50,8 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
}
@Override
- public SearchResult searchByViewport(@NonNull final Viewport viewport, final MapTokens tokens) {
+ @NonNull
+ public SearchResult searchByViewport(@NonNull final Viewport viewport, @NonNull final MapTokens tokens) {
return new SearchResult(OkapiClient.getCachesBBox(viewport, this));
}
@@ -98,7 +100,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
}
@Override
- public boolean addToWatchlist(final Geocache cache) {
+ public boolean addToWatchlist(@NonNull final Geocache cache) {
final boolean added = OkapiClient.setWatchState(cache, true, this);
if (added) {
@@ -109,7 +111,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
}
@Override
- public boolean removeFromWatchlist(final Geocache cache) {
+ public boolean removeFromWatchlist(@NonNull final Geocache cache) {
final boolean removed = OkapiClient.setWatchState(cache, false, this);
if (removed) {
@@ -125,12 +127,13 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
}
@Override
- public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) {
+ @NonNull
+ public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache) {
return new OkapiLoggingManager(activity, this, cache);
}
@Override
- public boolean canLog(final Geocache cache) {
+ public boolean canLog(@NonNull final Geocache cache) {
return true;
}
@@ -149,7 +152,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
}
@Override
- public boolean isOwner(final Geocache cache) {
+ public boolean isOwner(@NonNull final Geocache cache) {
return StringUtils.isNotEmpty(getUserName()) && StringUtils.equals(cache.getOwnerDisplayName(), getUserName());
}
@@ -175,8 +178,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
@Override
public SearchResult searchByKeyword(final @NonNull String name, final @NonNull RecaptchaReceiver recaptchaReceiver) {
- final Geopoint currentPos = CgeoApplication.getInstance().currentGeo().getCoords();
- return new SearchResult(OkapiClient.getCachesNamed(currentPos, name, this));
+ return new SearchResult(OkapiClient.getCachesNamed(Sensors.getInstance().currentGeo().getCoords(), name, this));
}
@Override
diff --git a/main/src/cgeo/geocaching/connector/oc/OCConnector.java b/main/src/cgeo/geocaching/connector/oc/OCConnector.java
index 9c79f71..8ac457b 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCConnector.java
@@ -28,42 +28,46 @@ public class OCConnector extends AbstractConnector {
}
@Override
- public boolean canHandle(@NonNull String geocode) {
+ public boolean canHandle(@NonNull final String geocode) {
return codePattern.matcher(geocode).matches();
}
@Override
+ @NonNull
public String getName() {
return name;
}
@Override
- public String getCacheUrl(@NonNull Geocache cache) {
+ @NonNull
+ public String getCacheUrl(@NonNull final Geocache cache) {
return getCacheUrlPrefix() + cache.getGeocode();
}
@Override
+ @NonNull
public String getHost() {
return host;
}
@Override
- public boolean isZippedGPXFile(String fileName) {
+ public boolean isZippedGPXFile(@NonNull final String fileName) {
return GPX_ZIP_FILE_PATTERN.matcher(fileName).matches();
}
@Override
- public boolean isOwner(final Geocache cache) {
+ public boolean isOwner(@NonNull final Geocache cache) {
return false;
}
@Override
+ @NonNull
protected String getCacheUrlPrefix() {
return "http://" + host + "/viewcache.php?wp=";
}
@Override
- public int getCacheMapMarkerId(boolean disabled) {
+ public int getCacheMapMarkerId(final boolean disabled) {
if (disabled) {
return R.drawable.marker_disabled_oc;
}
@@ -71,7 +75,8 @@ public class OCConnector extends AbstractConnector {
}
@Override
- public final List<LogType> getPossibleLogTypes(Geocache cache) {
+ @NonNull
+ public final List<LogType> getPossibleLogTypes(@NonNull final Geocache cache) {
if (cache.isEventCache()) {
return EVENT_LOG_TYPES;
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 1d0f991..ee095e3 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -397,7 +397,6 @@ final class OkapiClient {
}
if (response.hasNonNull(CACHE_MY_NOTES)) {
cache.setPersonalNote(response.get(CACHE_MY_NOTES).asText());
- cache.parseWaypointsFromNote();
}
cache.setLogPasswordRequired(response.get(CACHE_REQ_PASSWORD).asBoolean());
@@ -620,6 +619,7 @@ final class OkapiClient {
cache.setCoords(new Geopoint(latitude, longitude));
}
+ @NonNull
private static CacheSize getCacheSize(final ObjectNode response) {
if (!response.has(CACHE_SIZE2)) {
return getCacheSizeDeprecated(response);
@@ -633,6 +633,7 @@ final class OkapiClient {
}
}
+ @NonNull
private static CacheSize getCacheSizeDeprecated(final ObjectNode response) {
if (!response.has(CACHE_SIZE_DEPRECATED)) {
return CacheSize.NOT_CHOSEN;
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
index 75bc987..76e597c 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
@@ -9,6 +9,9 @@ import cgeo.geocaching.connector.LogResult;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.StatusCode;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
import android.net.Uri;
import java.util.Calendar;
@@ -19,7 +22,7 @@ public class OkapiLoggingManager extends AbstractLoggingManager {
private final OCApiLiveConnector connector;
private final Geocache cache;
- private LogCacheActivity activity;
+ private final LogCacheActivity activity;
private boolean hasLoaderError = true;
public OkapiLoggingManager(final LogCacheActivity activity, final OCApiLiveConnector connector, final Geocache cache) {
@@ -37,18 +40,21 @@ public class OkapiLoggingManager extends AbstractLoggingManager {
}
@Override
- public final LogResult postLog(final LogType logType, final Calendar date, final String log, final String logPassword, final List<TrackableLog> trackableLogs) {
+ @NonNull
+ public final LogResult postLog(@NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, @Nullable final String logPassword, @NonNull final List<TrackableLog> trackableLogs) {
final LogResult result = OkapiClient.postLog(cache, logType, date, log, logPassword, connector);
connector.login(null, null);
return result;
}
@Override
+ @NonNull
public final ImageResult postLogImage(final String logId, final String imageCaption, final String imageDescription, final Uri imageUri) {
return new ImageResult(StatusCode.LOG_POST_ERROR, "");
}
@Override
+ @NonNull
public List<LogType> getPossibleLogTypes() {
if (hasLoaderError) {
return Collections.emptyList();
diff --git a/main/src/cgeo/geocaching/connector/ox/OXConnector.java b/main/src/cgeo/geocaching/connector/ox/OXConnector.java
index dd048f9..41035d1 100644
--- a/main/src/cgeo/geocaching/connector/ox/OXConnector.java
+++ b/main/src/cgeo/geocaching/connector/ox/OXConnector.java
@@ -29,33 +29,37 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I
private static final Pattern PATTERN_GEOCODE = Pattern.compile("OX[A-Z0-9]+", Pattern.CASE_INSENSITIVE);
@Override
- public boolean canHandle(@NonNull String geocode) {
+ public boolean canHandle(@NonNull final String geocode) {
return PATTERN_GEOCODE.matcher(geocode).matches();
}
@Override
- public String getCacheUrl(@NonNull Geocache cache) {
+ @NonNull
+ public String getCacheUrl(@NonNull final Geocache cache) {
return getCacheUrlPrefix() + cache.getGeocode();
}
@Override
+ @NonNull
public String getName() {
return "OpenCaching.com";
}
@Override
+ @NonNull
public String getHost() {
return "www.opencaching.com";
}
@Override
- public String getLicenseText(@NonNull Geocache cache) {
+ @NonNull
+ public String getLicenseText(@NonNull final Geocache cache) {
// NOT TO BE TRANSLATED
return "<a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a> data licensed under the Creative Commons CC-BY-SA 3.0 License";
}
@Override
- public boolean isOwner(final Geocache cache) {
+ public boolean isOwner(@NonNull final Geocache cache) {
return false;
}
@@ -73,17 +77,19 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I
}
@Override
- public SearchResult searchByCenter(@NonNull Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) {
+ public SearchResult searchByCenter(@NonNull final Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) {
return createSearchResult(OpenCachingApi.searchByCenter(center));
}
@Override
+ @NonNull
protected String getCacheUrlPrefix() {
return "http://www.opencaching.com/#!geocache/";
}
@Override
- public SearchResult searchByViewport(@NonNull Viewport viewport, final MapTokens tokens) {
+ @NonNull
+ public SearchResult searchByViewport(@NonNull final Viewport viewport, @NonNull final MapTokens tokens) {
return createSearchResult(OpenCachingApi.searchByBoundingBox(viewport));
}
@@ -97,7 +103,7 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I
return createSearchResult(OpenCachingApi.searchByKeyword(name));
}
- private static SearchResult createSearchResult(Collection<Geocache> caches) {
+ private static SearchResult createSearchResult(final Collection<Geocache> caches) {
if (caches == null) {
return null;
}
diff --git a/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java
index fb554b9..c3a7437 100644
--- a/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java
+++ b/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java
@@ -16,14 +16,14 @@ public abstract class AbstractTrackableConnector implements TrackableConnector {
}
@Override
- public @Nullable
- String getTrackableCodeFromUrl(@NonNull String url) {
+ @Nullable
+ public String getTrackableCodeFromUrl(@NonNull final String url) {
return null;
}
@Override
- public @NonNull
- List<UserAction> getUserActions() {
+ @NonNull
+ public List<UserAction> getUserActions() {
return AbstractConnector.getDefaultUserActions();
}
}
diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java
index 03052f9..b6792f0 100644
--- a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java
+++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java
@@ -15,17 +15,18 @@ public class GeokretyConnector extends AbstractTrackableConnector {
private static final Pattern PATTERN_GK_CODE = Pattern.compile("GK[0-9A-F]{4,}");
@Override
- public boolean canHandleTrackable(String geocode) {
+ public boolean canHandleTrackable(final String geocode) {
return geocode != null && PATTERN_GK_CODE.matcher(geocode).matches();
}
@Override
- public String getUrl(Trackable trackable) {
+ @NonNull
+ public String getUrl(@NonNull final Trackable trackable) {
return "http://geokrety.org/konkret.php?id=" + getId(trackable.getGeocode());
}
@Override
- public Trackable searchTrackable(String geocode, String guid, String id) {
+ 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) {
return null;
@@ -33,7 +34,7 @@ public class GeokretyConnector extends AbstractTrackableConnector {
return GeokretyParser.parse(page);
}
- protected static int getId(String geocode) {
+ protected static int getId(final String geocode) {
try {
final String hex = geocode.substring(2);
return Integer.parseInt(hex, 16);
@@ -45,9 +46,9 @@ public class GeokretyConnector extends AbstractTrackableConnector {
@Override
public @Nullable
- String getTrackableCodeFromUrl(@NonNull String url) {
+ String getTrackableCodeFromUrl(@NonNull final String url) {
// http://geokrety.org/konkret.php?id=38545
- String id = StringUtils.substringAfterLast(url, "konkret.php?id=");
+ final String id = StringUtils.substringAfterLast(url, "konkret.php?id=");
if (StringUtils.isNumeric(id)) {
return geocode(Integer.parseInt(id));
}
diff --git a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java
index 6071b5f..01c1897 100644
--- a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java
+++ b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java
@@ -16,16 +16,17 @@ public interface TrackableConnector {
public boolean canHandleTrackable(final String geocode);
- public String getUrl(final Trackable trackable);
+ @NonNull
+ public String getUrl(@NonNull final Trackable trackable);
public boolean isLoggable();
public Trackable searchTrackable(String geocode, String guid, String id);
- public @Nullable
- String getTrackableCodeFromUrl(final @NonNull String url);
+ @Nullable
+ public String getTrackableCodeFromUrl(final @NonNull String url);
- public @NonNull
- List<UserAction> getUserActions();
+ @NonNull
+ public List<UserAction> getUserActions();
}
diff --git a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java
index 3307481..5d825a3 100644
--- a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java
+++ b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java
@@ -25,7 +25,8 @@ public class TravelBugConnector extends AbstractTrackableConnector {
}
@Override
- public String getUrl(final Trackable trackable) {
+ @NonNull
+ public String getUrl(@NonNull final Trackable trackable) {
return "http://www.geocaching.com//track/details.aspx?tracker=" + trackable.getGeocode();
}
diff --git a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java
index 0295927..7e7e1b6 100644
--- a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java
+++ b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java
@@ -2,22 +2,23 @@ package cgeo.geocaching.connector.trackable;
import cgeo.geocaching.Trackable;
-import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
public class UnknownTrackableConnector extends AbstractTrackableConnector {
@Override
- public boolean canHandleTrackable(String geocode) {
+ public boolean canHandleTrackable(final String geocode) {
return false;
}
@Override
- public String getUrl(Trackable trackable) {
- return StringUtils.EMPTY;
+ @NonNull
+ public String getUrl(@NonNull final Trackable trackable) {
+ throw new IllegalStateException("getUrl cannot be called on unknown trackables");
}
@Override
- public Trackable searchTrackable(String geocode, String guid, String id) {
+ 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 771a508..823ea7e 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
@@ -4,6 +4,8 @@ import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import android.util.SparseArray;
@@ -163,7 +165,10 @@ public enum CacheAttribute {
enabled ? stringIdYes : stringIdNo);
}
+ @NonNull
private final static Map<String, CacheAttribute> FIND_BY_GCRAWNAME;
+
+ @NonNull
private final static SparseArray<CacheAttribute> FIND_BY_OCACODE = new SparseArray<>();
static {
final HashMap<String, CacheAttribute> mapGcRawNames = new HashMap<>();
@@ -176,14 +181,17 @@ public enum CacheAttribute {
FIND_BY_GCRAWNAME = Collections.unmodifiableMap(mapGcRawNames);
}
+ @Nullable
public static CacheAttribute getByRawName(final String rawName) {
return rawName != null ? FIND_BY_GCRAWNAME.get(rawName) : null;
}
+ @Nullable
public static CacheAttribute getByOcACode(final int ocAcode) {
return FIND_BY_OCACODE.get(ocAcode);
}
+ @NonNull
public static String trimAttributeName(final String attributeName) {
if (null == attributeName) {
return "";
diff --git a/main/src/cgeo/geocaching/enumerations/CacheSize.java b/main/src/cgeo/geocaching/enumerations/CacheSize.java
index 3a2f379..37446b9 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheSize.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheSize.java
@@ -3,6 +3,8 @@ package cgeo.geocaching.enumerations;
import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
@@ -38,6 +40,7 @@ public enum CacheSize {
this.ocSize2 = ocSize2;
}
+ @NonNull
final private static Map<String, CacheSize> FIND_BY_ID;
static {
final HashMap<String, CacheSize> mapping = new HashMap<>();
@@ -50,6 +53,7 @@ public enum CacheSize {
FIND_BY_ID = Collections.unmodifiableMap(mapping);
}
+ @NonNull
public static CacheSize getById(final String id) {
if (id == null) {
return UNKNOWN;
@@ -73,6 +77,7 @@ public enum CacheSize {
* @param id
* @return
*/
+ @NonNull
private static CacheSize getByNumber(final String id) {
try {
final int numerical = Integer.parseInt(id);
diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java
index 995c436..f551c52 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheType.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheType.java
@@ -4,6 +4,8 @@ import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
@@ -56,9 +58,15 @@ public enum CacheType {
this.markerId = markerId;
}
+ @NonNull
private final static Map<String, CacheType> FIND_BY_ID;
+
+ @NonNull
private final static Map<String, CacheType> FIND_BY_PATTERN;
+
+ @NonNull
private final static Map<String, CacheType> FIND_BY_GUID;
+
static {
final HashMap<String, CacheType> mappingId = new HashMap<>();
final HashMap<String, CacheType> mappingPattern = new HashMap<>();
@@ -80,6 +88,7 @@ public enum CacheType {
FIND_BY_GUID = Collections.unmodifiableMap(mappingGuid);
}
+ @NonNull
public static CacheType getById(final String id) {
final CacheType result = (id != null) ? CacheType.FIND_BY_ID.get(id.toLowerCase(Locale.US).trim()) : null;
if (result == null) {
@@ -88,6 +97,7 @@ public enum CacheType {
return result;
}
+ @NonNull
public static CacheType getByPattern(final String pattern) {
final CacheType result = (pattern != null) ? CacheType.FIND_BY_PATTERN.get(pattern.toLowerCase(Locale.US).trim()) : null;
if (result == null) {
@@ -96,6 +106,7 @@ public enum CacheType {
return result;
}
+ @NonNull
public static CacheType getByGuid(final String id) {
final CacheType result = (id != null) ? CacheType.FIND_BY_GUID.get(id) : null;
if (result == null) {
diff --git a/main/src/cgeo/geocaching/enumerations/LogType.java b/main/src/cgeo/geocaching/enumerations/LogType.java
index 5345611..4c83321 100644
--- a/main/src/cgeo/geocaching/enumerations/LogType.java
+++ b/main/src/cgeo/geocaching/enumerations/LogType.java
@@ -3,6 +3,8 @@ package cgeo.geocaching.enumerations;
import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
@@ -65,7 +67,10 @@ public enum LogType {
this(id, iconName, type, oc_type, stringId, R.drawable.mark_gray);
}
+ @NonNull
private final static Map<String, LogType> FIND_BY_ICONNAME;
+
+ @NonNull
private final static Map<String, LogType> FIND_BY_TYPE;
static {
final HashMap<String, LogType> mappingPattern = new HashMap<>();
@@ -80,6 +85,7 @@ public enum LogType {
FIND_BY_TYPE = Collections.unmodifiableMap(mappingType);
}
+ @NonNull
public static LogType getById(final int id) {
for (final LogType logType : values()) {
if (logType.id == id) {
@@ -89,6 +95,7 @@ public enum LogType {
return UNKNOWN;
}
+ @NonNull
public static LogType getByIconName(final String imageType) {
// Special case for post reviewer note, which appears sometimes as 18.png (in individual entries) or as 68.png
// (in logs counts).
@@ -102,6 +109,7 @@ public enum LogType {
return result;
}
+ @NonNull
public static LogType getByType(final String type) {
final LogType result = type != null ? LogType.FIND_BY_TYPE.get(type.toLowerCase(Locale.US).trim()) : null;
if (result == null) {
diff --git a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java
index e008294..fefeb62 100644
--- a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java
+++ b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java
@@ -3,15 +3,17 @@ package cgeo.geocaching.enumerations;
import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
public enum LogTypeTrackable {
DO_NOTHING("", R.string.log_tb_nothing),
VISITED("_Visited", R.string.log_tb_visit),
DROPPED_OFF("_DroppedOff", R.string.log_tb_drop);
- final public String action;
+ @NonNull final public String action;
final private int resourceId;
- LogTypeTrackable(String action, int resourceId) {
+ LogTypeTrackable(@NonNull final String action, final int resourceId) {
this.action = action;
this.resourceId = resourceId;
}
diff --git a/main/src/cgeo/geocaching/enumerations/WaypointType.java b/main/src/cgeo/geocaching/enumerations/WaypointType.java
index 1805635..81c0e4d 100644
--- a/main/src/cgeo/geocaching/enumerations/WaypointType.java
+++ b/main/src/cgeo/geocaching/enumerations/WaypointType.java
@@ -3,6 +3,8 @@ package cgeo.geocaching.enumerations;
import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -22,11 +24,12 @@ public enum WaypointType {
WAYPOINT("waypoint", R.string.wp_waypoint, R.drawable.waypoint_waypoint),
ORIGINAL("original", R.string.wp_original, R.drawable.waypoint_waypoint);
+ @NonNull
public final String id;
public final int stringId;
public final int markerId;
- WaypointType(String id, int stringId, int markerId) {
+ WaypointType(@NonNull final String id, final int stringId, final int markerId) {
this.id = id;
this.stringId = stringId;
this.markerId = markerId;
@@ -36,11 +39,14 @@ public enum WaypointType {
* inverse lookup of waypoint IDs<br/>
* non public so that <code>null</code> handling can be handled centrally in the enum type itself
*/
+ @NonNull
private static final Map<String, WaypointType> FIND_BY_ID;
+
+ @NonNull
public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL = new HashSet<>();
static {
final HashMap<String, WaypointType> mapping = new HashMap<>();
- for (WaypointType wt : values()) {
+ for (final WaypointType wt : values()) {
mapping.put(wt.id, wt);
if (wt != WaypointType.OWN && wt != WaypointType.ORIGINAL) {
ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL.add(wt);
@@ -53,11 +59,12 @@ public enum WaypointType {
* inverse lookup of waypoint IDs<br/>
* here the <code>null</code> handling shall be done
*/
+ @NonNull
public static WaypointType findById(final String id) {
if (null == id) {
return WAYPOINT;
}
- WaypointType waypointType = FIND_BY_ID.get(id);
+ final WaypointType waypointType = FIND_BY_ID.get(id);
if (null == waypointType) {
return WAYPOINT;
}
diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java
index c03b848..c4a6adc 100644
--- a/main/src/cgeo/geocaching/export/FieldnoteExport.java
+++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java
@@ -59,10 +59,11 @@ public class FieldnoteExport extends AbstractExport {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
final Context themedContext;
- if (Settings.isLightSkin() && VERSION.SDK_INT < VERSION_CODES.HONEYCOMB)
+ if (Settings.isLightSkin() && VERSION.SDK_INT < VERSION_CODES.HONEYCOMB) {
themedContext = new ContextThemeWrapper(activity, R.style.dark);
- else
+ } else {
themedContext = activity;
+ }
final View layout = View.inflate(themedContext, R.layout.fieldnote_export_dialog, null);
builder.setView(layout);
@@ -135,8 +136,10 @@ public class FieldnoteExport extends AbstractExport {
for (final Geocache cache : caches) {
if (ConnectorFactory.getConnector(cache).equals(connector) && cache.isLogOffline()) {
final LogEntry log = DataStore.loadLogOffline(cache.getGeocode());
- if (!onlyNew || log.date > Settings.getFieldnoteExportDate()) {
- fieldNotes.add(cache, log);
+ if (log != null) {
+ if (!onlyNew || log.date > Settings.getFieldnoteExportDate()) {
+ fieldNotes.add(cache, log);
+ }
}
}
publishProgress(++i);
diff --git a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
index fa84df9..427fd48 100644
--- a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
+++ b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
@@ -9,6 +9,7 @@ import cgeo.geocaching.utils.Log;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import android.app.ProgressDialog;
import android.content.DialogInterface;
@@ -203,7 +204,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
* @param filename
* @return <code>true</code> if the filename belongs to the list
*/
- protected boolean filenameBelongsToList(final String filename) {
+ protected boolean filenameBelongsToList(@NonNull final String filename) {
for (final String ext : extensions) {
if (StringUtils.endsWithIgnoreCase(filename, ext)) {
return true;
diff --git a/main/src/cgeo/geocaching/files/FileParser.java b/main/src/cgeo/geocaching/files/FileParser.java
index 9521c70..9c70a0d 100644
--- a/main/src/cgeo/geocaching/files/FileParser.java
+++ b/main/src/cgeo/geocaching/files/FileParser.java
@@ -16,7 +16,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collection;
-import java.util.Date;
import java.util.concurrent.CancellationException;
public abstract class FileParser {
@@ -24,25 +23,22 @@ public abstract class FileParser {
* Parses caches from input stream.
*
* @param stream
+ * the input stream
* @param progressHandler
- * for reporting parsing progress (in bytes read from input stream)
+ * for reporting parsing progress (in bytes read from input stream)
* @return collection of caches
* @throws IOException
- * if the input stream can't be read
+ * if the input stream can't be read
* @throws ParserException
- * if the input stream contains data not matching the file format of the parser
+ * if the input stream contains data not matching the file format of the parser
*/
+ @NonNull
public abstract Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException;
/**
* Convenience method for parsing a file.
- *
- * @param file
- * @param progressHandler
- * @return
- * @throws IOException
- * @throws ParserException
*/
+ @NonNull
public Collection<Geocache> parse(final File file, final CancellableHandler progressHandler) throws IOException, ParserException {
final BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file));
try {
@@ -52,6 +48,7 @@ public abstract class FileParser {
}
}
+ @NonNull
protected static StringBuilder readStream(@NonNull final InputStream is, @Nullable final CancellableHandler progressHandler) throws IOException {
final StringBuilder buffer = new StringBuilder();
final ProgressInputStream progressInputStream = new ProgressInputStream(is);
@@ -84,7 +81,7 @@ public abstract class FileParser {
} else {
cache.setInventoryItems(0);
}
- final long time = new Date().getTime();
+ final long time = System.currentTimeMillis();
cache.setUpdated(time);
cache.setDetailedUpdate(time);
}
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
index cd99ae9..7dd5c4a 100644
--- a/main/src/cgeo/geocaching/files/GPXParser.java
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -274,6 +274,7 @@ public abstract class GPXParser extends FileParser {
}
@Override
+ @NonNull
public Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException {
resetCache();
final RootElement root = new RootElement(namespace, "gpx");
diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java
index bca7dcf..a5a4b9c 100644
--- a/main/src/cgeo/geocaching/files/LocParser.java
+++ b/main/src/cgeo/geocaching/files/LocParser.java
@@ -31,8 +31,10 @@ import java.util.Set;
public final class LocParser extends FileParser {
+ @NonNull
private static final String NAME_OWNER_SEPARATOR = " by ";
+ @NonNull
private static final CacheSize[] SIZES = {
CacheSize.NOT_CHOSEN, // 1
CacheSize.MICRO, // 2
@@ -45,16 +47,17 @@ public final class LocParser extends FileParser {
};
// Used so that the initial value of the geocache is not null. Never filled.
+ @NonNull
private static final Geocache DUMMY_GEOCACHE = new Geocache();
- private int listId;
+ private final int listId;
public static void parseLoc(final SearchResult searchResult, final String fileContent, final Set<Geocache> caches) {
final Map<String, Geocache> cidCoords = parseLoc(fileContent);
// save found cache coordinates
final HashSet<String> contained = new HashSet<>();
- for (String geocode : searchResult.getGeocodes()) {
+ for (final String geocode : searchResult.getGeocodes()) {
if (cidCoords.containsKey(geocode)) {
contained.add(geocode);
}
@@ -70,10 +73,12 @@ public final class LocParser extends FileParser {
}
}
+ @NonNull
private static Map<String, Geocache> parseLoc(final String content) {
return parseLoc(new ByteArrayInputStream(content.getBytes(Charsets.UTF_8)));
}
+ @NonNull
private static Map<String, Geocache> parseLoc(final InputStream content) {
try {
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
@@ -146,22 +151,24 @@ public final class LocParser extends FileParser {
cache.setOwnerUserId(coord.getOwnerUserId());
}
+ @NonNull
public static Geopoint parsePoint(final String latitude, final String longitude) {
// the loc file contains the coordinates as plain floating point values, therefore avoid using the GeopointParser
try {
return new Geopoint(Double.valueOf(latitude), Double.valueOf(longitude));
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.e("LOC format has changed", e);
}
// fall back to parser, just in case the format changes
return new Geopoint(latitude, longitude);
}
- public LocParser(int listId) {
+ public LocParser(final int listId) {
this.listId = listId;
}
@Override
+ @NonNull
public Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException {
final int maxSize = stream.available();
final Map<String, Geocache> coords = parseLoc(stream);
diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java
index 8896833..7fce27d 100644
--- a/main/src/cgeo/geocaching/files/LocalStorage.java
+++ b/main/src/cgeo/geocaching/files/LocalStorage.java
@@ -45,7 +45,7 @@ public final class LocalStorage {
public static final String HEADER_ETAG = "etag";
/** Name of the local private directory used to hold cached information */
- public final static String cache = ".cgeo";
+ public final static String CACHE_DIRNAME = ".cgeo";
private static File internalStorageBase;
@@ -74,7 +74,7 @@ public final class LocalStorage {
private static File getStorageSpecific(final boolean secondary) {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ^ secondary ?
getExternalStorageBase() :
- new File(getInternalStorageBase(), LocalStorage.cache);
+ new File(getInternalStorageBase(), LocalStorage.CACHE_DIRNAME);
}
public static File getExternalDbDirectory() {
@@ -86,7 +86,7 @@ public final class LocalStorage {
}
private static File getExternalStorageBase() {
- return new File(Environment.getExternalStorageDirectory(), LocalStorage.cache);
+ return new File(Environment.getExternalStorageDirectory(), LocalStorage.CACHE_DIRNAME);
}
private static File getInternalStorageBase() {
@@ -105,7 +105,7 @@ public final class LocalStorage {
* @return the file extension, including the leading dot, or the empty string if none could be determined
*/
static String getExtension(final String url) {
- String urlExt;
+ final String urlExt;
if (url.startsWith("data:")) {
// "data:image/png;base64,i53…" -> ".png"
urlExt = StringUtils.substringAfter(StringUtils.substringBefore(url, ";"), "/");
@@ -124,7 +124,7 @@ public final class LocalStorage {
* the geocode
* @return the cache directory
*/
- public static File getStorageDir(@Nullable final String geocode) {
+ public static File getStorageDir(@NonNull final String geocode) {
return storageDir(getStorage(), geocode);
}
@@ -136,12 +136,12 @@ public final class LocalStorage {
* the geocode
* @return the cache directory
*/
- private static File getStorageSecDir(@Nullable final String geocode) {
+ private static File getStorageSecDir(@NonNull final String geocode) {
return storageDir(getStorageSec(), geocode);
}
- private static File storageDir(final File base, @Nullable final String geocode) {
- return new File(base, StringUtils.defaultIfEmpty(geocode, "_others"));
+ private static File storageDir(final File base, @NonNull final String geocode) {
+ return new File(base, geocode);
}
/**
@@ -157,7 +157,7 @@ public final class LocalStorage {
* true if an url was given, false if a file name was given
* @return the file
*/
- public static File getStorageFile(@Nullable final String geocode, final String fileNameOrUrl, final boolean isUrl, final boolean createDirs) {
+ public static File getStorageFile(@NonNull final String geocode, final String fileNameOrUrl, final boolean isUrl, final boolean createDirs) {
return buildFile(getStorageDir(geocode), fileNameOrUrl, isUrl, createDirs);
}
@@ -244,14 +244,14 @@ public final class LocalStorage {
public static String getSavedHeader(final File baseFile, final String name) {
try {
final File file = filenameForHeader(baseFile, name);
- final Reader f = new InputStreamReader(new FileInputStream(file), CharEncoding.UTF_8);
+ final Reader reader = new InputStreamReader(new FileInputStream(file), CharEncoding.UTF_8);
try {
// No header will be more than 256 bytes
final char[] value = new char[256];
- final int count = f.read(value);
+ final int count = reader.read(value);
return new String(value, 0, count);
} finally {
- f.close();
+ reader.close();
}
} catch (final FileNotFoundException ignored) {
// Do nothing, the file does not exist
@@ -442,10 +442,10 @@ public final class LocalStorage {
try {
fr = new InputStreamReader(new FileInputStream(file), CharEncoding.UTF_8);
br = new BufferedReader(fr);
- String s = br.readLine();
- while (s != null) {
- if (s.startsWith("dev_mount")) {
- final String[] tokens = StringUtils.split(s);
+ String str = br.readLine();
+ while (str != null) {
+ if (str.startsWith("dev_mount")) {
+ final String[] tokens = StringUtils.split(str);
if (tokens.length >= 3) {
final String path = tokens[2]; // mountpoint
if (!extStorage.equals(path)) {
@@ -456,7 +456,7 @@ public final class LocalStorage {
}
}
}
- s = br.readLine();
+ str = br.readLine();
}
} catch (final IOException e) {
Log.e("Could not get additional mount points for user content. " +
diff --git a/main/src/cgeo/geocaching/filter/AbstractFilter.java b/main/src/cgeo/geocaching/filter/AbstractFilter.java
index e602b0f..248c9c2 100644
--- a/main/src/cgeo/geocaching/filter/AbstractFilter.java
+++ b/main/src/cgeo/geocaching/filter/AbstractFilter.java
@@ -2,6 +2,8 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.Geocache;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.ArrayList;
import java.util.List;
@@ -13,9 +15,9 @@ abstract class AbstractFilter implements IFilter {
}
@Override
- public void filter(final List<Geocache> list) {
+ public void filter(@NonNull final List<Geocache> list) {
final List<Geocache> itemsToRemove = new ArrayList<>();
- for (Geocache item : list) {
+ for (final Geocache item : list) {
if (!accepts(item)) {
itemsToRemove.add(item);
}
diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java
index b59ab29..2fc6eb2 100644
--- a/main/src/cgeo/geocaching/filter/AttributeFilter.java
+++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java
@@ -4,6 +4,8 @@ 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.LinkedList;
@@ -25,13 +27,14 @@ class AttributeFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return cache.getAttributes().contains(attribute);
}
public static class Factory implements IFilterFactory {
@Override
+ @NonNull
public List<IFilter> getFilters() {
final String packageName = CgeoApplication.getInstance().getBaseContext().getPackageName();
final Resources res = CgeoApplication.getInstance().getResources();
diff --git a/main/src/cgeo/geocaching/filter/DifficultyFilter.java b/main/src/cgeo/geocaching/filter/DifficultyFilter.java
index 175ad75..7989560 100644
--- a/main/src/cgeo/geocaching/filter/DifficultyFilter.java
+++ b/main/src/cgeo/geocaching/filter/DifficultyFilter.java
@@ -3,6 +3,8 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.ArrayList;
import java.util.List;
@@ -13,7 +15,7 @@ class DifficultyFilter extends AbstractRangeFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
final float difficulty = cache.getDifficulty();
return rangeMin <= difficulty && difficulty < rangeMax;
}
@@ -24,6 +26,7 @@ class DifficultyFilter extends AbstractRangeFilter {
private static final int DIFFICULTY_MAX = 5;
@Override
+ @NonNull
public List<IFilter> getFilters() {
final ArrayList<IFilter> filters = new ArrayList<>(DIFFICULTY_MAX);
for (int difficulty = DIFFICULTY_MIN; difficulty <= DIFFICULTY_MAX; difficulty++) {
diff --git a/main/src/cgeo/geocaching/filter/DistanceFilter.java b/main/src/cgeo/geocaching/filter/DistanceFilter.java
index 3890571..f1ba7f8 100644
--- a/main/src/cgeo/geocaching/filter/DistanceFilter.java
+++ b/main/src/cgeo/geocaching/filter/DistanceFilter.java
@@ -2,9 +2,12 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.sensors.GeoData;
import cgeo.geocaching.R;
import cgeo.geocaching.location.Geopoint;
+import cgeo.geocaching.sensors.GeoData;
+import cgeo.geocaching.sensors.Sensors;
+
+import org.eclipse.jdt.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
@@ -14,15 +17,15 @@ class DistanceFilter extends AbstractFilter {
private final int minDistance;
private final int maxDistance;
- public DistanceFilter(String name, final int minDistance, final int maxDistance) {
+ public DistanceFilter(final String name, final int minDistance, final int maxDistance) {
super(name);
this.minDistance = minDistance;
this.maxDistance = maxDistance;
- geo = CgeoApplication.getInstance().currentGeo();
+ geo = Sensors.getInstance().currentGeo();
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
final Geopoint currentPos = new Geopoint(geo);
final Geopoint coords = cache.getCoords();
if (coords == null) {
@@ -39,6 +42,7 @@ class DistanceFilter extends AbstractFilter {
private static final int[] KILOMETERS = { 0, 2, 5, 10, 20, 50 };
@Override
+ @NonNull
public List<IFilter> getFilters() {
final List<IFilter> filters = new ArrayList<>(KILOMETERS.length);
for (int i = 0; i < KILOMETERS.length; i++) {
diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
index 9f1d563..590a726 100644
--- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java
+++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
@@ -54,12 +54,12 @@ public final class FilterUserInterface {
register(R.string.cache_attributes, AttributeFilter.Factory.class);
register(R.string.cache_status, StateFilter.Factory.class);
register(R.string.caches_filter_track, TrackablesFilter.class);
- register(R.string.caches_filter_modified, ModifiedFilter.class);
register(R.string.caches_filter_origin, OriginFilter.Factory.class);
register(R.string.caches_filter_distance, DistanceFilter.Factory.class);
- register(R.string.caches_filter_personal_note, PersonalNoteFilter.class);
register(R.string.caches_filter_popularity, PopularityFilter.Factory.class);
register(R.string.caches_filter_popularity_ratio, PopularityRatioFilter.Factory.class);
+ register(R.string.caches_filter_personal_data, PersonalDataFilterFactory.class);
+ register(R.string.caches_filter_rating, RatingFilter.class);
// sort by localized names
Collections.sort(registry, new Comparator<FactoryEntry>() {
@@ -87,16 +87,16 @@ public final class FilterUserInterface {
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int itemIndex) {
- FactoryEntry entry = adapter.getItem(itemIndex);
+ final FactoryEntry entry = adapter.getItem(itemIndex);
// reset?
if (entry.filterFactory == null) {
runAfterwards.call(null);
}
else {
try {
- IFilterFactory factoryInstance = entry.filterFactory.newInstance();
+ final IFilterFactory factoryInstance = entry.filterFactory.newInstance();
selectFromFactory(factoryInstance, entry.name, runAfterwards);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("selectFilter", e);
}
}
diff --git a/main/src/cgeo/geocaching/filter/IFilter.java b/main/src/cgeo/geocaching/filter/IFilter.java
index 4fafe6f..de39e5a 100644
--- a/main/src/cgeo/geocaching/filter/IFilter.java
+++ b/main/src/cgeo/geocaching/filter/IFilter.java
@@ -2,6 +2,8 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.Geocache;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.List;
public interface IFilter {
@@ -12,7 +14,7 @@ public interface IFilter {
* @param cache
* @return true if the filter accepts the cache, false otherwise
*/
- boolean accepts(final Geocache cache);
+ boolean accepts(@NonNull final Geocache cache);
- void filter(final List<Geocache> list);
+ void filter(@NonNull final List<Geocache> list);
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/filter/IFilterFactory.java b/main/src/cgeo/geocaching/filter/IFilterFactory.java
index afc99af..82e69da 100644
--- a/main/src/cgeo/geocaching/filter/IFilterFactory.java
+++ b/main/src/cgeo/geocaching/filter/IFilterFactory.java
@@ -1,7 +1,10 @@
package cgeo.geocaching.filter;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.List;
interface IFilterFactory {
+ @NonNull
List<? extends IFilter> getFilters();
}
diff --git a/main/src/cgeo/geocaching/filter/ModifiedFilter.java b/main/src/cgeo/geocaching/filter/ModifiedFilter.java
index 2ac088a..c224cb4 100644
--- a/main/src/cgeo/geocaching/filter/ModifiedFilter.java
+++ b/main/src/cgeo/geocaching/filter/ModifiedFilter.java
@@ -4,6 +4,8 @@ import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.Collections;
import java.util.List;
@@ -14,12 +16,13 @@ class ModifiedFilter extends AbstractFilter implements IFilterFactory {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
// modified on GC
return cache.hasUserModifiedCoords() || cache.hasFinalDefined();
}
@Override
+ @NonNull
public List<ModifiedFilter> getFilters() {
return Collections.singletonList(this);
}
diff --git a/main/src/cgeo/geocaching/filter/OriginFilter.java b/main/src/cgeo/geocaching/filter/OriginFilter.java
index 99d1c05..4fb3301 100644
--- a/main/src/cgeo/geocaching/filter/OriginFilter.java
+++ b/main/src/cgeo/geocaching/filter/OriginFilter.java
@@ -4,6 +4,8 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -19,16 +21,17 @@ public class OriginFilter extends AbstractFilter {
}
@Override
- public final boolean accepts(final Geocache cache) {
+ public final boolean accepts(@NonNull final Geocache cache) {
return ConnectorFactory.getConnector(cache) == connector;
}
public static final class Factory implements IFilterFactory {
@Override
+ @NonNull
public List<OriginFilter> getFilters() {
final ArrayList<OriginFilter> filters = new ArrayList<>();
- for (IConnector connector : ConnectorFactory.getConnectors()) {
+ for (final IConnector connector : ConnectorFactory.getConnectors()) {
filters.add(new OriginFilter(connector));
}
diff --git a/main/src/cgeo/geocaching/filter/OwnRatingFilter.java b/main/src/cgeo/geocaching/filter/OwnRatingFilter.java
new file mode 100644
index 0000000..0c468a9
--- /dev/null
+++ b/main/src/cgeo/geocaching/filter/OwnRatingFilter.java
@@ -0,0 +1,35 @@
+package cgeo.geocaching.filter;
+
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
+import cgeo.geocaching.gcvote.GCVote;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Filter {@link Geocache}s if they have a locally stored <b>own</b> {@link GCVote} rating. This filter will not do any
+ * network request to find potentially missing local votes.
+ *
+ */
+public class OwnRatingFilter extends AbstractFilter implements IFilterFactory {
+
+ protected OwnRatingFilter() {
+ super(CgeoApplication.getInstance().getString(R.string.caches_filter_own_rating));
+ }
+
+ @Override
+ public boolean accepts(@NonNull final Geocache cache) {
+ return cache.getMyVote() > 0;
+ }
+
+ @Override
+ @NonNull
+ public List<OwnRatingFilter> getFilters() {
+ return Collections.singletonList(this);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java b/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java
new file mode 100644
index 0000000..6c6186b
--- /dev/null
+++ b/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java
@@ -0,0 +1,16 @@
+package cgeo.geocaching.filter;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class PersonalDataFilterFactory implements IFilterFactory {
+
+ @Override
+ @NonNull
+ public List<? extends IFilter> getFilters() {
+ return Arrays.asList(new OwnRatingFilter(), new PersonalNoteFilter(), new ModifiedFilter());
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java b/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java
index 15d262f..978ad6b 100644
--- a/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java
+++ b/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java
@@ -5,10 +5,14 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import java.util.Collections;
import java.util.List;
+/**
+ * Filter that accepts {@link Geocache}s with a non empty personal note stored locally.
+ */
public class PersonalNoteFilter extends AbstractFilter implements IFilterFactory {
protected PersonalNoteFilter() {
@@ -16,11 +20,12 @@ public class PersonalNoteFilter extends AbstractFilter implements IFilterFactory
}
@Override
- public boolean accepts(Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return StringUtils.isNotBlank(cache.getPersonalNote());
}
@Override
+ @NonNull
public List<PersonalNoteFilter> getFilters() {
return Collections.singletonList(this);
}
diff --git a/main/src/cgeo/geocaching/filter/PopularityFilter.java b/main/src/cgeo/geocaching/filter/PopularityFilter.java
index 0fc807d..bb564e8 100644
--- a/main/src/cgeo/geocaching/filter/PopularityFilter.java
+++ b/main/src/cgeo/geocaching/filter/PopularityFilter.java
@@ -4,6 +4,8 @@ import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.ArrayList;
import java.util.List;
@@ -11,14 +13,14 @@ class PopularityFilter extends AbstractFilter {
private final int minFavorites;
private final int maxFavorites;
- public PopularityFilter(String name, final int minFavorites, final int maxFavorites) {
+ public PopularityFilter(final String name, final int minFavorites, final int maxFavorites) {
super(name);
this.minFavorites = minFavorites;
this.maxFavorites = maxFavorites;
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return (cache.getFavoritePoints() > minFavorites) && (cache.getFavoritePoints() <= maxFavorites);
}
@@ -27,6 +29,7 @@ class PopularityFilter extends AbstractFilter {
private static final int[] FAVORITES = { 10, 20, 50, 100, 200, 500 };
@Override
+ @NonNull
public List<IFilter> getFilters() {
final List<IFilter> filters = new ArrayList<>(FAVORITES.length);
for (final int minRange : FAVORITES) {
diff --git a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java
index f7ac4db..53904f1 100644
--- a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java
+++ b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java
@@ -6,6 +6,8 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.enumerations.LogType;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.ArrayList;
import java.util.List;
@@ -23,7 +25,7 @@ class PopularityRatioFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
final int finds = getFindsCount(cache);
if (finds == 0) { // Prevent division by zero
@@ -51,6 +53,7 @@ class PopularityRatioFilter extends AbstractFilter {
private static final int[] RATIOS = { 10, 20, 30, 40, 50, 75 };
@Override
+ @NonNull
public List<IFilter> getFilters() {
final List<IFilter> filters = new ArrayList<>(RATIOS.length);
for (final int minRange : RATIOS) {
diff --git a/main/src/cgeo/geocaching/filter/RatingFilter.java b/main/src/cgeo/geocaching/filter/RatingFilter.java
new file mode 100644
index 0000000..3edfcb6
--- /dev/null
+++ b/main/src/cgeo/geocaching/filter/RatingFilter.java
@@ -0,0 +1,35 @@
+package cgeo.geocaching.filter;
+
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
+import cgeo.geocaching.gcvote.GCVote;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Filter {@link Geocache}s if they have a locally stored {@link GCVote} rating. This filter will not do any network
+ * request to find potentially missing local votes.
+ *
+ */
+public class RatingFilter extends AbstractFilter implements IFilterFactory {
+
+ protected RatingFilter() {
+ super(CgeoApplication.getInstance().getString(R.string.caches_filter_rating));
+ }
+
+ @Override
+ public boolean accepts(@NonNull final Geocache cache) {
+ return cache.getRating() > 0;
+ }
+
+ @Override
+ @NonNull
+ public List<RatingFilter> getFilters() {
+ return Collections.singletonList(this);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/filter/SizeFilter.java b/main/src/cgeo/geocaching/filter/SizeFilter.java
index f02874c..4c7c122 100644
--- a/main/src/cgeo/geocaching/filter/SizeFilter.java
+++ b/main/src/cgeo/geocaching/filter/SizeFilter.java
@@ -3,6 +3,8 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.enumerations.CacheSize;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.LinkedList;
import java.util.List;
@@ -15,7 +17,7 @@ class SizeFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return cacheSize == cache.getSize();
}
@@ -27,10 +29,11 @@ class SizeFilter extends AbstractFilter {
public static class Factory implements IFilterFactory {
@Override
+ @NonNull
public List<IFilter> getFilters() {
final CacheSize[] cacheSizes = CacheSize.values();
final List<IFilter> filters = new LinkedList<>();
- for (CacheSize cacheSize : cacheSizes) {
+ for (final CacheSize cacheSize : cacheSizes) {
if (cacheSize != CacheSize.UNKNOWN) {
filters.add(new SizeFilter(cacheSize));
}
diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java
index ebe133c..f574045 100644
--- a/main/src/cgeo/geocaching/filter/StateFilter.java
+++ b/main/src/cgeo/geocaching/filter/StateFilter.java
@@ -4,6 +4,8 @@ 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;
@@ -26,7 +28,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return cache.isFound();
}
@@ -39,7 +41,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return !cache.isFound();
}
@@ -51,7 +53,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return cache.isArchived();
}
}
@@ -62,7 +64,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return cache.isDisabled();
}
}
@@ -73,7 +75,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return cache.isPremiumMembersOnly();
}
}
@@ -84,7 +86,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return !cache.isPremiumMembersOnly();
}
}
@@ -95,7 +97,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return cache.isLogOffline();
}
}
@@ -106,7 +108,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return cache.isOffline();
}
}
@@ -117,7 +119,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return !cache.isOffline();
}
}
@@ -125,6 +127,7 @@ abstract class StateFilter extends AbstractFilter {
public static class Factory implements IFilterFactory {
@Override
+ @NonNull
public List<StateFilter> getFilters() {
final List<StateFilter> filters = new ArrayList<>(6);
filters.add(new StateFoundFilter());
diff --git a/main/src/cgeo/geocaching/filter/TerrainFilter.java b/main/src/cgeo/geocaching/filter/TerrainFilter.java
index 7da6a19..977e4a5 100644
--- a/main/src/cgeo/geocaching/filter/TerrainFilter.java
+++ b/main/src/cgeo/geocaching/filter/TerrainFilter.java
@@ -3,6 +3,8 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.ArrayList;
import java.util.List;
@@ -13,7 +15,7 @@ class TerrainFilter extends AbstractRangeFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
final float terrain = cache.getTerrain();
return rangeMin <= terrain && terrain < rangeMax;
}
@@ -23,6 +25,7 @@ class TerrainFilter extends AbstractRangeFilter {
private static final int TERRAIN_MAX = 7;
@Override
+ @NonNull
public List<IFilter> getFilters() {
final ArrayList<IFilter> filters = new ArrayList<>(TERRAIN_MAX);
for (int terrain = TERRAIN_MIN; terrain <= TERRAIN_MAX; terrain++) {
diff --git a/main/src/cgeo/geocaching/filter/TrackablesFilter.java b/main/src/cgeo/geocaching/filter/TrackablesFilter.java
index d836a0f..7ad06a1 100644
--- a/main/src/cgeo/geocaching/filter/TrackablesFilter.java
+++ b/main/src/cgeo/geocaching/filter/TrackablesFilter.java
@@ -4,6 +4,8 @@ import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.Collections;
import java.util.List;
@@ -13,11 +15,12 @@ class TrackablesFilter extends AbstractFilter implements IFilterFactory {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return cache.hasTrackables();
}
@Override
+ @NonNull
public List<TrackablesFilter> getFilters() {
return Collections.singletonList(this);
}
diff --git a/main/src/cgeo/geocaching/filter/TypeFilter.java b/main/src/cgeo/geocaching/filter/TypeFilter.java
index d363d39..412cbc2 100644
--- a/main/src/cgeo/geocaching/filter/TypeFilter.java
+++ b/main/src/cgeo/geocaching/filter/TypeFilter.java
@@ -3,6 +3,8 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.enumerations.CacheType;
+import org.eclipse.jdt.annotation.NonNull;
+
import java.util.LinkedList;
import java.util.List;
@@ -15,7 +17,7 @@ class TypeFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final Geocache cache) {
+ public boolean accepts(@NonNull final Geocache cache) {
return cacheType == cache.getType();
}
@@ -27,10 +29,11 @@ class TypeFilter extends AbstractFilter {
public static class Factory implements IFilterFactory {
@Override
+ @NonNull
public List<IFilter> getFilters() {
final CacheType[] types = CacheType.values();
final List<IFilter> filters = new LinkedList<>();
- for (CacheType cacheType : types) {
+ for (final CacheType cacheType : types) {
if (cacheType != CacheType.ALL) {
filters.add(new TypeFilter(cacheType));
}
diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java
index eaf7687..2985e89 100644
--- a/main/src/cgeo/geocaching/gcvote/GCVote.java
+++ b/main/src/cgeo/geocaching/gcvote/GCVote.java
@@ -131,8 +131,11 @@ public final class GCVote {
* @return {@code true} if the rating was submitted successfully
*/
public static boolean setRating(final Geocache cache, final float rating) {
- if (!isVotingPossible(cache) || !isValidRating(rating)) {
- throw new IllegalArgumentException(!isVotingPossible(cache) ? "voting is not possible for " + cache : "invalid rating " + rating);
+ if (!isVotingPossible(cache)) {
+ throw new IllegalArgumentException("voting is not possible for " + cache);
+ }
+ if (!isValidRating(rating)) {
+ throw new IllegalArgumentException("invalid rating " + rating);
}
final ImmutablePair<String, String> login = Settings.getGCvoteLogin();
@@ -199,7 +202,7 @@ public final class GCVote {
return rating >= MIN_RATING && rating <= MAX_RATING;
}
- public static boolean isVotingPossible(final Geocache cache) {
+ public static boolean isVotingPossible(@NonNull final Geocache cache) {
return Settings.isGCvoteLogin() && StringUtils.isNotBlank(cache.getGuid()) && cache.supportsGCVote();
}
diff --git a/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java b/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java
new file mode 100644
index 0000000..da14e0b
--- /dev/null
+++ b/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java
@@ -0,0 +1,74 @@
+package cgeo.geocaching.gcvote;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
+import cgeo.geocaching.gcvote.GCVoteRatingBarUtil.OnRatingChangeListener;
+import cgeo.geocaching.settings.Settings;
+
+import org.eclipse.jdt.annotation.Nullable;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Build.VERSION;
+import android.os.Build.VERSION_CODES;
+import android.view.ContextThemeWrapper;
+import android.view.View;
+import android.widget.Button;
+
+/**
+ * Small dialog showing only a rating bar to vote on GCVote.com. Confirming the dialog will send the vote over the
+ * network (in the background).
+ */
+public class GCVoteDialog {
+
+ public static void show(final Activity context, final Geocache cache, final @Nullable Runnable afterVoteSent) {
+ final Context themedContext;
+
+ if (Settings.isLightSkin() && VERSION.SDK_INT < VERSION_CODES.HONEYCOMB) {
+ themedContext = new ContextThemeWrapper(context, R.style.dark);
+ } else {
+ themedContext = context;
+ }
+
+ final View votingLayout = View.inflate(themedContext, R.layout.gcvote_dialog, null);
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(themedContext);
+ builder.setView(votingLayout);
+ builder.setPositiveButton(R.string.cache_menu_vote, new OnClickListener() {
+
+ @Override
+ public void onClick(final DialogInterface dialog, final int which) {
+ vote(cache, GCVoteRatingBarUtil.getRating(votingLayout), afterVoteSent);
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(final DialogInterface dialog, final int whichButton) {
+ dialog.dismiss();
+ }
+ });
+ final AlertDialog dialog = builder.create();
+
+ GCVoteRatingBarUtil.initializeRatingBar(cache, votingLayout, new OnRatingChangeListener() {
+
+ @Override
+ public void onRatingChanged(final float stars) {
+ final Button button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
+ // this listener might be fired already while the dialog is not yet shown
+ if (button != null) {
+ button.setEnabled(GCVote.isValidRating(stars));
+ }
+ }
+ });
+ dialog.show();
+ dialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(GCVote.isValidRating(cache.getMyVote()));
+ }
+
+ protected static void vote(final Geocache cache, final float rating, final @Nullable Runnable afterVoteSent) {
+ new GCVotePoster(cache, rating, afterVoteSent).execute();
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/gcvote/GCVotePoster.java b/main/src/cgeo/geocaching/gcvote/GCVotePoster.java
new file mode 100644
index 0000000..924aa56
--- /dev/null
+++ b/main/src/cgeo/geocaching/gcvote/GCVotePoster.java
@@ -0,0 +1,53 @@
+package cgeo.geocaching.gcvote;
+
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
+import cgeo.geocaching.utils.Log;
+
+import org.eclipse.jdt.annotation.Nullable;
+
+import android.os.AsyncTask;
+import android.widget.Toast;
+
+class GCVotePoster extends AsyncTask<Void, Void, Boolean> {
+
+ private final Geocache cache;
+ private final float rating;
+ private final @Nullable Runnable afterVoteSent;
+
+ public GCVotePoster(final Geocache cache, final float rating, final @Nullable Runnable afterVoteSent) {
+ this.cache = cache;
+ this.rating = rating;
+ this.afterVoteSent = afterVoteSent;
+ }
+
+ @Override
+ protected Boolean doInBackground(final Void... inputs) {
+ try {
+ if (GCVote.isValidRating(rating) && GCVote.isVotingPossible(cache)) {
+ // store locally
+ cache.setMyVote(rating);
+ DataStore.saveChangedCache(cache);
+
+ // send over network
+ return GCVote.setRating(cache, rating);
+ }
+ } catch (final RuntimeException e) {
+ Log.e("GCVoteAsyncTask.doInBackground", e);
+ }
+
+ return false;
+ }
+
+ @Override
+ protected void onPostExecute(final Boolean status) {
+ final CgeoApplication context = CgeoApplication.getInstance();
+ final String text = context.getString(status ? R.string.gcvote_sent : R.string.err_gcvote_send_rating);
+ Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
+ if (afterVoteSent != null) {
+ afterVoteSent.run();
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/gcvote/GCVoteRatingBarUtil.java b/main/src/cgeo/geocaching/gcvote/GCVoteRatingBarUtil.java
new file mode 100644
index 0000000..2d485bd
--- /dev/null
+++ b/main/src/cgeo/geocaching/gcvote/GCVoteRatingBarUtil.java
@@ -0,0 +1,58 @@
+package cgeo.geocaching.gcvote;
+
+import butterknife.ButterKnife;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
+
+import org.eclipse.jdt.annotation.Nullable;
+
+import android.view.View;
+import android.widget.RatingBar;
+import android.widget.RatingBar.OnRatingBarChangeListener;
+import android.widget.TextView;
+
+/**
+ * TODO: convert to fragment
+ *
+ */
+public final class GCVoteRatingBarUtil {
+ public interface OnRatingChangeListener {
+ public void onRatingChanged(final float stars);
+ }
+
+ private GCVoteRatingBarUtil() {
+ // utility class
+ }
+
+ public static void initializeRatingBar(final Geocache cache, final View parentView, @Nullable final OnRatingChangeListener changeListener) {
+ if (GCVote.isVotingPossible(cache)) {
+ final RatingBar ratingBar = ButterKnife.findById(parentView, R.id.gcvoteRating);
+ final TextView label = ButterKnife.findById(parentView, R.id.gcvoteLabel);
+ ratingBar.setVisibility(View.VISIBLE);
+ label.setVisibility(View.VISIBLE);
+ ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {
+
+ @Override
+ public void onRatingChanged(final RatingBar ratingBar, final float stars, final boolean fromUser) {
+ // 0.5 is not a valid rating, therefore we must limit
+ final float rating = GCVote.isValidRating(stars) ? stars : 0;
+ if (rating < stars) {
+ ratingBar.setRating(rating);
+ }
+ label.setText(GCVote.getDescription(rating));
+ if (changeListener != null) {
+ changeListener.onRatingChanged(rating);
+ }
+ }
+ });
+ ratingBar.setRating(cache.getMyVote());
+ }
+ }
+
+ public static float getRating(final View parentView) {
+ final RatingBar ratingBar = ButterKnife.findById(parentView, R.id.gcvoteRating);
+ return ratingBar.getRating();
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/list/StoredList.java b/main/src/cgeo/geocaching/list/StoredList.java
index 4291a0a..0ffd58a 100644
--- a/main/src/cgeo/geocaching/list/StoredList.java
+++ b/main/src/cgeo/geocaching/list/StoredList.java
@@ -106,11 +106,8 @@ public final class StoredList extends AbstractList {
final List<AbstractList> lists = new ArrayList<>();
lists.addAll(getSortedLists());
- if (exceptListId > StoredList.TEMPORARY_LIST.id) {
- final StoredList exceptList = DataStore.getList(exceptListId);
- if (exceptList != null) {
- lists.remove(exceptList);
- }
+ if (exceptListId == StoredList.STANDARD_LIST_ID || exceptListId >= DataStore.customListIdOffset) {
+ lists.remove(DataStore.getList(exceptListId));
}
if (!onlyConcreteLists) {
diff --git a/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java
deleted file mode 100644
index e1573c9..0000000
--- a/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package cgeo.geocaching.loaders;
-
-import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.connector.gc.GCParser;
-import cgeo.geocaching.settings.Settings;
-
-import android.content.Context;
-
-public class AddressGeocacheListLoader extends AbstractSearchLoader {
-
- private final String address;
-
- public AddressGeocacheListLoader(Context context, String address) {
- super(context);
- this.address = address;
- }
-
- @Override
- public SearchResult runSearch() {
- return GCParser.searchByAddress(address, Settings.getCacheType(), Settings.isShowCaptcha(), this);
- }
-
-}
diff --git a/main/src/cgeo/geocaching/location/AndroidGeocoder.java b/main/src/cgeo/geocaching/location/AndroidGeocoder.java
new file mode 100644
index 0000000..98ea285
--- /dev/null
+++ b/main/src/cgeo/geocaching/location/AndroidGeocoder.java
@@ -0,0 +1,59 @@
+package cgeo.geocaching.location;
+
+import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RxUtils;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.eclipse.jdt.annotation.NonNull;
+
+import rx.Observable;
+import rx.functions.Func0;
+
+import android.content.Context;
+import android.location.Address;
+import android.location.Geocoder;
+
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Encapsulation of the Android {@link Geocoder} with default error handling. All methods of this class
+ * are blocking and will do network lookups.
+ *
+ */
+public class AndroidGeocoder {
+ private final Geocoder geocoder;
+
+ public AndroidGeocoder(final Context context) {
+ geocoder = new Geocoder(context, Locale.getDefault());
+ }
+
+ /**
+ * Retrieve addresses from a textual location using Android geocoding API. The work happens on the network
+ * scheduler.
+ *
+ * @param keyword
+ * the location
+ * @return an observable containing zero or more locations
+ *
+ * @see Geocoder#getFromLocationName(String, int)
+ */
+ public Observable<Address> getFromLocationName(@NonNull final String keyword) {
+ return Observable.defer(new Func0<Observable<Address>>() {
+ @Override
+ public Observable<Address> call() {
+ try {
+ final List<Address> addresses = geocoder.getFromLocationName(keyword, 20);
+ if (CollectionUtils.isEmpty(addresses)) {
+ return Observable.error(new RuntimeException("no result from Android geocoder"));
+ }
+ return Observable.from(addresses);
+ } catch (final Exception e) {
+ Log.i("Unable to use Android geocoder: " + e.getMessage());
+ return Observable.error(e);
+ }
+ }
+ }).subscribeOn(RxUtils.networkScheduler);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/location/GCGeocoder.java b/main/src/cgeo/geocaching/location/GCGeocoder.java
new file mode 100644
index 0000000..549044f
--- /dev/null
+++ b/main/src/cgeo/geocaching/location/GCGeocoder.java
@@ -0,0 +1,65 @@
+package cgeo.geocaching.location;
+
+import cgeo.geocaching.network.Network;
+import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RxUtils;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+
+import rx.Observable;
+import rx.functions.Func0;
+
+import android.location.Address;
+
+import java.util.Locale;
+
+public class GCGeocoder {
+
+ private GCGeocoder() {
+ // Do not instantiate
+ }
+
+ /**
+ * Retrieve addresses from a textual location using geocaching.com geocoding API. The work happens on the network
+ * scheduler.
+ *
+ * @param address
+ * the location
+ * @return an observable containing zero or more locations
+ *
+ * @see android.location.Geocoder#getFromLocationName(String, int)
+ */
+ public static Observable<Address> getFromLocationName(@NonNull final String address) {
+ return Observable.defer(new Func0<Observable<Address>>() {
+ @Override
+ public Observable<Address> call() {
+ if (!Settings.isGCConnectorActive()) {
+ return Observable.error(new RuntimeException("geocaching.com connector is not active"));
+ }
+ final ObjectNode response = Network.requestJSON("https://www.geocaching.com/api/geocode", new Parameters("q", address));
+ if (response == null || !StringUtils.equalsIgnoreCase(response.path("status").asText(), "success")) {
+ return Observable.error(new RuntimeException("unable to use geocaching.com geocoder"));
+ }
+
+ final JsonNode data = response.path("data");
+ final Address geocodedAddress = new Address(Locale.getDefault());
+ try {
+ geocodedAddress.setLatitude(data.get("lat").asDouble());
+ geocodedAddress.setLongitude(data.get("lng").asDouble());
+ geocodedAddress.setAddressLine(0, address);
+ return Observable.just(geocodedAddress);
+ } catch (final Exception e) {
+ Log.e("unable to decode answer from geocaching.com geocoder", e);
+ return Observable.error(e);
+ }
+ }
+ }).subscribeOn(RxUtils.networkScheduler);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/location/Geocoder.java b/main/src/cgeo/geocaching/location/Geocoder.java
deleted file mode 100644
index 1582daa..0000000
--- a/main/src/cgeo/geocaching/location/Geocoder.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package cgeo.geocaching.location;
-
-import cgeo.geocaching.utils.Log;
-
-import org.apache.commons.lang3.StringUtils;
-import org.eclipse.jdt.annotation.NonNull;
-
-import android.content.Context;
-import android.location.Address;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Encapsulation of the Android {@link android.location.Geocoder} with default error handling. All methods of this class
- * are blocking and will do network lookups.
- *
- */
-public class Geocoder {
- private final android.location.Geocoder geocoder;
-
- public Geocoder(final Context context) {
- geocoder = new android.location.Geocoder(context, Locale.getDefault());
- }
-
- /**
- * @param keyword
- * @return
- *
- * @see android.location.Geocoder#getFromLocationName(String, int)
- */
- public @NonNull List<Address> getFromLocationName(final String keyword) {
- try {
- return geocoder.getFromLocationName(keyword, 20);
- } catch (final Exception e) {
- handleException(e);
- return Collections.emptyList();
- }
- }
-
- public @NonNull List<Address> getFromLocation(final Geopoint coords) {
- try {
- return geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 20);
- } catch (final IOException e) {
- handleException(e);
- return Collections.emptyList();
- }
- }
-
- private static void handleException(final Exception e) {
- // non Google devices come without the geocoder
- if (StringUtils.containsIgnoreCase(e.getMessage(), "Service not Available")) {
- Log.i("No geocoder available");
- }
- else {
- Log.e("Geocoder", e);
- }
- }
-}
diff --git a/main/src/cgeo/geocaching/location/GeopointParser.java b/main/src/cgeo/geocaching/location/GeopointParser.java
index e73e787..a6b8e45 100644
--- a/main/src/cgeo/geocaching/location/GeopointParser.java
+++ b/main/src/cgeo/geocaching/location/GeopointParser.java
@@ -122,7 +122,7 @@ class GeopointParser {
// Nothing found with "N 52...", try to match string as decimal degree parts (i.e. multiple doubles)
try {
- final String[] items = StringUtils.split(text.trim());
+ final String[] items = StringUtils.split(StringUtils.trimToEmpty(text));
if (items.length > 0 && items.length <= 2) {
final int index = (latlon == LatLon.LON ? items.length - 1 : 0);
final String textPart = items[index];
diff --git a/main/src/cgeo/geocaching/location/MapQuestGeocoder.java b/main/src/cgeo/geocaching/location/MapQuestGeocoder.java
new file mode 100644
index 0000000..537ae40
--- /dev/null
+++ b/main/src/cgeo/geocaching/location/MapQuestGeocoder.java
@@ -0,0 +1,117 @@
+package cgeo.geocaching.location;
+
+import cgeo.geocaching.network.Network;
+import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RxUtils;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+
+import rx.Observable;
+import rx.Observable.OnSubscribe;
+import rx.Subscriber;
+import rx.functions.Func0;
+
+import android.location.Address;
+
+import java.util.Locale;
+
+public class MapQuestGeocoder {
+
+ private static final String MAPQUEST_KEY = "Fmjtd|luurn1u2n9,bs=o5-9wynua";
+
+ private MapQuestGeocoder() {
+ // Do not instantiate
+ }
+
+ /**
+ * Retrieve addresses from a textual location using MapQuest geocoding API. The work happens on the network
+ * scheduler.
+ *
+ * @param address
+ * the location
+ * @return an observable containing zero or more locations
+ *
+ * @see android.location.Geocoder#getFromLocationName(String, int)
+ */
+ public static Observable<Address> getFromLocationName(@NonNull final String address) {
+ return Observable.defer(new Func0<Observable<Address>>() {
+ @Override
+ public Observable<Address> call() {
+ final ObjectNode response = Network.requestJSON("https://www.mapquestapi.com/geocoding/v1/address",
+ new Parameters("key", MAPQUEST_KEY, "location", address, "maxResults", "20", "thumbMaps", "false"));
+ if (response == null) {
+ Log.w("MapQuest decoder error: no response");
+ return Observable.error(new RuntimeException("no answer from MapQuest geocoder"));
+ }
+ final int statusCode = response.path("info").path("statuscode").asInt(-1);
+ if (statusCode != 0) {
+ Log.w("MapQuest decoder error: statuscode is not 0");
+ return Observable.error(new RuntimeException("no correct answer from MapQuest geocoder"));
+ }
+ return Observable.create(new OnSubscribe<Address>() {
+ @Override
+ public void call(final Subscriber<? super Address> subscriber) {
+ try {
+ for (final JsonNode address: response.get("results").get(0).get("locations")) {
+ subscriber.onNext(mapquestToAddress(address));
+ }
+ subscriber.onCompleted();
+ } catch (final Exception e) {
+ Log.e("Error decoding MapQuest address", e);
+ subscriber.onError(e);
+ }
+ }
+ });
+ }
+ }).subscribeOn(RxUtils.networkScheduler);
+ }
+
+ private static Address mapquestToAddress(final JsonNode mapquestAddress) {
+ final Address address = new Address(Locale.getDefault());
+ for (int i = 1; i <= 6; i++) {
+ final String adminAreaName = "adminArea" + i;
+ setComponent(address, mapquestAddress, adminAreaName, mapquestAddress.path(adminAreaName + "Type").asText());
+ }
+ setComponent(address, mapquestAddress, "postalCode", "PostalCode");
+ int index = 0;
+ for (final String addressComponent: new String[]{ mapquestAddress.path("street").asText(), address.getSubLocality(), address.getLocality(),
+ address.getPostalCode(), address.getSubAdminArea(), address.getAdminArea(), address.getCountryCode() }) {
+ if (StringUtils.isNotBlank(addressComponent)) {
+ address.setAddressLine(index++, addressComponent);
+ }
+ }
+ address.setLatitude(mapquestAddress.get("latLng").get("lat").asDouble());
+ address.setLongitude(mapquestAddress.get("latLng").get("lng").asDouble());
+ return address;
+ }
+
+ private static void setComponent(final Address address, final JsonNode mapquestAddress, final String adminArea, final String adminAreaType) {
+ final String content = StringUtils.trimToNull(mapquestAddress.path(adminArea).asText());
+ switch (adminAreaType) {
+ case "City":
+ address.setLocality(content);
+ break;
+ case "Neighborhood":
+ address.setSubLocality(content);
+ break;
+ case "PostalCode":
+ address.setPostalCode(content);
+ break;
+ case "State":
+ address.setAdminArea(content);
+ break;
+ case "County":
+ address.setSubAdminArea(content);
+ break;
+ case "Country":
+ address.setCountryCode(content);
+ break;
+ }
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/location/Viewport.java b/main/src/cgeo/geocaching/location/Viewport.java
index e482828..b885336 100644
--- a/main/src/cgeo/geocaching/location/Viewport.java
+++ b/main/src/cgeo/geocaching/location/Viewport.java
@@ -87,7 +87,7 @@ public final class Viewport {
*/
public int count(final @NonNull Collection<? extends ICoordinates> points) {
int total = 0;
- for (ICoordinates point: points) {
+ for (final ICoordinates point: points) {
if (point != null && contains(point)) {
total += 1;
}
@@ -102,7 +102,7 @@ public final class Viewport {
/**
* Check whether another viewport is fully included into the current one.
- *
+ *
* @param vp
* the other viewport
* @return true if the viewport is fully included into this one, false otherwise
@@ -118,6 +118,7 @@ public final class Viewport {
* the database table to use as prefix, or null if no prefix is required
* @return the string without the "where" keyword
*/
+ @NonNull
public StringBuilder sqlWhere(@Nullable final String dbTable) {
final String prefix = dbTable == null ? "" : (dbTable + ".");
return new StringBuilder(prefix).append("latitude >= ").append(getLatitudeMin()).append(" and ")
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index 2868679..f2a5146 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -34,6 +34,7 @@ import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OnMapDragListener;
import cgeo.geocaching.sensors.GeoData;
import cgeo.geocaching.sensors.GeoDirHandler;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.LiveMapInfoDialogBuilder;
import cgeo.geocaching.utils.AngleUtils;
@@ -133,7 +134,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
// Those are initialized in onCreate() and will never be null afterwards
private Resources res;
private Activity activity;
- private CgeoApplication app;
private MapItemFactory mapItemFactory;
private String mapTitle;
final private LeastRecentlyUsedSet<Geocache> caches = new LeastRecentlyUsedSet<>(MAX_CACHES + DataStore.getAllCachesCount());
@@ -382,7 +382,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
// class init
res = this.getResources();
activity = this.getActivity();
- app = (CgeoApplication) activity.getApplication();
final MapProvider mapProvider = Settings.getMapProvider();
mapItemFactory = mapProvider.getMapItemFactory();
@@ -491,7 +490,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
});
}
- if (!app.isLiveMapHintShownInThisSession() && Settings.getLiveMapHintShowCount() <= 3) {
+ if (!CgeoApplication.getInstance().isLiveMapHintShownInThisSession() && Settings.getLiveMapHintShowCount() <= 3) {
LiveMapInfoDialogBuilder.create(activity).show();
}
}
@@ -955,7 +954,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
// minimum change of location in fraction of map width/height (whatever is smaller) for position overlay update
private static final float MIN_LOCATION_DELTA = 0.01f;
- Location currentLocation = CgeoApplication.getInstance().currentGeo();
+ Location currentLocation = Sensors.getInstance().currentGeo();
float currentHeading;
private long timeLastPositionOverlayCalculation = 0;
@@ -1539,7 +1538,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
if (myLocSwitch != null) {
myLocSwitch.setChecked(followMyLocation);
if (followMyLocation) {
- myLocationInMiddle(app.currentGeo());
+ myLocationInMiddle(Sensors.getInstance().currentGeo());
}
}
}
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java
index d1d458d..97e0e45 100644
--- a/main/src/cgeo/geocaching/network/HtmlImage.java
+++ b/main/src/cgeo/geocaching/network/HtmlImage.java
@@ -44,7 +44,6 @@ import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.util.Date;
/**
* All-purpose image getter that can also be used as a ImageGetter interface when displaying caches.
@@ -70,7 +69,7 @@ public class HtmlImage implements Html.ImageGetter {
};
public static final String SHARED = "shared";
- final private String geocode;
+ @NonNull final private String geocode;
/**
* on error: return large error image, if {@code true}, otherwise empty 1x1 image
*/
@@ -91,34 +90,45 @@ public class HtmlImage implements Html.ImageGetter {
// Background loading
final private PublishSubject<Observable<String>> loading = PublishSubject.create();
- final private Observable<String> waitForEnd = Observable.merge(loading).publish().refCount();
+ final private Observable<String> waitForEnd = Observable.merge(loading).cache();
final private CompositeSubscription subscription = new CompositeSubscription(waitForEnd.subscribe());
/**
- * Create a new HtmlImage object with different behaviours depending on <tt>onlySave</tt> and <tt>view</tt> values.
+ * Create a new HtmlImage object with different behaviors depending on <tt>onlySave</tt> and <tt>view</tt> values.
* There are the three possible use cases:
* <ul>
- * <li>If onlySave is true, getDrawable() will return null immediately and will queue the image retrieval
- * and saving in the loading subject. Downloads will start in parallel when the blocking
- * waitForBackgroundLoading() method is called, and they can be cancelled through the given handler.</li>
- * <li>If onlySave is false and the instance is called through fetchDrawable(), then an observable for the
- * given URL will be returned. This observable will emit the local copy of the image if it is present</li>
- * regardless of its freshness, then if needed an updated fresher copy after retrieving it from the network.
- * <li>If onlySave is false and the instance is used as an ImageGetter, only the final version of the
- * image will be returned, unless a view has been provided. If it has, then a dummy drawable is returned
- * and is updated when the image is available, possibly several times if we had a stale copy of the image
- * and then got a new one from the network.</li>
+ * <li>If onlySave is true, {@link #getDrawable(String)} will return <tt>null</tt> immediately and will queue the
+ * image retrieval and saving in the loading subject. Downloads will start in parallel when the blocking
+ * {@link #waitForEndObservable(cgeo.geocaching.utils.CancellableHandler)} method is called, and they can be
+ * cancelled through the given handler.</li>
+ * <li>If <tt>onlySave</tt> is <tt>false</tt> and the instance is called through {@link #fetchDrawable(String)},
+ * then an observable for the given URL will be returned. This observable will emit the local copy of the image if
+ * it is present regardless of its freshness, then if needed an updated fresher copy after retrieving it from the
+ * network.</li>
+ * <li>If <tt>onlySave</tt> is <tt>false</tt> and the instance is used as an {@link android.text.Html.ImageGetter},
+ * only the final version of the image will be returned, unless a view has been provided. If it has, then a dummy
+ * drawable is returned and is updated when the image is available, possibly several times if we had a stale copy of
+ * the image and then got a new one from the network.</li>
* </ul>
*
- * @param geocode the geocode of the item for which we are requesting the image
- * @param returnErrorImage set to <tt>true</tt> if an error image should be returned in case of a problem,
- * <tt>false</tt> to get a transparent 1x1 image instead
- * @param listId the list this cache belongs to, used to determine if an older image for the offline case can be used or not
- * @param onlySave if set to <tt>true</tt>, {@link #getDrawable(String)} will only fetch and store the image, not return it
- * @param view if non-null, {@link #getDrawable(String)} will return an initially empty drawable which will be redrawn when
- * the image is ready through an invalidation of the given view
+ * @param geocode
+ * the geocode of the item for which we are requesting the image, or {@link #SHARED} to use the shared
+ * cache directory
+ * @param returnErrorImage
+ * set to <tt>true</tt> if an error image should be returned in case of a problem, <tt>false</tt> to get
+ * a transparent 1x1 image instead
+ * @param listId
+ * the list this cache belongs to, used to determine if an older image for the offline case can be used
+ * or not
+ * @param onlySave
+ * if set to <tt>true</tt>, {@link #getDrawable(String)} will only fetch and store the image, not return
+ * it
+ * @param view
+ * if non-null, {@link #getDrawable(String)} will return an initially empty drawable which will be
+ * redrawn when
+ * the image is ready through an invalidation of the given view
*/
- public HtmlImage(final String geocode, final boolean returnErrorImage, final int listId, final boolean onlySave, final TextView view) {
+ public HtmlImage(@NonNull final String geocode, final boolean returnErrorImage, final int listId, final boolean onlySave, final TextView view) {
this.geocode = geocode;
this.returnErrorImage = returnErrorImage;
this.listId = listId;
@@ -132,12 +142,12 @@ public class HtmlImage implements Html.ImageGetter {
}
/**
- * Create a new HtmlImage object with different behaviours depending on <tt>onlySave</tt> value. No view object
+ * Create a new HtmlImage object with different behaviors depending on <tt>onlySave</tt> value. No view object
* will be tied to this HtmlImage.
*
* For documentation, see {@link #HtmlImage(String, boolean, int, boolean, TextView)}.
*/
- public HtmlImage(final String geocode, final boolean returnErrorImage, final int listId, final boolean onlySave) {
+ public HtmlImage(@NonNull final String geocode, final boolean returnErrorImage, final int listId, final boolean onlySave) {
this(geocode, returnErrorImage, listId, onlySave, null);
}
@@ -243,23 +253,23 @@ public class HtmlImage implements Html.ImageGetter {
}
if (onlySave) {
subscriber.onCompleted();
- } else {
- RxUtils.computationScheduler.createWorker().schedule(new Action0() {
- @Override
- public void call() {
- final ImmutablePair<BitmapDrawable, Boolean> loaded = loadFromDisk();
- final BitmapDrawable image = loaded.left;
- if (image != null) {
- subscriber.onNext(image);
- } else {
- subscriber.onNext(returnErrorImage ?
- new BitmapDrawable(resources, BitmapFactory.decodeResource(resources, R.drawable.image_not_loaded)) :
- ImageUtils.getTransparent1x1Drawable(resources));
- }
- subscriber.onCompleted();
- }
- });
+ return;
}
+ RxUtils.computationScheduler.createWorker().schedule(new Action0() {
+ @Override
+ public void call() {
+ final ImmutablePair<BitmapDrawable, Boolean> loaded = loadFromDisk();
+ final BitmapDrawable image = loaded.left;
+ if (image != null) {
+ subscriber.onNext(image);
+ } else {
+ subscriber.onNext(returnErrorImage ?
+ new BitmapDrawable(resources, BitmapFactory.decodeResource(resources, R.drawable.image_not_loaded)) :
+ ImageUtils.getTransparent1x1Drawable(resources));
+ }
+ subscriber.onCompleted();
+ }
+ });
}
});
}
@@ -338,7 +348,7 @@ public class HtmlImage implements Html.ImageGetter {
* @return A pair whose first element is the bitmap if available, and the second one is <code>true</code> if the image is present and fresh enough.
*/
@NonNull
- private ImmutablePair<Bitmap, Boolean> loadImageFromStorage(final String url, final String pseudoGeocode, final boolean forceKeep) {
+ private ImmutablePair<Bitmap, Boolean> loadImageFromStorage(final String url, @NonNull final String pseudoGeocode, final boolean forceKeep) {
try {
final File file = LocalStorage.getStorageFile(pseudoGeocode, url, true, false);
final ImmutablePair<Bitmap, Boolean> image = loadCachedImage(file, forceKeep);
@@ -390,7 +400,7 @@ public class HtmlImage implements Html.ImageGetter {
@NonNull
private ImmutablePair<Bitmap, Boolean> loadCachedImage(final File file, final boolean forceKeep) {
if (file.exists()) {
- final boolean freshEnough = listId >= StoredList.STANDARD_LIST_ID || file.lastModified() > (new Date().getTime() - (24 * 60 * 60 * 1000)) || forceKeep;
+ final boolean freshEnough = listId >= StoredList.STANDARD_LIST_ID || file.lastModified() > (System.currentTimeMillis() - (24 * 60 * 60 * 1000)) || forceKeep;
if (freshEnough && onlySave) {
return ImmutablePair.of((Bitmap) null, true);
}
diff --git a/main/src/cgeo/geocaching/network/OAuth.java b/main/src/cgeo/geocaching/network/OAuth.java
index c23ffbf..4f1fcc0 100644
--- a/main/src/cgeo/geocaching/network/OAuth.java
+++ b/main/src/cgeo/geocaching/network/OAuth.java
@@ -8,7 +8,6 @@ import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
public class OAuth {
@@ -24,7 +23,7 @@ public class OAuth {
"oauth_consumer_key", consumerKey,
"oauth_nonce", CryptUtils.md5(Long.toString(System.currentTimeMillis())),
"oauth_signature_method", "HMAC-SHA1",
- "oauth_timestamp", Long.toString(new Date().getTime() / 1000),
+ "oauth_timestamp", Long.toString(System.currentTimeMillis() / 1000),
"oauth_token", StringUtils.defaultString(tokens.getTokenPublic()),
"oauth_version", "1.0");
params.sort();
@@ -41,10 +40,7 @@ public class OAuth {
}
/**
- * percent encode following http://tools.ietf.org/html/rfc5849#section-3.6
- *
- * @param url
- * @return
+ * Percent encode following http://tools.ietf.org/html/rfc5849#section-3.6
*/
static String percentEncode(@NonNull final String url) {
return StringUtils.replace(Network.rfc3986URLEncode(url), "*", "%2A");
diff --git a/main/src/cgeo/geocaching/sensors/GeoData.java b/main/src/cgeo/geocaching/sensors/GeoData.java
index 880efd0..b8b16fd 100644
--- a/main/src/cgeo/geocaching/sensors/GeoData.java
+++ b/main/src/cgeo/geocaching/sensors/GeoData.java
@@ -91,7 +91,7 @@ public class GeoData extends Location {
final String homeLocationStr = Settings.getHomeLocation();
if (StringUtils.isNotBlank(homeLocationStr)) {
try {
- assert (homeLocationStr != null);
+ assert homeLocationStr != null;
final Geopoint homeLocation = new Geopoint(homeLocationStr);
Log.i("No last known location available, using home location");
final Location initialLocation = new Location(HOME_PROVIDER);
diff --git a/main/src/cgeo/geocaching/sensors/GeoDirHandler.java b/main/src/cgeo/geocaching/sensors/GeoDirHandler.java
index d043a4a..4743140 100644
--- a/main/src/cgeo/geocaching/sensors/GeoDirHandler.java
+++ b/main/src/cgeo/geocaching/sensors/GeoDirHandler.java
@@ -1,16 +1,11 @@
package cgeo.geocaching.sensors;
-import cgeo.geocaching.CgeoApplication;
-import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.utils.AngleUtils;
-
import org.apache.commons.lang3.tuple.ImmutablePair;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
-import rx.functions.Func1;
import rx.functions.Func2;
import rx.subscriptions.CompositeSubscription;
@@ -34,8 +29,6 @@ public abstract class GeoDirHandler {
public static final int UPDATE_GEODIR = 1 << 3;
public static final int LOW_POWER = 1 << 4;
- private static final CgeoApplication app = CgeoApplication.getInstance();
-
/**
* Update method called when new geodata is available. This method is called on the UI thread.
* {@link #start(int)} must be called with the {@link #UPDATE_GEODATA} flag set.
@@ -67,22 +60,6 @@ public abstract class GeoDirHandler {
public void updateGeoDir(final GeoData geoData, final float direction) {
}
- private static Observable<Float> fixedDirection() {
- return app.directionObservable().map(new Func1<Float, Float>() {
- @Override
- public Float call(final Float direction) {
- final GeoData geoData = app.currentGeo();
- return fixDirection(geoData, direction);
- }
- });
-
- }
-
- private static float fixDirection(final GeoData geoData, final float direction) {
- final boolean useGPSBearing = !Settings.isUseCompass() || geoData.getSpeed() > 5;
- return useGPSBearing ? AngleUtils.reverseDirectionNow(geoData.getBearing()) : direction;
- }
-
private static <T> Observable<T> throttleIfNeeded(final Observable<T> observable, final long windowDuration, final TimeUnit unit) {
return windowDuration > 0 ? observable.throttleFirst(windowDuration, unit) : observable;
}
@@ -108,8 +85,10 @@ public abstract class GeoDirHandler {
public Subscription start(final int flags, final long windowDuration, final TimeUnit unit) {
final CompositeSubscription subscriptions = new CompositeSubscription();
final boolean lowPower = (flags & LOW_POWER) != 0;
+ final Sensors sensors = Sensors.getInstance();
+
if ((flags & UPDATE_GEODATA) != 0) {
- subscriptions.add(throttleIfNeeded(app.geoDataObservable(lowPower), windowDuration, unit).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<GeoData>() {
+ subscriptions.add(throttleIfNeeded(sensors.geoDataObservable(lowPower), windowDuration, unit).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<GeoData>() {
@Override
public void call(final GeoData geoData) {
updateGeoData(geoData);
@@ -117,7 +96,7 @@ public abstract class GeoDirHandler {
}));
}
if ((flags & UPDATE_DIRECTION) != 0) {
- subscriptions.add(throttleIfNeeded(fixedDirection(), windowDuration, unit).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Float>() {
+ subscriptions.add(throttleIfNeeded(sensors.directionObservable(), windowDuration, unit).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Float>() {
@Override
public void call(final Float direction) {
updateDirection(direction);
@@ -126,10 +105,10 @@ public abstract class GeoDirHandler {
}
if ((flags & UPDATE_GEODIR) != 0) {
// combineOnLatest() does not implement backpressure handling, so we need to explicitely use a backpressure operator there.
- subscriptions.add(throttleIfNeeded(Observable.combineLatest(app.geoDataObservable(lowPower), app.directionObservable(), new Func2<GeoData, Float, ImmutablePair<GeoData, Float>>() {
+ subscriptions.add(throttleIfNeeded(Observable.combineLatest(sensors.geoDataObservable(lowPower), sensors.directionObservable(), new Func2<GeoData, Float, ImmutablePair<GeoData, Float>>() {
@Override
public ImmutablePair<GeoData, Float> call(final GeoData geoData, final Float direction) {
- return ImmutablePair.of(geoData, fixDirection(geoData, direction));
+ return ImmutablePair.of(geoData, direction);
}
}), windowDuration, unit).onBackpressureDrop().observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<ImmutablePair<GeoData, Float>>() {
@Override
diff --git a/main/src/cgeo/geocaching/sensors/Sensors.java b/main/src/cgeo/geocaching/sensors/Sensors.java
new file mode 100644
index 0000000..498ec0e
--- /dev/null
+++ b/main/src/cgeo/geocaching/sensors/Sensors.java
@@ -0,0 +1,160 @@
+package cgeo.geocaching.sensors;
+
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.playservices.LocationProvider;
+import cgeo.geocaching.sensors.GpsStatusProvider.Status;
+import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.utils.AngleUtils;
+import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RxUtils;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+import rx.Observable;
+import rx.functions.Action1;
+import rx.functions.Func1;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class Sensors {
+
+ private Observable<GeoData> geoDataObservable;
+ private Observable<GeoData> geoDataObservableLowPower;
+ private Observable<Float> directionObservable;
+ private Observable<Status> gpsStatusObservable;
+ @NonNull private volatile GeoData currentGeo = GeoData.DUMMY_LOCATION;
+ private volatile float currentDirection = 0.0f;
+ private volatile boolean hasValidLocation = false;
+ private final boolean hasMagneticFieldSensor;
+ private final CgeoApplication app = CgeoApplication.getInstance();
+
+ private static class InstanceHolder {
+ static final Sensors INSTANCE = new Sensors();
+ }
+
+ private final Action1<GeoData> rememberGeodataAction = new Action1<GeoData>() {
+ @Override
+ public void call(final GeoData geoData) {
+ currentGeo = geoData;
+ hasValidLocation = true;
+ }
+ };
+
+ private final Action1<Float> onNextrememberDirectionAction = new Action1<Float>() {
+ @Override
+ public void call(final Float direction) {
+ currentDirection = direction;
+ }
+ };
+
+ private Sensors() {
+ gpsStatusObservable = GpsStatusProvider.create(app).replay(1).refCount();
+ final SensorManager sensorManager = (SensorManager) app.getSystemService(Context.SENSOR_SERVICE);
+ hasMagneticFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null;
+ }
+
+ public static final Sensors getInstance() {
+ return InstanceHolder.INSTANCE;
+ }
+
+ public void setupGeoDataObservables(final boolean useGooglePlayServices, final boolean useLowPowerLocation) {
+ if (useGooglePlayServices) {
+ geoDataObservable = LocationProvider.getMostPrecise(app).doOnNext(rememberGeodataAction);
+ if (useLowPowerLocation) {
+ geoDataObservableLowPower = LocationProvider.getLowPower(app).doOnNext(rememberGeodataAction);
+ } else {
+ geoDataObservableLowPower = geoDataObservable;
+ }
+ } else {
+ geoDataObservable = RxUtils.rememberLast(GeoDataProvider.create(app).doOnNext(rememberGeodataAction), null);
+ geoDataObservableLowPower = geoDataObservable;
+ }
+ }
+
+ private static final Func1<GeoData, Float> GPS_TO_DIRECTION = new Func1<GeoData, Float>() {
+ @Override
+ public Float call(final GeoData geoData) {
+ return AngleUtils.reverseDirectionNow(geoData.getBearing());
+ }
+ };
+
+ public void setupDirectionObservable(final boolean useLowPower) {
+ // If we have no magnetic sensor, there is no point in trying to setup any, we will always get the direction from the GPS.
+ if (!hasMagneticFieldSensor) {
+ Log.i("No magnetic field sensor, using only the GPS for the orientation");
+ directionObservable = RxUtils.rememberLast(geoDataObservableLowPower.map(GPS_TO_DIRECTION).doOnNext(onNextrememberDirectionAction), 0f);
+ return;
+ }
+
+ // Combine the magnetic direction observable with the GPS when compass is disabled or speed is high enough.
+
+ final AtomicBoolean useDirectionFromGps = new AtomicBoolean(false);
+
+ final Observable<Float> magneticDirectionObservable = RotationProvider.create(app, useLowPower).onErrorResumeNext(new Func1<Throwable, Observable<? extends Float>>() {
+ @Override
+ public Observable<? extends Float> call(final Throwable throwable) {
+ return OrientationProvider.create(app);
+ }
+ }).onErrorResumeNext(new Func1<Throwable, Observable<? extends Float>>() {
+ @Override
+ public Observable<? extends Float> call(final Throwable throwable) {
+ Log.e("Device orientation will not be available as no suitable sensors were found, disabling compass");
+ Settings.setUseCompass(false);
+ return Observable.<Float>never().startWith(0.0f);
+ }
+ }).filter(new Func1<Float, Boolean>() {
+ @Override
+ public Boolean call(final Float aFloat) {
+ return Settings.isUseCompass() && !useDirectionFromGps.get();
+ }
+ });
+
+ final Observable<Float> directionFromGpsObservable = geoDataObservable(true).filter(new Func1<GeoData, Boolean>() {
+ @Override
+ public Boolean call(final GeoData geoData) {
+ final boolean useGps = geoData.getSpeed() > 5.0f;
+ useDirectionFromGps.set(useGps);
+ return useGps || !Settings.isUseCompass();
+ }
+ }).map(GPS_TO_DIRECTION);
+
+ directionObservable = RxUtils.rememberLast(Observable.merge(magneticDirectionObservable, directionFromGpsObservable).doOnNext(onNextrememberDirectionAction), 0f);
+ }
+
+ public Observable<GeoData> geoDataObservable(final boolean lowPower) {
+ return lowPower ? geoDataObservableLowPower : geoDataObservable;
+ }
+
+ public Observable<Float> directionObservable() {
+ return directionObservable;
+ }
+
+ public Observable<Status> gpsStatusObservable() {
+ if (gpsStatusObservable == null) {
+ gpsStatusObservable = GpsStatusProvider.create(app).share();
+ }
+ return gpsStatusObservable;
+ }
+
+ @NonNull
+ public GeoData currentGeo() {
+ return currentGeo;
+ }
+
+ public boolean hasValidLocation() {
+ return hasValidLocation;
+ }
+
+ public float currentDirection() {
+ return currentDirection;
+ }
+
+ public boolean hasMagneticFieldSensor() {
+ return hasMagneticFieldSensor;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java
index b678d3b..ad15d81 100644
--- a/main/src/cgeo/geocaching/settings/Settings.java
+++ b/main/src/cgeo/geocaching/settings/Settings.java
@@ -627,7 +627,7 @@ public class Settings {
}
public static boolean isMapTrail() {
- return getBoolean(R.string.pref_maptrail, true);
+ return getBoolean(R.string.pref_maptrail, false);
}
public static void setMapTrail(final boolean showTrail) {
@@ -808,6 +808,7 @@ public class Settings {
* @return The cache type used for filtering or ALL if no filter is active.
* Returns never null
*/
+ @NonNull
public static CacheType getCacheType() {
return CacheType.getById(getString(R.string.pref_cachetype, CacheType.ALL.id));
}
diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java
index 662ba33..99de30f 100644
--- a/main/src/cgeo/geocaching/settings/SettingsActivity.java
+++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java
@@ -12,6 +12,7 @@ import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.files.SimpleDirChooser;
import cgeo.geocaching.maps.MapProviderFactory;
import cgeo.geocaching.maps.interfaces.MapSource;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.utils.DatabaseBackupUtils;
import cgeo.geocaching.utils.DebugUtils;
import cgeo.geocaching.utils.Log;
@@ -421,11 +422,12 @@ public class SettingsActivity extends PreferenceActivity {
}
private void initGeoDirPreferences() {
+ final Sensors sensors = Sensors.getInstance();
final Preference playServices = getPreference(R.string.pref_googleplayservices);
playServices.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(final Preference preference, final Object newValue) {
- CgeoApplication.getInstance().setupGeoDataObservables((Boolean) newValue, Settings.useLowPowerMode());
+ sensors.setupGeoDataObservables((Boolean) newValue, Settings.useLowPowerMode());
return true;
}
});
@@ -433,10 +435,9 @@ public class SettingsActivity extends PreferenceActivity {
getPreference(R.string.pref_lowpowermode).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(final Preference preference, final Object newValue) {
- final CgeoApplication app = CgeoApplication.getInstance();
final Boolean useLowPower = (Boolean) newValue;
- app.setupGeoDataObservables(Settings.useGooglePlayServices(), useLowPower);
- app.setupDirectionObservable(useLowPower);
+ sensors.setupGeoDataObservables(Settings.useGooglePlayServices(), useLowPower);
+ sensors.setupDirectionObservable(useLowPower);
return true;
}
});
diff --git a/main/src/cgeo/geocaching/sorting/DateComparator.java b/main/src/cgeo/geocaching/sorting/DateComparator.java
index 6d294db..af50213 100644
--- a/main/src/cgeo/geocaching/sorting/DateComparator.java
+++ b/main/src/cgeo/geocaching/sorting/DateComparator.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.sensors.Sensors;
import java.util.ArrayList;
import java.util.Date;
@@ -22,7 +22,7 @@ class DateComparator extends AbstractCacheComparator {
final ArrayList<Geocache> list = new ArrayList<>();
list.add(cache1);
list.add(cache2);
- final DistanceComparator distanceComparator = new DistanceComparator(CgeoApplication.getInstance().currentGeo().getCoords(), list);
+ final DistanceComparator distanceComparator = new DistanceComparator(Sensors.getInstance().currentGeo().getCoords(), list);
return distanceComparator.compare(cache1, cache2);
}
return dateDifference;
diff --git a/main/src/cgeo/geocaching/sorting/SizeComparator.java b/main/src/cgeo/geocaching/sorting/SizeComparator.java
index 9e911f5..8cb5178 100644
--- a/main/src/cgeo/geocaching/sorting/SizeComparator.java
+++ b/main/src/cgeo/geocaching/sorting/SizeComparator.java
@@ -9,11 +9,6 @@ import cgeo.geocaching.Geocache;
class SizeComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final Geocache cache) {
- return cache.getSize() != null;
- }
-
- @Override
protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return cache2.getSize().comparable - cache1.getSize().comparable;
}
diff --git a/main/src/cgeo/geocaching/ui/AddressListAdapter.java b/main/src/cgeo/geocaching/ui/AddressListAdapter.java
index 691c8d2..901bffc 100644
--- a/main/src/cgeo/geocaching/ui/AddressListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/AddressListAdapter.java
@@ -3,12 +3,13 @@ package cgeo.geocaching.ui;
import butterknife.InjectView;
import cgeo.geocaching.CacheListActivity;
-import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.location.Units;
+import cgeo.geocaching.sensors.Sensors;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
import android.app.Activity;
import android.location.Address;
@@ -23,7 +24,7 @@ import java.util.ArrayList;
public class AddressListAdapter extends ArrayAdapter<Address> {
final private LayoutInflater inflater;
- final private Geopoint location;
+ @NonNull final private Geopoint location;
protected static final class ViewHolder extends AbstractViewHolder {
@InjectView(R.id.label) protected TextView label;
@@ -37,7 +38,7 @@ public class AddressListAdapter extends ArrayAdapter<Address> {
public AddressListAdapter(final Activity context) {
super(context, 0);
inflater = context.getLayoutInflater();
- location = CgeoApplication.getInstance().currentGeo().getCoords();
+ location = Sensors.getInstance().currentGeo().getCoords();
}
@Override
@@ -72,7 +73,7 @@ public class AddressListAdapter extends ArrayAdapter<Address> {
}
private CharSequence getDistanceText(final Address address) {
- if (location != null && address.hasLatitude() && address.hasLongitude()) {
+ if (address.hasLatitude() && address.hasLongitude()) {
return Units.getDistanceFromKilometers(location.distanceTo(new Geopoint(address.getLatitude(), address.getLongitude())));
}
diff --git a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
index 13887c0..e2af419 100644
--- a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
+++ b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
@@ -2,13 +2,13 @@ package cgeo.geocaching.ui;
import butterknife.ButterKnife;
-import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.ICoordinates;
import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.location.Units;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.utils.Formatter;
import org.apache.commons.lang3.StringUtils;
@@ -18,11 +18,9 @@ import org.eclipse.jdt.annotation.NonNull;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.Resources;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
+import android.widget.RatingBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -74,33 +72,18 @@ public final class CacheDetailsCreator {
final RelativeLayout layout = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.cache_information_item, null, false);
final TextView nameView = ButterKnife.findById(layout, R.id.name);
lastValueView = ButterKnife.findById(layout, R.id.value);
- final LinearLayout layoutStars = ButterKnife.findById(layout, R.id.stars);
nameView.setText(activity.getResources().getString(nameId));
lastValueView.setText(String.format("%.1f", value) + ' ' + activity.getResources().getString(R.string.cache_rating_of) + " " + String.format("%d", max));
- createStarImages(layoutStars, value, max);
+
+ final RatingBar layoutStars = ButterKnife.findById(layout, R.id.stars);
+ layoutStars.setRating(value);
layoutStars.setVisibility(View.VISIBLE);
parentView.addView(layout);
return layout;
}
- private void createStarImages(final ViewGroup starsContainer, final float value, final int max) {
- final LayoutInflater inflater = LayoutInflater.from(activity);
-
- for (int i = 0; i < max; i++) {
- final ImageView star = (ImageView) inflater.inflate(R.layout.star_image, starsContainer, false);
- if (value - i >= 0.75) {
- star.setImageResource(R.drawable.star_on);
- } else if (value - i >= 0.25) {
- star.setImageResource(R.drawable.star_half);
- } else {
- star.setImageResource(R.drawable.star_off);
- }
- starsContainer.addView(star);
- }
- }
-
public void addCacheState(final Geocache cache) {
if (cache.isLogOffline() || cache.isArchived() || cache.isDisabled() || cache.isPremiumMembersOnly() || cache.isFound()) {
final List<String> states = new ArrayList<>(5);
@@ -135,7 +118,7 @@ public final class CacheDetailsCreator {
if (target.getCoords() == null) {
return null;
}
- return CgeoApplication.getInstance().currentGeo().getCoords().distanceTo(target);
+ return Sensors.getInstance().currentGeo().getCoords().distanceTo(target);
}
public void addRating(final Geocache cache) {
@@ -150,7 +133,7 @@ public final class CacheDetailsCreator {
}
public void addSize(final Geocache cache) {
- if (null != cache.getSize() && cache.showSize()) {
+ if (cache.showSize()) {
add(R.string.cache_size, cache.getSize().getL10n());
}
}
diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
index f080761..34cac01 100644
--- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
@@ -3,7 +3,6 @@ package cgeo.geocaching.ui;
import butterknife.InjectView;
import cgeo.geocaching.CacheDetailActivity;
-import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.enumerations.CacheListType;
@@ -11,6 +10,7 @@ import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.filter.IFilter;
import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.sensors.GeoData;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.sorting.CacheComparator;
import cgeo.geocaching.sorting.DistanceComparator;
@@ -119,7 +119,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
public CacheListAdapter(final Activity activity, final List<Geocache> list, final CacheListType cacheListType) {
super(activity, 0, list);
- final GeoData currentGeo = CgeoApplication.getInstance().currentGeo();
+ final GeoData currentGeo = Sensors.getInstance().currentGeo();
coords = currentGeo.getCoords();
this.res = activity.getResources();
this.list = list;
diff --git a/main/src/cgeo/geocaching/ui/ImagesList.java b/main/src/cgeo/geocaching/ui/ImagesList.java
index 458f8db..32e29bb 100644
--- a/main/src/cgeo/geocaching/ui/ImagesList.java
+++ b/main/src/cgeo/geocaching/ui/ImagesList.java
@@ -106,7 +106,7 @@ public class ImagesList {
for (final Image img : images) {
final LinearLayout rowView = (LinearLayout) inflater.inflate(R.layout.cache_image_item, imagesView, false);
- assert(rowView != null);
+ assert rowView != null;
if (StringUtils.isNotBlank(img.getTitle())) {
final TextView titleView = ButterKnife.findById(rowView, R.id.title);
@@ -121,7 +121,7 @@ public class ImagesList {
}
final ImageView imageView = (ImageView) inflater.inflate(R.layout.image_item, rowView, false);
- assert(imageView != null);
+ assert imageView != null;
subscriptions.add(AndroidObservable.bindActivity(activity, imgGetter.fetchDrawable(img.getUrl())).subscribe(new Action1<BitmapDrawable>() {
@Override
public void call(final BitmapDrawable image) {
diff --git a/main/src/cgeo/geocaching/ui/WrappingGridView.java b/main/src/cgeo/geocaching/ui/WrappingGridView.java
new file mode 100644
index 0000000..2c85887
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/WrappingGridView.java
@@ -0,0 +1,38 @@
+package cgeo.geocaching.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.GridView;
+
+/**
+ * GridView that will adjust its height to really use wrap_content. The standard GridView only shows one line of items.
+ *
+ * @see <a href="https://gist.github.com/runemart/9781609">https://gist.github.com/runemart/9781609</a>
+ *
+ */
+public class WrappingGridView extends GridView {
+
+ public WrappingGridView(final Context context) {
+ super(context);
+ }
+
+ public WrappingGridView(final Context context, final AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public WrappingGridView(final Context context, final AttributeSet attrs, final int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+ int heightSpec = heightMeasureSpec;
+ if (getLayoutParams().height == android.view.ViewGroup.LayoutParams.WRAP_CONTENT) {
+ // The two leftmost bits in the height measure spec have
+ // a special meaning, hence we can't use them to describe height.
+ heightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
+ }
+ super.onMeasure(widthMeasureSpec, heightSpec);
+ }
+
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/utils/CryptUtils.java b/main/src/cgeo/geocaching/utils/CryptUtils.java
index f2ff0c2..70d5895 100644
--- a/main/src/cgeo/geocaching/utils/CryptUtils.java
+++ b/main/src/cgeo/geocaching/utils/CryptUtils.java
@@ -23,8 +23,8 @@ public final class CryptUtils {
}
private static final byte[] EMPTY = {};
- private static char[] BASE64MAP1 = new char[64];
- private static byte[] BASE64MAP2 = new byte[128];
+ private static final char[] BASE64MAP1 = new char[64];
+ private static final byte[] BASE64MAP2 = new byte[128];
static {
int i = 0;
diff --git a/main/src/cgeo/geocaching/utils/Log.java b/main/src/cgeo/geocaching/utils/Log.java
index f338a8e..2f51e42 100644
--- a/main/src/cgeo/geocaching/utils/Log.java
+++ b/main/src/cgeo/geocaching/utils/Log.java
@@ -43,56 +43,60 @@ public final class Log {
Log.isDebug = isDebug;
}
+ private static String addThreadInfo(final String msg) {
+ return new StringBuilder("[").append(Thread.currentThread().getName()).append("] ").append(msg).toString();
+ }
+
public static void v(final String msg) {
if (isDebug) {
- android.util.Log.v(TAG, msg);
+ android.util.Log.v(TAG, addThreadInfo(msg));
}
}
public static void v(final String msg, final Throwable t) {
if (isDebug) {
- android.util.Log.v(TAG, msg, t);
+ android.util.Log.v(TAG, addThreadInfo(msg), t);
}
}
public static void d(final String msg) {
if (isDebug) {
- android.util.Log.d(TAG, msg);
+ android.util.Log.d(TAG, addThreadInfo(msg));
}
}
public static void d(final String msg, final Throwable t) {
if (isDebug) {
- android.util.Log.d(TAG, msg, t);
+ android.util.Log.d(TAG, addThreadInfo(msg), t);
}
}
public static void i(final String msg) {
if (isDebug) {
- android.util.Log.i(TAG, msg);
+ android.util.Log.i(TAG, addThreadInfo(msg));
}
}
public static void i(final String msg, final Throwable t) {
if (isDebug) {
- android.util.Log.i(TAG, msg, t);
+ android.util.Log.i(TAG, addThreadInfo(msg), t);
}
}
public static void w(final String msg) {
- android.util.Log.w(TAG, msg);
+ android.util.Log.w(TAG, addThreadInfo(msg));
}
public static void w(final String msg, final Throwable t) {
- android.util.Log.w(TAG, msg, t);
+ android.util.Log.w(TAG, addThreadInfo(msg), t);
}
public static void e(final String msg) {
- android.util.Log.e(TAG, msg);
+ android.util.Log.e(TAG, addThreadInfo(msg));
}
public static void e(final String msg, final Throwable t) {
- android.util.Log.e(TAG, msg, t);
+ android.util.Log.e(TAG, addThreadInfo(msg), t);
}
/**
@@ -116,7 +120,7 @@ public final class Log {
Writer writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), CharEncoding.UTF_8));
- writer.write(msg);
+ writer.write(addThreadInfo(msg));
} catch (final IOException e) {
Log.e("logToFile: cannot write to " + file, e);
} finally {
diff --git a/main/src/cgeo/geocaching/utils/RxUtils.java b/main/src/cgeo/geocaching/utils/RxUtils.java
index beb5e18..af58214 100644
--- a/main/src/cgeo/geocaching/utils/RxUtils.java
+++ b/main/src/cgeo/geocaching/utils/RxUtils.java
@@ -11,6 +11,7 @@ import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func0;
import rx.functions.Func1;
+import rx.internal.util.RxThreadFactory;
import rx.observables.BlockingObservable;
import rx.observers.Subscribers;
import rx.schedulers.Schedulers;
@@ -25,8 +26,7 @@ import android.os.Process;
import java.util.HashMap;
import java.util.Map;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -39,12 +39,12 @@ public class RxUtils {
public final static Scheduler computationScheduler = Schedulers.computation();
- public static final Scheduler networkScheduler = Schedulers.from(new ThreadPoolExecutor(10, 10, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()));
+ public static final Scheduler networkScheduler = Schedulers.from(Executors.newFixedThreadPool(10, new RxThreadFactory("network-")));
- public static final Scheduler refreshScheduler = Schedulers.from(new ThreadPoolExecutor(3, 3, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()));
+ public static final Scheduler refreshScheduler = Schedulers.from(Executors.newFixedThreadPool(3, new RxThreadFactory("refresh-")));
private static final HandlerThread looperCallbacksThread =
- new HandlerThread("Looper callbacks thread", Process.THREAD_PRIORITY_DEFAULT);
+ new HandlerThread("looper callbacks", Process.THREAD_PRIORITY_DEFAULT);
static {
looperCallbacksThread.start();
@@ -158,8 +158,8 @@ public class RxUtils {
};
}
- public static<T> Observable<T> rememberLast(final Observable<T> observable) {
- final AtomicReference<T> lastValue = new AtomicReference<>(null);
+ 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>() {
@Override
public void call(final T value) {
@@ -224,7 +224,7 @@ public class RxUtils {
if (cached.containsKey(key)) {
return cached.get(key);
}
- final Observable<V> value = func.call(key).replay().refCount();
+ final Observable<V> value = func.call(key).share();
cached.put(key, value);
return value;
}