* Drop support for Android versions < 4.0

* Convert all http client to use OkHttp
* Use Android number picker instead of third party lib
This commit is contained in:
Doug Keen 2015-10-18 17:26:30 -07:00
parent 4d98f0df42
commit 958541e2af
10 changed files with 116 additions and 133 deletions

View File

@ -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 {

View File

@ -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(

View File

@ -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() {

View File

@ -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<StationPair, Integer, RealTimeDepartures> {
@ -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<Route> 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");
}

View File

@ -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<GetRouteFareTask.Params, Integer, String> {
@ -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");
}

View File

@ -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<StationPair, Integer, ScheduleInformation> {
@ -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");
}

View File

@ -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);
private static class RetryInterceptor implements Interceptor {
private static final String TAG = "RetryInterceptor";
@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;
}
}
public static OkHttpClient makeHttpClient() {
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(CONNECTION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.interceptors().add(new RetryInterceptor());
return client;
}
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);
}
}
static final int CONNECTION_TIMEOUT_MILLIS = 10000;
}

View File

@ -1,10 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
android:layout_height="wrap_content"
android:orientation="horizontal">
<NumberPicker
android:id="@+id/numberPicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2" />
<TextView
android:id="@+id/textView1"
@ -14,15 +18,8 @@
android:layout_weight="1"
android:gravity="center_vertical"
android:maxLines="3"
android:paddingLeft="10sp"
android:singleLine="false"
android:text="minutes before departure"
/>
<com.codetroopers.betterpickers.numberpicker.NumberPicker
android:id="@+id/numberPicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
android:text="@string/minutes_before_departure" />
</LinearLayout>

View File

@ -37,7 +37,7 @@
<string name="getting_on_this_train">I will board this train</string>
<string name="departure_options">Departure options</string>
<string name="your_train">Your train</string>
<string name="set_up_departure_alarm">Set up departure alarm</string>
<string name="set_up_departure_alarm">Set alarm</string>
<string name="train_alarm_text">Your train is leaving soon!</string>
<string name="silence_alarm">Silence alarm</string>
<string name="cancel_alarm">Cancel alarm</string>
@ -47,5 +47,6 @@
<string name="arrives_at_destination">Arrive @ dest. ~</string>
<string name="arrival_message">I\'ll be arriving at %1$s around %2$s</string>
<string name="share_arrival_time">Share arrival time</string>
<string name="minutes_before_departure">minutes before departure</string>
</resources>

View File

@ -3,7 +3,7 @@
<!-- Base application theme is the default theme. -->
<style name="AppTheme" parent="Theme.AppCompat"></style>
<style name="AppTheme" parent="Theme.AppCompat"/>
<style name="ButtonBar">
<item name="android:layout_width">fill_parent</item>