From 958541e2af558f10d864c3a1e33f5fadfdcee845 Mon Sep 17 00:00:00 2001 From: Doug Keen Date: Sun, 18 Oct 2015 17:26:30 -0700 Subject: [PATCH] * Drop support for Android versions < 4.0 * Convert all http client to use OkHttp * Use Android number picker instead of third party lib --- app/build.gradle | 13 ++-- .../activities/TrainAlarmDialogFragment.java | 11 ++-- .../dougkeen/bart/controls/SwipeHelper.java | 27 ++++---- .../GetRealTimeDeparturesTask.java | 28 ++++----- .../bart/networktasks/GetRouteFareTask.java | 40 +++++------- .../GetScheduleInformationTask.java | 37 +++++------ .../bart/networktasks/NetworkUtils.java | 63 ++++++++++--------- .../main/res/layout/train_alarm_dialog.xml | 25 ++++---- app/src/main/res/values/strings.xml | 3 +- app/src/main/res/values/styles.xml | 2 +- 10 files changed, 116 insertions(+), 133 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d79ca26..a3d1ad9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,7 +7,7 @@ dependencies { compile 'org.apache.commons:commons-lang3:3.4' compile 'com.fasterxml.jackson.core:jackson-databind:2.6.1' compile 'org.springframework.android:spring-android-rest-template:1.0.1.RELEASE' - compile 'com.code-troopers.betterpickers:library:2.0.0' + compile 'com.squareup.okhttp:okhttp:2.5.0' compile 'com.android.support:appcompat-v7:22.2.1' @@ -16,7 +16,7 @@ dependencies { } android { - compileSdkVersion 22 + compileSdkVersion 23 buildToolsVersion "22.0.1" compileOptions { @@ -25,12 +25,11 @@ android { } defaultConfig { - versionName "2.2.4" - versionCode 31 + versionName "2.2.5" + versionCode 32 - // TODO(fuegofro) - bring this back down to 8 if it's easy by using a different number picker library - minSdkVersion 9 - targetSdkVersion 22 + minSdkVersion 14 + targetSdkVersion 23 } buildTypes { diff --git a/app/src/main/java/com/dougkeen/bart/activities/TrainAlarmDialogFragment.java b/app/src/main/java/com/dougkeen/bart/activities/TrainAlarmDialogFragment.java index b7a5e41..1954126 100644 --- a/app/src/main/java/com/dougkeen/bart/activities/TrainAlarmDialogFragment.java +++ b/app/src/main/java/com/dougkeen/bart/activities/TrainAlarmDialogFragment.java @@ -13,8 +13,8 @@ import android.support.v4.app.FragmentActivity; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; +import android.widget.NumberPicker; -import com.codetroopers.betterpickers.numberpicker.NumberPicker; import com.dougkeen.bart.BartRunnerApplication; import com.dougkeen.bart.R; import com.dougkeen.bart.model.Departure; @@ -54,8 +54,8 @@ public class TrainAlarmDialogFragment extends DialogFragment { final Departure boardedDeparture = application.getBoardedDeparture(); final int maxValue = boardedDeparture.getMeanSecondsLeft() / 60; - numberPicker.setMin(1); - numberPicker.setMax(maxValue); + numberPicker.setMinValue(1); + numberPicker.setMaxValue(maxValue); if (boardedDeparture.isAlarmPending()) { setNumber(numberPicker, boardedDeparture.getAlarmLeadTimeMinutes()); @@ -71,8 +71,7 @@ public class TrainAlarmDialogFragment extends DialogFragment { } private void setNumber(NumberPicker numberPicker, int value) { - // Passing in null for the decimalPart and sign doesn't change them. - numberPicker.setNumber(value, null /* decimalPart */, null /* sign */); + numberPicker.setValue(value); } @NonNull @@ -95,7 +94,7 @@ public class TrainAlarmDialogFragment extends DialogFragment { int which) { NumberPicker numberPicker = (NumberPicker) getDialog() .findViewById(R.id.numberPicker); - final int alarmLeadTime = numberPicker.getNumber(); + final int alarmLeadTime = numberPicker.getValue(); // Save most recent selection Editor editor = getActivity().getPreferences( diff --git a/app/src/main/java/com/dougkeen/bart/controls/SwipeHelper.java b/app/src/main/java/com/dougkeen/bart/controls/SwipeHelper.java index 2021bca..0d554be 100644 --- a/app/src/main/java/com/dougkeen/bart/controls/SwipeHelper.java +++ b/app/src/main/java/com/dougkeen/bart/controls/SwipeHelper.java @@ -19,10 +19,9 @@ package com.dougkeen.bart.controls; -import static com.nineoldandroids.view.ViewHelper.setAlpha; -import static com.nineoldandroids.view.ViewHelper.setTranslationX; -import static com.nineoldandroids.view.ViewPropertyAnimator.animate; - +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; @@ -32,9 +31,6 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import com.dougkeen.bart.model.Constants; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorListenerAdapter; -import com.nineoldandroids.animation.ValueAnimator; /** * A utility class for animating the dismissal of a view (with 'onDismiss' @@ -167,7 +163,7 @@ public class SwipeHelper implements View.OnTouchListener { dismissWithAnimation(dismissRight); } else { // cancel - animate(mView).translationX(0).alpha(1) + mView.animate().translationX(0).alpha(1) .setDuration(mAnimationTime).setListener(null); } mVelocityTracker = null; @@ -198,10 +194,9 @@ public class SwipeHelper implements View.OnTouchListener { if (mSwiping) { mTranslationX = deltaX; - setTranslationX(mView, deltaX); + mView.setTranslationX(deltaX); // TODO: use an ease-out interpolator or such - setAlpha( - mView, + mView.setAlpha( Math.max( 0f, Math.min(1f, 1f - 2f * Math.abs(deltaX) @@ -215,7 +210,7 @@ public class SwipeHelper implements View.OnTouchListener { } public void dismissWithAnimation(boolean dismissRight) { - animate(mView).translationX(dismissRight ? mViewWidth : -mViewWidth) + mView.animate().translationX(dismissRight ? mViewWidth : -mViewWidth) .alpha(0).setDuration(mAnimationTime) .setListener(new AnimatorListenerAdapter() { @Override @@ -250,7 +245,7 @@ public class SwipeHelper implements View.OnTouchListener { */ // setAlpha(mView, 1f); - setTranslationX(mView, 0); + mView.setTranslationX(0); lp.height = originalHeight; mView.setLayoutParams(lp); } @@ -273,12 +268,12 @@ public class SwipeHelper implements View.OnTouchListener { mView.measure(measureSpec, measureSpec); mViewWidth = mView.getMeasuredWidth(); final int viewHeight = mView.getMeasuredHeight(); - setAlpha(mView, 0f); + mView.setAlpha(0f); final ViewGroup.LayoutParams lp = mView.getLayoutParams(); final int originalHeight = lp.height; - setTranslationX(mView, mViewWidth); + mView.setTranslationX(mViewWidth); // Grow space ValueAnimator animator = ValueAnimator.ofInt(1, viewHeight) @@ -292,7 +287,7 @@ public class SwipeHelper implements View.OnTouchListener { mView.setLayoutParams(lp); // Swipe view into space that opened up - animate(mView).translationX(0).alpha(1) + mView.animate().translationX(0).alpha(1) .setDuration(mAnimationTime) // Dummy listener so the default doesn't run .setListener(new AnimatorListenerAdapter() { diff --git a/app/src/main/java/com/dougkeen/bart/networktasks/GetRealTimeDeparturesTask.java b/app/src/main/java/com/dougkeen/bart/networktasks/GetRealTimeDeparturesTask.java index 2ba3ea2..ed63478 100644 --- a/app/src/main/java/com/dougkeen/bart/networktasks/GetRealTimeDeparturesTask.java +++ b/app/src/main/java/com/dougkeen/bart/networktasks/GetRealTimeDeparturesTask.java @@ -1,17 +1,10 @@ package com.dougkeen.bart.networktasks; import java.io.IOException; -import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.util.List; -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpUriRequest; - import android.os.AsyncTask; import android.util.Log; import android.util.Xml; @@ -20,6 +13,9 @@ import com.dougkeen.bart.model.Constants; import com.dougkeen.bart.model.RealTimeDepartures; import com.dougkeen.bart.model.Route; import com.dougkeen.bart.model.StationPair; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; public abstract class GetRealTimeDeparturesTask extends AsyncTask { @@ -30,6 +26,8 @@ public abstract class GetRealTimeDeparturesTask extends + Constants.API_KEY + "&orig=%1$s"; private final static int MAX_ATTEMPTS = 5; + private final OkHttpClient mClient = NetworkUtils.makeHttpClient(); + private Exception mException; private List mRoutes; @@ -83,7 +81,9 @@ public abstract class GetRealTimeDeparturesTask extends mRoutes.get(0).getDirection()); } - HttpUriRequest request = new HttpGet(url); + + Request request = new Request.Builder() + .url(url).build(); EtdContentHandler handler = new EtdContentHandler( params.getOrigin(), params.getDestination(), mRoutes); @@ -91,17 +91,13 @@ public abstract class GetRealTimeDeparturesTask extends return null; } - HttpResponse response = NetworkUtils.executeWithRecovery(request); + Response response = mClient.newCall(request).execute(); - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - throw new IOException("Server returned " - + response.getStatusLine().toString()); + if (!response.isSuccessful()) { + throw new IOException("Server returned " + response.code()); } - StringWriter writer = new StringWriter(); - IOUtils.copy(response.getEntity().getContent(), writer, "UTF-8"); - - xml = writer.toString(); + xml = response.body().string(); if (xml.length() == 0) { throw new IOException("Server returned blank xml document"); } diff --git a/app/src/main/java/com/dougkeen/bart/networktasks/GetRouteFareTask.java b/app/src/main/java/com/dougkeen/bart/networktasks/GetRouteFareTask.java index 0f82892..0f722a2 100644 --- a/app/src/main/java/com/dougkeen/bart/networktasks/GetRouteFareTask.java +++ b/app/src/main/java/com/dougkeen/bart/networktasks/GetRouteFareTask.java @@ -1,23 +1,20 @@ package com.dougkeen.bart.networktasks; -import java.io.IOException; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; - -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpUriRequest; -import org.xml.sax.SAXException; - import android.os.AsyncTask; import android.util.Log; import android.util.Xml; import com.dougkeen.bart.model.Constants; import com.dougkeen.bart.model.Station; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; public abstract class GetRouteFareTask extends AsyncTask { @@ -26,6 +23,8 @@ public abstract class GetRouteFareTask extends private final static String FARE_URL = "http://api.bart.gov/api/sched.aspx?cmd=fare&date=today&key=" + Constants.API_KEY + "&orig=%1$s&dest=%2$s"; + private final static OkHttpClient client = NetworkUtils.makeHttpClient(); + private Exception mException; private String fare; @@ -45,26 +44,21 @@ public abstract class GetRouteFareTask extends String xml = null; try { - HttpUriRequest request = new HttpGet( - String.format(FARE_URL, params.origin.abbreviation, - params.destination.abbreviation)); + Request request = new Request.Builder() + .url(String.format(FARE_URL, params.origin.abbreviation, params.destination.abbreviation)).build(); FareContentHandler handler = new FareContentHandler(); if (isCancelled()) { return null; } - HttpResponse response = NetworkUtils.executeWithRecovery(request); + Response response = client.newCall(request).execute(); - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - throw new IOException("Server returned " - + response.getStatusLine().toString()); + if (!response.isSuccessful()) { + throw new IOException("Server returned " + response.code()); } - StringWriter writer = new StringWriter(); - IOUtils.copy(response.getEntity().getContent(), writer, "UTF-8"); - - xml = writer.toString(); + xml = response.body().string(); if (xml.length() == 0) { throw new IOException("Server returned blank xml document"); } diff --git a/app/src/main/java/com/dougkeen/bart/networktasks/GetScheduleInformationTask.java b/app/src/main/java/com/dougkeen/bart/networktasks/GetScheduleInformationTask.java index 5482632..a302969 100644 --- a/app/src/main/java/com/dougkeen/bart/networktasks/GetScheduleInformationTask.java +++ b/app/src/main/java/com/dougkeen/bart/networktasks/GetScheduleInformationTask.java @@ -1,17 +1,5 @@ package com.dougkeen.bart.networktasks; -import java.io.IOException; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; - -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpUriRequest; -import org.xml.sax.SAXException; - import android.os.AsyncTask; import android.util.Log; import android.util.Xml; @@ -19,6 +7,15 @@ import android.util.Xml; import com.dougkeen.bart.model.Constants; import com.dougkeen.bart.model.ScheduleInformation; import com.dougkeen.bart.model.StationPair; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; public abstract class GetScheduleInformationTask extends AsyncTask { @@ -28,6 +25,8 @@ public abstract class GetScheduleInformationTask extends private final static int MAX_ATTEMPTS = 5; + private final static OkHttpClient client = NetworkUtils.makeHttpClient(); + private Exception mException; @Override @@ -50,7 +49,7 @@ public abstract class GetScheduleInformationTask extends params.getOrigin().abbreviation, params.getDestination().abbreviation); - HttpUriRequest request = new HttpGet(url); + Request request = new Request.Builder().url(url).build(); if (isCancelled()) { return null; @@ -59,17 +58,13 @@ public abstract class GetScheduleInformationTask extends ScheduleContentHandler handler = new ScheduleContentHandler( params.getOrigin(), params.getDestination()); - HttpResponse response = NetworkUtils.executeWithRecovery(request); + Response response = client.newCall(request).execute(); - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - throw new IOException("Server returned " - + response.getStatusLine().toString()); + if (!response.isSuccessful()) { + throw new IOException("Server returned " + response.code()); } - StringWriter writer = new StringWriter(); - IOUtils.copy(response.getEntity().getContent(), writer, "UTF-8"); - - xml = writer.toString(); + xml = response.body().string(); if (xml.length() == 0) { throw new IOException("Server returned blank xml document"); } diff --git a/app/src/main/java/com/dougkeen/bart/networktasks/NetworkUtils.java b/app/src/main/java/com/dougkeen/bart/networktasks/NetworkUtils.java index 8c221aa..ba88395 100644 --- a/app/src/main/java/com/dougkeen/bart/networktasks/NetworkUtils.java +++ b/app/src/main/java/com/dougkeen/bart/networktasks/NetworkUtils.java @@ -1,40 +1,47 @@ package com.dougkeen.bart.networktasks; -import java.io.IOException; +import android.util.Log; -import org.apache.http.HttpResponse; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.conn.params.ConnManagerParams; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpConnectionParams; -import org.apache.http.params.HttpParams; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; public class NetworkUtils { - public static HttpClient getHttpClient() { - HttpClient client = new DefaultHttpClient(); - final HttpParams params = client.getParams(); - HttpConnectionParams.setConnectionTimeout(params, - NetworkUtils.CONNECTION_TIMEOUT_MILLIS); - HttpConnectionParams.setSoTimeout(params, - NetworkUtils.CONNECTION_TIMEOUT_MILLIS); - ConnManagerParams.setTimeout(params, - NetworkUtils.CONNECTION_TIMEOUT_MILLIS); - return client; - } + private static class RetryInterceptor implements Interceptor { + private static final String TAG = "RetryInterceptor"; - public static HttpResponse executeWithRecovery(final HttpUriRequest request) - throws IOException { - try { - return getHttpClient().execute(request); - } catch (IllegalStateException e) { - // try again... this is a rare error - return getHttpClient().execute(request); + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // try the request + Response response; + int attempt = 0; + do { + attempt++; + try { + response = chain.proceed(request); + } catch (IOException e) { + Log.w(TAG, "Request failed: ", e); + response = null; + } + } while ((response == null || !response.isSuccessful()) && attempt < 2); + + return response; } } - static final int CONNECTION_TIMEOUT_MILLIS = 10000; + public static OkHttpClient makeHttpClient() { + OkHttpClient client = new OkHttpClient(); + client.setConnectTimeout(CONNECTION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); + client.interceptors().add(new RetryInterceptor()); + return client; + } + static final int CONNECTION_TIMEOUT_MILLIS = 10000; } diff --git a/app/src/main/res/layout/train_alarm_dialog.xml b/app/src/main/res/layout/train_alarm_dialog.xml index a06870c..090407d 100644 --- a/app/src/main/res/layout/train_alarm_dialog.xml +++ b/app/src/main/res/layout/train_alarm_dialog.xml @@ -1,10 +1,14 @@ - + android:layout_height="wrap_content" + android:orientation="horizontal"> + + - - + android:text="@string/minutes_before_departure" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7d6a0b7..a3e1b78 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -37,7 +37,7 @@ I will board this train Departure options Your train - Set up departure alarm + Set alarm Your train is leaving soon! Silence alarm Cancel alarm @@ -47,5 +47,6 @@ Arrive @ dest. ~ I\'ll be arriving at %1$s around %2$s Share arrival time + minutes before departure diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index fc7208f..42010e8 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -3,7 +3,7 @@ - +