diff options
67 files changed, 774 insertions, 653 deletions
diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml index 38f82a8..7836d07 100644 --- a/main/AndroidManifest.xml +++ b/main/AndroidManifest.xml @@ -445,7 +445,7 @@ </service> <activity - android:name=".connector.oc.OCDEAuthorizationActivity" + android:name=".connector.oc.OCAuthorizationActivity" android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:launchMode="singleTask" @@ -458,25 +458,7 @@ <data android:host="www.cgeo.org" - android:pathPrefix="/opencaching.de/" - android:scheme="callback" /> - </intent-filter> - </activity> - <activity - android:name=".connector.oc.OCPLAuthorizationActivity" - android:configChanges="keyboardHidden|orientation" - android:label="@string/app_name" - android:launchMode="singleTask" - android:windowSoftInputMode="stateHidden" > - <intent-filter> - <action android:name="android.intent.action.VIEW" /> - - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> - - <data - android:host="www.cgeo.org" - android:pathPrefix="/opencaching.pl/" + android:pathPrefix="/opencaching" android:scheme="callback" /> </intent-filter> </activity> diff --git a/main/build.xml b/main/build.xml index 257aaf3..a888e9b 100644 --- a/main/build.xml +++ b/main/build.xml @@ -112,6 +112,12 @@ <filter token="ocde.okapi.consumer.secret" value="${ocde.okapi.consumer.secret}"/> <filter token="ocpl.okapi.consumer.key" value="${ocpl.okapi.consumer.key}"/> <filter token="ocpl.okapi.consumer.secret" value="${ocpl.okapi.consumer.secret}"/> + <filter token="ocus.okapi.consumer.key" value="${ocus.okapi.consumer.key}"/> + <filter token="ocus.okapi.consumer.secret" value="${ocus.okapi.consumer.secret}"/> + <filter token="ocnl.okapi.consumer.key" value="${ocnl.okapi.consumer.key}"/> + <filter token="ocnl.okapi.consumer.secret" value="${ocnl.okapi.consumer.secret}"/> + <filter token="ocro.okapi.consumer.key" value="${ocro.okapi.consumer.key}"/> + <filter token="ocro.okapi.consumer.secret" value="${ocro.okapi.consumer.secret}"/> </filterset> </copy> </target> diff --git a/main/libs/rxjava-android-0.17.1-cgeo.jar b/main/libs/rxjava-android-0.17.5.jar Binary files differindex 1120cb5..42b7f16 100644 --- a/main/libs/rxjava-android-0.17.1-cgeo.jar +++ b/main/libs/rxjava-android-0.17.5.jar diff --git a/main/libs/rxjava-async-util-0.17.1-cgeo.jar b/main/libs/rxjava-async-util-0.17.5.jar Binary files differindex 644daab..bc71622 100644 --- a/main/libs/rxjava-async-util-0.17.1-cgeo.jar +++ b/main/libs/rxjava-async-util-0.17.5.jar diff --git a/main/libs/rxjava-core-0.17.1-cgeo.jar b/main/libs/rxjava-core-0.17.1-cgeo.jar Binary files differdeleted file mode 100644 index 75692f2..0000000 --- a/main/libs/rxjava-core-0.17.1-cgeo.jar +++ /dev/null diff --git a/main/libs/rxjava-core-0.17.5.jar b/main/libs/rxjava-core-0.17.5.jar Binary files differnew file mode 100644 index 0000000..5a54704 --- /dev/null +++ b/main/libs/rxjava-core-0.17.5.jar diff --git a/main/proguard-project.txt b/main/proguard-project.txt index bb064b9..5b606f5 100644 --- a/main/proguard-project.txt +++ b/main/proguard-project.txt @@ -48,10 +48,6 @@ # The backup agent class is not called from our code. -keep public class cgeo.geocaching.backup.CentralBackupAgent --keepclassmembers class cgeo.geocaching.compatibility.AndroidLevel8 { - public static <methods>; -} - # Butter knife view injection, see http://jakewharton.github.io/butterknife/ -dontwarn butterknife.internal.** -keep class **$$ViewInjector { *; } diff --git a/main/project/rawimages/c-geo_contacts_play_icon.png b/main/project/rawimages/c-geo_contacts_play_icon.png Binary files differnew file mode 100644 index 0000000..f2d66c0 --- /dev/null +++ b/main/project/rawimages/c-geo_contacts_play_icon.png diff --git a/main/res/values-lt/strings.xml b/main/res/values-lt/strings.xml index 4c380d8..edb9e4b 100644 --- a/main/res/values-lt/strings.xml +++ b/main/res/values-lt/strings.xml @@ -245,7 +245,7 @@ <string name="caches_store_offline">Išsaugoti slėptuves</string> <string name="caches_store_selected">Išsaugoti pasirinktas</string> <string name="caches_history">Istorija</string> - <string name="caches_on_map">Žemėlapyje</string> + <string name="caches_on_map">Rodyti\nžemėlapyje</string> <string name="caches_sort">Rūšiuoti</string> <string name="caches_sort_title">Rūšiuoti pagal</string> <string name="caches_sort_distance">Atstumą</string> diff --git a/main/res/values/changelog_master.xml b/main/res/values/changelog_master.xml index 1e3c3d4..572bfbf 100644 --- a/main/res/values/changelog_master.xml +++ b/main/res/values/changelog_master.xml @@ -2,5 +2,10 @@ <resources> <!-- changelog for the master branch --> <string name="changelog_master" translatable="false"> + <b>Next feature release:</b>\n + <b>New features:</b>\n + · Changed initial coordinate format for waypoints to MinDec\n + <b>Bugfixing:</b>\n + · Improved long click detection in lists\n </string> </resources> diff --git a/main/res/values/preference_keys.xml b/main/res/values/preference_keys.xml index d231795..dc151e7 100644 --- a/main/res/values/preference_keys.xml +++ b/main/res/values/preference_keys.xml @@ -12,17 +12,26 @@ <string name="preference_screen_basicmembers">fakekey_basicmembers_screen</string> <string name="preference_screen_ocde">preference_screen_ocde</string> <string name="preference_screen_ocpl">preference_screen_ocpl</string> + <string name="preference_screen_ocnl">preference_screen_ocnl</string> + <string name="preference_screen_ocus">preference_screen_ocus</string> + <string name="preference_screen_ocro">preference_screen_ocro</string> <string name="preference_screen_ec">preference_screen_ec</string> <string name="preference_screen_twitter">preference_screen_twitter</string> <string name="preference_screen_navigation_menu">fakekey_navigation_menu_screen</string> <string name="pref_fakekey_ocde_authorization">fakekey_ocde_authorization</string> <string name="pref_fakekey_ocpl_authorization">fakekey_ocpl_authorization</string> + <string name="pref_fakekey_ocnl_authorization">fakekey_ocnl_authorization</string> + <string name="pref_fakekey_ocus_authorization">fakekey_ocus_authorization</string> + <string name="pref_fakekey_ocro_authorization">fakekey_ocro_authorization</string> <string name="pref_fakekey_twitter_authorization">fakekey_twitter_authorization</string> <string name="pref_connectorGCActive">connectorGCActive</string> <string name="pref_username">username</string> <string name="pref_password">password</string> <string name="pref_connectorOCActive">connectorOCActive</string> <string name="pref_connectorOCPLActive">connectorOCPLActive</string> + <string name="pref_connectorOCNLActive">connectorOCNLActive</string> + <string name="pref_connectorOCUSActive">connectorOCUSActive</string> + <string name="pref_connectorOCROActive">connectorOCROActive</string> <string name="pref_ecusername">ecusername</string> <string name="pref_ecpassword">ecpassword</string> <string name="pref_connectorECActive">connectorECActive</string> @@ -131,9 +140,24 @@ <string name="pref_ocpl_tokenpublic">ocpl_tokenpublic</string> <string name="pref_temp_ocpl_token_secret">ocpl-temp-token-secret</string> <string name="pref_temp_ocpl_token_public">ocpl-temp-token-public</string> + <string name="pref_ocnl_tokensecret">ocnl_tokensecret</string> + <string name="pref_ocnl_tokenpublic">ocnl_tokenpublic</string> + <string name="pref_temp_ocnl_token_secret">ocnl-temp-token-secret</string> + <string name="pref_temp_ocnl_token_public">ocnl-temp-token-public</string> + <string name="pref_ocus_tokensecret">ocus_tokensecret</string> + <string name="pref_ocus_tokenpublic">ocus_tokenpublic</string> + <string name="pref_temp_ocus_token_secret">ocus-temp-token-secret</string> + <string name="pref_temp_ocus_token_public">ocus-temp-token-public</string> + <string name="pref_ocro_tokensecret">ocro_tokensecret</string> + <string name="pref_ocro_tokenpublic">ocro_tokenpublic</string> + <string name="pref_temp_ocro_token_secret">ocro-temp-token-secret</string> + <string name="pref_temp_ocro_token_public">ocro-temp-token-public</string> <string name="pref_fakekey_gc_website">fakekey_gc_website</string> <string name="pref_fakekey_ocde_website">fakekey_ocde_website</string> <string name="pref_fakekey_ocpl_website">fakekey_ocpl_website</string> + <string name="pref_fakekey_ocnl_website">fakekey_ocnl_website</string> + <string name="pref_fakekey_ocus_website">fakekey_ocus_website</string> + <string name="pref_fakekey_ocro_website">fakekey_ocro_website</string> <string name="pref_fakekey_ec_website">fakekey_ec_website</string> <string name="pref_fakekey_ox_website">fakekey_ox_website</string> <string name="pref_fakekey_gcvote_website">fakekey_gcvote_website</string> diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index 48cc323..cd7f3be 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -411,6 +411,15 @@ <string name="init_oc_pl">Opencaching.pl</string> <string name="settings_activate_oc_pl">Activate</string> <string name="init_oc_pl_description">Authorize c:geo with opencaching.pl to search for caches and access/filter your found caches.</string> + <string name="init_oc_nl">Opencaching.nl</string> + <string name="settings_activate_oc_nl">Activate</string> + <string name="init_oc_nl_description">Authorize c:geo with opencaching.nl to search for caches and access/filter your found caches.</string> + <string name="init_oc_us">Opencaching.us</string> + <string name="settings_activate_oc_us">Activate</string> + <string name="init_oc_us_description">Authorize c:geo with opencaching.us to search for caches and access/filter your found caches.</string> + <string name="init_oc_ro">Opencaching.ro</string> + <string name="settings_activate_oc_ro">Activate</string> + <string name="init_oc_ro_description">Authorize c:geo with opencaching.ro to search for caches and access/filter your found caches.</string> <string name="init_gcvote">GCvote.com</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Activate</string> @@ -583,6 +592,9 @@ <!-- auth opencaching --> <string name="auth_ocde">opencaching.de</string> <string name="auth_ocpl">opencaching.pl</string> + <string name="auth_ocnl">opencaching.nl</string> + <string name="auth_ocus">opencaching.us</string> + <string name="auth_ocro">opencaching.ro</string> <string name="auth_dialog_completed_oc">c:geo is now authorized to interact with %s.</string> <!-- cache --> diff --git a/main/res/xml/preferences.xml b/main/res/xml/preferences.xml index 454574e..1836dbe 100644 --- a/main/res/xml/preferences.xml +++ b/main/res/xml/preferences.xml @@ -132,6 +132,90 @@ android:title="@string/settings_open_website" /> </PreferenceCategory> </PreferenceScreen> + <PreferenceScreen + android:key="@string/preference_screen_ocnl" + android:title="@string/init_oc_nl" > + <PreferenceCategory android:title="@string/settings_settings" > + <CheckBoxPreference + android:defaultValue="false" + android:key="@string/pref_connectorOCNLActive" + android:title="@string/settings_activate_oc_nl" /> + + <cgeo.geocaching.settings.TextPreference + android:dependency="@string/pref_connectorOCNLActive" + android:layout="@layout/text_preference" + android:text="@string/init_oc_nl_description" /> + + <cgeo.geocaching.settings.OAuthPreference + android:dependency="@string/pref_connectorOCNLActive" + android:key="@string/pref_fakekey_ocnl_authorization" /> + </PreferenceCategory> + <PreferenceCategory android:title="@string/settings_information" > + <cgeo.geocaching.settings.CapabilitiesPreference + android:title="@string/settings_features" + cgeo:connector="OB" /> + + <Preference + android:key="@string/pref_fakekey_ocnl_website" + android:title="@string/settings_open_website" /> + </PreferenceCategory> + </PreferenceScreen> + <PreferenceScreen + android:key="@string/preference_screen_ocus" + android:title="@string/init_oc_us" > + <PreferenceCategory android:title="@string/settings_settings" > + <CheckBoxPreference + android:defaultValue="false" + android:key="@string/pref_connectorOCUSActive" + android:title="@string/settings_activate_oc_us" /> + + <cgeo.geocaching.settings.TextPreference + android:dependency="@string/pref_connectorOCUSActive" + android:layout="@layout/text_preference" + android:text="@string/init_oc_us_description" /> + + <cgeo.geocaching.settings.OAuthPreference + android:dependency="@string/pref_connectorOCUSActive" + android:key="@string/pref_fakekey_ocus_authorization" /> + </PreferenceCategory> + <PreferenceCategory android:title="@string/settings_information" > + <cgeo.geocaching.settings.CapabilitiesPreference + android:title="@string/settings_features" + cgeo:connector="OU" /> + + <Preference + android:key="@string/pref_fakekey_ocus_website" + android:title="@string/settings_open_website" /> + </PreferenceCategory> + </PreferenceScreen> + <PreferenceScreen + android:key="@string/preference_screen_ocro" + android:title="@string/init_oc_ro" > + <PreferenceCategory android:title="@string/settings_settings" > + <CheckBoxPreference + android:defaultValue="false" + android:key="@string/pref_connectorOCROActive" + android:title="@string/settings_activate_oc_ro" /> + + <cgeo.geocaching.settings.TextPreference + android:dependency="@string/pref_connectorOCROActive" + android:layout="@layout/text_preference" + android:text="@string/init_oc_ro_description" /> + + <cgeo.geocaching.settings.OAuthPreference + android:dependency="@string/pref_connectorOCROActive" + android:key="@string/pref_fakekey_ocro_authorization" /> + </PreferenceCategory> + <PreferenceCategory android:title="@string/settings_information" > + <cgeo.geocaching.settings.CapabilitiesPreference + android:title="@string/settings_features" + cgeo:connector="OR" /> + + <Preference + android:key="@string/pref_fakekey_ocro_website" + android:title="@string/settings_open_website" /> + </PreferenceCategory> + </PreferenceScreen> <PreferenceScreen android:title="@string/settings_title_ec" android:key="@string/preference_screen_ec"> <PreferenceCategory android:title="@string/settings_settings" > <CheckBoxPreference diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java index 82543b0..683579f 100644 --- a/main/src/cgeo/geocaching/AbstractPopupActivity.java +++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java @@ -14,13 +14,12 @@ import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.CacheDetailsCreator; import cgeo.geocaching.ui.LoggingUI; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import org.apache.commons.lang3.StringUtils; import rx.Observable; -import rx.android.observables.AndroidObservable; import rx.functions.Action1; import rx.functions.Func0; -import rx.schedulers.Schedulers; import android.graphics.Rect; import android.os.Bundle; @@ -80,13 +79,13 @@ public abstract class AbstractPopupActivity extends AbstractActivity implements if (!cache.supportsGCVote()) { return; } - AndroidObservable.bindActivity(this, Observable.defer(new Func0<Observable<GCVoteRating>>() { + RxUtils.subscribeOnIOThenUI(Observable.defer(new Func0<Observable<GCVoteRating>>() { @Override public Observable<GCVoteRating> call() { final GCVoteRating rating = GCVote.getRating(cache.getGuid(), geocode); return rating != null ? Observable.just(rating) : Observable.<GCVoteRating>empty(); } - }).subscribeOn(Schedulers.io())).subscribe(new Action1<GCVoteRating>() { + }), new Action1<GCVoteRating>() { @Override public void call(final GCVoteRating rating) { cache.setRating(rating.getRating()); diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index f525955..0f86de6 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -45,6 +45,7 @@ import cgeo.geocaching.utils.CryptUtils; import cgeo.geocaching.utils.ImageUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MatcherWrapper; +import cgeo.geocaching.utils.RxUtils; import cgeo.geocaching.utils.SimpleCancellableHandler; import cgeo.geocaching.utils.SimpleHandler; import cgeo.geocaching.utils.TextUtils; @@ -61,7 +62,6 @@ import rx.Observer; import rx.Scheduler.Inner; import rx.Subscriber; import rx.Subscription; -import rx.android.observables.AndroidObservable; import rx.functions.Action1; import rx.schedulers.Schedulers; @@ -878,7 +878,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc view = (ScrollView) getLayoutInflater().inflate(R.layout.cachedetail_details_page, null); // Start loading preview map - AndroidObservable.bindActivity(CacheDetailActivity.this, previewMap.subscribeOn(Schedulers.io())).subscribe(new Action1<BitmapDrawable>() { + RxUtils.subscribeOnIOThenUI(previewMap, new Action1<BitmapDrawable>() { @Override public void call(final BitmapDrawable image) { final Bitmap bitmap = image.getBitmap(); @@ -1605,71 +1605,70 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } }); - AndroidObservable.bindActivity(this, producer.subscribeOn(Schedulers.io())) - .subscribe(new Observer<Spanned>() { - @Override - public void onCompleted() { - if (null != loadingIndicatorView) { - loadingIndicatorView.setVisibility(View.GONE); - } - } + RxUtils.subscribeOnIOThenUI(producer, new Observer<Spanned>() { + @Override + public void onCompleted() { + if (null != loadingIndicatorView) { + loadingIndicatorView.setVisibility(View.GONE); + } + } - @Override - public void onError(final Throwable throwable) { - showToast(res.getString(R.string.err_load_descr_failed)); - } + @Override + public void onError(final Throwable throwable) { + showToast(res.getString(R.string.err_load_descr_failed)); + } - @Override - public void onNext(final Spanned description) { - if (StringUtils.isNotBlank(descriptionString)) { - try { - descriptionView.setText(description, TextView.BufferType.SPANNABLE); - } catch (final Exception e) { - // On 4.1, there is sometimes a crash on measuring the layout: https://code.google.com/p/android/issues/detail?id=35412 - Log.e("Android bug setting text: ", e); - // remove the formatting by converting to a simple string - descriptionView.setText(description.toString()); - } - descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - fixTextColor(descriptionString); - descriptionView.setVisibility(View.VISIBLE); - registerForContextMenu(descriptionView); + @Override + public void onNext(final Spanned description) { + if (StringUtils.isNotBlank(descriptionString)) { + try { + descriptionView.setText(description, TextView.BufferType.SPANNABLE); + } catch (final Exception e) { + // On 4.1, there is sometimes a crash on measuring the layout: https://code.google.com/p/android/issues/detail?id=35412 + Log.e("Android bug setting text: ", e); + // remove the formatting by converting to a simple string + descriptionView.setText(description.toString()); + } + descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); + fixTextColor(descriptionString); + descriptionView.setVisibility(View.VISIBLE); + registerForContextMenu(descriptionView); + } + } + + /** + * Handle caches with black font color in dark skin and white font color in light skin + * by changing background color of the view + * + * @param text + * to be checked + */ + private void fixTextColor(final String text) { + int backcolor; + if (Settings.isLightSkin()) { + backcolor = color.white; + + for (final Pattern pattern : LIGHT_COLOR_PATTERNS) { + final MatcherWrapper matcher = new MatcherWrapper(pattern, text); + if (matcher.find()) { + descriptionView.setBackgroundResource(color.darker_gray); + return; } } + } else { + backcolor = color.black; - /** - * Handle caches with black font color in dark skin and white font color in light skin - * by changing background color of the view - * - * @param text - * to be checked - */ - private void fixTextColor(final String text) { - int backcolor; - if (Settings.isLightSkin()) { - backcolor = color.white; - - for (final Pattern pattern : LIGHT_COLOR_PATTERNS) { - final MatcherWrapper matcher = new MatcherWrapper(pattern, text); - if (matcher.find()) { - descriptionView.setBackgroundResource(color.darker_gray); - return; - } - } - } else { - backcolor = color.black; - - for (final Pattern pattern : DARK_COLOR_PATTERNS) { - final MatcherWrapper matcher = new MatcherWrapper(pattern, text); - if (matcher.find()) { - descriptionView.setBackgroundResource(color.darker_gray); - return; - } - } + for (final Pattern pattern : DARK_COLOR_PATTERNS) { + final MatcherWrapper matcher = new MatcherWrapper(pattern, text); + if (matcher.find()) { + descriptionView.setBackgroundResource(color.darker_gray); + return; } - descriptionView.setBackgroundResource(backcolor); } - }); + } + descriptionView.setBackgroundResource(backcolor); + } + }); } private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ListView> { diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java index eda8420..09aee93 100644 --- a/main/src/cgeo/geocaching/CgeoApplication.java +++ b/main/src/cgeo/geocaching/CgeoApplication.java @@ -42,7 +42,7 @@ public class CgeoApplication extends Application { public synchronized Observable<IGeoData> geoDataObservable() { if (geoDataObservable == null) { - final ConnectableObservable<IGeoData> onDemand = GeoDataProvider.create(this).publish(); + final ConnectableObservable<IGeoData> onDemand = GeoDataProvider.create(this).replay(1); onDemand.subscribe(new Action1<IGeoData>() { @Override public void call(final IGeoData geoData) { @@ -56,7 +56,7 @@ public class CgeoApplication extends Application { public synchronized Observable<Float> directionObservable() { if (directionObservable == null) { - final ConnectableObservable<Float> onDemand = DirectionProvider.create(this).publish(); + final ConnectableObservable<Float> onDemand = DirectionProvider.create(this).replay(1); onDemand.subscribe(new Action1<Float>() { @Override public void call(final Float direction) { diff --git a/main/src/cgeo/geocaching/DataStore.java b/main/src/cgeo/geocaching/DataStore.java index f627d7d..ee6c9ef 100644 --- a/main/src/cgeo/geocaching/DataStore.java +++ b/main/src/cgeo/geocaching/DataStore.java @@ -20,16 +20,15 @@ import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.FileUtils; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; -import rx.android.observables.AndroidObservable; 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; @@ -393,7 +392,7 @@ 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); - AndroidObservable.bindActivity(fromActivity, Async.fromFunc0(new Func0<Boolean>() { + RxUtils.subscribeOnIOThenUI(Async.fromCallable(new Func0<Boolean>() { @Override public Boolean call() { if (!LocalStorage.isExternalStorageAvailable()) { @@ -418,7 +417,7 @@ public class DataStore { init(); return true; } - })).subscribeOn(Schedulers.io()).subscribe(new Action1<Boolean>() { + }), new Action1<Boolean>() { @Override public void call(final Boolean success) { dialog.dismiss(); diff --git a/main/src/cgeo/geocaching/Intents.java b/main/src/cgeo/geocaching/Intents.java index 5c969a1..a55c22a 100644 --- a/main/src/cgeo/geocaching/Intents.java +++ b/main/src/cgeo/geocaching/Intents.java @@ -33,4 +33,20 @@ public class Intents { private static final String PREFIX_ACTION = "cgeo.geocaching.intent.action."; public static final String ACTION_GEOCACHE = PREFIX_ACTION + "GEOCACHE"; public static final String ACTION_TRACKABLE = PREFIX_ACTION + "TRACKABLE"; + + private static final String PREFIX_OAUTH = "cgeo.geocaching.intent.oauth."; + public static final String EXTRA_OAUTH_HOST = PREFIX_OAUTH + "host"; + public static final String EXTRA_OAUTH_PATH_REQUEST = PREFIX_OAUTH + "request"; + public static final String EXTRA_OAUTH_PATH_AUTHORIZE = PREFIX_OAUTH + "authorize"; + public static final String EXTRA_OAUTH_PATH_ACCESS = PREFIX_OAUTH + "access"; + public static final String EXTRA_OAUTH_HTTPS = PREFIX_OAUTH + "https"; + public static final String EXTRA_OAUTH_CONSUMER_KEY = PREFIX_OAUTH + "ConsumerKey"; + public static final String EXTRA_OAUTH_CONSUMER_SECRET = PREFIX_OAUTH + "ConsumerSecret"; + public static final String EXTRA_OAUTH_CALLBACK = PREFIX_OAUTH + "callback"; + + public static final String EXTRA_OAUTH_TITLE_RES_ID = PREFIX_OAUTH + "titleresId"; + public static final String EXTRA_OAUTH_TEMP_TOKEN_KEY_PREF = PREFIX_OAUTH + "tempKeyPref"; + public static final String EXTRA_OAUTH_TEMP_TOKEN_SECRET_PREF = PREFIX_OAUTH + "tempSecretPref"; + public static final String EXTRA_OAUTH_TOKEN_PUBLIC_KEY = PREFIX_OAUTH + "publicTokenPref"; + public static final String EXTRA_OAUTH_TOKEN_SECRET_KEY = PREFIX_OAUTH + "secretTokenPref"; } diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java index 3295d04..b82614b 100644 --- a/main/src/cgeo/geocaching/MainActivity.java +++ b/main/src/cgeo/geocaching/MainActivity.java @@ -21,6 +21,7 @@ import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.DatabaseBackupUtils; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import cgeo.geocaching.utils.Version; import com.google.zxing.integration.android.IntentIntegrator; @@ -29,9 +30,7 @@ import org.apache.commons.lang3.StringUtils; import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; -import rx.android.observables.AndroidObservable; import rx.functions.Action1; -import rx.schedulers.Schedulers; import rx.subscriptions.Subscriptions; import android.app.AlertDialog; @@ -551,10 +550,9 @@ public class MainActivity extends AbstractActivity { subscriber.onError(e); } } - }).subscribeOn(Schedulers.io()); - AndroidObservable.bindActivity(MainActivity.this, address) - .onErrorResumeNext(Observable.from(geo.getCoords().toString())) - .subscribe(new Action1<String>() { + }); + RxUtils.subscribeOnIOThenUI(address.onErrorResumeNext(Observable.from(geo.getCoords().toString())), + new Action1<String>() { @Override public void call(final String address) { navLocation.setText(address); diff --git a/main/src/cgeo/geocaching/PocketQueryList.java b/main/src/cgeo/geocaching/PocketQueryList.java index e624808..e748b29 100644 --- a/main/src/cgeo/geocaching/PocketQueryList.java +++ b/main/src/cgeo/geocaching/PocketQueryList.java @@ -2,13 +2,12 @@ package cgeo.geocaching; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.connector.gc.GCParser; +import cgeo.geocaching.utils.RxUtils; import org.apache.commons.collections4.CollectionUtils; import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; -import rx.android.observables.AndroidObservable; -import rx.schedulers.Schedulers; import rx.functions.Action1; import android.app.Activity; @@ -46,13 +45,13 @@ public final class PocketQueryList { public static void promptForListSelection(final Activity activity, final Action1<PocketQueryList> runAfterwards) { final Dialog waitDialog = ProgressDialog.show(activity, activity.getString(R.string.search_pocket_title), activity.getString(R.string.search_pocket_loading), true, true); - AndroidObservable.bindActivity(activity, Observable.create(new OnSubscribe<List<PocketQueryList>>() { + RxUtils.subscribeOnIOThenUI(Observable.create(new OnSubscribe<List<PocketQueryList>>() { @Override public void call(final Subscriber<? super List<PocketQueryList>> subscriber) { subscriber.onNext(GCParser.searchPocketQueryList()); subscriber.onCompleted(); } - }).subscribeOn(Schedulers.io())).subscribe(new Action1<List<PocketQueryList>>() { + }), new Action1<List<PocketQueryList>>() { @Override public void call(final List<PocketQueryList> pocketQueryLists) { waitDialog.dismiss(); diff --git a/main/src/cgeo/geocaching/StatusFragment.java b/main/src/cgeo/geocaching/StatusFragment.java index 5229f1e..a59316f 100644 --- a/main/src/cgeo/geocaching/StatusFragment.java +++ b/main/src/cgeo/geocaching/StatusFragment.java @@ -3,9 +3,9 @@ package cgeo.geocaching; import cgeo.geocaching.network.StatusUpdater; import cgeo.geocaching.network.StatusUpdater.Status; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import rx.Subscription; -import rx.android.observables.AndroidObservable; import rx.functions.Action1; import android.content.Intent; @@ -30,7 +30,7 @@ public class StatusFragment extends Fragment { final ViewGroup statusGroup = (ViewGroup) inflater.inflate(R.layout.status, container, false); final ImageView statusIcon = (ImageView) statusGroup.findViewById(R.id.status_icon); final TextView statusMessage = (TextView) statusGroup.findViewById(R.id.status_message); - statusSubscription = AndroidObservable.bindFragment(this, StatusUpdater.latestStatus).subscribe(new Action1<Status>() { + statusSubscription = RxUtils.subscribeOnIOThenUI(StatusUpdater.latestStatus, new Action1<Status>() { @Override public void call(final Status status) { if (status == null) { diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java index 11f19f5..a14a397 100644 --- a/main/src/cgeo/geocaching/TrackableActivity.java +++ b/main/src/cgeo/geocaching/TrackableActivity.java @@ -20,12 +20,12 @@ import cgeo.geocaching.ui.UserNameClickListener; import cgeo.geocaching.ui.logs.TrackableLogsViewCreator; import cgeo.geocaching.utils.HtmlUtils; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import cgeo.geocaching.utils.UnknownTagsHandler; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; -import rx.android.observables.AndroidObservable; import rx.android.observables.ViewObservable; import rx.functions.Action1; @@ -524,14 +524,12 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } }); - AndroidObservable.bindActivity(TrackableActivity.this, - new HtmlImage(geocode, true, 0, false).fetchDrawable(trackable.getImage())) - .subscribe(new Action1<BitmapDrawable>() { - @Override - public void call(final BitmapDrawable bitmapDrawable) { - trackableImage.setImageDrawable(bitmapDrawable); - } - }); + RxUtils.subscribeThenUI(new HtmlImage(geocode, true, 0, false).fetchDrawable(trackable.getImage()), new Action1<BitmapDrawable>() { + @Override + public void call(final BitmapDrawable bitmapDrawable) { + trackableImage.setImageDrawable(bitmapDrawable); + } + }); imageView.addView(trackableImage); } diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index fd83043..1ed9b9b 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -4,10 +4,10 @@ import butterknife.ButterKnife; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; -import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.network.Cookies; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.ClipboardUtils; +import cgeo.geocaching.utils.EditUtils; import cgeo.geocaching.utils.HtmlUtils; import cgeo.geocaching.utils.TranslationUtils; @@ -86,11 +86,16 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst } protected static void disableSuggestions(final EditText edit) { - Compatibility.disableSuggestions(edit); + EditUtils.disableSuggestions(edit); } protected void restartActivity() { - Compatibility.restartActivity(this); + final Intent intent = getIntent(); + overridePendingTransition(0, 0); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + finish(); + overridePendingTransition(0, 0); + startActivity(intent); } @Override diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java deleted file mode 100644 index 1189ff5..0000000 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java +++ /dev/null @@ -1,41 +0,0 @@ -package cgeo.geocaching.compatibility; - -import cgeo.geocaching.utils.Log; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.backup.BackupManager; -import android.os.Environment; -import android.view.Surface; - -import java.io.File; - -@TargetApi(8) -public class AndroidLevel8 implements AndroidLevel8Interface { - - @Override - public void dataChanged(final String name) { - Log.i("Requesting settings backup with settings manager"); - BackupManager.dataChanged(name); - } - - @Override - public int getRotationOffset(final Activity activity) { - switch (activity.getWindowManager().getDefaultDisplay().getRotation()) { - case Surface.ROTATION_90: - return 90; - case Surface.ROTATION_180: - return 180; - case Surface.ROTATION_270: - return 270; - default: - return 0; - } - } - - @Override - public File getExternalPictureDir() { - return Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_PICTURES); - } -} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java deleted file mode 100644 index 6d5781f..0000000 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java +++ /dev/null @@ -1,38 +0,0 @@ -package cgeo.geocaching.compatibility; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Environment; -import android.view.Display; - -import java.io.File; - -@TargetApi(value = 7) -public class AndroidLevel8Emulation implements AndroidLevel8Interface { - - @Override - public void dataChanged(final String name) { - // do nothing - } - - @Override - public int getRotationOffset(Activity activity) { - final Display display = activity.getWindowManager().getDefaultDisplay(); - - // the non deprecated method is available in API 8+ only, so we cannot deal better with this - @SuppressWarnings("deprecation") - final int rotation = display.getOrientation(); - - if (rotation == Configuration.ORIENTATION_LANDSCAPE) { - return 90; - } - return 0; - } - - @Override - public File getExternalPictureDir() { - // Use externalStorage/Pictures as default - return new File(Environment.getExternalStorageDirectory(), "Pictures"); - } -} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java deleted file mode 100644 index 2ba3708..0000000 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java +++ /dev/null @@ -1,11 +0,0 @@ -package cgeo.geocaching.compatibility; - -import android.app.Activity; - -import java.io.File; - -public interface AndroidLevel8Interface { - public void dataChanged(final String name); - public int getRotationOffset(final Activity activity); - public File getExternalPictureDir(); -}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/compatibility/Compatibility.java b/main/src/cgeo/geocaching/compatibility/Compatibility.java index 31c9e31..a293cfd 100644 --- a/main/src/cgeo/geocaching/compatibility/Compatibility.java +++ b/main/src/cgeo/geocaching/compatibility/Compatibility.java @@ -1,89 +1,25 @@ package cgeo.geocaching.compatibility; -import cgeo.geocaching.activity.AbstractActivity; -import cgeo.geocaching.utils.AngleUtils; -import cgeo.geocaching.utils.Log; - -import org.apache.commons.lang3.reflect.MethodUtils; import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; -import android.content.Intent; import android.graphics.Point; import android.os.Build; -import android.text.InputType; -import android.widget.EditText; - -import java.io.File; public final class Compatibility { private final static int sdkVersion = Build.VERSION.SDK_INT; - private final static boolean isLevel8 = sdkVersion >= 8; - private final static boolean isLevel5 = sdkVersion >= 5; - private final static AndroidLevel8Interface level8; private final static AndroidLevel11Interface level11; private final static AndroidLevel13Interface level13; private final static AndroidLevel19Interface level19; static { - level8 = isLevel8 ? new AndroidLevel8() : new AndroidLevel8Emulation(); level11 = sdkVersion >= 11 ? new AndroidLevel11() : new AndroidLevel11Emulation(); level13 = sdkVersion >= 13 ? new AndroidLevel13() : new AndroidLevel13Emulation(); level19 = sdkVersion >= 19 ? new AndroidLevel19() : new AndroidLevel19Emulation(); } - /** - * Add 90, 180 or 270 degrees to the given rotation. - * - * @param directionNowPre - * the direction in degrees before adjustment - * @param activity - * the activity whose rotation is used to adjust the direction - * @return the adjusted direction, in the [0, 360[ range - */ - public static float getDirectionNow(final float directionNowPre, final Activity activity) { - return AngleUtils.normalize(directionNowPre + level8.getRotationOffset(activity)); - } - - public static void dataChanged(final String name) { - level8.dataChanged(name); - } - - public static void disableSuggestions(EditText edit) { - if (isLevel5) { - edit.setInputType(edit.getInputType() - | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS - | InputType.TYPE_TEXT_VARIATION_FILTER); - } - else { - edit.setInputType(edit.getInputType() - | InputType.TYPE_TEXT_VARIATION_FILTER); - } - } - - private static void overridePendingTransition(final Activity activity, int enterAnim, int exitAnim) { - try { - MethodUtils.invokeMethod(activity, "overridePendingTransition", enterAnim, exitAnim); - } catch (Exception e) { - Log.e("cannot call overridePendingTransition", e); - } - } - - public static void restartActivity(AbstractActivity activity) { - final Intent intent = activity.getIntent(); - if (isLevel5) { - overridePendingTransition(activity, 0, 0); - intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - } - activity.finish(); - if (isLevel5) { - overridePendingTransition(activity, 0, 0); - } - activity.startActivity(intent); - } - public static void invalidateOptionsMenu(final Activity activity) { level11.invalidateOptionsMenu(activity); } @@ -96,10 +32,6 @@ public final class Compatibility { return level13.getDisplaySize(); } - public static File getExternalPictureDir() { - return level8.getExternalPictureDir(); - } - public static void importGpxFromStorageAccessFramework(final @NonNull Activity activity, int requestCodeImportGpx) { level19.importGpxFromStorageAccessFramework(activity, requestCodeImportGpx); } diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java index 35eae81..1f23df8 100644 --- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java +++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java @@ -50,11 +50,18 @@ public final class ConnectorFactory { new OCConnector("OpenCaching.IT", "www.opencaching.it", "OC"), new OCConnector("OpenCaching.JP", "www.opencaching.jp", "OJ"), new OCConnector("OpenCaching.NO/SE", "www.opencaching.se", "OS"), - new OCApiConnector("OpenCaching.NL", "www.opencaching.nl", "OB", "PdzU8jzIlcfMADXaYN8j", "CC BY-SA 3.0", ApiSupport.current), + new OCApiLiveConnector("opencaching.nl", "www.opencaching.nl", "OB", "CC BY-SA 3.0", + R.string.oc_nl_okapi_consumer_key, R.string.oc_nl_okapi_consumer_secret, + R.string.pref_connectorOCNLActive, R.string.pref_ocnl_tokenpublic, R.string.pref_ocnl_tokensecret, ApiSupport.current), new OCApiLiveConnector("opencaching.pl", "www.opencaching.pl", "OP", "CC BY-SA 3.0", R.string.oc_pl_okapi_consumer_key, R.string.oc_pl_okapi_consumer_secret, R.string.pref_connectorOCPLActive, R.string.pref_ocpl_tokenpublic, R.string.pref_ocpl_tokensecret, ApiSupport.current), - new OCApiConnector("OpenCaching.US", "www.opencaching.us", "OU", "pTsYAYSXFcfcRQnYE6uA", "CC BY-NC-SA 2.5", ApiSupport.current), + new OCApiLiveConnector("opencaching.us", "www.opencaching.us", "OU", "CC BY-NC-SA 2.5", + R.string.oc_us_okapi_consumer_key, R.string.oc_us_okapi_consumer_secret, + R.string.pref_connectorOCUSActive, R.string.pref_ocus_tokenpublic, R.string.pref_ocus_tokensecret, ApiSupport.current), + new OCApiLiveConnector("opencaching.ro", "www.opencaching.ro", "OR", "CC BY-SA 3.0", + R.string.oc_ro_okapi_consumer_key, R.string.oc_ro_okapi_consumer_secret, + R.string.pref_connectorOCROActive, R.string.pref_ocro_tokenpublic, R.string.pref_ocro_tokensecret, ApiSupport.current), new OXConnector(), new GeocachingAustraliaConnector(), new GeopeitusConnector(), diff --git a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java index 934cc88..280069f 100644 --- a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java +++ b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java @@ -4,12 +4,10 @@ import cgeo.geocaching.R; import cgeo.geocaching.loaders.RecaptchaReceiver; import cgeo.geocaching.network.Network; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import org.apache.commons.io.IOUtils; - import rx.Observable; -import rx.android.observables.AndroidObservable; -import rx.schedulers.Schedulers; import rx.functions.Action1; import rx.functions.Func0; @@ -39,17 +37,36 @@ public class RecaptchaHandler extends Handler { } private void loadChallenge(final ImageView imageView, final View reloadButton) { - getCaptcha().subscribe(new Action1<Bitmap>() { + final Observable<Bitmap> captcha = Observable.defer(new Func0<Observable<? extends Bitmap>>() { + @Override + public Observable<? extends Bitmap> call() { + final String url = "http://www.google.com/recaptcha/api/image?c=" + recaptchaReceiver.getChallenge(); + final InputStream is = Network.getResponseStream(Network.getRequest(url)); + if (is != null) { + try { + final Bitmap img = BitmapFactory.decodeStream(is); + return Observable.from(img); + } catch (final Exception e) { + Log.e("RecaptchaHandler.getCaptcha", e); + return Observable.error(e); + } finally { + IOUtils.closeQuietly(is); + } + } + return Observable.empty(); + } + }); + RxUtils.subscribeOnIOThenUI(captcha, new Action1<Bitmap>() { @Override public void call(final Bitmap bitmap) { imageView.setImageBitmap(bitmap); } }, new Action1<Throwable>() { - @Override - public void call(final Throwable throwable) { - // Do nothing - } - }); + @Override + public void call(final Throwable throwable) { + // Do nothing + } + }); reloadButton.setEnabled(true); } @@ -88,27 +105,4 @@ public class RecaptchaHandler extends Handler { } } - private Observable<Bitmap> getCaptcha() { - return AndroidObservable.bindActivity(activity, - Observable.defer(new Func0<Observable<? extends Bitmap>>() { - @Override - public Observable<? extends Bitmap> call() { - final String url = "http://www.google.com/recaptcha/api/image?c=" + recaptchaReceiver.getChallenge(); - final InputStream is = Network.getResponseStream(Network.getRequest(url)); - if (is != null) { - try { - final Bitmap img = BitmapFactory.decodeStream(is); - return Observable.from(img); - } catch (final Exception e) { - Log.e("RecaptchaHandler.getCaptcha", e); - return Observable.error(e); - } finally { - IOUtils.closeQuietly(is); - } - } - return Observable.empty(); - } - }).subscribeOn(Schedulers.io())); - } - } diff --git a/main/src/cgeo/geocaching/connector/oc/OCAuthParams.java b/main/src/cgeo/geocaching/connector/oc/OCAuthParams.java new file mode 100644 index 0000000..131ddad --- /dev/null +++ b/main/src/cgeo/geocaching/connector/oc/OCAuthParams.java @@ -0,0 +1,70 @@ +package cgeo.geocaching.connector.oc; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.Intents; +import cgeo.geocaching.R; +import cgeo.geocaching.network.OAuthAuthorizationActivity.OAuthParameters; + +import org.eclipse.jdt.annotation.NonNull; + +import android.content.Intent; + +public class OCAuthParams extends OAuthParameters { + + public static final OCAuthParams OC_DE_AUTH_PARAMS = new OCAuthParams("www.opencaching.de", false, + R.string.oc_de_okapi_consumer_key, R.string.oc_de_okapi_consumer_secret, "callback://www.cgeo.org/opencaching.de/", + R.string.auth_ocde, R.string.pref_ocde_tokenpublic, R.string.pref_ocde_tokensecret, R.string.pref_temp_ocde_token_public, R.string.pref_temp_ocde_token_secret); + + public static final OCAuthParams OC_NL_AUTH_PARAMS = new OCAuthParams("www.opencaching.nl", false, + R.string.oc_nl_okapi_consumer_key, R.string.oc_nl_okapi_consumer_secret, "callback://www.cgeo.org/opencaching.nl/", + R.string.auth_ocnl, R.string.pref_ocnl_tokenpublic, R.string.pref_ocnl_tokensecret, R.string.pref_temp_ocnl_token_public, R.string.pref_temp_ocnl_token_secret); + + public static final OCAuthParams OC_PL_AUTH_PARAMS = new OCAuthParams("www.opencaching.pl", false, + R.string.oc_pl_okapi_consumer_key, R.string.oc_pl_okapi_consumer_secret, "callback://www.cgeo.org/opencaching.pl/", + R.string.auth_ocpl, R.string.pref_ocpl_tokenpublic, R.string.pref_ocpl_tokensecret, R.string.pref_temp_ocpl_token_public, R.string.pref_temp_ocpl_token_secret); + + public static final OCAuthParams OC_US_AUTH_PARAMS = new OCAuthParams("www.opencaching.us", false, + R.string.oc_us_okapi_consumer_key, R.string.oc_us_okapi_consumer_secret, "callback://www.cgeo.org/opencaching.us/", + R.string.auth_ocus, R.string.pref_ocus_tokenpublic, R.string.pref_ocus_tokensecret, R.string.pref_temp_ocus_token_public, R.string.pref_temp_ocus_token_secret); + + public static final OCAuthParams OC_RO_AUTH_PARAMS = new OCAuthParams("www.opencaching.ro", false, + R.string.oc_ro_okapi_consumer_key, R.string.oc_ro_okapi_consumer_secret, "callback://www.cgeo.org/opencaching.ro/", + R.string.auth_ocro, R.string.pref_ocro_tokenpublic, R.string.pref_ocro_tokensecret, R.string.pref_temp_ocro_token_public, R.string.pref_temp_ocro_token_secret); + + public final int authTitleResId; + public final int tokenPublicPrefKey; + public final int tokenSecretPrefKey; + public final int tempTokenPublicPrefKey; + public final int tempTokenSecretPrefKey; + + public OCAuthParams(@NonNull String host, boolean https, int consumerKeyResId, int consumerSecretResId, @NonNull String callback, + int authTitleResId, int tokenPublicPrefKey, int tokenSecretPrefKey, int tempTokePublicPrefKey, int tempTokenSecretPrefKey) { + super(host, "/okapi/services/oauth/request_token", + "/okapi/services/oauth/authorize", + "/okapi/services/oauth/access_token", + https, + CgeoApplication.getInstance().getString(consumerKeyResId), + CgeoApplication.getInstance().getString(consumerSecretResId), + callback); + this.authTitleResId = authTitleResId; + this.tokenPublicPrefKey = tokenPublicPrefKey; + this.tokenSecretPrefKey = tokenSecretPrefKey; + this.tempTokenPublicPrefKey = tempTokePublicPrefKey; + this.tempTokenSecretPrefKey = tempTokenSecretPrefKey; + } + + @Override + public void setOAuthExtras(Intent intent) { + super.setOAuthExtras(intent); + + if (intent != null) { + intent.putExtra(Intents.EXTRA_OAUTH_TITLE_RES_ID, authTitleResId); + intent.putExtra(Intents.EXTRA_OAUTH_TOKEN_PUBLIC_KEY, tokenPublicPrefKey); + intent.putExtra(Intents.EXTRA_OAUTH_TOKEN_SECRET_KEY, tokenSecretPrefKey); + intent.putExtra(Intents.EXTRA_OAUTH_TEMP_TOKEN_KEY_PREF, tempTokenPublicPrefKey); + intent.putExtra(Intents.EXTRA_OAUTH_TEMP_TOKEN_SECRET_PREF, tempTokenSecretPrefKey); + } + } + + +} diff --git a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java index 19f4447..eb7e7a1 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java @@ -1,6 +1,6 @@ package cgeo.geocaching.connector.oc; -import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.Intents; import cgeo.geocaching.R; import cgeo.geocaching.connector.oc.OkapiError.OkapiErrors; import cgeo.geocaching.network.OAuthAuthorizationActivity; @@ -12,43 +12,51 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.eclipse.jdt.annotation.Nullable; -public abstract class OCAuthorizationActivity extends OAuthAuthorizationActivity { +import android.os.Bundle; - final IOCAuthParams authParams; +public class OCAuthorizationActivity extends OAuthAuthorizationActivity { - public OCAuthorizationActivity(IOCAuthParams authParams) { - super(authParams.getSite(), - "/okapi/services/oauth/request_token", - "/okapi/services/oauth/authorize", - "/okapi/services/oauth/access_token", - false, - CgeoApplication.getInstance().getResources().getString(authParams.getCKResId()), - CgeoApplication.getInstance().getResources().getString(authParams.getCSResId()), - authParams.getCallbackUri()); - this.authParams = authParams; + private int titleResId; + private int tokenPublicPrefKey; + private int tokenSecretPrefKey; + private int tempTokenPublicPrefKey; + private int tempTokenSecretPrefKey; + + @Override + public void onCreate(Bundle savedInstanceState) { + + Bundle extras = getIntent().getExtras(); + if (extras != null) { + titleResId = extras.getInt(Intents.EXTRA_OAUTH_TITLE_RES_ID); + tokenPublicPrefKey = extras.getInt(Intents.EXTRA_OAUTH_TOKEN_PUBLIC_KEY); + tokenSecretPrefKey = extras.getInt(Intents.EXTRA_OAUTH_TOKEN_SECRET_KEY); + tempTokenPublicPrefKey = extras.getInt(Intents.EXTRA_OAUTH_TEMP_TOKEN_KEY_PREF); + tempTokenSecretPrefKey = extras.getInt(Intents.EXTRA_OAUTH_TEMP_TOKEN_SECRET_PREF); + } + super.onCreate(savedInstanceState); } @Override protected ImmutablePair<String, String> getTempTokens() { - return Settings.getTokenPair(authParams.getTempTokenPublicPrefKey(), authParams.getTempTokenSecretPrefKey()); + return Settings.getTokenPair(tempTokenPublicPrefKey, tempTokenSecretPrefKey); } @Override protected void setTempTokens(@Nullable final String tokenPublic, @Nullable final String tokenSecret) { - Settings.setTokens(authParams.getTempTokenPublicPrefKey(), tokenPublic, authParams.getTempTokenSecretPrefKey(), tokenSecret); + Settings.setTokens(tempTokenPublicPrefKey, tokenPublic, tempTokenSecretPrefKey, tokenSecret); } @Override protected void setTokens(@Nullable final String tokenPublic, @Nullable final String tokenSecret, final boolean enable) { - Settings.setTokens(authParams.getTokenPublicPrefKey(), tokenPublic, authParams.getTokenSecretPrefKey(), tokenSecret); + Settings.setTokens(tokenPublicPrefKey, tokenPublic, tokenSecretPrefKey, tokenSecret); if (tokenPublic != null) { - Settings.setTokens(authParams.getTempTokenPublicPrefKey(), null, authParams.getTempTokenSecretPrefKey(), null); + Settings.setTokens(tempTokenPublicPrefKey, null, tempTokenSecretPrefKey, null); } } @Override protected String getAuthTitle() { - return res.getString(authParams.getAuthTitleResId()); + return res.getString(titleResId); } @Override @@ -67,5 +75,4 @@ public abstract class OCAuthorizationActivity extends OAuthAuthorizationActivity } return StringUtils.EMPTY; } - } diff --git a/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java b/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java deleted file mode 100644 index 17c1cb8..0000000 --- a/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java +++ /dev/null @@ -1,51 +0,0 @@ -package cgeo.geocaching.connector.oc; - -import cgeo.geocaching.R; - -public class OCDEAuthParams implements IOCAuthParams { - - @Override - public String getSite() { - return "www.opencaching.de"; - } - - @Override - public int getCKResId() { - return R.string.oc_de_okapi_consumer_key; - } - - @Override - public int getCSResId() { - return R.string.oc_de_okapi_consumer_secret; - } - - @Override - public int getAuthTitleResId() { - return R.string.auth_ocde; - } - - @Override - public int getTokenPublicPrefKey() { - return R.string.pref_ocde_tokenpublic; - } - - @Override - public int getTokenSecretPrefKey() { - return R.string.pref_ocde_tokensecret; - } - - @Override - public int getTempTokenPublicPrefKey() { - return R.string.pref_temp_ocde_token_public; - } - - @Override - public int getTempTokenSecretPrefKey() { - return R.string.pref_temp_ocde_token_secret; - } - - @Override - public String getCallbackUri() { - return "callback://www.cgeo.org/opencaching.de/"; - } -} diff --git a/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java deleted file mode 100644 index 1d2aa49..0000000 --- a/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java +++ /dev/null @@ -1,8 +0,0 @@ -package cgeo.geocaching.connector.oc; - -public final class OCDEAuthorizationActivity extends OCAuthorizationActivity { - - public OCDEAuthorizationActivity() { - super(new OCDEAuthParams()); - } -} diff --git a/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java b/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java deleted file mode 100644 index dfe03e5..0000000 --- a/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java +++ /dev/null @@ -1,51 +0,0 @@ -package cgeo.geocaching.connector.oc; - -import cgeo.geocaching.R; - -public class OCPLAuthParams implements IOCAuthParams { - - @Override - public String getSite() { - return "www.opencaching.pl"; - } - - @Override - public int getCKResId() { - return R.string.oc_pl_okapi_consumer_key; - } - - @Override - public int getCSResId() { - return R.string.oc_pl_okapi_consumer_secret; - } - - @Override - public int getAuthTitleResId() { - return R.string.auth_ocpl; - } - - @Override - public int getTokenPublicPrefKey() { - return R.string.pref_ocpl_tokenpublic; - } - - @Override - public int getTokenSecretPrefKey() { - return R.string.pref_ocpl_tokensecret; - } - - @Override - public int getTempTokenPublicPrefKey() { - return R.string.pref_temp_ocpl_token_public; - } - - @Override - public int getTempTokenSecretPrefKey() { - return R.string.pref_temp_ocpl_token_secret; - } - - @Override - public String getCallbackUri() { - return "callback://www.cgeo.org/opencaching.pl/"; - } -} diff --git a/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java deleted file mode 100644 index 30ea150..0000000 --- a/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java +++ /dev/null @@ -1,8 +0,0 @@ -package cgeo.geocaching.connector.oc; - -public final class OCPLAuthorizationActivity extends OCAuthorizationActivity { - - public OCPLAuthorizationActivity() { - super(new OCPLAuthParams()); - } -} diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index 5d713eb..bde85ee 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -10,6 +10,7 @@ import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.FileUtils; import cgeo.geocaching.utils.ImageUtils; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import ch.boye.httpclientandroidlib.HttpResponse; import ch.boye.httpclientandroidlib.androidextra.Base64; @@ -127,9 +128,8 @@ public class HtmlImage implements Html.ImageGetter { return drawable.toBlockingObservable().lastOrDefault(null); } - // Caches are loaded from disk on Schedulers.computation() to avoid using more threads than processors - // on the phone while decoding the image. Downloads happen on downloadScheduler, in parallel with image - // decoding. + // Caches are loaded from disk on a computation scheduler to avoid using more threads than cores while decoding + // the image. Downloads happen on downloadScheduler, in parallel with image decoding. public Observable<BitmapDrawable> fetchDrawable(final String url) { if (StringUtils.isBlank(url) || ImageUtils.containsPattern(url, BLOCKED)) { @@ -143,7 +143,7 @@ public class HtmlImage implements Html.ImageGetter { @Override public void call(final Subscriber<? super BitmapDrawable> subscriber) { subscription.add(subscriber); - subscriber.add(Schedulers.computation().schedule(new Action1<Inner>() { + subscriber.add(RxUtils.computationScheduler.schedule(new Action1<Inner>() { @Override public void call(final Inner inner) { final Pair<BitmapDrawable, Boolean> loaded = loadFromDisk(); @@ -195,7 +195,7 @@ public class HtmlImage implements Html.ImageGetter { if (onlySave) { subscriber.onCompleted(); } else { - Schedulers.computation().schedule(new Action1<Inner>() { + RxUtils.computationScheduler.schedule(new Action1<Inner>() { @Override public void call(final Inner inner) { final Pair<BitmapDrawable, Boolean> loaded = loadFromDisk(); diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java index a5a2383..e74751b 100644 --- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java @@ -2,8 +2,10 @@ package cgeo.geocaching.network; import butterknife.InjectView; +import cgeo.geocaching.Intents; import cgeo.geocaching.R; import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.utils.BundleUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MatcherWrapper; @@ -39,14 +41,14 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { private static final int STATUS_SUCCESS = 1; private static final int STATUS_ERROR_EXT_MSG = 2; - @NonNull final private String host; - @NonNull final private String pathRequest; - @NonNull final private String pathAuthorize; - @NonNull final private String pathAccess; - private final boolean https; - @NonNull final private String consumerKey; - @NonNull final private String consumerSecret; - @NonNull final private String callback; + @NonNull private String host = StringUtils.EMPTY; + @NonNull private String pathRequest = StringUtils.EMPTY; + @NonNull private String pathAuthorize = StringUtils.EMPTY; + @NonNull private String pathAccess = StringUtils.EMPTY; + private boolean https = false; + @NonNull private String consumerKey = StringUtils.EMPTY; + @NonNull private String consumerSecret = StringUtils.EMPTY; + @NonNull private String callback = StringUtils.EMPTY; private String OAtoken = null; private String OAtokenSecret = null; private final Pattern paramsPattern1 = Pattern.compile("oauth_token=([a-zA-Z0-9\\-\\_.]+)"); @@ -56,6 +58,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { @InjectView(R.id.auth_2) protected TextView auth_2; private ProgressDialog requestTokenDialog = null; private ProgressDialog changeTokensDialog = null; + private Handler requestTokenHandler = new Handler() { @Override @@ -81,6 +84,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { } }; + private Handler changeTokensHandler = new Handler() { @Override @@ -100,29 +104,22 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { } }; - public OAuthAuthorizationActivity - (@NonNull String host, - @NonNull String pathRequest, - @NonNull String pathAuthorize, - @NonNull String pathAccess, - boolean https, - @NonNull String consumerKey, - @NonNull String consumerSecret, - @NonNull String callback) { - this.host = host; - this.pathRequest = pathRequest; - this.pathAuthorize = pathAuthorize; - this.pathAccess = pathAccess; - this.https = https; - this.consumerKey = consumerKey; - this.consumerSecret = consumerSecret; - this.callback = callback; - } - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.authorization_activity, true); + Bundle extras = getIntent().getExtras(); + if (extras != null) { + host = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_HOST, host); + pathRequest = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_PATH_REQUEST, pathRequest); + pathAuthorize = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_PATH_AUTHORIZE, pathAuthorize); + pathAccess = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_PATH_ACCESS, pathAccess); + https = extras.getBoolean(Intents.EXTRA_OAUTH_HTTPS, https); + consumerKey = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_CONSUMER_KEY, consumerKey); + consumerSecret = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_CONSUMER_SECRET, consumerSecret); + callback = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_CALLBACK, callback); + } + setTitle(getAuthTitle()); auth_1.setText(getAuthExplainShort()); @@ -355,4 +352,47 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { protected String getAuthAuthorize() { return res.getString(R.string.auth_authorize, getAuthTitle()); } + + public static class OAuthParameters { + @NonNull public final String host; + @NonNull public final String pathRequest; + @NonNull public final String pathAuthorize; + @NonNull public final String pathAccess; + public final boolean https; + @NonNull public final String consumerKey; + @NonNull public final String consumerSecret; + @NonNull public final String callback; + + public OAuthParameters(@NonNull String host, + @NonNull String pathRequest, + @NonNull String pathAuthorize, + @NonNull String pathAccess, + boolean https, + @NonNull String consumerKey, + @NonNull String consumerSecret, + @NonNull String callback) { + this.host = host; + this.pathRequest = pathRequest; + this.pathAuthorize = pathAuthorize; + this.pathAccess = pathAccess; + this.https = https; + this.consumerKey = consumerKey; + this.consumerSecret = consumerSecret; + this.callback = callback; + } + + public void setOAuthExtras(Intent intent) { + if (intent != null) { + intent.putExtra(Intents.EXTRA_OAUTH_HOST, host); + intent.putExtra(Intents.EXTRA_OAUTH_PATH_REQUEST, pathRequest); + intent.putExtra(Intents.EXTRA_OAUTH_PATH_AUTHORIZE, pathAuthorize); + intent.putExtra(Intents.EXTRA_OAUTH_PATH_ACCESS, pathAccess); + intent.putExtra(Intents.EXTRA_OAUTH_HTTPS, https); + intent.putExtra(Intents.EXTRA_OAUTH_CONSUMER_KEY, consumerKey); + intent.putExtra(Intents.EXTRA_OAUTH_CONSUMER_SECRET, consumerSecret); + intent.putExtra(Intents.EXTRA_OAUTH_CALLBACK, callback); + } + } + + } } diff --git a/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java b/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java index 885ed48..45559f4 100644 --- a/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java +++ b/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java @@ -1,7 +1,6 @@ package cgeo.geocaching.search; import org.apache.commons.lang3.StringUtils; - import rx.functions.Func1; import android.content.Context; @@ -36,7 +35,7 @@ public class AutoCompleteAdapter extends ArrayAdapter<String> { @Override public Filter getFilter() { - Filter filter = new Filter() { + return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { @@ -67,6 +66,5 @@ public class AutoCompleteAdapter extends ArrayAdapter<String> { } } }; - return filter; } }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/sensors/DirectionProvider.java b/main/src/cgeo/geocaching/sensors/DirectionProvider.java index 4f11a35..788d5bd 100644 --- a/main/src/cgeo/geocaching/sensors/DirectionProvider.java +++ b/main/src/cgeo/geocaching/sensors/DirectionProvider.java @@ -28,8 +28,8 @@ public class DirectionProvider { static class Listener implements SensorEventListener, StartableHandlerThread.Callback { private int count = 0; - private SensorManager sensorManager; + private SensorManager sensorManager; @Override public void onSensorChanged(final SensorEvent event) { subject.onNext(event.values[0]); @@ -71,10 +71,10 @@ public class DirectionProvider { private static final StartableHandlerThread handlerThread = new StartableHandlerThread("DirectionProvider thread", Process.THREAD_PRIORITY_BACKGROUND, new Listener()); + static { handlerThread.start(); } - static public Observable<Float> create(final Context context) { return Observable.create(new OnSubscribe<Float>() { @Override diff --git a/main/src/cgeo/geocaching/sensors/GeoDirHandler.java b/main/src/cgeo/geocaching/sensors/GeoDirHandler.java index dd61cb1..c10cb48 100644 --- a/main/src/cgeo/geocaching/sensors/GeoDirHandler.java +++ b/main/src/cgeo/geocaching/sensors/GeoDirHandler.java @@ -16,7 +16,7 @@ import rx.subscriptions.CompositeSubscription; * GeoData and Direction handler. * <p> * To use this class, override {@link #updateGeoDir(IGeoData, float)}. You need to start the handler using - * {@link #start()}. A good place to do so might be the {@code onResume} method of the Activity. Stop the Handler + * {@link #start(int)}. A good place to do so might be the {@code onResume} method of the Activity. Stop the Handler * accordingly in {@code onPause}. * * The direction is always relative to the top of the device (natural direction), and that it must diff --git a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java index 8a9d1c7..298270b 100644 --- a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java +++ b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java @@ -5,13 +5,12 @@ import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.network.Cookies; import cgeo.geocaching.ui.dialog.Dialogs; +import cgeo.geocaching.utils.RxUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; -import rx.android.observables.AndroidObservable; import rx.functions.Action1; import rx.functions.Func0; -import rx.schedulers.Schedulers; import rx.util.async.Async; import android.app.ProgressDialog; @@ -38,7 +37,7 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab protected abstract ImmutablePair<String, String> getCredentials(); - protected abstract ImmutablePair<StatusCode, Drawable> login(); + protected abstract ImmutablePair<StatusCode, ? extends Drawable> login(); private class LoginCheckClickListener implements OnPreferenceClickListener { final private SettingsActivity activity; @@ -65,14 +64,14 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab loginDialog.setCancelable(false); Cookies.clearCookies(); - AndroidObservable.bindActivity(activity, Async.start(new Func0<ImmutablePair<StatusCode, Drawable>>() { + RxUtils.subscribeOnIOThenUI(Async.start(new Func0<ImmutablePair<StatusCode, ? extends Drawable>>() { @Override - public ImmutablePair<StatusCode, Drawable> call() { + public ImmutablePair<StatusCode, ? extends Drawable> call() { return login(); } - }, Schedulers.io())).subscribe(new Action1<ImmutablePair<StatusCode, Drawable>>() { + }), new Action1<ImmutablePair<StatusCode, ? extends Drawable>>() { @Override - public void call(final ImmutablePair<StatusCode, Drawable> loginInfo) { + public void call(final ImmutablePair<StatusCode, ? extends Drawable> loginInfo) { loginDialog.dismiss(); if (loginInfo.getLeft() == StatusCode.NO_ERROR) { Dialogs.message(activity, R.string.init_login_popup, R.string.init_login_popup_ok, loginInfo.getRight()); @@ -81,7 +80,8 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab res.getString(R.string.init_login_popup_failed_reason) + " " + loginInfo.getLeft().getErrorString(res) - + "."); + + "." + ); } activity.initBasicMemberPreferences(); } diff --git a/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java b/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java index 8257fdd..2a05f47 100644 --- a/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java +++ b/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java @@ -25,14 +25,14 @@ public class CheckGcCredentialsPreference extends AbstractCheckCredentialsPrefer } @Override - protected ImmutablePair<StatusCode, Drawable> login() { + protected ImmutablePair<StatusCode, ? extends Drawable> login() { final StatusCode loginResult = GCLogin.getInstance().login(); switch (loginResult) { case NO_ERROR: GCLogin.detectGcCustomDate(); - return new ImmutablePair<StatusCode, Drawable>(StatusCode.NO_ERROR, GCLogin.getInstance().downloadAvatarAndGetMemberStatus()); + return ImmutablePair.of(StatusCode.NO_ERROR, GCLogin.getInstance().downloadAvatarAndGetMemberStatus()); default: - return new ImmutablePair<StatusCode, Drawable>(loginResult, null); + return ImmutablePair.of(loginResult, null); } } } diff --git a/main/src/cgeo/geocaching/settings/OAuthPreference.java b/main/src/cgeo/geocaching/settings/OAuthPreference.java index df77197..477af3f 100644 --- a/main/src/cgeo/geocaching/settings/OAuthPreference.java +++ b/main/src/cgeo/geocaching/settings/OAuthPreference.java @@ -2,8 +2,9 @@ package cgeo.geocaching.settings; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; -import cgeo.geocaching.connector.oc.OCDEAuthorizationActivity; -import cgeo.geocaching.connector.oc.OCPLAuthorizationActivity; +import cgeo.geocaching.connector.oc.OCAuthParams; +import cgeo.geocaching.connector.oc.OCAuthorizationActivity; +import cgeo.geocaching.network.OAuthAuthorizationActivity.OAuthParameters; import cgeo.geocaching.twitter.TwitterAuthorizationActivity; import android.content.Context; @@ -16,17 +17,22 @@ public class OAuthPreference extends AbstractClickablePreference { private static final int NO_KEY = -1; private enum OAuthActivityMapping { - NONE(NO_KEY, null), - OCDE(R.string.pref_fakekey_ocde_authorization, OCDEAuthorizationActivity.class), - OCPL(R.string.pref_fakekey_ocpl_authorization, OCPLAuthorizationActivity.class), - TWITTER(R.string.pref_fakekey_twitter_authorization, TwitterAuthorizationActivity.class); + NONE(NO_KEY, null, null), + OCDE(R.string.pref_fakekey_ocde_authorization, OCAuthorizationActivity.class, OCAuthParams.OC_DE_AUTH_PARAMS), + OCPL(R.string.pref_fakekey_ocpl_authorization, OCAuthorizationActivity.class, OCAuthParams.OC_PL_AUTH_PARAMS), + OCNL(R.string.pref_fakekey_ocnl_authorization, OCAuthorizationActivity.class, OCAuthParams.OC_NL_AUTH_PARAMS), + OCUS(R.string.pref_fakekey_ocus_authorization, OCAuthorizationActivity.class, OCAuthParams.OC_US_AUTH_PARAMS), + OCRO(R.string.pref_fakekey_ocro_authorization, OCAuthorizationActivity.class, OCAuthParams.OC_RO_AUTH_PARAMS), + TWITTER(R.string.pref_fakekey_twitter_authorization, TwitterAuthorizationActivity.class, TwitterAuthorizationActivity.TWITTER_OAUTH_PARAMS); public final int prefKeyId; public final Class<?> authActivity; + public final OAuthParameters authParams; - OAuthActivityMapping(int prefKeyId, Class<?> clazz) { + OAuthActivityMapping(int prefKeyId, Class<?> authActivity, OAuthParameters authParams) { this.prefKeyId = prefKeyId; - this.authActivity = clazz; + this.authActivity = authActivity; + this.authParams = authParams; } } @@ -58,9 +64,10 @@ public class OAuthPreference extends AbstractClickablePreference { return new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - if (oAuthMapping.authActivity != null) { + if (oAuthMapping.authActivity != null && oAuthMapping.authParams != null) { Intent authIntent = new Intent(preference.getContext(), oAuthMapping.authActivity); + oAuthMapping.authParams.setOAuthExtras(authIntent); activity.startActivityForResult(authIntent, oAuthMapping.prefKeyId); } diff --git a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java index 49239bc..1b18438 100644 --- a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java +++ b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java @@ -6,14 +6,13 @@ import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import ch.boye.httpclientandroidlib.HttpResponse; import org.apache.commons.lang3.StringUtils; import rx.Observable; -import rx.android.observables.AndroidObservable; import rx.functions.Action1; import rx.functions.Func0; -import rx.schedulers.Schedulers; import android.app.ProgressDialog; import android.content.Context; @@ -53,30 +52,29 @@ public class RegisterSend2CgeoPreference extends AbstractClickablePreference { activity.getString(R.string.init_sendToCgeo_registering), true); progressDialog.setCancelable(false); - AndroidObservable.bindActivity(activity, - Observable.defer(new Func0<Observable<Integer>>() { - @Override - public Observable<Integer> call() { - final String nam = StringUtils.defaultString(deviceName); - final String cod = StringUtils.defaultString(deviceCode); - - final Parameters params = new Parameters("name", nam, "code", cod); - HttpResponse response = Network.getRequest("http://send2.cgeo.org/auth.html", params); - - if (response != null && response.getStatusLine().getStatusCode() == 200) { - //response was OK - final String[] strings = StringUtils.split(Network.getResponseData(response), ','); - Settings.setWebNameCode(nam, strings[0]); - try { - return Observable.from(Integer.parseInt(strings[1].trim())); - } catch (final Exception e) { - Log.e("RegisterSend2CgeoPreference", e); - } - } - - return Observable.empty(); + RxUtils.subscribeOnIOThenUI(Observable.defer(new Func0<Observable<Integer>>() { + @Override + public Observable<Integer> call() { + final String nam = StringUtils.defaultString(deviceName); + final String cod = StringUtils.defaultString(deviceCode); + + final Parameters params = new Parameters("name", nam, "code", cod); + HttpResponse response = Network.getRequest("http://send2.cgeo.org/auth.html", params); + + if (response != null && response.getStatusLine().getStatusCode() == 200) { + //response was OK + final String[] strings = StringUtils.split(Network.getResponseData(response), ','); + Settings.setWebNameCode(nam, strings[0]); + try { + return Observable.from(Integer.parseInt(strings[1].trim())); + } catch (final Exception e) { + Log.e("RegisterSend2CgeoPreference", e); } - }).firstOrDefault(0).subscribeOn(Schedulers.io())).subscribe(new Action1<Integer>() { + } + + return Observable.empty(); + } + }).firstOrDefault(0), new Action1<Integer>() { @Override public void call(final Integer pin) { progressDialog.dismiss(); diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java index 6c3c984..59140ba 100644 --- a/main/src/cgeo/geocaching/settings/Settings.java +++ b/main/src/cgeo/geocaching/settings/Settings.java @@ -462,7 +462,7 @@ public class Settings { } public static CoordInputFormatEnum getCoordInputFormat() { - return CoordInputFormatEnum.fromInt(getInt(R.string.pref_coordinputformat, 0)); + return CoordInputFormatEnum.fromInt(getInt(R.string.pref_coordinputformat, CoordInputFormatEnum.Min.ordinal())); } public static void setCoordInputFormat(final CoordInputFormatEnum format) { diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java index 76f48e2..3fdf161 100644 --- a/main/src/cgeo/geocaching/settings/SettingsActivity.java +++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java @@ -8,9 +8,9 @@ import cgeo.geocaching.SelectMapfileActivity; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum; -import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.GCLogin; +import cgeo.geocaching.connector.oc.OCAuthParams; import cgeo.geocaching.files.SimpleDirChooser; import cgeo.geocaching.maps.MapProviderFactory; import cgeo.geocaching.maps.interfaces.MapSource; @@ -21,6 +21,7 @@ import org.apache.commons.lang3.StringUtils; import org.openintents.intents.FileManagerIntents; import android.app.ProgressDialog; +import android.app.backup.BackupManager; import android.content.Context; import android.content.Intent; import android.content.res.Resources; @@ -111,7 +112,8 @@ public class SettingsActivity extends PreferenceActivity { @Override protected void onPause() { - Compatibility.dataChanged(getPackageName()); + Log.i("Requesting settings backup with settings manager"); + BackupManager.dataChanged(getPackageName()); super.onPause(); } @@ -155,11 +157,17 @@ public class SettingsActivity extends PreferenceActivity { private void initServicePreferences() { getPreference(R.string.pref_connectorOCActive).setOnPreferenceChangeListener(VALUE_CHANGE_LISTENER); getPreference(R.string.pref_connectorOCPLActive).setOnPreferenceChangeListener(VALUE_CHANGE_LISTENER); + getPreference(R.string.pref_connectorOCNLActive).setOnPreferenceChangeListener(VALUE_CHANGE_LISTENER); + getPreference(R.string.pref_connectorOCUSActive).setOnPreferenceChangeListener(VALUE_CHANGE_LISTENER); + getPreference(R.string.pref_connectorOCROActive).setOnPreferenceChangeListener(VALUE_CHANGE_LISTENER); getPreference(R.string.pref_connectorGCActive).setOnPreferenceChangeListener(VALUE_CHANGE_LISTENER); getPreference(R.string.pref_connectorECActive).setOnPreferenceChangeListener(VALUE_CHANGE_LISTENER); setWebsite(R.string.pref_fakekey_gc_website, GCConnector.getInstance().getHost()); - setWebsite(R.string.pref_fakekey_ocde_website, "opencaching.de"); - setWebsite(R.string.pref_fakekey_ocpl_website, "opencaching.pl"); + setWebsite(R.string.pref_fakekey_ocde_website, OCAuthParams.OC_DE_AUTH_PARAMS.host); + setWebsite(R.string.pref_fakekey_ocpl_website, OCAuthParams.OC_PL_AUTH_PARAMS.host); + setWebsite(R.string.pref_fakekey_ocnl_website, OCAuthParams.OC_NL_AUTH_PARAMS.host); + setWebsite(R.string.pref_fakekey_ocus_website, OCAuthParams.OC_US_AUTH_PARAMS.host); + setWebsite(R.string.pref_fakekey_ocro_website, OCAuthParams.OC_RO_AUTH_PARAMS.host); setWebsite(R.string.pref_fakekey_ec_website, "extremcaching.com"); setWebsite(R.string.pref_fakekey_gcvote_website, "gcvote.com"); setWebsite(R.string.pref_fakekey_sendtocgeo_website, "send2.cgeo.org"); @@ -412,6 +420,15 @@ public class SettingsActivity extends PreferenceActivity { case R.string.pref_fakekey_ocpl_authorization: setOCPLAuthTitle(); break; + case R.string.pref_fakekey_ocnl_authorization: + setOCNLAuthTitle(); + break; + case R.string.pref_fakekey_ocus_authorization: + setOCUSAuthTitle(); + break; + case R.string.pref_fakekey_ocro_authorization: + setOCROAuthTitle(); + break; case R.string.pref_fakekey_twitter_authorization: setTwitterAuthTitle(); break; @@ -434,6 +451,27 @@ public class SettingsActivity extends PreferenceActivity { : R.string.settings_authorize)); } + void setOCNLAuthTitle() { + getPreference(R.string.pref_fakekey_ocnl_authorization) + .setTitle(getString(Settings.hasOCAuthorization(R.string.pref_ocnl_tokenpublic, R.string.pref_ocnl_tokensecret) + ? R.string.settings_reauthorize + : R.string.settings_authorize)); + } + + void setOCUSAuthTitle() { + getPreference(R.string.pref_fakekey_ocus_authorization) + .setTitle(getString(Settings.hasOCAuthorization(R.string.pref_ocus_tokenpublic, R.string.pref_ocus_tokensecret) + ? R.string.settings_reauthorize + : R.string.settings_authorize)); + } + + void setOCROAuthTitle() { + getPreference(R.string.pref_fakekey_ocro_authorization) + .setTitle(getString(Settings.hasOCAuthorization(R.string.pref_ocro_tokenpublic, R.string.pref_ocro_tokensecret) + ? R.string.settings_reauthorize + : R.string.settings_authorize)); + } + void setTwitterAuthTitle() { getPreference(R.string.pref_fakekey_twitter_authorization) .setTitle(getString(Settings.hasTwitterAuthorization() @@ -493,6 +531,18 @@ public class SettingsActivity extends PreferenceActivity { setOCPLAuthTitle(); redrawScreen(R.string.preference_screen_ocpl); break; + case R.string.pref_fakekey_ocnl_authorization: + setOCNLAuthTitle(); + redrawScreen(R.string.preference_screen_ocnl); + break; + case R.string.pref_fakekey_ocus_authorization: + setOCUSAuthTitle(); + redrawScreen(R.string.preference_screen_ocus); + break; + case R.string.pref_fakekey_ocro_authorization: + setOCROAuthTitle(); + redrawScreen(R.string.preference_screen_ocro); + break; case R.string.pref_fakekey_twitter_authorization: setTwitterAuthTitle(); redrawScreen(R.string.preference_screen_twitter); @@ -534,7 +584,13 @@ public class SettingsActivity extends PreferenceActivity { } Settings.setMapSource(mapSource); preference.setSummary(mapSource.getName()); - } else if (isPreference(preference, R.string.pref_connectorOCActive) || isPreference(preference, R.string.pref_connectorOCPLActive) || isPreference(preference, R.string.pref_connectorGCActive) || isPreference(preference, R.string.pref_connectorECActive)) { + } else if (isPreference(preference, R.string.pref_connectorOCActive) + || isPreference(preference, R.string.pref_connectorOCPLActive) + || isPreference(preference, R.string.pref_connectorOCNLActive) + || isPreference(preference, R.string.pref_connectorOCUSActive) + || isPreference(preference, R.string.pref_connectorOCROActive) + || isPreference(preference, R.string.pref_connectorGCActive) + || isPreference(preference, R.string.pref_connectorECActive)) { // // reset log-in status if connector activation was changed CgeoApplication.getInstance().forceRelog(); } else if (preference instanceof ListPreference) { diff --git a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java index b813389..97332d3 100644 --- a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java @@ -9,16 +9,15 @@ import org.eclipse.jdt.annotation.Nullable; public class TwitterAuthorizationActivity extends OAuthAuthorizationActivity { - public TwitterAuthorizationActivity() { - super("api.twitter.com", - "/oauth/request_token", - "/oauth/authorize", - "/oauth/access_token", - true, - Settings.getKeyConsumerPublic(), - Settings.getKeyConsumerSecret(), - "callback://www.cgeo.org/twitter/"); - } + public static final OAuthParameters TWITTER_OAUTH_PARAMS = new OAuthParameters( + "api.twitter.com", + "/oauth/request_token", + "/oauth/authorize", + "/oauth/access_token", + true, + Settings.getKeyConsumerPublic(), + Settings.getKeyConsumerSecret(), + "callback://www.cgeo.org/twitter/"); @Override protected final ImmutablePair<String, String> getTempTokens() { diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java index ca4e825..d827e3e 100644 --- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java +++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java @@ -379,6 +379,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { final TouchListener touchListener = new TouchListener(cache, v); v.setOnClickListener(touchListener); + v.setOnLongClickListener(touchListener); v.setOnTouchListener(touchListener); holder.checkbox.setVisibility(selectMode ? View.VISIBLE : View.GONE); @@ -535,62 +536,48 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { } } - private class TouchListener implements View.OnClickListener, View.OnTouchListener { + private class TouchListener implements View.OnClickListener, View.OnLongClickListener, View.OnTouchListener { - private boolean touch = true; - private final GestureDetector gestureDetector; private final Geocache cache; + private final GestureDetector gestureDetector; public TouchListener(final Geocache cache, final View view) { this.cache = cache; - final FlingGesture dGesture = new FlingGesture(cache, view); - gestureDetector = new GestureDetector(getContext(), dGesture); + gestureDetector = new GestureDetector(getContext(), new FlingGesture(cache)); } - // tap on item + // Tap on item @Override - public void onClick(View view) { - if (!touch) { - touch = true; - return; - } - + public void onClick(final View view) { if (isSelectMode()) { cache.setStatusChecked(!cache.isStatusChecked()); notifyDataSetChanged(); - return; + } else { + CacheDetailActivity.startActivity(getContext(), cache.getGeocode(), cache.getName()); } + } - // load cache details - CacheDetailActivity.startActivity(getContext(), cache.getGeocode(), cache.getName()); + // Long tap on item + @Override + public boolean onLongClick(final View view) { + view.showContextMenu(); + return true; } - // swipe on item + // Swipe on item @Override - public boolean onTouch(View view, MotionEvent event) { - if (gestureDetector.onTouchEvent(event)) { - touch = false; - return true; - } + public boolean onTouch(final View view, final MotionEvent event) { + return gestureDetector.onTouchEvent(event); - return false; } } private class FlingGesture extends GestureDetector.SimpleOnGestureListener { private final Geocache cache; - private final View view; - public FlingGesture(final Geocache cache, final View view) { + public FlingGesture(final Geocache cache) { this.cache = cache; - this.view = view; - } - - // long tap on item - @Override - public void onLongPress(MotionEvent e) { - view.showContextMenu(); } @Override diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java index eaaf711..f7111f7 100644 --- a/main/src/cgeo/geocaching/ui/CompassView.java +++ b/main/src/cgeo/geocaching/ui/CompassView.java @@ -16,7 +16,6 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; import android.util.AttributeSet; -import android.util.FloatMath; import android.view.View; import java.util.concurrent.TimeUnit; @@ -158,19 +157,19 @@ public class CompassView extends View { * @return the new value */ static protected float smoothUpdate(float goal, float actual) { - final float diff = AngleUtils.difference(actual, goal); + final double diff = AngleUtils.difference(actual, goal); - float offset = 0; + double offset = 0; // If the difference is smaller than 1 degree, do nothing as it // causes the arrow to vibrate. Round away from 0. if (diff > 1.0) { - offset = FloatMath.ceil(diff / 10.0f); // for larger angles, rotate faster + offset = Math.ceil(diff / 10.0); // for larger angles, rotate faster } else if (diff < 1.0) { - offset = FloatMath.floor(diff / 10.0f); + offset = Math.floor(diff / 10.0); } - return AngleUtils.normalize(actual + offset); + return AngleUtils.normalize((float) (actual + offset)); } @Override diff --git a/main/src/cgeo/geocaching/ui/ImagesList.java b/main/src/cgeo/geocaching/ui/ImagesList.java index 31a61b5..d1b2a64 100644 --- a/main/src/cgeo/geocaching/ui/ImagesList.java +++ b/main/src/cgeo/geocaching/ui/ImagesList.java @@ -6,11 +6,11 @@ import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.list.StoredList; import cgeo.geocaching.network.HtmlImage; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import rx.Subscription; -import rx.android.observables.AndroidObservable; import rx.functions.Action0; import rx.functions.Action1; import rx.subscriptions.CompositeSubscription; @@ -30,12 +30,14 @@ import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; +import android.webkit.MimeTypeMap; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.util.Collection; import java.util.LinkedList; @@ -116,13 +118,12 @@ public class ImagesList { final ImageView imageView = (ImageView) inflater.inflate(R.layout.image_item, null); assert(imageView != null); - subscriptions.add(AndroidObservable.bindActivity(activity, imgGetter.fetchDrawable(img.getUrl())) - .subscribe(new Action1<BitmapDrawable>() { - @Override - public void call(final BitmapDrawable image) { - display(imageView, image, img, rowView); - } - })); + subscriptions.add(RxUtils.subscribeThenUI(imgGetter.fetchDrawable(img.getUrl()), new Action1<BitmapDrawable>() { + @Override + public void call(final BitmapDrawable image) { + display(imageView, image, img, rowView); + } + })); rowView.addView(imageView); imagesView.addView(rowView); } @@ -141,7 +142,7 @@ public class ImagesList { imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { - viewImageInStandardApp(image); + viewImageInStandardApp(img, image); } }); activity.registerForContextMenu(imageView); @@ -181,7 +182,7 @@ public class ImagesList { public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.image_open_file: - viewImageInStandardApp(currentDrawable); + viewImageInStandardApp(currentImage, currentDrawable); return true; case R.id.image_open_browser: if (currentImage != null) { @@ -193,26 +194,35 @@ public class ImagesList { } } - private void viewImageInStandardApp(final BitmapDrawable image) { + private static String mimeTypeForUrl(final String url) { + return StringUtils.defaultString(MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(url)), "image/*"); + } + + private static File saveToTemporaryJPGFile(final BitmapDrawable image) throws FileNotFoundException { final File file = LocalStorage.getStorageFile(null, "temp.jpg", false, true); BufferedOutputStream stream = null; try { stream = new BufferedOutputStream(new FileOutputStream(file)); image.getBitmap().compress(CompressFormat.JPEG, 100, stream); - } catch (Exception e) { - Log.e("ImagesList.viewImageInStandardApp", e); - return; } finally { IOUtils.closeQuietly(stream); } + file.deleteOnExit(); + return file; + } - final Intent intent = new Intent(); - intent.setAction(android.content.Intent.ACTION_VIEW); - intent.setDataAndType(Uri.fromFile(file), "image/jpeg"); - activity.startActivity(intent); - - if (file.exists()) { - file.deleteOnExit(); + private void viewImageInStandardApp(final Image img, final BitmapDrawable image) { + try { + final Intent intent = new Intent().setAction(android.content.Intent.ACTION_VIEW); + final File file = LocalStorage.getStorageFile(geocode, img.getUrl(), true, true); + if (file.exists()) { + intent.setDataAndType(Uri.fromFile(file), mimeTypeForUrl(img.getUrl())); + } else { + intent.setDataAndType(Uri.fromFile(saveToTemporaryJPGFile(image)), "image/jpeg"); + } + activity.startActivity(intent); + } catch (Exception e) { + Log.e("ImagesList.viewImageInStandardApp", e); } } diff --git a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java index c150434..cb52319 100644 --- a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java +++ b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java @@ -5,11 +5,11 @@ import cgeo.geocaching.sensors.IGeoData; import cgeo.geocaching.R; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.Settings.CoordInputFormatEnum; +import cgeo.geocaching.utils.EditUtils; import org.apache.commons.lang3.StringUtils; @@ -103,14 +103,14 @@ public class CoordinatesInputDialog extends NoTitleDialog { eLonSec.addTextChangedListener(new TextChanged(eLonSec)); eLonSub.addTextChangedListener(new TextChanged(eLonSub)); - Compatibility.disableSuggestions(eLatDeg); - Compatibility.disableSuggestions(eLatMin); - Compatibility.disableSuggestions(eLatSec); - Compatibility.disableSuggestions(eLatSub); - Compatibility.disableSuggestions(eLonDeg); - Compatibility.disableSuggestions(eLonMin); - Compatibility.disableSuggestions(eLonSec); - Compatibility.disableSuggestions(eLonSub); + EditUtils.disableSuggestions(eLatDeg); + EditUtils.disableSuggestions(eLatMin); + EditUtils.disableSuggestions(eLatSec); + EditUtils.disableSuggestions(eLatSub); + EditUtils.disableSuggestions(eLonDeg); + EditUtils.disableSuggestions(eLonMin); + EditUtils.disableSuggestions(eLonSec); + EditUtils.disableSuggestions(eLonSub); bLat.setOnClickListener(new ButtonClickListener()); bLon.setOnClickListener(new ButtonClickListener()); diff --git a/main/src/cgeo/geocaching/utils/BundleUtils.java b/main/src/cgeo/geocaching/utils/BundleUtils.java new file mode 100644 index 0000000..9c4255b --- /dev/null +++ b/main/src/cgeo/geocaching/utils/BundleUtils.java @@ -0,0 +1,17 @@ +package cgeo.geocaching.utils; + +import org.eclipse.jdt.annotation.NonNull; + +import android.os.Bundle; + +public class BundleUtils { + + @NonNull + public static String getString(Bundle bundle, @NonNull String key, @NonNull String defaultValue) { + String res = bundle.getString(key); + if (res != null) { + return res; + } + return defaultValue; + } +} diff --git a/main/src/cgeo/geocaching/utils/EditUtils.java b/main/src/cgeo/geocaching/utils/EditUtils.java index d975df9..0bfe2ea 100644 --- a/main/src/cgeo/geocaching/utils/EditUtils.java +++ b/main/src/cgeo/geocaching/utils/EditUtils.java @@ -1,5 +1,6 @@ package cgeo.geocaching.utils; +import android.text.InputType; import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.EditorInfo; @@ -41,4 +42,9 @@ public final class EditUtils { } + public static void disableSuggestions(EditText edit) { + edit.setInputType(edit.getInputType() + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS + | InputType.TYPE_TEXT_VARIATION_FILTER); + } } diff --git a/main/src/cgeo/geocaching/utils/ImageUtils.java b/main/src/cgeo/geocaching/utils/ImageUtils.java index 0d8bec8..aae0f14 100644 --- a/main/src/cgeo/geocaching/utils/ImageUtils.java +++ b/main/src/cgeo/geocaching/utils/ImageUtils.java @@ -15,6 +15,7 @@ import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.media.ExifInterface; import android.net.Uri; +import android.os.Environment; import java.io.BufferedOutputStream; import java.io.File; @@ -202,8 +203,8 @@ public final class ImageUtils { public static File getOutputImageFile() { // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. + final File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "cgeo"); - File mediaStorageDir = new File(Compatibility.getExternalPictureDir(), "cgeo"); // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. diff --git a/main/src/cgeo/geocaching/utils/RxUtils.java b/main/src/cgeo/geocaching/utils/RxUtils.java new file mode 100644 index 0000000..9926bab --- /dev/null +++ b/main/src/cgeo/geocaching/utils/RxUtils.java @@ -0,0 +1,51 @@ +package cgeo.geocaching.utils; + +import rx.Observable; +import rx.Observer; +import rx.Scheduler; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class RxUtils { + + // Utility class, not to be instanciated + private RxUtils() {} + + final static private int cores = Runtime.getRuntime().availableProcessors(); + public final static Scheduler computationScheduler = Schedulers.executor(new ThreadPoolExecutor(1, cores, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>())); + + public static <T> Subscription subscribeThenUI(final Observable<T> observable, final Observer<T> observer) { + return observable.observeOn(AndroidSchedulers.mainThread()).subscribe(observer); + } + + public static <T> Subscription subscribeThenUI(final Observable<T> observable, final Action1<T> action) { + return observable.observeOn(AndroidSchedulers.mainThread()).subscribe(action); + } + + public static <T> Subscription subscribeThenUI(final Observable<T> observable, final Action1<T> action, final Action1<Throwable> onError) { + return observable.observeOn(AndroidSchedulers.mainThread()).subscribe(action, onError); + } + + public static <T> Observable<T> onIO(final Observable<T> observable) { + return observable.subscribeOn(Schedulers.io()); + } + + public static <T> Subscription subscribeOnIOThenUI(final Observable<T> observable, final Observer<T> observer) { + return subscribeThenUI(onIO(observable), observer); + } + + public static <T> Subscription subscribeOnIOThenUI(final Observable<T> observable, final Action1<T> action) { + return subscribeThenUI(onIO(observable), action); + } + + public static <T> Subscription subscribeOnIOThenUI(final Observable<T> observable, final Action1<T> action, final Action1<Throwable> onError) { + return subscribeThenUI(onIO(observable), action, onError); + } + +} diff --git a/main/templates/keys.xml b/main/templates/keys.xml index e667df5..2c41a2a 100644 --- a/main/templates/keys.xml +++ b/main/templates/keys.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <!-- Google Maps --> <string name="maps_api_key" translatable="false">@maps.api.key@</string> @@ -10,4 +10,16 @@ <!-- Opencaching.pl --> <string name="oc_pl_okapi_consumer_key" translatable="false">@ocpl.okapi.consumer.key@</string> <string name="oc_pl_okapi_consumer_secret" translatable="false">@ocpl.okapi.consumer.secret@</string> + <!-- disable unused resource warning until remaining implementation has been merged --> + <!-- Opencaching.us --> + <string name="oc_us_okapi_consumer_key" translatable="false">@ocus.okapi.consumer.key@</string> + <string name="oc_us_okapi_consumer_secret" translatable="false">@ocus.okapi.consumer.secret@</string> + + <!-- Opencaching.nl --> + <string name="oc_nl_okapi_consumer_key" translatable="false">@ocnl.okapi.consumer.key@</string> + <string name="oc_nl_okapi_consumer_secret" translatable="false">@ocnl.okapi.consumer.secret@</string> + + <!-- Opencaching.ro --> + <string name="oc_ro_okapi_consumer_key" translatable="false">@ocro.okapi.consumer.key@</string> + <string name="oc_ro_okapi_consumer_secret" translatable="false">@ocro.okapi.consumer.secret@</string> </resources> diff --git a/main/templates/private.properties b/main/templates/private.properties index 0c40fda..2451048 100644 --- a/main/templates/private.properties +++ b/main/templates/private.properties @@ -30,3 +30,24 @@ ocde.okapi.consumer.secret= ocpl.okapi.consumer.key= ocpl.okapi.consumer.secret= + +# These keys allow c:geo to be registered at openaching.us and +# to search and log caches in your name +# You can request your own at http://www.opencaching.us/okapi/signup.html + +ocus.okapi.consumer.key= +ocus.okapi.consumer.secret= + +# These keys allow c:geo to be registered at openaching.nl and +# to search and log caches in your name +# You can request your own at http://www.opencaching.nl/okapi/signup.html + +ocnl.okapi.consumer.key= +ocnl.okapi.consumer.secret= + +# These keys allow c:geo to be registered at openaching.ro and +# to search and log caches in your name +# You can request your own at http://oc.opencaching.ro/okapi/signup.html + +ocro.okapi.consumer.key= +ocro.okapi.consumer.secret= diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml index 827115f..690838c 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionName="1.0" > <uses-sdk - android:minSdkVersion="7" + android:minSdkVersion="8" android:targetSdkVersion="13" /> <uses-feature diff --git a/tests/libs/docs/robotium-solo-3.6-javadoc.jar b/tests/libs/docs/robotium-solo-3.6-javadoc.jar Binary files differdeleted file mode 100644 index db4e75b..0000000 --- a/tests/libs/docs/robotium-solo-3.6-javadoc.jar +++ /dev/null diff --git a/tests/libs/docs/robotium-solo-5.1-javadoc.jar b/tests/libs/docs/robotium-solo-5.1-javadoc.jar Binary files differnew file mode 100644 index 0000000..92ebff2 --- /dev/null +++ b/tests/libs/docs/robotium-solo-5.1-javadoc.jar diff --git a/tests/libs/robotium-solo-3.6.jar b/tests/libs/robotium-solo-3.6.jar Binary files differdeleted file mode 100644 index 4280906..0000000 --- a/tests/libs/robotium-solo-3.6.jar +++ /dev/null diff --git a/tests/libs/robotium-solo-3.6.jar.properties b/tests/libs/robotium-solo-3.6.jar.properties deleted file mode 100644 index 10e60fa..0000000 --- a/tests/libs/robotium-solo-3.6.jar.properties +++ /dev/null @@ -1 +0,0 @@ -doc=./docs/robotium-solo-3.6-javadoc.jar
\ No newline at end of file diff --git a/tests/libs/robotium-solo-5.1.jar b/tests/libs/robotium-solo-5.1.jar Binary files differnew file mode 100644 index 0000000..1931dd9 --- /dev/null +++ b/tests/libs/robotium-solo-5.1.jar diff --git a/tests/libs/robotium-solo-5.1.jar.properties b/tests/libs/robotium-solo-5.1.jar.properties new file mode 100644 index 0000000..9df11e1 --- /dev/null +++ b/tests/libs/robotium-solo-5.1.jar.properties @@ -0,0 +1 @@ +doc=./docs/robotium-solo-5.1-javadoc.jar
\ No newline at end of file diff --git a/tests/src/cgeo/geocaching/files/SimpleDirChooserUITest.java b/tests/src/cgeo/geocaching/files/SimpleDirChooserUITest.java index 05b4ee1..985733a 100644 --- a/tests/src/cgeo/geocaching/files/SimpleDirChooserUITest.java +++ b/tests/src/cgeo/geocaching/files/SimpleDirChooserUITest.java @@ -1,18 +1,18 @@ package cgeo.geocaching.files; -import com.jayway.android.robotium.solo.Solo; +import cgeo.geocaching.Intents; + +import com.robotium.solo.Solo; import android.annotation.TargetApi; +import android.content.Intent; import android.os.Build; import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.Suppress; import android.widget.CheckBox; import java.util.ArrayList; @TargetApi(Build.VERSION_CODES.FROYO) -@Suppress() -/* This test breaks the continuous integration server, do not run it for now. */ public class SimpleDirChooserUITest extends ActivityInstrumentationTestCase2<SimpleDirChooser> { private Solo solo; @@ -24,9 +24,14 @@ public class SimpleDirChooserUITest extends ActivityInstrumentationTestCase2<Sim @Override public void setUp() throws Exception { super.setUp(); + setActivityIntent(new Intent().putExtra(Intents.EXTRA_START_DIR, "").putExtra(SimpleDirChooser.EXTRA_CHOOSE_FOR_WRITING, false)); solo = new Solo(getInstrumentation(), getActivity()); } + public ArrayList<CheckBox> getCurrentCheckBoxes() { + return solo.getCurrentViews(CheckBox.class); + } + public void testSingleSelection() throws InterruptedException { // normally our activity should be ready, but we already had Jenkins report no checkboxes right here at the beginning solo.waitForActivity(solo.getCurrentActivity().getClass().getSimpleName(), 2000); @@ -37,11 +42,11 @@ public class SimpleDirChooserUITest extends ActivityInstrumentationTestCase2<Sim // according to the documentation, automatic pauses only happen in the clickXYZ() methods. // Therefore lets introduce a manual pause after the scrolling methods. - final int lastIndex = solo.getCurrentCheckBoxes().size() - 1; + final int lastIndex = getCurrentCheckBoxes().size() - 1; solo.clickOnCheckBox(lastIndex); - assertTrue(solo.getCurrentCheckBoxes().get(lastIndex).isChecked()); - assertFalse(solo.getCurrentCheckBoxes().get(0).isChecked()); + assertTrue(solo.isCheckBoxChecked(lastIndex)); + assertFalse(solo.isCheckBoxChecked(0)); assertChecked("Clicked last checkbox", 1); solo.scrollUp(); @@ -54,23 +59,23 @@ public class SimpleDirChooserUITest extends ActivityInstrumentationTestCase2<Sim pause(); solo.clickOnCheckBox(0); assertChecked("Clicked first checkbox", 1); - assertTrue(solo.getCurrentCheckBoxes().get(0).isChecked()); + assertTrue(solo.isCheckBoxChecked(0)); solo.clickOnCheckBox(1); assertChecked("Clicked second checkbox", 1); - assertTrue(solo.getCurrentCheckBoxes().get(1).isChecked()); + assertTrue(solo.isCheckBoxChecked(1)); } private static void pause() throws InterruptedException { - Thread.sleep(500); + Thread.sleep(100); } private void assertChecked(String message, int expectedChecked) { - int checked = 0; - final ArrayList<CheckBox> boxes = solo.getCurrentCheckBoxes(); + final ArrayList<CheckBox> boxes = getCurrentCheckBoxes(); assertNotNull("Could not get checkboxes", boxes); assertTrue("There are no checkboxes", boxes.size() > 1); - for (CheckBox checkBox : boxes) { - if (checkBox.isChecked()) { + int checked = 0; + for (int i = 0; i < boxes.size(); i++) { + if (solo.isCheckBoxChecked(i)) { checked++; } } diff --git a/tests/src/cgeo/geocaching/compatibility/CompatibilityTest.java b/tests/src/cgeo/geocaching/sensors/SensorsTest.java index 5857e46..87ff1de 100644 --- a/tests/src/cgeo/geocaching/compatibility/CompatibilityTest.java +++ b/tests/src/cgeo/geocaching/sensors/SensorsTest.java @@ -1,16 +1,16 @@ -package cgeo.geocaching.compatibility; +package cgeo.geocaching.sensors; import cgeo.geocaching.MainActivity; -import android.test.ActivityInstrumentationTestCase2; - import junit.framework.Assert; -public class CompatibilityTest extends ActivityInstrumentationTestCase2<MainActivity> { +import android.test.ActivityInstrumentationTestCase2; + +public class SensorsTest extends ActivityInstrumentationTestCase2<MainActivity> { private MainActivity activity; - public CompatibilityTest() { + public SensorsTest() { super(MainActivity.class); } @@ -20,11 +20,6 @@ public class CompatibilityTest extends ActivityInstrumentationTestCase2<MainActi activity = getActivity(); } - public static void testDataChanged() { - // This should not raise an exception in any Android version - Compatibility.dataChanged("cgeo.geocaching"); - } - public void testGetDirectionNow() { final float angle = DirectionProvider.getDirectionNow(1.0f); Assert.assertTrue(angle == 1.0f || angle == 91.0f || angle == 181.0f || angle == 271.0f); diff --git a/tests/tests.iml b/tests/tests.iml index ba3aeeb..6a6c905 100644 --- a/tests/tests.iml +++ b/tests/tests.iml @@ -19,19 +19,14 @@ <orderEntry type="module-library"> <library> <CLASSES> - <root url="jar://$MODULE_DIR$/libs/android-junit-report-1.5.8.jar!/" /> + <root url="file://$MODULE_DIR$/libs" /> </CLASSES> <JAVADOC /> - <SOURCES /> - </library> - </orderEntry> - <orderEntry type="module-library"> - <library> - <CLASSES> - <root url="jar://$MODULE_DIR$/libs/robotium-solo-3.6.jar!/" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> + <SOURCES> + <root url="file://$MODULE_DIR$/libs" /> + </SOURCES> + <jarDirectory url="file://$MODULE_DIR$/libs" recursive="false" /> + <jarDirectory url="file://$MODULE_DIR$/libs" recursive="false" type="SOURCES" /> </library> </orderEntry> <orderEntry type="inheritedJdk" /> |
