aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching')
-rw-r--r--main/src/cgeo/geocaching/AbstractLoggingActivity.java7
-rw-r--r--main/src/cgeo/geocaching/AbstractPopupActivity.java8
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java417
-rw-r--r--main/src/cgeo/geocaching/CompassActivity.java13
-rw-r--r--main/src/cgeo/geocaching/DirectionProvider.java2
-rw-r--r--main/src/cgeo/geocaching/EditWaypointActivity.java4
-rw-r--r--main/src/cgeo/geocaching/Geocache.java71
-rw-r--r--main/src/cgeo/geocaching/ImageSelectActivity.java6
-rw-r--r--main/src/cgeo/geocaching/LogCacheActivity.java22
-rw-r--r--main/src/cgeo/geocaching/MainActivity.java95
-rw-r--r--main/src/cgeo/geocaching/SearchActivity.java21
-rw-r--r--main/src/cgeo/geocaching/StatusFragment.java2
-rw-r--r--main/src/cgeo/geocaching/StoredList.java6
-rw-r--r--main/src/cgeo/geocaching/Trackable.java23
-rw-r--r--main/src/cgeo/geocaching/TrackableActivity.java237
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java13
-rw-r--r--main/src/cgeo/geocaching/apps/AbstractApp.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java14
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java33
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java8
-rw-r--r--main/src/cgeo/geocaching/cgData.java18
-rw-r--r--main/src/cgeo/geocaching/cgeocaches.java112
-rw-r--r--main/src/cgeo/geocaching/connector/ConnectorFactory.java69
-rw-r--r--main/src/cgeo/geocaching/connector/ILoggingManager.java13
-rw-r--r--main/src/cgeo/geocaching/connector/NoLoggingManager.java2
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ILogin.java57
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java58
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConstants.java9
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java4
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java272
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Login.java76
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java34
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java120
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java6
-rw-r--r--main/src/cgeo/geocaching/connector/oc/UserInfo.java41
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java10
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java42
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java82
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java19
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java50
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java24
-rw-r--r--main/src/cgeo/geocaching/export/FieldnoteExport.java28
-rw-r--r--main/src/cgeo/geocaching/export/GpxExport.java238
-rw-r--r--main/src/cgeo/geocaching/export/GpxSerializer.java255
-rw-r--r--main/src/cgeo/geocaching/files/GPXImporter.java63
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java40
-rw-r--r--main/src/cgeo/geocaching/network/HtmlImage.java4
-rw-r--r--main/src/cgeo/geocaching/network/Network.java8
-rw-r--r--main/src/cgeo/geocaching/network/StatusUpdater.java9
-rw-r--r--main/src/cgeo/geocaching/speech/SpeechService.java5
-rw-r--r--main/src/cgeo/geocaching/speech/TextFactory.java78
-rw-r--r--main/src/cgeo/geocaching/ui/AbstractUserClickListener.java76
-rw-r--r--main/src/cgeo/geocaching/ui/CompassView.java44
-rw-r--r--main/src/cgeo/geocaching/ui/HtmlImageCounter.java19
-rw-r--r--main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java31
-rw-r--r--main/src/cgeo/geocaching/ui/UserActionsClickListener.java26
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java42
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/DateDialog.java12
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/NoTitleDialog.java30
-rw-r--r--main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java101
-rw-r--r--main/src/cgeo/geocaching/ui/logs/LogViewHolder.java (renamed from main/src/cgeo/geocaching/LogViewHolder.java)3
-rw-r--r--main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java175
-rw-r--r--main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java70
-rw-r--r--main/src/cgeo/geocaching/utils/AngleUtils.java4
-rw-r--r--main/src/cgeo/geocaching/utils/ClipboardUtils.java4
-rw-r--r--main/src/cgeo/geocaching/utils/CryptUtils.java4
-rw-r--r--main/src/cgeo/geocaching/utils/DateUtils.java7
-rw-r--r--main/src/cgeo/geocaching/utils/EditUtils.java4
-rw-r--r--main/src/cgeo/geocaching/utils/FileUtils.java8
-rw-r--r--main/src/cgeo/geocaching/utils/HtmlUtils.java6
-rw-r--r--main/src/cgeo/geocaching/utils/ImageUtils.java (renamed from main/src/cgeo/geocaching/utils/ImageHelper.java)6
-rw-r--r--main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java6
-rw-r--r--main/src/cgeo/geocaching/utils/LogTemplateProvider.java2
-rw-r--r--main/src/cgeo/geocaching/utils/ProcessUtils.java47
-rw-r--r--main/src/cgeo/geocaching/utils/TextUtils.java (renamed from main/src/cgeo/geocaching/utils/BaseUtils.java)10
-rw-r--r--main/src/cgeo/geocaching/utils/TranslationUtils.java6
-rw-r--r--main/src/cgeo/geocaching/utils/XmlUtils.java2
77 files changed, 2128 insertions, 1469 deletions
diff --git a/main/src/cgeo/geocaching/AbstractLoggingActivity.java b/main/src/cgeo/geocaching/AbstractLoggingActivity.java
index 78da757..1524834 100644
--- a/main/src/cgeo/geocaching/AbstractLoggingActivity.java
+++ b/main/src/cgeo/geocaching/AbstractLoggingActivity.java
@@ -5,6 +5,7 @@ import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.connector.gc.GCSmiliesProvider;
import cgeo.geocaching.connector.gc.GCSmiliesProvider.Smiley;
+import cgeo.geocaching.connector.trackable.TravelBugConnector;
import cgeo.geocaching.utils.LogTemplateProvider;
import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate;
@@ -23,12 +24,12 @@ public abstract class AbstractLoggingActivity extends AbstractActivity {
getMenuInflater().inflate(R.menu.abstract_logging_activity, menu);
final SubMenu menuLog = menu.findItem(R.id.menu_templates).getSubMenu();
- for (LogTemplate template : LogTemplateProvider.getTemplates()) {
+ for (final LogTemplate template : LogTemplateProvider.getTemplates()) {
menuLog.add(0, template.getItemId(), 0, template.getResourceId());
}
final SubMenu menuSmilies = menu.findItem(R.id.menu_smilies).getSubMenu();
- for (Smiley smiley : GCSmiliesProvider.getSmilies()) {
+ for (final Smiley smiley : GCSmiliesProvider.getSmilies()) {
menuSmilies.add(0, smiley.getItemId(), 0, smiley.text);
}
@@ -46,7 +47,7 @@ public abstract class AbstractLoggingActivity extends AbstractActivity {
smileyVisible = true;
}
final Trackable trackable = getLogContext().getTrackable();
- if (trackable != null && ConnectorFactory.getConnector(trackable).equals(GCConnector.getInstance())) {
+ if (trackable != null && ConnectorFactory.getConnector(trackable).equals(TravelBugConnector.getInstance())) {
smileyVisible = true;
}
diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java
index 73dc86d..64e5539 100644
--- a/main/src/cgeo/geocaching/AbstractPopupActivity.java
+++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java
@@ -2,6 +2,7 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.gcvote.GCVote;
@@ -46,7 +47,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
public void handleMessage(Message msg) {
try {
details.addRating(cache);
- } catch (Exception e) {
+ } catch (final Exception e) {
// nothing
}
}
@@ -62,7 +63,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
cacheDistance.bringToFront();
}
onUpdateGeoData(geo);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("Failed to UpdateLocation location.");
}
}
@@ -205,8 +206,9 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
menu.findItem(R.id.menu_navigate).setVisible(visible);
menu.findItem(R.id.menu_caches_around).setVisible(visible);
+ menu.findItem(R.id.menu_default_navigation).setTitle(NavigationAppFactory.getDefaultNavigationApplication().getName());
LoggingUI.onPrepareOptionsMenu(menu, cache);
- } catch (Exception e) {
+ } catch (final Exception e) {
// nothing
}
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index 7acb4ae..6ec034d 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -14,7 +14,6 @@ import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.enumerations.CacheAttribute;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
-import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.geopoint.Units;
@@ -29,19 +28,22 @@ import cgeo.geocaching.ui.DecryptTextClickListener;
import cgeo.geocaching.ui.EditNoteDialog;
import cgeo.geocaching.ui.EditNoteDialog.EditNoteDialogListener;
import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.ui.HtmlImageCounter;
import cgeo.geocaching.ui.ImagesList;
import cgeo.geocaching.ui.LoggingUI;
+import cgeo.geocaching.ui.OwnerActionsClickListener;
import cgeo.geocaching.ui.WeakReferenceHandler;
-import cgeo.geocaching.utils.BaseUtils;
+import cgeo.geocaching.ui.logs.CacheLogsViewCreator;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.ClipboardUtils;
import cgeo.geocaching.utils.CryptUtils;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.HtmlUtils;
-import cgeo.geocaching.utils.ImageHelper;
+import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
import cgeo.geocaching.utils.RunnableWithArgument;
+import cgeo.geocaching.utils.TextUtils;
import cgeo.geocaching.utils.TranslationUtils;
import cgeo.geocaching.utils.UnknownTagsHandler;
@@ -103,12 +105,9 @@ import android.widget.TextView.BufferType;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
import java.util.regex.Pattern;
/**
@@ -175,7 +174,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
cacheDistanceView.setText(dist.toString());
cacheDistanceView.bringToFront();
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("Failed to update location.");
}
}
@@ -192,7 +191,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// some views that must be available from everywhere // TODO: Reference can block GC?
private TextView cacheDistanceView;
- private Handler cacheChangeNotificationHandler = new Handler() {
+ private final Handler cacheChangeNotificationHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
notifyDataSetChanged();
@@ -232,9 +231,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// try to get data from URI
if (geocode == null && guid == null && uri != null) {
- String uriHost = uri.getHost().toLowerCase(Locale.US);
- String uriPath = uri.getPath().toLowerCase(Locale.US);
- String uriQuery = uri.getQuery();
+ final String uriHost = uri.getHost().toLowerCase(Locale.US);
+ final String uriPath = uri.getPath().toLowerCase(Locale.US);
+ final String uriQuery = uri.getQuery();
if (uriQuery != null) {
Log.i("Opening URI: " + uriHost + uriPath + "?" + uriQuery);
@@ -302,11 +301,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
title = geocode;
}
progress.show(this, title, res.getString(R.string.cache_dialog_loading_details), true, loadCacheHandler.cancelMessage());
- } catch (Exception e) {
+ } catch (final Exception e) {
// nothing, we lost the window
}
- ImageView defaultNavigationImageView = (ImageView) findViewById(R.id.defaultNavigation);
+ final ImageView defaultNavigationImageView = (ImageView) findViewById(R.id.defaultNavigation);
defaultNavigationImageView.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
@@ -375,7 +374,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
switch (viewId) {
case R.id.value: // coordinates, gc-code, name
clickedItemText = ((TextView) view).getText();
- String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText();
+ final String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText();
buildOptionsContextmenu(menu, viewId, itemTitle, true);
break;
case R.id.shortdesc:
@@ -384,7 +383,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
break;
case R.id.longdesc:
// combine short and long description
- String shortDesc = cache.getShortDescription();
+ final String shortDesc = cache.getShortDescription();
if (StringUtils.isBlank(shortDesc)) {
clickedItemText = ((TextView) view).getText();
} else {
@@ -433,7 +432,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
break;
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
}
}
break;
@@ -579,8 +578,8 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
menu.findItem(MENU_CALENDAR).setVisible(cache.canBeAddedToCalendar());
menu.findItem(MENU_CACHES_AROUND).setVisible(null != cache.getCoords() && cache.supportsCachesAround());
menu.findItem(MENU_BROWSER).setVisible(cache.canOpenInBrowser());
+ LoggingUI.onPrepareOptionsMenu(menu, cache);
}
- LoggingUI.onPrepareOptionsMenu(menu, cache);
return super.onPrepareOptionsMenu(menu);
}
@@ -788,7 +787,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
.setPositiveButton(getString(android.R.string.yes), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
- Intent intent = new Intent(Intent.ACTION_VIEW);
+ final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(ICalendar.CALENDAR_ADDON_URI));
startActivity(intent);
}
@@ -832,95 +831,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
NavigationAppFactory.showNavigationMenu(this, cache, null, null, true, true);
}
- /**
- * Listener for clicks on username
- */
- private class UserActionsClickListener implements View.OnClickListener {
-
- @Override
- public void onClick(View view) {
- if (view == null) {
- return;
- }
- if (!cache.supportsUserActions()) {
- return;
- }
-
- clickedItemText = ((TextView) view).getText().toString();
- showUserActionsDialog(clickedItemText);
- }
- }
-
- /**
- * Listener for clicks on owner name
- */
- private class OwnerActionsClickListener implements View.OnClickListener {
-
- @Override
- public void onClick(View view) {
- if (view == null) {
- return;
- }
- if (!cache.supportsUserActions()) {
- return;
- }
-
- // Use real owner name vice the one owner chose to display
- if (StringUtils.isNotBlank(cache.getOwnerUserId())) {
- clickedItemText = cache.getOwnerUserId();
- } else {
- clickedItemText = ((TextView) view).getText().toString();
- }
- showUserActionsDialog(clickedItemText);
- }
- }
-
- /**
- * Opens a dialog to do actions on an username
- */
- private void showUserActionsDialog(final CharSequence name) {
- final CharSequence[] items = { res.getString(R.string.user_menu_view_hidden),
- res.getString(R.string.user_menu_view_found),
- res.getString(R.string.user_menu_open_browser),
- res.getString(R.string.user_menu_send_message)
- };
-
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(res.getString(R.string.user_menu_title) + " " + name);
- builder.setItems(items, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int item) {
- switch (item) {
- case 0:
- cgeocaches.startActivityOwner(CacheDetailActivity.this, name.toString());
- return;
- case 1:
- cgeocaches.startActivityUserName(CacheDetailActivity.this, name.toString());
- return;
- case 2:
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(name.toString()))));
- return;
- case 3:
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/email/?u=" + Network.encode(name.toString()))));
- return;
- default:
- break;
- }
- }
- });
- AlertDialog alert = builder.create();
- alert.show();
- }
-
private void loadCacheImages() {
if (imagesList != null) {
return;
}
- PageViewCreator creator = getViewCreator(Page.IMAGES);
+ final PageViewCreator creator = getViewCreator(Page.IMAGES);
if (creator == null) {
return;
}
- View imageView = creator.getView();
+ final View imageView = creator.getView();
if (imageView == null) {
return;
}
@@ -1062,12 +981,12 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
noAttributeIconsFound = true;
- for (String attributeName : cache.getAttributes()) {
+ for (final String attributeName : cache.getAttributes()) {
// check if another attribute icon fits in this row
attributeRow.measure(0, 0);
- int rowWidth = attributeRow.getMeasuredWidth();
- FrameLayout fl = (FrameLayout) getLayoutInflater().inflate(R.layout.attribute_image, null);
- ImageView iv = (ImageView) fl.getChildAt(0);
+ final int rowWidth = attributeRow.getMeasuredWidth();
+ final FrameLayout fl = (FrameLayout) getLayoutInflater().inflate(R.layout.attribute_image, null);
+ final ImageView iv = (ImageView) fl.getChildAt(0);
if ((parentWidth - rowWidth) < iv.getLayoutParams().width) {
// make a new row
attributeRow = newAttributeIconsRow();
@@ -1083,14 +1002,14 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// strike through?
if (strikethru) {
// generate strikethru image with same properties as attribute image
- ImageView strikethruImage = new ImageView(CacheDetailActivity.this);
+ final ImageView strikethruImage = new ImageView(CacheDetailActivity.this);
strikethruImage.setLayoutParams(iv.getLayoutParams());
d = res.getDrawable(R.drawable.attribute__strikethru);
strikethruImage.setImageDrawable(d);
fl.addView(strikethruImage);
}
} else {
- Drawable d = res.getDrawable(R.drawable.attribute_unknown);
+ final Drawable d = res.getDrawable(R.drawable.attribute_unknown);
iv.setImageDrawable(d);
}
@@ -1101,7 +1020,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
private LinearLayout newAttributeIconsRow() {
- LinearLayout rowLayout = new LinearLayout(CacheDetailActivity.this);
+ final LinearLayout rowLayout = new LinearLayout(CacheDetailActivity.this);
rowLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
rowLayout.setOrientation(LinearLayout.HORIZONTAL);
@@ -1166,7 +1085,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final CacheDetailsCreator details = new CacheDetailsCreator(CacheDetailActivity.this, detailsList);
// cache name (full name)
- Spannable span = (new Spannable.Factory()).newSpannable(Html.fromHtml(cache.getName()).toString());
+ final Spannable span = (new Spannable.Factory()).newSpannable(Html.fromHtml(cache.getName()).toString());
if (cache.isDisabled() || cache.isArchived()) { // strike
span.setSpan(new StrikethroughSpan(), 0, span.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
@@ -1199,18 +1118,18 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// cache author
if (StringUtils.isNotBlank(cache.getOwnerDisplayName()) || StringUtils.isNotBlank(cache.getOwnerUserId())) {
- TextView ownerView = details.add(R.string.cache_owner, "");
+ final TextView ownerView = details.add(R.string.cache_owner, "");
if (StringUtils.isNotBlank(cache.getOwnerDisplayName())) {
ownerView.setText(cache.getOwnerDisplayName(), TextView.BufferType.SPANNABLE);
} else { // OwnerReal guaranteed to be not blank based on above
ownerView.setText(cache.getOwnerUserId(), TextView.BufferType.SPANNABLE);
}
- ownerView.setOnClickListener(new OwnerActionsClickListener());
+ ownerView.setOnClickListener(new OwnerActionsClickListener(cache));
}
// cache hidden
if (cache.getHiddenDate() != null) {
- long time = cache.getHiddenDate().getTime();
+ final long time = cache.getHiddenDate().getTime();
if (time > 0) {
String dateString = Formatter.formatFullDate(time);
if (cache.isEventCache()) {
@@ -1227,7 +1146,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// cache coordinates
if (cache.getCoords() != null) {
- TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString());
+ final TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString());
valueView.setOnClickListener(new CoordinatesFormatSwitcher(cache.getCoords()));
registerForContextMenu(valueView);
}
@@ -1241,31 +1160,31 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
updateOfflineBox(view, cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener());
// watchlist
- Button buttonWatchlistAdd = (Button) view.findViewById(R.id.add_to_watchlist);
- Button buttonWatchlistRemove = (Button) view.findViewById(R.id.remove_from_watchlist);
+ final Button buttonWatchlistAdd = (Button) view.findViewById(R.id.add_to_watchlist);
+ final Button buttonWatchlistRemove = (Button) view.findViewById(R.id.remove_from_watchlist);
buttonWatchlistAdd.setOnClickListener(new AddToWatchlistClickListener());
buttonWatchlistRemove.setOnClickListener(new RemoveFromWatchlistClickListener());
updateWatchlistBox();
// favorite points
- Button buttonFavPointAdd = (Button) view.findViewById(R.id.add_to_favpoint);
- Button buttonFavPointRemove = (Button) view.findViewById(R.id.remove_from_favpoint);
+ final Button buttonFavPointAdd = (Button) view.findViewById(R.id.add_to_favpoint);
+ final Button buttonFavPointRemove = (Button) view.findViewById(R.id.remove_from_favpoint);
buttonFavPointAdd.setOnClickListener(new FavoriteAddClickListener());
buttonFavPointRemove.setOnClickListener(new FavoriteRemoveClickListener());
updateFavPointBox();
// list
- Button buttonChangeList = (Button) view.findViewById(R.id.change_list);
+ final Button buttonChangeList = (Button) view.findViewById(R.id.change_list);
buttonChangeList.setOnClickListener(new ChangeListClickListener());
updateListBox();
// data license
- IConnector connector = ConnectorFactory.getConnector(cache);
+ final IConnector connector = ConnectorFactory.getConnector(cache);
if (connector != null) {
- String license = connector.getLicenseText(cache);
+ final String license = connector.getLicenseText(cache);
if (StringUtils.isNotBlank(license)) {
view.findViewById(R.id.license_box).setVisibility(View.VISIBLE);
- TextView licenseView = ((TextView) view.findViewById(R.id.license));
+ final TextView licenseView = ((TextView) view.findViewById(R.id.license));
licenseView.setText(Html.fromHtml(license), BufferType.SPANNABLE);
licenseView.setClickable(true);
licenseView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
@@ -1613,15 +1532,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
* shows/hides buttons, sets text in watchlist box
*/
private void updateWatchlistBox() {
- LinearLayout layout = (LinearLayout) view.findViewById(R.id.watchlist_box);
- boolean supportsWatchList = cache.supportsWatchList();
+ final LinearLayout layout = (LinearLayout) view.findViewById(R.id.watchlist_box);
+ final boolean supportsWatchList = cache.supportsWatchList();
layout.setVisibility(supportsWatchList ? View.VISIBLE : View.GONE);
if (!supportsWatchList) {
return;
}
- Button buttonAdd = (Button) view.findViewById(R.id.add_to_watchlist);
- Button buttonRemove = (Button) view.findViewById(R.id.remove_from_watchlist);
- TextView text = (TextView) view.findViewById(R.id.watchlist_text);
+ final Button buttonAdd = (Button) view.findViewById(R.id.add_to_watchlist);
+ final Button buttonRemove = (Button) view.findViewById(R.id.remove_from_watchlist);
+ final TextView text = (TextView) view.findViewById(R.id.watchlist_text);
if (cache.isOnWatchlist() || cache.isOwner()) {
buttonAdd.setVisibility(View.GONE);
@@ -1647,15 +1566,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
* shows/hides buttons, sets text in watchlist box
*/
private void updateFavPointBox() {
- LinearLayout layout = (LinearLayout) view.findViewById(R.id.favpoint_box);
- boolean supportsFavoritePoints = cache.supportsFavoritePoints();
+ final LinearLayout layout = (LinearLayout) view.findViewById(R.id.favpoint_box);
+ final boolean supportsFavoritePoints = cache.supportsFavoritePoints();
layout.setVisibility(supportsFavoritePoints ? View.VISIBLE : View.GONE);
if (!supportsFavoritePoints || cache.isOwner() || !Settings.isPremiumMember()) {
return;
}
- Button buttonAdd = (Button) view.findViewById(R.id.add_to_favpoint);
- Button buttonRemove = (Button) view.findViewById(R.id.remove_from_favpoint);
- TextView text = (TextView) view.findViewById(R.id.favpoint_text);
+ final Button buttonAdd = (Button) view.findViewById(R.id.add_to_favpoint);
+ final Button buttonRemove = (Button) view.findViewById(R.id.remove_from_favpoint);
+ final TextView text = (TextView) view.findViewById(R.id.favpoint_text);
if (cache.isFavorite()) {
buttonAdd.setVisibility(View.GONE);
@@ -1680,15 +1599,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
* shows/hides/updates list box
*/
private void updateListBox() {
- View box = view.findViewById(R.id.list_box);
+ final View box = view.findViewById(R.id.list_box);
if (cache.isOffline()) {
// show box
box.setVisibility(View.VISIBLE);
// update text
- TextView text = (TextView) view.findViewById(R.id.list_text);
- StoredList list = cgData.getList(cache.getListId());
+ final TextView text = (TextView) view.findViewById(R.id.list_text);
+ final StoredList list = cgData.getList(cache.getListId());
if (list != null) {
text.setText(res.getString(R.string.cache_list_text) + " " + list.title);
} else {
@@ -1732,8 +1651,8 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- return ImageHelper.scaleBitmapToFitDisplay(image);
- } catch (Exception e) {
+ return ImageUtils.scaleBitmapToFitDisplay(image);
+ } catch (final Exception e) {
Log.w("CacheDetailActivity.PreviewMapTask", e);
return null;
}
@@ -1757,12 +1676,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
((ImageView) view.findViewById(R.id.map_preview)).setImageDrawable(image);
view.findViewById(R.id.map_preview_box).setVisibility(View.VISIBLE);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("CacheDetailActivity.PreviewMapTask", e);
}
}
}
-
}
protected class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
@@ -1789,7 +1707,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (Settings.isAutoLoadDescription()) {
loadLongDescription();
} else {
- Button showDesc = (Button) view.findViewById(R.id.show_description);
+ final Button showDesc = (Button) view.findViewById(R.id.show_description);
showDesc.setVisibility(View.VISIBLE);
showDesc.setOnClickListener(new View.OnClickListener() {
@Override
@@ -1838,7 +1756,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final TextView hintView = ((TextView) view.findViewById(R.id.hint));
if (StringUtils.isNotBlank(cache.getHint())) {
- if (BaseUtils.containsHtml(cache.getHint())) {
+ if (TextUtils.containsHtml(cache.getHint())) {
hintView.setText(Html.fromHtml(cache.getHint(), new HtmlImage(cache.getGeocode(), false, cache.getListId(), false), null), TextView.BufferType.SPANNABLE);
hintView.setText(CryptUtils.rot13((Spannable) hintView.getText()));
}
@@ -1923,7 +1841,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
private void loadLongDescription() {
- Button showDesc = (Button) view.findViewById(R.id.show_description);
+ final Button showDesc = (Button) view.findViewById(R.id.show_description);
showDesc.setVisibility(View.GONE);
showDesc.setOnClickListener(null);
view.findViewById(R.id.loading).setVisibility(View.VISIBLE);
@@ -1965,21 +1883,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
editNoteDialogListener.onFinishEditNoteDialog(note);
}
- private static class HtmlImageCounter implements Html.ImageGetter {
-
- private int imageCount = 0;
-
- @Override
- public Drawable getDrawable(String url) {
- imageCount++;
- return null;
- }
-
- public int getImageCount() {
- return imageCount;
- }
- }
-
/**
* Loads the description in background. <br />
* <br />
@@ -2008,7 +1911,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
protected Void doInBackground(Object... params) {
try {
// Fast preview: parse only HTML without loading any images
- HtmlImageCounter imageCounter = new HtmlImageCounter();
+ final HtmlImageCounter imageCounter = new HtmlImageCounter();
final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler();
description = Html.fromHtml(descriptionString, imageCounter, unknownTagsHandler);
publishProgress();
@@ -2035,7 +1938,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (needsRefresh) {
publishProgress();
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("LoadDescriptionTask: ", e);
}
return null;
@@ -2050,7 +1953,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (StringUtils.isNotBlank(descriptionString)) {
try {
descriptionView.setText(description, TextView.BufferType.SPANNABLE);
- } catch (Exception e) {
+ } catch (final Exception e) {
// On 4.1, there is sometimes a crash on measuring the layout: https://code.google.com/p/android/issues/detail?id=35412
Log.e("Android bug setting text: ", e);
// remove the formatting by converting to a simple string
@@ -2072,7 +1975,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (shortDescView != null) {
final String shortDescription = cache.getShortDescription();
if (StringUtils.isNotBlank(shortDescription)) {
- int index = descriptionString.indexOf(shortDescription);
+ final int index = descriptionString.indexOf(shortDescription);
if (index >= 0 && index < 200) {
shortDescView.setVisibility(View.GONE);
}
@@ -2101,7 +2004,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (Settings.isLightSkin()) {
backcolor = color.white;
- for (Pattern pattern : LIGHT_COLOR_PATTERNS) {
+ for (final Pattern pattern : LIGHT_COLOR_PATTERNS) {
final MatcherWrapper matcher = new MatcherWrapper(pattern, text);
if (matcher.find()) {
view.setBackgroundResource(color.darker_gray);
@@ -2111,7 +2014,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
} else {
backcolor = color.black;
- for (Pattern pattern : DARK_COLOR_PATTERNS) {
+ for (final Pattern pattern : DARK_COLOR_PATTERNS) {
final MatcherWrapper matcher = new MatcherWrapper(pattern, text);
if (matcher.find()) {
view.setBackgroundResource(color.darker_gray);
@@ -2123,176 +2026,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- private class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> {
- private final boolean allLogs;
-
- LogsViewCreator(boolean allLogs) {
- this.allLogs = allLogs;
- }
-
- @Override
- public ListView getDispatchedView() {
- if (cache == null) {
- // something is really wrong
- return null;
- }
-
- view = (ListView) getLayoutInflater().inflate(R.layout.cachedetail_logs_page, null);
-
- // log count
- final Map<LogType, Integer> logCounts = cache.getLogCounts();
- if (logCounts != null) {
- final List<Entry<LogType, Integer>> sortedLogCounts = new ArrayList<Entry<LogType, Integer>>(logCounts.size());
- for (Entry<LogType, Integer> entry : logCounts.entrySet()) {
- // it may happen that the label is unknown -> then avoid any output for this type
- if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getKey().getL10n() != null) {
- sortedLogCounts.add(entry);
- }
- }
-
- if (!sortedLogCounts.isEmpty()) {
- // sort the log counts by type id ascending. that way the FOUND, DNF log types are the first and most visible ones
- Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() {
-
- @Override
- public int compare(Entry<LogType, Integer> logCountItem1, Entry<LogType, Integer> logCountItem2) {
- return logCountItem1.getKey().compareTo(logCountItem2.getKey());
- }
- });
-
- ArrayList<String> labels = new ArrayList<String>(sortedLogCounts.size());
- for (Entry<LogType, Integer> pair : sortedLogCounts) {
- labels.add(pair.getValue() + "× " + pair.getKey().getL10n());
- }
-
- final TextView countView = new TextView(CacheDetailActivity.this);
- countView.setText(res.getString(R.string.cache_log_types) + ": " + StringUtils.join(labels, ", "));
- view.addHeaderView(countView, null, false);
- }
- }
-
- final List<LogEntry> logs = allLogs ? cache.getLogs() : cache.getFriendsLogs();
- view.setAdapter(new ArrayAdapter<LogEntry>(CacheDetailActivity.this, R.layout.logs_item, logs) {
- final UserActionsClickListener userActionsClickListener = new UserActionsClickListener();
- final DecryptTextClickListener decryptTextClickListener = new DecryptTextClickListener();
-
- @Override
- public View getView(final int position, final View convertView, final ViewGroup parent) {
- View rowView = convertView;
- if (null == rowView) {
- rowView = getLayoutInflater().inflate(R.layout.logs_item, null);
- }
- LogViewHolder holder = (LogViewHolder) rowView.getTag();
- if (null == holder) {
- holder = new LogViewHolder(rowView);
- }
- holder.setPosition(position);
-
- final LogEntry log = getItem(position);
-
- if (log.date > 0) {
- holder.date.setText(Formatter.formatShortDateVerbally(log.date));
- holder.date.setVisibility(View.VISIBLE);
- } else {
- holder.date.setVisibility(View.GONE);
- }
-
- holder.type.setText(log.type.getL10n());
- holder.author.setText(StringEscapeUtils.unescapeHtml4(log.author));
-
- // finds count
- holder.countOrLocation.setVisibility(View.VISIBLE);
- if (log.found == -1) {
- holder.countOrLocation.setVisibility(View.GONE);
- } else {
- holder.countOrLocation.setText(res.getQuantityString(R.plurals.cache_counts, log.found, log.found));
- }
-
- // logtext, avoid parsing HTML if not necessary
- String logText = log.log;
- if (BaseUtils.containsHtml(logText)) {
- logText = log.getDisplayText();
- // Fast preview: parse only HTML without loading any images
- HtmlImageCounter imageCounter = new HtmlImageCounter();
- final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler();
- holder.text.setText(Html.fromHtml(logText, imageCounter, unknownTagsHandler), TextView.BufferType.SPANNABLE);
- if (imageCounter.getImageCount() > 0) {
- // Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview
- LogImageLoader loader = new LogImageLoader(holder);
- loader.execute(logText);
- }
- }
- else {
- holder.text.setText(logText, TextView.BufferType.SPANNABLE);
- }
-
- // images
- if (log.hasLogImages()) {
- holder.images.setText(log.getImageTitles());
- holder.images.setVisibility(View.VISIBLE);
- holder.images.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ImagesActivity.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<Image>(log.getLogImages()));
- }
- });
- } else {
- holder.images.setVisibility(View.GONE);
- }
-
- // colored marker
- int marker = log.type.markerId;
- if (marker != 0) {
- holder.marker.setVisibility(View.VISIBLE);
- holder.marker.setImageResource(marker);
- }
- else {
- holder.marker.setVisibility(View.GONE);
- }
-
- if (null == convertView) {
- // if convertView != null then this listeners are already set
- holder.author.setOnClickListener(userActionsClickListener);
- holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
- holder.text.setOnClickListener(decryptTextClickListener);
- registerForContextMenu(holder.text);
- }
-
- return rowView;
- }
- });
-
- return view;
- }
-
- /** Loads the Log Images outside the ui thread. */
-
- private class LogImageLoader extends AsyncTask<String, Progress, Spanned> {
- final private LogViewHolder holder;
- final private int position;
-
- public LogImageLoader(LogViewHolder holder) {
- this.holder = holder;
- this.position = holder.getPosition();
- }
-
- @Override
- protected Spanned doInBackground(String... logtext) {
- return Html.fromHtml(logtext[0], new HtmlImage(cache.getGeocode(), false, cache.getListId(), false), null); //, TextView.BufferType.SPANNABLE)
- }
-
- @Override
- protected void onPostExecute(Spanned result) {
- // Ensure that this holder and its view still references the right item before updating the text.
- if (position == holder.getPosition()) {
- holder.text.setText(result);
- }
- }
-
- }
-
- }
-
private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
@Override
@@ -2342,7 +2075,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// visited
if (wpt.isVisited()) {
- TypedValue a = new TypedValue();
+ final TypedValue a = new TypedValue();
getTheme().resolveAttribute(R.attr.text_color_grey, a, true);
if (a.type >= TypedValue.TYPE_FIRST_COLOR_INT && a.type <= TypedValue.TYPE_LAST_COLOR_INT) {
// really should be just a color!
@@ -2354,7 +2087,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (StringUtils.isNotBlank(wpt.getNote())) {
final TextView noteView = (TextView) waypointView.findViewById(R.id.note);
noteView.setVisibility(View.VISIBLE);
- if (BaseUtils.containsHtml(wpt.getNote())) {
+ if (TextUtils.containsHtml(wpt.getNote())) {
noteView.setText(Html.fromHtml(wpt.getNote()), TextView.BufferType.SPANNABLE);
}
else {
@@ -2429,9 +2162,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
view.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
- Object selection = arg0.getItemAtPosition(arg2);
+ final Object selection = arg0.getItemAtPosition(arg2);
if (selection instanceof Trackable) {
- Trackable trackable = (Trackable) selection;
+ final Trackable trackable = (Trackable) selection;
TrackableActivity.startActivity(CacheDetailActivity.this, trackable.getGuid(), trackable.getGeocode(), trackable.getName());
}
}
@@ -2476,10 +2209,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
*/
private AlertDialog createResetCacheCoordinatesDialog(final Geocache cache, final Waypoint wpt) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.waypoint_reset_cache_coords);
- String[] items = new String[] { res.getString(R.string.waypoint_localy_reset_cache_coords), res.getString(R.string.waypoint_reset_local_and_remote_cache_coords) };
+ final String[] items = new String[] { res.getString(R.string.waypoint_localy_reset_cache_coords), res.getString(R.string.waypoint_reset_local_and_remote_cache_coords) };
builder.setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() {
@Override
@@ -2531,7 +2264,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private final boolean local;
private final boolean remote;
private final Waypoint wpt;
- private ProgressDialog progress;
+ private final ProgressDialog progress;
public static final int LOCAL = 0;
public static final int ON_WEBSITE = 1;
@@ -2561,7 +2294,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
handler.sendEmptyMessage(LOCAL);
}
- IConnector con = ConnectorFactory.getConnector(cache);
+ final IConnector con = ConnectorFactory.getConnector(cache);
if (remote && con.supportsOwnCoordinates()) {
runOnUiThread(new Runnable() {
@Override
@@ -2675,10 +2408,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return new DescriptionViewCreator();
case LOGS:
- return new LogsViewCreator(true);
+ return new CacheLogsViewCreator(this, cache, true);
case LOGSFRIENDS:
- return new LogsViewCreator(false);
+ return new CacheLogsViewCreator(this, cache, false);
case WAYPOINTS:
return new WaypointsViewCreator();
@@ -2704,7 +2437,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final Button offlineStore = (Button) view.findViewById(R.id.offline_store);
if (cache.isOffline()) {
- long diff = (System.currentTimeMillis() / (60 * 1000)) - (cache.getDetailedUpdate() / (60 * 1000)); // minutes
+ final long diff = (System.currentTimeMillis() / (60 * 1000)) - (cache.getDetailedUpdate() / (60 * 1000)); // minutes
String ago;
if (diff < 15) {
diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java
index 4f8af08..059f664 100644
--- a/main/src/cgeo/geocaching/CompassActivity.java
+++ b/main/src/cgeo/geocaching/CompassActivity.java
@@ -18,6 +18,7 @@ import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorManager;
+import android.media.AudioManager;
import android.os.Bundle;
import android.speech.tts.TextToSpeech.Engine;
import android.view.Menu;
@@ -94,6 +95,9 @@ public class CompassActivity extends AbstractActivity {
setCacheInfo();
Views.inject(this);
+
+ // make sure we can control the TTS volume
+ setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
@Override
@@ -127,8 +131,7 @@ public class CompassActivity extends AbstractActivity {
final IWaypoint coordinate = coordinates.get(i);
subMenu.add(0, COORDINATES_OFFSET + i, 0, coordinate.getName() + " (" + coordinate.getCoordType() + ")");
}
- }
- else {
+ } else {
menu.findItem(R.id.menu_select_destination).setVisible(false);
}
return true;
@@ -199,8 +202,7 @@ public class CompassActivity extends AbstractActivity {
protected void onActivityResult(int request, int result, Intent data) {
if (request == REQUEST_TTS_DATA_CHECK && result == Engine.CHECK_VOICE_DATA_PASS) {
SpeechService.startService(this, dstCoords);
- }
- else {
+ } else {
Log.i("TTS failed to start. Request: " + request + " result: " + result);
startActivity(new Intent(Engine.ACTION_INSTALL_TTS_DATA));
}
@@ -248,8 +250,7 @@ public class CompassActivity extends AbstractActivity {
if (geo.getCoords() != null) {
if (geo.getSatellitesVisible() >= 0) {
navSatellites.setText(res.getString(R.string.loc_sat) + ": " + geo.getSatellitesFixed() + "/" + geo.getSatellitesVisible());
- }
- else {
+ } else {
navSatellites.setText("");
}
navType.setText(res.getString(geo.getLocationProvider().resourceId));
diff --git a/main/src/cgeo/geocaching/DirectionProvider.java b/main/src/cgeo/geocaching/DirectionProvider.java
index 37b184a..b4fb86c 100644
--- a/main/src/cgeo/geocaching/DirectionProvider.java
+++ b/main/src/cgeo/geocaching/DirectionProvider.java
@@ -27,6 +27,8 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve
@Override
protected void onFirstObserver() {
+ @SuppressWarnings("deprecation")
+ // This will be removed when using a new location service. Until then, it is okay to be used.
final Sensor defaultSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
sensorManager.registerListener(this, defaultSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java
index ab35641..dce49a3 100644
--- a/main/src/cgeo/geocaching/EditWaypointActivity.java
+++ b/main/src/cgeo/geocaching/EditWaypointActivity.java
@@ -11,7 +11,7 @@ import cgeo.geocaching.geopoint.DistanceParser;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
-import cgeo.geocaching.utils.BaseUtils;
+import cgeo.geocaching.utils.TextUtils;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
@@ -99,7 +99,7 @@ public class EditWaypointActivity extends AbstractActivity {
buttonLon.setText(waypoint.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE));
}
waypointName.setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getName())).toString());
- if (BaseUtils.containsHtml(waypoint.getNote())) {
+ if (TextUtils.containsHtml(waypoint.getNote())) {
note.setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getNote())).toString());
}
else {
diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java
index 00f1a1f..9649f5f 100644
--- a/main/src/cgeo/geocaching/Geocache.java
+++ b/main/src/cgeo/geocaching/Geocache.java
@@ -106,20 +106,20 @@ public class Geocache implements ICache, IWaypoint {
private float myVote = 0; // valid ratings are larger than zero
private int inventoryItems = 0;
private boolean onWatchlist = false;
- private List<String> attributes = new LazyInitializedList<String>() {
+ private final List<String> attributes = new LazyInitializedList<String>() {
@Override
public List<String> call() {
return cgData.loadAttributes(geocode);
}
};
- private List<Waypoint> waypoints = new LazyInitializedList<Waypoint>() {
+ private final List<Waypoint> waypoints = new LazyInitializedList<Waypoint>() {
@Override
public List<Waypoint> call() {
return cgData.loadWaypoints(geocode);
}
};
private List<Image> spoilers = null;
- private List<LogEntry> logs = new LazyInitializedList<LogEntry>() {
+ private final List<LogEntry> logs = new LazyInitializedList<LogEntry>() {
@Override
public List<LogEntry> call() {
return cgData.loadLogs(geocode);
@@ -135,6 +135,7 @@ public class Geocache implements ICache, IWaypoint {
private String nameForSorting;
private final EnumSet<StorageLocation> storageLocation = EnumSet.of(StorageLocation.HEAP);
private boolean finalDefined = false;
+ private boolean logPasswordRequired = false;
private int zoomlevel = Tile.ZOOMLEVEL_MAX + 1;
private static final Pattern NUMBER_PATTERN = Pattern.compile("\\d+");
@@ -319,7 +320,7 @@ public class Geocache implements ICache, IWaypoint {
this.setWaypoints(other.waypoints, false);
}
else {
- ArrayList<Waypoint> newPoints = new ArrayList<Waypoint>(waypoints);
+ final ArrayList<Waypoint> newPoints = new ArrayList<Waypoint>(waypoints);
Waypoint.mergeWayPoints(newPoints, other.waypoints, false);
this.setWaypoints(newPoints, false);
}
@@ -346,12 +347,10 @@ public class Geocache implements ICache, IWaypoint {
// if cache has ORIGINAL type waypoint ... it is considered that it has modified coordinates, otherwise not
userModifiedCoords = false;
- if (waypoints != null) {
- for (Waypoint wpt : waypoints) {
- if (wpt.getWaypointType() == WaypointType.ORIGINAL) {
- userModifiedCoords = true;
- break;
- }
+ for (final Waypoint wpt : waypoints) {
+ if (wpt.getWaypointType() == WaypointType.ORIGINAL) {
+ userModifiedCoords = true;
+ break;
}
}
@@ -465,7 +464,7 @@ public class Geocache implements ICache, IWaypoint {
fromActivity.showToast(((Activity) fromActivity).getResources().getString(R.string.err_cannot_log_visit));
return;
}
- Intent logVisitIntent = new Intent((Activity) fromActivity, LogCacheActivity.class);
+ final Intent logVisitIntent = new Intent((Activity) fromActivity, LogCacheActivity.class);
logVisitIntent.putExtra(LogCacheActivity.EXTRAS_ID, cacheId);
logVisitIntent.putExtra(LogCacheActivity.EXTRAS_GEOCODE, geocode);
@@ -484,7 +483,7 @@ public class Geocache implements ICache, IWaypoint {
}
final boolean status = cgData.saveLogOffline(geocode, date.getTime(), logType, log);
- Resources res = fromActivity.getResources();
+ final Resources res = fromActivity.getResources();
if (status) {
ActivityMixin.showToast(fromActivity, res.getString(R.string.info_log_saved));
cgData.saveVisitDate(geocode);
@@ -677,7 +676,7 @@ public class Geocache implements ICache, IWaypoint {
*/
private void initializeCacheTexts() {
if (description == null || shortdesc == null || hint == null || location == null) {
- Geocache partial = cgData.loadCacheTexts(this.getGeocode());
+ final Geocache partial = cgData.loadCacheTexts(this.getGeocode());
if (description == null) {
setDescription(partial.getDescription());
}
@@ -752,7 +751,7 @@ public class Geocache implements ICache, IWaypoint {
return;
}
- StringBuilder subject = new StringBuilder("Geocache ");
+ final StringBuilder subject = new StringBuilder("Geocache ");
subject.append(geocode);
if (StringUtils.isNotBlank(name)) {
subject.append(" - ").append(name);
@@ -1024,7 +1023,7 @@ public class Geocache implements ICache, IWaypoint {
}
finalDefined = false;
if (waypoints != null) {
- for (Waypoint waypoint : waypoints) {
+ for (final Waypoint waypoint : waypoints) {
waypoint.setGeocode(geocode);
if (waypoint.isFinalWithCoords()) {
finalDefined = true;
@@ -1045,8 +1044,8 @@ public class Geocache implements ICache, IWaypoint {
* @return only the logs of friends, never <code>null</code>
*/
public List<LogEntry> getFriendsLogs() {
- ArrayList<LogEntry> friendLogs = new ArrayList<LogEntry>();
- for (LogEntry log : logs) {
+ final ArrayList<LogEntry> friendLogs = new ArrayList<LogEntry>();
+ for (final LogEntry log : logs) {
if (log.friend) {
friendLogs.add(log);
}
@@ -1261,7 +1260,7 @@ public class Geocache implements ICache, IWaypoint {
*/
private void resetFinalDefined() {
finalDefined = false;
- for (Waypoint wp : waypoints) {
+ for (final Waypoint wp : waypoints) {
if (wp.isFinalWithCoords()) {
finalDefined = true;
break;
@@ -1409,14 +1408,14 @@ public class Geocache implements ICache, IWaypoint {
addOrChangeWaypoint(waypoint, false);
count++;
}
- } catch (Geopoint.ParseException e) {
+ } catch (final Geopoint.ParseException e) {
// ignore
}
note = note.substring(matcher.start() + 1);
matcher = new MatcherWrapper(coordPattern, note);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Geocache.parseWaypointsFromNote", e);
}
}
@@ -1426,7 +1425,7 @@ public class Geocache implements ICache, IWaypoint {
*/
private static WaypointType parseWaypointType(final String input) {
final String lowerInput = StringUtils.substring(input, 0, 20).toLowerCase(Locale.getDefault());
- for (WaypointType wpType : WaypointType.values()) {
+ for (final WaypointType wpType : WaypointType.values()) {
if (lowerInput.contains(wpType.getL10n().toLowerCase(Locale.getDefault()))) {
return wpType;
}
@@ -1484,7 +1483,7 @@ public class Geocache implements ICache, IWaypoint {
}
public void store(final int listId, CancellableHandler handler) {
- int newListId = listId < StoredList.STANDARD_LIST_ID
+ final int newListId = listId < StoredList.STANDARD_LIST_ID
? Math.max(getListId(), StoredList.STANDARD_LIST_ID)
: listId;
storeCache(this, null, newListId, false, handler);
@@ -1515,7 +1514,7 @@ public class Geocache implements ICache, IWaypoint {
cgData.removeCache(getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE));
handler.sendMessage(Message.obtain());
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("cache.drop: ", e);
}
}
@@ -1614,7 +1613,7 @@ public class Geocache implements ICache, IWaypoint {
// store spoilers
if (CollectionUtils.isNotEmpty(cache.getSpoilers())) {
- for (Image oneSpoiler : cache.getSpoilers()) {
+ for (final Image oneSpoiler : cache.getSpoilers()) {
imgGetter.getDrawable(oneSpoiler.getUrl());
}
}
@@ -1625,9 +1624,9 @@ public class Geocache implements ICache, IWaypoint {
// store images from logs
if (Settings.isStoreLogImages()) {
- for (LogEntry log : cache.getLogs()) {
+ for (final LogEntry log : cache.getLogs()) {
if (log.hasLogImages()) {
- for (Image oneLogImg : log.getLogImages()) {
+ for (final Image oneLogImg : log.getLogImages()) {
imgGetter.getDrawable(oneLogImg.getUrl());
}
}
@@ -1650,7 +1649,7 @@ public class Geocache implements ICache, IWaypoint {
if (handler != null) {
handler.sendMessage(Message.obtain());
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Geocache.storeCache", e);
}
}
@@ -1703,7 +1702,7 @@ public class Geocache implements ICache, IWaypoint {
if (hours >= 0 && hours < 24 && minutes >= 0 && minutes < 60) {
return String.valueOf(hours * 60 + minutes);
}
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
// cannot happen, but static code analysis doesn't know
}
}
@@ -1718,7 +1717,7 @@ public class Geocache implements ICache, IWaypoint {
if (hours >= 0 && hours < 24) {
return String.valueOf(hours * 60);
}
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
// cannot happen, but static code analysis doesn't know
}
}
@@ -1747,9 +1746,9 @@ public class Geocache implements ICache, IWaypoint {
}
public List<Image> getImages() {
- List<Image> result = new ArrayList<Image>();
+ final List<Image> result = new ArrayList<Image>();
result.addAll(getSpoilers());
- for (LogEntry log : getLogs()) {
+ for (final LogEntry log : getLogs()) {
result.addAll(log.getLogImages());
}
return result;
@@ -1767,7 +1766,7 @@ public class Geocache implements ICache, IWaypoint {
* the cache, so the result might be wrong.
*/
public boolean hasOwnLog(LogType logType) {
- for (LogEntry logEntry : getLogs()) {
+ for (final LogEntry logEntry : getLogs()) {
if (logEntry.type == logType && logEntry.isOwn()) {
return true;
}
@@ -1778,4 +1777,12 @@ public class Geocache implements ICache, IWaypoint {
public int getMapMarkerId() {
return getConnector().getCacheMapMarkerId(isDisabled() || isArchived());
}
+
+ public boolean isLogPasswordRequired() {
+ return logPasswordRequired;
+ }
+
+ public void setLogPasswordRequired(boolean required) {
+ logPasswordRequired = required;
+ }
}
diff --git a/main/src/cgeo/geocaching/ImageSelectActivity.java b/main/src/cgeo/geocaching/ImageSelectActivity.java
index 26dd85a..39824a9 100644
--- a/main/src/cgeo/geocaching/ImageSelectActivity.java
+++ b/main/src/cgeo/geocaching/ImageSelectActivity.java
@@ -5,7 +5,7 @@ import butterknife.Views;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.compatibility.Compatibility;
-import cgeo.geocaching.utils.ImageHelper;
+import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
@@ -282,10 +282,10 @@ public class ImageSelectActivity extends AbstractActivity {
} else {
image = BitmapFactory.decodeFile(filePath);
}
- final BitmapDrawable scaledImage = ImageHelper.scaleBitmapTo(image, maxXY, maxXY);
+ final BitmapDrawable scaledImage = ImageUtils.scaleBitmapTo(image, maxXY, maxXY);
image = null;
final String uploadFilename = getOutputImageFile().getPath();
- ImageHelper.storeBitmap(scaledImage.getBitmap(), Bitmap.CompressFormat.JPEG, 75, uploadFilename);
+ ImageUtils.storeBitmap(scaledImage.getBitmap(), Bitmap.CompressFormat.JPEG, 75, uploadFilename);
return uploadFilename;
}
diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java
index 62c94ce..b3b6c09 100644
--- a/main/src/cgeo/geocaching/LogCacheActivity.java
+++ b/main/src/cgeo/geocaching/LogCacheActivity.java
@@ -71,6 +71,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
private Button postButton = null;
private CheckBox tweetCheck = null;
private LinearLayout tweetBox = null;
+ private LinearLayout logPasswordBox = null;
private boolean tbChanged = false;
private SparseArray<TrackableLog> actionButtons;
@@ -252,6 +253,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
postButton = (Button) findViewById(R.id.post);
tweetBox = (LinearLayout) findViewById(R.id.tweet_box);
tweetCheck = (CheckBox) findViewById(R.id.tweet);
+ logPasswordBox = (LinearLayout) findViewById(R.id.log_password_box);
// initialize with default values
setDefaultValues();
@@ -302,6 +304,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
tweetCheck.setChecked(true);
updateTweetBox(typeSelected);
+ updateLogPasswordBox(typeSelected);
final Button imageButton = (Button) findViewById(R.id.image_btn);
imageButton.setOnClickListener(new View.OnClickListener() {
@@ -377,6 +380,8 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
final EditText logView = (EditText) findViewById(R.id.log);
logView.setText(StringUtils.EMPTY);
+ final EditText logPasswordView = (EditText) findViewById(R.id.log_password);
+ logPasswordView.setText(StringUtils.EMPTY);
updateImageButton();
@@ -491,6 +496,14 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
}
}
+ private void updateLogPasswordBox(LogType type) {
+ if (type == LogType.FOUND_IT && cache.isLogPasswordRequired()) {
+ logPasswordBox.setVisibility(View.VISIBLE);
+ } else {
+ logPasswordBox.setVisibility(View.GONE);
+ }
+ }
+
private class DateListener implements View.OnClickListener {
@Override
@@ -507,7 +520,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
final String message = res.getString(StringUtils.isBlank(imageUri.getPath()) ?
R.string.log_saving :
R.string.log_saving_and_uploading);
- new Poster(LogCacheActivity.this, message).execute(currentLogText());
+ new Poster(LogCacheActivity.this, message).execute(currentLogText(), currentLogPassword());
}
}
@@ -520,8 +533,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
@Override
protected StatusCode doInBackgroundInternal(final String[] logTexts) {
final String log = logTexts[0];
+ final String logPwd = logTexts.length > 1 ? logTexts[1] : null;
try {
- final LogResult logResult = loggingManager.postLog(cache, typeSelected, date, log, trackables);
+ final LogResult logResult = loggingManager.postLog(cache, typeSelected, date, log, logPwd, trackables);
if (logResult.getPostLogResult() == StatusCode.NO_ERROR) {
final LogEntry logNow = new LogEntry(date, typeSelected, log);
@@ -593,6 +607,10 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia
return ((EditText) findViewById(R.id.log)).getText().toString();
}
+ private String currentLogPassword() {
+ return ((EditText) findViewById(R.id.log_password)).getText().toString();
+ }
+
@Override
protected LogContext getLogContext() {
return new LogContext(cache);
diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java
index ff24322..5898cba 100644
--- a/main/src/cgeo/geocaching/MainActivity.java
+++ b/main/src/cgeo/geocaching/MainActivity.java
@@ -5,9 +5,7 @@ import butterknife.Views;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.connector.ConnectorFactory;
-import cgeo.geocaching.connector.IConnector;
-import cgeo.geocaching.connector.gc.Login;
-import cgeo.geocaching.connector.oc.OCApiLiveConnector;
+import cgeo.geocaching.connector.capability.ILogin;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.geopoint.Geopoint;
@@ -38,11 +36,13 @@ import android.location.Geocoder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
@@ -53,8 +53,6 @@ import java.util.List;
import java.util.Locale;
public class MainActivity extends AbstractActivity {
- @InjectView(R.id.user_info_gc) protected TextView userInfoViewGc;
- @InjectView(R.id.user_info_ocde) protected TextView userInfoViewOcDe;
@InjectView(R.id.nav_satellites) protected TextView navSatellites;
@InjectView(R.id.filter_button_title)protected TextView filterTitle;
@InjectView(R.id.map) protected ImageView findOnMap;
@@ -67,6 +65,7 @@ public class MainActivity extends AbstractActivity {
@InjectView(R.id.nav_accuracy) protected TextView navAccuracy ;
@InjectView(R.id.nav_location) protected TextView navLocation ;
@InjectView(R.id.offline_count) protected TextView countBubble ;
+ @InjectView(R.id.info_area) protected LinearLayout infoArea;
private static final String SCAN_INTENT = "com.google.zxing.client.android.SCAN";
public static final int SEARCH_REQUEST_CODE = 2;
@@ -86,46 +85,30 @@ public class MainActivity extends AbstractActivity {
@Override
public void handleMessage(Message msg) {
- if (Settings.isGCConnectorActive()) {
- StringBuilder userInfo = new StringBuilder("geocaching.com").append(Formatter.SEPARATOR);
- if (Login.isActualLoginStatus()) {
- userInfo.append(Login.getActualUserName());
- if (Login.getActualCachesFound() >= 0) {
- userInfo.append(" (").append(String.valueOf(Login.getActualCachesFound())).append(')');
- }
- userInfo.append(Formatter.SEPARATOR);
- }
- userInfo.append(Login.getActualStatus());
+ // Get active connectors with login status
+ ILogin[] loginConns = ConnectorFactory.getActiveLiveConnectors();
- userInfoViewGc.setText(userInfo.toString());
- userInfoViewGc.setVisibility(View.VISIBLE);
- }
- else {
- userInfoViewGc.setVisibility(View.GONE);
- }
+ // Update UI
+ infoArea.removeAllViews();
+ LayoutInflater inflater = getLayoutInflater();
- if (Settings.isOCConnectorActive()) {
- StringBuilder userInfo = new StringBuilder("opencaching.de").append(Formatter.SEPARATOR);
- IConnector conn = ConnectorFactory.getConnector("OCXXXX");
- if (conn instanceof OCApiLiveConnector) {
- OCApiLiveConnector ocapiConn = (OCApiLiveConnector) conn;
- if (ocapiConn.supportsPersonalization()) {
- userInfo.append(ocapiConn.getUserName());
- int count = ocapiConn.getCachesFound();
- if (count >= 0) {
- userInfo.append(" (").append(String.valueOf(count)).append(')');
- }
- } else {
- userInfo.append("Anonymous");
+ for (ILogin conn : loginConns) {
+
+ TextView connectorInfo = (TextView) inflater.inflate(R.layout.main_activity_connectorstatus, null);
+ infoArea.addView(connectorInfo);
+
+ StringBuilder userInfo = new StringBuilder(conn.getName()).append(Formatter.SEPARATOR);
+ if (conn.isLoggedIn()) {
+ userInfo.append(conn.getUserName());
+ if (conn.getCachesFound() >= 0) {
+ userInfo.append(" (").append(String.valueOf(conn.getCachesFound())).append(')');
}
+ userInfo.append(Formatter.SEPARATOR);
}
- userInfoViewOcDe.setText(userInfo.toString());
- userInfoViewOcDe.setVisibility(View.VISIBLE);
- }
- else {
- userInfoViewOcDe.setVisibility(View.GONE);
- }
+ userInfo.append(conn.getLoginStatusString());
+ connectorInfo.setText(userInfo);
+ }
}
};
@@ -727,35 +710,11 @@ public class MainActivity extends AbstractActivity {
return;
}
- if (Settings.isGCConnectorActive()) {
- // login
- final StatusCode status = Login.login();
-
- if (status == StatusCode.NO_ERROR) {
- app.firstRun = false;
- Login.detectGcCustomDate();
- updateUserInfoHandler.sendEmptyMessage(-1);
- }
-
- if (app.showLoginToast) {
- firstLoginHandler.sendMessage(firstLoginHandler.obtainMessage(0, status));
- app.showLoginToast = false;
+ ILogin[] conns = ConnectorFactory.getActiveLiveConnectors();
- // invoke settings activity to insert login details
- if (status == StatusCode.NO_LOGIN_INFO_STORED) {
- SettingsActivity.startActivity(MainActivity.this);
- }
- }
- }
- if (Settings.isOCConnectorActive()) {
- IConnector conn = ConnectorFactory.getConnector("OCXXXX");
- if (conn instanceof OCApiLiveConnector) {
- OCApiLiveConnector ocapiConn = (OCApiLiveConnector) conn;
- if (ocapiConn.supportsPersonalization()) {
- ocapiConn.retrieveUserInfo();
- }
- updateUserInfoHandler.sendEmptyMessage(-1);
- }
+ for (ILogin conn : conns) {
+ conn.login(firstLoginHandler, MainActivity.this);
+ updateUserInfoHandler.sendEmptyMessage(-1);
}
}
}
diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java
index 0c31abf..c2a7b6d 100644
--- a/main/src/cgeo/geocaching/SearchActivity.java
+++ b/main/src/cgeo/geocaching/SearchActivity.java
@@ -7,11 +7,10 @@ import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.connector.capability.ISearchByGeocode;
-import cgeo.geocaching.connector.gc.GCConstants;
+import cgeo.geocaching.connector.trackable.TrackableConnector;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
-import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.EditUtils;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
@@ -61,7 +60,7 @@ public class SearchActivity extends AbstractActivity {
super.onCreate(savedInstanceState);
// search query
- Intent intent = getIntent();
+ final Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
final String query = intent.getStringExtra(SearchManager.QUERY);
final boolean keywordSearch = intent.getBooleanExtra(Intents.EXTRA_KEYWORD_SEARCH, true);
@@ -122,7 +121,7 @@ public class SearchActivity extends AbstractActivity {
// otherwise see if this is a pure geocode
if (StringUtils.isEmpty(geocode)) {
- geocode = StringUtils.trim(query);
+ geocode = StringUtils.upperCase(StringUtils.trim(query));
}
final IConnector connector = ConnectorFactory.getConnector(geocode);
@@ -134,10 +133,10 @@ public class SearchActivity extends AbstractActivity {
}
// Check if the query is a TB code
- final String trackable = BaseUtils.getMatch(query, GCConstants.PATTERN_TB_CODE, true, 0, "", false);
- if (StringUtils.isNotBlank(trackable)) {
+ final TrackableConnector trackableConnector = ConnectorFactory.getTrackableConnector(geocode);
+ if (trackableConnector != ConnectorFactory.UNKNOWN_TRACKABLE_CONNECTOR) {
final Intent trackablesIntent = new Intent(this, TrackableActivity.class);
- trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, trackable.toUpperCase(Locale.US));
+ trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, geocode.toUpperCase(Locale.US));
startActivity(trackablesIntent);
return true;
}
@@ -240,7 +239,7 @@ public class SearchActivity extends AbstractActivity {
lonEdit.setHint(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE_RAW));
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("Failed to update location.");
}
}
@@ -250,7 +249,7 @@ public class SearchActivity extends AbstractActivity {
@Override
public void onClick(View arg0) {
- CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(SearchActivity.this, null, null, app.currentGeo());
+ final CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(SearchActivity.this, null, null, app.currentGeo());
coordsDialog.setCancelable(true);
coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
@Override
@@ -284,7 +283,7 @@ public class SearchActivity extends AbstractActivity {
} else {
try {
cgeocaches.startActivityCoordinates(this, new Geopoint(StringUtils.trim(latText), StringUtils.trim(lonText)));
- } catch (Geopoint.ParseException e) {
+ } catch (final Geopoint.ParseException e) {
showToast(res.getString(e.resource));
}
}
@@ -300,7 +299,7 @@ public class SearchActivity extends AbstractActivity {
private void findByKeywordFn() {
// find caches by coordinates
- String keyText = keywordEditText.getText().toString();
+ final String keyText = keywordEditText.getText().toString();
if (StringUtils.isBlank(keyText)) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_keyword));
diff --git a/main/src/cgeo/geocaching/StatusFragment.java b/main/src/cgeo/geocaching/StatusFragment.java
index 5a9a5b4..e0e714a 100644
--- a/main/src/cgeo/geocaching/StatusFragment.java
+++ b/main/src/cgeo/geocaching/StatusFragment.java
@@ -57,7 +57,7 @@ public class StatusFragment extends Fragment {
@Override
public void handleMessage(final Message msg) {
final Status data = (Status) msg.obj;
- updateDisplay(data != null && data.message != null ? data : null);
+ updateDisplay(data != null && data.message != null ? data : Status.defaultStatus());
}
private void updateDisplay(final Status data) {
diff --git a/main/src/cgeo/geocaching/StoredList.java b/main/src/cgeo/geocaching/StoredList.java
index b92ce9a..55a155c 100644
--- a/main/src/cgeo/geocaching/StoredList.java
+++ b/main/src/cgeo/geocaching/StoredList.java
@@ -71,7 +71,7 @@ public final class StoredList {
promptForListSelection(titleId, runAfterwards, false, -1);
}
- public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards, final boolean onlyMoveTargets, final int exceptListId) {
+ public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId) {
final List<StoredList> lists = getSortedLists();
if (lists == null) {
@@ -89,7 +89,7 @@ public final class StoredList {
for (StoredList list : lists) {
listsTitle.add(list.getTitleAndCount());
}
- if (!onlyMoveTargets) {
+ if (!onlyConcreteLists) {
listsTitle.add("<" + res.getString(R.string.list_menu_all_lists) + ">");
}
listsTitle.add("<" + res.getString(R.string.list_menu_create) + ">");
@@ -101,7 +101,7 @@ public final class StoredList {
builder.setItems(listsTitle.toArray(items), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int itemId) {
- if (itemId == lists.size() && !onlyMoveTargets) {
+ if (itemId == lists.size() && !onlyConcreteLists) {
// all lists
runAfterwards.run(StoredList.ALL_LIST_ID);
} else if (itemId >= lists.size()) {
diff --git a/main/src/cgeo/geocaching/Trackable.java b/main/src/cgeo/geocaching/Trackable.java
index f777351..d532cda 100644
--- a/main/src/cgeo/geocaching/Trackable.java
+++ b/main/src/cgeo/geocaching/Trackable.java
@@ -1,7 +1,8 @@
package cgeo.geocaching;
+import cgeo.geocaching.connector.ConnectorFactory;
+import cgeo.geocaching.connector.trackable.TrackableConnector;
import cgeo.geocaching.enumerations.LogType;
-import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
@@ -38,17 +39,11 @@ public class Trackable implements ILogable {
private String trackingcode = null;
public String getUrl() {
- if (StringUtils.startsWithIgnoreCase(getGeocode(), "GK")) {
- String hex = getGeocode().substring(3);
- try {
- int id = Integer.parseInt(hex, 16);
- return "http://geokrety.org/konkret.php?id=" + id;
- } catch (NumberFormatException e) {
- Log.e("Trackable.getUrl", e);
- return null;
- }
- }
- return "http://www.geocaching.com//track/details.aspx?tracker=" + geocode;
+ return getConnector().getUrl(this);
+ }
+
+ private TrackableConnector getConnector() {
+ return ConnectorFactory.getConnector(this);
}
public String getGuid() {
@@ -208,7 +203,7 @@ public class Trackable implements ILogable {
}
public boolean isLoggable() {
- return !StringUtils.startsWithIgnoreCase(getGeocode(), "GK");
+ return getConnector().isLoggable();
}
public String getTrackingcode() {
@@ -220,7 +215,7 @@ public class Trackable implements ILogable {
}
static public List<LogType> getPossibleLogTypes() {
- List<LogType> logTypes = new ArrayList<LogType>();
+ final List<LogType> logTypes = new ArrayList<LogType>();
logTypes.add(LogType.RETRIEVED_IT);
logTypes.add(LogType.GRABBED_IT);
logTypes.add(LogType.NOTE);
diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java
index 9822946..d1f323c 100644
--- a/main/src/cgeo/geocaching/TrackableActivity.java
+++ b/main/src/cgeo/geocaching/TrackableActivity.java
@@ -5,16 +5,18 @@ import butterknife.Views;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.AbstractViewPagerActivity;
-import cgeo.geocaching.connector.gc.GCParser;
+import cgeo.geocaching.connector.ConnectorFactory;
+import cgeo.geocaching.connector.trackable.TrackableConnector;
+import cgeo.geocaching.connector.trackable.TravelBugConnector;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.network.HtmlImage;
-import cgeo.geocaching.network.Network;
import cgeo.geocaching.ui.AbstractCachingPageViewCreator;
import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.ui.Formatter;
-import cgeo.geocaching.utils.BaseUtils;
+import cgeo.geocaching.ui.UserActionsClickListener;
+import cgeo.geocaching.ui.logs.TrackableLogsViewCreator;
import cgeo.geocaching.utils.HtmlUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.UnknownTagsHandler;
@@ -31,16 +33,12 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Html;
-import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
@@ -60,15 +58,15 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
this.resId = resId;
}
}
+
private Trackable trackable = null;
private String geocode = null;
private String name = null;
private String guid = null;
private String id = null;
- private String contextMenuUser = null;
private LayoutInflater inflater = null;
private ProgressDialog waitDialog = null;
- private Handler loadTrackableHandler = new Handler() {
+ private final Handler loadTrackableHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -100,7 +98,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
invalidateOptionsMenuCompatible();
reinitializeViewPager();
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("TrackableActivity.loadTrackableHandler: ", e);
}
@@ -118,8 +116,8 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
setTitle(res.getString(R.string.trackable));
// get parameters
- Bundle extras = getIntent().getExtras();
- Uri uri = getIntent().getData();
+ final Bundle extras = getIntent().getExtras();
+ final Uri uri = getIntent().getData();
// try to get data from extras
if (extras != null) {
@@ -131,7 +129,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
// try to get data from URI
if (geocode == null && guid == null && id == null && uri != null) {
- String uriHost = uri.getHost().toLowerCase(Locale.US);
+ final String uriHost = uri.getHost().toLowerCase(Locale.US);
if (uriHost.contains("geocaching.com")) {
geocode = uri.getQueryParameter("tracker");
guid = uri.getQueryParameter("guid");
@@ -155,7 +153,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
return;
}
} else if (uriHost.contains("coord.info")) {
- String uriPath = uri.getPath().toLowerCase(Locale.US);
+ final String uriPath = uri.getPath().toLowerCase(Locale.US);
if (uriPath != null && uriPath.startsWith("/tb")) {
geocode = uriPath.substring(1).toUpperCase(Locale.US);
guid = null;
@@ -186,57 +184,11 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
waitDialog = ProgressDialog.show(this, message, res.getString(R.string.trackable_details_loading), true, true);
createViewPager(0, null);
- LoadTrackableThread thread = new LoadTrackableThread(loadTrackableHandler, geocode, guid, id);
+ final LoadTrackableThread thread = new LoadTrackableThread(loadTrackableHandler, geocode, guid, id);
thread.start();
}
@Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) {
- super.onCreateContextMenu(menu, view, info);
- final int viewId = view.getId();
-
- if (viewId == R.id.author) { // Log item author
- contextMenuUser = ((TextView) view).getText().toString();
- } else { // Trackable owner, and user holding trackable now
- RelativeLayout itemLayout = (RelativeLayout) view.getParent();
- TextView itemName = (TextView) itemLayout.findViewById(R.id.name);
-
- String selectedName = itemName.getText().toString();
- if (selectedName.equals(res.getString(R.string.trackable_owner))) {
- contextMenuUser = trackable.getOwner();
- } else if (selectedName.equals(res.getString(R.string.trackable_spotted))) {
- contextMenuUser = trackable.getSpottedName();
- }
- }
-
- menu.setHeaderTitle(res.getString(R.string.user_menu_title) + " " + contextMenuUser);
- menu.add(viewId, 1, 0, res.getString(R.string.user_menu_view_hidden));
- menu.add(viewId, 2, 0, res.getString(R.string.user_menu_view_found));
- menu.add(viewId, 3, 0, res.getString(R.string.user_menu_open_browser));
- menu.add(viewId, 4, 0, res.getString(R.string.user_menu_send_message));
- }
-
- @Override
- public boolean onContextItemSelected(final MenuItem item) {
- switch (item.getItemId()) {
- case 1:
- cgeocaches.startActivityOwner(this, contextMenuUser);
- return true;
- case 2:
- cgeocaches.startActivityUserName(this, contextMenuUser);
- return true;
- case 3:
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(contextMenuUser))));
- return true;
- case 4:
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/email/?u=" + Network.encode(contextMenuUser))));
- return true;
- default:
- return false;
- }
- }
-
- @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.trackable_activity, menu);
return true;
@@ -280,29 +232,26 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
@Override
public void run() {
- trackable = cgData.loadTrackable(geocode);
-
- if ((trackable == null || trackable.isLoggable()) && !StringUtils.startsWithIgnoreCase(geocode, "GK")) {
- trackable = GCParser.searchTrackable(geocode, guid, id);
- }
- handler.sendMessage(Message.obtain());
- }
- }
-
- private class UserActionsListener implements View.OnClickListener {
-
- @Override
- public void onClick(View view) {
- if (view == null) {
- return;
+ if (StringUtils.isNotEmpty(geocode)) {
+ trackable = cgData.loadTrackable(geocode);
+
+ if (trackable == null || trackable.isLoggable()) {
+ // iterate over the connectors as some codes may be handled by multiple connectors
+ for (final TrackableConnector trackableConnector : ConnectorFactory.getTrackableConnectors()) {
+ if (trackableConnector.canHandleTrackable(geocode)) {
+ trackable = trackableConnector.searchTrackable(geocode, guid, id);
+ if (trackable != null) {
+ break;
+ }
+ }
+ }
+ }
}
-
- try {
- registerForContextMenu(view);
- openContextMenu(view);
- } catch (Exception e) {
- Log.e("TrackableActivity.UserActionsListener.onClick ", e);
+ // fall back to GC search by GUID
+ if (trackable == null) {
+ trackable = TravelBugConnector.getInstance().searchTrackable(geocode, guid, id);
}
+ handler.sendMessage(Message.obtain());
}
}
@@ -322,12 +271,12 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
try {
- HtmlImage imgGetter = new HtmlImage(trackable.getGeocode(), false, 0, false);
+ final HtmlImage imgGetter = new HtmlImage(trackable.getGeocode(), false, 0, false);
- BitmapDrawable image = imgGetter.getDrawable(url);
- Message message = handler.obtainMessage(0, image);
+ final BitmapDrawable image = imgGetter.getDrawable(url);
+ final Message message = handler.obtainMessage(0, image);
handler.sendMessage(message);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("TrackableActivity.TrackableIconThread.run: ", e);
}
}
@@ -365,7 +314,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
case DETAILS:
return new DetailsViewCreator();
case LOGS:
- return new LogsViewCreator();
+ return new TrackableLogsViewCreator(this, trackable);
default:
throw new IllegalArgumentException();
}
@@ -378,7 +327,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
@Override
protected Pair<List<? extends Page>, Integer> getOrderedPages() {
- List<Page> pages = new ArrayList<TrackableActivity.Page>();
+ final List<Page> pages = new ArrayList<TrackableActivity.Page>();
pages.add(Page.DETAILS);
if (!trackable.getLogs().isEmpty()) {
pages.add(Page.LOGS);
@@ -386,98 +335,6 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
return new ImmutablePair<List<? extends Page>, Integer>(pages, 0);
}
- public class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> {
-
- @Override
- public ListView getDispatchedView() {
- view = (ListView) getLayoutInflater().inflate(R.layout.trackable_logs_view, null);
-
- if (trackable != null && trackable.getLogs() != null) {
- view.setAdapter(new ArrayAdapter<LogEntry>(TrackableActivity.this, R.layout.logs_item, trackable.getLogs()) {
- @Override
- public View getView(int position, View convertView, android.view.ViewGroup parent) {
- View rowView = convertView;
- if (null == rowView) {
- rowView = getLayoutInflater().inflate(R.layout.logs_item, null);
- }
- LogViewHolder holder = (LogViewHolder) rowView.getTag();
- if (null == holder) {
- holder = new LogViewHolder(rowView);
- }
-
- final LogEntry log = getItem(position);
- fillViewHolder(holder, log);
- return rowView;
- }
- });
- }
- return view;
- }
-
- protected void fillViewHolder(LogViewHolder holder, final LogEntry log) {
- if (log.date > 0) {
- holder.date.setText(Formatter.formatShortDateVerbally(log.date));
- }
-
- holder.type.setText(log.type.getL10n());
- holder.author.setText(Html.fromHtml(log.author), TextView.BufferType.SPANNABLE);
-
- if (StringUtils.isBlank(log.cacheName)) {
- holder.countOrLocation.setVisibility(View.GONE);
- } else {
- holder.countOrLocation.setText(Html.fromHtml(log.cacheName));
- final String cacheGuid = log.cacheGuid;
- final String cacheName = log.cacheName;
- holder.countOrLocation.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View arg0) {
- CacheDetailActivity.startActivityGuid(TrackableActivity.this, cacheGuid, Html.fromHtml(cacheName).toString());
- }
- });
- }
-
- TextView logView = holder.text;
- logView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
-
- String logText = log.log;
- if (BaseUtils.containsHtml(logText)) {
- logText = log.getDisplayText();
- logView.setText(Html.fromHtml(logText, new HtmlImage(null, false, StoredList.TEMPORARY_LIST_ID, false), null), TextView.BufferType.SPANNABLE);
- }
- else {
- logView.setText(logText);
- }
-
- ImageView statusMarker = holder.marker;
- // colored marker
- int marker = log.type.markerId;
- if (marker != 0) {
- statusMarker.setVisibility(View.VISIBLE);
- statusMarker.setImageResource(marker);
- }
- else {
- statusMarker.setVisibility(View.GONE);
- }
-
- // images
- if (log.hasLogImages()) {
- holder.images.setText(log.getImageTitles());
- holder.images.setVisibility(View.VISIBLE);
- holder.images.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ImagesActivity.startActivityLogImages(TrackableActivity.this, trackable.getGeocode(), new ArrayList<Image>(log.getLogImages()));
- }
- });
- } else {
- holder.images.setVisibility(View.GONE);
- }
-
- holder.author.setOnClickListener(new UserActionsListener());
- }
-
- }
-
public class DetailsViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
@InjectView(R.id.goal_box) protected LinearLayout goalBox;
@@ -518,10 +375,10 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
details.add(R.string.trackable_code, trackable.getGeocode());
// trackable owner
- TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown));
+ final TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown));
if (StringUtils.isNotBlank(trackable.getOwner())) {
owner.setText(Html.fromHtml(trackable.getOwner()), TextView.BufferType.SPANNABLE);
- owner.setOnClickListener(new UserActionsListener());
+ owner.setOnClickListener(new UserActionsClickListener());
}
// trackable spotted
@@ -546,7 +403,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
// days since last spotting
if (showTimeSpan && trackable.getLogs() != null) {
- for (LogEntry log : trackable.getLogs()) {
+ for (final LogEntry log : trackable.getLogs()) {
if (log.type == LogType.RETRIEVED_IT || log.type == LogType.GRABBED_IT || log.type == LogType.DISCOVERED_IT || log.type == LogType.PLACED_IT) {
final int days = log.daysSinceLog();
text.append(" (").append(res.getQuantityString(R.plurals.days_ago, days, days)).append(')');
@@ -565,13 +422,13 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
});
} else if (Trackable.SPOTTED_USER == trackable.getSpottedType()) {
- spotted.setOnClickListener(new UserActionsListener());
+ spotted.setOnClickListener(new UserActionsClickListener());
}
}
// trackable origin
if (StringUtils.isNotBlank(trackable.getOrigin())) {
- TextView origin = details.add(R.string.trackable_origin, "");
+ final TextView origin = details.add(R.string.trackable_origin, "");
origin.setText(Html.fromHtml(trackable.getOrigin()), TextView.BufferType.SPANNABLE);
}
@@ -621,7 +478,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
@Override
public void handleMessage(Message message) {
- BitmapDrawable image = (BitmapDrawable) message.obj;
+ final BitmapDrawable image = (BitmapDrawable) message.obj;
if (image != null) {
trackableImage.setImageDrawable((BitmapDrawable) message.obj);
}
@@ -633,12 +490,12 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
@Override
public void run() {
try {
- HtmlImage imgGetter = new HtmlImage(geocode, true, 0, false);
+ final HtmlImage imgGetter = new HtmlImage(geocode, true, 0, false);
- BitmapDrawable image = imgGetter.getDrawable(trackable.getImage());
- Message message = handler.obtainMessage(0, image);
+ final BitmapDrawable image = imgGetter.getDrawable(trackable.getImage());
+ final Message message = handler.obtainMessage(0, image);
handler.sendMessage(message);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("TrackableActivity.DetailsViewCreator.ImageGetterThread: ", e);
}
}
diff --git a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
index e0c304a..0345633 100644
--- a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
@@ -208,6 +208,7 @@ public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends
pageOrder.add(null);
}
}
+ viewPagerAdapter.notifyDataSetChanged();
viewPager.setCurrentItem(startPageIndex, false);
}
@@ -233,15 +234,19 @@ public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends
final Pair<List<? extends Page>, Integer> pagesAndIndex = getOrderedPages();
pageOrder.addAll(pagesAndIndex.getLeft());
+ // Since we just added pages notifyDataSetChanged needs to be called before we possibly setCurrentItem below.
+ // But, calling it will reset current item and we won't be able to tell if we would have been out of bounds
+ final int currentItem = getCurrentItem();
+
+ // notify the adapter that the data has changed
+ viewPagerAdapter.notifyDataSetChanged();
+
// switch to details page, if we're out of bounds
final int defaultPage = pagesAndIndex.getRight();
- if (getCurrentItem() < 0 || getCurrentItem() >= viewPagerAdapter.getCount()) {
+ if (currentItem < 0 || currentItem >= viewPagerAdapter.getCount()) {
viewPager.setCurrentItem(defaultPage, false);
}
- // notify the adapter that the data has changed
- viewPagerAdapter.notifyDataSetChanged();
-
// notify the indicator that the data has changed
titleIndicator.notifyDataSetChanged();
}
diff --git a/main/src/cgeo/geocaching/apps/AbstractApp.java b/main/src/cgeo/geocaching/apps/AbstractApp.java
index ef56f87..4d7abde 100644
--- a/main/src/cgeo/geocaching/apps/AbstractApp.java
+++ b/main/src/cgeo/geocaching/apps/AbstractApp.java
@@ -5,6 +5,8 @@ import cgeo.geocaching.MainActivity;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.utils.ProcessUtils;
+import org.apache.commons.lang3.StringUtils;
+
import android.content.Intent;
public abstract class AbstractApp implements App {
@@ -26,7 +28,7 @@ public abstract class AbstractApp implements App {
@Override
public boolean isInstalled() {
- if (ProcessUtils.isInstalled(packageName)) {
+ if (StringUtils.isNotEmpty(packageName) && ProcessUtils.isLaunchable(packageName)) {
return true;
}
return MainActivity.isIntentAvailable(intent);
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
index 1019b0f..a3532a5 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
@@ -27,22 +27,28 @@ abstract class GoogleNavigationApp extends AbstractPointNavigationApp {
try {
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri
.parse("google.navigation:ll=" + coords.getLatitude() + ","
- + coords.getLongitude() + mode)));
+ + coords.getLongitude() + "&mode=" + mode)));
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.i("GoogleNavigationApp.navigate: No navigation application available.", e);
}
}
static class GoogleNavigationWalkingApp extends GoogleNavigationApp {
GoogleNavigationWalkingApp() {
- super(R.string.cache_menu_navigation_walk, "&mode=w");
+ super(R.string.cache_menu_navigation_walk, "w");
}
}
static class GoogleNavigationDrivingApp extends GoogleNavigationApp {
GoogleNavigationDrivingApp() {
- super(R.string.cache_menu_navigation_drive, "&mode=d");
+ super(R.string.cache_menu_navigation_drive, "d");
+ }
+ }
+
+ static class GoogleNavigationBikeApp extends GoogleNavigationApp {
+ GoogleNavigationBikeApp() {
+ super(R.string.cache_menu_navigation_bike, "b");
}
}
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
index 5545936..7316d4c 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
@@ -11,6 +11,7 @@ import cgeo.geocaching.apps.App;
import cgeo.geocaching.apps.cache.CacheBeaconApp;
import cgeo.geocaching.apps.cache.GccApp;
import cgeo.geocaching.apps.cache.WhereYouGoApp;
+import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationBikeApp;
import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationDrivingApp;
import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationWalkingApp;
import cgeo.geocaching.geopoint.Geopoint;
@@ -59,6 +60,10 @@ public final class NavigationAppFactory extends AbstractAppFactory {
*/
GOOGLE_NAVIGATION_WALK(new GoogleNavigationWalkingApp(), 12),
/**
+ * Google Navigation in walking mode
+ */
+ GOOGLE_NAVIGATION_BIKE(new GoogleNavigationBikeApp(), 21),
+ /**
* Google Maps Directions
*/
GOOGLE_MAPS_DIRECTIONS(new GoogleMapsDirectionApp(), 13),
@@ -134,7 +139,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
builder.setTitle(R.string.cache_menu_navigate);
final List<NavigationAppsEnum> items = new ArrayList<NavigationAppFactory.NavigationAppsEnum>();
final int defaultNavigationTool = Settings.getDefaultNavigationTool();
- for (NavigationAppsEnum navApp : getInstalledNavigationApps()) {
+ for (final NavigationAppsEnum navApp : getInstalledNavigationApps()) {
if ((showInternalMap || !(navApp.app instanceof InternalMap)) &&
(showDefaultNavigation || defaultNavigationTool != navApp.id)) {
boolean add = false;
@@ -161,8 +166,8 @@ public final class NavigationAppFactory extends AbstractAppFactory {
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
- NavigationAppsEnum selectedItem = adapter.getItem(item);
- App app = selectedItem.app;
+ final NavigationAppsEnum selectedItem = adapter.getItem(item);
+ final App app = selectedItem.app;
if (cache != null) {
navigateCache(activity, cache, app);
}
@@ -185,7 +190,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
*/
public static List<NavigationAppsEnum> getInstalledNavigationApps() {
final List<NavigationAppsEnum> installedNavigationApps = new ArrayList<NavigationAppsEnum>();
- for (NavigationAppsEnum appEnum : NavigationAppsEnum.values()) {
+ for (final NavigationAppsEnum appEnum : NavigationAppsEnum.values()) {
if (appEnum.app.isInstalled()) {
installedNavigationApps.add(appEnum);
}
@@ -200,7 +205,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
*/
public static List<NavigationAppsEnum> getInstalledDefaultNavigationApps() {
final List<NavigationAppsEnum> installedNavigationApps = new ArrayList<NavigationAppsEnum>();
- for (NavigationAppsEnum appEnum : NavigationAppsEnum.values()) {
+ for (final NavigationAppsEnum appEnum : NavigationAppsEnum.values()) {
if (appEnum.app.isInstalled() && appEnum.app.isDefaultNavigationApp()) {
installedNavigationApps.add(appEnum);
}
@@ -225,9 +230,9 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* @param menu
*/
public static void addMenuItems(final Menu menu, final Geocache cache) {
- for (NavigationAppsEnum navApp : getInstalledNavigationApps()) {
+ for (final NavigationAppsEnum navApp : getInstalledNavigationApps()) {
if (navApp.app instanceof CacheNavigationApp) {
- CacheNavigationApp cacheApp = (CacheNavigationApp) navApp.app;
+ final CacheNavigationApp cacheApp = (CacheNavigationApp) navApp.app;
if (cacheApp.isEnabled(cache)) {
menu.add(0, MENU_ITEM_OFFSET + navApp.id, 0, navApp.app.getName());
}
@@ -236,9 +241,9 @@ public final class NavigationAppFactory extends AbstractAppFactory {
}
public static void addMenuItems(final Menu menu, final Waypoint waypoint) {
- for (NavigationAppsEnum navApp : getInstalledNavigationApps()) {
+ for (final NavigationAppsEnum navApp : getInstalledNavigationApps()) {
if (navApp.app instanceof WaypointNavigationApp) {
- WaypointNavigationApp waypointApp = (WaypointNavigationApp) navApp.app;
+ final WaypointNavigationApp waypointApp = (WaypointNavigationApp) navApp.app;
if (waypointApp.isEnabled(waypoint)) {
menu.add(0, MENU_ITEM_OFFSET + navApp.id, 0, navApp.app.getName());
}
@@ -262,7 +267,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
private static void navigateCache(Activity activity, Geocache cache, App app) {
if (app instanceof CacheNavigationApp) {
- CacheNavigationApp cacheApp = (CacheNavigationApp) app;
+ final CacheNavigationApp cacheApp = (CacheNavigationApp) app;
cacheApp.navigate(activity, cache);
}
}
@@ -275,21 +280,21 @@ public final class NavigationAppFactory extends AbstractAppFactory {
private static void navigateWaypoint(Activity activity, Waypoint waypoint, App app) {
if (app instanceof WaypointNavigationApp) {
- WaypointNavigationApp waypointApp = (WaypointNavigationApp) app;
+ final WaypointNavigationApp waypointApp = (WaypointNavigationApp) app;
waypointApp.navigate(activity, waypoint);
}
}
private static void navigateGeopoint(Activity activity, Geopoint destination, App app) {
if (app instanceof GeopointNavigationApp) {
- GeopointNavigationApp geopointApp = (GeopointNavigationApp) app;
+ final GeopointNavigationApp geopointApp = (GeopointNavigationApp) app;
geopointApp.navigate(activity, destination);
}
}
private static App getAppFromMenuItem(MenuItem item) {
final int id = item.getItemId();
- for (NavigationAppsEnum navApp : NavigationAppsEnum.values()) {
+ for (final NavigationAppsEnum navApp : NavigationAppsEnum.values()) {
if (MENU_ITEM_OFFSET + navApp.id == id) {
return navApp.app;
}
@@ -362,7 +367,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
private static App getNavigationAppForId(final int navigationAppId) {
final List<NavigationAppsEnum> installedNavigationApps = getInstalledNavigationApps();
- for (NavigationAppsEnum navigationApp : installedNavigationApps) {
+ for (final NavigationAppsEnum navigationApp : installedNavigationApps) {
if (navigationApp.id == navigationAppId) {
return navigationApp.app;
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java b/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java
index 012b94f..e2c0828 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java
@@ -4,6 +4,7 @@ import cgeo.geocaching.R;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.utils.ProcessUtils;
import android.app.Activity;
import android.content.ActivityNotFoundException;
@@ -12,13 +13,16 @@ import android.net.Uri;
class StreetviewApp extends AbstractPointNavigationApp {
+ private static final String PACKAGE_NAME_STREET_VIEW = "com.google.android.street";
+ private static final boolean INSTALLED = ProcessUtils.isInstalled(PACKAGE_NAME_STREET_VIEW);
+
StreetviewApp() {
super(getString(R.string.cache_menu_streetview), null);
}
@Override
public boolean isInstalled() {
- return true;
+ return INSTALLED;
}
@Override
@@ -26,7 +30,7 @@ class StreetviewApp extends AbstractPointNavigationApp {
try {
activity.startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("google.streetview:cbll=" + point.getLatitude() + "," + point.getLongitude())));
- } catch (ActivityNotFoundException e) {
+ } catch (final ActivityNotFoundException e) {
ActivityMixin.showToast(activity, cgeoapplication.getInstance().getString(R.string.err_application_no));
}
}
diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java
index 2ef5b27..6f535dc 100644
--- a/main/src/cgeo/geocaching/cgData.java
+++ b/main/src/cgeo/geocaching/cgData.java
@@ -67,8 +67,8 @@ public class cgData {
"difficulty", "direction", "distance", "terrain", "latlon", "location", "elevation", "personal_note", "shortdesc",
// 24 25 26 27 28 29 30 31 32
"favourite_cnt", "rating", "votes", "myvote", "disabled", "archived", "members", "found", "favourite",
- // 33 34 35 36 37 38 39 40 41 42
- "inventoryunknown", "onWatchlist", "reliable_latlon", "coordsChanged", "latitude", "longitude", "finalDefined", "_id", "inventorycoins", "inventorytags"
+ // 33 34 35 36 37 38 39 40 41 42 43
+ "inventoryunknown", "onWatchlist", "reliable_latlon", "coordsChanged", "latitude", "longitude", "finalDefined", "_id", "inventorycoins", "inventorytags", "logPasswordRequired"
// reason is replaced by listId in Geocache
};
@@ -86,7 +86,7 @@ public class cgData {
private static int[] cacheColumnIndex;
private static CacheCache cacheCache = new CacheCache();
private static SQLiteDatabase database = null;
- private static final int dbVersion = 67;
+ private static final int dbVersion = 68;
public static final int customListIdOffset = 10;
private static final String dbName = "data";
private static final String dbTableCaches = "cg_caches";
@@ -146,6 +146,7 @@ public class cgData {
+ "onWatchlist integer default 0, "
+ "coordsChanged integer default 0, "
+ "finalDefined integer default 0"
+ + "logPasswordRequired integer default 0"
+ "); ";
private static final String dbCreateLists = ""
+ "create table " + dbTableLists + " ("
@@ -685,6 +686,15 @@ public class cgData {
}
}
+ // Introduces logPasswordRequired on caches
+ if (oldVersion < 68) {
+ try {
+ db.execSQL("alter table " + dbTableCaches + " add column logPasswordRequired integer default 0");
+ } catch (Exception e) {
+ Log.e("Failed to upgrade to ver. 68", e);
+
+ }
+ }
}
db.setTransactionSuccessful();
@@ -1052,6 +1062,7 @@ public class cgData {
values.put("onWatchlist", cache.isOnWatchlist() ? 1 : 0);
values.put("coordsChanged", cache.hasUserModifiedCoords() ? 1 : 0);
values.put("finalDefined", cache.hasFinalDefined() ? 1 : 0);
+ values.put("logPasswordRequired", cache.isLogPasswordRequired() ? 1 : 0);
init();
@@ -1643,6 +1654,7 @@ public class cgData {
cache.setReliableLatLon(cursor.getInt(cacheColumnIndex[35]) > 0);
cache.setUserModifiedCoords(cursor.getInt(cacheColumnIndex[36]) > 0);
cache.setFinalDefined(cursor.getInt(cacheColumnIndex[39]) > 0);
+ cache.setLogPasswordRequired(cursor.getInt(cacheColumnIndex[43]) > 0);
Log.d("Loading " + cache.toString() + " (" + cache.getListId() + ") from DB");
diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java
index 40dddd4..e321d59 100644
--- a/main/src/cgeo/geocaching/cgeocaches.java
+++ b/main/src/cgeo/geocaching/cgeocaches.java
@@ -177,7 +177,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
showFooterMoreCaches();
if (search != null && search.getError() == StatusCode.UNAPPROVED_LICENSE) {
- AlertDialog.Builder dialog = new AlertDialog.Builder(this);
+ final AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle(res.getString(R.string.license));
dialog.setMessage(res.getString(R.string.err_license));
dialog.setCancelable(true);
@@ -198,7 +198,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
});
- AlertDialog alert = dialog.create();
+ final AlertDialog alert = dialog.create();
alert.show();
} else if (search != null && search.getError() != null) {
showToast(res.getString(R.string.err_download_fail) + ' ' + search.getError().getErrorString(res) + '.');
@@ -211,7 +211,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
setAdapterCurrentCoordinates(false);
- } catch (Exception e) {
+ } catch (final Exception e) {
showToast(res.getString(R.string.err_detail_cache_find_any));
Log.e("cgeocaches.loadCachesHandler", e);
@@ -225,14 +225,14 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
try {
hideLoading();
showProgress(false);
- } catch (Exception e2) {
+ } catch (final Exception e2) {
Log.e("cgeocaches.loadCachesHandler.2", e2);
}
adapter.setSelectMode(false);
}
- private Handler loadCachesHandler = new LoadCachesHandler(this);
+ private final Handler loadCachesHandler = new LoadCachesHandler(this);
private static class LoadCachesHandler extends WeakReferenceHandler<cgeocaches> {
@@ -277,7 +277,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
protected void updateTitle() {
- ArrayList<Integer> numbers = new ArrayList<Integer>();
+ final ArrayList<Integer> numbers = new ArrayList<Integer>();
if (adapter.isFiltered()) {
numbers.add(adapter.getCount());
}
@@ -292,7 +292,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
}
- private Handler loadDetailsHandler = new Handler() {
+ private final Handler loadDetailsHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -303,8 +303,8 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
adapter.notifyDataSetChanged();
- int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000);
- int minutesRemaining = ((detailTotal - detailProgress) * secondsElapsed / ((detailProgress > 0) ? detailProgress : 1) / 60);
+ final int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000);
+ final int minutesRemaining = ((detailTotal - detailProgress) * secondsElapsed / ((detailProgress > 0) ? detailProgress : 1) / 60);
progress.setProgress(detailProgress);
if (minutesRemaining < 1) {
@@ -340,7 +340,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
/**
* TODO Possibly parts should be a Thread not a Handler
*/
- private Handler downloadFromWebHandler = new Handler() {
+ private final Handler downloadFromWebHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
setAdapter();
@@ -375,7 +375,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
}
};
- private Handler clearOfflineLogsHandler = new Handler() {
+ private final Handler clearOfflineLogsHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -391,7 +391,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
};
- private Handler importGpxAttachementFinishedHandler = new Handler() {
+ private final Handler importGpxAttachementFinishedHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
refreshCurrentList();
@@ -413,7 +413,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
// get parameters
Bundle extras = getIntent().getExtras();
if (extras != null) {
- Object typeObject = extras.get(Intents.EXTRA_LIST_TYPE);
+ final Object typeObject = extras.get(Intents.EXTRA_LIST_TYPE);
type = (typeObject instanceof CacheListType) ? (CacheListType) typeObject : CacheListType.OFFLINE;
coords = extras.getParcelable(Intents.EXTRA_COORDS);
}
@@ -478,24 +478,14 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
private void importGpxAttachement() {
- new AlertDialog.Builder(this)
- .setTitle(res.getString(R.string.gpx_import_title))
- .setMessage(res.getString(R.string.gpx_import_confirm))
- .setCancelable(false)
- .setPositiveButton(getString(android.R.string.yes), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- new GPXImporter(cgeocaches.this, listId, importGpxAttachementFinishedHandler).importGPX();
- }
- })
- .setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- })
- .create()
- .show();
+ new StoredList.UserInterface(this).promptForListSelection(R.string.gpx_import_select_list_title, new RunnableWithArgument<Integer>() {
+
+ @Override
+ public void run(Integer listId) {
+ new GPXImporter(cgeocaches.this, listId, importGpxAttachementFinishedHandler).importGPX();
+ switchListById(listId);
+ }
+ }, true, 0);
}
@Override
@@ -514,7 +504,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
// refresh standard list if it has changed (new caches downloaded)
if (type == CacheListType.OFFLINE && listId >= StoredList.STANDARD_LIST_ID && search != null) {
- SearchResult newSearch = cgData.getBatchOfStoredCaches(coords, Settings.getCacheType(), listId);
+ final SearchResult newSearch = cgData.getBatchOfStoredCaches(coords, Settings.getCacheType(), listId);
if (newSearch != null && newSearch.getTotal() != search.getTotal()) {
refreshCurrentList();
}
@@ -549,7 +539,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
menu.add(0, MENU_SWITCH_SELECT_MODE, 0, res.getString(R.string.caches_select_mode)).setIcon(R.drawable.ic_menu_agenda);
menu.add(0, MENU_INVERT_SELECTION, 0, res.getString(R.string.caches_select_invert)).setIcon(R.drawable.ic_menu_mark);
if (type == CacheListType.OFFLINE) {
- SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_OFFLINE, 0, res.getString(R.string.caches_manage)).setIcon(R.drawable.ic_menu_save);
+ final SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_OFFLINE, 0, res.getString(R.string.caches_manage)).setIcon(R.drawable.ic_menu_save);
subMenu.add(0, MENU_DROP_CACHES, 0, res.getString(R.string.caches_drop_all)); // delete saved caches
subMenu.add(0, MENU_DROP_CACHES_AND_LIST, 0, res.getString(R.string.caches_drop_all_and_list));
subMenu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.cache_offline_refresh)); // download details for all caches
@@ -566,7 +556,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
subMenu.add(0, MENU_EXPORT, 0, res.getString(R.string.export)); // export caches
} else {
if (type == CacheListType.HISTORY) {
- SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_HISTORY, 0, res.getString(R.string.caches_manage)).setIcon(R.drawable.ic_menu_save);
+ final SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_HISTORY, 0, res.getString(R.string.caches_manage)).setIcon(R.drawable.ic_menu_save);
subMenu.add(0, MENU_REMOVE_FROM_HISTORY, 0, res.getString(R.string.cache_clear_history)); // remove from history
subMenu.add(0, MENU_EXPORT, 0, res.getString(R.string.export)); // export caches
subMenu.add(0, MENU_CLEAR_OFFLINE_LOGS, 0, res.getString(R.string.caches_clear_offlinelogs));
@@ -579,7 +569,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
navigationMenu = CacheListAppFactory.addMenuItems(menu, this, res);
if (type == CacheListType.OFFLINE) {
- SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_LISTS, 0, res.getString(R.string.list_menu)).setIcon(R.drawable.ic_menu_more);
+ final SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_LISTS, 0, res.getString(R.string.list_menu)).setIcon(R.drawable.ic_menu_more);
subMenu.add(0, MENU_CREATE_LIST, 0, res.getString(R.string.list_menu_create));
subMenu.add(0, MENU_DROP_LIST, 0, res.getString(R.string.list_menu_drop));
subMenu.add(0, MENU_RENAME_LIST, 0, res.getString(R.string.list_menu_rename));
@@ -664,7 +654,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
setMenuItemLabel(menu, MENU_REMOVE_FROM_HISTORY, R.string.cache_remove_from_history, R.string.cache_clear_history);
setMenuItemLabel(menu, MENU_EXPORT, R.string.export, R.string.export);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("cgeocaches.onPrepareOptionsMenu", e);
}
@@ -672,7 +662,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
private boolean containsEvents() {
- for (Geocache cache : adapter.getCheckedOrAllCaches()) {
+ for (final Geocache cache : adapter.getCheckedOrAllCaches()) {
if (cache.isEventCache()) {
return true;
}
@@ -681,7 +671,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
private boolean containsOfflineLogs() {
- for (Geocache cache : adapter.getCheckedOrAllCaches()) {
+ for (final Geocache cache : adapter.getCheckedOrAllCaches()) {
if (cache.isLogOffline()) {
return true;
}
@@ -694,7 +684,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
if (menuItem == null) {
return;
}
- boolean hasSelection = adapter != null && adapter.getCheckedCount() > 0;
+ final boolean hasSelection = adapter != null && adapter.getCheckedCount() > 0;
if (hasSelection) {
menuItem.setTitle(res.getString(resIdSelection) + " (" + adapter.getCheckedCount() + ")");
} else {
@@ -704,7 +694,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- int itemId = item.getItemId();
+ final int itemId = item.getItemId();
switch (itemId) {
case MENU_SWITCH_SELECT_MODE:
adapter.switchSelectMode();
@@ -794,7 +784,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
public void deletePastEvents() {
final List<Geocache> deletion = new ArrayList<Geocache>();
- for (Geocache cache : adapter.getCheckedOrAllCaches()) {
+ for (final Geocache cache : adapter.getCheckedOrAllCaches()) {
if (cache.isEventCache()) {
final Date eventDate = cache.getHiddenDate();
if (DateUtils.daysSince(eventDate.getTime()) > 0) {
@@ -840,7 +830,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
AdapterContextMenuInfo adapterInfo = null;
try {
adapterInfo = (AdapterContextMenuInfo) info;
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("cgeocaches.onCreateContextMenu", e);
}
@@ -897,7 +887,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
AdapterContextMenuInfo adapterInfo = null;
try {
adapterInfo = (AdapterContextMenuInfo) info;
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("cgeocaches.onContextItemSelected", e);
}
@@ -1106,7 +1096,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
showProgress(false);
- int etaTime = ((detailTotal * 25) / 60);
+ final int etaTime = ((detailTotal * 25) / 60);
String message;
if (etaTime < 1) {
message = res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm);
@@ -1124,7 +1114,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
public void removeFromHistoryCheck() {
- AlertDialog.Builder dialog = new AlertDialog.Builder(this);
+ final AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setCancelable(true);
dialog.setTitle(res.getString(R.string.caches_removing_from_history));
dialog.setMessage((adapter != null && adapter.getCheckedCount() > 0) ? res.getString(R.string.cache_remove_from_history)
@@ -1143,7 +1133,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
});
- AlertDialog alert = dialog.create();
+ final AlertDialog alert = dialog.create();
alert.show();
}
@@ -1153,7 +1143,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
for (int i = 0; i < geocodes.length; i++) {
geocodes[i] = caches.get(i).getGeocode();
}
- Bundle b = new Bundle();
+ final Bundle b = new Bundle();
b.putStringArray(Intents.EXTRA_CACHELIST, geocodes);
getSupportLoaderManager().initLoader(CacheListLoaderType.REMOVE_FROM_HISTORY.ordinal(), b, this);
}
@@ -1169,7 +1159,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
public void dropStored(final boolean removeListAfterwards) {
- AlertDialog.Builder dialog = new AlertDialog.Builder(this);
+ final AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setCancelable(true);
dialog.setTitle(res.getString(R.string.caches_drop_stored));
@@ -1194,7 +1184,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
});
- AlertDialog alert = dialog.create();
+ final AlertDialog alert = dialog.create();
alert.show();
}
@@ -1232,7 +1222,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
removeGeoAndDir();
final List<Geocache> cachesWithStaticMaps = new ArrayList<Geocache>(this.caches.size());
- for (Geocache cache : this.caches) {
+ for (final Geocache cache : this.caches) {
if (Settings.isStoreOfflineMaps() && cache.hasStaticMap()) {
cachesWithStaticMaps.add(cache);
continue;
@@ -1244,7 +1234,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
}
- for (Geocache cache : cachesWithStaticMaps) {
+ for (final Geocache cache : cachesWithStaticMaps) {
if (!refreshCache(cache)) {
break;
}
@@ -1276,7 +1266,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
Log.i("Waiting for next cache " + delay + " ms");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("cgeocaches.LoadDetailsThread.sleep", e);
}
}
@@ -1291,10 +1281,10 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
handler.sendEmptyMessage(cacheList.indexOf(cache));
yield();
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
Log.i(e.getMessage());
return false;
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("cgeocaches.LoadDetailsThread", e);
}
@@ -1334,7 +1324,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
deviceCode = "";
}
final Parameters params = new Parameters("code", deviceCode);
- HttpResponse responseFromWeb = Network.getRequest("http://send2.cgeo.org/read.html", params);
+ final HttpResponse responseFromWeb = Network.getRequest("http://send2.cgeo.org/read.html", params);
if (responseFromWeb != null && responseFromWeb.getStatusLine().getStatusCode() == 200) {
final String response = Network.getResponseData(responseFromWeb);
@@ -1374,7 +1364,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
sleep(500); //Cache was loaded 0.5s
times = 0;
}
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
Log.e("cgeocaches.LoadFromWebThread.sleep", e);
}
}
@@ -1476,7 +1466,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
return;
}
- StoredList list = cgData.getList(id);
+ final StoredList list = cgData.getList(id);
if (list == null) {
return;
}
@@ -1565,8 +1555,8 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
// apply filter settings (if there's a filter)
- Set<String> geocodes = new HashSet<String>();
- for (Geocache cache : adapter.getFilteredList()) {
+ final Set<String> geocodes = new HashSet<String>();
+ for (final Geocache cache : adapter.getFilteredList()) {
geocodes.add(cache.getGeocode());
}
@@ -1641,7 +1631,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
private void setDateComparatorForEventList() {
if (CollectionUtils.isNotEmpty(cacheList)) {
boolean eventsOnly = true;
- for (Geocache cache : cacheList) {
+ for (final Geocache cache : cacheList) {
if (!cache.isEventCache()) {
eventsOnly = false;
break;
@@ -1726,7 +1716,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
if (type >= CacheListLoaderType.values().length) {
throw new IllegalArgumentException("invalid loader type " + type);
}
- CacheListLoaderType enumType = CacheListLoaderType.values()[type];
+ final CacheListLoaderType enumType = CacheListLoaderType.values()[type];
AbstractSearchLoader loader = null;
switch (enumType) {
case OFFLINE:
diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
index 3319fe4..c5a083c 100644
--- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java
+++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
@@ -4,6 +4,7 @@ import cgeo.geocaching.ICache;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Trackable;
+import cgeo.geocaching.connector.capability.ILogin;
import cgeo.geocaching.connector.capability.ISearchByCenter;
import cgeo.geocaching.connector.capability.ISearchByViewPort;
import cgeo.geocaching.connector.gc.GCConnector;
@@ -12,6 +13,10 @@ import cgeo.geocaching.connector.oc.OCApiConnector.ApiSupport;
import cgeo.geocaching.connector.oc.OCApiLiveConnector;
import cgeo.geocaching.connector.oc.OCConnector;
import cgeo.geocaching.connector.ox.OXConnector;
+import cgeo.geocaching.connector.trackable.GeokretyConnector;
+import cgeo.geocaching.connector.trackable.TrackableConnector;
+import cgeo.geocaching.connector.trackable.TravelBugConnector;
+import cgeo.geocaching.connector.trackable.UnknownTrackableConnector;
import cgeo.geocaching.geopoint.Viewport;
import org.apache.commons.lang3.StringUtils;
@@ -21,9 +26,9 @@ import java.util.List;
public final class ConnectorFactory {
private static final UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector();
- private static final IConnector[] connectors = new IConnector[] {
+ private static final IConnector[] CONNECTORS = new IConnector[] {
GCConnector.getInstance(),
- new OCApiLiveConnector("Opencaching.de", "www.opencaching.de", "OC", R.string.oc_de_okapi_consumer_key, R.string.oc_de_okapi_consumer_secret, ApiSupport.current),
+ new OCApiLiveConnector("opencaching.de", "www.opencaching.de", "OC", R.string.oc_de_okapi_consumer_key, R.string.oc_de_okapi_consumer_secret, ApiSupport.current),
new OCConnector("OpenCaching.CZ", "www.opencaching.cz", "OZ"),
new OCApiConnector("OpenCaching.CO.UK", "www.opencaching.org.uk", "OK", "arU4okouc4GEjMniE2fq", ApiSupport.oldapi),
new OCConnector("OpenCaching.ES", "www.opencachingspain.es", "OC"),
@@ -40,21 +45,28 @@ public final class ConnectorFactory {
UNKNOWN_CONNECTOR // the unknown connector MUST be the last one
};
+ public static final UnknownTrackableConnector UNKNOWN_TRACKABLE_CONNECTOR = new UnknownTrackableConnector();
+ private static final TrackableConnector[] TRACKABLE_CONNECTORS = 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
+ };
+
private static final ISearchByViewPort[] searchByViewPortConns;
private static final ISearchByCenter[] searchByCenterConns;
static {
- List<ISearchByViewPort> vpConns = new ArrayList<ISearchByViewPort>();
- for (IConnector conn : connectors) {
+ final List<ISearchByViewPort> vpConns = new ArrayList<ISearchByViewPort>();
+ for (final IConnector conn : CONNECTORS) {
if (conn instanceof ISearchByViewPort) {
vpConns.add((ISearchByViewPort) conn);
}
}
searchByViewPortConns = vpConns.toArray(new ISearchByViewPort[vpConns.size()]);
- List<ISearchByCenter> centerConns = new ArrayList<ISearchByCenter>();
- for (IConnector conn : connectors) {
+ final List<ISearchByCenter> centerConns = new ArrayList<ISearchByCenter>();
+ for (final IConnector conn : CONNECTORS) {
// GCConnector is handled specially, omit it here!
if (conn instanceof ISearchByCenter && !(conn instanceof GCConnector)) {
centerConns.add((ISearchByCenter) conn);
@@ -64,18 +76,28 @@ public final class ConnectorFactory {
}
public static IConnector[] getConnectors() {
- return connectors;
+ return CONNECTORS;
}
public static ISearchByCenter[] getSearchByCenterConnectors() {
return searchByCenterConns;
}
+ public static ILogin[] getActiveLiveConnectors() {
+ final List<ILogin> liveConns = new ArrayList<ILogin>();
+ for (final IConnector conn : CONNECTORS) {
+ if (conn instanceof ILogin && conn.isActivated()) {
+ liveConns.add((ILogin) conn);
+ }
+ }
+ return liveConns.toArray(new ILogin[liveConns.size()]);
+ }
+
public static boolean canHandle(final String geocode) {
if (isInvalidGeocode(geocode)) {
return false;
}
- for (IConnector connector : connectors) {
+ for (final IConnector connector : CONNECTORS) {
if (connector.canHandle(geocode)) {
return true;
}
@@ -87,8 +109,17 @@ public final class ConnectorFactory {
return getConnector(cache.getGeocode());
}
- public static IConnector getConnector(Trackable trackable) {
- return getConnector(trackable.getGeocode());
+ public static TrackableConnector getConnector(Trackable trackable) {
+ return getTrackableConnector(trackable.getGeocode());
+ }
+
+ public static TrackableConnector getTrackableConnector(String geocode) {
+ for (final TrackableConnector connector : TRACKABLE_CONNECTORS) {
+ if (connector.canHandleTrackable(geocode)) {
+ return connector;
+ }
+ }
+ return UNKNOWN_TRACKABLE_CONNECTOR; // avoid null checks by returning a non implementing connector
}
public static IConnector getConnector(final String geocodeInput) {
@@ -97,12 +128,12 @@ public final class ConnectorFactory {
if (isInvalidGeocode(geocode)) {
return UNKNOWN_CONNECTOR;
}
- for (IConnector connector : connectors) {
+ for (final IConnector connector : CONNECTORS) {
if (connector.canHandle(geocode)) {
return connector;
}
}
- // in case of errors, take UNKNOWN
+ // in case of errors, take UNKNOWN to avoid null checks everywhere
return UNKNOWN_CONNECTOR;
}
@@ -113,10 +144,10 @@ public final class ConnectorFactory {
/** @see ISearchByViewPort#searchByViewport */
public static SearchResult searchByViewport(final Viewport viewport, final String[] tokens) {
- SearchResult result = new SearchResult();
- for (ISearchByViewPort vpconn : searchByViewPortConns) {
+ final SearchResult result = new SearchResult();
+ for (final ISearchByViewPort vpconn : searchByViewPortConns) {
if (vpconn.isActivated()) {
- SearchResult temp = vpconn.searchByViewport(viewport, tokens);
+ final SearchResult temp = vpconn.searchByViewport(viewport, tokens);
if (temp != null) {
result.addGeocodes(temp.getGeocodes());
}
@@ -126,8 +157,8 @@ public final class ConnectorFactory {
}
public static String getGeocodeFromURL(final String url) {
- for (IConnector connector : connectors) {
- String geocode = connector.getGeocodeFromUrl(url);
+ for (final IConnector connector : CONNECTORS) {
+ final String geocode = connector.getGeocodeFromUrl(url);
if (StringUtils.isNotBlank(geocode)) {
return geocode;
}
@@ -135,4 +166,8 @@ public final class ConnectorFactory {
return null;
}
+ public static TrackableConnector[] getTrackableConnectors() {
+ return TRACKABLE_CONNECTORS;
+ }
+
}
diff --git a/main/src/cgeo/geocaching/connector/ILoggingManager.java b/main/src/cgeo/geocaching/connector/ILoggingManager.java
index f0029f9..c5586b3 100644
--- a/main/src/cgeo/geocaching/connector/ILoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/ILoggingManager.java
@@ -11,10 +11,23 @@ import java.util.List;
public interface ILoggingManager {
+ /**
+ * Post a log for a cache online
+ *
+ * @param cache
+ * @param logType
+ * @param date
+ * @param log
+ * @param logPassword
+ * optional, maybe null
+ * @param trackableLogs
+ * @return
+ */
LogResult postLog(Geocache cache,
LogType logType,
Calendar date,
String log,
+ String logPassword,
List<TrackableLog> trackableLogs);
ImageResult postLogImage(String logId,
diff --git a/main/src/cgeo/geocaching/connector/NoLoggingManager.java b/main/src/cgeo/geocaching/connector/NoLoggingManager.java
index bfea4ca..04a73c1 100644
--- a/main/src/cgeo/geocaching/connector/NoLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/NoLoggingManager.java
@@ -19,7 +19,7 @@ public class NoLoggingManager implements ILoggingManager {
}
@Override
- public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, List<TrackableLog> trackableLogs) {
+ public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, String logPassword, List<TrackableLog> trackableLogs) {
return new LogResult(StatusCode.LOG_POST_ERROR, "");
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ILogin.java b/main/src/cgeo/geocaching/connector/capability/ILogin.java
new file mode 100644
index 0000000..4a839c8
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/capability/ILogin.java
@@ -0,0 +1,57 @@
+package cgeo.geocaching.connector.capability;
+
+import cgeo.geocaching.connector.IConnector;
+
+import android.content.Context;
+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.
+ *
+ * @param handler
+ * Handler to receive status feedback
+ * @param fromActivity
+ * Calling activity context
+ * @return true in case of success, false in case of failure
+ */
+ boolean login(Handler handler, Context fromActivity);
+
+ /**
+ * Returns the status of the last {@link}login() request
+ *
+ * @return
+ */
+ boolean isLoggedIn();
+
+ /**
+ * User-centered string describing the current login/connection status
+ *
+ * @return
+ */
+ 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.
+ *
+ * @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.
+ *
+ * @return
+ */
+ int getCachesFound();
+
+}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index 9b2a84a..33bb1ce 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -5,9 +5,12 @@ import cgeo.geocaching.ICache;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
+import cgeo.geocaching.SettingsActivity;
import cgeo.geocaching.cgData;
+import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.AbstractConnector;
import cgeo.geocaching.connector.ILoggingManager;
+import cgeo.geocaching.connector.capability.ILogin;
import cgeo.geocaching.connector.capability.ISearchByCenter;
import cgeo.geocaching.connector.capability.ISearchByGeocode;
import cgeo.geocaching.connector.capability.ISearchByViewPort;
@@ -21,10 +24,12 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
+import android.content.Context;
+import android.os.Handler;
import java.util.regex.Pattern;
-public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort {
+public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort, ILogin {
private static final String CACHE_URL_SHORT = "http://coord.info/";
// Double slash is used to force open in browser
@@ -35,6 +40,11 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
*/
private static final Pattern gpxZipFilePattern = Pattern.compile("((\\d{7,})|(pocketquery))" + "(_.+)?" + "\\.zip", Pattern.CASE_INSENSITIVE);
+ /**
+ * Pattern for GC codes
+ */
+ private final static Pattern PATTERN_GC_CODE = Pattern.compile("GC[0-9A-Z]+", Pattern.CASE_INSENSITIVE);
+
private GCConnector() {
// singleton
}
@@ -55,7 +65,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
if (geocode == null) {
return false;
}
- return GCConstants.PATTERN_GC_CODE.matcher(geocode).matches() || GCConstants.PATTERN_TB_CODE.matcher(geocode).matches();
+ return GCConnector.PATTERN_GC_CODE.matcher(geocode).matches();
}
@Override
@@ -105,7 +115,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
@Override
public String getName() {
- return "GeoCaching.com";
+ return "geocaching.com";
}
@Override
@@ -282,4 +292,46 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
return R.drawable.marker;
}
+
+ @Override
+ public boolean login(Handler handler, Context fromActivity) {
+ // login
+ final StatusCode status = Login.login();
+
+ if (status == StatusCode.NO_ERROR) {
+ cgeoapplication.getInstance().firstRun = false;
+ Login.detectGcCustomDate();
+ }
+
+ if (cgeoapplication.getInstance().showLoginToast && handler != null) {
+ handler.sendMessage(handler.obtainMessage(0, status));
+ cgeoapplication.getInstance().showLoginToast = false;
+
+ // invoke settings activity to insert login details
+ if (status == StatusCode.NO_LOGIN_INFO_STORED && fromActivity != null) {
+ SettingsActivity.startActivity(fromActivity);
+ }
+ }
+ return status == StatusCode.NO_ERROR;
+ }
+
+ @Override
+ public String getUserName() {
+ return Login.getActualUserName();
+ }
+
+ @Override
+ public int getCachesFound() {
+ return Login.getActualCachesFound();
+ }
+
+ @Override
+ public String getLoginStatusString() {
+ return Login.getActualStatus();
+ }
+
+ @Override
+ public boolean isLoggedIn() {
+ return Login.isActualLoginStatus();
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
index b4f5845..f2e2e69 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
@@ -84,6 +84,7 @@ public final class GCConstants {
public final static String ERROR_TB_DOES_NOT_EXIST = "does not exist in the system";
public final static String ERROR_TB_ELEMENT_EXCEPTION = "ElementNotFound Exception";
public final static String ERROR_TB_ARITHMETIC_OVERFLOW = "operation resulted in an overflow";
+ public final static String ERROR_TB_NOT_ACTIVATED = "hasn't been activated";
/**
* some parts of the webpage don't correctly encode the name, therefore this pattern must be checked with a
* trackable name that needs HTML encoding
@@ -157,12 +158,6 @@ public final class GCConstants {
public final static Pattern PATTERN_VIEWSTATES = Pattern.compile("id=\"__VIEWSTATE(\\d*)\"[^(value)]+value=\"([^\"]+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
public final static Pattern PATTERN_USERTOKEN = Pattern.compile("userToken\\s*=\\s*'([^']+)'");
- /**
- * Patterns for GC and TB codes
- */
- public final static Pattern PATTERN_GC_CODE = Pattern.compile("GC[0-9A-Z]+", Pattern.CASE_INSENSITIVE);
- public final static Pattern PATTERN_TB_CODE = Pattern.compile("TB[0-9A-Z]+", Pattern.CASE_INSENSITIVE);
-
/** Live Map since 14.02.2012 */
public final static Pattern PATTERN_USERSESSION = Pattern.compile("UserSession\\('([^']+)'");
public final static Pattern PATTERN_SESSIONTOKEN = Pattern.compile("sessionToken:'([^']+)'");
@@ -194,7 +189,7 @@ public final class GCConstants {
*/
public static long gccodeToGCId(final String gccode) {
long base = GC_BASE31;
- String geocodeWO = gccode.substring(2).toUpperCase(Locale.US);
+ final String geocodeWO = gccode.substring(2).toUpperCase(Locale.US);
if ((geocodeWO.length() < 4) || (geocodeWO.length() == 4 && SEQUENCE_GCID.indexOf(geocodeWO.charAt(0)) < 16)) {
base = GC_BASE16;
diff --git a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
index 4f2f8c4..dd150de 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
@@ -1,10 +1,10 @@
package cgeo.geocaching.connector.gc;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.LogCacheActivity;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
import cgeo.geocaching.TrackableLog;
-import cgeo.geocaching.LogCacheActivity;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.ImageResult;
@@ -80,7 +80,7 @@ public class GCLoggingManager implements ILoggingManager, LoaderManager.LoaderCa
}
@Override
- public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, List<TrackableLog> trackableLogs) {
+ public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, String logPassword, List<TrackableLog> trackableLogs) {
try {
final ImmutablePair<StatusCode, String> postResult = GCParser.postLog(cache.getGeocode(), cache.getCacheId(), viewstates, logType,
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index 15958ba..3e26eb2 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -28,10 +28,10 @@ import cgeo.geocaching.loaders.RecaptchaReceiver;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.ui.DirectionImage;
-import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
+import cgeo.geocaching.utils.TextUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
@@ -79,14 +79,14 @@ public abstract class GCParser {
// recaptcha
String recaptchaChallenge = null;
if (showCaptcha) {
- String recaptchaJsParam = BaseUtils.getMatch(page, GCConstants.PATTERN_SEARCH_RECAPTCHA, false, null);
+ final String recaptchaJsParam = TextUtils.getMatch(page, GCConstants.PATTERN_SEARCH_RECAPTCHA, false, null);
if (recaptchaJsParam != null) {
final Parameters params = new Parameters("k", recaptchaJsParam.trim());
final String recaptchaJs = Network.getResponseData(Network.getRequest("http://www.google.com/recaptcha/api/challenge", params));
if (StringUtils.isNotBlank(recaptchaJs)) {
- recaptchaChallenge = BaseUtils.getMatch(recaptchaJs, GCConstants.PATTERN_SEARCH_RECAPTCHACHALLENGE, true, 1, null, true);
+ recaptchaChallenge = TextUtils.getMatch(recaptchaJs, GCConstants.PATTERN_SEARCH_RECAPTCHACHALLENGE, true, 1, null, true);
}
}
if (thread != null && StringUtils.isNotBlank(recaptchaChallenge)) {
@@ -109,7 +109,7 @@ public abstract class GCParser {
page = page.substring(startPos); // cut on <table
startPos = page.indexOf('>');
- int endPos = page.indexOf("ctl00_ContentBody_UnitTxt");
+ final int endPos = page.indexOf("ctl00_ContentBody_UnitTxt");
if (startPos == -1 || endPos == -1) {
Log.e("GCParser.parseSearch: ID \"ctl00_ContentBody_UnitTxt\" not found on page");
return null;
@@ -122,7 +122,7 @@ public abstract class GCParser {
for (int z = 1; z < rows_count; z++) {
final Geocache cache = new Geocache();
- String row = rows[z];
+ final String row = rows[z];
// check for cache type presence
if (!row.contains("images/wpttypes")) {
@@ -150,7 +150,7 @@ public abstract class GCParser {
}
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// failed to parse GUID and/or Disabled
Log.w("GCParser.parseSearch: Failed to parse GUID and/or Disabled data");
}
@@ -160,21 +160,21 @@ public abstract class GCParser {
continue;
}
- cache.setGeocode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_GEOCODE, true, 1, cache.getGeocode(), true));
+ cache.setGeocode(TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_GEOCODE, true, 1, cache.getGeocode(), true));
// cache type
- cache.setType(CacheType.getByPattern(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_TYPE, true, 1, null, true)));
+ cache.setType(CacheType.getByPattern(TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_TYPE, true, 1, null, true)));
// cache direction - image
if (Settings.getLoadDirImg()) {
- final String direction = BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION_DISTANCE, false, 1, null, false);
+ final String direction = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION_DISTANCE, false, 1, null, false);
if (direction != null) {
cache.setDirectionImg(direction);
}
}
// cache distance - estimated distance for basic members
- final String distance = BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION_DISTANCE, false, 2, null, false);
+ final String distance = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION_DISTANCE, false, 2, null, false);
if (distance != null) {
cache.setDistance(DistanceParser.parseDistance(distance, Settings.isUseMetricUnits()));
}
@@ -193,7 +193,7 @@ public abstract class GCParser {
}
// size
- final String container = BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_CONTAINER, false, 1, null, false);
+ final String container = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_CONTAINER, false, 1, null, false);
cache.setSize(CacheSize.getById(container));
// cache inventory
@@ -203,7 +203,7 @@ public abstract class GCParser {
if (matcherTbs.groupCount() > 0) {
try {
cache.setInventoryItems(Integer.parseInt(matcherTbs.group(1)));
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.e("Error parsing trackables count", e);
}
inventoryPre = matcherTbs.group(2);
@@ -229,7 +229,7 @@ public abstract class GCParser {
cache.setFound(row.contains("/images/icons/16/found.png"));
// id
- String result = BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_ID, null);
+ String result = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_ID, null);
if (null != result) {
cache.setCacheId(result);
cids.add(cache.getCacheId());
@@ -237,11 +237,11 @@ public abstract class GCParser {
// favorite count
try {
- result = BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_FAVORITE, false, 1, null, true);
+ result = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_FAVORITE, false, 1, null, true);
if (null != result) {
cache.setFavoritePoints(Integer.parseInt(result));
}
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.w("GCParser.parseSearch: Failed to parse favorite count");
}
@@ -250,11 +250,11 @@ public abstract class GCParser {
// total caches found
try {
- String result = BaseUtils.getMatch(page, GCConstants.PATTERN_SEARCH_TOTALCOUNT, false, 1, null, true);
+ final String result = TextUtils.getMatch(page, GCConstants.PATTERN_SEARCH_TOTALCOUNT, false, 1, null, true);
if (null != result) {
searchResult.setTotal(Integer.parseInt(result));
}
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.w("GCParser.parseSearch: Failed to parse cache count");
}
@@ -284,7 +284,7 @@ public abstract class GCParser {
params.put("__VIEWSTATEFIELDCOUNT", String.valueOf(searchResult.viewstates.length));
}
}
- for (String cid : cids) {
+ for (final String cid : cids) {
params.put("CID", cid);
}
@@ -308,7 +308,7 @@ public abstract class GCParser {
LocParser.parseLoc(searchResult, coordinates);
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("GCParser.parseSearch.CIDs", e);
}
}
@@ -316,7 +316,7 @@ public abstract class GCParser {
// get direction images
if (Settings.getLoadDirImg()) {
final Set<Geocache> caches = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
- for (Geocache cache : caches) {
+ for (final Geocache cache : caches) {
if (cache.getCoords() == null && StringUtils.isNotEmpty(cache.getDirectionImg())) {
DirectionImage.getDrawable(cache.getDirectionImg());
}
@@ -327,7 +327,7 @@ public abstract class GCParser {
}
private static Float parseStars(final String value) {
- float floatValue = Float.parseFloat(StringUtils.replaceChars(value, ',', '.'));
+ final float floatValue = Float.parseFloat(StringUtils.replaceChars(value, ',', '.'));
return floatValue >= 0.5 && floatValue <= 5.0 ? floatValue : null;
}
@@ -374,7 +374,7 @@ public abstract class GCParser {
return searchResult;
}
- final String cacheName = Html.fromHtml(BaseUtils.getMatch(page, GCConstants.PATTERN_NAME, true, "")).toString();
+ final String cacheName = Html.fromHtml(TextUtils.getMatch(page, GCConstants.PATTERN_NAME, true, "")).toString();
if (GCConstants.STRING_UNKNOWN_ERROR.equalsIgnoreCase(cacheName)) {
searchResult.setError(StatusCode.UNKNOWN_ERROR);
return searchResult;
@@ -385,30 +385,30 @@ public abstract class GCParser {
cache.setArchived(page.contains(GCConstants.STRING_ARCHIVED));
- cache.setPremiumMembersOnly(BaseUtils.matches(page, GCConstants.PATTERN_PREMIUMMEMBERS));
+ cache.setPremiumMembersOnly(TextUtils.matches(page, GCConstants.PATTERN_PREMIUMMEMBERS));
- cache.setFavorite(BaseUtils.matches(page, GCConstants.PATTERN_FAVORITE));
+ cache.setFavorite(TextUtils.matches(page, GCConstants.PATTERN_FAVORITE));
// cache geocode
- cache.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_GEOCODE, true, cache.getGeocode()));
+ cache.setGeocode(TextUtils.getMatch(page, GCConstants.PATTERN_GEOCODE, true, cache.getGeocode()));
// cache id
- cache.setCacheId(BaseUtils.getMatch(page, GCConstants.PATTERN_CACHEID, true, cache.getCacheId()));
+ cache.setCacheId(TextUtils.getMatch(page, GCConstants.PATTERN_CACHEID, true, cache.getCacheId()));
// cache guid
- cache.setGuid(BaseUtils.getMatch(page, GCConstants.PATTERN_GUID, true, cache.getGuid()));
+ cache.setGuid(TextUtils.getMatch(page, GCConstants.PATTERN_GUID, true, cache.getGuid()));
// name
cache.setName(cacheName);
// owner real name
- cache.setOwnerUserId(Network.decode(BaseUtils.getMatch(page, GCConstants.PATTERN_OWNER_USERID, true, cache.getOwnerUserId())));
+ cache.setOwnerUserId(Network.decode(TextUtils.getMatch(page, GCConstants.PATTERN_OWNER_USERID, true, cache.getOwnerUserId())));
cache.setUserModifiedCoords(false);
String tableInside = page;
- int pos = tableInside.indexOf(GCConstants.STRING_CACHEDETAILS);
+ final int pos = tableInside.indexOf(GCConstants.STRING_CACHEDETAILS);
if (pos == -1) {
Log.e("GCParser.parseCache: ID \"cacheDetails\" not found on page");
return null;
@@ -418,96 +418,96 @@ public abstract class GCParser {
if (StringUtils.isNotBlank(tableInside)) {
// cache terrain
- String result = BaseUtils.getMatch(tableInside, GCConstants.PATTERN_TERRAIN, true, null);
+ String result = TextUtils.getMatch(tableInside, GCConstants.PATTERN_TERRAIN, true, null);
if (result != null) {
try {
cache.setTerrain(Float.parseFloat(StringUtils.replaceChars(result, '_', '.')));
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.e("Error parsing terrain value", e);
}
}
// cache difficulty
- result = BaseUtils.getMatch(tableInside, GCConstants.PATTERN_DIFFICULTY, true, null);
+ result = TextUtils.getMatch(tableInside, GCConstants.PATTERN_DIFFICULTY, true, null);
if (result != null) {
try {
cache.setDifficulty(Float.parseFloat(StringUtils.replaceChars(result, '_', '.')));
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.e("Error parsing difficulty value", e);
}
}
// owner
- cache.setOwnerDisplayName(StringEscapeUtils.unescapeHtml4(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_OWNER_DISPLAYNAME, true, cache.getOwnerDisplayName())));
+ cache.setOwnerDisplayName(StringEscapeUtils.unescapeHtml4(TextUtils.getMatch(tableInside, GCConstants.PATTERN_OWNER_DISPLAYNAME, true, cache.getOwnerDisplayName())));
// hidden
try {
- String hiddenString = BaseUtils.getMatch(tableInside, GCConstants.PATTERN_HIDDEN, true, null);
+ String hiddenString = TextUtils.getMatch(tableInside, GCConstants.PATTERN_HIDDEN, true, null);
if (StringUtils.isNotBlank(hiddenString)) {
cache.setHidden(Login.parseGcCustomDate(hiddenString));
}
if (cache.getHiddenDate() == null) {
// event date
- hiddenString = BaseUtils.getMatch(tableInside, GCConstants.PATTERN_HIDDENEVENT, true, null);
+ hiddenString = TextUtils.getMatch(tableInside, GCConstants.PATTERN_HIDDENEVENT, true, null);
if (StringUtils.isNotBlank(hiddenString)) {
cache.setHidden(Login.parseGcCustomDate(hiddenString));
}
}
- } catch (ParseException e) {
+ } catch (final ParseException e) {
// failed to parse cache hidden date
Log.w("GCParser.parseCache: Failed to parse cache hidden (event) date");
}
// favorite
try {
- cache.setFavoritePoints(Integer.parseInt(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_FAVORITECOUNT, true, "0")));
- } catch (NumberFormatException e) {
+ cache.setFavoritePoints(Integer.parseInt(TextUtils.getMatch(tableInside, GCConstants.PATTERN_FAVORITECOUNT, true, "0")));
+ } catch (final NumberFormatException e) {
Log.e("Error parsing favorite count", e);
}
// cache size
- cache.setSize(CacheSize.getById(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_SIZE, true, CacheSize.NOT_CHOSEN.id)));
+ cache.setSize(CacheSize.getById(TextUtils.getMatch(tableInside, GCConstants.PATTERN_SIZE, true, CacheSize.NOT_CHOSEN.id)));
}
// cache found
- cache.setFound(BaseUtils.matches(page, GCConstants.PATTERN_FOUND) || BaseUtils.matches(page, GCConstants.PATTERN_FOUND_ALTERNATIVE));
+ cache.setFound(TextUtils.matches(page, GCConstants.PATTERN_FOUND) || TextUtils.matches(page, GCConstants.PATTERN_FOUND_ALTERNATIVE));
// cache found date
try {
- final String foundDateString = BaseUtils.getMatch(page, GCConstants.PATTERN_FOUND_DATE, true, null);
+ final String foundDateString = TextUtils.getMatch(page, GCConstants.PATTERN_FOUND_DATE, true, null);
if (StringUtils.isNotBlank(foundDateString)) {
cache.setVisitedDate(Login.parseGcCustomDate(foundDateString).getTime());
}
- } catch (ParseException e) {
+ } catch (final ParseException e) {
// failed to parse cache found date
Log.w("GCParser.parseCache: Failed to parse cache found date");
}
// cache type
- cache.setType(CacheType.getByPattern(BaseUtils.getMatch(page, GCConstants.PATTERN_TYPE, true, cache.getType().id)));
+ cache.setType(CacheType.getByPattern(TextUtils.getMatch(page, GCConstants.PATTERN_TYPE, true, cache.getType().id)));
// on watchlist
- cache.setOnWatchlist(BaseUtils.matches(page, GCConstants.PATTERN_WATCHLIST));
+ cache.setOnWatchlist(TextUtils.matches(page, GCConstants.PATTERN_WATCHLIST));
// latitude and longitude. Can only be retrieved if user is logged in
- String latlon = BaseUtils.getMatch(page, GCConstants.PATTERN_LATLON, true, "");
+ String latlon = TextUtils.getMatch(page, GCConstants.PATTERN_LATLON, true, "");
if (StringUtils.isNotEmpty(latlon)) {
try {
cache.setCoords(new Geopoint(latlon));
cache.setReliableLatLon(true);
- } catch (Geopoint.GeopointException e) {
+ } catch (final Geopoint.GeopointException e) {
Log.w("GCParser.parseCache: Failed to parse cache coordinates", e);
}
}
// cache location
- cache.setLocation(BaseUtils.getMatch(page, GCConstants.PATTERN_LOCATION, true, ""));
+ cache.setLocation(TextUtils.getMatch(page, GCConstants.PATTERN_LOCATION, true, ""));
// cache hint
- String result = BaseUtils.getMatch(page, GCConstants.PATTERN_HINT, false, null);
+ final String result = TextUtils.getMatch(page, GCConstants.PATTERN_HINT, false, null);
if (result != null) {
// replace linebreak and paragraph tags
- String hint = GCConstants.PATTERN_LINEBREAK.matcher(result).replaceAll("\n");
+ final String hint = GCConstants.PATTERN_LINEBREAK.matcher(result).replaceAll("\n");
if (hint != null) {
cache.setHint(StringUtils.replace(hint, "</p>", "").trim());
}
@@ -516,17 +516,17 @@ public abstract class GCParser {
cache.checkFields();
// cache personal note
- cache.setPersonalNote(BaseUtils.getMatch(page, GCConstants.PATTERN_PERSONALNOTE, true, cache.getPersonalNote()));
+ cache.setPersonalNote(TextUtils.getMatch(page, GCConstants.PATTERN_PERSONALNOTE, true, cache.getPersonalNote()));
// cache short description
- cache.setShortDescription(BaseUtils.getMatch(page, GCConstants.PATTERN_SHORTDESC, true, ""));
+ cache.setShortDescription(TextUtils.getMatch(page, GCConstants.PATTERN_SHORTDESC, true, ""));
// cache description
- cache.setDescription(BaseUtils.getMatch(page, GCConstants.PATTERN_DESC, true, ""));
+ cache.setDescription(TextUtils.getMatch(page, GCConstants.PATTERN_DESC, true, ""));
// cache attributes
try {
- final String attributesPre = BaseUtils.getMatch(page, GCConstants.PATTERN_ATTRIBUTES, true, null);
+ final String attributesPre = TextUtils.getMatch(page, GCConstants.PATTERN_ATTRIBUTES, true, null);
if (null != attributesPre) {
final MatcherWrapper matcherAttributesInside = new MatcherWrapper(GCConstants.PATTERN_ATTRIBUTESINSIDE, attributesPre);
@@ -539,8 +539,8 @@ public abstract class GCParser {
// if the image name can be recognized, use the image name as attribute
final String imageName = matcherAttributesInside.group(1).trim();
if (StringUtils.isNotEmpty(imageName)) {
- int start = imageName.lastIndexOf('/');
- int end = imageName.lastIndexOf('.');
+ final int start = imageName.lastIndexOf('/');
+ final int end = imageName.lastIndexOf('.');
if (start >= 0 && end >= 0) {
attribute = imageName.substring(start + 1, end).replace('-', '_').toLowerCase(Locale.US);
}
@@ -550,7 +550,7 @@ public abstract class GCParser {
}
cache.setAttributes(attributes);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// failed to parse cache attributes
Log.w("GCParser.parseCache: Failed to parse cache attributes");
}
@@ -567,7 +567,7 @@ public abstract class GCParser {
while (matcherSpoilersInside.find()) {
// the original spoiler URL (include .../display/... contains a low-resolution image
// if we shorten the URL we get the original-resolution image
- String url = matcherSpoilersInside.group(1).replace("/display", "");
+ final String url = matcherSpoilersInside.group(1).replace("/display", "");
String title = null;
if (matcherSpoilersInside.group(3) != null) {
@@ -579,7 +579,7 @@ public abstract class GCParser {
}
cache.addSpoiler(new Image(url, title, description));
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// failed to parse cache spoilers
Log.w("GCParser.parseCache: Failed to parse cache spoilers");
}
@@ -613,20 +613,20 @@ public abstract class GCParser {
}
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// failed to parse cache inventory
Log.w("GCParser.parseCache: Failed to parse cache inventory (2)");
}
// cache logs counts
try {
- final String countlogs = BaseUtils.getMatch(page, GCConstants.PATTERN_COUNTLOGS, true, null);
+ final String countlogs = TextUtils.getMatch(page, GCConstants.PATTERN_COUNTLOGS, true, null);
if (null != countlogs) {
final MatcherWrapper matcherLog = new MatcherWrapper(GCConstants.PATTERN_COUNTLOG, countlogs);
while (matcherLog.find()) {
- String typeStr = matcherLog.group(1);
- String countStr = matcherLog.group(2).replaceAll("[.,]", "");
+ final String typeStr = matcherLog.group(1);
+ final String countStr = matcherLog.group(2).replaceAll("[.,]", "");
if (StringUtils.isNotBlank(typeStr)
&& LogType.UNKNOWN != LogType.getByIconName(typeStr)
@@ -635,7 +635,7 @@ public abstract class GCParser {
}
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// failed to parse logs
Log.w("GCParser.parseCache: Failed to parse cache log count");
}
@@ -645,7 +645,7 @@ public abstract class GCParser {
// add waypoint for original coordinates in case of user-modified listing-coordinates
try {
- final String originalCoords = BaseUtils.getMatch(page, GCConstants.PATTERN_LATLON_ORIG, false, null);
+ final String originalCoords = TextUtils.getMatch(page, GCConstants.PATTERN_LATLON_ORIG, false, null);
if (null != originalCoords) {
final Waypoint waypoint = new Waypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false);
@@ -653,7 +653,7 @@ public abstract class GCParser {
cache.addOrChangeWaypoint(waypoint, false);
cache.setUserModifiedCoords(true);
}
- } catch (Geopoint.GeopointException e) {
+ } catch (final Geopoint.GeopointException e) {
}
int wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">");
@@ -687,21 +687,21 @@ public abstract class GCParser {
// waypoint name
// res is null during the unit tests
- final String name = BaseUtils.getMatch(wp[6], GCConstants.PATTERN_WPNAME, true, 1, cgeoapplication.getInstance().getString(R.string.waypoint), true);
+ final String name = TextUtils.getMatch(wp[6], GCConstants.PATTERN_WPNAME, true, 1, cgeoapplication.getInstance().getString(R.string.waypoint), true);
// waypoint type
- final String resulttype = BaseUtils.getMatch(wp[3], GCConstants.PATTERN_WPTYPE, null);
+ final String resulttype = TextUtils.getMatch(wp[3], GCConstants.PATTERN_WPTYPE, null);
final Waypoint waypoint = new Waypoint(name, WaypointType.findById(resulttype), false);
// waypoint prefix
- waypoint.setPrefix(BaseUtils.getMatch(wp[4], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, true, 2, waypoint.getPrefix(), false));
+ waypoint.setPrefix(TextUtils.getMatch(wp[4], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, true, 2, waypoint.getPrefix(), false));
// waypoint lookup
- waypoint.setLookup(BaseUtils.getMatch(wp[5], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, true, 2, waypoint.getLookup(), false));
+ waypoint.setLookup(TextUtils.getMatch(wp[5], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, true, 2, waypoint.getLookup(), false));
// waypoint latitude and logitude
- latlon = Html.fromHtml(BaseUtils.getMatch(wp[7], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, false, 2, "", false)).toString().trim();
+ latlon = Html.fromHtml(TextUtils.getMatch(wp[7], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, false, 2, "", false)).toString().trim();
if (!StringUtils.startsWith(latlon, "???")) {
waypoint.setLatlon(latlon);
waypoint.setCoords(new Geopoint(latlon));
@@ -713,7 +713,7 @@ public abstract class GCParser {
}
// waypoint note
- waypoint.setNote(BaseUtils.getMatch(wp[3], GCConstants.PATTERN_WPNOTE, waypoint.getNote()));
+ waypoint.setNote(TextUtils.getMatch(wp[3], GCConstants.PATTERN_WPNOTE, waypoint.getNote()));
cache.addOrChangeWaypoint(waypoint, false);
}
@@ -785,7 +785,7 @@ public abstract class GCParser {
// save to application
search.setError(searchResult.getError());
search.setViewstates(searchResult.viewstates);
- for (String geocode : searchResult.getGeocodes()) {
+ for (final String geocode : searchResult.getGeocodes()) {
search.addGeocode(geocode);
}
return search;
@@ -896,7 +896,7 @@ public abstract class GCParser {
return null;
}
try {
- JSONObject response = Network.requestJSON("http://www.geocaching.com/api/geocode", new Parameters("q", address));
+ final JSONObject response = Network.requestJSON("http://www.geocaching.com/api/geocode", new Parameters("q", address));
if (response == null) {
return null;
}
@@ -906,12 +906,12 @@ public abstract class GCParser {
if (!response.has("data")) {
return null;
}
- JSONObject data = response.getJSONObject("data");
+ final JSONObject data = response.getJSONObject("data");
if (data == null) {
return null;
}
return searchByCoords(new Geopoint(data.getDouble("lat"), data.getDouble("lng")), cacheType, showCaptcha, recaptchaReceiver);
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.w("GCParser.searchByAddress", e);
}
@@ -1008,7 +1008,7 @@ public abstract class GCParser {
final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/seek/log.aspx").encodedQuery("ID=" + cacheid).build().toString();
String page = Login.postRequestLogged(uri, params);
if (!Login.getLoginStatus(page)) {
- Log.e("GCParser.postLogTrackable: Can not log in geocaching");
+ Log.e("GCParser.postLog: Cannot log in geocaching");
return new ImmutablePair<StatusCode, String>(StatusCode.NOT_LOGGED_IN, "");
}
@@ -1036,7 +1036,7 @@ public abstract class GCParser {
if (trackables != null && !trackables.isEmpty()) { // we have some trackables to proceed
final StringBuilder hdnSelected = new StringBuilder();
- for (TrackableLog tb : trackables) {
+ for (final TrackableLog tb : trackables) {
final String action = Integer.toString(tb.id) + tb.action.action;
final StringBuilder paramText = new StringBuilder("ctl00$ContentBody$LogBookPanel1$uxTrackables$repTravelBugs$ctl");
@@ -1057,7 +1057,7 @@ public abstract class GCParser {
page = Network.getResponseData(Network.postRequest(uri, params));
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("GCParser.postLog.confim", e);
}
@@ -1077,11 +1077,11 @@ public abstract class GCParser {
Login.setActualCachesFound(Login.getActualCachesFound() + 1);
}
- final String logID = BaseUtils.getMatch(page, GCConstants.PATTERN_LOG_IMAGE_UPLOAD, "");
+ final String logID = TextUtils.getMatch(page, GCConstants.PATTERN_LOG_IMAGE_UPLOAD, "");
return new ImmutablePair<StatusCode, String>(StatusCode.NO_ERROR, logID);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("GCParser.postLog.check", e);
}
@@ -1103,19 +1103,12 @@ public abstract class GCParser {
* @return status code to indicate success or failure
*/
public static ImmutablePair<StatusCode, String> uploadLogImage(final String logId, final String caption, final String description, final Uri imageUri) {
- final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/seek/upload.aspx").encodedQuery("LID=" + logId).build().toString();
-
- String page = Network.getResponseData(Network.getRequest(uri));
+ final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/seek/upload.aspx").build().toString();
- if (!Login.getLoginStatus(page)) {
- // Login.isActualLoginStatus() was wrong, we are not logged in
- final StatusCode loginState = Login.login();
- if (loginState == StatusCode.NO_ERROR) {
- page = Network.getResponseData(Network.getRequest(uri));
- } else {
- Log.e("Image upload: No login (error: " + loginState + ')');
- return ImmutablePair.of(StatusCode.NOT_LOGGED_IN, null);
- }
+ final String page = Login.getRequestLogged(uri, new Parameters("LID=", logId));
+ if (StringUtils.isBlank(page)) {
+ Log.e("GCParser.uploadLogImage: No data from server");
+ return new ImmutablePair<StatusCode, String>(StatusCode.UNKNOWN_ERROR, null);
}
final String[] viewstates = Login.getViewstates(page);
@@ -1131,7 +1124,7 @@ public abstract class GCParser {
final File image = new File(imageUri.getPath());
final String response = Network.getResponseData(Network.postRequest(uri, uploadParams, "ctl00$ContentBody$ImageUploadControl1$uxFileUpload", "image/jpeg", image));
- MatcherWrapper matcherUrl = new MatcherWrapper(GCConstants.PATTERN_IMAGE_UPLOAD_URL, response);
+ final MatcherWrapper matcherUrl = new MatcherWrapper(GCConstants.PATTERN_IMAGE_UPLOAD_URL, response);
if (matcherUrl.find()) {
Log.i("Logimage successfully uploaded.");
@@ -1195,7 +1188,7 @@ public abstract class GCParser {
final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/track/log.aspx").encodedQuery("wid=" + tbid).build().toString();
final String page = Login.postRequestLogged(uri, params);
if (!Login.getLoginStatus(page)) {
- Log.e("GCParser.postLogTrackable: Can not log in geocaching");
+ Log.e("GCParser.postLogTrackable: Cannot log in geocaching");
return StatusCode.NOT_LOGGED_IN;
}
@@ -1206,7 +1199,7 @@ public abstract class GCParser {
Log.i("Log successfully posted to trackable #" + trackingCode);
return StatusCode.NO_ERROR;
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("GCParser.postLogTrackable.check", e);
}
@@ -1223,14 +1216,14 @@ public abstract class GCParser {
*/
static boolean addToWatchlist(final Geocache cache) {
final String uri = "http://www.geocaching.com/my/watchlist.aspx?w=" + cache.getCacheId();
- String page = Login.postRequestLogged(uri, null);
+ final String page = Login.postRequestLogged(uri, null);
if (StringUtils.isBlank(page)) {
Log.e("GCParser.addToWatchlist: No data from server");
return false; // error
}
- boolean guidOnPage = cache.isGuidContainedInPage(page);
+ final boolean guidOnPage = cache.isGuidContainedInPage(page);
if (guidOnPage) {
Log.i("GCParser.addToWatchlist: cache is on watchlist");
cache.setOnWatchlist(true);
@@ -1264,7 +1257,7 @@ public abstract class GCParser {
Login.transferViewstates(page, params);
page = Network.getResponseData(Network.postRequest(uri, params));
- boolean guidOnPage = cache.isGuidContainedInPage(page);
+ final boolean guidOnPage = cache.isGuidContainedInPage(page);
if (!guidOnPage) {
Log.i("GCParser.removeFromWatchlist: cache removed from watchlist");
cache.setOnWatchlist(false);
@@ -1302,14 +1295,14 @@ public abstract class GCParser {
private static boolean changeFavorite(final Geocache cache, final boolean add) {
final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
- final String userToken = BaseUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
+ final String userToken = TextUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
if (StringUtils.isEmpty(userToken)) {
return false;
}
final String uri = "http://www.geocaching.com/datastore/favorites.svc/update?u=" + userToken + "&f=" + Boolean.toString(add);
- HttpResponse response = Network.postRequest(uri, null);
+ final HttpResponse response = Network.postRequest(uri, null);
if (response != null && response.getStatusLine().getStatusCode() == 200) {
Log.i("GCParser.changeFavorite: cache added/removed to/from favorites");
@@ -1338,7 +1331,7 @@ public abstract class GCParser {
* Parse a trackable HTML description into a Trackable object
*
* @param page
- * the HTML page to parse, already processed through {@link BaseUtils#replaceWhitespace}
+ * the HTML page to parse, already processed through {@link TextUtils#replaceWhitespace}
* @return the parsed trackable, or null if none could be parsed
*/
static Trackable parseTrackable(final String page, final String possibleTrackingcode) {
@@ -1354,20 +1347,20 @@ public abstract class GCParser {
final Trackable trackable = new Trackable();
// trackable geocode
- trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode()));
+ trackable.setGeocode(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, StringUtils.upperCase(possibleTrackingcode)));
// trackable id
- trackable.setGuid(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GUID, true, trackable.getGuid()));
+ trackable.setGuid(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GUID, true, trackable.getGuid()));
// trackable icon
- trackable.setIconUrl(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ICON, true, trackable.getIconUrl()));
+ trackable.setIconUrl(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ICON, true, trackable.getIconUrl()));
// trackable name
- trackable.setName(Html.fromHtml(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_NAME, true, "")).toString());
+ trackable.setName(Html.fromHtml(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_NAME, true, "")).toString());
// trackable type
if (StringUtils.isNotBlank(trackable.getName())) {
- trackable.setType(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_TYPE, true, trackable.getType()));
+ trackable.setType(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_TYPE, true, trackable.getType()));
}
// trackable owner name
@@ -1377,13 +1370,13 @@ public abstract class GCParser {
trackable.setOwnerGuid(matcherOwner.group(1));
trackable.setOwner(matcherOwner.group(2).trim());
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// failed to parse trackable owner name
Log.w("GCParser.parseTrackable: Failed to parse trackable owner name");
}
// trackable origin
- trackable.setOrigin(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ORIGIN, true, trackable.getOrigin()));
+ trackable.setOrigin(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ORIGIN, true, trackable.getOrigin()));
// trackable spotted
try {
@@ -1401,43 +1394,43 @@ public abstract class GCParser {
trackable.setSpottedType(Trackable.SPOTTED_USER);
}
- if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDUNKNOWN)) {
+ if (TextUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDUNKNOWN)) {
trackable.setSpottedType(Trackable.SPOTTED_UNKNOWN);
}
- if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) {
+ if (TextUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) {
trackable.setSpottedType(Trackable.SPOTTED_OWNER);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// failed to parse trackable last known place
Log.w("GCParser.parseTrackable: Failed to parse trackable last known place");
}
// released date - can be missing on the page
try {
- String releaseString = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_RELEASES, false, null);
+ final String releaseString = TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_RELEASES, false, null);
if (releaseString != null) {
trackable.setReleased(dateTbIn1.parse(releaseString));
if (trackable.getReleased() == null) {
trackable.setReleased(dateTbIn2.parse(releaseString));
}
}
- } catch (ParseException e1) {
+ } catch (final ParseException e1) {
trackable.setReleased(null);
}
// trackable distance
- final String distance = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_DISTANCE, false, null);
+ final String distance = TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_DISTANCE, false, null);
if (null != distance) {
try {
trackable.setDistance(DistanceParser.parseDistance(distance, Settings.isUseMetricUnits()));
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.e("GCParser.parseTrackable: Failed to parse distance", e);
}
}
// trackable goal
- trackable.setGoal(convertLinks(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal())));
+ trackable.setGoal(convertLinks(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal())));
// trackable details & image
try {
@@ -1453,10 +1446,13 @@ public abstract class GCParser {
trackable.setDetails(convertLinks(details));
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// failed to parse trackable details & image
Log.w("GCParser.parseTrackable: Failed to parse trackable details & image");
}
+ if (StringUtils.isEmpty(trackable.getDetails()) && page.contains(GCConstants.ERROR_TB_NOT_ACTIVATED)) {
+ trackable.setDetails(cgeoapplication.getInstance().getString(R.string.trackable_not_activated));
+ }
// trackable logs
try {
@@ -1474,7 +1470,7 @@ public abstract class GCParser {
long date = 0;
try {
date = Login.parseGcCustomDate(matcherLogs.group(2)).getTime();
- } catch (ParseException e) {
+ } catch (final ParseException e) {
}
final LogEntry logDone = new LogEntry(
@@ -1502,7 +1498,7 @@ public abstract class GCParser {
trackable.getLogs().add(logDone);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// failed to parse logs
Log.w("GCParser.parseCache: Failed to parse cache logs", e);
}
@@ -1572,10 +1568,10 @@ public abstract class GCParser {
}
} else {
// extract embedded JSON data from page
- rawResponse = BaseUtils.getMatch(page, GCConstants.PATTERN_LOGBOOK, "");
+ rawResponse = TextUtils.getMatch(page, GCConstants.PATTERN_LOGBOOK, "");
}
- List<LogEntry> logs = new ArrayList<LogEntry>();
+ final List<LogEntry> logs = new ArrayList<LogEntry>();
try {
final JSONObject resp = new JSONObject(rawResponse);
@@ -1596,7 +1592,7 @@ public abstract class GCParser {
long date = 0;
try {
date = Login.parseGcCustomDate(entry.getString("Visited")).getTime();
- } catch (ParseException e) {
+ } catch (final ParseException e) {
Log.e("GCParser.loadLogsFromDetails: failed to parse log date.");
}
@@ -1624,7 +1620,7 @@ public abstract class GCParser {
logs.add(logDone);
}
- } catch (JSONException e) {
+ } catch (final JSONException e) {
// failed to parse logs
Log.w("GCParser.loadLogsFromDetails: Failed to parse cache logs", e);
}
@@ -1641,16 +1637,16 @@ public abstract class GCParser {
final MatcherWrapper typeBoxMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPEBOX, page);
if (typeBoxMatcher.find() && typeBoxMatcher.groupCount() > 0) {
- String typesText = typeBoxMatcher.group(1);
+ final String typesText = typeBoxMatcher.group(1);
final MatcherWrapper typeMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPE2, typesText);
while (typeMatcher.find()) {
if (typeMatcher.groupCount() > 1) {
try {
- int type = Integer.parseInt(typeMatcher.group(2));
+ final int type = Integer.parseInt(typeMatcher.group(2));
if (type > 0) {
types.add(LogType.getById(type));
}
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.e("Error parsing log types", e);
}
}
@@ -1698,7 +1694,7 @@ public abstract class GCParser {
Log.i("Trackable in inventory (#" + entry.ctl + "/" + entry.id + "): " + entry.trackCode + " - " + entry.name);
trackableLogs.add(entry);
}
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.e("GCParser.parseTrackableLog", e);
}
}
@@ -1727,10 +1723,10 @@ public abstract class GCParser {
//cache.setLogs(loadLogsFromDetails(page, cache, false));
if (Settings.isFriendLogsWanted()) {
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs);
- List<LogEntry> allLogs = cache.getLogs();
- List<LogEntry> friendLogs = loadLogsFromDetails(page, cache, true, false);
+ final List<LogEntry> allLogs = cache.getLogs();
+ final List<LogEntry> friendLogs = loadLogsFromDetails(page, cache, true, false);
if (friendLogs != null) {
- for (LogEntry log : friendLogs) {
+ for (final LogEntry log : friendLogs) {
if (allLogs.contains(log)) {
allLogs.get(allLogs.indexOf(log)).friend = true;
} else {
@@ -1774,7 +1770,7 @@ public abstract class GCParser {
public static boolean editModifiedCoordinates(Geocache cache, Geopoint wpt) {
final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
- final String userToken = BaseUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
+ final String userToken = TextUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
if (StringUtils.isEmpty(userToken)) {
return false;
}
@@ -1793,7 +1789,7 @@ public abstract class GCParser {
final String uriSuffix = wpt != null ? "SetUserCoordinate" : "ResetUserCoordinate";
final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/";
- HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo);
+ final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo);
Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString());
if (response != null && response.getStatusLine().getStatusCode() == 200) {
@@ -1801,7 +1797,7 @@ public abstract class GCParser {
return true;
}
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("Unknown exception with json wrap code", e);
}
Log.e("GCParser.deleteModifiedCoordinates - cannot delete modified coords");
@@ -1810,13 +1806,13 @@ public abstract class GCParser {
public static boolean uploadPersonalNote(Geocache cache) {
final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
- final String userToken = BaseUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
+ final String userToken = TextUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
if (StringUtils.isEmpty(userToken)) {
return false;
}
try {
- JSONObject jo = new JSONObject()
+ final JSONObject jo = new JSONObject()
.put("dto", (new JSONObject()
.put("et", cache.getPersonalNote())
.put("ut", userToken)));
@@ -1824,7 +1820,7 @@ public abstract class GCParser {
final String uriSuffix = "SetUserCacheNote";
final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/";
- HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo);
+ final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo);
Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString());
if (response != null && response.getStatusLine().getStatusCode() == 200) {
@@ -1832,7 +1828,7 @@ public abstract class GCParser {
return true;
}
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("Unknown exception with json wrap code", e);
}
Log.e("GCParser.uploadPersonalNote - cannot upload personal note");
diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java
index 7351311..3146712 100644
--- a/main/src/cgeo/geocaching/connector/gc/Login.java
+++ b/main/src/cgeo/geocaching/connector/gc/Login.java
@@ -8,9 +8,9 @@ import cgeo.geocaching.network.Cookies;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
-import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
+import cgeo.geocaching.utils.TextUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
@@ -52,9 +52,9 @@ public abstract class Login {
"dd/MM/yyyy"
};
- Map<String, SimpleDateFormat> map = new HashMap<String, SimpleDateFormat>();
+ final Map<String, SimpleDateFormat> map = new HashMap<String, SimpleDateFormat>();
- for (String format : formats) {
+ for (final String format : formats) {
map.put(format, new SimpleDateFormat(format, Locale.ENGLISH));
}
@@ -77,7 +77,7 @@ public abstract class Login {
Login.setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_working));
HttpResponse loginResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx");
String loginData = Network.getResponseData(loginResponse);
- if (loginResponse != null && loginResponse.getStatusLine().getStatusCode() == 503 && BaseUtils.matches(loginData, GCConstants.PATTERN_MAINTENANCE)) {
+ if (loginResponse != null && loginResponse.getStatusLine().getStatusCode() == 503 && TextUtils.matches(loginData, GCConstants.PATTERN_MAINTENANCE)) {
return StatusCode.MAINTENANCE;
}
@@ -147,9 +147,9 @@ public abstract class Login {
}
public static StatusCode logout() {
- HttpResponse logoutResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fdefault.aspx%3f");
- String logoutData = Network.getResponseData(logoutResponse);
- if (logoutResponse != null && logoutResponse.getStatusLine().getStatusCode() == 503 && BaseUtils.matches(logoutData, GCConstants.PATTERN_MAINTENANCE)) {
+ final HttpResponse logoutResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fdefault.aspx%3f");
+ final String logoutData = Network.getResponseData(logoutResponse);
+ if (logoutResponse != null && logoutResponse.getStatusLine().getStatusCode() == 503 && TextUtils.matches(logoutData, GCConstants.PATTERN_MAINTENANCE)) {
return StatusCode.MAINTENANCE;
}
@@ -205,17 +205,17 @@ public abstract class Login {
setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_ok));
// on every page except login page
- setActualLoginStatus(BaseUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME));
+ setActualLoginStatus(TextUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME));
if (isActualLoginStatus()) {
- setActualUserName(BaseUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???"));
+ setActualUserName(TextUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???"));
int cachesCount = 0;
try {
- cachesCount = Integer.parseInt(BaseUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", ""));
- } catch (NumberFormatException e) {
+ cachesCount = Integer.parseInt(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", ""));
+ } catch (final NumberFormatException e) {
Log.e("getLoginStatus: bad cache count", e);
}
setActualCachesFound(cachesCount);
- Settings.setMemberStatus(BaseUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, null));
+ Settings.setMemberStatus(TextUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, null));
if ( page.contains(GCConstants.MEMBER_STATUS_RENEW) ) {
Settings.setMemberStatus(GCConstants.MEMBER_STATUS_PM);
}
@@ -223,7 +223,7 @@ public abstract class Login {
}
// login page
- setActualLoginStatus(BaseUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME_LOGIN_PAGE));
+ setActualLoginStatus(TextUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME_LOGIN_PAGE));
if (isActualLoginStatus()) {
setActualUserName(Settings.getUsername());
// number of caches found is not part of this page
@@ -260,23 +260,23 @@ public abstract class Login {
public static BitmapDrawable downloadAvatarAndGetMemberStatus() {
try {
- final String profile = BaseUtils.replaceWhitespace(Network.getResponseData(Network.getRequest("http://www.geocaching.com/my/")));
+ final String profile = TextUtils.replaceWhitespace(Network.getResponseData(Network.getRequest("http://www.geocaching.com/my/")));
- Settings.setMemberStatus(BaseUtils.getMatch(profile, GCConstants.PATTERN_MEMBER_STATUS, true, null));
+ Settings.setMemberStatus(TextUtils.getMatch(profile, GCConstants.PATTERN_MEMBER_STATUS, true, null));
if (profile.contains(GCConstants.MEMBER_STATUS_RENEW)) {
Settings.setMemberStatus(GCConstants.MEMBER_STATUS_PM);
}
- setActualCachesFound(Integer.parseInt(BaseUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", "")));
+ setActualCachesFound(Integer.parseInt(TextUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", "")));
- final String avatarURL = BaseUtils.getMatch(profile, GCConstants.PATTERN_AVATAR_IMAGE_PROFILE_PAGE, false, null);
+ final String avatarURL = TextUtils.getMatch(profile, GCConstants.PATTERN_AVATAR_IMAGE_PROFILE_PAGE, false, null);
if (null != avatarURL) {
final HtmlImage imgGetter = new HtmlImage("", false, 0, false);
return imgGetter.getDrawable(avatarURL);
}
// No match? There may be no avatar set by user.
Log.d("No avatar set for user");
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("Error when retrieving user avatar", e);
}
return null;
@@ -294,7 +294,7 @@ public abstract class Login {
return;
}
- String customDate = BaseUtils.getMatch(result, GCConstants.PATTERN_CUSTOMDATE, true, null);
+ final String customDate = TextUtils.getMatch(result, GCConstants.PATTERN_CUSTOMDATE, true, null);
if (null != customDate) {
Settings.setGcCustomDate(customDate);
}
@@ -310,14 +310,14 @@ public abstract class Login {
if (gcCustomDateFormats.containsKey(format)) {
try {
return gcCustomDateFormats.get(format).parse(trimmed);
- } catch (ParseException e) {
+ } catch (final ParseException e) {
}
}
- for (SimpleDateFormat sdf : gcCustomDateFormats.values()) {
+ for (final SimpleDateFormat sdf : gcCustomDateFormats.values()) {
try {
return sdf.parse(trimmed);
- } catch (ParseException e) {
+ } catch (final ParseException e) {
}
}
@@ -347,7 +347,7 @@ public abstract class Login {
return true;
}
- for (String s : a) {
+ for (final String s : a) {
if (StringUtils.isNotEmpty(s)) {
return false;
}
@@ -373,24 +373,24 @@ public abstract class Login {
if (matcherViewstateCount.find()) {
try {
count = Integer.parseInt(matcherViewstateCount.group(1));
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.e("getViewStates", e);
}
}
- String[] viewstates = new String[count];
+ final String[] viewstates = new String[count];
// Get the viewstates
final MatcherWrapper matcherViewstates = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATES, page);
while (matcherViewstates.find()) {
- String sno = matcherViewstates.group(1); // number of viewstate
+ final String sno = matcherViewstates.group(1); // number of viewstate
int no;
if (StringUtils.isEmpty(sno)) {
no = 0;
} else {
try {
no = Integer.parseInt(sno);
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.e("getViewStates", e);
no = 0;
}
@@ -436,17 +436,17 @@ public abstract class Login {
* @return
*/
public static String postRequestLogged(final String uri, final Parameters params) {
- HttpResponse response = Network.postRequest(uri, params);
- String data = Network.getResponseData(response);
+ final String data = Network.getResponseData(Network.postRequest(uri, params));
- if (!getLoginStatus(data)) {
- if (login() == StatusCode.NO_ERROR) {
- response = Network.postRequest(uri, params);
- data = Network.getResponseData(response);
- } else {
- Log.i("Working as guest.");
- }
+ if (getLoginStatus(data)) {
+ return data;
}
+
+ if (login() == StatusCode.NO_ERROR) {
+ return Network.getResponseData(Network.postRequest(uri, params));
+ }
+
+ Log.i("Working as guest.");
return data;
}
@@ -476,8 +476,8 @@ public abstract class Login {
public static String[] getMapTokens() {
final HttpResponse response = Network.getRequest(GCConstants.URL_LIVE_MAP);
final String data = Network.getResponseData(response);
- final String userSession = BaseUtils.getMatch(data, GCConstants.PATTERN_USERSESSION, "");
- final String sessionToken = BaseUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, "");
+ final String userSession = TextUtils.getMatch(data, GCConstants.PATTERN_USERSESSION, "");
+ final String sessionToken = TextUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, "");
return new String[] { userSession, sessionToken };
}
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
index 4c6db97..5f30934 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
@@ -6,9 +6,10 @@ import cgeo.geocaching.Settings;
import cgeo.geocaching.cgData;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.ILoggingManager;
+import cgeo.geocaching.connector.capability.ILogin;
import cgeo.geocaching.connector.capability.ISearchByCenter;
import cgeo.geocaching.connector.capability.ISearchByViewPort;
-import cgeo.geocaching.connector.oc.OkapiClient.UserInfo;
+import cgeo.geocaching.connector.oc.UserInfo.UserInfoStatus;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.utils.CryptUtils;
@@ -16,11 +17,13 @@ import cgeo.geocaching.utils.CryptUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
+import android.content.Context;
+import android.os.Handler;
-public class OCApiLiveConnector extends OCApiConnector implements ISearchByCenter, ISearchByViewPort {
+public class OCApiLiveConnector extends OCApiConnector implements ISearchByCenter, ISearchByViewPort, ILogin {
private String cS;
- private UserInfo userInfo = new UserInfo(StringUtils.EMPTY, 0, false);
+ private UserInfo userInfo = new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.NOT_RETRIEVED);
public OCApiLiveConnector(String name, String host, String prefix, int cKResId, int cSResId, ApiSupport apiSupport) {
super(name, host, prefix, CryptUtils.rot13(cgeoapplication.getInstance().getResources().getString(cKResId)), apiSupport);
@@ -104,16 +107,33 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
return getSupportedAuthLevel() == OAuthLevel.Level3;
}
- public boolean retrieveUserInfo() {
- userInfo = OkapiClient.getUserInfo(this);
- return userInfo.isRetrieveSuccessful();
+ @Override
+ public boolean login(Handler handler, Context fromActivity) {
+ if (supportsPersonalization()) {
+ userInfo = OkapiClient.getUserInfo(this);
+ } else {
+ userInfo = new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.NOT_SUPPORTED);
+ }
+ return userInfo.getStatus() == UserInfoStatus.SUCCESSFUL;
}
- public Object getUserName() {
+ @Override
+ public String getUserName() {
return userInfo.getName();
}
+ @Override
public int getCachesFound() {
return userInfo.getFinds();
}
+
+ @Override
+ public String getLoginStatusString() {
+ return cgeoapplication.getInstance().getString(userInfo.getStatus().resId);
+ }
+
+ @Override
+ public boolean isLoggedIn() {
+ return userInfo.getStatus() == UserInfoStatus.SUCCESSFUL;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 3c99bc9..b6f9711 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -14,6 +14,7 @@ import cgeo.geocaching.connector.LogResult;
import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.connector.oc.OCApiConnector.ApiSupport;
import cgeo.geocaching.connector.oc.OCApiConnector.OAuthLevel;
+import cgeo.geocaching.connector.oc.UserInfo.UserInfoStatus;
import cgeo.geocaching.enumerations.CacheAttribute;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
@@ -93,6 +94,7 @@ final public class OkapiClient {
private static final String CACHE_LOCATION = "location";
private static final String CACHE_NAME = "name";
private static final String CACHE_CODE = "code";
+ private static final String CACHE_REQ_PASSWORD = "req_passwd";
private static final String LOG_TYPE = "type";
private static final String LOG_COMMENT = "comment";
@@ -108,7 +110,7 @@ final public class OkapiClient {
// Additional: additional fields for full cache (L3 - only for level 3 auth, current - only for connectors with current api)
private static final String SERVICE_CACHE_CORE_FIELDS = "code|name|location|type|status|difficulty|terrain|size";
private static final String SERVICE_CACHE_CORE_L3_FIELDS = "is_found";
- private static final String SERVICE_CACHE_ADDITIONAL_FIELDS = "owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|date_hidden|alt_wpts|attrnames";
+ private static final String SERVICE_CACHE_ADDITIONAL_FIELDS = "owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|date_hidden|alt_wpts|attrnames|req_passwd";
private static final String SERVICE_CACHE_ADDITIONAL_CURRENT_FIELDS = "gc_code|attribution_note";
private static final String SERVICE_CACHE_ADDITIONAL_L3_FIELDS = "is_watched";
@@ -118,12 +120,12 @@ final public class OkapiClient {
public static Geocache getCache(final String geoCode) {
final Parameters params = new Parameters("cache_code", geoCode);
- IConnector connector = ConnectorFactory.getConnector(geoCode);
+ final IConnector connector = ConnectorFactory.getConnector(geoCode);
if (!(connector instanceof OCApiConnector)) {
return null;
}
- OCApiConnector ocapiConn = (OCApiConnector) connector;
+ final OCApiConnector ocapiConn = (OCApiConnector) connector;
params.add("fields", getFullFields(ocapiConn));
params.add("attribution_append", "none");
@@ -138,16 +140,18 @@ final public class OkapiClient {
}
public static List<Geocache> getCachesAround(final Geopoint center, OCApiConnector connector) {
- String centerString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center) + SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center);
+ final String centerString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center) + SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center);
final Parameters params = new Parameters("search_method", METHOD_SEARCH_NEAREST);
final Map<String, String> valueMap = new LinkedHashMap<String, String>();
valueMap.put("center", centerString);
valueMap.put("limit", "20");
- addFilterParams(valueMap, connector);
+ return requestCaches(connector, params, valueMap);
+ }
+ private static List<Geocache> requestCaches(OCApiConnector connector, final Parameters params, final Map<String, String> valueMap) {
+ addFilterParams(valueMap, connector);
params.add("search_params", new JSONObject(valueMap).toString());
-
addRetrieveParams(params, connector);
final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params);
@@ -166,7 +170,7 @@ final public class OkapiClient {
return Collections.emptyList();
}
- String bboxString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, viewport.bottomLeft)
+ final String bboxString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, viewport.bottomLeft)
+ SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, viewport.bottomLeft)
+ SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, viewport.topRight)
+ SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, viewport.topRight);
@@ -174,19 +178,7 @@ final public class OkapiClient {
final Map<String, String> valueMap = new LinkedHashMap<String, String>();
valueMap.put("bbox", bboxString);
- addFilterParams(valueMap, connector);
-
- params.add("search_params", new JSONObject(valueMap).toString());
-
- addRetrieveParams(params, connector);
-
- final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params);
-
- if (data == null) {
- return Collections.emptyList();
- }
-
- return parseCaches(data);
+ return requestCaches(connector, params, valueMap);
}
public static boolean setWatchState(final Geocache cache, final boolean watched, OCApiConnector connector) {
@@ -204,7 +196,7 @@ final public class OkapiClient {
return true;
}
- public static LogResult postLog(final Geocache cache, LogType logType, Calendar date, String log, OCApiConnector connector) {
+ public static LogResult postLog(final Geocache cache, LogType logType, Calendar date, String log, String logPassword, OCApiConnector connector) {
final Parameters params = new Parameters("cache_code", cache.getGeocode());
params.add("logtype", logType.oc_type);
params.add("comment", log);
@@ -213,6 +205,9 @@ final public class OkapiClient {
if (logType.equals(LogType.NEEDS_MAINTENANCE)) {
params.add("needs_maintenance", "true");
}
+ if (logPassword != null) {
+ params.add("password", logPassword);
+ }
final JSONObject data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params);
@@ -226,7 +221,7 @@ final public class OkapiClient {
}
return new LogResult(StatusCode.LOG_POST_ERROR, "");
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.postLog", e);
}
return new LogResult(StatusCode.LOG_POST_ERROR, "");
@@ -243,19 +238,20 @@ final public class OkapiClient {
// Get and iterate result list
final JSONObject cachesResponse = response.getJSONObject("results");
if (cachesResponse != null) {
- List<Geocache> caches = new ArrayList<Geocache>(cachesResponse.length());
+ final List<Geocache> caches = new ArrayList<Geocache>(cachesResponse.length());
@SuppressWarnings("unchecked")
+ final
Iterator<String> keys = cachesResponse.keys();
while (keys.hasNext()) {
- String key = keys.next();
- Geocache cache = parseSmallCache(cachesResponse.getJSONObject(key));
+ final String key = keys.next();
+ final Geocache cache = parseSmallCache(cachesResponse.getJSONObject(key));
if (cache != null) {
caches.add(cache);
}
}
return caches;
}
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.parseCachesResult", e);
}
return Collections.emptyList();
@@ -269,7 +265,7 @@ final public class OkapiClient {
parseCoreCache(response, cache);
cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.parseSmallCache", e);
}
return cache;
@@ -297,9 +293,9 @@ final public class OkapiClient {
cache.setFavoritePoints(response.getInt(CACHE_RECOMMENDATIONS));
// not used: req_password
// Prepend gc-link to description if available
- StringBuilder description = new StringBuilder(500);
+ final StringBuilder description = new StringBuilder(500);
if (!response.isNull("gc_code")) {
- String gccode = response.getString("gc_code");
+ final String gccode = response.getString("gc_code");
description.append(cgeoapplication.getInstance().getResources()
.getString(R.string.cache_listed_on, GCConnector.getInstance().getName()))
.append(": <a href=\"http://coord.info/")
@@ -318,7 +314,7 @@ final public class OkapiClient {
final JSONArray images = response.getJSONArray(CACHE_IMAGES);
if (images != null) {
for (int i = 0; i < images.length(); i++) {
- JSONObject imageResponse = images.getJSONObject(i);
+ final JSONObject imageResponse = images.getJSONObject(i);
if (imageResponse.getBoolean(CACHE_IMAGE_IS_SPOILER)) {
final String title = imageResponse.getString(CACHE_IMAGE_CAPTION);
final String url = absoluteUrl(imageResponse.getString(CACHE_IMAGE_URL), cache.getGeocode());
@@ -336,11 +332,12 @@ final public class OkapiClient {
if (!response.isNull(CACHE_IS_WATCHED)) {
cache.setOnWatchlist(response.getBoolean(CACHE_IS_WATCHED));
}
+ cache.setLogPasswordRequired(response.getBoolean(CACHE_REQ_PASSWORD));
cache.setDetailedUpdatedNow();
// save full detailed caches
cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.parseCache", e);
}
return cache;
@@ -387,8 +384,8 @@ final public class OkapiClient {
List<LogEntry> result = null;
for (int i = 0; i < logsJSON.length(); i++) {
try {
- JSONObject logResponse = logsJSON.getJSONObject(i);
- LogEntry log = new LogEntry(
+ final JSONObject logResponse = logsJSON.getJSONObject(i);
+ final LogEntry log = new LogEntry(
parseUser(logResponse.getJSONObject(LOG_USER)),
parseDate(logResponse.getString(LOG_DATE)).getTime(),
parseLogType(logResponse.getString(LOG_TYPE)),
@@ -397,7 +394,7 @@ final public class OkapiClient {
result = new ArrayList<LogEntry>();
}
result.add(log);
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.parseLogs", e);
}
}
@@ -408,12 +405,12 @@ final public class OkapiClient {
List<Waypoint> result = null;
for (int i = 0; i < wptsJson.length(); i++) {
try {
- JSONObject wptResponse = wptsJson.getJSONObject(i);
- Waypoint wpt = new Waypoint(wptResponse.getString(WPT_NAME),
+ final JSONObject wptResponse = wptsJson.getJSONObject(i);
+ final Waypoint wpt = new Waypoint(wptResponse.getString(WPT_NAME),
parseWptType(wptResponse.getString(WPT_TYPE)),
false);
wpt.setNote(wptResponse.getString(WPT_DESCRIPTION));
- Geopoint pt = parseCoords(wptResponse.getString(WPT_LOCATION));
+ final Geopoint pt = parseCoords(wptResponse.getString(WPT_LOCATION));
if (pt != null) {
wpt.setCoords(pt);
}
@@ -421,7 +418,7 @@ final public class OkapiClient {
result = new ArrayList<Waypoint>();
}
result.add(wpt);
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.parseWaypoints", e);
}
}
@@ -468,7 +465,7 @@ final public class OkapiClient {
final String strippedDate = date.replaceAll("\\+0([0-9]){1}\\:00", "+0$100");
try {
return ISO8601DATEFORMAT.parse(strippedDate);
- } catch (ParseException e) {
+ } catch (final ParseException e) {
Log.e("OkapiClient.parseDate", e);
}
return null;
@@ -486,17 +483,17 @@ final public class OkapiClient {
private static List<String> parseAttributes(JSONArray nameList) {
- List<String> result = new ArrayList<String>();
+ final List<String> result = new ArrayList<String>();
for (int i = 0; i < nameList.length(); i++) {
try {
- String name = nameList.getString(i);
- CacheAttribute attr = CacheAttribute.getByOcId(AttributeParser.getOcDeId(name));
+ final String name = nameList.getString(i);
+ final CacheAttribute attr = CacheAttribute.getByOcId(AttributeParser.getOcDeId(name));
if (attr != null) {
result.add(attr.rawName);
}
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.parseAttributes", e);
}
}
@@ -517,7 +514,7 @@ final public class OkapiClient {
double size = 0;
try {
size = response.getDouble(CACHE_SIZE);
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.getCacheSize", e);
}
switch ((int) Math.round(size)) {
@@ -584,7 +581,7 @@ final public class OkapiClient {
return StringUtils.EMPTY;
}
- StringBuilder res = new StringBuilder(500);
+ final StringBuilder res = new StringBuilder(500);
res.append(SERVICE_CACHE_CORE_FIELDS);
res.append(SEPARATOR).append(SERVICE_CACHE_ADDITIONAL_FIELDS);
@@ -673,7 +670,7 @@ final public class OkapiClient {
final JSONObject data = request(connector, OkapiService.SERVICE_USER, params);
if (data == null) {
- return new UserInfo(StringUtils.EMPTY, 0, false);
+ return new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.FAILED);
}
String name = StringUtils.EMPTY;
@@ -683,7 +680,7 @@ final public class OkapiClient {
if (!data.isNull(USER_USERNAME)) {
try {
name = data.getString(USER_USERNAME);
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.getUserInfo - name", e);
success = false;
}
@@ -694,7 +691,7 @@ final public class OkapiClient {
if (!data.isNull(USER_CACHES_FOUND)) {
try {
finds = data.getInt(USER_CACHES_FOUND);
- } catch (JSONException e) {
+ } catch (final JSONException e) {
Log.e("OkapiClient.getUserInfo - finds", e);
success = false;
}
@@ -702,32 +699,7 @@ final public class OkapiClient {
success = false;
}
- return new UserInfo(name, finds, success);
- }
-
- public static class UserInfo {
-
- private final String name;
- private final int finds;
- private final boolean retrieveSuccessful;
-
- UserInfo(String name, int finds, boolean retrieveSuccessful) {
- this.name = name;
- this.finds = finds;
- this.retrieveSuccessful = retrieveSuccessful;
- }
-
- public String getName() {
- return name;
- }
-
- public int getFinds() {
- return finds;
- }
-
- public boolean isRetrieveSuccessful() {
- return retrieveSuccessful;
- }
+ return new UserInfo(name, finds, success ? UserInfoStatus.SUCCESSFUL : UserInfoStatus.FAILED);
}
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
index 8a94218..c4bf91f 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.connector.oc;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.TrackableLog;
import cgeo.geocaching.LogCacheActivity;
+import cgeo.geocaching.TrackableLog;
import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.ImageResult;
import cgeo.geocaching.connector.LogResult;
@@ -38,8 +38,8 @@ public class OkapiLoggingManager implements ILoggingManager {
}
@Override
- public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, List<TrackableLog> trackableLogs) {
- return OkapiClient.postLog(cache, logType, date, log, connector);
+ public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, String logPassword, List<TrackableLog> trackableLogs) {
+ return OkapiClient.postLog(cache, logType, date, log, logPassword, connector);
}
@Override
diff --git a/main/src/cgeo/geocaching/connector/oc/UserInfo.java b/main/src/cgeo/geocaching/connector/oc/UserInfo.java
new file mode 100644
index 0000000..0dc0440
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/oc/UserInfo.java
@@ -0,0 +1,41 @@
+package cgeo.geocaching.connector.oc;
+
+import cgeo.geocaching.R;
+
+public class UserInfo {
+
+ public enum UserInfoStatus {
+ NOT_RETRIEVED(R.string.init_login_popup_working),
+ SUCCESSFUL(R.string.init_login_popup_ok),
+ FAILED(R.string.init_login_popup_failed),
+ NOT_SUPPORTED(R.string.init_login_popup_not_authorized);
+
+ public final int resId;
+
+ UserInfoStatus(int resId) {
+ this.resId = resId;
+ }
+ }
+
+ private final String name;
+ private final int finds;
+ private final UserInfoStatus status;
+
+ UserInfo(String name, int finds, UserInfoStatus status) {
+ this.name = name;
+ this.finds = finds;
+ this.status = status;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getFinds() {
+ return finds;
+ }
+
+ public UserInfoStatus getStatus() {
+ return status;
+ }
+}
diff --git a/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java
new file mode 100644
index 0000000..cd32d87
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java
@@ -0,0 +1,10 @@
+package cgeo.geocaching.connector.trackable;
+
+
+public abstract class AbstractTrackableConnector implements TrackableConnector {
+
+ @Override
+ public boolean isLoggable() {
+ return false;
+ }
+}
diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java
new file mode 100644
index 0000000..8387076
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java
@@ -0,0 +1,42 @@
+package cgeo.geocaching.connector.trackable;
+
+import cgeo.geocaching.Trackable;
+import cgeo.geocaching.network.Network;
+import cgeo.geocaching.utils.Log;
+
+import java.util.regex.Pattern;
+
+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) {
+ return geocode != null && PATTERN_GK_CODE.matcher(geocode).matches();
+ }
+
+ @Override
+ public String getUrl(Trackable trackable) {
+ return "http://geokrety.org/konkret.php?id=" + getId(trackable.getGeocode());
+ }
+
+ @Override
+ public Trackable searchTrackable(String geocode, String guid, String id) {
+ final String page = Network.getResponseData(Network.getRequest("http://geokrety.org/export2.php?gkid=" + getId(geocode)));
+ if (page == null) {
+ return null;
+ }
+ return GeokretyParser.parse(page);
+ }
+
+ private static int getId(String geocode) {
+ try {
+ final String hex = geocode.substring(2);
+ return Integer.parseInt(hex, 16);
+ } catch (final NumberFormatException e) {
+ Log.e("Trackable.getUrl", e);
+ }
+ return -1;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
new file mode 100644
index 0000000..66ca5f7
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
@@ -0,0 +1,82 @@
+package cgeo.geocaching.connector.trackable;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.Trackable;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.utils.Log;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import android.sax.Element;
+import android.sax.EndTextElementListener;
+import android.sax.RootElement;
+import android.sax.StartElementListener;
+import android.util.Xml;
+
+public class GeokretyParser {
+
+ public static Trackable parse(final String page) {
+ final Trackable trackable = new Trackable();
+
+ final RootElement root = new RootElement("gkxml");
+ final Element geokret = root.getChild("geokrety").getChild("geokret");
+
+ geokret.setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String name) {
+ trackable.setName(name);
+ }
+ });
+
+ geokret.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attributes) {
+ try {
+ if (attributes.getIndex("id") > -1) {
+ trackable.setGeocode(geocode(Integer.valueOf(attributes.getValue("id"))));
+ }
+ if (attributes.getIndex("dist") > -1) {
+ trackable.setDistance(Float.valueOf(attributes.getValue("dist")));
+ }
+ if (attributes.getIndex("type") > -1) {
+ trackable.setType(getType(Integer.valueOf(attributes.getValue("type"))));
+ }
+ } catch (final NumberFormatException e) {
+ Log.e("Parsing geokret", e);
+ }
+ }
+ });
+
+ try {
+ Xml.parse(page, root.getContentHandler());
+ return trackable;
+ } catch (final SAXException e) {
+ Log.w("Cannot parse geokrety", e);
+ }
+
+ return null;
+ }
+
+ protected static String getType(int type) {
+ switch (type) {
+ case 0:
+ return cgeoapplication.getInstance().getString(R.string.geokret_type_traditional);
+ case 1:
+ return cgeoapplication.getInstance().getString(R.string.geokret_type_book_or_media);
+ case 2:
+ return cgeoapplication.getInstance().getString(R.string.geokret_type_human);
+ case 3:
+ return cgeoapplication.getInstance().getString(R.string.geokret_type_coin);
+ case 4:
+ return cgeoapplication.getInstance().getString(R.string.geokret_type_post);
+ }
+ return null;
+ }
+
+ protected static String geocode(final int id) {
+ return String.format("GK%04X", id);
+ }
+}
diff --git a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java
new file mode 100644
index 0000000..c09dc07
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java
@@ -0,0 +1,19 @@
+package cgeo.geocaching.connector.trackable;
+
+import cgeo.geocaching.Trackable;
+
+/**
+ * Methods to be implemented by any connector for handling trackables
+ *
+ */
+public interface TrackableConnector {
+
+ public boolean canHandleTrackable(final String geocode);
+
+ public String getUrl(final Trackable trackable);
+
+ public boolean isLoggable();
+
+ public Trackable searchTrackable(String geocode, String guid, String id);
+
+}
diff --git a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java
new file mode 100644
index 0000000..0dac6cc
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java
@@ -0,0 +1,50 @@
+package cgeo.geocaching.connector.trackable;
+
+import cgeo.geocaching.Trackable;
+import cgeo.geocaching.connector.gc.GCParser;
+
+import java.util.regex.Pattern;
+
+public class TravelBugConnector extends AbstractTrackableConnector {
+
+ /**
+ * TB codes really start with TB1, there is no padding or minimum length
+ */
+ private final static Pattern PATTERN_TB_CODE = Pattern.compile("(TB[0-9A-Z]+)|([0-9A-Z]{6})", Pattern.CASE_INSENSITIVE);
+
+ @Override
+ public boolean canHandleTrackable(String geocode) {
+ return TravelBugConnector.PATTERN_TB_CODE.matcher(geocode).matches();
+ }
+
+ @Override
+ public String getUrl(Trackable trackable) {
+ return "http://www.geocaching.com//track/details.aspx?tracker=" + trackable.getGeocode();
+ }
+
+ @Override
+ public boolean isLoggable() {
+ return true;
+ }
+
+ @Override
+ public Trackable searchTrackable(String geocode, String guid, String id) {
+ return GCParser.searchTrackable(geocode, guid, id);
+ }
+
+ /**
+ * initialization on demand holder pattern
+ */
+ private static class Holder {
+ private static final TravelBugConnector INSTANCE = new TravelBugConnector();
+ }
+
+ private TravelBugConnector() {
+ // singleton
+ }
+
+ public static TravelBugConnector getInstance() {
+ return Holder.INSTANCE;
+ }
+
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java
new file mode 100644
index 0000000..0295927
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java
@@ -0,0 +1,24 @@
+package cgeo.geocaching.connector.trackable;
+
+import cgeo.geocaching.Trackable;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class UnknownTrackableConnector extends AbstractTrackableConnector {
+
+ @Override
+ public boolean canHandleTrackable(String geocode) {
+ return false;
+ }
+
+ @Override
+ public String getUrl(Trackable trackable) {
+ return StringUtils.EMPTY;
+ }
+
+ @Override
+ public Trackable searchTrackable(String geocode, String guid, String id) {
+ return null;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java
index a42a48a..38b603c 100644
--- a/main/src/cgeo/geocaching/export/FieldnoteExport.java
+++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java
@@ -70,10 +70,10 @@ class FieldnoteExport extends AbstractExport {
}
private Dialog getExportOptionsDialog(final Geocache[] caches, final Activity activity) {
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
// AlertDialog has always dark style, so we have to apply it as well always
- View layout = View.inflate(new ContextThemeWrapper(activity, R.style.dark), R.layout.fieldnote_export_dialog, null);
+ final View layout = View.inflate(new ContextThemeWrapper(activity, R.style.dark), R.layout.fieldnote_export_dialog, null);
builder.setView(layout);
final CheckBox uploadOption = (CheckBox) layout.findViewById(R.id.upload);
@@ -132,13 +132,13 @@ class FieldnoteExport extends AbstractExport {
final StringBuilder fieldNoteBuffer = new StringBuilder();
try {
int i = 0;
- for (Geocache cache : caches) {
+ for (final Geocache cache : caches) {
if (cache.isLogOffline()) {
appendFieldNote(fieldNoteBuffer, cache, cgData.loadLogOffline(cache.getGeocode()));
publishProgress(++i);
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("FieldnoteExport.ExportTask generation", e);
return false;
}
@@ -151,17 +151,17 @@ class FieldnoteExport extends AbstractExport {
exportLocation.mkdirs();
- SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
+ final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".txt");
Writer fileWriter = null;
BufferedOutputStream buffer = null;
try {
- OutputStream os = new FileOutputStream(exportFile);
+ final OutputStream os = new FileOutputStream(exportFile);
buffer = new BufferedOutputStream(os);
fileWriter = new OutputStreamWriter(buffer, CharEncoding.UTF_16);
fileWriter.write(fieldNoteBuffer.toString());
- } catch (IOException e) {
+ } catch (final IOException e) {
Log.e("FieldnoteExport.ExportTask export", e);
return false;
} finally {
@@ -181,17 +181,11 @@ class FieldnoteExport extends AbstractExport {
}
final String uri = "http://www.geocaching.com/my/uploadfieldnotes.aspx";
- String page = Network.getResponseData(Network.getRequest(uri));
+ final String page = Login.getRequestLogged(uri, null);
- if (!Login.getLoginStatus(page)) {
- // Login.isActualLoginStatus() was wrong, we are not logged in
- final StatusCode loginState = Login.login();
- if (loginState == StatusCode.NO_ERROR) {
- page = Network.getResponseData(Network.getRequest(uri));
- } else {
- Log.e("FieldnoteExport.ExportTask upload: No login (error: " + loginState + ')');
- return false;
- }
+ if (StringUtils.isBlank(page)) {
+ Log.e("FieldnoteExport.ExportTask get page: No data from server");
+ return false;
}
final String[] viewstates = Login.getViewstates(page);
diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java
index 66345da..ab2e281 100644
--- a/main/src/cgeo/geocaching/export/GpxExport.java
+++ b/main/src/cgeo/geocaching/export/GpxExport.java
@@ -1,24 +1,12 @@
package cgeo.geocaching.export;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
-import cgeo.geocaching.enumerations.CacheAttribute;
-import cgeo.geocaching.enumerations.LoadFlags;
-import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.utils.AsyncTaskWithProgress;
-import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.XmlUtils;
-import cgeo.org.kxml2.io.KXmlSerializer;
-
-import org.apache.commons.lang3.StringUtils;
-import org.xmlpull.v1.XmlSerializer;
import android.app.Activity;
import android.app.AlertDialog;
@@ -39,22 +27,11 @@ import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
-import java.util.Set;
class GpxExport extends AbstractExport {
- private static final SimpleDateFormat dateFormatZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
- public static final String PREFIX_XSI = "http://www.w3.org/2001/XMLSchema-instance";
- public static final String PREFIX_GPX = "http://www.topografix.com/GPX/1/0";
- public static final String PREFIX_GROUNDSPEAK = "http://www.groundspeak.com/cache/1/0";
-
- /**
- * During the export, only this number of geocaches is fully loaded into memory.
- */
- public static final int CACHES_PER_BATCH = 100;
protected GpxExport() {
super(getString(R.string.export_gpx));
@@ -62,7 +39,7 @@ class GpxExport extends AbstractExport {
@Override
public void export(final List<Geocache> caches, final Activity activity) {
- String[] geocodes = getGeocodes(caches);
+ final String[] geocodes = getGeocodes(caches);
if (null == activity) {
// No activity given, so no user interaction possible.
// Start export with default parameters.
@@ -75,10 +52,10 @@ class GpxExport extends AbstractExport {
}
private Dialog getExportDialog(final String[] geocodes, final Activity activity) {
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
// AlertDialog has always dark style, so we have to apply it as well always
- View layout = View.inflate(new ContextThemeWrapper(activity, R.style.dark), R.layout.gpx_export_dialog, null);
+ final View layout = View.inflate(new ContextThemeWrapper(activity, R.style.dark), R.layout.gpx_export_dialog, null);
builder.setView(layout);
final TextView text = (TextView) layout.findViewById(R.id.info);
@@ -108,7 +85,7 @@ class GpxExport extends AbstractExport {
}
private static String[] getGeocodes(final List<Geocache> caches) {
- ArrayList<String> allGeocodes = new ArrayList<String>(caches.size());
+ final ArrayList<String> allGeocodes = new ArrayList<String>(caches.size());
for (final Geocache geocache : caches) {
allGeocodes.add(geocache.getGeocode());
}
@@ -117,7 +94,6 @@ class GpxExport extends AbstractExport {
protected class ExportTask extends AsyncTaskWithProgress<String, File> {
private final Activity activity;
- private int countExported = 0;
/**
* Instantiates and configures the task for exporting field notes.
@@ -137,7 +113,7 @@ class GpxExport extends AbstractExport {
return null;
}
- List<String> allGeocodes = new ArrayList<String>(Arrays.asList(geocodes));
+ final List<String> allGeocodes = new ArrayList<String>(Arrays.asList(geocodes));
setMessage(cgeoapplication.getInstance().getResources().getQuantityString(R.plurals.cache_counts, allGeocodes.size(), allGeocodes.size()));
@@ -148,38 +124,21 @@ class GpxExport extends AbstractExport {
final File exportLocation = new File(Settings.getGpxExportDir());
exportLocation.mkdirs();
- final XmlSerializer gpx = new KXmlSerializer();
writer = new BufferedWriter(new FileWriter(exportFile));
- gpx.setOutput(writer);
+ new GpxSerializer().writeGPX(allGeocodes, writer, new GpxSerializer.ProgressListener() {
- gpx.startDocument("UTF-8", true);
- gpx.setPrefix("", PREFIX_GPX);
- gpx.setPrefix("xsi", PREFIX_XSI);
- gpx.setPrefix("groundspeak", PREFIX_GROUNDSPEAK);
- gpx.startTag(PREFIX_GPX, "gpx");
- gpx.attribute("", "version", "1.0");
- gpx.attribute("", "creator", "c:geo - http://www.cgeo.org/");
- gpx.attribute(PREFIX_XSI, "schemaLocation",
- PREFIX_GPX + " http://www.topografix.com/GPX/1/0/gpx.xsd " +
- PREFIX_GROUNDSPEAK + " http://www.groundspeak.com/cache/1/0/1/cache.xsd");
-
- // Split the overall set of geocodes into small chunks. That is a compromise between memory efficiency (because
- // we don't load all caches fully into memory) and speed (because we don't query each cache separately).
- while (!allGeocodes.isEmpty()) {
- final List<String> batch = allGeocodes.subList(0, Math.min(CACHES_PER_BATCH, allGeocodes.size()));
- exportBatch(gpx, batch);
- batch.clear();
- }
-
- gpx.endTag(PREFIX_GPX, "gpx");
- gpx.endDocument();
+ @Override
+ public void publishProgress(int countExported) {
+ ExportTask.this.publishProgress(countExported);
+ }
+ });
} catch (final Exception e) {
Log.e("GpxExport.ExportTask export", e);
if (writer != null) {
try {
writer.close();
- } catch (IOException e1) {
+ } catch (final IOException e1) {
// Ignore double error
}
}
@@ -194,184 +153,13 @@ class GpxExport extends AbstractExport {
return exportFile;
}
- private void exportBatch(final XmlSerializer gpx, Collection<String> geocodesOfBatch) throws IOException {
- Set<Geocache> caches = cgData.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY);
- for (Geocache cache : caches) {
- gpx.startTag(PREFIX_GPX, "wpt");
- gpx.attribute("", "lat", Double.toString(cache.getCoords().getLatitude()));
- gpx.attribute("", "lon", Double.toString(cache.getCoords().getLongitude()));
-
- final Date hiddenDate = cache.getHiddenDate();
- if (hiddenDate != null) {
- XmlUtils.simpleText(gpx, PREFIX_GPX, "time", dateFormatZ.format(hiddenDate));
- }
-
- XmlUtils.multipleTexts(gpx, PREFIX_GPX,
- "name", cache.getGeocode(),
- "desc", cache.getName(),
- "url", cache.getUrl(),
- "urlname", cache.getName(),
- "sym", cache.isFound() ? "Geocache Found" : "Geocache",
- "type", "Geocache|" + cache.getType().pattern);
-
- gpx.startTag(PREFIX_GROUNDSPEAK, "cache");
- gpx.attribute("", "id", cache.getCacheId());
- gpx.attribute("", "available", !cache.isDisabled() ? "True" : "False");
- gpx.attribute("", "archives", cache.isArchived() ? "True" : "False");
-
- XmlUtils.multipleTexts(gpx, PREFIX_GROUNDSPEAK,
- "name", cache.getName(),
- "placed_by", cache.getOwnerDisplayName(),
- "owner", cache.getOwnerUserId(),
- "type", cache.getType().pattern,
- "container", cache.getSize().id,
- "difficulty", Float.toString(cache.getDifficulty()),
- "terrain", Float.toString(cache.getTerrain()),
- "country", cache.getLocation(),
- "state", "",
- "encoded_hints", cache.getHint());
-
- writeAttributes(gpx, cache);
-
- gpx.startTag(PREFIX_GROUNDSPEAK, "short_description");
- gpx.attribute("", "html", BaseUtils.containsHtml(cache.getShortDescription()) ? "True" : "False");
- gpx.text(cache.getShortDescription());
- gpx.endTag(PREFIX_GROUNDSPEAK, "short_description");
-
- gpx.startTag(PREFIX_GROUNDSPEAK, "long_description");
- gpx.attribute("", "html", BaseUtils.containsHtml(cache.getDescription()) ? "True" : "False");
- gpx.text(cache.getDescription());
- gpx.endTag(PREFIX_GROUNDSPEAK, "long_description");
-
- writeLogs(gpx, cache);
-
- gpx.endTag(PREFIX_GROUNDSPEAK, "cache");
- gpx.endTag(PREFIX_GPX, "wpt");
-
- writeWaypoints(gpx, cache);
-
- countExported++;
- publishProgress(countExported);
- }
- }
-
- private void writeWaypoints(final XmlSerializer gpx, final Geocache cache) throws IOException {
- List<Waypoint> waypoints = cache.getWaypoints();
- List<Waypoint> ownWaypoints = new ArrayList<Waypoint>(waypoints.size());
- List<Waypoint> originWaypoints = new ArrayList<Waypoint>(waypoints.size());
- for (Waypoint wp : cache.getWaypoints()) {
- if (wp.isUserDefined()) {
- ownWaypoints.add(wp);
- } else {
- originWaypoints.add(wp);
- }
- }
- int maxPrefix = 0;
- for (Waypoint wp : originWaypoints) {
- String prefix = wp.getPrefix();
- try {
- final int numericPrefix = Integer.parseInt(prefix);
- maxPrefix = Math.max(numericPrefix, maxPrefix);
- } catch (NumberFormatException ex) {
- // ignore non numeric prefix, as it should be unique in the list of non-own waypoints already
- }
- writeCacheWaypoint(gpx, wp, prefix);
- }
- // Prefixes must be unique. There use numeric strings as prefixes in OWN waypoints
- for (Waypoint wp : ownWaypoints) {
- maxPrefix++;
- String prefix = StringUtils.leftPad(String.valueOf(maxPrefix), 2, '0');
- writeCacheWaypoint(gpx, wp, prefix);
- }
- }
-
- /**
- * Writes one waypoint entry for cache waypoint.
- *
- * @param cache
- * The
- * @param wp
- * @param prefix
- * @throws IOException
- */
- private void writeCacheWaypoint(final XmlSerializer gpx, final Waypoint wp, final String prefix) throws IOException {
- final Geopoint coords = wp.getCoords();
- // TODO: create some extension to GPX to include waypoint without coords
- if (coords != null) {
- gpx.startTag(PREFIX_GPX, "wpt");
- gpx.attribute("", "lat", Double.toString(coords.getLatitude()));
- gpx.attribute("", "lon", Double.toString(coords.getLongitude()));
- XmlUtils.multipleTexts(gpx, PREFIX_GPX,
- "name", prefix + wp.getGeocode().substring(2),
- "cmt", wp.getNote(),
- "desc", wp.getName(),
- "sym", wp.getWaypointType().toString(), //TODO: Correct identifier string
- "type", "Waypoint|" + wp.getWaypointType().toString()); //TODO: Correct identifier string
- gpx.endTag(PREFIX_GPX, "wpt");
- }
- }
-
- private void writeLogs(final XmlSerializer gpx, final Geocache cache) throws IOException {
- if (cache.getLogs().isEmpty()) {
- return;
- }
- gpx.startTag(PREFIX_GROUNDSPEAK, "logs");
-
- for (LogEntry log : cache.getLogs()) {
- gpx.startTag(PREFIX_GROUNDSPEAK, "log");
- gpx.attribute("", "id", Integer.toString(log.id));
-
- XmlUtils.multipleTexts(gpx, PREFIX_GROUNDSPEAK,
- "date", dateFormatZ.format(new Date(log.date)),
- "type", log.type.type);
-
- gpx.startTag(PREFIX_GROUNDSPEAK, "finder");
- gpx.attribute("", "id", "");
- gpx.text(log.author);
- gpx.endTag(PREFIX_GROUNDSPEAK, "finder");
-
- gpx.startTag(PREFIX_GROUNDSPEAK, "text");
- gpx.attribute("", "encoded", "False");
- gpx.text(log.log);
- gpx.endTag(PREFIX_GROUNDSPEAK, "text");
-
- gpx.endTag(PREFIX_GROUNDSPEAK, "log");
- }
-
- gpx.endTag(PREFIX_GROUNDSPEAK, "logs");
- }
-
- private void writeAttributes(final XmlSerializer gpx, final Geocache cache) throws IOException {
- if (cache.getAttributes().isEmpty()) {
- return;
- }
- //TODO: Attribute conversion required: English verbose name, gpx-id
- gpx.startTag(PREFIX_GROUNDSPEAK, "attributes");
-
- for (String attribute : cache.getAttributes()) {
- final CacheAttribute attr = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attribute));
- if (attr == null) {
- continue;
- }
- final boolean enabled = CacheAttribute.isEnabled(attribute);
-
- gpx.startTag(PREFIX_GROUNDSPEAK, "attribute");
- gpx.attribute("", "id", Integer.toString(attr.gcid));
- gpx.attribute("", "inc", enabled ? "1" : "0");
- gpx.text(attr.getL10n(enabled));
- gpx.endTag(PREFIX_GROUNDSPEAK, "attribute");
- }
-
- gpx.endTag(PREFIX_GROUNDSPEAK, "attributes");
- }
-
@Override
protected void onPostExecuteInternal(final File exportFile) {
if (null != activity) {
if (exportFile != null) {
ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString());
if (Settings.getShareAfterExport()) {
- Intent shareIntent = new Intent();
+ final Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(exportFile));
shareIntent.setType("application/xml");
diff --git a/main/src/cgeo/geocaching/export/GpxSerializer.java b/main/src/cgeo/geocaching/export/GpxSerializer.java
new file mode 100644
index 0000000..2d25296
--- /dev/null
+++ b/main/src/cgeo/geocaching/export/GpxSerializer.java
@@ -0,0 +1,255 @@
+package cgeo.geocaching.export;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.LogEntry;
+import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.cgData;
+import cgeo.geocaching.enumerations.CacheAttribute;
+import cgeo.geocaching.enumerations.LoadFlags;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.utils.TextUtils;
+import cgeo.geocaching.utils.XmlUtils;
+import cgeo.org.kxml2.io.KXmlSerializer;
+
+import org.apache.commons.lang3.StringUtils;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+public final class GpxSerializer {
+
+ private static final SimpleDateFormat dateFormatZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
+ public static final String PREFIX_XSI = "http://www.w3.org/2001/XMLSchema-instance";
+ public static final String PREFIX_GPX = "http://www.topografix.com/GPX/1/0";
+ public static final String PREFIX_GROUNDSPEAK = "http://www.groundspeak.com/cache/1/0";
+
+ /**
+ * During the export, only this number of geocaches is fully loaded into memory.
+ */
+ public static final int CACHES_PER_BATCH = 100;
+
+ /**
+ * counter for exported caches, used for progress reporting
+ */
+ private int countExported;
+ private ProgressListener progressListener;
+ private final XmlSerializer gpx = new KXmlSerializer();
+
+ protected static interface ProgressListener {
+
+ void publishProgress(int countExported);
+
+ }
+
+ public void writeGPX(List<String> allGeocodesIn, Writer writer, final ProgressListener progressListener) throws IOException {
+ // create a copy of the geocode list, as we need to modify it, but it might be immutable
+ final ArrayList<String> allGeocodes = new ArrayList<String>(allGeocodesIn);
+
+ this.progressListener = progressListener;
+ gpx.setOutput(writer);
+
+ gpx.startDocument("UTF-8", true);
+ gpx.setPrefix("", PREFIX_GPX);
+ gpx.setPrefix("xsi", PREFIX_XSI);
+ gpx.setPrefix("groundspeak", PREFIX_GROUNDSPEAK);
+ gpx.startTag(PREFIX_GPX, "gpx");
+ gpx.attribute("", "version", "1.0");
+ gpx.attribute("", "creator", "c:geo - http://www.cgeo.org/");
+ gpx.attribute(PREFIX_XSI, "schemaLocation",
+ PREFIX_GPX + " http://www.topografix.com/GPX/1/0/gpx.xsd " +
+ PREFIX_GROUNDSPEAK + " http://www.groundspeak.com/cache/1/0/1/cache.xsd");
+
+ // Split the overall set of geocodes into small chunks. That is a compromise between memory efficiency (because
+ // we don't load all caches fully into memory) and speed (because we don't query each cache separately).
+ while (!allGeocodes.isEmpty()) {
+ final List<String> batch = allGeocodes.subList(0, Math.min(CACHES_PER_BATCH, allGeocodes.size()));
+ exportBatch(gpx, batch);
+ batch.clear();
+ }
+
+ gpx.endTag(PREFIX_GPX, "gpx");
+ gpx.endDocument();
+ }
+
+ private void exportBatch(final XmlSerializer gpx, Collection<String> geocodesOfBatch) throws IOException {
+ final Set<Geocache> caches = cgData.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY);
+ for (final Geocache cache : caches) {
+ gpx.startTag(PREFIX_GPX, "wpt");
+ gpx.attribute("", "lat", Double.toString(cache.getCoords().getLatitude()));
+ gpx.attribute("", "lon", Double.toString(cache.getCoords().getLongitude()));
+
+ final Date hiddenDate = cache.getHiddenDate();
+ if (hiddenDate != null) {
+ XmlUtils.simpleText(gpx, PREFIX_GPX, "time", dateFormatZ.format(hiddenDate));
+ }
+
+ XmlUtils.multipleTexts(gpx, PREFIX_GPX,
+ "name", cache.getGeocode(),
+ "desc", cache.getName(),
+ "url", cache.getUrl(),
+ "urlname", cache.getName(),
+ "sym", cache.isFound() ? "Geocache Found" : "Geocache",
+ "type", "Geocache|" + cache.getType().pattern);
+
+ gpx.startTag(PREFIX_GROUNDSPEAK, "cache");
+ gpx.attribute("", "id", cache.getCacheId());
+ gpx.attribute("", "available", !cache.isDisabled() ? "True" : "False");
+ gpx.attribute("", "archives", cache.isArchived() ? "True" : "False");
+
+ XmlUtils.multipleTexts(gpx, PREFIX_GROUNDSPEAK,
+ "name", cache.getName(),
+ "placed_by", cache.getOwnerDisplayName(),
+ "owner", cache.getOwnerUserId(),
+ "type", cache.getType().pattern,
+ "container", cache.getSize().id,
+ "difficulty", Float.toString(cache.getDifficulty()),
+ "terrain", Float.toString(cache.getTerrain()),
+ "country", cache.getLocation(),
+ "state", "",
+ "encoded_hints", cache.getHint());
+
+ writeAttributes(cache);
+
+ gpx.startTag(PREFIX_GROUNDSPEAK, "short_description");
+ gpx.attribute("", "html", TextUtils.containsHtml(cache.getShortDescription()) ? "True" : "False");
+ gpx.text(cache.getShortDescription());
+ gpx.endTag(PREFIX_GROUNDSPEAK, "short_description");
+
+ gpx.startTag(PREFIX_GROUNDSPEAK, "long_description");
+ gpx.attribute("", "html", TextUtils.containsHtml(cache.getDescription()) ? "True" : "False");
+ gpx.text(cache.getDescription());
+ gpx.endTag(PREFIX_GROUNDSPEAK, "long_description");
+
+ writeLogs(cache);
+
+ gpx.endTag(PREFIX_GROUNDSPEAK, "cache");
+ gpx.endTag(PREFIX_GPX, "wpt");
+
+ writeWaypoints(cache);
+
+ countExported++;
+ if (progressListener != null) {
+ progressListener.publishProgress(countExported);
+ }
+ }
+ }
+
+ private void writeWaypoints(final Geocache cache) throws IOException {
+ final List<Waypoint> waypoints = cache.getWaypoints();
+ final List<Waypoint> ownWaypoints = new ArrayList<Waypoint>(waypoints.size());
+ final List<Waypoint> originWaypoints = new ArrayList<Waypoint>(waypoints.size());
+ for (final Waypoint wp : cache.getWaypoints()) {
+ if (wp.isUserDefined()) {
+ ownWaypoints.add(wp);
+ } else {
+ originWaypoints.add(wp);
+ }
+ }
+ int maxPrefix = 0;
+ for (final Waypoint wp : originWaypoints) {
+ final String prefix = wp.getPrefix();
+ try {
+ final int numericPrefix = Integer.parseInt(prefix);
+ maxPrefix = Math.max(numericPrefix, maxPrefix);
+ } catch (final NumberFormatException ex) {
+ // ignore non numeric prefix, as it should be unique in the list of non-own waypoints already
+ }
+ writeCacheWaypoint(wp, prefix);
+ }
+ // Prefixes must be unique. There use numeric strings as prefixes in OWN waypoints
+ for (final Waypoint wp : ownWaypoints) {
+ maxPrefix++;
+ final String prefix = StringUtils.leftPad(String.valueOf(maxPrefix), 2, '0');
+ writeCacheWaypoint(wp, prefix);
+ }
+ }
+
+ /**
+ * Writes one waypoint entry for cache waypoint.
+ *
+ * @param cache
+ * The
+ * @param wp
+ * @param prefix
+ * @throws IOException
+ */
+ private void writeCacheWaypoint(final Waypoint wp, final String prefix) throws IOException {
+ final Geopoint coords = wp.getCoords();
+ // TODO: create some extension to GPX to include waypoint without coords
+ if (coords != null) {
+ gpx.startTag(PREFIX_GPX, "wpt");
+ gpx.attribute("", "lat", Double.toString(coords.getLatitude()));
+ gpx.attribute("", "lon", Double.toString(coords.getLongitude()));
+ XmlUtils.multipleTexts(gpx, PREFIX_GPX,
+ "name", prefix + wp.getGeocode().substring(2),
+ "cmt", wp.getNote(),
+ "desc", wp.getName(),
+ "sym", wp.getWaypointType().toString(), //TODO: Correct identifier string
+ "type", "Waypoint|" + wp.getWaypointType().toString()); //TODO: Correct identifier string
+ gpx.endTag(PREFIX_GPX, "wpt");
+ }
+ }
+
+ private void writeLogs(final Geocache cache) throws IOException {
+ if (cache.getLogs().isEmpty()) {
+ return;
+ }
+ gpx.startTag(PREFIX_GROUNDSPEAK, "logs");
+
+ for (final LogEntry log : cache.getLogs()) {
+ gpx.startTag(PREFIX_GROUNDSPEAK, "log");
+ gpx.attribute("", "id", Integer.toString(log.id));
+
+ XmlUtils.multipleTexts(gpx, PREFIX_GROUNDSPEAK,
+ "date", dateFormatZ.format(new Date(log.date)),
+ "type", log.type.type);
+
+ gpx.startTag(PREFIX_GROUNDSPEAK, "finder");
+ gpx.attribute("", "id", "");
+ gpx.text(log.author);
+ gpx.endTag(PREFIX_GROUNDSPEAK, "finder");
+
+ gpx.startTag(PREFIX_GROUNDSPEAK, "text");
+ gpx.attribute("", "encoded", "False");
+ gpx.text(log.log);
+ gpx.endTag(PREFIX_GROUNDSPEAK, "text");
+
+ gpx.endTag(PREFIX_GROUNDSPEAK, "log");
+ }
+
+ gpx.endTag(PREFIX_GROUNDSPEAK, "logs");
+ }
+
+ private void writeAttributes(final Geocache cache) throws IOException {
+ if (cache.getAttributes().isEmpty()) {
+ return;
+ }
+ //TODO: Attribute conversion required: English verbose name, gpx-id
+ gpx.startTag(PREFIX_GROUNDSPEAK, "attributes");
+
+ for (final String attribute : cache.getAttributes()) {
+ final CacheAttribute attr = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attribute));
+ if (attr == null) {
+ continue;
+ }
+ final boolean enabled = CacheAttribute.isEnabled(attribute);
+
+ gpx.startTag(PREFIX_GROUNDSPEAK, "attribute");
+ gpx.attribute("", "id", Integer.toString(attr.gcid));
+ gpx.attribute("", "inc", enabled ? "1" : "0");
+ gpx.text(attr.getL10n(enabled));
+ gpx.endTag(PREFIX_GROUNDSPEAK, "attribute");
+ }
+
+ gpx.endTag(PREFIX_GROUNDSPEAK, "attributes");
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java
index 10d791b..0b2e49f 100644
--- a/main/src/cgeo/geocaching/files/GPXImporter.java
+++ b/main/src/cgeo/geocaching/files/GPXImporter.java
@@ -57,12 +57,12 @@ public class GPXImporter {
private static final List<String> GPX_MIME_TYPES = Arrays.asList("text/xml", "application/xml");
private static final List<String> ZIP_MIME_TYPES = Arrays.asList("application/zip", "application/x-compressed", "application/x-zip-compressed", "application/x-zip", "application/octet-stream");
- private Progress progress = new Progress(true);
+ private final Progress progress = new Progress(true);
- private Resources res;
- private int listId;
- private IAbstractActivity fromActivity;
- private Handler importFinishedHandler;
+ private final Resources res;
+ private final int listId;
+ private final IAbstractActivity fromActivity;
+ private final Handler importFinishedHandler;
public GPXImporter(final IAbstractActivity fromActivity, final int listId, final Handler importFinishedHandler) {
this.listId = listId;
@@ -143,14 +143,12 @@ public class GPXImporter {
final Collection<Geocache> caches = doImport();
Log.i("Imported successfully " + caches.size() + " caches.");
- final SearchResult search = new SearchResult();
- for (Geocache cache : caches) {
- search.addAndPutInCache(cache);
- }
+ final SearchResult search = new SearchResult(caches);
+ // Do not put imported caches into the cachecache. That would consume lots of memory for no benefit.
if (Settings.isStoreOfflineMaps() || Settings.isStoreOfflineWpMaps()) {
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_STORE_STATIC_MAPS, R.string.gpx_import_store_static_maps, search.getCount()));
- boolean finishedWithoutCancel = importStaticMaps(search);
+ final boolean finishedWithoutCancel = importStaticMaps(search);
// Skip last message if static maps where canceled
if (!finishedWithoutCancel) {
return;
@@ -158,16 +156,16 @@ public class GPXImporter {
}
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED, search.getCount(), 0, search));
- } catch (IOException e) {
+ } catch (final IOException e) {
Log.i("Importing caches failed - error reading data: ", e);
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_io, 0, e.getLocalizedMessage()));
- } catch (ParserException e) {
+ } catch (final ParserException e) {
Log.i("Importing caches failed - data format error", e);
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_parser, 0, e.getLocalizedMessage()));
- } catch (CancellationException e) {
+ } catch (final CancellationException e) {
Log.i("Importing caches canceled");
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_CANCELED));
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("Importing caches failed - unknown error: ", e);
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_unexpected, 0, e.getLocalizedMessage()));
}
@@ -207,14 +205,14 @@ public class GPXImporter {
protected Collection<Geocache> doImport() throws IOException, ParserException {
Log.i("Import LOC file: " + file.getAbsolutePath());
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) file.length()));
- LocParser parser = new LocParser(listId);
+ final LocParser parser = new LocParser(listId);
return parser.parse(file, progressHandler);
}
}
static class ImportLocAttachmentThread extends ImportThread {
private final Uri uri;
- private ContentResolver contentResolver;
+ private final ContentResolver contentResolver;
public ImportLocAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
super(listId, importStepHandler, progressHandler);
@@ -226,8 +224,8 @@ public class GPXImporter {
protected Collection<Geocache> doImport() throws IOException, ParserException {
Log.i("Import LOC from uri: " + uri);
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, -1));
- InputStream is = contentResolver.openInputStream(uri);
- LocParser parser = new LocParser(listId);
+ final InputStream is = contentResolver.openInputStream(uri);
+ final LocParser parser = new LocParser(listId);
try {
return parser.parse(is, progressHandler);
} finally {
@@ -247,7 +245,7 @@ public class GPXImporter {
try {
// try to parse cache file as GPX 10
return doImport(new GPX10Parser(listId));
- } catch (ParserException pe) {
+ } catch (final ParserException pe) {
// didn't work -> lets try GPX11
return doImport(new GPX11Parser(listId));
}
@@ -285,7 +283,7 @@ public class GPXImporter {
static class ImportGpxAttachmentThread extends ImportGpxThread {
private final Uri uri;
- private ContentResolver contentResolver;
+ private final ContentResolver contentResolver;
public ImportGpxAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
super(listId, importStepHandler, progressHandler);
@@ -297,7 +295,7 @@ public class GPXImporter {
protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException {
Log.i("Import GPX from uri: " + uri);
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, -1));
- InputStream is = contentResolver.openInputStream(uri);
+ final InputStream is = contentResolver.openInputStream(uri);
try {
return parser.parse(is, progressHandler);
} finally {
@@ -371,7 +369,7 @@ public class GPXImporter {
static class ImportGpxZipAttachmentThread extends ImportGpxZipThread {
private final Uri uri;
- private ContentResolver contentResolver;
+ private final ContentResolver contentResolver;
public ImportGpxZipAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
super(listId, importStepHandler, progressHandler);
@@ -394,13 +392,11 @@ public class GPXImporter {
};
final private Handler importStepHandler = new Handler() {
- private boolean showProgressAfterCancel = false;
-
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case IMPORT_STEP_START:
- Message cancelMessage = importStepHandler.obtainMessage(IMPORT_STEP_CANCEL);
+ final Message cancelMessage = importStepHandler.obtainMessage(IMPORT_STEP_CANCEL);
progress.show((Context) fromActivity, res.getString(R.string.gpx_import_title_reading_file), res.getString(R.string.gpx_import_loading_caches), ProgressDialog.STYLE_HORIZONTAL, cancelMessage);
break;
@@ -412,7 +408,7 @@ public class GPXImporter {
case IMPORT_STEP_STORE_STATIC_MAPS:
progress.dismiss();
- Message skipMessage = importStepHandler.obtainMessage(IMPORT_STEP_STATIC_MAPS_SKIPPED, msg.arg2, 0);
+ final Message skipMessage = importStepHandler.obtainMessage(IMPORT_STEP_STATIC_MAPS_SKIPPED, msg.arg2, 0);
progress.show((Context) fromActivity, res.getString(R.string.gpx_import_title_static_maps), res.getString(R.string.gpx_import_store_static_maps), ProgressDialog.STYLE_HORIZONTAL, skipMessage);
progress.setMaxProgressAndReset(msg.arg2);
break;
@@ -420,7 +416,7 @@ public class GPXImporter {
case IMPORT_STEP_STATIC_MAPS_SKIPPED:
progress.dismiss();
progressHandler.cancel();
- StringBuilder bufferSkipped = new StringBuilder(20);
+ final StringBuilder bufferSkipped = new StringBuilder(20);
bufferSkipped.append(res.getString(R.string.gpx_import_static_maps_skipped)).append(", ").append(msg.arg1).append(' ').append(res.getString(R.string.gpx_import_caches_imported));
fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_imported), bufferSkipped.toString());
importFinished();
@@ -444,11 +440,8 @@ public class GPXImporter {
break;
case IMPORT_STEP_CANCELED:
- StringBuilder bufferCanceled = new StringBuilder(20);
+ final StringBuilder bufferCanceled = new StringBuilder(20);
bufferCanceled.append(res.getString(R.string.gpx_import_canceled));
- if (showProgressAfterCancel) {
- bufferCanceled.append(", ").append(progress.getProgress()).append(' ').append(res.getString(R.string.gpx_import_caches_imported));
- }
fromActivity.showShortToast(bufferCanceled.toString());
importFinished();
break;
@@ -469,13 +462,13 @@ public class GPXImporter {
return null;
}
final String gpxFileName = gpxfile.getName();
- File dir = gpxfile.getParentFile();
- String[] filenameList = dir.list();
- for (String filename : filenameList) {
+ final File dir = gpxfile.getParentFile();
+ final String[] filenameList = dir.list();
+ for (final String filename : filenameList) {
if (!StringUtils.containsIgnoreCase(filename, WAYPOINTS_FILE_SUFFIX)) {
continue;
}
- String expectedGpxFileName = StringUtils.substringBeforeLast(filename, WAYPOINTS_FILE_SUFFIX)
+ final String expectedGpxFileName = StringUtils.substringBeforeLast(filename, WAYPOINTS_FILE_SUFFIX)
+ StringUtils.substringAfterLast(filename, WAYPOINTS_FILE_SUFFIX);
if (gpxFileName.equals(expectedGpxFileName)) {
return filename;
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
index 8412207..f5ae381 100644
--- a/main/src/cgeo/geocaching/files/GPXParser.java
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -206,7 +206,7 @@ public abstract class GPXParser extends FileParser {
String stringName;
try {
stringName = cgeoapplication.getInstance().getResources().getResourceName(stringId);
- } catch (NullPointerException e) {
+ } catch (final NullPointerException e) {
return null;
}
if (stringName == null) {
@@ -272,7 +272,7 @@ public abstract class GPXParser extends FileParser {
Double.valueOf(longitude)));
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("Failed to parse waypoint's latitude and/or longitude.");
}
}
@@ -313,6 +313,8 @@ public abstract class GPXParser extends FileParser {
// finally store the cache in the database
result.add(geocode);
cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+
+ // avoid the cachecache using lots of memory for caches which the user did not actually look at
cgData.removeAllFromCache();
showProgressMessage(progressHandler, progressStream.getProgress());
} else if (StringUtils.isNotBlank(cache.getName())
@@ -361,7 +363,7 @@ public abstract class GPXParser extends FileParser {
public void end(String body) {
try {
cache.setHidden(parseDate(body));
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("Failed to parse cache date", e);
}
}
@@ -441,7 +443,7 @@ public abstract class GPXParser extends FileParser {
}
final MatcherWrapper matcherCode = new MatcherWrapper(patternUrlGeocode, url);
if (matcherCode.matches()) {
- String geocode = matcherCode.group(1);
+ final String geocode = matcherCode.group(1);
cache.setGeocode(geocode);
}
}
@@ -463,7 +465,7 @@ public abstract class GPXParser extends FileParser {
final Element cacheParent = getCacheParent(waypoint);
// GSAK extensions
- for (String gsakNamespace : GSAK_NS) {
+ for (final String gsakNamespace : GSAK_NS) {
final Element gsak = cacheParent.getChild(gsakNamespace, "wptExtension");
gsak.getChild(gsakNamespace, "Watch").setEndTextElementListener(new EndTextElementListener() {
@@ -481,7 +483,7 @@ public abstract class GPXParser extends FileParser {
}
// 3 different versions of the GC schema
- for (String nsGC : nsGCList) {
+ for (final String nsGC : nsGCList) {
// waypoints.cache
final Element gcCache = cacheParent.getChild(nsGC, "cache");
@@ -499,7 +501,7 @@ public abstract class GPXParser extends FileParser {
if (attrs.getIndex("available") > -1) {
cache.setDisabled(!attrs.getValue("available").equalsIgnoreCase("true"));
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("Failed to parse cache attributes.");
}
}
@@ -568,14 +570,14 @@ public abstract class GPXParser extends FileParser {
public void start(Attributes attrs) {
try {
if (attrs.getIndex("id") > -1 && attrs.getIndex("inc") > -1) {
- int attributeId = Integer.parseInt(attrs.getValue("id"));
- boolean attributeActive = Integer.parseInt(attrs.getValue("inc")) != 0;
- String internalId = CacheAttributeTranslator.getInternalId(attributeId, attributeActive);
+ final int attributeId = Integer.parseInt(attrs.getValue("id"));
+ final boolean attributeActive = Integer.parseInt(attrs.getValue("inc")) != 0;
+ final String internalId = CacheAttributeTranslator.getInternalId(attributeId, attributeActive);
if (internalId != null) {
cache.getAttributes().add(internalId);
}
}
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
// nothing
}
}
@@ -588,7 +590,7 @@ public abstract class GPXParser extends FileParser {
public void end(String body) {
try {
cache.setDifficulty(Float.parseFloat(body));
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.w("Failed to parse difficulty", e);
}
}
@@ -601,7 +603,7 @@ public abstract class GPXParser extends FileParser {
public void end(String body) {
try {
cache.setTerrain(Float.parseFloat(body));
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.w("Failed to parse terrain", e);
}
}
@@ -625,7 +627,7 @@ public abstract class GPXParser extends FileParser {
@Override
public void end(String state) {
- String trimmedState = state.trim();
+ final String trimmedState = state.trim();
if (StringUtils.isNotEmpty(trimmedState)) { // state can be completely empty
if (StringUtils.isBlank(cache.getLocation())) {
cache.setLocation(validate(state));
@@ -678,7 +680,7 @@ public abstract class GPXParser extends FileParser {
if (attrs.getIndex("ref") > -1) {
trackable.setGeocode(attrs.getValue("ref"));
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// nothing
}
}
@@ -722,7 +724,7 @@ public abstract class GPXParser extends FileParser {
if (attrs.getIndex("id") > -1) {
log.id = Integer.parseInt(attrs.getValue("id"));
}
- } catch (Exception e) {
+ } catch (final Exception e) {
// nothing
}
}
@@ -745,7 +747,7 @@ public abstract class GPXParser extends FileParser {
public void end(String body) {
try {
log.date = parseDate(body).getTime();
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.w("Failed to parse log date", e);
}
}
@@ -784,7 +786,7 @@ public abstract class GPXParser extends FileParser {
progressStream = new ProgressInputStream(stream);
Xml.parse(progressStream, Xml.Encoding.UTF_8, root.getContentHandler());
return cgData.loadCaches(result, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL));
- } catch (SAXException e) {
+ } catch (final SAXException e) {
Log.w("Cannot parse .gpx file as GPX " + version + ": could not parse XML - ", e);
throw new ParserException("Cannot parse .gpx file as GPX " + version + ": could not parse XML", e);
}
@@ -831,7 +833,7 @@ public abstract class GPXParser extends FileParser {
return WaypointType.FINAL;
}
// this is not fully correct, but lets also look for localized waypoint types
- for (WaypointType waypointType : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) {
+ for (final WaypointType waypointType : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) {
final String localized = waypointType.getL10n();
if (StringUtils.isNotEmpty(localized)) {
if (localized.equalsIgnoreCase(sym)) {
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java
index 616a951..0649e12 100644
--- a/main/src/cgeo/geocaching/network/HtmlImage.java
+++ b/main/src/cgeo/geocaching/network/HtmlImage.java
@@ -7,7 +7,7 @@ import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.files.LocalStorage;
import cgeo.geocaching.utils.IOUtils;
-import cgeo.geocaching.utils.ImageHelper;
+import cgeo.geocaching.utils.ImageUtils;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
@@ -132,7 +132,7 @@ public class HtmlImage implements Html.ImageGetter {
}
}
- return imagePre != null ? ImageHelper.scaleBitmapToFitDisplay(imagePre) : null;
+ return imagePre != null ? ImageUtils.scaleBitmapToFitDisplay(imagePre) : null;
}
/**
diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java
index 5a8cbb2..57196c5 100644
--- a/main/src/cgeo/geocaching/network/Network.java
+++ b/main/src/cgeo/geocaching/network/Network.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.network;
import cgeo.geocaching.Settings;
import cgeo.geocaching.files.LocalStorage;
-import cgeo.geocaching.utils.BaseUtils;
+import cgeo.geocaching.utils.TextUtils;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.Header;
@@ -418,7 +418,7 @@ public abstract class Network {
private static String getResponseDataNoError(final HttpResponse response, boolean replaceWhitespace) {
try {
String data = EntityUtils.toString(response.getEntity(), CharEncoding.UTF_8);
- return replaceWhitespace ? BaseUtils.replaceWhitespace(data) : data;
+ return replaceWhitespace ? TextUtils.replaceWhitespace(data) : data;
} catch (Exception e) {
Log.e("getResponseData", e);
return null;
@@ -428,7 +428,7 @@ public abstract class Network {
/**
* Get the body of a HTTP response.
*
- * {@link BaseUtils#replaceWhitespace(String)} will be called on the result
+ * {@link TextUtils#replaceWhitespace(String)} will be called on the result
*
* @param response a HTTP response, which can be null
* @return the body if the response comes from a successful HTTP request, <code>null</code> otherwise
@@ -441,7 +441,7 @@ public abstract class Network {
* Get the body of a HTTP response.
*
* @param response a HTTP response, which can be null
- * @param replaceWhitespace <code>true</code> if {@link BaseUtils#replaceWhitespace(String)}
+ * @param replaceWhitespace <code>true</code> if {@link TextUtils#replaceWhitespace(String)}
* should be called on the body
* @return the body if the response comes from a successful HTTP request, <code>null</code> otherwise
*/
diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java
index bfc77ba..d54f706 100644
--- a/main/src/cgeo/geocaching/network/StatusUpdater.java
+++ b/main/src/cgeo/geocaching/network/StatusUpdater.java
@@ -9,6 +9,8 @@ import cgeo.geocaching.utils.Version;
import org.json.JSONException;
import org.json.JSONObject;
+import android.os.Build.VERSION;
+import android.os.Build.VERSION_CODES;
import android.os.Looper;
import java.util.Locale;
@@ -27,6 +29,13 @@ public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implement
this.icon = icon;
this.url = url;
}
+
+ final static public Status closeoutStatus =
+ new Status("", "status_closeout_warning", "attribute_abandonedbuilding", "http://www.cgeo.org/closeout/");
+
+ final static public Status defaultStatus() {
+ return VERSION.SDK_INT < VERSION_CODES.ECLAIR_MR1 ? closeoutStatus : null;
+ }
}
@Override
diff --git a/main/src/cgeo/geocaching/speech/SpeechService.java b/main/src/cgeo/geocaching/speech/SpeechService.java
index 7226014..7bc948d 100644
--- a/main/src/cgeo/geocaching/speech/SpeechService.java
+++ b/main/src/cgeo/geocaching/speech/SpeechService.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.speech;
import cgeo.geocaching.DirectionProvider;
+import cgeo.geocaching.Settings;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
@@ -37,8 +38,8 @@ public class SpeechService extends Service implements OnInitListener {
private boolean initialized = false;
protected float direction;
protected Geopoint position;
- protected boolean directionInitialized;
- protected boolean positionInitialized;
+ protected boolean directionInitialized = !Settings.isUseCompass(); // don't wait for magnetometer, if it shall not be used
+ protected boolean positionInitialized = false;
GeoDirHandler geoHandler = new GeoDirHandler() {
@Override
diff --git a/main/src/cgeo/geocaching/speech/TextFactory.java b/main/src/cgeo/geocaching/speech/TextFactory.java
index 0e13564..e367bb1 100644
--- a/main/src/cgeo/geocaching/speech/TextFactory.java
+++ b/main/src/cgeo/geocaching/speech/TextFactory.java
@@ -22,50 +22,80 @@ public class TextFactory {
}
private static String getDistance(Geopoint position, Geopoint target) {
- float kilometers = position.distanceTo(target);
+ final float kilometers = position.distanceTo(target);
if (Settings.isUseMetricUnits()) {
- if (kilometers >= 5.0) {
- return getString(R.string.tts_kilometers, String.valueOf(Math.round(kilometers)));
- }
- if (kilometers >= 1.0) {
- String digits = String.format(Locale.getDefault(), "%.1f", kilometers);
- return getString(R.string.tts_kilometers, digits);
- }
- int meters = (int) (kilometers * 1000.0);
- if (meters > 50) {
- return getString(R.string.tts_meters, String.valueOf(Math.round(meters / 10.0) * 10));
- }
- return getString(R.string.tts_meters, String.valueOf(meters));
+ return getDistance(kilometers, (int) (kilometers * 1000.0),
+ 5.0f, 1.0f, 50,
+ R.plurals.tts_kilometers, R.string.tts_one_kilometer,
+ R.plurals.tts_meters, R.string.tts_one_meter);
}
+ return getDistance(kilometers / IConversion.MILES_TO_KILOMETER,
+ (int) (kilometers * 1000.0 * IConversion.METERS_TO_FEET),
+ 3.0f, 0.2f, 300,
+ R.plurals.tts_miles, R.string.tts_one_mile,
+ R.plurals.tts_feet, R.string.tts_one_foot);
+ }
- float miles = kilometers / IConversion.MILES_TO_KILOMETER;
- if (miles >= 3.0) {
- return getString(R.string.tts_miles, String.valueOf(Math.round(miles)));
+ private static String getDistance(float farDistance, int nearDistance,
+ float farFarAway, float farNearAway, int nearFarAway,
+ int farId, int farOneId, int nearId, int nearOneId) {
+ if (farDistance >= farFarAway) {
+ // example: "5 kilometers" - always without decimal digits
+ final int quantity = Math.round(farDistance);
+ if (quantity == 1) {
+ return getString(farOneId, quantity, String.valueOf(quantity));
+ }
+ return getQuantityString(farId, quantity, String.valueOf(quantity));
}
- if (miles >= 0.2) { // approx 1000 ft
- String digits = String.format(Locale.getDefault(), "%.1f", miles);
- return getString(R.string.tts_miles, digits);
+ if (farDistance >= farNearAway) {
+ // example: "2.2 kilometers" - decimals if necessary
+ final float precision1 = Math.round(farDistance * 10.0f) / 10.0f;
+ final float precision0 = Math.round(farDistance);
+ if (Math.abs(precision1 - precision0) < 0.0001) {
+ // this is an int - e.g. 2 kilometers
+ final int quantity = (int) precision0;
+ if (quantity == 1) {
+ return getString(farOneId, quantity, String.valueOf(quantity));
+ }
+ return getQuantityString(farId, quantity, String.valueOf(quantity));
+ }
+ // this is no int - e.g. 1.7 kilometers
+ final String digits = String.format(Locale.getDefault(), "%.1f", farDistance);
+ // always use the plural (9 leads to plural)
+ return getQuantityString(farId, 9, digits);
+ }
+ // example: "34 meters"
+ int quantity = nearDistance;
+ if (quantity > nearFarAway) {
+ // example: "120 meters" - rounded to 10 meters
+ quantity = (int) Math.round(quantity / 10.0) * 10;
}
- int feet = (int) (kilometers * 1000.0 * IConversion.METERS_TO_FEET);
- if (feet > 300) {
- return getString(R.string.tts_feet, String.valueOf(Math.round(feet / 10.0) * 10));
+ if (quantity == 1) {
+ return getString(nearOneId, quantity, String.valueOf(quantity));
}
- return getString(R.string.tts_feet, String.valueOf(feet));
+ return getQuantityString(nearId, quantity, String.valueOf(quantity));
}
private static String getString(int resourceId, Object... formatArgs) {
return cgeoapplication.getInstance().getString(resourceId, formatArgs);
}
+ private static String getQuantityString(int resourceId, int quantity, Object... formatArgs) {
+ return cgeoapplication.getInstance().getResources().getQuantityString(resourceId, quantity, formatArgs);
+ }
+
private static String getDirection(Geopoint position, Geopoint target, float direction) {
final int bearing = (int) position.bearingTo(target);
- int degrees = (int) AngleUtils.normalize(bearing - direction);
+ final int degrees = (int) AngleUtils.normalize(bearing - direction);
int hours = (degrees + 15) / 30;
if (hours == 0) {
hours = 12;
}
+ if (hours == 1) {
+ return getString(R.string.tts_one_oclock, String.valueOf(hours));
+ }
return getString(R.string.tts_oclock, String.valueOf(hours));
}
}
diff --git a/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java b/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java
new file mode 100644
index 0000000..b717568
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java
@@ -0,0 +1,76 @@
+package cgeo.geocaching.ui;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.cgeocaches;
+import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.network.Network;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.view.View;
+
+abstract class AbstractUserClickListener implements View.OnClickListener {
+
+ private final boolean enabled;
+
+ public AbstractUserClickListener(final boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (view == null) {
+ return;
+ }
+ if (!enabled) {
+ return;
+ }
+
+ showUserActionsDialog(getUserName(view), view);
+ }
+
+ protected abstract CharSequence getUserName(View view);
+
+ /**
+ * Opens a dialog to do actions on an user name
+ */
+ protected static void showUserActionsDialog(final CharSequence name, final View view) {
+ final AbstractActivity context = (AbstractActivity) view.getContext();
+ final Resources res = context.getResources();
+ final CharSequence[] items = { res.getString(R.string.user_menu_view_hidden),
+ res.getString(R.string.user_menu_view_found),
+ res.getString(R.string.user_menu_open_browser),
+ res.getString(R.string.user_menu_send_message)
+ };
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(res.getString(R.string.user_menu_title) + " " + name);
+ builder.setItems(items, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int item) {
+ switch (item) {
+ case 0:
+ cgeocaches.startActivityOwner(context, name.toString());
+ return;
+ case 1:
+ cgeocaches.startActivityUserName(context, name.toString());
+ return;
+ case 2:
+ context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(name.toString()))));
+ return;
+ case 3:
+ context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/email/?u=" + Network.encode(name.toString()))));
+ return;
+ default:
+ break;
+ }
+ }
+ });
+ final AlertDialog alert = builder.create();
+ alert.show();
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java
index c926057..b73a2a9 100644
--- a/main/src/cgeo/geocaching/ui/CompassView.java
+++ b/main/src/cgeo/geocaching/ui/CompassView.java
@@ -171,12 +171,12 @@ public class CompassView extends View implements PeriodicHandlerListener {
headingDrawn = cacheHeadingShown;
}
- float azimuthTemp = azimuthDrawn;
+ final float azimuthTemp = azimuthDrawn;
final float azimuthRelative = AngleUtils.normalize(azimuthTemp - headingDrawn);
// compass margins
- int canvasCenterX = (compassRoseWidth / 2) + ((getWidth() - compassRoseWidth) / 2);
- int canvasCenterY = (compassRoseHeight / 2) + ((getHeight() - compassRoseHeight) / 2);
+ final int canvasCenterX = (compassRoseWidth / 2) + ((getWidth() - compassRoseWidth) / 2);
+ final int canvasCenterY = (compassRoseHeight / 2) + ((getHeight() - compassRoseHeight) / 2);
super.onDraw(canvas);
@@ -217,38 +217,36 @@ public class CompassView extends View implements PeriodicHandlerListener {
}
private int measureWidth(int measureSpec) {
- int result;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
+ final int specMode = MeasureSpec.getMode(measureSpec);
+ final int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
- result = specSize;
- } else {
- result = compassArrow.getWidth() + getPaddingLeft() + getPaddingRight();
+ return specSize;
+ }
- if (specMode == MeasureSpec.AT_MOST) {
- result = Math.min(result, specSize);
- }
+ final int desired = compassArrow.getWidth() + getPaddingLeft() + getPaddingRight();
+ if (specMode == MeasureSpec.AT_MOST) {
+ return Math.min(desired, specSize);
}
- return result;
+ return desired;
}
private int measureHeight(int measureSpec) {
- int result;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
+ // The duplicated code in measureHeight and measureWidth cannot be avoided.
+ // Those methods must be efficient, therefore we cannot extract the code differences and unify the remainder.
+ final int specMode = MeasureSpec.getMode(measureSpec);
+ final int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
- result = specSize;
- } else {
- result = compassArrow.getHeight() + getPaddingTop() + getPaddingBottom();
+ return specSize;
+ }
- if (specMode == MeasureSpec.AT_MOST) {
- result = Math.min(result, specSize);
- }
+ final int desired = compassArrow.getHeight() + getPaddingTop() + getPaddingBottom();
+ if (specMode == MeasureSpec.AT_MOST) {
+ return Math.min(desired, specSize);
}
- return result;
+ return desired;
}
}
diff --git a/main/src/cgeo/geocaching/ui/HtmlImageCounter.java b/main/src/cgeo/geocaching/ui/HtmlImageCounter.java
new file mode 100644
index 0000000..24b70ea
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/HtmlImageCounter.java
@@ -0,0 +1,19 @@
+package cgeo.geocaching.ui;
+
+import android.graphics.drawable.Drawable;
+import android.text.Html;
+
+public class HtmlImageCounter implements Html.ImageGetter {
+
+ private int imageCount = 0;
+
+ @Override
+ public Drawable getDrawable(String url) {
+ imageCount++;
+ return null;
+ }
+
+ public int getImageCount() {
+ return imageCount;
+ }
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java b/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java
new file mode 100644
index 0000000..45ce237
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java
@@ -0,0 +1,31 @@
+package cgeo.geocaching.ui;
+
+import cgeo.geocaching.Geocache;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * Listener for clicks on owner name
+ */
+public class OwnerActionsClickListener extends AbstractUserClickListener {
+
+ private final Geocache cache;
+
+ public OwnerActionsClickListener(Geocache cache) {
+ super(cache.supportsUserActions());
+ this.cache = cache;
+ }
+
+ @Override
+ protected String getUserName(View view) {
+ // Use real owner name vice the one owner chose to display
+ if (StringUtils.isNotBlank(cache.getOwnerUserId())) {
+ return cache.getOwnerUserId();
+ }
+ return ((TextView) view).getText().toString();
+ }
+}
+
diff --git a/main/src/cgeo/geocaching/ui/UserActionsClickListener.java b/main/src/cgeo/geocaching/ui/UserActionsClickListener.java
new file mode 100644
index 0000000..292074e
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/UserActionsClickListener.java
@@ -0,0 +1,26 @@
+package cgeo.geocaching.ui;
+
+import cgeo.geocaching.Geocache;
+
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * Listener for clicks on user name
+ */
+public class UserActionsClickListener extends AbstractUserClickListener {
+
+ public UserActionsClickListener(Geocache cache) {
+ super(cache.supportsUserActions());
+ }
+
+ public UserActionsClickListener() {
+ super(true);
+ }
+
+ @Override
+ protected CharSequence getUserName(View view) {
+ return ((TextView) view).getText().toString();
+ }
+}
+
diff --git a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
index 4ab9af0..60116f9 100644
--- a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
@@ -13,13 +13,10 @@ import cgeo.geocaching.geopoint.GeopointFormatter;
import org.apache.commons.lang3.StringUtils;
-import android.app.Dialog;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
@@ -28,7 +25,7 @@ import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
-public class CoordinatesInputDialog extends Dialog {
+public class CoordinatesInputDialog extends NoTitleDialog {
final private AbstractActivity context;
final private IGeoData geo;
@@ -65,13 +62,6 @@ public class CoordinatesInputDialog extends Dialog {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- try {
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
- } catch (Exception e) {
- // nothing
- }
-
setContentView(R.layout.coordinatesinput_dialog);
final Spinner spinner = (Spinner) findViewById(R.id.spinnerCoordinateFormats);
@@ -338,7 +328,7 @@ public class CoordinatesInputDialog extends Dialog {
if (currentFormat == coordInputFormatEnum.Plain) {
try {
gp = new Geopoint(eLat.getText().toString(), eLon.getText().toString());
- } catch (Geopoint.ParseException e) {
+ } catch (final Geopoint.ParseException e) {
if (signalError) {
context.showToast(context.getResources().getString(R.string.err_parse_lat_lon));
}
@@ -347,20 +337,20 @@ public class CoordinatesInputDialog extends Dialog {
return true;
}
- String latDir = bLat.getText().toString();
- String lonDir = bLon.getText().toString();
- String latDeg = eLatDeg.getText().toString();
- String lonDeg = eLonDeg.getText().toString();
- String latDegFrac = eLatMin.getText().toString();
- String lonDegFrac = eLonMin.getText().toString();
- String latMin = eLatMin.getText().toString();
- String lonMin = eLonMin.getText().toString();
- String latMinFrac = eLatSec.getText().toString();
- String lonMinFrac = eLonSec.getText().toString();
- String latSec = eLatSec.getText().toString();
- String lonSec = eLonSec.getText().toString();
- String latSecFrac = eLatSub.getText().toString();
- String lonSecFrac = eLonSub.getText().toString();
+ final String latDir = bLat.getText().toString();
+ final String lonDir = bLon.getText().toString();
+ final String latDeg = eLatDeg.getText().toString();
+ final String lonDeg = eLonDeg.getText().toString();
+ final String latDegFrac = eLatMin.getText().toString();
+ final String lonDegFrac = eLonMin.getText().toString();
+ final String latMin = eLatMin.getText().toString();
+ final String lonMin = eLonMin.getText().toString();
+ final String latMinFrac = eLatSec.getText().toString();
+ final String lonMinFrac = eLonSec.getText().toString();
+ final String latSec = eLatSec.getText().toString();
+ final String lonSec = eLonSec.getText().toString();
+ final String latSecFrac = eLatSub.getText().toString();
+ final String lonSecFrac = eLonSub.getText().toString();
switch (currentFormat) {
case Deg:
diff --git a/main/src/cgeo/geocaching/ui/dialog/DateDialog.java b/main/src/cgeo/geocaching/ui/dialog/DateDialog.java
index a9c579c..18f8e2e 100644
--- a/main/src/cgeo/geocaching/ui/dialog/DateDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/DateDialog.java
@@ -3,15 +3,12 @@ package cgeo.geocaching.ui.dialog;
import cgeo.geocaching.R;
import android.app.Activity;
-import android.app.Dialog;
import android.os.Bundle;
-import android.view.ViewGroup.LayoutParams;
-import android.view.Window;
import android.widget.DatePicker;
import java.util.Calendar;
-public class DateDialog extends Dialog {
+public class DateDialog extends NoTitleDialog {
public interface DateDialogParent {
abstract public void setDate(final Calendar date);
@@ -32,13 +29,6 @@ public class DateDialog extends Dialog {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- try {
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
- } catch (Exception e) {
- // nothing
- }
-
setContentView(R.layout.date);
final DatePicker picker = (DatePicker) findViewById(R.id.picker);
diff --git a/main/src/cgeo/geocaching/ui/dialog/NoTitleDialog.java b/main/src/cgeo/geocaching/ui/dialog/NoTitleDialog.java
new file mode 100644
index 0000000..fc5ebe6
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/dialog/NoTitleDialog.java
@@ -0,0 +1,30 @@
+package cgeo.geocaching.ui.dialog;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.ViewGroup.LayoutParams;
+import android.view.Window;
+
+public abstract class NoTitleDialog extends Dialog {
+
+ public NoTitleDialog(Context context) {
+ super(context);
+ }
+
+ public NoTitleDialog(Context context, int theme) {
+ super(context, theme);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ try {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ } catch (final Exception e) {
+ // nothing
+ }
+ }
+}
diff --git a/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java
new file mode 100644
index 0000000..a785681
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java
@@ -0,0 +1,101 @@
+package cgeo.geocaching.ui.logs;
+
+import cgeo.geocaching.CacheDetailActivity;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.LogEntry;
+import cgeo.geocaching.R;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.ui.UserActionsClickListener;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.content.res.Resources;
+import android.view.View;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class CacheLogsViewCreator extends LogsViewCreator {
+ private final boolean allLogs;
+ private final Geocache cache;
+ private final Resources res = cgeoapplication.getInstance().getResources();
+
+ public CacheLogsViewCreator(CacheDetailActivity cacheDetailActivity, final Geocache cache, boolean allLogs) {
+ super(cacheDetailActivity);
+ this.cache = cache;
+ this.allLogs = allLogs;
+ }
+
+ @Override
+ protected List<LogEntry> getLogs() {
+ return allLogs ? cache.getLogs() : cache.getFriendsLogs();
+ }
+
+ @Override
+ protected void addHeaderView() {
+ // adds the log counts
+ final Map<LogType, Integer> logCounts = cache.getLogCounts();
+ if (logCounts != null) {
+ final List<Entry<LogType, Integer>> sortedLogCounts = new ArrayList<Entry<LogType, Integer>>(logCounts.size());
+ for (final Entry<LogType, Integer> entry : logCounts.entrySet()) {
+ // it may happen that the label is unknown -> then avoid any output for this type
+ if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getKey().getL10n() != null) {
+ sortedLogCounts.add(entry);
+ }
+ }
+
+ if (!sortedLogCounts.isEmpty()) {
+ // sort the log counts by type id ascending. that way the FOUND, DNF log types are the first and most visible ones
+ Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() {
+
+ @Override
+ public int compare(Entry<LogType, Integer> logCountItem1, Entry<LogType, Integer> logCountItem2) {
+ return logCountItem1.getKey().compareTo(logCountItem2.getKey());
+ }
+ });
+
+ final ArrayList<String> labels = new ArrayList<String>(sortedLogCounts.size());
+ for (final Entry<LogType, Integer> pair : sortedLogCounts) {
+ labels.add(pair.getValue() + "× " + pair.getKey().getL10n());
+ }
+
+ final TextView countView = new TextView(activity);
+ countView.setText(res.getString(R.string.cache_log_types) + ": " + StringUtils.join(labels, ", "));
+ view.addHeaderView(countView, null, false);
+ }
+ }
+ }
+
+ @Override
+ protected void fillCountOrLocation(LogViewHolder holder, final LogEntry log) {
+ // finds count
+ if (log.found == -1) {
+ holder.countOrLocation.setVisibility(View.GONE);
+ } else {
+ holder.countOrLocation.setVisibility(View.VISIBLE);
+ holder.countOrLocation.setText(res.getQuantityString(R.plurals.cache_counts, log.found, log.found));
+ }
+ }
+
+ @Override
+ protected boolean isValid() {
+ return cache != null;
+ }
+
+ @Override
+ protected String getGeocode() {
+ return cache.getGeocode();
+ }
+
+ @Override
+ protected UserActionsClickListener createUserActionsListener() {
+ return new UserActionsClickListener(cache);
+ }
+
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/LogViewHolder.java b/main/src/cgeo/geocaching/ui/logs/LogViewHolder.java
index 14148d0..16f5537 100644
--- a/main/src/cgeo/geocaching/LogViewHolder.java
+++ b/main/src/cgeo/geocaching/ui/logs/LogViewHolder.java
@@ -1,7 +1,8 @@
-package cgeo.geocaching;
+package cgeo.geocaching.ui.logs;
import butterknife.InjectView;
+import cgeo.geocaching.R;
import cgeo.geocaching.ui.AbstractViewHolder;
import android.view.View;
diff --git a/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java
new file mode 100644
index 0000000..ee2713a
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java
@@ -0,0 +1,175 @@
+package cgeo.geocaching.ui.logs;
+
+import cgeo.geocaching.Image;
+import cgeo.geocaching.ImagesActivity;
+import cgeo.geocaching.LogEntry;
+import cgeo.geocaching.R;
+import cgeo.geocaching.StoredList;
+import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.Progress;
+import cgeo.geocaching.network.HtmlImage;
+import cgeo.geocaching.ui.AbstractCachingPageViewCreator;
+import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
+import cgeo.geocaching.ui.DecryptTextClickListener;
+import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.ui.HtmlImageCounter;
+import cgeo.geocaching.ui.UserActionsClickListener;
+import cgeo.geocaching.utils.TextUtils;
+import cgeo.geocaching.utils.UnknownTagsHandler;
+
+import org.apache.commons.lang3.StringEscapeUtils;
+
+import android.os.AsyncTask;
+import android.text.Html;
+import android.text.Spanned;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> {
+
+ protected final AbstractActivity activity;
+
+ public LogsViewCreator(AbstractActivity activity) {
+ this.activity = activity;
+ }
+
+ @Override
+ public ListView getDispatchedView() {
+ if (!isValid()) {
+ return null;
+ }
+
+ final List<LogEntry> logs = getLogs();
+
+ view = (ListView) activity.getLayoutInflater().inflate(R.layout.logs_page, null);
+ addHeaderView();
+ view.setAdapter(new ArrayAdapter<LogEntry>(activity, R.layout.logs_item, logs) {
+
+ @Override
+ public View getView(final int position, final View convertView, final android.view.ViewGroup parent) {
+ View rowView = convertView;
+ if (null == rowView) {
+ rowView = activity.getLayoutInflater().inflate(R.layout.logs_item, null);
+ }
+ LogViewHolder holder = (LogViewHolder) rowView.getTag();
+ if (null == holder) {
+ holder = new LogViewHolder(rowView);
+ }
+ holder.setPosition(position);
+
+ final LogEntry log = getItem(position);
+ fillViewHolder(convertView, holder, log);
+ return rowView;
+ }
+ });
+
+ return view;
+ }
+
+ protected void fillViewHolder(final View convertView, LogViewHolder holder, final LogEntry log) {
+ if (log.date > 0) {
+ holder.date.setText(Formatter.formatShortDateVerbally(log.date));
+ holder.date.setVisibility(View.VISIBLE);
+ } else {
+ holder.date.setVisibility(View.GONE);
+ }
+
+ holder.type.setText(log.type.getL10n());
+ holder.author.setText(StringEscapeUtils.unescapeHtml4(log.author));
+
+ fillCountOrLocation(holder, log);
+
+ // logtext, avoid parsing HTML if not necessary
+ String logText = log.log;
+ if (TextUtils.containsHtml(logText)) {
+ logText = log.getDisplayText();
+ // Fast preview: parse only HTML without loading any images
+ final HtmlImageCounter imageCounter = new HtmlImageCounter();
+ final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler();
+ holder.text.setText(Html.fromHtml(logText, imageCounter, unknownTagsHandler), TextView.BufferType.SPANNABLE);
+ if (imageCounter.getImageCount() > 0) {
+ // Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview
+ final LogImageLoader loader = new LogImageLoader(holder);
+ loader.execute(logText);
+ }
+ }
+ else {
+ holder.text.setText(logText, TextView.BufferType.SPANNABLE);
+ }
+
+ // images
+ if (log.hasLogImages()) {
+ holder.images.setText(log.getImageTitles());
+ holder.images.setVisibility(View.VISIBLE);
+ holder.images.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ ImagesActivity.startActivityLogImages(activity, getGeocode(), new ArrayList<Image>(log.getLogImages()));
+ }
+ });
+ } else {
+ holder.images.setVisibility(View.GONE);
+ }
+
+ // colored marker
+ final int marker = log.type.markerId;
+ if (marker != 0) {
+ holder.marker.setVisibility(View.VISIBLE);
+ holder.marker.setImageResource(marker);
+ }
+ else {
+ holder.marker.setVisibility(View.GONE);
+ }
+
+ if (null == convertView) {
+ holder.author.setOnClickListener(createUserActionsListener());
+ holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
+ holder.text.setOnClickListener(new DecryptTextClickListener());
+ activity.registerForContextMenu(holder.text);
+ }
+ }
+
+ abstract protected UserActionsClickListener createUserActionsListener();
+
+ abstract protected String getGeocode();
+
+ abstract protected List<LogEntry> getLogs();
+
+ abstract protected void addHeaderView();
+
+ abstract protected void fillCountOrLocation(LogViewHolder holder, final LogEntry log);
+
+ abstract protected boolean isValid();
+
+ /** Loads the Log Images outside the ui thread. */
+
+ private class LogImageLoader extends AsyncTask<String, Progress, Spanned> {
+ final private LogViewHolder holder;
+ final private int position;
+
+ public LogImageLoader(LogViewHolder holder) {
+ this.holder = holder;
+ this.position = holder.getPosition();
+ }
+
+ @Override
+ protected Spanned doInBackground(String... logtext) {
+ return Html.fromHtml(logtext[0], new HtmlImage(getGeocode(), false, StoredList.STANDARD_LIST_ID, false), null); //, TextView.BufferType.SPANNABLE)
+ }
+
+ @Override
+ protected void onPostExecute(Spanned result) {
+ // Ensure that this holder and its view still references the right item before updating the text.
+ if (position == holder.getPosition()) {
+ holder.text.setText(result);
+ }
+ }
+
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java
new file mode 100644
index 0000000..4c57406
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java
@@ -0,0 +1,70 @@
+package cgeo.geocaching.ui.logs;
+
+import cgeo.geocaching.CacheDetailActivity;
+import cgeo.geocaching.LogEntry;
+import cgeo.geocaching.Trackable;
+import cgeo.geocaching.TrackableActivity;
+import cgeo.geocaching.ui.UserActionsClickListener;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.text.Html;
+import android.view.View;
+
+import java.util.List;
+
+public class TrackableLogsViewCreator extends LogsViewCreator {
+
+ private final Trackable trackable;
+
+ /**
+ * @param trackableActivity
+ */
+ public TrackableLogsViewCreator(TrackableActivity trackableActivity, final Trackable trackable) {
+ super(trackableActivity);
+ this.trackable = trackable;
+ }
+
+ @Override
+ protected boolean isValid() {
+ return trackable != null;
+ }
+
+ @Override
+ protected List<LogEntry> getLogs() {
+ return trackable.getLogs();
+ }
+
+ @Override
+ protected void addHeaderView() {
+ // empty
+ }
+
+ @Override
+ protected void fillCountOrLocation(LogViewHolder holder, final LogEntry log) {
+ if (StringUtils.isBlank(log.cacheName)) {
+ holder.countOrLocation.setVisibility(View.GONE);
+ } else {
+ holder.countOrLocation.setText(Html.fromHtml(log.cacheName));
+ final String cacheGuid = log.cacheGuid;
+ final String cacheName = log.cacheName;
+ holder.countOrLocation.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ CacheDetailActivity.startActivityGuid(activity, cacheGuid, Html.fromHtml(cacheName).toString());
+ }
+ });
+ }
+ }
+
+ @Override
+ protected String getGeocode() {
+ return trackable.getGeocode();
+ }
+
+ @Override
+ protected UserActionsClickListener createUserActionsListener() {
+ return new UserActionsClickListener();
+ }
+
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/utils/AngleUtils.java b/main/src/cgeo/geocaching/utils/AngleUtils.java
index 6e59a91..fdd9a9d 100644
--- a/main/src/cgeo/geocaching/utils/AngleUtils.java
+++ b/main/src/cgeo/geocaching/utils/AngleUtils.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.utils;
-public class AngleUtils {
+public final class AngleUtils {
private AngleUtils() {
// Do not instantiate
@@ -8,7 +8,7 @@ public class AngleUtils {
/**
* Return the angle to turn of to go from an angle to the other
- *
+ *
* @param from
* the origin angle in degrees
* @param to
diff --git a/main/src/cgeo/geocaching/utils/ClipboardUtils.java b/main/src/cgeo/geocaching/utils/ClipboardUtils.java
index 9343576..67069b2 100644
--- a/main/src/cgeo/geocaching/utils/ClipboardUtils.java
+++ b/main/src/cgeo/geocaching/utils/ClipboardUtils.java
@@ -12,6 +12,10 @@ import android.content.Context;
@SuppressWarnings("deprecation")
public final class ClipboardUtils {
+ private ClipboardUtils() {
+ // utility class
+ }
+
/**
* Places the text passed in onto the clipboard as text
*
diff --git a/main/src/cgeo/geocaching/utils/CryptUtils.java b/main/src/cgeo/geocaching/utils/CryptUtils.java
index aecf717..18a337d 100644
--- a/main/src/cgeo/geocaching/utils/CryptUtils.java
+++ b/main/src/cgeo/geocaching/utils/CryptUtils.java
@@ -12,6 +12,10 @@ import javax.crypto.spec.SecretKeySpec;
public final class CryptUtils {
+ private CryptUtils() {
+ // utility class
+ }
+
private static char[] base64map1 = new char[64];
private static byte[] base64map2 = new byte[128];
diff --git a/main/src/cgeo/geocaching/utils/DateUtils.java b/main/src/cgeo/geocaching/utils/DateUtils.java
index fd5ef4a..b148979 100644
--- a/main/src/cgeo/geocaching/utils/DateUtils.java
+++ b/main/src/cgeo/geocaching/utils/DateUtils.java
@@ -2,7 +2,12 @@ package cgeo.geocaching.utils;
import java.util.Calendar;
-public class DateUtils {
+public final class DateUtils {
+
+ private DateUtils() {
+ // utility class
+ }
+
public static int daysSince(long date) {
final Calendar logDate = Calendar.getInstance();
logDate.setTimeInMillis(date);
diff --git a/main/src/cgeo/geocaching/utils/EditUtils.java b/main/src/cgeo/geocaching/utils/EditUtils.java
index f2f89e7..d975df9 100644
--- a/main/src/cgeo/geocaching/utils/EditUtils.java
+++ b/main/src/cgeo/geocaching/utils/EditUtils.java
@@ -8,6 +8,10 @@ import android.widget.TextView;
public final class EditUtils {
+ private EditUtils() {
+ // utility class
+ }
+
public static void setActionListener(final EditText editText, final Runnable runnable) {
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
diff --git a/main/src/cgeo/geocaching/utils/FileUtils.java b/main/src/cgeo/geocaching/utils/FileUtils.java
index 6fefc02..5ab8fcc 100644
--- a/main/src/cgeo/geocaching/utils/FileUtils.java
+++ b/main/src/cgeo/geocaching/utils/FileUtils.java
@@ -9,12 +9,16 @@ import java.io.File;
import java.util.List;
/**
- * Utiliy class for files
+ * Utility class for files
*
* @author rsudev
*
*/
-public class FileUtils {
+public final class FileUtils {
+
+ private FileUtils() {
+ // utility class
+ }
public static void listDir(List<File> result, File directory, FileSelector chooser, Handler feedBackHandler) {
diff --git a/main/src/cgeo/geocaching/utils/HtmlUtils.java b/main/src/cgeo/geocaching/utils/HtmlUtils.java
index 89b1070..5717a37 100644
--- a/main/src/cgeo/geocaching/utils/HtmlUtils.java
+++ b/main/src/cgeo/geocaching/utils/HtmlUtils.java
@@ -10,7 +10,11 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-public class HtmlUtils {
+public final class HtmlUtils {
+
+ private HtmlUtils() {
+ // utility class
+ }
/**
* Extract the text from a HTML based string. This is similar to what HTML.fromHtml(...) does, but this method also
diff --git a/main/src/cgeo/geocaching/utils/ImageHelper.java b/main/src/cgeo/geocaching/utils/ImageUtils.java
index a01e836..ea7d3ff 100644
--- a/main/src/cgeo/geocaching/utils/ImageHelper.java
+++ b/main/src/cgeo/geocaching/utils/ImageUtils.java
@@ -11,10 +11,10 @@ import android.graphics.drawable.BitmapDrawable;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
-public class ImageHelper {
+public final class ImageUtils {
- // Do not let this class be instantiated, this is a utility class.
- private ImageHelper() {
+ private ImageUtils() {
+ // Do not let this class be instantiated, this is a utility class.
}
/**
diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java
index 698d38a..708dff0 100644
--- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java
+++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java
@@ -10,13 +10,13 @@ import java.util.List;
/**
* Synchronized set wrapper for the LeastRecentlyUsedMap.
*
- * This code is heavily based on the HashSet code that represent Map as a Set.
+ * This code is heavily based on the HashSet code that represents Map as a Set.
* Unfortunately HashSet does not allow to use a custom Map as its Storage.
* Therefore overriding removeEldestEntry() is impossible for a normal LinkedHashSet.
*
* Synchronization is added to guard against concurrent modification. Iterator
* access has to be guarded externally or the synchronized getAsList method can be used
- * to get a clone for iteration
+ * to get a clone for iteration.
*/
public class LeastRecentlyUsedSet<E> extends AbstractSet<E>
implements Cloneable, java.io.Serializable {
@@ -28,7 +28,7 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E>
public LeastRecentlyUsedSet(int maxEntries, int initialCapacity, float loadFactor) {
// because we don't use any Map.get() methods from the Set, BOUNDED and LRU_CACHE have the exact same Behaviour
- // So we useLRU_CACHE mode because it should perform a bit better (as it doesn't re-add explicitly)
+ // So we use LRU_CACHE mode because it should perform a bit better (as it doesn't re-add explicitly)
map = new LeastRecentlyUsedMap.LruCache<E, Object>(maxEntries, initialCapacity, loadFactor);
}
diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
index 0a8e547..2576e64 100644
--- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
+++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
@@ -188,7 +188,7 @@ public class LogTemplateProvider {
}
try {
- return Integer.parseInt(BaseUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", ""));
+ return Integer.parseInt(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", ""));
} catch (NumberFormatException e) {
Log.e("parseFindCount", e);
return -1;
diff --git a/main/src/cgeo/geocaching/utils/ProcessUtils.java b/main/src/cgeo/geocaching/utils/ProcessUtils.java
index 53991fb..85cedc5 100644
--- a/main/src/cgeo/geocaching/utils/ProcessUtils.java
+++ b/main/src/cgeo/geocaching/utils/ProcessUtils.java
@@ -3,14 +3,55 @@ package cgeo.geocaching.utils;
import cgeo.geocaching.cgeoapplication;
import android.content.Intent;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-public class ProcessUtils {
+import java.util.List;
- public static boolean isInstalled(final String packageName) {
+public final class ProcessUtils {
+
+ private ProcessUtils() {
+ // utility class
+ }
+
+ /**
+ * Preferred method to detect the availability of an external app
+ *
+ * @param packageName
+ * @return
+ */
+ public static boolean isLaunchable(final String packageName) {
return getLaunchIntent(packageName) != null;
}
+ /**
+ * Checks whether a launch intent is available or if the package is just installed
+ * This function is relatively costly, so if you know that the package in question has
+ * a launch intent, use isLaunchable() instead.
+ *
+ * @param packageName
+ * @return
+ */
+ public static boolean isInstalled(final String packageName) {
+ return isLaunchable(packageName) || hasPackageInstalled(packageName);
+ }
+
+ /**
+ * This will find installed applications even without launch intent (e.g. the streetview plugin).
+ */
+ private static boolean hasPackageInstalled(final String packageName) {
+ final List<PackageInfo> packs = cgeoapplication.getInstance().getPackageManager().getInstalledPackages(0);
+ for (final PackageInfo packageInfo : packs) {
+ if (packageName.equals(packageInfo.packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * This will find applications, which can be launched.
+ */
public static Intent getLaunchIntent(final String packageName) {
if (packageName == null) {
return null;
@@ -20,7 +61,7 @@ public class ProcessUtils {
// This can throw an exception where the exception type is only defined on API Level > 3
// therefore surround with try-catch
return packageManager.getLaunchIntentForPackage(packageName);
- } catch (Exception e) {
+ } catch (final Exception e) {
return null;
}
}
diff --git a/main/src/cgeo/geocaching/utils/BaseUtils.java b/main/src/cgeo/geocaching/utils/TextUtils.java
index b8006ad..68ac595 100644
--- a/main/src/cgeo/geocaching/utils/BaseUtils.java
+++ b/main/src/cgeo/geocaching/utils/TextUtils.java
@@ -9,10 +9,14 @@ import java.util.regex.Pattern;
/**
* Misc. utils. All methods don't use Android specific stuff to use these methods in plain JUnit tests.
*/
-public final class BaseUtils {
+public final class TextUtils {
private static final Pattern PATTERN_REMOVE_NONPRINTABLE = Pattern.compile("\\p{Cntrl}");
+ private TextUtils() {
+ // utility class
+ }
+
/**
* Searches for the pattern p in the data. If the pattern is not found defaultValue is returned
*
@@ -69,7 +73,7 @@ public final class BaseUtils {
* @return defaultValue or the first group if the pattern matches (trimmed if wanted)
*/
public static String getMatch(final String data, final Pattern p, final boolean trim, final String defaultValue) {
- return BaseUtils.getMatch(data, p, trim, 1, defaultValue, false);
+ return TextUtils.getMatch(data, p, trim, 1, defaultValue, false);
}
/**
@@ -84,7 +88,7 @@ public final class BaseUtils {
* @return defaultValue or the first group if the pattern matches (trimmed)
*/
public static String getMatch(final String data, final Pattern p, final String defaultValue) {
- return BaseUtils.getMatch(data, p, true, 1, defaultValue, false);
+ return TextUtils.getMatch(data, p, true, 1, defaultValue, false);
}
/**
diff --git a/main/src/cgeo/geocaching/utils/TranslationUtils.java b/main/src/cgeo/geocaching/utils/TranslationUtils.java
index 4d318f0..1224f7e 100644
--- a/main/src/cgeo/geocaching/utils/TranslationUtils.java
+++ b/main/src/cgeo/geocaching/utils/TranslationUtils.java
@@ -19,6 +19,10 @@ public final class TranslationUtils {
public static final int translationTextLengthToWarn = 500;
private static final String TRANSLATION_APP = "com.google.android.apps.translate";
+ private TranslationUtils() {
+ // utility class
+ }
+
/**
* Build a URI for Google Translate
*
@@ -31,7 +35,7 @@ public final class TranslationUtils {
private static String buildTranslationURI(final String toLang, final String text) {
String content = Network.encode(text);
// the app works better without the "+", the website works better with "+", therefore assume using the app if installed
- if (ProcessUtils.isInstalled(TRANSLATION_APP)) {
+ if (ProcessUtils.isLaunchable(TRANSLATION_APP)) {
content = content.replace("+", "%20");
}
return translationWebsite + translationForceClassicMode + translationAutoSelect + translationFieldSeparator + toLang + translationFieldSeparator + content;
diff --git a/main/src/cgeo/geocaching/utils/XmlUtils.java b/main/src/cgeo/geocaching/utils/XmlUtils.java
index 4e08f42..2d85950 100644
--- a/main/src/cgeo/geocaching/utils/XmlUtils.java
+++ b/main/src/cgeo/geocaching/utils/XmlUtils.java
@@ -4,7 +4,7 @@ import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
-public class XmlUtils {
+public final class XmlUtils {
private XmlUtils() {
// Do not instantiate