diff options
164 files changed, 1241 insertions, 814 deletions
diff --git a/.idea/inspectionProfiles/c_geo_standards.xml b/.idea/inspectionProfiles/c_geo_standards.xml index e839710..41a24a9 100644 --- a/.idea/inspectionProfiles/c_geo_standards.xml +++ b/.idea/inspectionProfiles/c_geo_standards.xml @@ -454,7 +454,7 @@ <inspection_tool class="UnnecessaryCallToStringValueOf" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UnnecessaryConstructor" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UnnecessaryEnumModifier" enabled="true" level="WARNING" enabled_by_default="true" /> - <inspection_tool class="UnnecessaryFullyQualifiedName" enabled="true" level="WARNING" enabled_by_default="true"> + <inspection_tool class="UnnecessaryFullyQualifiedName" enabled="true" level="WEAK WARNING" enabled_by_default="true"> <option name="m_ignoreJavadoc" value="false" /> </inspection_tool> <inspection_tool class="UnnecessaryInheritDoc" enabled="true" level="WARNING" enabled_by_default="true" /> diff --git a/cgeo-calendar/.classpath b/cgeo-calendar/.classpath index 2f1c26a..004d749 100644 --- a/cgeo-calendar/.classpath +++ b/cgeo-calendar/.classpath @@ -10,5 +10,6 @@ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> <classpathentry combineaccessrules="false" kind="src" path="/cgeo"/> <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> + <classpathentry kind="lib" path="/cgeo/compile-libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar"/> <classpathentry kind="output" path="bin/classes"/> </classpath> diff --git a/cgeo-calendar/.settings/org.eclipse.jdt.ui.prefs b/cgeo-calendar/.settings/org.eclipse.jdt.ui.prefs index 7616a5b..06e562c 100644 --- a/cgeo-calendar/.settings/org.eclipse.jdt.ui.prefs +++ b/cgeo-calendar/.settings/org.eclipse.jdt.ui.prefs @@ -1,4 +1,3 @@ -#Wed Sep 14 20:41:07 CEST 2011 eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_cgeo @@ -9,7 +8,7 @@ org.eclipse.jdt.ui.ondemandthreshold=99 org.eclipse.jdt.ui.staticondemandthreshold=99 sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_annotations=true sp_cleanup.add_missing_deprecated_annotations=true sp_cleanup.add_missing_methods=false sp_cleanup.add_missing_nls_tags=false @@ -20,15 +19,17 @@ sp_cleanup.always_use_blocks=true sp_cleanup.always_use_parentheses_in_expressions=false sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=true sp_cleanup.correct_indentation=false sp_cleanup.format_source_code=true sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=false -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=true +sp_cleanup.make_private_fields_final=true sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=false +sp_cleanup.make_variable_declarations_final=true sp_cleanup.never_use_blocks=false sp_cleanup.never_use_parentheses_in_expressions=true sp_cleanup.on_save_use_additional_actions=true @@ -36,15 +37,16 @@ sp_cleanup.organize_imports=true sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_with_declaring_class=true sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=false -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true sp_cleanup.remove_unused_private_members=false @@ -52,10 +54,13 @@ sp_cleanup.remove_unused_private_methods=true sp_cleanup.remove_unused_private_types=true sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=true sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false sp_cleanup.use_parentheses_in_expressions=false sp_cleanup.use_this_for_non_static_field_access=false sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true sp_cleanup.use_this_for_non_static_method_access=false sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false diff --git a/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java b/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java index 893161c..e35ed19 100644 --- a/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java +++ b/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java @@ -1,13 +1,17 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + import android.util.Log; abstract class AbstractAddEntry { + @NonNull protected final CalendarEntry entry; + @NonNull protected final CalendarActivity activity; - public AbstractAddEntry(final CalendarEntry entry, final CalendarActivity activity) { + public AbstractAddEntry(@NonNull final CalendarEntry entry, @NonNull final CalendarActivity activity) { this.entry = entry; this.activity = activity; } diff --git a/cgeo-calendar/src/cgeo/calendar/AddEntry.java b/cgeo-calendar/src/cgeo/calendar/AddEntry.java index 30af346..a267e47 100644 --- a/cgeo-calendar/src/cgeo/calendar/AddEntry.java +++ b/cgeo-calendar/src/cgeo/calendar/AddEntry.java @@ -1,5 +1,7 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + import android.content.ContentValues; import android.net.Uri; import android.text.Html; @@ -16,7 +18,7 @@ class AddEntry extends AbstractAddEntry { * @param calendarId * The selected calendar */ - public AddEntry(final CalendarEntry entry, final CalendarActivity activity, final int calendarId) { + public AddEntry(@NonNull final CalendarEntry entry, @NonNull final CalendarActivity activity, final int calendarId) { super(entry, activity); this.calendarId = calendarId; } diff --git a/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java b/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java index 11820b4..731a0f8 100644 --- a/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java +++ b/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java @@ -1,5 +1,7 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + import android.content.Intent; import android.text.Html; @@ -12,7 +14,7 @@ import java.util.Date; */ class AddEntryLevel14 extends AbstractAddEntry { - public AddEntryLevel14(final CalendarEntry entry, final CalendarActivity activity) { + public AddEntryLevel14(@NonNull final CalendarEntry entry, @NonNull final CalendarActivity activity) { super(entry, activity); } diff --git a/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java b/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java index 2f0c08d..e21de2b 100644 --- a/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java +++ b/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java @@ -1,5 +1,7 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; @@ -47,7 +49,7 @@ public final class CalendarActivity extends Activity { * @param entry * new entry to be stored */ - private void selectCalendarForAdding(final CalendarEntry entry) { + private void selectCalendarForAdding(@NonNull final CalendarEntry entry) { final SparseArray<String> calendars = queryCalendars(); if (calendars.size() == 0) { @@ -80,6 +82,7 @@ public final class CalendarActivity extends Activity { builder.create().show(); } + @NonNull private SparseArray<String> queryCalendars() { final SparseArray<String> calendars = new SparseArray<>(); diff --git a/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java b/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java index 1e37d6b..8308b7b 100644 --- a/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java +++ b/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java @@ -3,6 +3,7 @@ package cgeo.calendar; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.CharEncoding; +import org.eclipse.jdt.annotation.NonNull; import android.net.Uri; import android.text.Html; @@ -16,16 +17,23 @@ import java.util.Date; class CalendarEntry { + @NonNull private final String shortDesc; + @NonNull private final String hiddenDate; + @NonNull private final String url; + @NonNull private final String personalNote; + @NonNull private final String name; + @NonNull private final String coords; private int startTimeMinutes = -1; + @NonNull private final Uri uri; - public CalendarEntry(final Uri uri) { + public CalendarEntry(@NonNull final Uri uri) { this.uri = uri; this.shortDesc = getParameter(ICalendar.PARAM_SHORT_DESC); this.hiddenDate = getParameter(ICalendar.PARAM_HIDDEN_DATE); @@ -43,7 +51,8 @@ class CalendarEntry { } } - private String getParameter(final String paramKey) { + @NonNull + private String getParameter(@NonNull final String paramKey) { try { final String param = uri.getQueryParameter(paramKey); if (param == null) { @@ -60,18 +69,22 @@ class CalendarEntry { return getName().length() > 0 && getHiddenDate().length() > 0; } + @NonNull public String getHiddenDate() { return hiddenDate; } + @NonNull public String getUrl() { return url; } + @NonNull public String getPersonalNote() { return personalNote; } + @NonNull public String getShortDesc() { return shortDesc; } @@ -79,6 +92,7 @@ class CalendarEntry { /** * @return <code>Date</code> based on hidden date. Time is set to 00:00:00. */ + @NonNull protected Date parseDate() { try { final Calendar cal = Calendar.getInstance(); @@ -90,13 +104,14 @@ class CalendarEntry { return cal.getTime(); } catch (final NumberFormatException e) { // cannot happen normally, but static code analysis does not know + throw new IllegalStateException("hidden date must be a valid date for cache calendar entries"); } - return null; } /** * @return description string with images removed and personal note included */ + @NonNull protected String parseDescription() { final StringBuilder description = new StringBuilder(); description.append(getUrl()); @@ -121,6 +136,7 @@ class CalendarEntry { return description.toString(); } + @NonNull public String getName() { return name; } @@ -129,6 +145,7 @@ class CalendarEntry { return startTimeMinutes; } + @NonNull public String getCoords() { return coords; } diff --git a/cgeo-calendar/src/cgeo/calendar/Compatibility.java b/cgeo-calendar/src/cgeo/calendar/Compatibility.java index ff14a0f..61ea636 100644 --- a/cgeo-calendar/src/cgeo/calendar/Compatibility.java +++ b/cgeo-calendar/src/cgeo/calendar/Compatibility.java @@ -1,5 +1,7 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + import android.net.Uri; import android.os.Build; @@ -9,10 +11,12 @@ public final class Compatibility { private final static boolean IS_LEVEL_8 = SDK_VERSION >= 8; private final static boolean IS_LEVEL_14 = SDK_VERSION >= 14; + @NonNull public static Uri getCalendarProviderURI() { return Uri.parse(IS_LEVEL_8 ? "content://com.android.calendar/calendars" : "content://calendar/calendars"); } + @NonNull public static Uri getCalendarEventsProviderURI() { return Uri.parse(IS_LEVEL_8 ? "content://com.android.calendar/events" : "content://calendar/events"); } diff --git a/cgeo-contacts/.classpath b/cgeo-contacts/.classpath index 448b12e..004d749 100644 --- a/cgeo-contacts/.classpath +++ b/cgeo-contacts/.classpath @@ -10,6 +10,6 @@ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> <classpathentry combineaccessrules="false" kind="src" path="/cgeo"/> <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> - <classpathentry kind="lib" path="org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar"/> + <classpathentry kind="lib" path="/cgeo/compile-libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar"/> <classpathentry kind="output" path="bin/classes"/> </classpath> diff --git a/cgeo-contacts/.settings/org.eclipse.jdt.ui.prefs b/cgeo-contacts/.settings/org.eclipse.jdt.ui.prefs index 7616a5b..06e562c 100644 --- a/cgeo-contacts/.settings/org.eclipse.jdt.ui.prefs +++ b/cgeo-contacts/.settings/org.eclipse.jdt.ui.prefs @@ -1,4 +1,3 @@ -#Wed Sep 14 20:41:07 CEST 2011 eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_cgeo @@ -9,7 +8,7 @@ org.eclipse.jdt.ui.ondemandthreshold=99 org.eclipse.jdt.ui.staticondemandthreshold=99 sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_annotations=true sp_cleanup.add_missing_deprecated_annotations=true sp_cleanup.add_missing_methods=false sp_cleanup.add_missing_nls_tags=false @@ -20,15 +19,17 @@ sp_cleanup.always_use_blocks=true sp_cleanup.always_use_parentheses_in_expressions=false sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=true sp_cleanup.correct_indentation=false sp_cleanup.format_source_code=true sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=false -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=true +sp_cleanup.make_private_fields_final=true sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=false +sp_cleanup.make_variable_declarations_final=true sp_cleanup.never_use_blocks=false sp_cleanup.never_use_parentheses_in_expressions=true sp_cleanup.on_save_use_additional_actions=true @@ -36,15 +37,16 @@ sp_cleanup.organize_imports=true sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_with_declaring_class=true sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=false -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true sp_cleanup.remove_unused_private_members=false @@ -52,10 +54,13 @@ sp_cleanup.remove_unused_private_methods=true sp_cleanup.remove_unused_private_types=true sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=true sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false sp_cleanup.use_parentheses_in_expressions=false sp_cleanup.use_this_for_non_static_field_access=false sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true sp_cleanup.use_this_for_non_static_method_access=false sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false diff --git a/cgeo-contacts/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar b/cgeo-contacts/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar Binary files differdeleted file mode 100644 index daca164..0000000 --- a/cgeo-contacts/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar +++ /dev/null diff --git a/cgeo-contacts/src/cgeo/contacts/ContactsActivity.java b/cgeo-contacts/src/cgeo/contacts/ContactsActivity.java index 7d2f1e1..60accca 100644 --- a/cgeo-contacts/src/cgeo/contacts/ContactsActivity.java +++ b/cgeo-contacts/src/cgeo/contacts/ContactsActivity.java @@ -72,7 +72,7 @@ public final class ContactsActivity extends Activity { } } - private void selectContact(final List<Pair<Integer, String>> contacts) { + private void selectContact(@NonNull final List<Pair<Integer, String>> contacts) { final List<String> list = new ArrayList<>(); for (final Pair<Integer, String> p : contacts) { list.add(p.second); @@ -100,6 +100,7 @@ public final class ContactsActivity extends Activity { finish(); } + @NonNull private List<Pair<Integer, String>> getContacts(final @NonNull String searchName, final Uri uri, final @NonNull String idColumnName, final @NonNull String selectionColumnName, final boolean like) { final String[] projection = new String[] { idColumnName, selectionColumnName }; final String selection = selectionColumnName + (like ? " LIKE" : " =") + " ? COLLATE NOCASE"; @@ -131,7 +132,8 @@ public final class ContactsActivity extends Activity { toast.show(); } - private static String getParameter(final Uri uri, final String paramKey) { + @NonNull + private static String getParameter(@NonNull final Uri uri, @NonNull final String paramKey) { try { final String param = uri.getQueryParameter(paramKey); if (param == null) { diff --git a/main/.settings/org.eclipse.jdt.ui.prefs b/main/.settings/org.eclipse.jdt.ui.prefs index 4d4a905..d321d7d 100644 --- a/main/.settings/org.eclipse.jdt.ui.prefs +++ b/main/.settings/org.eclipse.jdt.ui.prefs @@ -12,7 +12,7 @@ org.eclipse.jdt.ui.overrideannotation=true org.eclipse.jdt.ui.staticondemandthreshold=99 sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_annotations=true sp_cleanup.add_missing_deprecated_annotations=true sp_cleanup.add_missing_methods=false sp_cleanup.add_missing_nls_tags=false @@ -41,15 +41,15 @@ sp_cleanup.organize_imports=true sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_with_declaring_class=true sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true sp_cleanup.remove_redundant_type_arguments=false sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=false -sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml index ca3026a..9364d41 100644 --- a/main/AndroidManifest.xml +++ b/main/AndroidManifest.xml @@ -7,7 +7,7 @@ <uses-sdk android:minSdkVersion="9" - android:targetSdkVersion="19" /> + android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> @@ -587,7 +587,7 @@ <!-- provide enhanced meta data for caches (and waypoints) when invoking Locus from c:geo --> <provider - android:name=".apps.LocusDataStorageProvider" + android:name="menion.android.locus.LocusDataStorageProvider" android:authorities="cgeo.geocaching.apps.locusdatastorageprovider" /> <!-- search suggestions for the search bar at the top --> diff --git a/main/build.gradle b/main/build.gradle index 9034c74..ff2160f 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -27,9 +27,8 @@ gradle connectedCheck //https://github.com/stephanenicolas/Quality-Tools-for-Android def AAVersion = '3.2' -def RXJavaVersion = '1.0.4' +def RXJavaVersion = '1.0.5' def RXAndroidVersion = '0.24.0' -def RXJavaAsyncUtilVersion = '0.21.0' def JacksonCoreVersion = '2.4.4' def JacksonDatabindVersion = '2.4.4' def JacksonAnnotationsVersion = '2.4.4' @@ -168,7 +167,6 @@ dependencies { compile "io.reactivex:rxjava:$RXJavaVersion" compile "io.reactivex:rxandroid:$RXAndroidVersion" - compile "io.reactivex:rxjava-async-util:$RXJavaAsyncUtilVersion" compile "com.fasterxml.jackson.core:jackson-core:$JacksonCoreVersion" compile "com.fasterxml.jackson.core:jackson-databind:$JacksonDatabindVersion" diff --git a/main/libs/rxjava-1.0.4.jar b/main/libs/rxjava-1.0.4.jar Binary files differdeleted file mode 100644 index feed10f..0000000 --- a/main/libs/rxjava-1.0.4.jar +++ /dev/null diff --git a/main/libs/rxjava-1.0.4.jar.properties b/main/libs/rxjava-1.0.4.jar.properties deleted file mode 100644 index 944cfad..0000000 --- a/main/libs/rxjava-1.0.4.jar.properties +++ /dev/null @@ -1,2 +0,0 @@ -src=src/rxjava-1.0.4-sources.jar -doc=src/rxjava-1.0.4-javadoc.jar diff --git a/main/libs/rxjava-1.0.5.jar b/main/libs/rxjava-1.0.5.jar Binary files differnew file mode 100644 index 0000000..4082c6a --- /dev/null +++ b/main/libs/rxjava-1.0.5.jar diff --git a/main/libs/rxjava-1.0.5.jar.properties b/main/libs/rxjava-1.0.5.jar.properties new file mode 100644 index 0000000..84598a3 --- /dev/null +++ b/main/libs/rxjava-1.0.5.jar.properties @@ -0,0 +1,2 @@ +src=src/rxjava-1.0.5-sources.jar +doc=src/rxjava-1.0.5-javadoc.jar diff --git a/main/libs/rxjava-async-util-0.21.0.jar b/main/libs/rxjava-async-util-0.21.0.jar Binary files differdeleted file mode 100644 index 9b57574..0000000 --- a/main/libs/rxjava-async-util-0.21.0.jar +++ /dev/null diff --git a/main/libs/rxjava-async-util-0.21.0.jar.properties b/main/libs/rxjava-async-util-0.21.0.jar.properties deleted file mode 100644 index 5a9fc9e..0000000 --- a/main/libs/rxjava-async-util-0.21.0.jar.properties +++ /dev/null @@ -1,2 +0,0 @@ -src=src/rxjava-async-util-0.21.0-sources.jar -doc=src/rxjava-async-util-0.21.0-javadoc.jar diff --git a/main/libs/src/rxjava-1.0.4-javadoc.jar b/main/libs/src/rxjava-1.0.4-javadoc.jar Binary files differdeleted file mode 100644 index 92dc0fc..0000000 --- a/main/libs/src/rxjava-1.0.4-javadoc.jar +++ /dev/null diff --git a/main/libs/src/rxjava-1.0.5-javadoc.jar b/main/libs/src/rxjava-1.0.5-javadoc.jar Binary files differnew file mode 100644 index 0000000..3d0c7d9 --- /dev/null +++ b/main/libs/src/rxjava-1.0.5-javadoc.jar diff --git a/main/libs/src/rxjava-1.0.4-sources.jar b/main/libs/src/rxjava-1.0.5-sources.jar Binary files differindex c77e946..72c7efc 100644 --- a/main/libs/src/rxjava-1.0.4-sources.jar +++ b/main/libs/src/rxjava-1.0.5-sources.jar diff --git a/main/libs/src/rxjava-async-util-0.21.0-javadoc.jar b/main/libs/src/rxjava-async-util-0.21.0-javadoc.jar Binary files differdeleted file mode 100644 index 28b1b63..0000000 --- a/main/libs/src/rxjava-async-util-0.21.0-javadoc.jar +++ /dev/null diff --git a/main/libs/src/rxjava-async-util-0.21.0-sources.jar b/main/libs/src/rxjava-async-util-0.21.0-sources.jar Binary files differdeleted file mode 100644 index 3337f37..0000000 --- a/main/libs/src/rxjava-async-util-0.21.0-sources.jar +++ /dev/null diff --git a/main/project.properties b/main/project.properties index 4dc8ffb..4fed171 100644 --- a/main/project.properties +++ b/main/project.properties @@ -11,7 +11,7 @@ proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt:../play-services-base/proguard.txt:../play-services-location/proguard.txt # Project target. -target=Google Inc.:Google APIs:19 +target=Google Inc.:Google APIs:21 android.library.reference.1=../mapswithme-api android.library.reference.2=../android-support-v7-appcompat android.library.reference.3=../showcaseview diff --git a/main/project/libraries/pom.xml b/main/project/libraries/pom.xml index a86c3c7..d8d69b2 100644 --- a/main/project/libraries/pom.xml +++ b/main/project/libraries/pom.xml @@ -30,9 +30,8 @@ <JacksonCoreVersion>2.4.4</JacksonCoreVersion> <JacksonDatabindVersion>2.4.4</JacksonDatabindVersion> - <RXAndroidVersion>0.23.0</RXAndroidVersion> - <RXJavaVersion>1.0.3</RXJavaVersion> - <RXJavaAsyncUtilVersion>0.21.0</RXJavaAsyncUtilVersion> + <RXAndroidVersion>0.24.0</RXAndroidVersion> + <RXJavaVersion>1.0.5</RXJavaVersion> </properties> <dependencies> @@ -98,11 +97,6 @@ </dependency> <dependency> <groupId>io.reactivex</groupId> - <artifactId>rxjava-async-util</artifactId> - <version>${RXJavaAsyncUtilVersion}</version> - </dependency> - <dependency> - <groupId>io.reactivex</groupId> <artifactId>rxandroid</artifactId> <version>${RXAndroidVersion}</version> </dependency> diff --git a/main/project/libraries/update-libs.sh b/main/project/libraries/update-libs.sh index b49dbef..71561e4 100755 --- a/main/project/libraries/update-libs.sh +++ b/main/project/libraries/update-libs.sh @@ -1,9 +1,8 @@ #! /bin/sh # -RXJAVA=1.0.4 +RXJAVA=1.0.5 RXANDROID=0.24.0 -RXJAVAASYNCUTIL=0.21.0 JACKSONCORE=2.4.4 JACKSONDATABIND=2.4.4 JACKSONANNOTATIONS=2.4.4 @@ -39,8 +38,6 @@ updatelib io/reactivex rxjava $RXJAVA fixgradle RXJavaVersion $RXJAVA updatelib io/reactivex rxandroid $RXANDROID fixgradle RXAndroidVersion $RXANDROID -updatelib io/reactivex rxjava-async-util $RXJAVAASYNCUTIL -fixgradle RXJavaAsyncUtilVersion $RXJAVAASYNCUTIL updatelib com/fasterxml/jackson/core jackson-core $JACKSONCORE fixgradle JacksonCoreVersion $JACKSONCORE diff --git a/main/res/layout/about_help_page.xml b/main/res/layout/about_help_page.xml index 8985ffa..ed64b92 100644 --- a/main/res/layout/about_help_page.xml +++ b/main/res/layout/about_help_page.xml @@ -7,106 +7,178 @@ android:padding="4dip" tools:context=".AboutActivity$HelpViewCreator" > - <LinearLayout - android:layout_width="fill_parent" + <TableLayout + android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="vertical" > + android:paddingLeft="10dp" > - <TextView - android:id="@+id/faq" + <TableRow + android:id="@+id/tableRow1" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/faq" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - - <TextView - android:id="@+id/website" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/faq_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/faq" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/faq_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + + <TableRow + android:id="@+id/tableRow2" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/website" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - - <TextView - android:id="@+id/facebook" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/website_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/website" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/website_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + + <TableRow + android:id="@+id/tableRow3" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/facebook" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - - <TextView - android:id="@+id/twitter" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/facebook_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/facebook" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/facebook_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + + <TableRow + android:id="@+id/tableRow4" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/twitter" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - - <TextView - android:id="@+id/support" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/twitter_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/twitter" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/twitter_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + + <TableRow + android:id="@+id/tableRow5" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/support" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - - <TextView - android:id="@+id/market" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/support_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/support" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/support_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + + <TableRow + android:id="@+id/tableRow6" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/market" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - </LinearLayout> + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/market_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/market" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/market_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + </TableLayout> </ScrollView>
\ No newline at end of file diff --git a/main/res/menu/cache_list_options.xml b/main/res/menu/cache_list_options.xml index 8c2b066..30fe28a 100644 --- a/main/res/menu/cache_list_options.xml +++ b/main/res/menu/cache_list_options.xml @@ -53,12 +53,12 @@ android:visible="false"> </item> <item - android:id="@+id/submenu_cache_list_app" + android:id="@+id/menu_cache_list_app_provider" + android:actionProviderClass="cgeo.geocaching.apps.cachelist.ListNavigationSelectionActionProvider" android:icon="@drawable/ic_menu_goto" android:title="@string/caches_on_map" + app:actionProviderClass="cgeo.geocaching.apps.cachelist.ListNavigationSelectionActionProvider" android:visible="false"> - <menu> - </menu> </item> <item android:id="@+id/menu_create_list" diff --git a/main/res/values-ca/strings.xml b/main/res/values-ca/strings.xml index 83555a3..04fb0fe 100644 --- a/main/res/values-ca/strings.xml +++ b/main/res/values-ca/strings.xml @@ -1138,13 +1138,7 @@ <string name="attribute_offset_cache_no">No és un catxé offset</string> <string name="quote">Per fer el geocatxing més fàcil, per fer els usuaris més dropos.</string> <string name="powered_by">Carnero</string> - <string name="support">Suport: <a href="">support@cgeo.org</a></string> - <string name="website">Lloc web: <a href=""> cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">Pàgina del c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">El c:geo a Google Play</a></string> <string name="about_twitter">Voleu que <b>el c:geo</b> publiqui un nou estatus al Twitter cada vegada que registreu un catxé?</string> - <string name="faq">PMF: <a href=""> faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Nova versió disponible.\nCliqueu per instal·lar-la.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nova versió nightly build disponible.\nCliqueu per instal·lar-la.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Nova versió candidate disponible.\nCliqueu per instal·lar-la.</string> diff --git a/main/res/values-cs/strings.xml b/main/res/values-cs/strings.xml index e2321a2..9e6651a 100644 --- a/main/res/values-cs/strings.xml +++ b/main/res/values-cs/strings.xml @@ -1134,13 +1134,7 @@ <string name="attribute_offset_cache_no">Není to Offset keš</string> <string name="quote">Učinit Geocaching lehčí a uživatele línější.</string> <string name="powered_by">carnero</string> - <string name="support">Podpora: <a href="">support@cgeo.org</a></string> - <string name="website">Stránka: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">Stránka c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo na Google Play</a></string> <string name="about_twitter">Má <b>c:geo</b> publikovat nový status na Twitteru vždy, když zaloguješ keš?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Dostupné nové vydání.\nKlepni pro instalaci.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Dostupné nové \"noční sestavení\"\nKlepni pro instalaci.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Dostupný nový kandidát na vydání.\nKlepni pro instalaci.</string> diff --git a/main/res/values-da/strings.xml b/main/res/values-da/strings.xml index e44c258..31d641c 100644 --- a/main/res/values-da/strings.xml +++ b/main/res/values-da/strings.xml @@ -1118,11 +1118,6 @@ <string name="attribute_offset_cache_yes">Offset-cache</string> <string name="attribute_offset_cache_no">Ikke en offset-cache</string> <string name="quote">To make geocaching easier, to make users lazier.</string> - <string name="support">Support: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string> - <string name="website">Hjemmeside: <a href="http://cgeo.org/">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo page</a></string> - <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo på Google Play</a></string> <string name="about_twitter">Skal <b>c:geo</b> sende status til Twitter hver gang du logger en cache?</string> <string name="status_new_release" tools:ignore="UnusedResources">Ny udgave er tilgængelig.\nKlik for at installere.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nyt nightly build af c:geo er tilgængelig.\nKlik for at installere.</string> diff --git a/main/res/values-de/strings.xml b/main/res/values-de/strings.xml index df275f1..665ce66 100644 --- a/main/res/values-de/strings.xml +++ b/main/res/values-de/strings.xml @@ -1135,13 +1135,7 @@ <string name="attribute_offset_cache_no">Kein Offset Cache</string> <string name="quote">Um Geocachen einfacher zu machen, um es Anwendern bequemer zu machen.</string> <string name="powered_by">carnero</string> - <string name="support">Support: <a href="">support@cgeo.org</a></string> - <string name="website">Webseite: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo auf Google Play</a></string> <string name="about_twitter">Soll jeder neue Fund auf Twitter veröffentlicht werden, wenn er über <b>c:geo</b> geloggt wird?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Neuer Release verfügbar.\nKlicken zum Installieren.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Neuer Nightly Build verfügbar.\nKlicken zum Installieren.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Neuer Release Candidate verfügbar.\nKlicken zum Installieren.</string> diff --git a/main/res/values-es/strings.xml b/main/res/values-es/strings.xml index 890b4c0..bf63714 100644 --- a/main/res/values-es/strings.xml +++ b/main/res/values-es/strings.xml @@ -1125,11 +1125,6 @@ <string name="attribute_offset_cache_yes">Caché offset</string> <string name="attribute_offset_cache_no">No es caché offset</string> <string name="quote">Para hacer el geocaching más sencillo, para hacer a los usuarios más vagos.</string> - <string name="support">Soporte: <a href="">support@cgeo.org</a></string> - <string name="website">Web: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo en Google Play</a></string> <string name="about_twitter">¿Debe <b>c:geo</b> publicar el nuevo estado en Twitter cuando registras un caché?</string> <string name="status_new_release" tools:ignore="UnusedResources">Nueva versión disponible. \nClick para instalar.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nueva versión nightly build disponible.\nHaz clic para instalar.</string> diff --git a/main/res/values-fr/strings.xml b/main/res/values-fr/strings.xml index 41e1341..5b2bf8f 100644 --- a/main/res/values-fr/strings.xml +++ b/main/res/values-fr/strings.xml @@ -1136,13 +1136,7 @@ <string name="attribute_offset_cache_no">Pas de cache relative</string> <string name="quote">Pour faciliter le géocaching.</string> <string name="powered_by">carnero</string> - <string name="support">support: <a href="">support@cgeo.org</a></string> - <string name="website">site: <a href="">cgeo.org</a></string> - <string name="facebook">facebook: <a href="">page c:geo</a></string> - <string name="twitter">twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo sur Google Play</a></string> <string name="about_twitter">Voulez-vous publier un nouveau statut sur Twitter à chaque nouvelle cache découverte sous <b>c:geo</b>?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Nouvelle version disponible.\nCliquer pour installer.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nouvelle version de test disponible.\nCliquer pour installer.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Nouvelle version candidate disponible.\nCliquer pour installer.</string> diff --git a/main/res/values-hu/strings.xml b/main/res/values-hu/strings.xml index dc98879..a8c4fb0 100644 --- a/main/res/values-hu/strings.xml +++ b/main/res/values-hu/strings.xml @@ -1141,13 +1141,7 @@ <string name="attribute_offset_cache_no">Nem offset láda</string> <string name="quote">Az egyszerűbb ládázásért, a lustább játékosokért.</string> <string name="powered_by">carnero</string> - <string name="support">Támogatás: <a href="">support@cgeo.org</a></string> - <string name="website">Weboldal: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Androidra: <a href="">c:geo a Google Play-en</a></string> <string name="about_twitter">Akarod, hogy a <b>c:geo</b> új bejegyzést írjon a Twitter-re, amikor megtalálsz egy ládát?</string> - <string name="faq">GYIK: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Új kiadás jelent meg.\nKattints a telepítéshez.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Új napi frissítés jelent meg.\nKattints a telepítéshez.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Új kiadás előtti verzió jelent meg.\nKattints a telepítéshez.</string> diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml index 73c02d7..58f6c90 100644 --- a/main/res/values-it/strings.xml +++ b/main/res/values-it/strings.xml @@ -1128,13 +1128,7 @@ <string name="attribute_offset_cache_no">Non è un offset cache</string> <string name="quote">Per rendere il geocaching più facile e gli utenti più pigri.</string> <string name="powered_by">carnero</string> - <string name="support">Supporto: <a href="">support@cgeo.org</a></string> - <string name="website">Sito: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">Pagina c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo su Google Play</a></string> <string name="about_twitter">Può <b>c:geo</b> pubblicare su Twitter ogni volta che logghi un cache?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Una nuova versione è disponibile.\nClicca per installarla.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Una nuova versione nightly è disponibile.\nClicca per installarla.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Una nuova release candidate è disponibile.\nClicca per installarla.</string> diff --git a/main/res/values-ja/strings.xml b/main/res/values-ja/strings.xml index e88c35a..2a52220 100644 --- a/main/res/values-ja/strings.xml +++ b/main/res/values-ja/strings.xml @@ -992,11 +992,6 @@ Google翻訳アプリで各言語の辞書をダウンロードしておけば <string name="attribute_geotour_no">ジオツアーの一部ではない</string> <string name="quote">To make geocaching easier, to make users lazier.</string> <string name="powered_by">carnero</string> - <string name="support">サポート: <a href="">support@cgeo.org</a></string> - <string name="website">Webサイト: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">Google Playのc:geo</a></string> <string name="about_twitter">キャッシュのログを書いたら<b>c:geo</b>にTwitterでつぶやいてほしい?</string> <string name="status_new_release" tools:ignore="UnusedResources">新しいバージョンがあります。\nクリックしてインストールしてください。</string> <string name="status_new_nightly" tools:ignore="UnusedResources">新しいナイトリービルドがあります。\nクリックしてインストールしてください。</string> diff --git a/main/res/values-lt/strings.xml b/main/res/values-lt/strings.xml index a326429..a35b4c2 100644 --- a/main/res/values-lt/strings.xml +++ b/main/res/values-lt/strings.xml @@ -1127,11 +1127,6 @@ <string name="attribute_offset_cache_yes">Offset cache</string> <string name="attribute_offset_cache_no">No offset cache</string> <string name="quote">To make geocaching easier, to make users lazier.</string> - <string name="support">Palaikymas: <a href="">support@cgeo.org</a></string> - <string name="website">Tinklapis: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo on Google Play</a></string> <string name="about_twitter">Kaskart registruojant slėptuvę <b>c:geo</b> paskelbs nauja statusą Twitter paskyroje.</string> <string name="status_new_release" tools:ignore="UnusedResources">Galima nauja versija. \nPaspauskite čia ir įdiekite.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Galima nauja naktinė versija.\nPaspauskite čia ir įdiekite.</string> diff --git a/main/res/values-nb/strings.xml b/main/res/values-nb/strings.xml index 4c55e8b..1243470 100644 --- a/main/res/values-nb/strings.xml +++ b/main/res/values-nb/strings.xml @@ -1124,11 +1124,6 @@ <string name="attribute_offset_cache_no">Ikke offset-cache</string> <string name="quote">For å gjøre geocaching enklere og brukerne latere.</string> <string name="powered_by">carnero</string> - <string name="support">e-post adresse: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string> - <string name="website">web-side: <a href="http://cgeo.org/">cgeo.org</a></string> - <string name="facebook">facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo i Google Play</a></string> <string name="about_twitter">Ønsker du at <b>c:geo</b> skal poste en status på Twitter hver gang du logger ett funn via <b>c:geo</b>?</string> <string name="status_new_release" tools:ignore="UnusedResources">Ny versjon tilgjengelig. \nKlikk for å installere.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Ny \"nightly build\" er tilgjengelig.\nKlikk for å installere.</string> diff --git a/main/res/values-nl/strings.xml b/main/res/values-nl/strings.xml index bcf8c74..e5303cb 100644 --- a/main/res/values-nl/strings.xml +++ b/main/res/values-nl/strings.xml @@ -1133,13 +1133,7 @@ <string name="attribute_offset_cache_no">Geen offset cache</string> <string name="quote">Om geocaching makkelijker en gebruikers luier te maken.</string> <string name="powered_by">carnero</string> - <string name="support">Support: <a href="">support@cgeo.org</a></string> - <string name="website">Website: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo op Google Play</a></string> <string name="about_twitter">Moet <b>c:geo</b> elke cache vondst publiceren naar Twitter?</string> - <string name="faq">FAQ: <a href=""> faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Nieuwe release beschikbaar.\nTik om te installeren.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nieuwe nightly-release beschikbaar.\nTik om te installeren.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Nieuwe release-candidaad beschikbaar.\nTik om te installeren.</string> diff --git a/main/res/values-pl/strings.xml b/main/res/values-pl/strings.xml index 4cd8bb8..2aeb9aa 100644 --- a/main/res/values-pl/strings.xml +++ b/main/res/values-pl/strings.xml @@ -1127,13 +1127,7 @@ <string name="attribute_offset_cache_no">Nie jest to skrzynka Offset</string> <string name="quote">Aby uczynić geocaching prostszym, a użytkowników bardziej leniwymi.</string> <string name="powered_by">carnero</string> - <string name="support">Wsparcie: <a href="">support@cgeo.org</a></string> - <string name="website">Website: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo strona</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo w Google Play</a></string> <string name="about_twitter">Czy chczesz aby <b>c:geo</b> publikował nowy status na Twitter za każdym razem kiedy znajdziesz skrzynkę?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Dostępna nowa wersja.\nKliknij aby zainstalować.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Dostępna nowa codzienna wersja.\nKliknij aby zainstalować.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Dostępny nowy kandydat na nową wersję.\nKliknij aby zainstalować.</string> diff --git a/main/res/values-pt/strings.xml b/main/res/values-pt/strings.xml index 9848860..0bec864 100644 --- a/main/res/values-pt/strings.xml +++ b/main/res/values-pt/strings.xml @@ -1131,13 +1131,7 @@ <string name="attribute_offset_cache_no">Cache sem offset de translação</string> <string name="quote">Para tornar o geocaching mais fácil, para tornar os utilizadores mais preguiçosos.</string> <string name="powered_by">carnero</string> - <string name="support">Suporte: <a href="">support@cgeo.org</a></string> - <string name="website">Site na internet: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">página do c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo no Google Play</a></string> <string name="about_twitter">O <b>c:geo</b> deve publicar no Twitter de cada vez que uma cache foi registrada?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Nova versão disponível.\nClique para instalar.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nova \'nightly build\' disponível.\nClique para instalar.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Nova \'release candidate\' disponível .\nClique para instalar.</string> diff --git a/main/res/values-ro/strings.xml b/main/res/values-ro/strings.xml index 64dfdb5..51e1208 100644 --- a/main/res/values-ro/strings.xml +++ b/main/res/values-ro/strings.xml @@ -1132,13 +1132,7 @@ <string name="attribute_offset_cache_no">Nu este geocutie decalată</string> <string name="quote">Pentru geocaching mai uşor, pentru căutători mai leneşi.</string> <string name="powered_by">carnero</string> - <string name="support">Suport: <a href="">support@cgeo.org</a></string> - <string name="website">Site: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">pagina c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo pe Google Play</a></string> <string name="about_twitter">Ar trebui ca <b>c:geo</b> să publice un statut nou pe Twitter de fiecare dată când scrii o însemnare pentru o geocutie?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">A apărut o versiune nouă.\nApasă aici pentru a instala.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">A apărut o nouă versiune zilnică.\nApasă aici pentru a instala.</string> <string name="status_new_rc" tools:ignore="UnusedResources">A apărut o un candidat pentru o versiune nouă.\nApasă aici pentru a instala.</string> diff --git a/main/res/values-sk/strings.xml b/main/res/values-sk/strings.xml index 447fb28..41afadd 100644 --- a/main/res/values-sk/strings.xml +++ b/main/res/values-sk/strings.xml @@ -1135,13 +1135,7 @@ <string name="attribute_offset_cache_no">Nie je offset cache</string> <string name="quote">Pre jednoduchšie hľadanie skrýš a používateľov lenivších.</string> <string name="powered_by">carnero</string> - <string name="support">Podpora: <a href="">support@cgeo.org</a></string> - <string name="website">Web: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href=""> c:geo na Google Play</a></string> <string name="about_twitter">Chcete, aby <b>c:geo</b> napísalo na váš Twitter vždy, keď zapíšete nájdenie skrýše?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Je dostupné nové vydanie.\nKliknite pre inštaláciu.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Je dostupná nová nočná zostava.\nKliknite pre inštaláciu.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Je dostupná nová verzia „release candidate“.\nKliknite pre inštaláciu.</string> diff --git a/main/res/values-sl/strings.xml b/main/res/values-sl/strings.xml index 71816d7..0d20fae 100644 --- a/main/res/values-sl/strings.xml +++ b/main/res/values-sl/strings.xml @@ -1110,13 +1110,7 @@ <string name="attribute_offset_cache_no">Ni Offset zaklad</string> <string name="quote">Za lažji geocaching in bolj lene zakladolovce.</string> <string name="powered_by">carnero</string> - <string name="support">Podpora: <a href="">support@cgeo.org</a></string> - <string name="website">Spletna stran: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo stran</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo na Google Play</a></string> <string name="about_twitter">Naj <b>c:geo</b> objavi nov status na Twitter, ko objavite nov zapis pri zakladu?</string> - <string name="faq">Pogosto zastavljena vprašanja: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Na voljo je nova različica.\nKliknite za namestitev.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Na voljo je nova dnevna različica.\nKliknite za namestitev.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Na voljo je nova preizkusna različica.\nKliknite za namestitev.</string> diff --git a/main/res/values-sv/strings.xml b/main/res/values-sv/strings.xml index 684d7cf..a2cefcd 100644 --- a/main/res/values-sv/strings.xml +++ b/main/res/values-sv/strings.xml @@ -1137,13 +1137,7 @@ <string name="attribute_offset_cache_no">Ingen offset cache</string> <string name="quote">To make geocaching easier, to make users lazier.</string> <string name="powered_by">carnero</string> - <string name="support">Support: <a href="">support@cgeo.org</a></string> - <string name="website">Hemsida: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo på Google Play</a></string> <string name="about_twitter">Ska <b>c:geo</b> publicera ny status på Twitter varje gång en cache loggas?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Ny officiell version finns tillgänglig.\nKlicka för att installera.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nytt nattligt bygge finns tillgängligt.\nKlicka för att installera.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Ny kandidat till officiellt bygge finns tillgängligt.\nKlicka för att installera.</string> diff --git a/main/res/values/changelog_master.xml b/main/res/values/changelog_master.xml index 1e3c3d4..e0c530e 100644 --- a/main/res/values/changelog_master.xml +++ b/main/res/values/changelog_master.xml @@ -2,5 +2,12 @@ <resources> <!-- changelog for the master branch --> <string name="changelog_master" translatable="false"> + <b>Next feature release:</b>\n + · New: confirmation on backup/restore\n + · New: sort events of same date by time (if recognized from cache description)\n + · New: show rudimentary details for geocaching.com.au swaggies\n + · New: Weekday shown in event lists\n + · New: Filter for caches with offline logs\n + \n </string> </resources> diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index 2d8bdf7..9c250c8 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -325,6 +325,7 @@ <string name="caches_filter_track">With Trackables</string> <string name="caches_filter_clear">Clear filters</string> <string name="caches_filter_modified">With modified coordinates</string> + <string name="caches_filter_offline_log">With offline log</string> <string name="caches_filter_origin">Origin</string> <string name="caches_filter_distance">Distance</string> <string name="caches_filter_personal_note">With personal note</string> @@ -497,6 +498,8 @@ <string name="init_backup_success">c:geo\'s database was successfully copied to:</string> <string name="init_backup_failed">Backup of c:geo\'s database failed.</string> <string name="init_backup_unnecessary">Database is empty, no backup necessary.</string> + <string name="backup_confirm_overwrite">Do you want to overwrite the existing backup from %s?</string> + <string name="restore_confirm_overwrite">Do you want to overwrite %s on your device with the backup?</string> <string name="init_restore_success">Restoration completed.</string> <string name="init_restore_failed">Restoration failed.</string> <string name="init_restore_running">Restoring cache database…</string> @@ -1234,13 +1237,15 @@ <string name="quote">To make geocaching easier, to make users lazier.</string> <string name="powered_by">carnero</string> <!-- Note: Links here are just for appearance. See AboutActivity to make changes --> - <string name="support">Support: <a href="">support@cgeo.org</a></string> - <string name="website">Website: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo on Google Play</a></string> + <string name="support_title">Support</string> + <string name="website_title">Website</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">c:geo page</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo on Google Play</a></string> <string name="about_twitter">Should <b>c:geo</b> publish a new status on Twitter every time you log a cache?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">FAQ</string> <!-- status (used via string based resource loading) --> <string name="status_new_release" tools:ignore="UnusedResources">New release available.\nClick to install.</string> diff --git a/main/res/values/strings_not_translatable.xml b/main/res/values/strings_not_translatable.xml index 35fef08..d699f62 100644 --- a/main/res/values/strings_not_translatable.xml +++ b/main/res/values/strings_not_translatable.xml @@ -90,5 +90,10 @@ <string name="caches_map_mapswithme" translatable="false">Maps.me</string> <string name="cache_menu_mapswithme" translatable="false">Maps.me</string> + <string name="faq_link"><a href="">faq.cgeo.org</a></string> + <string name="website_link"><a href="">cgeo.org</a></string> + <string name="twitter_link"><a href="">@android_GC</a></string> + <string name="support_link"><a href="">support@cgeo.org</a></string> + </resources> diff --git a/main/res/values/themes.xml b/main/res/values/themes.xml index 50485b3..751f325 100644 --- a/main/res/values/themes.xml +++ b/main/res/values/themes.xml @@ -9,7 +9,7 @@ <style name="cgeo_main.base" parent="@style/Theme.AppCompat"> - <!-- copy the style elements of the Wallpaper theme since AppCombat has no Wallpaper theme --> + <!-- copy the style elements of the Wallpaper theme since AppCompat has no Wallpaper theme --> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:windowShowWallpaper">true</item> diff --git a/main/src/cgeo/calendar/CalendarAddon.java b/main/src/cgeo/calendar/CalendarAddon.java index 8737447..88c67a8 100644 --- a/main/src/cgeo/calendar/CalendarAddon.java +++ b/main/src/cgeo/calendar/CalendarAddon.java @@ -8,6 +8,7 @@ import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.ProcessUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; import android.content.DialogInterface; @@ -27,10 +28,11 @@ public class CalendarAddon { return ProcessUtils.isIntentAvailable(ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST)); } - public static void addToCalendarWithIntent(final Activity activity, final Geocache cache) { + public static void addToCalendarWithIntent(@NonNull final Activity activity, @NonNull final Geocache cache) { final Resources res = activity.getResources(); if (CalendarAddon.isAvailable()) { final Date hiddenDate = cache.getHiddenDate(); + final String startTime = cache.guessEventTimeMinutes() >= 0 ? String.valueOf(cache.guessEventTimeMinutes()) : StringUtils.EMPTY; final Parameters params = new Parameters( ICalendar.PARAM_NAME, cache.getName(), ICalendar.PARAM_NOTE, StringUtils.defaultString(cache.getPersonalNote()), @@ -39,7 +41,7 @@ public class CalendarAddon { ICalendar.PARAM_COORDS, cache.getCoords() == null ? "" : cache.getCoords().format(GeopointFormatter.Format.LAT_LON_DECMINUTE_RAW), ICalendar.PARAM_LOCATION, StringUtils.defaultString(cache.getLocation()), ICalendar.PARAM_SHORT_DESC, StringUtils.defaultString(cache.getShortDescription()), - ICalendar.PARAM_START_TIME_MINUTES, StringUtils.defaultString(cache.guessEventTimeMinutes()) + ICalendar.PARAM_START_TIME_MINUTES, startTime ); activity.startActivity(new Intent(ICalendar.INTENT, @@ -51,10 +53,8 @@ public class CalendarAddon { .append(res.getString(R.string.addon_download_prompt)) .toString(), new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int id) { - final Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(ICalendar.CALENDAR_ADDON_URI)); - activity.startActivity(intent); + public void onClick(final DialogInterface dialog, final int id) { + ProcessUtils.openMarket(activity, "cgeo.calendar"); } }); } diff --git a/main/src/cgeo/calendar/ICalendar.java b/main/src/cgeo/calendar/ICalendar.java index 6ecb6d5..9001198 100644 --- a/main/src/cgeo/calendar/ICalendar.java +++ b/main/src/cgeo/calendar/ICalendar.java @@ -1,19 +1,22 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + public interface ICalendar { - static final String CALENDAR_ADDON_URI = "market://details?id=cgeo.calendar"; + @Deprecated + @NonNull static final String CALENDAR_ADDON_URI = "market://details?id=cgeo.calendar"; - static final String INTENT = "cgeo.calendar.RESERVE"; + @NonNull static final String INTENT = "cgeo.calendar.RESERVE"; - static final String URI_SCHEME = "add"; - static final String URI_HOST = "cgeo.org"; + @NonNull static final String URI_SCHEME = "add"; + @NonNull static final String URI_HOST = "cgeo.org"; - static final String PARAM_SHORT_DESC = "shortDesc"; // cache short description - static final String PARAM_HIDDEN_DATE = "hiddenDate"; // cache hidden date in milliseconds - static final String PARAM_URL = "url"; // cache URL - static final String PARAM_NOTE = "note"; // personal note - static final String PARAM_NAME = "name"; // cache name - static final String PARAM_LOCATION = "location"; // cache location, or empty string - static final String PARAM_COORDS = "coords"; // cache coordinates, or empty string - static final String PARAM_START_TIME_MINUTES = "time"; // time of start + @NonNull static final String PARAM_SHORT_DESC = "shortDesc"; // cache short description + @NonNull static final String PARAM_HIDDEN_DATE = "hiddenDate"; // cache hidden date in milliseconds + @NonNull static final String PARAM_URL = "url"; // cache URL + @NonNull static final String PARAM_NOTE = "note"; // personal note + @NonNull static final String PARAM_NAME = "name"; // cache name + @NonNull static final String PARAM_LOCATION = "location"; // cache location, or empty string + @NonNull static final String PARAM_COORDS = "coords"; // cache coordinates, or empty string + @NonNull static final String PARAM_START_TIME_MINUTES = "time"; // time of start } diff --git a/main/src/cgeo/contacts/ContactsAddon.java b/main/src/cgeo/contacts/ContactsAddon.java index 7165a77..6c0dd21 100644 --- a/main/src/cgeo/contacts/ContactsAddon.java +++ b/main/src/cgeo/contacts/ContactsAddon.java @@ -3,6 +3,8 @@ package cgeo.contacts; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.ProcessUtils; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.content.Intent; import android.net.Uri; @@ -13,7 +15,7 @@ public class ContactsAddon { // utility class } - public static void openContactCard(Activity context, String userName) { + public static void openContactCard(@NonNull final Activity context, @NonNull final String userName) { final Parameters params = new Parameters( IContacts.PARAM_NAME, userName ); diff --git a/main/src/cgeo/contacts/IContacts.java b/main/src/cgeo/contacts/IContacts.java index d68b78a..5a6c04d 100644 --- a/main/src/cgeo/contacts/IContacts.java +++ b/main/src/cgeo/contacts/IContacts.java @@ -1,10 +1,12 @@ package cgeo.contacts; +import org.eclipse.jdt.annotation.NonNull; + public interface IContacts { - static final String INTENT = "cgeo.contacts.FIND"; + @NonNull static final String INTENT = "cgeo.contacts.FIND"; - static final String URI_SCHEME = "find"; - static final String URI_HOST = "cgeo.org"; + @NonNull static final String URI_SCHEME = "find"; + @NonNull static final String URI_HOST = "cgeo.org"; - static final String PARAM_NAME = "name"; // user name + @NonNull static final String PARAM_NAME = "name"; // user name } diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java index ceafc31..ffc4b35 100644 --- a/main/src/cgeo/geocaching/AboutActivity.java +++ b/main/src/cgeo/geocaching/AboutActivity.java @@ -4,12 +4,14 @@ import butterknife.ButterKnife; import butterknife.InjectView; import cgeo.geocaching.activity.AbstractViewPagerActivity; +import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.sensors.OrientationProvider; import cgeo.geocaching.sensors.RotationProvider; import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.AbstractCachingPageViewCreator; import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; +import cgeo.geocaching.utils.ProcessUtils; import cgeo.geocaching.utils.Version; import org.apache.commons.io.IOUtils; @@ -98,6 +100,7 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> ButterKnife.inject(this, view); system.setText(systemInformation(AboutActivity.this)); system.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); + Compatibility.setTextIsSelectable(system, true); return view; } } @@ -125,7 +128,7 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> @Override public void onClick(final View v) { - market(); + ProcessUtils.openMarket(AboutActivity.this, getPackageName()); } }); return view; @@ -190,12 +193,6 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); } - final void market() { - final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName())); - marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - startActivity(marketIntent); - } - @Override protected final cgeo.geocaching.activity.AbstractViewPagerActivity.PageViewCreator createViewCreator(final Page page) { switch (page) { diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 2be802f..9ebad8b 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -61,6 +61,7 @@ import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; +import org.eclipse.jdt.annotation.Nullable; import rx.Observable; import rx.Observable.OnSubscribe; @@ -326,6 +327,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } @Override + @Nullable public String getAndroidBeamUri() { return cache != null ? cache.getCgeoUrl() : null; } @@ -494,13 +496,12 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public boolean onCreateOptionsMenu(final Menu menu) { CacheMenuHandler.addMenuItems(this, menu, cache); - MenuItem menuItem = menu.findItem(R.id.menu_default_navigation); + final MenuItem menuItem = menu.findItem(R.id.menu_default_navigation); final NavigationActionProvider navAction = (NavigationActionProvider) MenuItemCompat.getActionProvider(menuItem); if (navAction != null) { navAction.setNavigationSource(this); } - menuItem = menu.findItem(R.id.menu_navigate); - NavigationSelectionActionProvider.initialize(menuItem, cache); + NavigationSelectionActionProvider.initialize(menu.findItem(R.id.menu_navigate), cache); return true; } @@ -1462,9 +1463,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (unknownTagsHandler.isProblematicDetected()) { final int startPos = description.length(); final IConnector connector = ConnectorFactory.getConnector(cache); - final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>")); - ((Editable) description).append("\n\n").append(tableNote); - ((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (StringUtils.isNotEmpty(cache.getUrl())) { + final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>")); + ((Editable) description).append("\n\n").append(tableNote); + ((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } } } /** diff --git a/main/src/cgeo/geocaching/CacheListActivity.java b/main/src/cgeo/geocaching/CacheListActivity.java index 9090a4e..c6cac21 100644 --- a/main/src/cgeo/geocaching/CacheListActivity.java +++ b/main/src/cgeo/geocaching/CacheListActivity.java @@ -9,7 +9,9 @@ import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.activity.ShowcaseViewBuilder; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; -import cgeo.geocaching.apps.cachelist.CacheListAppFactory; +import cgeo.geocaching.apps.cachelist.CacheListApp; +import cgeo.geocaching.apps.cachelist.CacheListApps; +import cgeo.geocaching.apps.cachelist.ListNavigationSelectionActionProvider; import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.connector.gc.RecaptchaHandler; import cgeo.geocaching.enumerations.CacheListType; @@ -558,7 +560,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA public boolean onCreateOptionsMenu(final Menu menu) { getMenuInflater().inflate(R.menu.cache_list_options, menu); - CacheListAppFactory.addMenuItems(menu, this, res); sortProvider = (SortActionProvider) MenuItemCompat.getActionProvider(menu.findItem(R.id.menu_sort)); assert sortProvider != null; // We set it in the XML file sortProvider.setSelection(adapter.getCacheComparator()); @@ -579,6 +580,15 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA sortProvider.setSelection(selectedComparator); } }); + + ListNavigationSelectionActionProvider.initialize(menu.findItem(R.id.menu_cache_list_app_provider), new ListNavigationSelectionActionProvider.Callback() { + + @Override + public void onListNavigationSelected(final CacheListApp app) { + app.invoke(cacheList, CacheListActivity.this, getFilteredSearch()); + } + }); + return true; } @@ -639,6 +649,11 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA setMenuItemLabel(menu, R.id.menu_remove_from_history, R.string.cache_remove_from_history, R.string.cache_clear_history); menu.findItem(R.id.menu_import_android).setVisible(Compatibility.isStorageAccessFrameworkAvailable() && isOffline); + + final List<CacheListApp> listNavigationApps = CacheListApps.getActiveApps(); + menu.findItem(R.id.menu_cache_list_app_provider).setVisible(listNavigationApps.size() > 1); + menu.findItem(R.id.menu_cache_list_app).setVisible(listNavigationApps.size() == 1); + } catch (final RuntimeException e) { Log.e("CacheListActivity.onPrepareOptionsMenu", e); } @@ -679,9 +694,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA @Override public boolean onOptionsItemSelected(final MenuItem item) { - if (super.onOptionsItemSelected(item)) { - return true; - } switch (item.getItemId()) { case R.id.menu_show_on_map: goMap(); @@ -705,23 +717,23 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA case R.id.menu_import_android: importGpxFromAndroid(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_create_list: new StoredList.UserInterface(this).promptForListCreation(getListSwitchingRunnable(), listNameMemento.getTerm()); refreshSpinnerAdapter(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_drop_list: removeList(false); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_rename_list: renameList(); - return false; + return true; case R.id.menu_invert_selection: adapter.invertSelection(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_filter: showFilterMenu(null); return true; @@ -737,7 +749,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA case R.id.menu_remove_from_history: removeFromHistoryCheck(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_move_to_list: moveCachesToOtherList(); invalidateOptionsMenuCompatible(); @@ -751,13 +763,12 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA invalidateOptionsMenuCompatible(); return true; case R.id.menu_cache_list_app: - if (!cacheToShow()) { - return false; + if (cacheToShow()) { + CacheListApps.getActiveApps().get(0).invoke(cacheList, this, getFilteredSearch()); } - return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, getFilteredSearch()); - default: - return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, search); + return true; } + return super.onOptionsItemSelected(item); } private boolean cacheToShow() { diff --git a/main/src/cgeo/geocaching/CacheMenuHandler.java b/main/src/cgeo/geocaching/CacheMenuHandler.java index fa2f994..fbd8771 100644 --- a/main/src/cgeo/geocaching/CacheMenuHandler.java +++ b/main/src/cgeo/geocaching/CacheMenuHandler.java @@ -6,6 +6,8 @@ import cgeo.geocaching.apps.cache.navi.NavigationSelectionActionProvider; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.AbstractUIFactory; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.support.v4.app.Fragment; import android.support.v4.view.MenuItemCompat; @@ -38,7 +40,7 @@ public final class CacheMenuHandler extends AbstractUIFactory { } - public static boolean onMenuItemSelected(final MenuItem item, final CacheMenuHandler.ActivityInterface activityInterface, final Geocache cache) { + public static boolean onMenuItemSelected(final MenuItem item, @NonNull final CacheMenuHandler.ActivityInterface activityInterface, final Geocache cache) { assert activityInterface instanceof Activity || activityInterface instanceof Fragment; final Activity activity; if (activityInterface instanceof Activity) { diff --git a/main/src/cgeo/geocaching/DataStore.java b/main/src/cgeo/geocaching/DataStore.java index 02f48a0..52bf3f9 100644 --- a/main/src/cgeo/geocaching/DataStore.java +++ b/main/src/cgeo/geocaching/DataStore.java @@ -39,7 +39,6 @@ import rx.functions.Action1; import rx.functions.Func0; import rx.functions.Func1; import rx.schedulers.Schedulers; -import rx.util.async.Async; import android.app.Activity; import android.app.ProgressDialog; @@ -407,12 +406,12 @@ public class DataStore { */ public static void moveDatabase(final Activity fromActivity) { final ProgressDialog dialog = ProgressDialog.show(fromActivity, fromActivity.getString(R.string.init_dbmove_dbmove), fromActivity.getString(R.string.init_dbmove_running), true, false); - AppObservable.bindActivity(fromActivity, Async.fromCallable(new Func0<Boolean>() { + AppObservable.bindActivity(fromActivity, Observable.defer(new Func0<Observable<Boolean>>() { @Override - public Boolean call() { + public Observable<Boolean> call() { if (!LocalStorage.isExternalStorageAvailable()) { Log.w("Database was not moved: external memory not available"); - return false; + return Observable.just(false); } closeDb(); @@ -421,7 +420,7 @@ public class DataStore { if (!LocalStorage.copy(source, target)) { Log.e("Database could not be moved to " + target); init(); - return false; + return Observable.just(false); } if (!FileUtils.delete(source)) { Log.e("Original database could not be deleted during move"); @@ -430,7 +429,7 @@ public class DataStore { Log.i("Database was moved to " + target); init(); - return true; + return Observable.just(true); } })).subscribeOn(Schedulers.io()).subscribe(new Action1<Boolean>() { @Override @@ -884,7 +883,7 @@ public class DataStore { final File[] files = LocalStorage.getStorage().listFiles(); if (ArrayUtils.isNotEmpty(files)) { final Pattern oldFilePattern = Pattern.compile("^[GC|TB|EC|GK|O][A-Z0-9]{4,7}$"); - final SQLiteStatement select = db.compileStatement("select count(*) from " + dbTableCaches + " where geocode = ?"); + final SQLiteStatement select = PreparedStatement.CHECK_IF_PRESENT.getStatement(); final ArrayList<File> toRemove = new ArrayList<>(files.length); for (final File file : files) { if (file.isDirectory()) { @@ -2951,7 +2950,7 @@ public class DataStore { private static enum PreparedStatement { - HISTORY_COUNT("select count(_id) from " + dbTableCaches + " where visiteddate > 0"), + HISTORY_COUNT("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE visiteddate > 0"), MOVE_TO_STANDARD_LIST("UPDATE " + dbTableCaches + " SET reason = " + StoredList.STANDARD_LIST_ID + " WHERE reason = ?"), MOVE_TO_LIST("UPDATE " + dbTableCaches + " SET reason = ? WHERE geocode = ?"), UPDATE_VISIT_DATE("UPDATE " + dbTableCaches + " SET visiteddate = ? WHERE geocode = ?"), @@ -2967,10 +2966,11 @@ public class DataStore { LIST_ID_OF_GUID("SELECT reason FROM " + dbTableCaches + " WHERE guid = ?"), GEOCODE_OF_GUID("SELECT geocode FROM " + dbTableCaches + " WHERE guid = ?"), INSERT_SEARCH_DESTINATION("INSERT INTO " + dbTableSearchDestinationHistory + " (date, latitude, longitude) VALUES (?, ?, ?)"), - COUNT_TYPE_ALL_LIST("select count(_id) from " + dbTableCaches + " where detailed = 1 and type = ? and reason > 0"), // See use of COUNT_TYPE_LIST for synchronization - COUNT_ALL_TYPES_ALL_LIST("select count(_id) from " + dbTableCaches + " where detailed = 1 and reason > 0"), // See use of COUNT_TYPE_LIST for synchronization - COUNT_TYPE_LIST("select count(_id) from " + dbTableCaches + " where detailed = 1 and type = ? and reason = ?"), - COUNT_ALL_TYPES_LIST("select count(_id) from " + dbTableCaches + " where detailed = 1 and reason = ?"); // See use of COUNT_TYPE_LIST for synchronization + COUNT_TYPE_ALL_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND type = ? AND reason > 0"), // See use of COUNT_TYPE_LIST for synchronization + COUNT_ALL_TYPES_ALL_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND reason > 0"), // See use of COUNT_TYPE_LIST for synchronization + COUNT_TYPE_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND type = ? AND reason = ?"), + COUNT_ALL_TYPES_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND reason = ?"), // See use of COUNT_TYPE_LIST for synchronization + CHECK_IF_PRESENT("SELECT COUNT(*) FROM " + dbTableCaches + " WHERE geocode = ?"); private static final List<PreparedStatement> statements = new ArrayList<>(); diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java index 8e9485e..e47730b 100644 --- a/main/src/cgeo/geocaching/Geocache.java +++ b/main/src/cgeo/geocaching/Geocache.java @@ -85,6 +85,8 @@ public class Geocache implements IWaypoint { private long visitedDate = 0; private int listId = StoredList.TEMPORARY_LIST.id; private boolean detailed = false; + + @NonNull private String geocode = ""; private String cacheId = ""; private String guid = ""; @@ -484,6 +486,9 @@ public class Geocache implements IWaypoint { } public void openInBrowser(final Activity fromActivity) { + if (getUrl() == null) { + return; + } final Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getLongUrl())); // Check if cgeo is the default, show the chooser to let the user choose a browser @@ -696,11 +701,7 @@ public class Geocache implements IWaypoint { return getConnector() instanceof ISearchByCenter; } - public void shareCache(final Activity fromActivity, final Resources res) { - if (geocode == null) { - return; - } - + public void shareCache(@NonNull final Activity fromActivity, final Resources res) { final Intent intent = getShareIntent(); fromActivity.startActivity(Intent.createChooser(intent, res.getText(R.string.cache_menu_share))); @@ -717,22 +718,22 @@ public class Geocache implements IWaypoint { final Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_SUBJECT, subject.toString()); - intent.putExtra(Intent.EXTRA_TEXT, getUrl()); + intent.putExtra(Intent.EXTRA_TEXT, StringUtils.defaultString(getUrl())); return intent; } - @NonNull + @Nullable public String getUrl() { return getConnector().getCacheUrl(this); } - @NonNull + @Nullable public String getLongUrl() { return getConnector().getLongCacheUrl(this); } - @NonNull + @Nullable public String getCgeoUrl() { return getConnector().getCacheUrl(this); } @@ -1060,7 +1061,7 @@ public class Geocache implements IWaypoint { this.directionImg = directionImg; } - public void setGeocode(final String geocode) { + public void setGeocode(@NonNull final String geocode) { this.geocode = StringUtils.upperCase(geocode); } @@ -1631,10 +1632,9 @@ public class Geocache implements IWaypoint { * * @return start time in minutes after midnight */ - @Nullable - public String guessEventTimeMinutes() { + public int guessEventTimeMinutes() { if (!isEventCache()) { - return null; + return -1; } final String hourLocalized = CgeoApplication.getInstance().getString(R.string.cache_time_full_hours); @@ -1660,14 +1660,14 @@ public class Geocache implements IWaypoint { minutes = Integer.parseInt(matcher.group(2)); } if (hours >= 0 && hours < 24 && minutes >= 0 && minutes < 60) { - return String.valueOf(hours * 60 + minutes); + return hours * 60 + minutes; } } catch (final NumberFormatException ignored) { // cannot happen, but static code analysis doesn't know } } } - return null; + return -1; } public boolean hasStaticMap() { diff --git a/main/src/cgeo/geocaching/ImagesActivity.java b/main/src/cgeo/geocaching/ImagesActivity.java index b75e5eb..975a720 100644 --- a/main/src/cgeo/geocaching/ImagesActivity.java +++ b/main/src/cgeo/geocaching/ImagesActivity.java @@ -6,6 +6,7 @@ import cgeo.geocaching.ui.ImagesList; import cgeo.geocaching.ui.ImagesList.ImageType; import org.apache.commons.collections4.CollectionUtils; + import rx.Subscription; import android.content.Context; @@ -28,7 +29,7 @@ public class ImagesActivity extends AbstractActionBarActivity { private Subscription subscription; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // get parameters @@ -78,11 +79,12 @@ public class ImagesActivity extends AbstractActionBarActivity { super.onStop(); } - public static void startActivityLogImages(final Context fromActivity, final String geocode, List<Image> logImages) { + public static void startActivityLogImages(final Context fromActivity, final String geocode, final List<Image> logImages) { startActivity(fromActivity, geocode, logImages, ImageType.LogImages); } - private static void startActivity(final Context fromActivity, final String geocode, List<Image> logImages, ImageType imageType) { + @SuppressWarnings("deprecation") + private static void startActivity(final Context fromActivity, final String geocode, final List<Image> logImages, final ImageType imageType) { final Intent logImgIntent = new Intent(fromActivity, ImagesActivity.class); // if resuming our app within this activity, finish it and return to the cache activity logImgIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) @@ -95,18 +97,18 @@ public class ImagesActivity extends AbstractActionBarActivity { fromActivity.startActivity(logImgIntent); } - public static void startActivitySpoilerImages(final Context fromActivity, String geocode, List<Image> spoilers) { + public static void startActivitySpoilerImages(final Context fromActivity, final String geocode, final List<Image> spoilers) { startActivity(fromActivity, geocode, spoilers, ImageType.SpoilerImages); } @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + public void onCreateContextMenu(final ContextMenu menu, final View v, final ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); imagesList.onCreateContextMenu(menu, v); } @Override - public boolean onContextItemSelected(MenuItem item) { + public boolean onContextItemSelected(final MenuItem item) { if (imagesList.onContextItemSelected(item)) { return true; } diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java index 64ed46e..2f4471b 100644 --- a/main/src/cgeo/geocaching/SearchResult.java +++ b/main/src/cgeo/geocaching/SearchResult.java @@ -19,7 +19,6 @@ import rx.Observable; import rx.functions.Func0; import rx.functions.Func1; import rx.functions.Func2; -import rx.util.async.Async; import android.os.Parcel; import android.os.Parcelable; @@ -319,12 +318,12 @@ public class SearchResult implements Parcelable { return Observable.from(connectors).flatMap(new Func1<C, Observable<SearchResult>>() { @Override public Observable<SearchResult> call(final C connector) { - return connector.isActive() ? Async.start(new Func0<SearchResult>() { + return connector.isActive() ? Observable.defer(new Func0<Observable<SearchResult>>() { @Override - public SearchResult call() { - return func.call(connector); + public Observable<SearchResult> call() { + return Observable.just(func.call(connector)); } - }, RxUtils.networkScheduler) : Observable.<SearchResult>empty(); + }).subscribeOn(RxUtils.networkScheduler) : Observable.<SearchResult>empty(); } }).reduce(new SearchResult(), new Func2<SearchResult, SearchResult, SearchResult>() { @Override diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 5184f71..6d18cb4 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -16,9 +16,7 @@ import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import rx.Observable; -import rx.functions.Action0; import rx.functions.Func0; -import rx.util.async.Async; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -86,9 +84,9 @@ public final class StaticMapsProvider { final int requestWidth = Math.min(width / scale, GOOGLE_MAPS_MAX_SIZE); final int requestHeight = (aspectRatio > 1) ? Math.round(requestWidth / aspectRatio) : requestWidth; final int requestZoom = Math.min((scale == 2) ? zoom + 1 : zoom, GOOGLE_MAX_ZOOM); - return checkDownloadPermission(Async.fromAction(new Action0() { + return checkDownloadPermission(Observable.defer(new Func0<Observable<String>>() { @Override - public void call() { + public Observable<String> call() { final Parameters params = new Parameters( "center", latlonMap, "zoom", String.valueOf(requestZoom), @@ -104,7 +102,7 @@ public final class StaticMapsProvider { if (httpResponse == null) { Log.e("StaticMapsProvider.downloadMap: httpResponse is null"); - return; + return Observable.just(prefix); } final int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode != 200) { @@ -112,7 +110,7 @@ public final class StaticMapsProvider { if (statusCode == 403) { last403 = System.currentTimeMillis(); } - return; + return Observable.just(prefix); } final File file = getMapFile(geocode, prefix, true); if (LocalStorage.saveEntityToFile(httpResponse, file)) { @@ -122,8 +120,9 @@ public final class StaticMapsProvider { FileUtils.deleteIgnoringFailure(file); } } + return Observable.just(prefix); } - }, prefix, RxUtils.networkScheduler)); + }).subscribeOn(RxUtils.networkScheduler)); } public static Observable<String> downloadMaps(final Geocache cache) { @@ -216,9 +215,8 @@ public final class StaticMapsProvider { public static Observable<String> storeCachePreviewMap(final Geocache cache) { final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA); final Point displaySize = Compatibility.getDisplaySize(); - final int minSize = Math.min(displaySize.x, displaySize.y); final String markerUrl = MARKERS_URL + "my_location_mdpi.png"; - return downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, minSize, minSize, null); + return downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, displaySize.x, displaySize.y, null); } private static Observable<String> downloadMaps(final String geocode, final String markerUrl, final String prefix, diff --git a/main/src/cgeo/geocaching/UsefulAppsActivity.java b/main/src/cgeo/geocaching/UsefulAppsActivity.java index dd92350..d4517dc 100644 --- a/main/src/cgeo/geocaching/UsefulAppsActivity.java +++ b/main/src/cgeo/geocaching/UsefulAppsActivity.java @@ -5,8 +5,10 @@ import butterknife.InjectView; import cgeo.geocaching.activity.AbstractActionBarActivity; import cgeo.geocaching.ui.AbstractViewHolder; +import cgeo.geocaching.utils.ProcessUtils; + +import org.eclipse.jdt.annotation.NonNull; -import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -36,27 +38,16 @@ public class UsefulAppsActivity extends AbstractActionBarActivity { private final int titleId; private final int descriptionId; private final int iconId; + @NonNull private final String packageName; - public HelperApp(final int title, final int description, final int icon, final String packageName) { + public HelperApp(final int title, final int description, final int icon, @NonNull final String packageName) { this.titleId = title; this.descriptionId = description; this.iconId = icon; this.packageName = packageName; } - private void installFromMarket(final Activity activity) { - try { - // allow also opening pure http URLs in addition to market packages - final String url = (packageName.startsWith("http:")) ? packageName : "market://details?id=" + packageName; - final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - activity.startActivity(marketIntent); - - } catch (final RuntimeException ignored) { - // market not available in standard emulator - } - } } private static final HelperApp[] HELPER_APPS = { @@ -106,7 +97,12 @@ public class UsefulAppsActivity extends AbstractActionBarActivity { @Override public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) { final HelperApp helperApp = HELPER_APPS[position]; - helperApp.installFromMarket(UsefulAppsActivity.this); + if (helperApp.packageName.startsWith("http")) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(helperApp.packageName))); + } + else { + ProcessUtils.openMarket(UsefulAppsActivity.this, helperApp.packageName); + } } }); } diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index 4cddfe6..7626ba8 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -212,6 +212,7 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs public interface ActivitySharingInterface { /** Return an URL that represent the current activity for sharing or null for no sharing. */ + @Nullable public String getAndroidBeamUri(); } diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java index 14a2fbf..ff323e6 100644 --- a/main/src/cgeo/geocaching/activity/ActivityMixin.java +++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java @@ -190,7 +190,7 @@ public final class ActivityMixin { } public static void presentShowcase(final IAbstractActivity activity) { - if (VERSION.SDK_INT < 11) { + if (VERSION.SDK_INT < 14) { return; } final ShowcaseViewBuilder builder = activity.getShowcase(); diff --git a/main/src/cgeo/geocaching/apps/AbstractApp.java b/main/src/cgeo/geocaching/apps/AbstractApp.java index 494e245..fa052f1 100644 --- a/main/src/cgeo/geocaching/apps/AbstractApp.java +++ b/main/src/cgeo/geocaching/apps/AbstractApp.java @@ -5,28 +5,31 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.utils.ProcessUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import android.content.Intent; public abstract class AbstractApp implements App { - private final String packageName; - private final String intent; + @Nullable private final String packageName; + @Nullable private final String intent; + @NonNull private final String name; /** * a unique id, defined in res/values/ids.xml */ private final int id; - protected AbstractApp(final String name, final int id, final String intent, - final String packageName) { + protected AbstractApp(@NonNull final String name, final int id, @Nullable final String intent, + @Nullable final String packageName) { this.name = name; this.id = id; this.intent = intent; this.packageName = packageName; } - protected AbstractApp(final String name, final int id, final String intent) { + protected AbstractApp(@NonNull final String name, final int id, @Nullable final String intent) { this(name, id, intent, null); } @@ -38,6 +41,7 @@ public abstract class AbstractApp implements App { return ProcessUtils.isIntentAvailable(intent); } + @Nullable protected Intent getLaunchIntent() { return ProcessUtils.getLaunchIntent(packageName); } @@ -48,6 +52,7 @@ public abstract class AbstractApp implements App { } @Override + @NonNull public String getName() { return name; } @@ -57,12 +62,12 @@ public abstract class AbstractApp implements App { return id; } - protected static String getString(int ressourceId) { + protected static String getString(final int ressourceId) { return CgeoApplication.getInstance().getString(ressourceId); } @Override - public boolean isEnabled(Geocache cache) { + public boolean isEnabled(final Geocache cache) { return cache != null; } } diff --git a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java index baf36a4..9f39604 100644 --- a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java +++ b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java @@ -8,6 +8,7 @@ import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.utils.SynchronizedDateFormat; +import menion.android.locus.LocusDataStorageProvider; import menion.android.locus.addon.publiclib.DisplayData; import menion.android.locus.addon.publiclib.LocusUtils; import menion.android.locus.addon.publiclib.geoData.Point; @@ -15,6 +16,9 @@ import menion.android.locus.addon.publiclib.geoData.PointGeocachingData; import menion.android.locus.addon.publiclib.geoData.PointGeocachingDataWaypoint; import menion.android.locus.addon.publiclib.geoData.PointsData; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import android.app.Activity; import android.location.Location; @@ -31,7 +35,7 @@ import java.util.Locale; public abstract class AbstractLocusApp extends AbstractApp { private static final SynchronizedDateFormat ISO8601DATE = new SynchronizedDateFormat("yyyy-MM-dd'T'", Locale.US); - protected AbstractLocusApp(final String text, int id, final String intent) { + protected AbstractLocusApp(@NonNull final String text, final int id, @NonNull final String intent) { super(text, id, intent); } @@ -57,7 +61,7 @@ public abstract class AbstractLocusApp extends AbstractApp { final boolean withCacheDetails = objectsToShow.size() < 200; final PointsData pd = new PointsData("c:geo"); - for (Object o : objectsToShow) { + for (final Object o : objectsToShow) { Point p = null; // get icon and Point if (o instanceof Geocache) { @@ -98,7 +102,8 @@ public abstract class AbstractLocusApp extends AbstractApp { * should be false for all if more then 200 Caches are transferred * @return null, when the <code>Point</code> could not be constructed */ - private static Point getCachePoint(Geocache cache, boolean withWaypoints, boolean withCacheDetails) { + @Nullable + private static Point getCachePoint(final Geocache cache, final boolean withWaypoints, final boolean withCacheDetails) { if (cache == null || cache.getCoords() == null) { return null; } @@ -141,19 +146,24 @@ public abstract class AbstractLocusApp extends AbstractApp { if (withWaypoints && cache.hasWaypoints()) { pg.waypoints = new ArrayList<>(); - for (Waypoint waypoint : cache.getWaypoints()) { - if (waypoint == null || waypoint.getCoords() == null) { + for (final Waypoint waypoint : cache.getWaypoints()) { + if (waypoint == null) { continue; } - PointGeocachingDataWaypoint wp = new PointGeocachingDataWaypoint(); - wp.code = waypoint.getGeocode(); + + final PointGeocachingDataWaypoint wp = new PointGeocachingDataWaypoint(); + wp.code = waypoint.getLookup(); wp.name = waypoint.getName(); - String locusWpId = toLocusWaypoint(waypoint.getWaypointType()); + wp.description = waypoint.getNote(); + final String locusWpId = toLocusWaypoint(waypoint.getWaypointType()); if (locusWpId != null) { wp.type = locusWpId; } - wp.lat = waypoint.getCoords().getLatitude(); - wp.lon = waypoint.getCoords().getLongitude(); + + if (waypoint.getCoords() != null) { + wp.lat = waypoint.getCoords().getLatitude(); + wp.lon = waypoint.getCoords().getLongitude(); + } pg.waypoints.add(wp); } } @@ -177,7 +187,8 @@ public abstract class AbstractLocusApp extends AbstractApp { * @param waypoint * @return null, when the <code>Point</code> could not be constructed */ - private static Point getWaypointPoint(Waypoint waypoint) { + @Nullable + private static Point getWaypointPoint(final Waypoint waypoint) { if (waypoint == null || waypoint.getCoords() == null) { return null; } @@ -248,6 +259,7 @@ public abstract class AbstractLocusApp extends AbstractApp { } } + @Nullable private static String toLocusWaypoint(final WaypointType wt) { switch (wt) { case FINAL: @@ -268,5 +280,4 @@ public abstract class AbstractLocusApp extends AbstractApp { return null; } } - } diff --git a/main/src/cgeo/geocaching/apps/App.java b/main/src/cgeo/geocaching/apps/App.java index 7e70581..db306ac 100644 --- a/main/src/cgeo/geocaching/apps/App.java +++ b/main/src/cgeo/geocaching/apps/App.java @@ -2,6 +2,8 @@ package cgeo.geocaching.apps; import cgeo.geocaching.Geocache; +import org.eclipse.jdt.annotation.NonNull; + public interface App { public boolean isInstalled(); @@ -10,6 +12,7 @@ public interface App { */ public boolean isUsableAsDefaultNavigationApp(); + @NonNull public String getName(); /** diff --git a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java index c4f2723..4e542b8 100644 --- a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java +++ b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java @@ -4,17 +4,19 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.apps.AbstractApp; import cgeo.geocaching.apps.cache.navi.CacheNavigationApp; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.content.Intent; abstract class AbstractGeneralApp extends AbstractApp implements CacheNavigationApp { - protected AbstractGeneralApp(final String name, final int id, final String packageName) { + protected AbstractGeneralApp(@NonNull final String name, final int id, @NonNull final String packageName) { super(name, id, null, packageName); } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { final Intent intent = getLaunchIntent(); if (intent != null) { intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java index 5e7a5cc..0bf2c1c 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java @@ -7,6 +7,8 @@ import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.apps.AbstractApp; import cgeo.geocaching.location.Geopoint; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.content.Intent; @@ -15,20 +17,20 @@ import android.content.Intent; */ abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp, GeopointNavigationApp { - protected AbstractPointNavigationApp(final String name, final int id, final String intent) { + protected AbstractPointNavigationApp(@NonNull final String name, final int id, final String intent) { super(name, id, intent); } - protected AbstractPointNavigationApp(final String name, final int id, final String intent, final String packageName) { + protected AbstractPointNavigationApp(@NonNull final String name, final int id, final String intent, final String packageName) { super(name, id, intent, packageName); } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { navigateWithNullCheck(activity, cache.getCoords()); } - private void navigateWithNullCheck(Activity activity, final Geopoint coords) { + private void navigateWithNullCheck(final Activity activity, final Geopoint coords) { if (coords != null) { navigate(activity, coords); } else { @@ -37,17 +39,17 @@ abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNa } @Override - public void navigate(Activity activity, Waypoint waypoint) { + public void navigate(final Activity activity, final Waypoint waypoint) { navigateWithNullCheck(activity, waypoint.getCoords()); } @Override - public boolean isEnabled(Geocache cache) { + public boolean isEnabled(final Geocache cache) { return cache.getCoords() != null; } @Override - public boolean isEnabled(Waypoint waypoint) { + public boolean isEnabled(final Waypoint waypoint) { return waypoint.getCoords() != null; } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java index a2a5803..700c8aa 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java @@ -11,11 +11,12 @@ import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.apps.AbstractApp; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp { - protected AbstractStaticMapsApp(final String name, final int id) { + protected AbstractStaticMapsApp(@NonNull final String name, final int id) { super(name, id, null); } @@ -29,11 +30,11 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat return false; } - protected static boolean hasStaticMap(Waypoint waypoint) { + protected static boolean hasStaticMap(final Waypoint waypoint) { if (waypoint==null) { return false; } - String geocode = waypoint.getGeocode(); + final String geocode = waypoint.getGeocode(); if (StringUtils.isNotEmpty(geocode) && DataStore.isOffline(geocode, null)) { return StaticMapsProvider.hasStaticMapForWaypoint(geocode, waypoint); } @@ -49,7 +50,7 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat } final String geocode = StringUtils.upperCase(logable.getGeocode()); - StaticMapsActivity_.IntentBuilder_ builder = StaticMapsActivity_.intent(activity).geocode(geocode).download(download); + final StaticMapsActivity_.IntentBuilder_ builder = StaticMapsActivity_.intent(activity).geocode(geocode).download(download); if (waypoint != null) { builder.waypointId(waypoint.getId()); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java index 82883a2..d97efb5 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java @@ -3,6 +3,7 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.Geocache; import cgeo.geocaching.apps.App; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum; +import cgeo.geocaching.ui.AbstractMenuActionProvider; import android.app.Activity; import android.content.Context; @@ -12,11 +13,10 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MenuItem.OnMenuItemClickListener; import android.view.SubMenu; -import android.view.View; import java.util.List; -public class NavigationSelectionActionProvider extends ActionProvider { +public class NavigationSelectionActionProvider extends AbstractMenuActionProvider { private Geocache geocache; private final Activity activity; @@ -26,17 +26,6 @@ public class NavigationSelectionActionProvider extends ActionProvider { activity = (Activity) context; } - @Override - public boolean hasSubMenu() { - return true; - } - - @Override - public View onCreateActionView() { - // must return null, otherwise the menu will not work - return null; - } - public void setTarget(final Geocache cache) { geocache = cache; } diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java index 40c4d92..8beb5e4 100644 --- a/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java +++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java @@ -8,7 +8,7 @@ import android.app.Activity; import java.util.List; -interface CacheListApp extends App { +public interface CacheListApp extends App { boolean invoke(final List<Geocache> caches, final Activity activity, final SearchResult search); diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java deleted file mode 100644 index b6706a0..0000000 --- a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java +++ /dev/null @@ -1,89 +0,0 @@ -package cgeo.geocaching.apps.cachelist; - -import cgeo.geocaching.Geocache; -import cgeo.geocaching.R; -import cgeo.geocaching.SearchResult; -import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.apps.AbstractAppFactory; -import cgeo.geocaching.utils.Log; - -import android.app.Activity; -import android.content.res.Resources; -import android.view.Menu; -import android.view.MenuItem; -import android.view.SubMenu; - -import java.util.ArrayList; -import java.util.List; - -public final class CacheListAppFactory extends AbstractAppFactory { - - private CacheListAppFactory() { - // utility class - } - - private static class LazyHolder { - public static final CacheListApp[] apps = { - new InternalCacheListMap(), - new LocusShowCacheListApp(), - new LocusExportCacheListApp(), - new MapsWithMeCacheListApp() - }; - } - - /** - * @param menu - * @param activity - * @param res - */ - public static void addMenuItems(final Menu menu, final Activity activity, final Resources res) { - final List<CacheListApp> activeApps = getActiveApps(); - if (activeApps.isEmpty()) { - return; - } - if (activeApps.size() == 1) { - final MenuItem subItem = menu.findItem(R.id.menu_cache_list_app); - subItem.setVisible(true); - subItem.setTitle(activeApps.get(0).getName()); - } else { - final MenuItem subItem = menu.findItem(R.id.submenu_cache_list_app); - subItem.setVisible(true); - final SubMenu subMenu = subItem.getSubMenu(); - for (final CacheListApp app : activeApps) { - subMenu.add(0, app.getId(), 0, app.getName()); - } - } - } - - private static List<CacheListApp> getActiveApps() { - final List<CacheListApp> activeApps = new ArrayList<>(LazyHolder.apps.length); - for (final CacheListApp app : LazyHolder.apps) { - if (app.isInstalled()) { - activeApps.add(app); - } - } - return activeApps; - } - - public static boolean onMenuItemSelected(final MenuItem item, final List<Geocache> caches, final Activity activity, - final SearchResult search) { - CacheListApp app; - if (item.getItemId() == R.id.menu_cache_list_app) { - app = getActiveApps().get(0); - } - else { - app = (CacheListApp) getAppFromMenuItem(item, LazyHolder.apps); - } - if (app != null) { - try { - final boolean result = app.invoke(caches, activity, search); - ActivityMixin.invalidateOptionsMenu(activity); - return result; - } catch (final Exception e) { - Log.e("CacheListAppFactory.onMenuItemSelected", e); - } - } - return false; - } - -} diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListApps.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListApps.java new file mode 100644 index 0000000..e8e81a8 --- /dev/null +++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListApps.java @@ -0,0 +1,29 @@ +package cgeo.geocaching.apps.cachelist; + +import java.util.ArrayList; +import java.util.List; + +public enum CacheListApps { + INTERNAL(new InternalCacheListMap()), + LOCUS_SHOW(new LocusShowCacheListApp()), + LOCUS_EXPORT(new LocusExportCacheListApp()), + MAPS_ME(new MapsWithMeCacheListApp()); + + private final CacheListApp app; + + private CacheListApps(final CacheListApp app) { + this.app = app; + } + + public static List<CacheListApp> getActiveApps() { + final List<CacheListApp> activeApps = new ArrayList<>(); + for (final CacheListApps appEnum : values()) { + if (appEnum.app.isInstalled()) { + activeApps.add(appEnum.app); + } + } + return activeApps; + } + +} + diff --git a/main/src/cgeo/geocaching/apps/cachelist/ListNavigationSelectionActionProvider.java b/main/src/cgeo/geocaching/apps/cachelist/ListNavigationSelectionActionProvider.java new file mode 100644 index 0000000..6a49995 --- /dev/null +++ b/main/src/cgeo/geocaching/apps/cachelist/ListNavigationSelectionActionProvider.java @@ -0,0 +1,60 @@ +package cgeo.geocaching.apps.cachelist; + +import cgeo.geocaching.ui.AbstractMenuActionProvider; + +import android.content.Context; +import android.support.v4.view.ActionProvider; +import android.support.v4.view.MenuItemCompat; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.SubMenu; + +import java.util.List; + +public class ListNavigationSelectionActionProvider extends AbstractMenuActionProvider { + + public static interface Callback { + void onListNavigationSelected(final CacheListApp app); + } + + private Callback callback; + + public ListNavigationSelectionActionProvider(final Context context) { + super(context); + } + + public void setCallback(final Callback callback) { + this.callback = callback; + } + + @Override + public void onPrepareSubMenu(final SubMenu subMenu) { + subMenu.clear(); + if (callback == null) { + return; + } + final List<CacheListApp> activeApps = CacheListApps.getActiveApps(); + for (int i = 0; i < activeApps.size(); i++) { + final CacheListApp app = activeApps.get(i); + subMenu.add(Menu.NONE, i, Menu.NONE, app.getName()).setOnMenuItemClickListener(new OnMenuItemClickListener() { + + @Override + public boolean onMenuItemClick(final MenuItem item) { + final CacheListApp app = activeApps.get(item.getItemId()); + callback.onListNavigationSelected(app); + return true; + } + }); + } + } + + public static void initialize(final MenuItem menuItem, final Callback callback) { + final ActionProvider actionProvider = MenuItemCompat.getActionProvider(menuItem); + if (actionProvider instanceof ListNavigationSelectionActionProvider) { + final ListNavigationSelectionActionProvider navigateAction = (ListNavigationSelectionActionProvider) actionProvider; + navigateAction.setCallback(callback); + } + } + +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java new file mode 100644 index 0000000..8398eb3 --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java @@ -0,0 +1,15 @@ +package cgeo.geocaching.compatibility; + +import android.annotation.TargetApi; +import android.os.Build; +import android.widget.TextView; + +@TargetApi(Build.VERSION_CODES.HONEYCOMB) +public class AndroidLevel11 implements AndroidLevel11Interface { + + @Override + public void setTextIsSelectable(final TextView textView, final boolean selectable) { + textView.setTextIsSelectable(selectable); + } + +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java new file mode 100644 index 0000000..b4111ab --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java @@ -0,0 +1,12 @@ +package cgeo.geocaching.compatibility; + +import android.widget.TextView; + +public class AndroidLevel11Emulation implements AndroidLevel11Interface { + + @Override + public void setTextIsSelectable(final TextView textView, final boolean selectable) { + // do nothing + } + +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java new file mode 100644 index 0000000..45c06a4 --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java @@ -0,0 +1,9 @@ +package cgeo.geocaching.compatibility; + +import android.widget.TextView; + +public interface AndroidLevel11Interface { + + void setTextIsSelectable(TextView textView, boolean selectable); + +} diff --git a/main/src/cgeo/geocaching/compatibility/Compatibility.java b/main/src/cgeo/geocaching/compatibility/Compatibility.java index 54e2966..ad16172 100644 --- a/main/src/cgeo/geocaching/compatibility/Compatibility.java +++ b/main/src/cgeo/geocaching/compatibility/Compatibility.java @@ -5,15 +5,18 @@ import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; import android.graphics.Point; import android.os.Build; +import android.widget.TextView; public final class Compatibility { private static final int SDK_VERSION = Build.VERSION.SDK_INT; + private static final AndroidLevel11Interface LEVEL_11; private static final AndroidLevel13Interface LEVEL_13; private static final AndroidLevel19Interface LEVEL_19; static { + LEVEL_11 = SDK_VERSION >= 11 ? new AndroidLevel11() : new AndroidLevel11Emulation(); LEVEL_13 = SDK_VERSION >= 13 ? new AndroidLevel13() : new AndroidLevel13Emulation(); LEVEL_19 = SDK_VERSION >= 19 ? new AndroidLevel19() : new AndroidLevel19Emulation(); } @@ -30,11 +33,15 @@ public final class Compatibility { return LEVEL_13.getDisplaySize(); } - public static void importGpxFromStorageAccessFramework(final @NonNull Activity activity, int requestCodeImportGpx) { + public static void importGpxFromStorageAccessFramework(final @NonNull Activity activity, final int requestCodeImportGpx) { LEVEL_19.importGpxFromStorageAccessFramework(activity, requestCodeImportGpx); } public static boolean isStorageAccessFrameworkAvailable() { return SDK_VERSION >= 19; } + + public static void setTextIsSelectable(final TextView textView, final boolean selectable) { + LEVEL_11.setTextIsSelectable(textView, selectable); + } } diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java index 4984273..0583aa1 100644 --- a/main/src/cgeo/geocaching/connector/AbstractConnector.java +++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java @@ -19,6 +19,7 @@ import cgeo.geocaching.location.Geopoint; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import rx.functions.Action1; @@ -129,7 +130,8 @@ public abstract class AbstractConnector implements IConnector { } @Override - public String getGeocodeFromUrl(final String url) { + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { final String urlPrefix = getCacheUrlPrefix(); if (StringUtils.isEmpty(urlPrefix) || StringUtils.startsWith(url, urlPrefix)) { @NonNull final String geocode = url.substring(urlPrefix.length()); @@ -144,7 +146,7 @@ public abstract class AbstractConnector implements IConnector { abstract protected String getCacheUrlPrefix(); @Override - @NonNull + @Nullable public String getLongCacheUrl(final @NonNull Geocache cache) { return getCacheUrl(cache); } @@ -201,7 +203,7 @@ public abstract class AbstractConnector implements IConnector { } @Override - public String getWaypointGpxId(final String prefix, final String geocode) { + public String getWaypointGpxId(final String prefix, @NonNull final String geocode) { // Default: just return the prefix return prefix; } diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java index b78b009..10417d2 100644 --- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java +++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java @@ -18,6 +18,7 @@ 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.SwaggieConnector; import cgeo.geocaching.connector.trackable.TrackableConnector; import cgeo.geocaching.connector.trackable.TravelBugConnector; import cgeo.geocaching.connector.trackable.UnknownTrackableConnector; @@ -74,8 +75,9 @@ public final class ConnectorFactory { @NonNull private static final Collection<TrackableConnector> TRACKABLE_CONNECTORS = Collections.unmodifiableCollection(Arrays.asList(new TrackableConnector[] { - new GeokretyConnector(), // GK must be first, as it overlaps with the secret codes of travel bugs - TravelBugConnector.getInstance(), + new GeokretyConnector(), + new SwaggieConnector(), + TravelBugConnector.getInstance(), // travel bugs last, as their secret codes overlap with other connectors UNKNOWN_TRACKABLE_CONNECTOR // must be last })); @@ -212,9 +214,12 @@ public final class ConnectorFactory { } @Nullable - public static String getGeocodeFromURL(final String url) { + public static String getGeocodeFromURL(@Nullable final String url) { + if (url == null) { + return null; + } for (final IConnector connector : CONNECTORS) { - final String geocode = connector.getGeocodeFromUrl(url); + @Nullable final String geocode = connector.getGeocodeFromUrl(url); if (StringUtils.isNotBlank(geocode)) { return geocode; } diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java index 0863723..dc4bb6a 100644 --- a/main/src/cgeo/geocaching/connector/IConnector.java +++ b/main/src/cgeo/geocaching/connector/IConnector.java @@ -6,6 +6,7 @@ import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.location.Geopoint; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.util.Collection; import java.util.List; @@ -34,7 +35,7 @@ public interface IConnector { * @param cache * @return */ - @NonNull + @Nullable public String getCacheUrl(final @NonNull Geocache cache); /** @@ -43,7 +44,7 @@ public interface IConnector { * @param cache * @return */ - @NonNull + @Nullable public String getLongCacheUrl(final @NonNull Geocache cache); /** @@ -138,7 +139,8 @@ public interface IConnector { * @param url * @return */ - public String getGeocodeFromUrl(final String url); + @Nullable + public String getGeocodeFromUrl(@NonNull final String url); /** * enable/disable uploading personal note @@ -231,7 +233,7 @@ public interface IConnector { * @param prefix * @return */ - public String getWaypointGpxId(String prefix, String geocode); + public String getWaypointGpxId(String prefix, @NonNull String geocode); /** * Get the 'prefix' (key) for a waypoint from the 'name' in the GPX file diff --git a/main/src/cgeo/geocaching/connector/UnknownConnector.java b/main/src/cgeo/geocaching/connector/UnknownConnector.java index fcf1152..cabf03e 100644 --- a/main/src/cgeo/geocaching/connector/UnknownConnector.java +++ b/main/src/cgeo/geocaching/connector/UnknownConnector.java @@ -4,6 +4,7 @@ import cgeo.geocaching.Geocache; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; class UnknownConnector extends AbstractConnector { @@ -14,9 +15,9 @@ class UnknownConnector extends AbstractConnector { } @Override - @NonNull + @Nullable public String getCacheUrl(@NonNull final Geocache cache) { - return StringUtils.EMPTY; + return null; } @Override @@ -42,7 +43,8 @@ class UnknownConnector extends AbstractConnector { } @Override - public String getGeocodeFromUrl(final String url) { + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { return null; } diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java index e43b9b5..3ad8117 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java @@ -305,7 +305,8 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public String getGeocodeFromUrl(final String url) { + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { // coord.info URLs String code = StringUtils.substringAfterLast(url, "coord.info/"); if (code != null && canHandle(code)) { @@ -375,7 +376,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public String getWaypointGpxId(final String prefix, final String geocode) { + public String getWaypointGpxId(final String prefix, @NonNull final String geocode) { String gpxId = prefix; if (StringUtils.isNotBlank(geocode) && geocode.length() > 2) { gpxId += geocode.substring(2); diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index f20df8d..4a8451b 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -57,7 +57,6 @@ import rx.functions.Action1; import rx.functions.Func0; import rx.functions.Func2; import rx.schedulers.Schedulers; -import rx.util.async.Async; import android.net.Uri; import android.text.Html; @@ -65,6 +64,7 @@ import android.text.Html; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.text.Collator; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; @@ -304,12 +304,13 @@ public abstract class GCParser { if (!cids.isEmpty() && (Settings.isGCPremiumMember() || showCaptcha) && ((recaptchaReceiver == null || StringUtils.isBlank(recaptchaReceiver.getChallenge())) || StringUtils.isNotBlank(recaptchaText))) { Log.i("Trying to get .loc for " + cids.size() + " caches"); - final Observable<Set<Geocache>> storedCaches = Async.start(new Func0<Set<Geocache>>() { + final Observable<Set<Geocache>> storedCaches = Observable.defer(new Func0<Observable<Set<Geocache>>>() { @Override - public Set<Geocache> call() { - return DataStore.loadCaches(Geocache.getGeocodes(caches), LoadFlags.LOAD_CACHE_OR_DB); + public Observable<Set<Geocache>> call() { + return Observable.just(DataStore.loadCaches(Geocache.getGeocodes(caches), LoadFlags.LOAD_CACHE_OR_DB)); } - }, Schedulers.io()); + }).subscribeOn(Schedulers.io()).cache(); + storedCaches.subscribe(); // Force asynchronous start of database loading try { // get coordinates for parsed caches @@ -979,22 +980,22 @@ public abstract class GCParser { * Observable that fetches a list of pocket queries. Returns a single element (which may be an empty list). * Executes on the network scheduler. */ - public static final Observable<List<PocketQueryList>> searchPocketQueryListObservable = Async.fromCallable(new Func0<List<PocketQueryList>>() { + public static final Observable<List<PocketQueryList>> searchPocketQueryListObservable = Observable.defer(new Func0<Observable<List<PocketQueryList>>>() { @Override - public List<PocketQueryList> call() { + public Observable<List<PocketQueryList>> call() { final Parameters params = new Parameters(); final String page = GCLogin.getInstance().getRequestLogged("http://www.geocaching.com/pocket/default.aspx", params); if (StringUtils.isBlank(page)) { Log.e("GCParser.searchPocketQueryList: No data from server"); - return Collections.emptyList(); + return Observable.just(Collections.<PocketQueryList>emptyList()); } final String subPage = StringUtils.substringAfter(page, "class=\"PocketQueryListTable"); if (StringUtils.isEmpty(subPage)) { Log.e("GCParser.searchPocketQueryList: class \"PocketQueryListTable\" not found on page"); - return Collections.emptyList(); + return Observable.just(Collections.<PocketQueryList>emptyList()); } final List<PocketQueryList> list = new ArrayList<>(); @@ -1016,17 +1017,18 @@ public abstract class GCParser { } // just in case, lets sort the resulting list + final Collator collator = TextUtils.getCollator(); Collections.sort(list, new Comparator<PocketQueryList>() { @Override public int compare(final PocketQueryList left, final PocketQueryList right) { - return String.CASE_INSENSITIVE_ORDER.compare(left.getName(), right.getName()); + return collator.compare(left.getName(), right.getName()); } }); - return list; + return Observable.just(list); } - }, RxUtils.networkScheduler); + }).subscribeOn(RxUtils.networkScheduler); public static ImmutablePair<StatusCode, String> postLog(final String geocode, final String cacheid, final String[] viewstates, final LogType logType, final int year, final int month, final int day, diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java index 93b61f9..18d296d 100644 --- a/main/src/cgeo/geocaching/connector/gc/Tile.java +++ b/main/src/cgeo/geocaching/connector/gc/Tile.java @@ -15,7 +15,6 @@ import org.eclipse.jdt.annotation.NonNull; import rx.Observable; import rx.functions.Func0; -import rx.util.async.Async; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -241,12 +240,12 @@ public class Tile { static Observable<String> requestMapInfo(final String url, final Parameters params, final String referer) { final HttpResponse response = Network.getRequest(url, params, new Parameters("Referer", referer)); - return Async.start(new Func0<String>() { + return Observable.defer(new Func0<Observable<String>>() { @Override - public String call() { - return Network.getResponseData(response); + public Observable<String> call() { + return Observable.just(Network.getResponseData(response)); } - }, RxUtils.networkScheduler); + }).subscribeOn(RxUtils.networkScheduler); } /** Request .png image for a tile. Return as soon as the request has been made, before the answer has been @@ -256,17 +255,17 @@ public class Tile { */ static Observable<Bitmap> requestMapTile(final Parameters params) { final HttpResponse response = Network.getRequest(GCConstants.URL_MAP_TILE, params, new Parameters("Referer", GCConstants.URL_LIVE_MAP)); - return Async.start(new Func0<Bitmap>() { + return Observable.defer(new Func0<Observable<Bitmap>>() { @Override - public Bitmap call() { + public Observable<Bitmap> call() { try { - return response != null ? BitmapFactory.decodeStream(response.getEntity().getContent()) : null; + return Observable.just(response != null ? BitmapFactory.decodeStream(response.getEntity().getContent()) : null); } catch (final IOException e) { Log.e("Tile.requestMapTile() ", e); - return null; + return Observable.just(null); } } - }, RxUtils.computationScheduler); + }).subscribeOn(RxUtils.computationScheduler); } public boolean containsPoint(final @NonNull ICoordinates point) { diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java index 275a103..3b8e866 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java @@ -62,8 +62,16 @@ import java.util.Map; import java.util.TimeZone; import java.util.regex.Pattern; +/** + * Client for the OpenCaching API (Okapi). + * + * @see <a href="http://www.opencaching.de/okapi/introduction.html">Okapi overview</a> + * + */ final class OkapiClient { + private static final String PARAMETER_LOGCOUNT_VALUE = "all"; + private static final String PARAMETER_LOGCOUNT_KEY = "lpc"; private static final char SEPARATOR = '|'; private static final String SEPARATOR_STRING = Character.toString(SEPARATOR); private static final SynchronizedDateFormat LOG_DATE_FORMAT = new SynchronizedDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", TimeZone.getTimeZone("UTC"), Locale.US); @@ -149,6 +157,7 @@ final class OkapiClient { params.add("fields", getFullFields(ocapiConn)); params.add("attribution_append", "none"); + params.add(PARAMETER_LOGCOUNT_KEY, PARAMETER_LOGCOUNT_VALUE); final JSONResult result = request(ocapiConn, OkapiService.SERVICE_CACHE, params); diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java index b6792f0..c2c9876 100644 --- a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java @@ -26,6 +26,7 @@ public class GeokretyConnector extends AbstractTrackableConnector { } @Override + @Nullable public Trackable searchTrackable(final String geocode, final String guid, final String id) { final String page = Network.getResponseData(Network.getRequest("http://geokrety.org/export2.php?gkid=" + getId(geocode))); if (page == null) { diff --git a/main/src/cgeo/geocaching/connector/trackable/SwaggieConnector.java b/main/src/cgeo/geocaching/connector/trackable/SwaggieConnector.java new file mode 100644 index 0000000..dcd618c --- /dev/null +++ b/main/src/cgeo/geocaching/connector/trackable/SwaggieConnector.java @@ -0,0 +1,51 @@ +package cgeo.geocaching.connector.trackable; + +import cgeo.geocaching.Trackable; +import cgeo.geocaching.network.Network; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import java.util.regex.Pattern; + +public final class SwaggieConnector extends AbstractTrackableConnector { + + private static final Pattern PATTERN_SW_CODE = Pattern.compile("SW[0-9]{4}"); + + @Override + public boolean canHandleTrackable(final String geocode) { + return geocode != null && PATTERN_SW_CODE.matcher(geocode).matches(); + } + + @Override + @NonNull + public String getUrl(@NonNull final Trackable trackable) { + return getUrl(trackable.getGeocode()); + } + + @Override + @Nullable + public Trackable searchTrackable(final String geocode, final String guid, final String id) { + final String page = Network.getResponseData(Network.getRequest(getUrl(geocode))); + if (page == null) { + return null; + } + return SwaggieParser.parse(page); + } + + @Override + @Nullable + public String getTrackableCodeFromUrl(@NonNull final String url) { + final String geocode = StringUtils.upperCase(StringUtils.substringAfterLast(url, "swaggie/")); + if (canHandleTrackable(geocode)) { + return geocode; + } + return null; + } + + private static String getUrl(final String geocode) { + return "http://geocaching.com.au/swaggie/" + geocode; + } + +} diff --git a/main/src/cgeo/geocaching/connector/trackable/SwaggieParser.java b/main/src/cgeo/geocaching/connector/trackable/SwaggieParser.java new file mode 100644 index 0000000..1883056 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/trackable/SwaggieParser.java @@ -0,0 +1,55 @@ +package cgeo.geocaching.connector.trackable; + +import cgeo.geocaching.Trackable; +import cgeo.geocaching.utils.TextUtils; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import java.util.regex.Pattern; + +final class SwaggieParser { + + private SwaggieParser() { + // utility class + } + + private static final Pattern PATTERN_NAME = Pattern.compile(Pattern.quote("<h1><a") + ".*?>(.*?)<"); + private static final Pattern PATTERN_GEOCODE = Pattern.compile(Pattern.quote("'/swaggie/") + "(.*?)'"); + private static final Pattern PATTERN_DESCRIPTION = Pattern.compile(Pattern.quote("'swaggie_description'>") + "(.*?)</div"); + private static final Pattern PATTERN_OWNER = Pattern.compile(">([^<]*?)</a> released"); + + @Nullable + public static Trackable parse(@NonNull final String page) { + final Trackable trackable = new Trackable(); + final String name = TextUtils.getMatch(page, PATTERN_NAME, null); + if (StringUtils.isEmpty(name)) { + return null; + } + trackable.setName(name); + + final String geocode = TextUtils.getMatch(page, PATTERN_GEOCODE, null); + if (StringUtils.isEmpty(geocode)) { + return null; + } + trackable.setGeocode(geocode); + + final String description = StringUtils.trim(TextUtils.getMatch(page, PATTERN_DESCRIPTION, StringUtils.EMPTY)); + if (StringUtils.isEmpty(description)) { + return null; + } + trackable.setDetails(description); + + final String owner = StringUtils.trim(TextUtils.getMatch(page, PATTERN_OWNER, StringUtils.EMPTY)); + if (StringUtils.isEmpty(owner)) { + return null; + } + trackable.setOwner(owner); + + trackable.setType("Swaggie"); + + return trackable; + } + +} diff --git a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java index 01c1897..1281683 100644 --- a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java @@ -21,6 +21,7 @@ public interface TrackableConnector { public boolean isLoggable(); + @Nullable public Trackable searchTrackable(String geocode, String guid, String id); @Nullable diff --git a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java index 5d825a3..665ebea 100644 --- a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java @@ -36,6 +36,7 @@ public class TravelBugConnector extends AbstractTrackableConnector { } @Override + @Nullable public Trackable searchTrackable(final String geocode, final String guid, final String id) { return GCParser.searchTrackable(geocode, guid, id); } diff --git a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java index 7e7e1b6..5fc7bf1 100644 --- a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java @@ -3,6 +3,7 @@ package cgeo.geocaching.connector.trackable; import cgeo.geocaching.Trackable; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; public class UnknownTrackableConnector extends AbstractTrackableConnector { @@ -18,6 +19,7 @@ public class UnknownTrackableConnector extends AbstractTrackableConnector { } @Override + @Nullable public Trackable searchTrackable(final String geocode, final String guid, final String id) { return null; } diff --git a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java index 585b890..770b63b 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java +++ b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java @@ -130,19 +130,22 @@ public enum CacheAttribute { // THIS LIST IS GENERATED: don't change anything here but read // project/attributes/readme.txt + @NonNull private static final String INTERNAL_YES = "_yes"; + @NonNull private static final String INTERNAL_NO = "_no"; public static final int NO_ID = -1; public final int gcid; public final int ocacode; + @NonNull public final String rawName; public final int drawableId; public final int stringIdYes; public final int stringIdNo; - CacheAttribute(final int gcid, final int ocacode, final String rawName, + CacheAttribute(final int gcid, final int ocacode, @NonNull final String rawName, final int drawableId, final int stringIdYes, final int stringIdNo) { this.gcid = gcid; this.ocacode = ocacode; @@ -159,12 +162,15 @@ public enum CacheAttribute { * true: for positive text, false: for negative text * @return the localized text */ + @NonNull public String getL10n(final boolean enabled) { return CgeoApplication.getInstance().getResources().getString( enabled ? stringIdYes : stringIdNo); } + @NonNull private final static Map<String, CacheAttribute> FIND_BY_GCRAWNAME = new HashMap<>(); + @NonNull private final static SparseArray<CacheAttribute> FIND_BY_OCACODE = new SparseArray<>(); static { for (final CacheAttribute attr : values()) { @@ -176,7 +182,7 @@ public enum CacheAttribute { } @Nullable - public static CacheAttribute getByRawName(final String rawName) { + public static CacheAttribute getByRawName(@Nullable final String rawName) { return rawName != null ? FIND_BY_GCRAWNAME.get(rawName) : null; } @@ -186,14 +192,14 @@ public enum CacheAttribute { } @NonNull - public static String trimAttributeName(final String attributeName) { + public static String trimAttributeName(@Nullable final String attributeName) { if (null == attributeName) { return ""; } return attributeName.replace(INTERNAL_YES, "").replace(INTERNAL_NO, "").trim(); } - public static boolean isEnabled(final String attributeName) { + public static boolean isEnabled(@Nullable final String attributeName) { return !StringUtils.endsWithIgnoreCase(attributeName, INTERNAL_NO); } diff --git a/main/src/cgeo/geocaching/enumerations/CacheListType.java b/main/src/cgeo/geocaching/enumerations/CacheListType.java index 1fce282..297e1be 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheListType.java +++ b/main/src/cgeo/geocaching/enumerations/CacheListType.java @@ -2,6 +2,8 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.loaders.AbstractSearchLoader.CacheListLoaderType; +import org.eclipse.jdt.annotation.NonNull; + public enum CacheListType { OFFLINE(true, CacheListLoaderType.OFFLINE), POCKET(false, CacheListLoaderType.POCKET), @@ -19,9 +21,9 @@ public enum CacheListType { */ public final boolean canSwitch; - public final CacheListLoaderType loaderType; + @NonNull public final CacheListLoaderType loaderType; - CacheListType(final boolean canSwitch, final CacheListLoaderType loaderType) { + CacheListType(final boolean canSwitch, @NonNull final CacheListLoaderType loaderType) { this.canSwitch = canSwitch; this.loaderType = loaderType; } diff --git a/main/src/cgeo/geocaching/enumerations/CacheSize.java b/main/src/cgeo/geocaching/enumerations/CacheSize.java index 54e12e0..10c8c9f 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheSize.java +++ b/main/src/cgeo/geocaching/enumerations/CacheSize.java @@ -4,6 +4,7 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.util.HashMap; import java.util.Locale; @@ -24,6 +25,7 @@ public enum CacheSize { OTHER("Other", 8, R.string.cache_size_other, "other"), UNKNOWN("Unknown", -1, R.string.cache_size_unknown, ""); // CacheSize not init. yet + @NonNull public final String id; public final int comparable; private final int stringId; @@ -32,13 +34,14 @@ public enum CacheSize { */ private final String ocSize2; - CacheSize(final String id, final int comparable, final int stringId, final String ocSize2) { + CacheSize(@NonNull final String id, final int comparable, final int stringId, final String ocSize2) { this.id = id; this.comparable = comparable; this.stringId = stringId; this.ocSize2 = ocSize2; } + @NonNull final private static Map<String, CacheSize> FIND_BY_ID = new HashMap<>(); static { for (final CacheSize cs : values()) { @@ -50,7 +53,7 @@ public enum CacheSize { } @NonNull - public static CacheSize getById(final String id) { + public static CacheSize getById(@Nullable final String id) { if (id == null) { return UNKNOWN; } @@ -87,6 +90,7 @@ public enum CacheSize { return UNKNOWN; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java index e66c742..4e3b33a 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheType.java +++ b/main/src/cgeo/geocaching/enumerations/CacheType.java @@ -57,8 +57,11 @@ public enum CacheType { this.markerId = markerId; } + @NonNull private final static Map<String, CacheType> FIND_BY_ID = new HashMap<>(); + @NonNull private final static Map<String, CacheType> FIND_BY_PATTERN = new HashMap<>(); + @NonNull private final static Map<String, CacheType> FIND_BY_GUID = new HashMap<>(); static { @@ -102,6 +105,7 @@ public enum CacheType { return result; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } diff --git a/main/src/cgeo/geocaching/enumerations/LoadFlags.java b/main/src/cgeo/geocaching/enumerations/LoadFlags.java index 69d8df2..0f08690 100644 --- a/main/src/cgeo/geocaching/enumerations/LoadFlags.java +++ b/main/src/cgeo/geocaching/enumerations/LoadFlags.java @@ -1,5 +1,7 @@ package cgeo.geocaching.enumerations; +import org.eclipse.jdt.annotation.NonNull; + import java.util.EnumSet; /** @@ -33,6 +35,7 @@ public interface LoadFlags { DB // include saving to CacheCache } + @NonNull public final static EnumSet<SaveFlag> SAVE_ALL = EnumSet.allOf(SaveFlag.class); public enum RemoveFlag { @@ -41,6 +44,7 @@ public interface LoadFlags { OWN_WAYPOINTS_ONLY_FOR_TESTING // only to be used in unit testing (as we never delete own waypoints) } + @NonNull public final static EnumSet<RemoveFlag> REMOVE_ALL = EnumSet.of(RemoveFlag.CACHE, RemoveFlag.DB); }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/enumerations/LogType.java b/main/src/cgeo/geocaching/enumerations/LogType.java index a27ec1a..bf0d66c 100644 --- a/main/src/cgeo/geocaching/enumerations/LogType.java +++ b/main/src/cgeo/geocaching/enumerations/LogType.java @@ -4,6 +4,7 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.util.HashMap; import java.util.Locale; @@ -47,13 +48,16 @@ public enum LogType { UNKNOWN(0, "unknown", "", "", R.string.err_unknown, R.drawable.mark_red); // LogType not init. yet public final int id; + @Nullable public final String iconName; + @NonNull public final String type; + @NonNull public final String oc_type; private final int stringId; public final int markerId; - LogType(final int id, final String iconName, final String type, final String oc_type, final int stringId, final int markerId) { + LogType(final int id, @Nullable final String iconName, @NonNull final String type, @NonNull final String oc_type, final int stringId, final int markerId) { this.id = id; this.iconName = iconName; this.type = type; @@ -110,6 +114,7 @@ public enum LogType { return result; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } diff --git a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java index fefeb62..05ce6fd 100644 --- a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java +++ b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java @@ -18,6 +18,7 @@ public enum LogTypeTrackable { this.resourceId = resourceId; } + @NonNull public String getLabel() { return CgeoApplication.getInstance().getString(resourceId); } diff --git a/main/src/cgeo/geocaching/enumerations/StatusCode.java b/main/src/cgeo/geocaching/enumerations/StatusCode.java index 9030e2b..37d027f 100644 --- a/main/src/cgeo/geocaching/enumerations/StatusCode.java +++ b/main/src/cgeo/geocaching/enumerations/StatusCode.java @@ -2,6 +2,8 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.R; +import org.eclipse.jdt.annotation.NonNull; + import android.content.res.Resources; public enum StatusCode { @@ -35,6 +37,7 @@ public enum StatusCode { return error_string; } + @NonNull public String getErrorString(final Resources res) { return res.getString(error_string); } diff --git a/main/src/cgeo/geocaching/enumerations/WaypointType.java b/main/src/cgeo/geocaching/enumerations/WaypointType.java index 732a665..d2281ef 100644 --- a/main/src/cgeo/geocaching/enumerations/WaypointType.java +++ b/main/src/cgeo/geocaching/enumerations/WaypointType.java @@ -49,6 +49,7 @@ public enum WaypointType { } } } + @NonNull public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL = Collections.unmodifiableSet(ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL_TMP); /** @@ -67,6 +68,7 @@ public enum WaypointType { return waypointType; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } diff --git a/main/src/cgeo/geocaching/export/GpxSerializer.java b/main/src/cgeo/geocaching/export/GpxSerializer.java index fe53f37..6755798 100644 --- a/main/src/cgeo/geocaching/export/GpxSerializer.java +++ b/main/src/cgeo/geocaching/export/GpxSerializer.java @@ -55,7 +55,7 @@ public final class GpxSerializer { } - public void writeGPX(List<String> allGeocodesIn, Writer writer, final ProgressListener progressListener) throws IOException { + public void writeGPX(final List<String> allGeocodesIn, final Writer writer, final ProgressListener progressListener) throws IOException { // create a copy of the geocode list, as we need to modify it, but it might be immutable final ArrayList<String> allGeocodes = new ArrayList<>(allGeocodesIn); @@ -88,7 +88,7 @@ public final class GpxSerializer { gpx.endDocument(); } - private void exportBatch(final XmlSerializer gpx, Collection<String> geocodesOfBatch) throws IOException { + private void exportBatch(final XmlSerializer gpx, final Collection<String> geocodesOfBatch) throws IOException { final Set<Geocache> caches = DataStore.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY); for (final Geocache cache : caches) { if (cache == null) { @@ -178,7 +178,7 @@ public final class GpxSerializer { * @return XML schema compliant boolean representation of the boolean flag. This must be either true, false, 0 or 1, * but no other value (also not upper case True/False). */ - private static String gpxBoolean(boolean boolFlag) { + private static String gpxBoolean(final boolean boolFlag) { return boolFlag ? "true" : "false"; } @@ -255,7 +255,7 @@ public final class GpxSerializer { } private void writeLogs(final Geocache cache) throws IOException { - List<LogEntry> logs = cache.getLogs(); + final List<LogEntry> logs = cache.getLogs(); if (logs.isEmpty()) { return; } @@ -291,7 +291,7 @@ public final class GpxSerializer { } private void writeTravelBugs(final Geocache cache) throws IOException { - List<Trackable> inventory = cache.getInventory(); + final List<Trackable> inventory = cache.getInventory(); if (CollectionUtils.isEmpty(inventory)) { return; } @@ -338,7 +338,7 @@ public final class GpxSerializer { return getLocationPart(cache, 0); } - private static String getLocationPart(final Geocache cache, int partIndex) { + private static String getLocationPart(final Geocache cache, final int partIndex) { final String location = cache.getLocation(); if (StringUtils.contains(location, ", ")) { final String[] parts = StringUtils.split(location, ','); @@ -350,7 +350,7 @@ public final class GpxSerializer { } public static String getCountry(final Geocache cache) { - String country = getLocationPart(cache, 1); + final String country = getLocationPart(cache, 1); if (StringUtils.isNotEmpty(country)) { return country; } diff --git a/main/src/cgeo/geocaching/filter/AbstractFilter.java b/main/src/cgeo/geocaching/filter/AbstractFilter.java index 248c9c2..20575a6 100644 --- a/main/src/cgeo/geocaching/filter/AbstractFilter.java +++ b/main/src/cgeo/geocaching/filter/AbstractFilter.java @@ -1,5 +1,6 @@ package cgeo.geocaching.filter; +import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import org.eclipse.jdt.annotation.NonNull; @@ -8,12 +9,18 @@ import java.util.ArrayList; import java.util.List; abstract class AbstractFilter implements IFilter { + @NonNull private final String name; - protected AbstractFilter(final String name) { + protected AbstractFilter(final int nameResourceId) { + this(CgeoApplication.getInstance().getString(nameResourceId)); + } + + protected AbstractFilter(@NonNull final String name) { this.name = name; } + @Override public void filter(@NonNull final List<Geocache> list) { final List<Geocache> itemsToRemove = new ArrayList<>(); @@ -26,6 +33,7 @@ abstract class AbstractFilter implements IFilter { } @Override + @NonNull public String getName() { return name; } diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java index 2fc6eb2..6ed4a8f 100644 --- a/main/src/cgeo/geocaching/filter/AttributeFilter.java +++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java @@ -15,7 +15,7 @@ class AttributeFilter extends AbstractFilter { private final String attribute; - public AttributeFilter(final String name, final String attribute) { + public AttributeFilter(@NonNull final String name, final String attribute) { super(name); this.attribute = attribute; } diff --git a/main/src/cgeo/geocaching/filter/DistanceFilter.java b/main/src/cgeo/geocaching/filter/DistanceFilter.java index f1ba7f8..b352f5d 100644 --- a/main/src/cgeo/geocaching/filter/DistanceFilter.java +++ b/main/src/cgeo/geocaching/filter/DistanceFilter.java @@ -17,7 +17,7 @@ class DistanceFilter extends AbstractFilter { private final int minDistance; private final int maxDistance; - public DistanceFilter(final String name, final int minDistance, final int maxDistance) { + public DistanceFilter(@NonNull final String name, final int minDistance, final int maxDistance) { super(name); this.minDistance = minDistance; this.maxDistance = maxDistance; diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java index 2d7dafc..97e70ba 100644 --- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java +++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java @@ -7,6 +7,9 @@ import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.TextUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import rx.functions.Action1; import android.app.Activity; @@ -24,10 +27,10 @@ import java.util.List; public final class FilterUserInterface { private static class FactoryEntry { - private final String name; - private final Class<? extends IFilterFactory> filterFactory; + @NonNull private final String name; + @Nullable private final Class<? extends IFilterFactory> filterFactory; - public FactoryEntry(final String name, final Class<? extends IFilterFactory> filterFactory) { + public FactoryEntry(@NonNull final String name, @Nullable final Class<? extends IFilterFactory> filterFactory) { this.name = name; this.filterFactory = filterFactory; } @@ -77,7 +80,7 @@ public final class FilterUserInterface { register(R.string.caches_filter_clear, null); } - private void register(final int resourceId, final Class<? extends IFilterFactory> factoryClass) { + private void register(final int resourceId, @Nullable final Class<? extends IFilterFactory> factoryClass) { registry.add(new FactoryEntry(res.getString(resourceId), factoryClass)); } @@ -92,12 +95,13 @@ public final class FilterUserInterface { public void onClick(final DialogInterface dialog, final int itemIndex) { final FactoryEntry entry = adapter.getItem(itemIndex); // reset? - if (entry.filterFactory == null) { + final Class<? extends IFilterFactory> filterFactory = entry.filterFactory; + if (filterFactory == null) { runAfterwards.call(null); } else { try { - final IFilterFactory factoryInstance = entry.filterFactory.newInstance(); + final IFilterFactory factoryInstance = filterFactory.newInstance(); selectFromFactory(factoryInstance, entry.name, runAfterwards); } catch (final Exception e) { Log.e("selectFilter", e); @@ -109,7 +113,7 @@ public final class FilterUserInterface { builder.create().show(); } - private void selectFromFactory(final IFilterFactory factory, final String menuTitle, final Action1<IFilter> runAfterwards) { + private void selectFromFactory(@NonNull final IFilterFactory factory, final String menuTitle, final Action1<IFilter> runAfterwards) { final List<IFilter> filters = Collections.unmodifiableList(factory.getFilters()); if (filters.size() == 1) { runAfterwards.call(filters.get(0)); diff --git a/main/src/cgeo/geocaching/filter/IFilter.java b/main/src/cgeo/geocaching/filter/IFilter.java index de39e5a..eea1303 100644 --- a/main/src/cgeo/geocaching/filter/IFilter.java +++ b/main/src/cgeo/geocaching/filter/IFilter.java @@ -8,6 +8,7 @@ import java.util.List; public interface IFilter { + @NonNull String getName(); /** diff --git a/main/src/cgeo/geocaching/filter/ModifiedFilter.java b/main/src/cgeo/geocaching/filter/ModifiedFilter.java index c224cb4..9b5c856 100644 --- a/main/src/cgeo/geocaching/filter/ModifiedFilter.java +++ b/main/src/cgeo/geocaching/filter/ModifiedFilter.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; @@ -12,7 +11,7 @@ import java.util.List; class ModifiedFilter extends AbstractFilter implements IFilterFactory { public ModifiedFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_modified)); + super(R.string.caches_filter_modified); } @Override diff --git a/main/src/cgeo/geocaching/filter/OfflineLogFilter.java b/main/src/cgeo/geocaching/filter/OfflineLogFilter.java new file mode 100644 index 0000000..0ed9618 --- /dev/null +++ b/main/src/cgeo/geocaching/filter/OfflineLogFilter.java @@ -0,0 +1,19 @@ +package cgeo.geocaching.filter; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; + +import org.eclipse.jdt.annotation.NonNull; + +public class OfflineLogFilter extends AbstractFilter { + + protected OfflineLogFilter() { + super(R.string.caches_filter_offline_log); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.isLogOffline(); + } + +} diff --git a/main/src/cgeo/geocaching/filter/OriginFilter.java b/main/src/cgeo/geocaching/filter/OriginFilter.java index 4fb3301..d51b02c 100644 --- a/main/src/cgeo/geocaching/filter/OriginFilter.java +++ b/main/src/cgeo/geocaching/filter/OriginFilter.java @@ -15,7 +15,7 @@ public class OriginFilter extends AbstractFilter { private final IConnector connector; - public OriginFilter(final IConnector connector) { + public OriginFilter(@NonNull final IConnector connector) { super(connector.getName()); this.connector = connector; } diff --git a/main/src/cgeo/geocaching/filter/OwnRatingFilter.java b/main/src/cgeo/geocaching/filter/OwnRatingFilter.java index 0c468a9..1b86bab 100644 --- a/main/src/cgeo/geocaching/filter/OwnRatingFilter.java +++ b/main/src/cgeo/geocaching/filter/OwnRatingFilter.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.gcvote.GCVote; @@ -18,7 +17,7 @@ import java.util.List; public class OwnRatingFilter extends AbstractFilter implements IFilterFactory { protected OwnRatingFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_own_rating)); + super(R.string.caches_filter_own_rating); } @Override diff --git a/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java b/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java index 6c6186b..e9780da 100644 --- a/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java +++ b/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java @@ -10,7 +10,7 @@ public class PersonalDataFilterFactory implements IFilterFactory { @Override @NonNull public List<? extends IFilter> getFilters() { - return Arrays.asList(new OwnRatingFilter(), new PersonalNoteFilter(), new ModifiedFilter()); + return Arrays.asList(new OwnRatingFilter(), new PersonalNoteFilter(), new ModifiedFilter(), new OfflineLogFilter()); } } diff --git a/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java b/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java index 978ad6b..11c623e 100644 --- a/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java +++ b/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; @@ -16,7 +15,7 @@ import java.util.List; public class PersonalNoteFilter extends AbstractFilter implements IFilterFactory { protected PersonalNoteFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_personal_note)); + super(R.string.caches_filter_personal_note); } @Override diff --git a/main/src/cgeo/geocaching/filter/PopularityFilter.java b/main/src/cgeo/geocaching/filter/PopularityFilter.java index bb564e8..eabc533 100644 --- a/main/src/cgeo/geocaching/filter/PopularityFilter.java +++ b/main/src/cgeo/geocaching/filter/PopularityFilter.java @@ -13,7 +13,7 @@ class PopularityFilter extends AbstractFilter { private final int minFavorites; private final int maxFavorites; - public PopularityFilter(final String name, final int minFavorites, final int maxFavorites) { + public PopularityFilter(@NonNull final String name, final int minFavorites, final int maxFavorites) { super(name); this.minFavorites = minFavorites; this.maxFavorites = maxFavorites; diff --git a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java index 53904f1..0548345 100644 --- a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java +++ b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java @@ -18,7 +18,7 @@ class PopularityRatioFilter extends AbstractFilter { private final int minRatio; private final int maxRatio; - public PopularityRatioFilter(final String name, final int minRatio, final int maxRatio) { + public PopularityRatioFilter(@NonNull final String name, final int minRatio, final int maxRatio) { super(name); this.minRatio = minRatio; this.maxRatio = maxRatio; diff --git a/main/src/cgeo/geocaching/filter/RatingFilter.java b/main/src/cgeo/geocaching/filter/RatingFilter.java index 3edfcb6..63e9c0b 100644 --- a/main/src/cgeo/geocaching/filter/RatingFilter.java +++ b/main/src/cgeo/geocaching/filter/RatingFilter.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.gcvote.GCVote; @@ -18,7 +17,7 @@ import java.util.List; public class RatingFilter extends AbstractFilter implements IFilterFactory { protected RatingFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_rating)); + super(R.string.caches_filter_rating); } @Override diff --git a/main/src/cgeo/geocaching/filter/SizeFilter.java b/main/src/cgeo/geocaching/filter/SizeFilter.java index 4c7c122..a48da2c 100644 --- a/main/src/cgeo/geocaching/filter/SizeFilter.java +++ b/main/src/cgeo/geocaching/filter/SizeFilter.java @@ -11,7 +11,7 @@ import java.util.List; class SizeFilter extends AbstractFilter { private final CacheSize cacheSize; - public SizeFilter(final CacheSize cacheSize) { + public SizeFilter(@NonNull final CacheSize cacheSize) { super(cacheSize.id); this.cacheSize = cacheSize; } @@ -22,6 +22,7 @@ class SizeFilter extends AbstractFilter { } @Override + @NonNull public String getName() { return cacheSize.getL10n(); } diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java index f574045..289f656 100644 --- a/main/src/cgeo/geocaching/filter/StateFilter.java +++ b/main/src/cgeo/geocaching/filter/StateFilter.java @@ -1,13 +1,10 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import org.eclipse.jdt.annotation.NonNull; -import android.content.res.Resources; - import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -15,16 +12,14 @@ import java.util.List; abstract class StateFilter extends AbstractFilter { - static final Resources res = CgeoApplication.getInstance().getResources(); - - protected StateFilter(final String name) { - super(name); + protected StateFilter(final int nameResourceId) { + super(nameResourceId); } static class StateFoundFilter extends StateFilter { public StateFoundFilter() { - super(res.getString(R.string.cache_status_found)); + super(R.string.cache_status_found); } @Override @@ -37,7 +32,7 @@ abstract class StateFilter extends AbstractFilter { static class StateNotFoundFilter extends StateFilter { public StateNotFoundFilter() { - super(res.getString(R.string.cache_not_status_found)); + super(R.string.cache_not_status_found); } @Override @@ -49,7 +44,7 @@ abstract class StateFilter extends AbstractFilter { static class StateArchivedFilter extends StateFilter { public StateArchivedFilter() { - super(res.getString(R.string.cache_status_archived)); + super(R.string.cache_status_archived); } @Override @@ -60,7 +55,7 @@ abstract class StateFilter extends AbstractFilter { static class StateDisabledFilter extends StateFilter { public StateDisabledFilter() { - super(res.getString(R.string.cache_status_disabled)); + super(R.string.cache_status_disabled); } @Override @@ -71,7 +66,7 @@ abstract class StateFilter extends AbstractFilter { static class StatePremiumFilter extends StateFilter { public StatePremiumFilter() { - super(res.getString(R.string.cache_status_premium)); + super(R.string.cache_status_premium); } @Override @@ -82,7 +77,7 @@ abstract class StateFilter extends AbstractFilter { static class StateNonPremiumFilter extends StateFilter { public StateNonPremiumFilter() { - super(res.getString(R.string.cache_status_not_premium)); + super(R.string.cache_status_not_premium); } @Override @@ -93,7 +88,7 @@ abstract class StateFilter extends AbstractFilter { private static class StateOfflineLogFilter extends StateFilter { public StateOfflineLogFilter() { - super(res.getString(R.string.cache_status_offline_log)); + super(R.string.cache_status_offline_log); } @Override @@ -104,7 +99,7 @@ abstract class StateFilter extends AbstractFilter { static class StateStoredFilter extends StateFilter { public StateStoredFilter() { - super(res.getString(R.string.cache_status_stored)); + super(R.string.cache_status_stored); } @Override @@ -115,7 +110,7 @@ abstract class StateFilter extends AbstractFilter { static class StateNotStoredFilter extends StateFilter { public StateNotStoredFilter() { - super(res.getString(R.string.cache_status_not_stored)); + super(R.string.cache_status_not_stored); } @Override diff --git a/main/src/cgeo/geocaching/filter/TrackablesFilter.java b/main/src/cgeo/geocaching/filter/TrackablesFilter.java index 7ad06a1..bdf91f7 100644 --- a/main/src/cgeo/geocaching/filter/TrackablesFilter.java +++ b/main/src/cgeo/geocaching/filter/TrackablesFilter.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; @@ -11,7 +10,7 @@ import java.util.List; class TrackablesFilter extends AbstractFilter implements IFilterFactory { public TrackablesFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_track)); + super(R.string.caches_filter_track); } @Override diff --git a/main/src/cgeo/geocaching/filter/TypeFilter.java b/main/src/cgeo/geocaching/filter/TypeFilter.java index 412cbc2..70a8068 100644 --- a/main/src/cgeo/geocaching/filter/TypeFilter.java +++ b/main/src/cgeo/geocaching/filter/TypeFilter.java @@ -11,7 +11,7 @@ import java.util.List; class TypeFilter extends AbstractFilter { private final CacheType cacheType; - public TypeFilter(final CacheType cacheType) { + public TypeFilter(@NonNull final CacheType cacheType) { super(cacheType.id); this.cacheType = cacheType; } @@ -22,6 +22,7 @@ class TypeFilter extends AbstractFilter { } @Override + @NonNull public String getName() { return cacheType.getL10n(); } diff --git a/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java b/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java index e5717ab..0738274 100644 --- a/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java +++ b/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java @@ -87,9 +87,8 @@ public class GCVoteDialog { cache.setMyVote(rating); DataStore.saveChangedCache(cache); return true; - } else { - Log.w("GCVoteDialog.vote: could not send vote"); } + Log.w("GCVoteDialog.vote: could not send vote"); } } catch (final RuntimeException e) { Log.e("GCVoteDialog.vote: could not send vote", e); diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index 457b06c..933fdbd 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -994,7 +994,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { final boolean needsRepaintForHeading = needsRepaintForHeading(); if (needsRepaintForDistanceOrAccuracy) { - if (map.followMyLocation) { + if (CGeoMap.followMyLocation) { map.centerMap(new Geopoint(currentLocation)); } } diff --git a/main/src/cgeo/geocaching/playservices/LocationProvider.java b/main/src/cgeo/geocaching/playservices/LocationProvider.java index 9d193b5..027ae29 100644 --- a/main/src/cgeo/geocaching/playservices/LocationProvider.java +++ b/main/src/cgeo/geocaching/playservices/LocationProvider.java @@ -102,12 +102,12 @@ public class LocationProvider implements GoogleApiClient.ConnectionCallbacks, Go // no less precise than 20 meters. final Observable<GeoData> untilPreciseEnoughObservable = lowPowerObservable.mergeWith(highPowerObservable.delaySubscription(6, TimeUnit.SECONDS)) - .lift(RxUtils.operatorTakeUntil(new Func1<GeoData, Boolean>() { + .takeUntil(new Func1<GeoData, Boolean>() { @Override public Boolean call(final GeoData geoData) { return geoData.getAccuracy() <= 20; } - })); + }); // After sending the last known location, try to get a precise location then use the low-power mode. If no // location information is given for 25 seconds (if the network location is turned off for example), get diff --git a/main/src/cgeo/geocaching/sensors/RotationProvider.java b/main/src/cgeo/geocaching/sensors/RotationProvider.java index 02dbc8c..c63e39f 100644 --- a/main/src/cgeo/geocaching/sensors/RotationProvider.java +++ b/main/src/cgeo/geocaching/sensors/RotationProvider.java @@ -43,6 +43,7 @@ public class RotationProvider extends LooperCallbacks<Float> implements SensorEv return ((SensorManager) context.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) != null; } + @TargetApi(19) public static boolean hasGeomagneticRotationSensor(final Context context) { return ((SensorManager) context.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR) != null; } diff --git a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java index ed09757..6130c4c 100644 --- a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java +++ b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java @@ -14,7 +14,6 @@ import rx.Observable; import rx.android.app.AppObservable; import rx.functions.Action1; import rx.functions.Func0; -import rx.util.async.Async; import android.app.ProgressDialog; import android.content.Context; @@ -74,10 +73,10 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab loginDialog.setCancelable(false); Cookies.clearCookies(); - AppObservable.bindActivity(settingsActivity, Async.start(new Func0<ImmutablePair<StatusCode, Observable<Drawable>>>() { + AppObservable.bindActivity(settingsActivity, Observable.defer(new Func0<Observable<ImmutablePair<StatusCode, Observable<Drawable>>>>() { @Override - public ImmutablePair<StatusCode, Observable<Drawable>> call() { - return login(); + public Observable<ImmutablePair<StatusCode, Observable<Drawable>>> call() { + return Observable.just(login()); } })).subscribeOn(RxUtils.networkScheduler).subscribe(new Action1<ImmutablePair<StatusCode, Observable<Drawable>>>() { @Override diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java index 99de30f..776b621 100644 --- a/main/src/cgeo/geocaching/settings/SettingsActivity.java +++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java @@ -327,13 +327,14 @@ public class SettingsActivity extends PreferenceActivity { backup.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(final Preference preference) { - return DatabaseBackupUtils.createBackup(SettingsActivity.this, new Runnable() { + DatabaseBackupUtils.createBackup(SettingsActivity.this, new Runnable() { @Override public void run() { VALUE_CHANGE_LISTENER.onPreferenceChange(SettingsActivity.this.getPreference(R.string.pref_fakekey_preference_backup_info), ""); } }); + return true; } }); diff --git a/main/src/cgeo/geocaching/sorting/DateComparator.java b/main/src/cgeo/geocaching/sorting/DateComparator.java index af50213..347eb44 100644 --- a/main/src/cgeo/geocaching/sorting/DateComparator.java +++ b/main/src/cgeo/geocaching/sorting/DateComparator.java @@ -17,13 +17,8 @@ class DateComparator extends AbstractCacheComparator { final Date date2 = cache2.getHiddenDate(); if (date1 != null && date2 != null) { final int dateDifference = date1.compareTo(date2); - // for equal dates, sort by distance if (dateDifference == 0) { - final ArrayList<Geocache> list = new ArrayList<>(); - list.add(cache1); - list.add(cache2); - final DistanceComparator distanceComparator = new DistanceComparator(Sensors.getInstance().currentGeo().getCoords(), list); - return distanceComparator.compare(cache1, cache2); + return sortSameDate(cache1, cache2); } return dateDifference; } @@ -35,4 +30,13 @@ class DateComparator extends AbstractCacheComparator { } return 0; } + + @SuppressWarnings("static-method") + protected int sortSameDate(final Geocache cache1, final Geocache cache2) { + final ArrayList<Geocache> list = new ArrayList<>(); + list.add(cache1); + list.add(cache2); + final DistanceComparator distanceComparator = new DistanceComparator(Sensors.getInstance().currentGeo().getCoords(), list); + return distanceComparator.compare(cache1, cache2); + } } diff --git a/main/src/cgeo/geocaching/sorting/EventDateComparator.java b/main/src/cgeo/geocaching/sorting/EventDateComparator.java index 197946a..425ddbb 100644 --- a/main/src/cgeo/geocaching/sorting/EventDateComparator.java +++ b/main/src/cgeo/geocaching/sorting/EventDateComparator.java @@ -1,5 +1,7 @@ package cgeo.geocaching.sorting; +import cgeo.geocaching.Geocache; + /** * Compares caches by date. Used only for event caches. */ @@ -7,4 +9,19 @@ public class EventDateComparator extends DateComparator { final static public EventDateComparator singleton = new EventDateComparator(); + @Override + protected int sortSameDate(final Geocache left, final Geocache right) { + return compare(left.guessEventTimeMinutes(), right.guessEventTimeMinutes()); + } + + /** + * copy of {@link Integer#compare(int, int)}, as that is not available on lower API levels + * + * @param left + * @param right + * @return + */ + private static int compare(final int left, final int right) { + return left < right ? -1 : (left == right ? 0 : 1); + } } diff --git a/main/src/cgeo/geocaching/sorting/NameComparator.java b/main/src/cgeo/geocaching/sorting/NameComparator.java index 376c8b9..ab7bbcb 100644 --- a/main/src/cgeo/geocaching/sorting/NameComparator.java +++ b/main/src/cgeo/geocaching/sorting/NameComparator.java @@ -1,15 +1,20 @@ package cgeo.geocaching.sorting; import cgeo.geocaching.Geocache; +import cgeo.geocaching.utils.TextUtils; import org.apache.commons.lang3.StringUtils; +import java.text.Collator; + /** * sorts caches by name * */ class NameComparator extends AbstractCacheComparator { + private final Collator collator = TextUtils.getCollator(); + @Override protected boolean canCompare(final Geocache cache) { return StringUtils.isNotBlank(cache.getName()); @@ -17,6 +22,6 @@ class NameComparator extends AbstractCacheComparator { @Override protected int compareCaches(final Geocache cache1, final Geocache cache2) { - return cache1.getNameForSorting().compareToIgnoreCase(cache2.getNameForSorting()); + return collator.compare(cache1.getNameForSorting(), cache2.getNameForSorting()); } } diff --git a/main/src/cgeo/geocaching/ui/AbstractMenuActionProvider.java b/main/src/cgeo/geocaching/ui/AbstractMenuActionProvider.java new file mode 100644 index 0000000..fbea675 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/AbstractMenuActionProvider.java @@ -0,0 +1,24 @@ +package cgeo.geocaching.ui; + +import android.content.Context; +import android.support.v4.view.ActionProvider; +import android.view.View; + +public abstract class AbstractMenuActionProvider extends ActionProvider { + + public AbstractMenuActionProvider(final Context context) { + super(context); + } + + @Override + public boolean hasSubMenu() { + return true; + } + + @Override + public View onCreateActionView() { + // must return null, otherwise the menu will not work + return null; + } + +} diff --git a/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java index 7e49c97..c29e1e8 100644 --- a/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java +++ b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java @@ -25,7 +25,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { private final boolean allLogs; private final Resources res = CgeoApplication.getInstance().getResources(); - public CacheLogsViewCreator(CacheDetailActivity cacheDetailActivity, boolean allLogs) { + public CacheLogsViewCreator(final CacheDetailActivity cacheDetailActivity, final boolean allLogs) { super(cacheDetailActivity); this.allLogs = allLogs; } @@ -37,7 +37,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { */ private Geocache getCache() { if (this.activity instanceof CacheDetailActivity) { - CacheDetailActivity details = (CacheDetailActivity) this.activity; + final CacheDetailActivity details = (CacheDetailActivity) this.activity; return details.getCache(); } return null; @@ -56,7 +56,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { final List<Entry<LogType, Integer>> sortedLogCounts = new ArrayList<>(logCounts.size()); for (final Entry<LogType, Integer> entry : logCounts.entrySet()) { // it may happen that the label is unknown -> then avoid any output for this type - if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getKey().getL10n() != null && entry.getValue() != 0) { + if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getValue() != 0) { sortedLogCounts.add(entry); } } @@ -66,7 +66,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() { @Override - public int compare(Entry<LogType, Integer> logCountItem1, Entry<LogType, Integer> logCountItem2) { + public int compare(final Entry<LogType, Integer> logCountItem1, final Entry<LogType, Integer> logCountItem2) { return logCountItem1.getKey().compareTo(logCountItem2.getKey()); } }); @@ -84,7 +84,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { } @Override - protected void fillCountOrLocation(LogViewHolder holder, final LogEntry log) { + protected void fillCountOrLocation(final LogViewHolder holder, final LogEntry log) { // finds count if (log.found == -1) { holder.countOrLocation.setVisibility(View.GONE); diff --git a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java index ab27264..1449f8c 100644 --- a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java +++ b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java @@ -6,6 +6,8 @@ import cgeo.geocaching.R; import cgeo.geocaching.ui.dialog.Dialogs; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import rx.functions.Action0; import rx.functions.Action1; @@ -14,6 +16,8 @@ import rx.schedulers.Schedulers; import android.app.Activity; import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; import android.content.res.Resources; import java.io.File; @@ -26,7 +30,8 @@ public class DatabaseBackupUtils { } /** - * restore the database in a new thread, showing a progress window + * After confirming to overwrite the existing caches on the devices, restore the database in a new thread, showing a + * progress window * * @param activity * calling activity @@ -35,6 +40,23 @@ public class DatabaseBackupUtils { if (!hasBackup()) { return; } + final int caches = DataStore.getAllCachesCount(); + if (caches == 0) { + restoreDatabaseInternal(activity); + } + else { + Dialogs.confirm(activity, R.string.init_backup_restore, activity.getString(R.string.restore_confirm_overwrite, activity.getResources().getQuantityString(R.plurals.cache_counts, caches, caches)), new OnClickListener() { + + @Override + public void onClick(final DialogInterface dialog, final int which) { + restoreDatabaseInternal(activity); + } + }); + + } + } + + private static void restoreDatabaseInternal(final Activity activity) { final Resources res = activity.getResources(); final ProgressDialog dialog = ProgressDialog.show(activity, res.getString(R.string.init_backup_restore), res.getString(R.string.init_restore_running), true, false); final AtomicBoolean restoreSuccessful = new AtomicBoolean(false); @@ -57,14 +79,34 @@ public class DatabaseBackupUtils { }); } - public static boolean createBackup(final Activity activity, final Runnable runAfterwards) { + /** + * Create a backup after confirming to overwrite the existing backup. + * + * @param activity + * @param runAfterwards + */ + public static void createBackup(final Activity activity, final Runnable runAfterwards) { // avoid overwriting an existing backup with an empty database // (can happen directly after reinstalling the app) if (DataStore.getAllCachesCount() == 0) { Dialogs.message(activity, R.string.init_backup, R.string.init_backup_unnecessary); - return false; + return; + } + if (hasBackup()) { + Dialogs.confirm(activity, R.string.init_backup, activity.getString(R.string.backup_confirm_overwrite, getBackupDateTime()), new OnClickListener() { + + @Override + public void onClick(final DialogInterface dialog, final int which) { + createBackupInternal(activity, runAfterwards); + } + }); } + else { + createBackupInternal(activity, runAfterwards); + } + } + private static void createBackupInternal(final Activity activity, final Runnable runAfterwards) { final ProgressDialog dialog = ProgressDialog.show(activity, activity.getString(R.string.init_backup), activity.getString(R.string.init_backup_running), true, false); @@ -88,9 +130,9 @@ public class DatabaseBackupUtils { } } }); - return true; } + @Nullable public static File getRestoreFile() { final File fileSourceFile = DataStore.getBackupFileInternal(); return fileSourceFile.exists() && fileSourceFile.length() > 0 ? fileSourceFile : null; @@ -100,6 +142,7 @@ public class DatabaseBackupUtils { return getRestoreFile() != null; } + @NonNull public static String getBackupDateTime() { final File restoreFile = getRestoreFile(); if (restoreFile == null) { diff --git a/main/src/cgeo/geocaching/utils/Formatter.java b/main/src/cgeo/geocaching/utils/Formatter.java index c764c5a..081779f 100644 --- a/main/src/cgeo/geocaching/utils/Formatter.java +++ b/main/src/cgeo/geocaching/utils/Formatter.java @@ -76,6 +76,10 @@ public abstract class Formatter { return dateFormat.format(date); } + private static String formatShortDateIncludingWeekday(final long time) { + return DateUtils.formatDateTime(CgeoApplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_WEEKDAY) + ", " + formatShortDate(time); + } + /** * Generate a numeric date string according to system-wide settings (locale, date format) * such as "10/20/2010". Today and yesterday will be presented as strings "today" and "yesterday". @@ -157,7 +161,7 @@ public abstract class Formatter { } else if (cache.isEventCache()) { final Date hiddenDate = cache.getHiddenDate(); if (hiddenDate != null) { - infos.add(Formatter.formatShortDate(hiddenDate.getTime())); + infos.add(Formatter.formatShortDateIncludingWeekday(hiddenDate.getTime())); } } } diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java index ff4013c..1db3d5b 100644 --- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java +++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java @@ -215,7 +215,7 @@ public final class LogTemplateProvider { } final Geocache cache = context.getCache(); if (cache != null) { - return cache.getUrl(); + return StringUtils.defaultString(cache.getUrl()); } return StringUtils.EMPTY; } diff --git a/main/src/cgeo/geocaching/utils/ProcessUtils.java b/main/src/cgeo/geocaching/utils/ProcessUtils.java index ce05483..45e80d1 100644 --- a/main/src/cgeo/geocaching/utils/ProcessUtils.java +++ b/main/src/cgeo/geocaching/utils/ProcessUtils.java @@ -3,7 +3,10 @@ package cgeo.geocaching.utils; import cgeo.geocaching.CgeoApplication; import org.apache.commons.collections4.CollectionUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import android.app.Activity; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -24,7 +27,7 @@ public final class ProcessUtils { * @param packageName * @return */ - public static boolean isLaunchable(final String packageName) { + public static boolean isLaunchable(@Nullable final String packageName) { return getLaunchIntent(packageName) != null; } @@ -36,14 +39,14 @@ public final class ProcessUtils { * @param packageName * @return */ - public static boolean isInstalled(final String packageName) { + public static boolean isInstalled(@NonNull final String packageName) { return isLaunchable(packageName) || hasPackageInstalled(packageName); } /** * This will find installed applications even without launch intent (e.g. the streetview plugin). */ - private static boolean hasPackageInstalled(final String packageName) { + private static boolean hasPackageInstalled(@NonNull final String packageName) { final List<PackageInfo> packs = CgeoApplication.getInstance().getPackageManager().getInstalledPackages(0); for (final PackageInfo packageInfo : packs) { if (packageName.equals(packageInfo.packageName)) { @@ -56,7 +59,8 @@ public final class ProcessUtils { /** * This will find applications, which can be launched. */ - public static Intent getLaunchIntent(final String packageName) { + @Nullable + public static Intent getLaunchIntent(@Nullable final String packageName) { if (packageName == null) { return null; } @@ -79,16 +83,16 @@ public final class ProcessUtils { * method queries the package manager for installed packages that can * respond to an intent with the specified action. If no suitable package is * found, this method returns false. - * + * * @param action * The Intent action to check for availability. * @param uri * The Intent URI to check for availability. - * + * * @return True if an Intent with the specified action can be sent and * responded to, false otherwise. */ - public static boolean isIntentAvailable(final String action, final Uri uri) { + public static boolean isIntentAvailable(@NonNull final String action, @Nullable final Uri uri) { final PackageManager packageManager = CgeoApplication.getInstance().getPackageManager(); final Intent intent; if (uri == null) { @@ -103,4 +107,18 @@ public final class ProcessUtils { return CollectionUtils.isNotEmpty(list) || CollectionUtils.isNotEmpty(servicesList); } + @SuppressWarnings("deprecation") + public static void openMarket(final Activity activity, @NonNull final String packageName) { + try { + final String url = "market://details?id=" + packageName; + final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + activity.startActivity(marketIntent); + + } catch (final RuntimeException ignored) { + // market not available, fall back to browser + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id=" + packageName))); + } + } + } diff --git a/main/src/cgeo/geocaching/utils/RxUtils.java b/main/src/cgeo/geocaching/utils/RxUtils.java index 280575b..08cc3e7 100644 --- a/main/src/cgeo/geocaching/utils/RxUtils.java +++ b/main/src/cgeo/geocaching/utils/RxUtils.java @@ -2,7 +2,6 @@ package cgeo.geocaching.utils; import rx.Observable; import rx.Observable.OnSubscribe; -import rx.Observable.Operator; import rx.Scheduler; import rx.Scheduler.Worker; import rx.Subscriber; @@ -17,7 +16,6 @@ import rx.observers.Subscribers; import rx.schedulers.Schedulers; import rx.subjects.PublishSubject; import rx.subscriptions.Subscriptions; -import rx.util.async.Async; import android.os.Handler; import android.os.HandlerThread; @@ -115,49 +113,6 @@ public class RxUtils { abstract protected void onStop(); } - public static <T> Operator<T, T> operatorTakeUntil(final Func1<? super T, Boolean> predicate) { - return new Operator<T, T>() { - @Override - public Subscriber<? super T> call(final Subscriber<? super T> subscriber) { - return new Subscriber<T>(subscriber) { - private boolean done = false; - - @Override - public void onCompleted() { - if (!done) { - subscriber.onCompleted(); - } - } - - @Override - public void onError(final Throwable throwable) { - if (!done) { - subscriber.onError(throwable); - } - } - - @Override - public void onNext(final T value) { - subscriber.onNext(value); - boolean shouldEnd = false; - try { - shouldEnd = predicate.call(value); - } catch (final Throwable e) { - done = true; - subscriber.onError(e); - unsubscribe(); - } - if (shouldEnd) { - done = true; - subscriber.onCompleted(); - unsubscribe(); - } - } - }; - } - }; - } - public static<T> Observable<T> rememberLast(final Observable<T> observable, final T initialValue) { final AtomicReference<T> lastValue = new AtomicReference<>(initialValue); return observable.doOnNext(new Action1<T>() { @@ -175,20 +130,26 @@ public class RxUtils { } public static <T> void andThenOnUi(final Scheduler scheduler, final Func0<T> background, final Action1<T> foreground) { - Async.fromCallable(background, scheduler).observeOn(AndroidSchedulers.mainThread()).subscribe(foreground); + scheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + final T value = background.call(); + AndroidSchedulers.mainThread().createWorker().schedule(new Action0() { + @Override + public void call() { + foreground.call(value); + } + }); + } + }); } public static void andThenOnUi(final Scheduler scheduler, final Action0 background, final Action0 foreground) { - andThenOnUi(scheduler, new Func0<Void>() { + scheduler.createWorker().schedule(new Action0() { @Override - public Void call() { + public void call() { background.call(); - return null; - } - }, new Action1<Void>() { - @Override - public void call(final Void ignored) { - foreground.call(); + AndroidSchedulers.mainThread().createWorker().schedule(foreground); } }); } diff --git a/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java b/main/thirdparty/menion/android/locus/LocusDataStorageProvider.java index 03954f5..b575cb5 100644 --- a/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java +++ b/main/thirdparty/menion/android/locus/LocusDataStorageProvider.java @@ -1,4 +1,4 @@ -package cgeo.geocaching.apps; +package menion.android.locus; import menion.android.locus.addon.publiclib.geoData.PointsData; import menion.android.locus.addon.publiclib.utils.DataCursor; diff --git a/mapswithme-api/build.gradle b/mapswithme-api/build.gradle index 86d5c77..94cd14f 100644 --- a/mapswithme-api/build.gradle +++ b/mapswithme-api/build.gradle @@ -1,34 +1,19 @@ apply plugin: 'android-library' -dependencies { - compile fileTree(dir: 'libs', include: '*.jar') -} - android { - compileSdkVersion 19 - buildToolsVersion "21.1.2" - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - resources.srcDirs = ['src'] - aidl.srcDirs = ['src'] - renderscript.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - } + // Define these properties in the gradle.properties file in the root project folder + compileSdkVersion propTargetSdkVersion.toInteger() + buildToolsVersion propBuildToolsVersion - // Move the tests to tests/java, tests/res, etc... - instrumentTest.setRoot('tests') + defaultConfig { + minSdkVersion propMinSdkVersion.toInteger() + targetSdkVersion propTargetSdkVersion.toInteger() + } - // Move the build types to build-types/<type> - // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... - // This moves them out of them default location under src/<type>/... which would - // conflict with src/ being used by the main source set. - // Adding new build types or product flavors should be accompanied - // by a similar customization. - debug.setRoot('build-types/debug') - release.setRoot('build-types/release') - } + sourceSets.main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + res.srcDirs = ['res'] + } } diff --git a/mapswithme-api/project.properties b/mapswithme-api/project.properties index 91d2b02..93c8c3c 100644 --- a/mapswithme-api/project.properties +++ b/mapswithme-api/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-19 +target=android-21 android.library=true diff --git a/mapswithme-api/res/layout/dlg_install_mwm.xml b/mapswithme-api/res/layout/dlg_install_mwm.xml index 0d174a8..1858369 100644 --- a/mapswithme-api/res/layout/dlg_install_mwm.xml +++ b/mapswithme-api/res/layout/dlg_install_mwm.xml @@ -54,16 +54,6 @@ android:background="@drawable/btn_green_selector" android:text="@string/down_pro" /> - <Button - android:id="@+id/btn_lite" - style="@style/promoButton" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_weight="1" - android:background="@drawable/btn_gray_selector" - android:padding="6dp" - android:text="@string/down_lite" /> - </LinearLayout> </ScrollView>
\ No newline at end of file diff --git a/mapswithme-api/res/values/strings.xml b/mapswithme-api/res/values/strings.xml index 1955847..d9e3f27 100644 --- a/mapswithme-api/res/values/strings.xml +++ b/mapswithme-api/res/values/strings.xml @@ -1,9 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string name="mwm_should_be_installed">Offline maps are required to proceed. We have partnered with MapsWithMe to provide you with offline maps of the entire world.\nTo continue please download the app:</string> - <string name="down_lite">Download MapsWithMe Lite (free)</string> - <string name="down_pro">Download MapsWithMe Pro</string> - - <string name="url_pro">http://mapswith.me/get</string> - <string name="url_lite">http://mapswith.me/app</string> + <string name="mwm_should_be_installed">Offline maps are required to proceed. We have partnered with MAPS.ME to provide you with offline maps of the entire world.\nTo continue please download the app:</string> + <string name="down_pro">Download MAPS.ME</string> + <string name="url_pro">http://maps.me/get</string> </resources>
\ No newline at end of file diff --git a/mapswithme-api/src/com/mapswithme/maps/api/DownloadMapsWithMeDialog.java b/mapswithme-api/src/com/mapswithme/maps/api/DownloadMapsWithMeDialog.java index 5670a5f..480bbe1 100644 --- a/mapswithme-api/src/com/mapswithme/maps/api/DownloadMapsWithMeDialog.java +++ b/mapswithme-api/src/com/mapswithme/maps/api/DownloadMapsWithMeDialog.java @@ -41,7 +41,6 @@ public class DownloadMapsWithMeDialog extends Dialog implements android.view.Vie requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.dlg_install_mwm); - findViewById(R.id.btn_lite).setOnClickListener(this); findViewById(R.id.btn_pro).setOnClickListener(this); setOwnerActivity(activity); @@ -59,7 +58,7 @@ public class DownloadMapsWithMeDialog extends Dialog implements android.view.Vie @Override public void onClick(View v) { - String url = getContext().getString(v.getId() == R.id.btn_lite ? R.string.url_lite : R.string.url_pro); + String url = getContext().getString(R.string.url_pro); onDownloadButtonClicked(url); } } diff --git a/play-services-base/project.properties b/play-services-base/project.properties index ad36a32..664c438 100644 --- a/play-services-base/project.properties +++ b/play-services-base/project.properties @@ -11,5 +11,5 @@ proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard.txt # Project target. -target=Google Inc.:Google APIs:19 +target=Google Inc.:Google APIs:21 android.library=true diff --git a/play-services-location/project.properties b/play-services-location/project.properties index 8a32119..51a7632 100644 --- a/play-services-location/project.properties +++ b/play-services-location/project.properties @@ -11,6 +11,6 @@ proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard.txt # Project target. -target=Google Inc.:Google APIs:19 +target=Google Inc.:Google APIs:21 android.library=true android.library.reference.1=../play-services-base diff --git a/tests/.settings/org.eclipse.jdt.ui.prefs b/tests/.settings/org.eclipse.jdt.ui.prefs index 1fda530..06e562c 100644 --- a/tests/.settings/org.eclipse.jdt.ui.prefs +++ b/tests/.settings/org.eclipse.jdt.ui.prefs @@ -8,7 +8,7 @@ org.eclipse.jdt.ui.ondemandthreshold=99 org.eclipse.jdt.ui.staticondemandthreshold=99 sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_annotations=true sp_cleanup.add_missing_deprecated_annotations=true sp_cleanup.add_missing_methods=false sp_cleanup.add_missing_nls_tags=false @@ -20,16 +20,16 @@ sp_cleanup.always_use_parentheses_in_expressions=false sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false sp_cleanup.convert_functional_interfaces=false -sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.convert_to_enhanced_for_loop=true sp_cleanup.correct_indentation=false sp_cleanup.format_source_code=true sp_cleanup.format_source_code_changes_only=true sp_cleanup.insert_inferred_type_arguments=false -sp_cleanup.make_local_variable_final=false -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=true +sp_cleanup.make_private_fields_final=true sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=false +sp_cleanup.make_variable_declarations_final=true sp_cleanup.never_use_blocks=false sp_cleanup.never_use_parentheses_in_expressions=true sp_cleanup.on_save_use_additional_actions=true @@ -37,16 +37,16 @@ sp_cleanup.organize_imports=true sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_with_declaring_class=true sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true sp_cleanup.remove_redundant_type_arguments=false sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=false -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true sp_cleanup.remove_unused_private_members=false @@ -55,7 +55,7 @@ sp_cleanup.remove_unused_private_types=true sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false sp_cleanup.use_anonymous_class_creation=false -sp_cleanup.use_blocks=false +sp_cleanup.use_blocks=true sp_cleanup.use_blocks_only_for_return_and_throw=false sp_cleanup.use_lambda=false sp_cleanup.use_parentheses_in_expressions=false diff --git a/tests/res/layout/cgeo_tests_activity.xml b/tests/res/layout/cgeo_tests_activity.xml index 43225ac..d035210 100644 --- a/tests/res/layout/cgeo_tests_activity.xml +++ b/tests/res/layout/cgeo_tests_activity.xml @@ -13,6 +13,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:layout_gravity="center_vertical" android:gravity="center_vertical" @@ -27,6 +28,7 @@ android:layout_height="fill_parent" android:layout_above="@+id/buttonRun" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_below="@+id/headline" > <TextView @@ -43,6 +45,7 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="false" + android:layout_alignParentStart="false" android:onClick="runTests" android:text="@string/run_tests" /> diff --git a/tests/src/cgeo/geocaching/GeocacheTest.java b/tests/src/cgeo/geocaching/GeocacheTest.java index 37b6883..3e29bcf 100644 --- a/tests/src/cgeo/geocaching/GeocacheTest.java +++ b/tests/src/cgeo/geocaching/GeocacheTest.java @@ -302,7 +302,7 @@ public class GeocacheTest extends CGeoTestCase { cache.setType(CacheType.EVENT); cache.setDescription(StringUtils.EMPTY); cache.setShortDescription("text 14:20 text"); - assertThat(cache.guessEventTimeMinutes()).isEqualTo(String.valueOf(14 * 60 + 20)); + assertThat(cache.guessEventTimeMinutes()).isEqualTo(14 * 60 + 20); } private static void assertTime(final String description, final int hours, final int minutes) { @@ -310,14 +310,14 @@ public class GeocacheTest extends CGeoTestCase { cache.setDescription(description); cache.setType(CacheType.EVENT); final int minutesAfterMidnight = hours * 60 + minutes; - assertThat(cache.guessEventTimeMinutes()).isEqualTo(String.valueOf(minutesAfterMidnight)); + assertThat(cache.guessEventTimeMinutes()).isEqualTo(minutesAfterMidnight); } private static void assertNoTime(final String description) { final Geocache cache = new Geocache(); cache.setDescription(description); cache.setType(CacheType.EVENT); - assertThat(cache.guessEventTimeMinutes()).isNull(); + assertThat(cache.guessEventTimeMinutes()).isEqualTo(-1); } public static void testGetPossibleLogTypes() throws Exception { diff --git a/tests/src/cgeo/geocaching/connector/oc/OkapiClientTest.java b/tests/src/cgeo/geocaching/connector/oc/OkapiClientTest.java index aa66ac9..22b2dbe 100644 --- a/tests/src/cgeo/geocaching/connector/oc/OkapiClientTest.java +++ b/tests/src/cgeo/geocaching/connector/oc/OkapiClientTest.java @@ -30,7 +30,7 @@ public class OkapiClientTest extends CGeoTestCase { public static void testOCSearchMustWorkWithoutOAuthAccessTokens() { final String geoCode = "OC1234"; - Geocache cache = OkapiClient.getCache(geoCode); + final Geocache cache = OkapiClient.getCache(geoCode); assertThat(cache).overridingErrorMessage("You must have a valid OKAPI key installed for running this test (but you do not need to set credentials in the app).").isNotNull(); assertThat(cache.getName()).isEqualTo("Wupper-Schein"); } @@ -55,9 +55,16 @@ public class OkapiClientTest extends CGeoTestCase { final String geoCode = "OC6465"; removeCacheCompletely(geoCode); - Geocache cache = OkapiClient.getCache(geoCode); + final Geocache cache = OkapiClient.getCache(geoCode); assertThat(cache).as("Cache from OKAPI").isNotNull(); assertThat(cache.getLogCounts().get(LogType.WILL_ATTEND)).isGreaterThan(0); } + public static void testGetAllLogs() { + final String geoCode = "OC10CB8"; + final Geocache cache = OkapiClient.getCache(geoCode); + final int defaultLogCount = 10; + assertThat(cache.getLogs().size()).isGreaterThan(defaultLogCount); + } + } diff --git a/tests/src/cgeo/geocaching/connector/trackable/SwaggieConnectorTest.java b/tests/src/cgeo/geocaching/connector/trackable/SwaggieConnectorTest.java new file mode 100644 index 0000000..54c3319 --- /dev/null +++ b/tests/src/cgeo/geocaching/connector/trackable/SwaggieConnectorTest.java @@ -0,0 +1,29 @@ +package cgeo.geocaching.connector.trackable; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.geocaching.Trackable; + +import junit.framework.TestCase; + +public class SwaggieConnectorTest extends TestCase { + + public static void testCanHandleTrackable() { + assertThat(new SwaggieConnector().canHandleTrackable("SW0001")).isTrue(); + assertThat(new SwaggieConnector().canHandleTrackable("SWABCD")).isFalse(); + assertThat(new SwaggieConnector().canHandleTrackable("GK82A2")).isFalse(); + assertThat(new SwaggieConnector().canHandleTrackable("TB1234")).isFalse(); + assertThat(new SwaggieConnector().canHandleTrackable("UNKNOWN")).isFalse(); + } + + public static void testGetTrackableCodeFromUrl() throws Exception { + assertThat(new SwaggieConnector().getTrackableCodeFromUrl("http://geocaching.com.au/swaggie/sw0017")).isEqualTo("SW0017"); + } + + public static void testGetUrl() throws Exception { + final Trackable trackable = new Trackable(); + trackable.setGeocode("SW0017"); + assertThat(new SwaggieConnector().getUrl(trackable)).isEqualTo("http://geocaching.com.au/swaggie/SW0017"); + } + +} diff --git a/tests/src/cgeo/geocaching/connector/trackable/SwaggieParserTest.java b/tests/src/cgeo/geocaching/connector/trackable/SwaggieParserTest.java new file mode 100644 index 0000000..2661fb3 --- /dev/null +++ b/tests/src/cgeo/geocaching/connector/trackable/SwaggieParserTest.java @@ -0,0 +1,34 @@ +package cgeo.geocaching.connector.trackable; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.geocaching.Trackable; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.network.Network; + +import junit.framework.TestCase; + +public class SwaggieParserTest extends TestCase { + + public static void testParse() { + final Trackable trackableIn = new Trackable(); + trackableIn.setGeocode("SW0017"); + + final String trackableUrl = ConnectorFactory.getTrackableConnector(trackableIn.getGeocode()).getUrl(trackableIn); + assertThat(trackableUrl).isNotNull(); + + final String page = Network.getResponseData(Network.getRequest(trackableUrl)); + assertThat(page).isNotNull(); + + assert page != null; + final Trackable trackable = SwaggieParser.parse(page); + assertThat(trackable).isNotNull(); + assert trackable != null; + + assertThat(trackable.getName()).isEqualTo("Law and Order 1"); + assertThat(trackable.getGeocode()).isEqualTo("SW0017"); + assertThat(trackable.getDetails()).isEqualTo("A mini CD that may or may not contain a DivX .AVI of the Law and Order: CSI episode that features geocaching as part of the storyline."); + assertThat(trackable.getType()).isEqualTo("Swaggie"); + assertThat(trackable.getOwner()).isEqualTo("Bear_Left"); + } +} diff --git a/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java b/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java index 8d80822..7123e87 100644 --- a/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java +++ b/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java @@ -26,14 +26,16 @@ public class TravelBugConnectorTest extends TestCase { } public static void testOnlineSearchBySecretCode() { - Trackable trackable = getConnector().searchTrackable("GST9HV", null, null); + final Trackable trackable = getConnector().searchTrackable("GST9HV", null, null); assertThat(trackable).isNotNull(); + assert trackable != null; assertThat(trackable.getName()).isEqualTo("Deutschland"); } public static void testOnlineSearchByPublicCode() { - Trackable trackable = getConnector().searchTrackable("TB4JD36", null, null); + final Trackable trackable = getConnector().searchTrackable("TB4JD36", null, null); assertThat(trackable).isNotNull(); + assert trackable != null; assertThat(trackable.getName()).isEqualTo("Mein Kilometerzähler"); } diff --git a/tests/src/cgeo/geocaching/export/ExportTest.java b/tests/src/cgeo/geocaching/export/ExportTest.java index bec676f..21c45a0 100644 --- a/tests/src/cgeo/geocaching/export/ExportTest.java +++ b/tests/src/cgeo/geocaching/export/ExportTest.java @@ -25,7 +25,7 @@ public class ExportTest extends CGeoTestCase { final Geocache cache = new Geocache(); cache.setGeocode("GCX1234"); final LogEntry log = new LogEntry(1353244820000L, LogType.FOUND_IT, "Hidden in a tree"); - FieldNotes fieldNotes = new FieldNotes(); + final FieldNotes fieldNotes = new FieldNotes(); fieldNotes.add(cache, log); assertEquals("Non matching export " + fieldNotes.getContent(), "GCX1234,2012-11-18T13:20:20Z,Found it,\"Hidden in a tree\"\n", fieldNotes.getContent()); } @@ -55,8 +55,8 @@ public class ExportTest extends CGeoTestCase { cache.setDetailed(true); DataStore.saveCache(cache, LoadFlags.SAVE_ALL); - List<Geocache> exportList = Collections.singletonList(cache); - GpxExportTester gpxExport = new GpxExportTester(); + final List<Geocache> exportList = Collections.singletonList(cache); + final GpxExportTester gpxExport = new GpxExportTester(); File result = null; try { result = gpxExport.testExportSync(exportList); @@ -67,17 +67,22 @@ public class ExportTest extends CGeoTestCase { assertThat(result).isNotNull(); // make sure we actually exported waypoints - String gpx = org.apache.commons.io.FileUtils.readFileToString(result); + final String gpx = org.apache.commons.io.FileUtils.readFileToString(result); assertThat(gpx).contains("<wpt"); assertThat(gpx).contains(cache.getGeocode()); + if (cache.getUrl() != null) { + assertThat(gpx).contains("<url>"); + } else { + assertThat(gpx).doesNotContain("<url>"); + } FileUtils.deleteIgnoringFailure(result); } private static class GpxExportTester extends GpxExport { - public File testExportSync(List<Geocache> caches) throws InterruptedException, ExecutionException { - final ArrayList<String> geocodes = new ArrayList<String>(caches.size()); + public File testExportSync(final List<Geocache> caches) throws InterruptedException, ExecutionException { + final ArrayList<String> geocodes = new ArrayList<>(caches.size()); for (final Geocache cache : caches) { geocodes.add(cache.getGeocode()); } diff --git a/tests/src/cgeo/geocaching/files/GPXParserTest.java b/tests/src/cgeo/geocaching/files/GPXParserTest.java index 2cc1f34..8562087 100644 --- a/tests/src/cgeo/geocaching/files/GPXParserTest.java +++ b/tests/src/cgeo/geocaching/files/GPXParserTest.java @@ -6,6 +6,8 @@ import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; import cgeo.geocaching.LogEntry; import cgeo.geocaching.Waypoint; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.IConnector; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; @@ -411,6 +413,9 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { assertThat(lab.getName()).isEqualTo("01_Munich Olympic Walk Of Stars_Updated-Project MUNICH2014 - Mia san Giga! Olympiapark"); assertThat(lab.getShortDescription()).isEqualTo("01_Munich Olympic Walk Of Stars_Updated (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark"); assertThat(lab.getDescription()).startsWith("DEU:"); + + final IConnector unknownConnector = ConnectorFactory.getConnector("ABC123"); + assertThat(ConnectorFactory.getConnector(lab)).isSameAs(unknownConnector); } } diff --git a/tests/src/cgeo/geocaching/location/GeocoderTest.java b/tests/src/cgeo/geocaching/location/GeocoderTest.java index 0cc1a79..51a8bc8 100644 --- a/tests/src/cgeo/geocaching/location/GeocoderTest.java +++ b/tests/src/cgeo/geocaching/location/GeocoderTest.java @@ -14,6 +14,8 @@ import rx.Observable; import android.location.Address; import android.location.Geocoder; +import java.util.Locale; + public class GeocoderTest extends CGeoTestCase { private static final String TEST_ADDRESS = "46 rue Barrault, Paris, France"; @@ -23,13 +25,19 @@ public class GeocoderTest extends CGeoTestCase { private static final Offset<Double> TEST_OFFSET = Offset.offset(0.00050); public static void testAndroidGeocoder() { - // Some emulators don't have access to Google Android geocoder - if (Geocoder.isPresent()) { - final AndroidGeocoder geocoder = new AndroidGeocoder(CgeoApplication.getInstance()); - testGeocoder(geocoder.getFromLocationName(TEST_ADDRESS), "Android", true); - testGeocoder(geocoder.getFromLocation(TEST_COORDS), "Android reverse", true); - } else { - Log.i("not testing absent Android geocoder"); + final Locale locale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + // Some emulators don't have access to Google Android geocoder + if (Geocoder.isPresent()) { + final AndroidGeocoder geocoder = new AndroidGeocoder(CgeoApplication.getInstance()); + testGeocoder(geocoder.getFromLocationName(TEST_ADDRESS), "Android", true); + testGeocoder(geocoder.getFromLocation(TEST_COORDS), "Android reverse", true); + } else { + Log.i("not testing absent Android geocoder"); + } + } finally { + Locale.setDefault(locale); } } @@ -38,8 +46,14 @@ public class GeocoderTest extends CGeoTestCase { } public static void testMapQuestGeocoder() { - testGeocoder(MapQuestGeocoder.getFromLocationName(TEST_ADDRESS), "MapQuest", true); - testGeocoder(MapQuestGeocoder.getFromLocation(TEST_COORDS), "MapQuest reverse", true); + final Locale locale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + testGeocoder(MapQuestGeocoder.getFromLocationName(TEST_ADDRESS), "MapQuest", true); + testGeocoder(MapQuestGeocoder.getFromLocation(TEST_COORDS), "MapQuest reverse", true); + } finally { + Locale.setDefault(locale); + } } public static void testGeocoder(final Observable<Address> addressObservable, final String geocoder, final boolean withAddress) { @@ -47,9 +61,10 @@ public class GeocoderTest extends CGeoTestCase { assertThat(address.getLatitude()).as(describe("latitude", geocoder)).isCloseTo(TEST_LATITUDE, TEST_OFFSET); assertThat(address.getLongitude()).as(describe("longitude", geocoder)).isCloseTo(TEST_LONGITUDE, TEST_OFFSET); if (withAddress) { - assertThat(StringUtils.lowerCase(address.getAddressLine(0))).as(describe("street address", geocoder)).startsWith("46 rue barrault"); + assertThat(StringUtils.lowerCase(address.getAddressLine(0))).as(describe("street address", geocoder)).contains("rue barrault"); assertThat(address.getLocality()).as(describe("locality", geocoder)).isEqualTo("Paris"); - assertThat(address.getCountryName()).as(describe("country name", geocoder)).isEqualTo("France"); + assertThat(address.getCountryCode()).as(describe("country code", geocoder)).isEqualTo("FR"); + // don't assert on country name, as this can be localized, e.g. with the mapquest geocoder } } diff --git a/tests/src/cgeo/geocaching/utils/ProcessUtilsTest.java b/tests/src/cgeo/geocaching/utils/ProcessUtilsTest.java index 2c6ed18..b442c8a 100644 --- a/tests/src/cgeo/geocaching/utils/ProcessUtilsTest.java +++ b/tests/src/cgeo/geocaching/utils/ProcessUtilsTest.java @@ -6,7 +6,7 @@ import junit.framework.TestCase; public class ProcessUtilsTest extends TestCase { public static void testIsInstalled() { - assertThat(ProcessUtils.isInstalled("com.android.launcher")).isTrue(); + assertThat(ProcessUtils.isInstalled("com.android.settings")).isTrue(); } public static void testIsInstalledNotLaunchable() { @@ -16,7 +16,7 @@ public class ProcessUtilsTest extends TestCase { } public static void testIsLaunchable() { - assertThat(ProcessUtils.isInstalled("com.android.settings")).isTrue(); + assertThat(ProcessUtils.isLaunchable("com.android.settings")).isTrue(); } } diff --git a/tests/src/cgeo/geocaching/utils/RxUtilsTest.java b/tests/src/cgeo/geocaching/utils/RxUtilsTest.java index 2487184..cc8589b 100644 --- a/tests/src/cgeo/geocaching/utils/RxUtilsTest.java +++ b/tests/src/cgeo/geocaching/utils/RxUtilsTest.java @@ -4,7 +4,6 @@ import static org.assertj.core.api.Assertions.assertThat; import rx.Observable; import rx.Subscription; -import rx.functions.Func1; import rx.subjects.PublishSubject; import rx.subjects.ReplaySubject; @@ -21,16 +20,6 @@ public class RxUtilsTest extends AndroidTestCase { range.onCompleted(); } - public static void testTakeUntil() { - final Observable<Integer> observable = range.lift(RxUtils.operatorTakeUntil(new Func1<Integer, Boolean>() { - @Override - public Boolean call(final Integer value) { - return value > 6; - } - })); - assertThat(observable.toList().toBlocking().single().toArray()).isEqualTo(new int[]{1, 2, 3, 4, 5, 6, 7}); - } - public static void testRememberLast() { final PublishSubject<String> rawObservable = PublishSubject.create(); final Observable<String> observable = RxUtils.rememberLast(rawObservable, "initial"); diff --git a/tests/src/cgeo/junit/CgeoTestRunner.java b/tests/src/cgeo/junit/CgeoTestRunner.java index 16a5f12..94803cf 100644 --- a/tests/src/cgeo/junit/CgeoTestRunner.java +++ b/tests/src/cgeo/junit/CgeoTestRunner.java @@ -11,10 +11,12 @@ import android.util.Log; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * Test runner which derives from the newer Google instrumentation test runner used by the Espresso test framework. It - * adds junit report functionality by cloning the behaviour of the {@link JUnitReportTestRunner}. + * adds junit report functionality by cloning the behavior of the {@link JUnitReportTestRunner}. * */ public class CgeoTestRunner extends GoogleInstrumentationTestRunner { @@ -86,21 +88,32 @@ public class CgeoTestRunner extends GoogleInstrumentationTestRunner { @Override public void start() { - mListener = new JUnitReportListener(getContext(), getTargetContext(), mReportFile, mReportDir, mFilterTraces, mMultiFile); - try { - Class<?> c = getClass(); - Field bridgeTestRunner = c.getSuperclass().getDeclaredField("bridgeTestRunner"); - bridgeTestRunner.setAccessible(true); - Object obj = bridgeTestRunner.get(this); - Method m = obj.getClass().getDeclaredMethod("getAndroidTestRunner", (Class[]) null); - AndroidTestRunner androidTestRunner = (AndroidTestRunner) m.invoke(obj); - androidTestRunner.addTestListener(mListener); - } catch (NoSuchFieldException | InvocationTargetException | IllegalAccessException | NoSuchMethodException | SecurityException x) { - Log.e(LOG_TAG, x.toString()); - } + makeAndroidTestRunnerAccessible(); super.start(); } + private void makeAndroidTestRunnerAccessible() { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + @Override + public Void run() { + mListener = new JUnitReportListener(getContext(), getTargetContext(), mReportFile, mReportDir, mFilterTraces, mMultiFile); + try { + Class<?> c = getClass(); + Field bridgeTestRunner = c.getSuperclass().getDeclaredField("bridgeTestRunner"); + bridgeTestRunner.setAccessible(true); + Object obj = bridgeTestRunner.get(this); + Method m = obj.getClass().getDeclaredMethod("getAndroidTestRunner", (Class[]) null); + AndroidTestRunner androidTestRunner = (AndroidTestRunner) m.invoke(obj); + androidTestRunner.addTestListener(mListener); + } catch (NoSuchFieldException | InvocationTargetException | IllegalAccessException + | NoSuchMethodException | SecurityException x) { + Log.e(LOG_TAG, x.toString()); + } + return null; + } + }); + } + @Override public void finish(int resultCode, Bundle results) { if (mListener != null) { |
